summaryrefslogtreecommitdiff
path: root/graphics/sam2p
diff options
context:
space:
mode:
authorNorbert Preining <norbert@preining.info>2019-09-02 13:46:59 +0900
committerNorbert Preining <norbert@preining.info>2019-09-02 13:46:59 +0900
commite0c6872cf40896c7be36b11dcc744620f10adf1d (patch)
tree60335e10d2f4354b0674ec22d7b53f0f8abee672 /graphics/sam2p
Initial commit
Diffstat (limited to 'graphics/sam2p')
-rw-r--r--graphics/sam2p/COPYING339
-rw-r--r--graphics/sam2p/Makefile225
-rw-r--r--graphics/sam2p/Makehelp.in9
-rw-r--r--graphics/sam2p/README2822
-rw-r--r--graphics/sam2p/StdAfx.cpp8
-rw-r--r--graphics/sam2p/StdAfx.h39
-rw-r--r--graphics/sam2p/aclocal.m41238
-rw-r--r--graphics/sam2p/appliers.cpp2255
-rw-r--r--graphics/sam2p/at_bitmap.h73
-rw-r--r--graphics/sam2p/bts.ttt1602
-rw-r--r--graphics/sam2p/c_lgcc.cpp66
-rw-r--r--graphics/sam2p/c_lgcc3.cpp31
-rw-r--r--graphics/sam2p/ccdep.pl397
-rw-r--r--graphics/sam2p/cgif.c1568
-rw-r--r--graphics/sam2p/cgif.h257
-rw-r--r--graphics/sam2p/cols2.pl311
-rw-r--r--graphics/sam2p/config-vc6.h197
-rw-r--r--graphics/sam2p/config.h.in201
-rw-r--r--graphics/sam2p/config2.h349
-rwxr-xr-xgraphics/sam2p/configure7538
-rw-r--r--graphics/sam2p/configure.in223
-rw-r--r--graphics/sam2p/contrib/aprea.ps22
-rw-r--r--graphics/sam2p/contrib/sam2p.tk1450
-rw-r--r--graphics/sam2p/contrib/sam2ptol.pm77
-rw-r--r--graphics/sam2p/contrib/template.job33
-rw-r--r--graphics/sam2p/crc32.c144
-rw-r--r--graphics/sam2p/crc32.h32
-rw-r--r--graphics/sam2p/debian/README.debian6
-rw-r--r--graphics/sam2p/debian/changelog281
-rw-r--r--graphics/sam2p/debian/control24
-rw-r--r--graphics/sam2p/debian/copyright4
-rw-r--r--graphics/sam2p/debian/dirs3
-rwxr-xr-xgraphics/sam2p/debian/rules69
-rw-r--r--graphics/sam2p/encoder.cpp1765
-rw-r--r--graphics/sam2p/encoder.hpp103
-rw-r--r--graphics/sam2p/error.cpp198
-rw-r--r--graphics/sam2p/error.hpp170
-rw-r--r--graphics/sam2p/examples/a_jpg.job8
-rw-r--r--graphics/sam2p/examples/a_jpg2.job8
-rw-r--r--graphics/sam2p/examples/a_l1r8r_eps.job9
-rw-r--r--graphics/sam2p/examples/at-logo_none_xpm.job10
-rw-r--r--graphics/sam2p/examples/fishg_lzw12_pdf.job8
-rw-r--r--graphics/sam2p/examples/fishg_lzw2_pdf.job8
-rw-r--r--graphics/sam2p/examples/fishwbb_l128n_eps.job10
-rw-r--r--graphics/sam2p/examples/fishwbb_l128r_eps.job10
-rw-r--r--graphics/sam2p/examples/fishwbb_l12bn_eps.job10
-rw-r--r--graphics/sam2p/examples/fishwbb_l12br_eps.job10
-rw-r--r--graphics/sam2p/examples/fishwbb_l12hn_eps.job10
-rw-r--r--graphics/sam2p/examples/fishwbb_l12hr_eps.job10
-rw-r--r--graphics/sam2p/examples/fishwbb_l148n_eps.job10
-rw-r--r--graphics/sam2p/examples/fishwbb_l148r_eps.job10
-rw-r--r--graphics/sam2p/examples/fishwbb_l14bn_eps.job10
-rw-r--r--graphics/sam2p/examples/fishwbb_l14br_eps.job10
-rw-r--r--graphics/sam2p/examples/fishwbb_l14hn_eps.job10
-rw-r--r--graphics/sam2p/examples/fishwbb_l14hr_eps.job10
-rw-r--r--graphics/sam2p/examples/fishwbb_l188n_eps.job10
-rw-r--r--graphics/sam2p/examples/fishwbb_l188r_eps.job10
-rw-r--r--graphics/sam2p/examples/fishwbb_l18bn_eps.job10
-rw-r--r--graphics/sam2p/examples/fishwbb_l18br_eps.job10
-rw-r--r--graphics/sam2p/examples/fishwbb_l18hn_eps.job10
-rw-r--r--graphics/sam2p/examples/fishwbb_l18hr_eps.job10
-rw-r--r--graphics/sam2p/examples/fusi2_png.job10
-rw-r--r--graphics/sam2p/examples/fusi_gif.job11
-rw-r--r--graphics/sam2p/examples/fusi_l1t8r_eps.job10
-rw-r--r--graphics/sam2p/examples/fusi_l1tbr_eps.job10
-rw-r--r--graphics/sam2p/examples/fusi_l1thn_eps.job11
-rw-r--r--graphics/sam2p/examples/fusi_l1thr_eps.job10
-rw-r--r--graphics/sam2p/examples/fusi_png.job9
-rw-r--r--graphics/sam2p/examples/fusi_pnm.job9
-rw-r--r--graphics/sam2p/examples/fusi_pnm_ascii.job9
-rw-r--r--graphics/sam2p/examples/fusi_tiff_bad_pdf.job8
-rw-r--r--graphics/sam2p/examples/fusi_tiff_eps.job8
-rw-r--r--graphics/sam2p/examples/fusi_tra_eps.job12
-rw-r--r--graphics/sam2p/examples/fusi_trabin_eps.job11
-rw-r--r--graphics/sam2p/examples/fusi_tradct_eps.job11
-rw-r--r--graphics/sam2p/examples/fusi_tradct_jpeg.job11
-rw-r--r--graphics/sam2p/examples/fusi_trafax_eps.job11
-rw-r--r--graphics/sam2p/examples/fusi_traijg_eps.job13
-rw-r--r--graphics/sam2p/examples/fusi_tral1a85_eps.job10
-rw-r--r--graphics/sam2p/examples/fusiblack_png.job9
-rw-r--r--graphics/sam2p/examples/fusiwhite_a85none.job8
-rw-r--r--graphics/sam2p/examples/fusiwhite_binnone.job8
-rw-r--r--graphics/sam2p/examples/fusiwhite_xwd.job8
-rw-r--r--graphics/sam2p/examples/j_taska_lzw_eps.job12
-rw-r--r--graphics/sam2p/examples/j_taska_rle_bmp.job11
-rw-r--r--graphics/sam2p/examples/mixing_ijg.job9
-rw-r--r--graphics/sam2p/examples/mixing_pcx_zip.job8
-rw-r--r--graphics/sam2p/examples/mixing_zip.job8
-rw-r--r--graphics/sam2p/examples/pts2.pbmbin0 -> 28336 bytes
-rw-r--r--graphics/sam2p/examples/pts2_l1g8n_eps.job9
-rw-r--r--graphics/sam2p/examples/pts2_l1g8r_eps.job9
-rw-r--r--graphics/sam2p/examples/pts2_l1gbr_eps.job9
-rw-r--r--graphics/sam2p/examples/pts2_pbm.job10
-rw-r--r--graphics/sam2p/examples/pts2_pbm_pnm.job9
-rw-r--r--graphics/sam2p/examples/pts2_pbm_zip0.job10
-rw-r--r--graphics/sam2p/examples/ptsbanner.gifbin0 -> 12183 bytes
-rw-r--r--graphics/sam2p/examples/ptsbanner2_ijg_tiff.job9
-rw-r--r--graphics/sam2p/examples/ptsbanner2_jai.job9
-rw-r--r--graphics/sam2p/examples/ptsbanner2_jai_jpeg.job9
-rw-r--r--graphics/sam2p/examples/ptsbanner2_jai_pdf.job8
-rw-r--r--graphics/sam2p/examples/ptsbanner2_jai_tiff.job9
-rw-r--r--graphics/sam2p/examples/ptsbanner2_jpeg_tiff.job9
-rw-r--r--graphics/sam2p/examples/ptsbanner__jpeg.job9
-rw-r--r--graphics/sam2p/examples/ptsbanner_bbox_pdf.job12
-rw-r--r--graphics/sam2p/examples/ptsbanner_gif_xwd.job8
-rw-r--r--graphics/sam2p/examples/ptsbanner_jpeg.job8
-rw-r--r--graphics/sam2p/examples/ptsbanner_jpg_xwd.job8
-rw-r--r--graphics/sam2p/examples/ptsbanner_lzw.job8
-rw-r--r--graphics/sam2p/examples/ptsbanner_lzw_framed.job13
-rw-r--r--graphics/sam2p/examples/ptsbanner_lzw_margin.job13
-rw-r--r--graphics/sam2p/examples/ptsbanner_lzw_margin_pdf.job13
-rw-r--r--graphics/sam2p/examples/ptsbanner_lzw_pdf.job12
-rw-r--r--graphics/sam2p/examples/ptsbanner_lzw_pdfb.job10
-rw-r--r--graphics/sam2p/examples/ptsbanner_lzw_ps.job12
-rw-r--r--graphics/sam2p/examples/ptsbanner_lzw_rot_ps.job10
-rw-r--r--graphics/sam2p/examples/ptsbanner_lzw_tiff.job12
-rw-r--r--graphics/sam2p/examples/ptsbanner_none_tiff.job8
-rw-r--r--graphics/sam2p/examples/ptsbanner_png.job8
-rw-r--r--graphics/sam2p/examples/ptsbanner_rle_pdf.job12
-rw-r--r--graphics/sam2p/examples/ptsbanner_rle_tiff.job11
-rw-r--r--graphics/sam2p/examples/ptsbanner_tralzw.job18
-rw-r--r--graphics/sam2p/examples/ptsbanner_xpm_zip.job8
-rw-r--r--graphics/sam2p/examples/ptsbanner_zip.job8
-rw-r--r--graphics/sam2p/examples/ptsbanner_ziprgb4_tiff.job13
-rw-r--r--graphics/sam2p/examples/ptsbanner_ziprgb8_tiff.job11
-rw-r--r--graphics/sam2p/examples/ptsbannerg_jai.job9
-rw-r--r--graphics/sam2p/examples/ptsbannerg_jai_pdf.job8
-rw-r--r--graphics/sam2p/examples/ptsbannerg_jai_tiff.job9
-rw-r--r--graphics/sam2p/examples/ptsbannerg_lzw_tiff.job12
-rw-r--r--graphics/sam2p/examples/sam2p_fishg.job8
-rw-r--r--graphics/sam2p/examples/sam2p_fisht.job8
-rw-r--r--graphics/sam2p/examples/sam2p_fishwbb.job8
-rw-r--r--graphics/sam2p/examples/sam2p_fishwbg.job8
-rw-r--r--graphics/sam2p/examples/sam2p_fishwbg_bug.job9
-rw-r--r--graphics/sam2p/examples/sam2p_fishwww.job8
-rw-r--r--graphics/sam2p/examples/sam2psho.job8
-rw-r--r--graphics/sam2p/examples/shot_fax31d_tiff.job12
-rw-r--r--graphics/sam2p/examples/shot_fax32d_tiff.job13
-rw-r--r--graphics/sam2p/examples/shot_fax4_tiff.job12
-rw-r--r--graphics/sam2p/examples/shot_gif.job8
-rw-r--r--graphics/sam2p/examples/shot_i1.job7
-rw-r--r--graphics/sam2p/examples/shot_l118r_eps.job10
-rw-r--r--graphics/sam2p/examples/shot_l11bn_eps.job10
-rw-r--r--graphics/sam2p/examples/shot_l11br_eps.job10
-rw-r--r--graphics/sam2p/examples/shot_l11hr_eps.job10
-rw-r--r--graphics/sam2p/examples/shot_l1m8r_eps.job11
-rw-r--r--graphics/sam2p/examples/shot_l1mbn_eps.job11
-rw-r--r--graphics/sam2p/examples/shot_l1mbr_eps.job11
-rw-r--r--graphics/sam2p/examples/shot_l1mhr_eps.job11
-rw-r--r--graphics/sam2p/examples/shot_pdfb.job9
-rw-r--r--graphics/sam2p/examples/shot_pdfb_hex.job9
-rw-r--r--graphics/sam2p/examples/shot_png.job7
-rw-r--r--graphics/sam2p/examples/shot_ppm.job10
-rw-r--r--graphics/sam2p/examples/sziget_al.job12
-rw-r--r--graphics/sam2p/examples/sziget_al_pdf.job9
-rw-r--r--graphics/sam2p/examples/sziget_ma.job8
-rw-r--r--graphics/sam2p/examples/transparent_tr.job7
-rw-r--r--graphics/sam2p/examples/transparent_tr_pdf.job7
-rw-r--r--graphics/sam2p/examples/xv_cant_display_eps.job14
-rw-r--r--graphics/sam2p/examples/xv_cant_display_eps_gray.job14
-rw-r--r--graphics/sam2p/examples/xv_cant_display_eps_rgb.job14
-rw-r--r--graphics/sam2p/examples/xv_cant_display_gif.job14
-rw-r--r--graphics/sam2p/examples/yellow_gif.job7
-rw-r--r--graphics/sam2p/examples/yellow_op.job9
-rw-r--r--graphics/sam2p/examples/yellow_op_pdf.job7
-rw-r--r--graphics/sam2p/examples/yellow_rle_tiff.job11
-rw-r--r--graphics/sam2p/files235
-rw-r--r--graphics/sam2p/gensi.cpp1222
-rw-r--r--graphics/sam2p/gensi.hpp726
-rw-r--r--graphics/sam2p/gensio.cpp912
-rw-r--r--graphics/sam2p/gensio.hpp403
-rw-r--r--graphics/sam2p/helpere.hpp43
-rwxr-xr-xgraphics/sam2p/hq.pl33
-rw-r--r--graphics/sam2p/image.cpp1922
-rw-r--r--graphics/sam2p/image.hpp405
-rw-r--r--graphics/sam2p/in_bmp.cpp49
-rw-r--r--graphics/sam2p/in_gif.cpp91
-rw-r--r--graphics/sam2p/in_jai.cpp394
-rw-r--r--graphics/sam2p/in_jai.hpp48
-rw-r--r--graphics/sam2p/in_jpeg.cpp39
-rw-r--r--graphics/sam2p/in_lbm.cpp279
-rw-r--r--graphics/sam2p/in_pcx.cpp548
-rw-r--r--graphics/sam2p/in_png.cpp67
-rw-r--r--graphics/sam2p/in_pnm.cpp82
-rw-r--r--graphics/sam2p/in_ps.cpp201
-rw-r--r--graphics/sam2p/in_tga.cpp52
-rw-r--r--graphics/sam2p/in_tiff.cpp68
-rw-r--r--graphics/sam2p/in_xpm.cpp411
-rw-r--r--graphics/sam2p/input-bmp.ci484
-rw-r--r--graphics/sam2p/input-pnm.ci495
-rw-r--r--graphics/sam2p/input-tga.ci591
-rw-r--r--graphics/sam2p/jpegdump_main.cpp306
-rw-r--r--graphics/sam2p/l1lzw.psm656
-rw-r--r--graphics/sam2p/l1zip.psm1439
-rw-r--r--graphics/sam2p/main.hpp20
-rw-r--r--graphics/sam2p/mapping.cpp309
-rw-r--r--graphics/sam2p/mapping.hpp157
-rw-r--r--graphics/sam2p/minips.cpp1104
-rw-r--r--graphics/sam2p/minips.hpp334
-rwxr-xr-xgraphics/sam2p/mkdist.sh102
-rw-r--r--graphics/sam2p/out_gif.cpp341
-rw-r--r--graphics/sam2p/ps_tiny.c874
-rw-r--r--graphics/sam2p/psmlib.psm199
-rw-r--r--graphics/sam2p/pts_defl.c3670
-rw-r--r--graphics/sam2p/pts_defl.h101
-rw-r--r--graphics/sam2p/pts_fax.c3222
-rw-r--r--graphics/sam2p/pts_fax.h515
-rw-r--r--graphics/sam2p/pts_lzw.c1490
-rw-r--r--graphics/sam2p/pts_lzw.h59
-rw-r--r--graphics/sam2p/resource.h44
-rw-r--r--graphics/sam2p/rule.cpp1104
-rw-r--r--graphics/sam2p/rule.hpp319
-rw-r--r--graphics/sam2p/sam2p16.icobin0 -> 318 bytes
-rw-r--r--graphics/sam2p/sam2p32.icobin0 -> 766 bytes
-rw-r--r--graphics/sam2p/sam2p_main.cpp1118
-rwxr-xr-xgraphics/sam2p/sam2p_pdf_scale.pl110
-rw-r--r--graphics/sam2p/snprintf.c996
-rw-r--r--graphics/sam2p/snprintf.h28
-rw-r--r--graphics/sam2p/test_main.cpp340
-rw-r--r--graphics/sam2p/testfax_main.c178
-rw-r--r--graphics/sam2p/vcsam2p.cpp921
-rw-r--r--graphics/sam2p/vcsam2p.dsp300
-rw-r--r--graphics/sam2p/vcsam2p.h14
-rw-r--r--graphics/sam2p/vcsam2p.icobin0 -> 1078 bytes
-rw-r--r--graphics/sam2p/vcsam2p.rc162
-rw-r--r--graphics/sam2p/xpmc.h4
226 files changed, 55714 insertions, 0 deletions
diff --git a/graphics/sam2p/COPYING b/graphics/sam2p/COPYING
new file mode 100644
index 0000000000..a43ea2126f
--- /dev/null
+++ b/graphics/sam2p/COPYING
@@ -0,0 +1,339 @@
+ GNU GENERAL PUBLIC LICENSE
+ Version 2, June 1991
+
+ Copyright (C) 1989, 1991 Free Software Foundation, Inc.
+ 675 Mass Ave, Cambridge, MA 02139, USA
+ Everyone is permitted to copy and distribute verbatim copies
+ of this license document, but changing it is not allowed.
+
+ Preamble
+
+ The licenses for most software are designed to take away your
+freedom to share and change it. By contrast, the GNU General Public
+License is intended to guarantee your freedom to share and change free
+software--to make sure the software is free for all its users. This
+General Public License applies to most of the Free Software
+Foundation's software and to any other program whose authors commit to
+using it. (Some other Free Software Foundation software is covered by
+the GNU Library General Public License instead.) You can apply it to
+your programs, too.
+
+ When we speak of free software, we are referring to freedom, not
+price. Our General Public Licenses are designed to make sure that you
+have the freedom to distribute copies of free software (and charge for
+this service if you wish), that you receive source code or can get it
+if you want it, that you can change the software or use pieces of it
+in new free programs; and that you know you can do these things.
+
+ To protect your rights, we need to make restrictions that forbid
+anyone to deny you these rights or to ask you to surrender the rights.
+These restrictions translate to certain responsibilities for you if you
+distribute copies of the software, or if you modify it.
+
+ For example, if you distribute copies of such a program, whether
+gratis or for a fee, you must give the recipients all the rights that
+you have. You must make sure that they, too, receive or can get the
+source code. And you must show them these terms so they know their
+rights.
+
+ We protect your rights with two steps: (1) copyright the software, and
+(2) offer you this license which gives you legal permission to copy,
+distribute and/or modify the software.
+
+ Also, for each author's protection and ours, we want to make certain
+that everyone understands that there is no warranty for this free
+software. If the software is modified by someone else and passed on, we
+want its recipients to know that what they have is not the original, so
+that any problems introduced by others will not reflect on the original
+authors' reputations.
+
+ Finally, any free program is threatened constantly by software
+patents. We wish to avoid the danger that redistributors of a free
+program will individually obtain patent licenses, in effect making the
+program proprietary. To prevent this, we have made it clear that any
+patent must be licensed for everyone's free use or not licensed at all.
+
+ The precise terms and conditions for copying, distribution and
+modification follow.
+
+ GNU GENERAL PUBLIC LICENSE
+ TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
+
+ 0. This License applies to any program or other work which contains
+a notice placed by the copyright holder saying it may be distributed
+under the terms of this General Public License. The "Program", below,
+refers to any such program or work, and a "work based on the Program"
+means either the Program or any derivative work under copyright law:
+that is to say, a work containing the Program or a portion of it,
+either verbatim or with modifications and/or translated into another
+language. (Hereinafter, translation is included without limitation in
+the term "modification".) Each licensee is addressed as "you".
+
+Activities other than copying, distribution and modification are not
+covered by this License; they are outside its scope. The act of
+running the Program is not restricted, and the output from the Program
+is covered only if its contents constitute a work based on the
+Program (independent of having been made by running the Program).
+Whether that is true depends on what the Program does.
+
+ 1. You may copy and distribute verbatim copies of the Program's
+source code as you receive it, in any medium, provided that you
+conspicuously and appropriately publish on each copy an appropriate
+copyright notice and disclaimer of warranty; keep intact all the
+notices that refer to this License and to the absence of any warranty;
+and give any other recipients of the Program a copy of this License
+along with the Program.
+
+You may charge a fee for the physical act of transferring a copy, and
+you may at your option offer warranty protection in exchange for a fee.
+
+ 2. You may modify your copy or copies of the Program or any portion
+of it, thus forming a work based on the Program, and copy and
+distribute such modifications or work under the terms of Section 1
+above, provided that you also meet all of these conditions:
+
+ a) You must cause the modified files to carry prominent notices
+ stating that you changed the files and the date of any change.
+
+ b) You must cause any work that you distribute or publish, that in
+ whole or in part contains or is derived from the Program or any
+ part thereof, to be licensed as a whole at no charge to all third
+ parties under the terms of this License.
+
+ c) If the modified program normally reads commands interactively
+ when run, you must cause it, when started running for such
+ interactive use in the most ordinary way, to print or display an
+ announcement including an appropriate copyright notice and a
+ notice that there is no warranty (or else, saying that you provide
+ a warranty) and that users may redistribute the program under
+ these conditions, and telling the user how to view a copy of this
+ License. (Exception: if the Program itself is interactive but
+ does not normally print such an announcement, your work based on
+ the Program is not required to print an announcement.)
+
+These requirements apply to the modified work as a whole. If
+identifiable sections of that work are not derived from the Program,
+and can be reasonably considered independent and separate works in
+themselves, then this License, and its terms, do not apply to those
+sections when you distribute them as separate works. But when you
+distribute the same sections as part of a whole which is a work based
+on the Program, the distribution of the whole must be on the terms of
+this License, whose permissions for other licensees extend to the
+entire whole, and thus to each and every part regardless of who wrote it.
+
+Thus, it is not the intent of this section to claim rights or contest
+your rights to work written entirely by you; rather, the intent is to
+exercise the right to control the distribution of derivative or
+collective works based on the Program.
+
+In addition, mere aggregation of another work not based on the Program
+with the Program (or with a work based on the Program) on a volume of
+a storage or distribution medium does not bring the other work under
+the scope of this License.
+
+ 3. You may copy and distribute the Program (or a work based on it,
+under Section 2) in object code or executable form under the terms of
+Sections 1 and 2 above provided that you also do one of the following:
+
+ a) Accompany it with the complete corresponding machine-readable
+ source code, which must be distributed under the terms of Sections
+ 1 and 2 above on a medium customarily used for software interchange; or,
+
+ b) Accompany it with a written offer, valid for at least three
+ years, to give any third party, for a charge no more than your
+ cost of physically performing source distribution, a complete
+ machine-readable copy of the corresponding source code, to be
+ distributed under the terms of Sections 1 and 2 above on a medium
+ customarily used for software interchange; or,
+
+ c) Accompany it with the information you received as to the offer
+ to distribute corresponding source code. (This alternative is
+ allowed only for noncommercial distribution and only if you
+ received the program in object code or executable form with such
+ an offer, in accord with Subsection b above.)
+
+The source code for a work means the preferred form of the work for
+making modifications to it. For an executable work, complete source
+code means all the source code for all modules it contains, plus any
+associated interface definition files, plus the scripts used to
+control compilation and installation of the executable. However, as a
+special exception, the source code distributed need not include
+anything that is normally distributed (in either source or binary
+form) with the major components (compiler, kernel, and so on) of the
+operating system on which the executable runs, unless that component
+itself accompanies the executable.
+
+If distribution of executable or object code is made by offering
+access to copy from a designated place, then offering equivalent
+access to copy the source code from the same place counts as
+distribution of the source code, even though third parties are not
+compelled to copy the source along with the object code.
+
+ 4. You may not copy, modify, sublicense, or distribute the Program
+except as expressly provided under this License. Any attempt
+otherwise to copy, modify, sublicense or distribute the Program is
+void, and will automatically terminate your rights under this License.
+However, parties who have received copies, or rights, from you under
+this License will not have their licenses terminated so long as such
+parties remain in full compliance.
+
+ 5. You are not required to accept this License, since you have not
+signed it. However, nothing else grants you permission to modify or
+distribute the Program or its derivative works. These actions are
+prohibited by law if you do not accept this License. Therefore, by
+modifying or distributing the Program (or any work based on the
+Program), you indicate your acceptance of this License to do so, and
+all its terms and conditions for copying, distributing or modifying
+the Program or works based on it.
+
+ 6. Each time you redistribute the Program (or any work based on the
+Program), the recipient automatically receives a license from the
+original licensor to copy, distribute or modify the Program subject to
+these terms and conditions. You may not impose any further
+restrictions on the recipients' exercise of the rights granted herein.
+You are not responsible for enforcing compliance by third parties to
+this License.
+
+ 7. If, as a consequence of a court judgment or allegation of patent
+infringement or for any other reason (not limited to patent issues),
+conditions are imposed on you (whether by court order, agreement or
+otherwise) that contradict the conditions of this License, they do not
+excuse you from the conditions of this License. If you cannot
+distribute so as to satisfy simultaneously your obligations under this
+License and any other pertinent obligations, then as a consequence you
+may not distribute the Program at all. For example, if a patent
+license would not permit royalty-free redistribution of the Program by
+all those who receive copies directly or indirectly through you, then
+the only way you could satisfy both it and this License would be to
+refrain entirely from distribution of the Program.
+
+If any portion of this section is held invalid or unenforceable under
+any particular circumstance, the balance of the section is intended to
+apply and the section as a whole is intended to apply in other
+circumstances.
+
+It is not the purpose of this section to induce you to infringe any
+patents or other property right claims or to contest validity of any
+such claims; this section has the sole purpose of protecting the
+integrity of the free software distribution system, which is
+implemented by public license practices. Many people have made
+generous contributions to the wide range of software distributed
+through that system in reliance on consistent application of that
+system; it is up to the author/donor to decide if he or she is willing
+to distribute software through any other system and a licensee cannot
+impose that choice.
+
+This section is intended to make thoroughly clear what is believed to
+be a consequence of the rest of this License.
+
+ 8. If the distribution and/or use of the Program is restricted in
+certain countries either by patents or by copyrighted interfaces, the
+original copyright holder who places the Program under this License
+may add an explicit geographical distribution limitation excluding
+those countries, so that distribution is permitted only in or among
+countries not thus excluded. In such case, this License incorporates
+the limitation as if written in the body of this License.
+
+ 9. The Free Software Foundation may publish revised and/or new versions
+of the General Public License from time to time. Such new versions will
+be similar in spirit to the present version, but may differ in detail to
+address new problems or concerns.
+
+Each version is given a distinguishing version number. If the Program
+specifies a version number of this License which applies to it and "any
+later version", you have the option of following the terms and conditions
+either of that version or of any later version published by the Free
+Software Foundation. If the Program does not specify a version number of
+this License, you may choose any version ever published by the Free Software
+Foundation.
+
+ 10. If you wish to incorporate parts of the Program into other free
+programs whose distribution conditions are different, write to the author
+to ask for permission. For software which is copyrighted by the Free
+Software Foundation, write to the Free Software Foundation; we sometimes
+make exceptions for this. Our decision will be guided by the two goals
+of preserving the free status of all derivatives of our free software and
+of promoting the sharing and reuse of software generally.
+
+ NO WARRANTY
+
+ 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
+FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN
+OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
+PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED
+OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS
+TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE
+PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,
+REPAIR OR CORRECTION.
+
+ 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
+WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
+REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,
+INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING
+OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED
+TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY
+YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER
+PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
+POSSIBILITY OF SUCH DAMAGES.
+
+ END OF TERMS AND CONDITIONS
+
+ Appendix: How to Apply These Terms to Your New Programs
+
+ If you develop a new program, and you want it to be of the greatest
+possible use to the public, the best way to achieve this is to make it
+free software which everyone can redistribute and change under these terms.
+
+ To do so, attach the following notices to the program. It is safest
+to attach them to the start of each source file to most effectively
+convey the exclusion of warranty; and each file should have at least
+the "copyright" line and a pointer to where the full notice is found.
+
+ <one line to give the program's name and a brief idea of what it does.>
+ Copyright (C) 19yy <name of author>
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+Also add information on how to contact you by electronic and paper mail.
+
+If the program is interactive, make it output a short notice like this
+when it starts in an interactive mode:
+
+ Gnomovision version 69, Copyright (C) 19yy name of author
+ Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
+ This is free software, and you are welcome to redistribute it
+ under certain conditions; type `show c' for details.
+
+The hypothetical commands `show w' and `show c' should show the appropriate
+parts of the General Public License. Of course, the commands you use may
+be called something other than `show w' and `show c'; they could even be
+mouse-clicks or menu items--whatever suits your program.
+
+You should also get your employer (if you work as a programmer) or your
+school, if any, to sign a "copyright disclaimer" for the program, if
+necessary. Here is a sample; alter the names:
+
+ Yoyodyne, Inc., hereby disclaims all copyright interest in the program
+ `Gnomovision' (which makes passes at compilers) written by James Hacker.
+
+ <signature of Ty Coon>, 1 April 1989
+ Ty Coon, President of Vice
+
+This General Public License does not permit incorporating your program into
+proprietary programs. If your program is a subroutine library, you may
+consider it more useful to permit linking proprietary applications with the
+library. If this is what you want to do, use the GNU Library General
+Public License instead of this License.
diff --git a/graphics/sam2p/Makefile b/graphics/sam2p/Makefile
new file mode 100644
index 0000000000..0e862188c9
--- /dev/null
+++ b/graphics/sam2p/Makefile
@@ -0,0 +1,225 @@
+#
+# Makefile, in GNU make syntax
+# by pts@fazekas.hu at Sun Feb 24 16:20:15 CET 2002
+# Sat Apr 20 19:14:11 CEST 2002
+# ccdep.pl at Sat Jun 1 15:51:36 CEST 2002
+#
+# To clean .o files and some more, run: make clean
+# To clean all, procsets and configure outputs, run: make allclean
+# To create a .tar.gz, run: make dist-noautoconf
+# To install dist, run: make dist-install
+#
+
+# Magic to convert `make clean' to `make MAKE_DIST=x clean' so that
+# `make clean' won't depend on the file Makedep to exist.
+ifeq ($(MAKECMDGOALS),clean)
+MAKE_DIST=000
+endif
+ifeq ($(MAKECMDGOALS),allclean)
+MAKE_DIST=000
+endif
+ifeq ($(MAKECMDGOALS),dist-noautoconf)
+MAKE_DIST=000
+endif
+ifeq ($(MAKECMDGOALS),dist-install)
+MAKE_DIST=000
+endif
+ifeq ($(MAKECMDGOALS),Makedep.force)
+MAKE_DIST=000
+endif
+
+BASH=bash
+PERL_BADLANG=x
+export PERL_BADLANG
+
+CXXX=$(CXD_assert)
+LDALL=$(LDXX) -s $(LDFLAGS) $(LIBS)
+ifeq ($(ENABLE_DEBUG), no)
+CXXX=$(CXD_no)
+endif
+ifeq ($(ENABLE_DEBUG), yes)
+CXXX=$(CXD_yes)
+LDALL=$(LDXX) $(LDFLAGS) $(LIBS)
+endif
+ifeq ($(ENABLE_DEBUG), checker)
+CXXX=$(CXD_checker)
+LDALL=checkerg++ $(LDFLAGS) $(LIBS)
+endif
+
+CXXALL=$(CXXX) $(CXXFLAGS) $(CXXFLAGSB)
+CCALL =$(CXXX) $(CXXFLAGS) $(CXXFLAGSB)
+CXDFAL=$(CXXFLAGS) $(CXXFLAGSB) $(LDFLAGS) $(LIBS)
+
+.PHONY: clean dist dist-noautoconf dist-more allclean distclean dist-install
+.PHONY: most all all1 install
+
+ALL_FALLBACK=jpegdump ps_tiny sam2p test testfax
+ALL=
+# Used my Makehedep to add dependencies to .o files.
+GLOBFILES=Makefile Makehelp Makedep
+
+MAKEDEP_CMD = perl -x -S ./ccdep.pl --FAL=assert,no,yes,checker $(CXX)
+ifeq ($(MAKE_DIST),)
+ most all: sam2p # First target, build this target by default `make'.
+ # Actually ./configure creates Makehelp as well, but by adding it to the
+ # left side below, make 3.81 would run configure twice (once for each
+ # `include' below).
+ #
+ # echo to config.h is needed to make config.h younger than config.h.in;
+ # configure doesn't change the timestamp of config.h if it's unchanged.
+ Makedep config.h: configure Makehelp.in config.h.in ccdep.pl sam2p_version.h; ./configure --enable-gif --enable-lzw && echo "" >>config.h
+ Makehelp:;
+ include Makehelp # Defines CXX. File generated by ./configure.
+ include Makedep # Contains ALL+=... .
+else
+ #ifeq ($(wildcard Makedep),Makedep)
+ ifeq ($(wildcard Makehelp Makedep),Makehelp Makedep)
+ # Do an `include Makedep' anyway, to get the proper value for ALL.
+ #Makehelp:;
+ Makedep:;
+ #include Makehelp # Defines CXX. File generated by ./configure.
+ include Makedep # Contains ALL+=... .
+ else
+ # For `make MAKE_DIST=x clean'.
+ ALL=$(ALL_FALLBACK)
+ # This forces an error for `make MAKE_DIST=x Makedep'. Just run
+ # `make Makedep' to build Makedep. We can't build it here, because we don't
+ # have Makehelp (which would be generated ./configure, but with MAKE_DIST=x
+ # we don't assume that ./configure has been run.)
+ Makedep: .Makedep.not.here.;
+ endif
+ most all:; # `make MAKE_DIST=x' should be a no-op by default.
+endif
+
+.PHONY: Makedep.force
+# Called by ./configure
+Makedep.force: sam2p_version.h; $(MAKEDEP_CMD)
+
+all1: $(ALL)
+# vvv for Epsilon at Thu Oct 31 09:58:58 CET 2002
+IDE_MODES := release debug
+IDE_TARGETS_debug := $(patsubst %,%.yes, $(TARGETS))
+IDE_TARGETS_release := $(TARGETS)
+
+CXD_assert =$(CXX) -s -O2
+CXD_no =$(CXX) -s -DNDEBUG -O3
+# CXD_yes =$(CXX) $(GFLAG) -lefence
+CXD_yes =$(CXX) $(GFLAG)
+CXD_checker=checkerg++ $(GFLAG)
+
+# .PHONY: clean dist allclean distclean
+
+SAM2P_VERSION=$(shell $(BASH) ./mkdist.sh --getversion)
+sam2p_version.h: debian/changelog mkdist.sh
+ (echo '/* Generated automatically by Makefile. */' && \
+ echo '#ifndef SAM2P_VERSION_H' && \
+ echo '#define SAM2P_VERSION_H 1' && \
+ echo '#define SAM2P_VERSION "$(SAM2P_VERSION)"' && \
+ echo '#endif') >$@
+
+xpmc.h: cols2.pl
+ perl -x ./cols2.pl >xpmc.h
+
+#HQ=perl -e'$$_=join"",<STDIN>; s@([^\w\.\/\-])@sprintf"\\%03o",ord$$1@ge; print "\"$$_\"\n"'
+HQ=perl -x ./hq.pl
+#%.tth: %.tte
+# <$< >$@ $(HQ)
+#%.tth: %.ttm
+# <$< >$@ $(HQ)
+%.tth: %.ttt
+ $(HQ) <$< >$@
+
+# Sun Sep 22 01:16:20 CEST 2002
+L1_LIST=l1g8z.pst l1ghz.pst l1gbz.pst \
+ l1g8l.pst l1ghl.pst l1gbl.pst
+PREPROC_STRIP=perl -ne's@/\s+(?=\w)@/@g;print if!/^\#/&&!/^\s*\Z/'
+L1_FLAGS=-DCFG_FMT_ZLIB_ONLY=1 -DNDEBUG=1 \
+ -DCFG_NO_VAR_S=1 -DUSE_NO_BIND=1 -DUSE_SHORT_NAMES=1 \
+ -DUSE_CURRENTFILE=1 -DUSE_NO_EOF=1 \
+ -DUSE_UNITLENGTH_8 -DUSE_EARLYCHANGE_1 -DUSE_LOWBITFIRST_FALSE \
+ -DUSE_NO_NULLDEF=1 -DUSE_PIN=1
+# TTT_QUOTE=perl -e '$$s=$$_=join"",<STDIN>; s@%.*@@g; s@[(][^()]*[)]@@g; die if /[()\\]/ or $$ARGV[0]!~/^(\w+)/; print "\n% TTT_QUOTE\n/$$1 ($$s)\n\n"' --
+TTT_QUOTE=perl -e '$$s=$$_=join"",<STDIN>; $$s=~s@([()\\])@\\$$1@g; die if $$ARGV[0]!~/^(\w+)/; print "\n% TTT_QUOTE\n/$$1 ($$s)\n\n"' --
+# vvv Dat: input file for `g++ -E' must have .h extension
+l1g8z.pst: l1zip.psm psmlib.psm ps_tiny
+ <$< >$@.tmp.h perl -pe0
+ $(CXX) -E $(L1_FLAGS) -DUSE_A85D=1 $@.tmp.h >$@.tmp.i
+ <$@.tmp.i >$@.tmp.pin $(PREPROC_STRIP)
+ <$@.tmp.pin >$@.tmp.ps0 ./ps_tiny
+ <$@.tmp.ps0 >$@.tmp.pst $(TTT_QUOTE) $@
+ mv -f $@.tmp.pst $@
+l1ghz.pst: l1zip.psm psmlib.psm ps_tiny
+ <$< >$@.tmp.h perl -pe0
+ $(CXX) -E $(L1_FLAGS) -DUSE_HEXD=1 $@.tmp.h >$@.tmp.i
+ <$@.tmp.i >$@.tmp.pin $(PREPROC_STRIP)
+ <$@.tmp.pin >$@.tmp.ps0 ./ps_tiny
+ <$@.tmp.ps0 >$@.tmp.pst $(TTT_QUOTE) $@
+ mv -f $@.tmp.pst $@
+l1gbz.pst: l1zip.psm psmlib.psm ps_tiny
+ <$< >$@.tmp.h perl -pe0
+ $(CXX) -E $(L1_FLAGS) -DUSE_BINARY=1 $@.tmp.h >$@.tmp.i
+ <$@.tmp.i >$@.tmp.pin $(PREPROC_STRIP)
+ <$@.tmp.pin >$@.tmp.ps0 ./ps_tiny
+ <$@.tmp.ps0 >$@.tmp.pst $(TTT_QUOTE) $@
+ mv -f $@.tmp.pst $@
+l1g8l.pst: l1lzw.psm psmlib.psm ps_tiny
+ <$< >$@.tmp.h perl -pe0
+ $(CXX) -E $(L1_FLAGS) -DUSE_A85D=1 $@.tmp.h >$@.tmp.i
+ <$@.tmp.i >$@.tmp.pin $(PREPROC_STRIP)
+ <$@.tmp.pin >$@.tmp.ps0 ./ps_tiny
+ <$@.tmp.ps0 >$@.tmp.pst $(TTT_QUOTE) $@
+ mv -f $@.tmp.pst $@
+l1ghl.pst: l1lzw.psm psmlib.psm ps_tiny
+ <$< >$@.tmp.h perl -pe0
+ $(CXX) -E $(L1_FLAGS) -DUSE_HEXD=1 $@.tmp.h >$@.tmp.i
+ <$@.tmp.i >$@.tmp.pin $(PREPROC_STRIP)
+ <$@.tmp.pin >$@.tmp.ps0 ./ps_tiny
+ <$@.tmp.ps0 >$@.tmp.pst $(TTT_QUOTE) $@
+ mv -f $@.tmp.pst $@
+l1gbl.pst: l1lzw.psm psmlib.psm ps_tiny
+ <$< >$@.tmp.h perl -pe0
+ $(CXX) -E $(L1_FLAGS) -DUSE_BINARY=1 $@.tmp.h >$@.tmp.i
+ <$@.tmp.i >$@.tmp.pin $(PREPROC_STRIP)
+ <$@.tmp.pin >$@.tmp.ps0 ./ps_tiny
+ <$@.tmp.ps0 >$@.tmp.pst $(TTT_QUOTE) $@
+ mv -f $@.tmp.pst $@
+# vvv copy the .ttt, not the .tth
+# The perl program down there is a portable cat(1) implementation.
+bts1.ttt: bts.ttt $(L1_LIST)
+ perl -pe0 $^ >$@
+bts2.ttt: bts1.ttt ps_tiny
+ ./ps_tiny --copy <$< >$@
+
+clean:
+ # Not removing sam2p_version.h, because it would trigger the rerun of ./configure at the next `make'.
+ rm -f *~ a.out DEADJOE core *.o *.tth *.tmp.pin *.tmp.i *.tmp.ps0 *.tmp.h *.tmp.pst autom4te.cache/*
+ rm -f sam2p.yes sam2p.no
+ rm -f debian/changelog.dch debian/*~
+ rm -f $(ALL) $(ALL:=.yes) $(ALL:=.no) $(ALL:=.assert) $(ALL:=.checker)
+ test ! -d autom4te.cache || rmdir autom4te.cache
+allclean: clean
+ rm -f config.h Makehelp Makedep config.cache config.log \
+ config.status test.eps test.pdf build build-stamp \
+ bts2.tth bts1.ttt bts2.ttt *.pst.tmp.* *.pst
+
+distclean: allclean
+ rm -f configure
+ -autoconf
+dist: distclean dist-noautoconf
+dist-noautoconf:
+ chmod 755 configure
+ $(BASH) ./mkdist.sh
+# vvv Create a distribution with more files to aid compilation
+dist-more: bts2.tth
+ $(BASH) ./mkdist.sh sam2p-more bts2.tth
+dist-install: dist-noautoconf
+ chmod 600 ../sam2p-*.tar.gz
+ scp ../sam2p-*.tar.gz kozma:public_html
+
+# Mac OS/X cp doesn't have -a, so we don't use it
+install: sam2p
+ -mkdir -p '$(bindir)'
+ cp sam2p '$(bindir)'
+ chmod 755 '$(bindir)'/sam2p
+
+# __END__ of Makefile
diff --git a/graphics/sam2p/Makehelp.in b/graphics/sam2p/Makehelp.in
new file mode 100644
index 0000000000..638345a5ab
--- /dev/null
+++ b/graphics/sam2p/Makehelp.in
@@ -0,0 +1,9 @@
+CXX=@CXX@
+LDXX=@LDXX@
+CXXFLAGS=-DHAVE_CONFIG2_H @CXXFLAGS@
+CXXFLAGSB=@CXXFLAGSB@
+ENABLE_DEBUG=@ENABLE_DEBUG@
+GFLAG=@GFLAG@
+prefix=@prefix@
+exec_prefix=@exec_prefix@
+bindir=@bindir@
diff --git a/graphics/sam2p/README b/graphics/sam2p/README
new file mode 100644
index 0000000000..68dad7c848
--- /dev/null
+++ b/graphics/sam2p/README
@@ -0,0 +1,2822 @@
+-*- coding: UTF-8 -*-
+
+README for sam2p
+by pts@fazekas.hu
+at Sun Dec 30 19:30:17 CET 2001 -- Fri Mar 22 19:25:03 CET 2002
+Sat Apr 27 00:39:12 CEST 2002
+Wed Jul 3 01:20:40 CEST 2002
+Wed Feb 5 19:46:51 CET 2003
+grammatical corrections by Steve Turner at Mon Jan 10 00:53:46 CET 2005
+
+This is the README file for sam2p, a raster to PostScript/PDF image
+conversion program. This file contains a 5-minute turbo tutorial for new and
+impatient users (search for the phrase `Turbo tutorial' in your text editor).
+As of now, this README file is the only, and definitive, documentation of sam2p.
+
+sam2p is a UNIX command line utility written in C++ (C++98) that converts many
+raster (bitmap) image formats into Adobe PostScript or PDF files and several
+other formats. The images are not vectorized. sam2p gives full control to
+the user to specify standards-compliance, compression, and bit depths. In
+some cases sam2p can compress an image 100 times smaller than the PostScript
+output of many other common image converters. sam2p provides ZIP, RLE and
+LZW (de)compression filters even on Level1 PostScript devices.
+
+Send donations to the author of sam2p:
+https://flattr.com/submit/auto?user_id=pts&url=https://github.com/pts/sam2p
+
+Do you need sam2p?
+
+-- If you have a raster image (e.g. PNG, JPEG), and you need EPS or PDF output,
+ then sam2p is probably very useful for you, because it can generate small
+ EPS and PDF files quickly, outperforming many other
+ tools (such as ImageMagick's convert) in speed and output file size. For
+ EPS output files, the compatibility of sam2p is also better that of other
+ tools.
+-- If you use any of pdftex, pdflatex, luatex, lualatex, xetex or xelatex,
+ and you have your raster images as PNG and JPEG files, then you don't need
+ sam2p or any other raster image converter, because \includegraphics works
+ on PNG and JPEG files directly.
+-- If you want to make your JPEG files smaller, there are much better tools
+ than sam2p for that.
+-- If you want to make your PNG files smaller, you can use sam2p to convert
+ PNG to PNG, but with other tools (such as pngout, advpng and zopflipng)
+ you can get a better compression ratio at a cost of slower compression
+ speed.
+-- If you want to make your PDF files smaller, use pdfsizeopt
+ (https://github.com/pts/pdfsizeopt). pdfsizeopt uses sam2p and other
+ tools (such as jbig2) under the hood to make the raster images embedded
+ in the PDF files smaller.
+
+How small is the EPS output of sam2p?
+
+-- A testimonial from Grant Ingram, UK: Anyway this is just a quick note to say
+ thanks for writing the sam2p utility which I am using to create EPS figures
+ of photographs for my thesis -- it works very well producing image sizes
+ that are some 3% of the ones produced by ImageMagick.
+
+-- A testimonial from Tom Schneider, US:
+
+ -rw------- 1 toms delila 88628 Mar 3 17:38 prototype-small.eps
+ -rw------- 1 toms delila 7979299 Feb 24 12:25 prototype.eps
+
+ Good GRIEF you have written a nice program!!!! The file is 90 fold
+ smaller than the one from ImageMagick's convert.
+
+ That image that was 90x smaller had been bugging me because it was so
+ large that xdvi would strongly hesitate while I passed by the page.
+ Now it just has a minor delay, thanks to you.
+
+-- Results are not always that impressive. See the section
+ {sam2p vs convert in 2017} for more details.
+
+Benefits of sam2p:
+
+-- sam2p produces much smaller output.
+-- sam2p gives the user complete control over the data layout of the output
+ image. This includes Compression, SampleFormat and TransferEncoding.
+-- sam2p is fast.
+-- sam2p doesn't depend on external libraries. (But it does depend on external
+ programs for _reading_ JPEG, TIFF and PNG files.)
+-- sam2p supports the mainstream image formats of today without compromise.
+ sam2p has many file format fine-tuning features that are missing from
+ most other converter utilities. For example:
+ TIFF ZIP compression, TIFF LZW compression, TIFF
+ JPEG compression, transparent PNG files, BMP RLE-4 and RLE-8
+ compression, etc.
+-- sam2p supports all levels (versions) of the PostScript language and
+ output images have the smallest file size allowed by the LanguageLevel.
+-- PostScript ZIP, RLE and LZW compression is provided for _all_
+ LanguageLevels (!), even for PSL1 (which appeared in 1984). You can print
+ your ZIP-compressed images onto your ancient printer of the 1980s.
+-- sam2p supports all versions of PDF, and as with PostScript,
+ output images have the smallest file size allowed by the version.
+-- Output images of sam2p are always compliant to the standard selected by
+ the user.
+-- Output images of sam2p are real-world compatible, i.e the author has
+ tested them with many common image processing programs, for example:
+ Ghostscript, pdfTeX, xpdf, Acrobat Reader, The GIMP, ImageMagick, xv,
+ Acrobat Distiller, QuarkXPress, InDesign. The author has also tested
+ PostScript files on HP and OkiData printers.
+-- sam2p converts every pixel faithfully, preserving all the 24 RGB bits
+ intact. There is no quality or information loss unless you ask for it.
+-- sam2p uses only a minimal number of libraries. You don't have to install
+ 33Mb of ballast software to use sam2p. Image libraries (libtiff etc.) are
+ _not_ used, the math library is not used, libstdc++ is not used, zlib is
+ not used.
+
+Long-term limitations of sam2p:
+
+-- Only DeviceRGB color space, with the Indexed, Gray and RGB image types.
+-- Indexed images are limited to a maximum of 256 colors.
+-- Alpha channel and transparency supported only for Indexed images: only
+ one color may be transparent.
+-- The entire input image is read into memory. During operation both the
+ input and the output images may be held in memory.
+
+Many thanks to Steve Turner for reviewing and making corrections to this
+document.
+
+Status
+~~~~~~
+sam2p is production-ready software. It is available from:
+
+ https://github.com/pts/sam2p
+
+The documentation is incomplete, but -- together with the examples -- it is
+quite useful. Please have a look at the home page to find articles and more
+documentation (the PDF docs are much more eye-pleasing than this README).
+The source code contains valuable comments, but they may be hard to find
+unless you're deeply into developing sam2p.
+
+The author is developing sam2p in his free time. (He is studying and
+working in non-free time.)
+
+The imaging model is complete. Image output routines are stable and
+adequate. Reasonable defaults are provided for all command line options.
+sam2p can usually find the best SampleFormat automatically. There is
+an educated (but not perfect) default guess for the Compression.
+
+See subsection {OutputRule combinations} about all planned formats.
+
+Turbo tutorial
+~~~~~~~~~~~~~~
+Quick compilation instructions:
+
+1. Run: make
+ It also runs ./configure with the right defaults for you.
+2. Copy the `sam2p' executable to your $PATH, or invoke it as `./sam2p'.
+
+Quick try:
+
+-- ./sam2p examples/pts2.pbm try.eps
+-- ./sam2p examples/pts2.pbm try.pdf
+-- ./sam2p examples/pts2.pbm try.ps
+-- ./sam2p examples/pts2.pbm try.png
+-- ./sam2p examples/pts2.pbm try.tiff
+-- ./sam2p examples/pts2.pbm try.xpm
+-- ./sam2p examples/pts2.pbm try.bmp
+-- ./sam2p examples/pts2.pbm try.jpg
+
+A really short User's guide
+"""""""""""""""""""""""""""
+To convert an image, call:
+
+ ./sam2p <INPUT.IMG> <OUTPUT.IMG>
+ Example: ./sam2p examples/pts2.pbm try.eps
+
+To print an image as a full PostScript page, call:
+
+ ./sam2p [MARGIN-SPECS] <INPUT.IMG> ps: - | lpr
+ Example: ./sam2p -m:1cm examples/pts2.pbm ps: - | lpr
+
+To convert an image to be included as EPS (Encapsulated PostScript) into
+(La)TeX documents, call:
+
+ ./sam2p <INPUT.IMG> <OUTPUT.eps>
+ Example: ./sam2p examples/pts2.pbm test.eps
+ In file.tex: \usepackage{graphicx} ... \includegraphics{test}
+
+To convert an image to be included as PDF into pdf(La)TeX documents, call:
+
+ ./sam2p <INPUT.IMG> <OUTPUT.pdf>
+ Example: ./sam2p examples/pts2.pbm test.pdf
+ In file.tex: \usepackage{graphicx} ... \includegraphics{test}
+
+If you have a large image file (possibly originating from dumb software),
+you can reduce the image size and keep the same filename. (Please note that
+some meta-information may be lost using this method.) This operation is
+_DANGEROUS_ if you don't have a backup, because due to a software or
+hardware problem, sam2p might clobber time image file so the actual image
+gets lost. To overwrite a file in-place, call:
+
+ ./sam2p <INPUT-OUTPUT.IMG> --
+ Example: ./sam2p test.tiff --
+
+You may specify a compression method (or supply other command line options)
+to make a file even smaller, call:
+
+ ./sam2p [OPTIONS] <INPUT.IMG> <OUTPUT.IMG>
+ Example: ./sam2p -c:zip test.tiff test2.tiff
+
+See the detailed documentation of available command-line options elsewhere
+in this document. You may also read section {FAQ} for more information.
+
+Too see a list about the supported input and output image file formats, call:
+
+ ./sam2p
+
+Example output:
+
+ This is sam2p v0.39.
+ Available Loaders: JAI PNG JPEG TIFF PNM BMP GIF LBM XPM PCX TGA.
+ Available Appliers: XWD Meta Empty BMP PNG TIFF6 TIFF6-JAI JPEG-JAI JPEG PNM GIF89a XPM PSL1C PSL23+PDF PDF-JAI PSL2-JAI l1fa85g P-TrOpBb.
+ Usage: [...]
+
+The list of ``Available Loaders'' lists the input image file formats. All
+except for JAI are self-explanatory. JAI is JPEG-as-is, it means reading a
+JPEG file and writing back the exactly same image into an other JPEG variant,
+without quality loss.
+
+From the list of ``Available Appliers'' one can derive the supported output
+image file formats. XWD, BMP, PNG, TIFF6, JPEG, PNM, GIF89a and XPM are
+self-explanatory. TIFF6-JAI, JPEG-JAI, PDF-JAI and PSL2-JAI are JPEG
+variants into which JAI files (see above) can be saved. While the names of
+the remaining appliers may be quite cryptic to the beginner user; most of
+those appliers provide sam2p's excellent support for writing PS, EPS and
+PDF files.
+
+sam2p operation modes
+~~~~~~~~~~~~~~~~~~~~~
+sam2p is a command line utility (i.e, without a graphical user
+interface), so it can be used by composing a command line with the
+appropriate options and parameters, and launching it. See sections ``Turbo
+tutorial'' and ``One-liner mode'' for more details.
+
+sam2p is not interactive, it doesn't ask questions; thus it is completely
+suitable for batch processing and automation. sam2p doesn't log errors, but
+its STDERR can be redirected to a log file quite easily.
+
+There are three modes sam2p can operate in:
+
+-- one-liner mode: (since sam2p 0.37)
+ the user, perhaps, has to type a long command line, specifying the input
+ and the output file name, output file format, compression options, etc.
+ Most of the functionality of sam2p is available in a quite intuitive way
+ in one-liner mode. Users of the `convert' utility from ImageMagick and
+ `tiff2ps' and `tiffcp' will find that one-liner mode of sam2p is very
+ similar to them. This mode is recommended for impatient users.
+
+ Due to the nature of sam2p development, some new functionality of job mode
+ might be missing from one-liner mode. Please report this as a bug.
+
+-- job mode: the user has to write a ``job'' file (recommended extension:
+ .job), which specifies all conversion parameters, including the input and
+ output file name. The name of the job file must be passed to sam2p. This
+ mode is recommended for expert users who want to retain full control of
+ all aspects of the final output. All functionality is available in job
+ mode. This is especially useful in repetative but time separated jobs.
+
+-- GUI mode: This is completely experimental, and will be very probably
+ dropped in the near future. Try executing sam2p.tk (TCL/Tk is required).
+ Please don't use GUI mode, use one-liner mode instead! The flexability
+ of a one-liner (or job) mode is nearly imposible to encompas in a GUI.
+ No more documentation is provided for GUI mode.
+
+ There might be a Micro$oft Windoze version of sam2p available in the near
+ future, but very probably you won't get real GUI with radio boxes, lists
+ and file selection dialogs. You'll have to start sam2p from the DOS
+ prompt...
+
+One-liner mode
+~~~~~~~~~~~~~~
+This section contains a reference-style summary for the one-liner mode.
+The author knows that this section is quite incomprehensible, and a bit old.
+He is planning to completely rewrite it to be readable for the novice user.
+
+The order of the arguments and options is significant.
+
+Input file extension is discarded. The file format is recognised by its
+magic number.
+
+Output file extension gives a hint for /FileFormat:
+
+.ps :\
+ .eps : \ where PS: implies scale to fit page
+ .epsi : > PSL1 PSLC PSL2 PSL3 and
+ .epsf : / EPS: implies no scale changes
+ [E]PS::/ also see Q9 in FAQs below
+.pdf : \ PDF1.0 PDF1.2 (and)
+ PDF: : / PDFB1.0 PDFB1.2
+.gif : GIF89a
+.pnm : PNM (for use with transparency)
+.pbm : PNM /SampleFormat/Gray1
+.pgm : PNM /SampleFormat/Gray8
+.ppm : PNM /SampleForamt/Rgb8
+.pam : PAM
+.pip : PIP
+.empty : Empty
+.meta : Meta
+.jpeg : JPEG
+ .jpg : "
+.tiff : TIFF
+ .tif : "
+.png : PNG
+.xpm : XPM
+.bmp : BMP /Compression/RLE
+.rle : BMP /Compression/RLE
+
+Options (case insensitive):
+
+-- --tmpremove {true|false} : remove temporary files after completion.
+ Set to false for debugging. Default: true.
+-- -j -j:job : display in-memory .job file
+-- -j:warn : be verbose and display warnings about impossible combinations in
+ the .job file
+-- -j:quiet : print only error and fatal error messages, suppress
+ warnings, notices etc. Must be put at the beginning of the
+ command line to suppress initial banners, too. For example,
+ `sam2p -j:quiet in.gif out.eps'.
+-- -s:Indexed1:Indexed4:Indexed8: Try /SampleFormats in this order, and try
+ all others after these. Can be specified separately
+ (e.g `-s Indexed1 -s Indexed2:Indexed8')
+-- -s:Indexed1:Indexed4:Indexed8:stop: Try only these /SampleFormats in
+ this order. Can be specified separately
+ (e.g `-s Indexed1:Indexed2 -s Indexed8:stop')
+-- -s:Indexed1:Indexed4:Indexed8:stopq: Try only these /SampleFormats in
+ this order, be quiet (no warnings on failures). Can be
+ specified separately (e.g `-s Indexed1:Indexed2 -s Indexed8:stop')
+-- -s:tr equivalent to `-s Transparent:Opaque:Mask:Transparent2:Transparent4:Transparent8'
+-- -l:... : /LoadHints(...)
+-- disabled: -a: /LoadHints(asis) extra /Compression/JAI; load JPEG files (and others as-is)
+
+-- -1 -ps:1 PSL1: : [tiff2ps] hint /FileFormat/PSL1 among /PSL*
+-- -1c -ps:1c -ps:c PSLC: : [pts] hint /FileFormat/PSLC among /PSL*
+-- -2 -ps:2 PSL2: EPS2: : [tiff2ps,imagemagick] default hint /FileFormat/PSL2 among /PSL*
+-- -3 -ps:3 PSL3: : [pts] hint /FileFormat/PSL3 among /PSL*
+-- -pdf:b0 PDFB1.0: : [pts] hint /FileFormat/PDFB1.0 among /PDF* (PDF 1.0 with inline image)
+-- -pdf:b2 PDFB1.2: : [pts] default hint /FileFormat/PDFB1.2 among /PDF* (PDF 1.2 with inline image; default because image processors usually keep inline images intact, so they wouldn't want to inefficiently recompress our image)
+-- -pdf:0 PDF1.0: : [pts] hint /FileFormat/PDF1.0 among /PDF* (PDF 1.0 with XObject image)
+-- -pdf:2 PDF1.2: : [pts] hint /FileFormat/PDF1.2 among /PDF* (PDF 1.2 with XObject image)
+-- EPS: EPSF: : [pts] hint /FileFormat/PSL2 or
+ /FileFormat/PSL3 (for /Compression/ZIP)
+-- PDF: : [pts] hint /FileFormat/PDFB1.0 or
+ /FileFormat/PDFB1.2 (for /Compression/ZIP)
+-- PS: : [pts] hint /Scale/RotateOK /FileFormat/PSL2 or
+ /FileFormat/PSL3 (for /Compression/ZIP)
+-- PS2: : [imagemagick] hint /Scale/RotateOK
+ /FileFormat/PSL2. Deprecated, please use PS:.
+
+-- -e:0 -e:none : /Scale/None
+-- -e -e:1 -e:scale : /Scale/OK
+-- -e:rot -e:rotate : /Scale/RotateOK
+
+-- GIF: GIF89a: : [imagemagick,pts] /FileFormat/GIF89a
+-- JPEG: JPG: : [imagemagick,pts] /FileFormat/JPEG
+-- TIFF: TIF: : [imagemagick,pts] /FileFormat/TIFF
+-- PNG: : [imagemagick] /FileFormat/PNG
+-- XPM: : [imagemagick] /FileFormat/XPM
+-- BMP: : [imagemagick] /FileFormat/BMP
+-- Empty: : [pts] /FileFormat/Empty
+-- Meta: : [pts] /FileFormat/Meta
+-- PIP: : [pts] /FileFormat/PIP
+-- PAM: : [pts] /FileFormat/PAM
+-- PNM: : [imagemagick] /FileFormat/PNM (for use with transparency)
+-- PBM: : [imagemagick] /FileFormat/PNM /SampleFormat/Gray1
+-- PGM: : [imagemagick] /FileFormat/PNM /SampleFormat/Gray8
+-- PPM: : [imagemagick] /FileFormat/PNM /SampleFormat/Rgb8
+
+-- -t:bin : [pts] hint /TransferEncoding/Binary (default unless /PS*)
+-- -t:hex : [pts] hint /TransferEncoding/Hex (default for /PSL1 /PSLC)
+-- -t:a85 : [pts] hint /TransferEncoding/A85 (default for /PSL2 /PSL3)
+-- -t:ascii : [pts] hint /TransferEncoding/ASCII
+-- -t:lsb1 -f:lsb2msb : [pts,tiffcp] hint /TransferEncoding/LSBfirst
+-- -t:msb1 -f:msb2lsb : [pts,tiffcp] hint /TransferEncoding/MSBfirst
+
+-- -c:none : [pts,tiffcp] non-default hint /Compression/None
+-- -c:lzw : [pts,tiffcp] hint /Compression/LZW
+-- -c:lzw:(1..99) : [pts] hint /Compression/LZW /Predictor ...
+-- -c:zip : [pts,tiffcp] hint /Compression/ZIP
+-- -c:zip:(1..99) : [pts] hint /Compression/ZIP /Predictor ...
+-- -c:zip:(1..99):(-1..9) : [pts] hint /Compression/ZIP /Predictor ... /Effort ...
+-- -c:(rle|packbits) : [pts,tiffcp] hint /Compression/RLE
+-- -c:(rle|packbits):(0..) : [pts] hint /Compression/RLE /RecordSize ...
+-- -c:fax : [pts] hint /Compression/Fax
+-- -c:fax:(-1..) : [pts] hint /Compression/Fax /K ...
+-- -c:dct : [pts] hint /Compression/DCT /DCT<<>>
+-- -c:dct:... : [pts] hint /Compression/DCT /DCT<<...>>
+-- -c:jpeg : [pts,tiffcp] hint /Compression/JAI, /Compression/IJG
+-- -c:jpeg:(0..100) : [pts] hint /Compression/JAI, /Compression/IJG /Quality ...
+-- -c:ijgi : [pts,tiffcp] hint /Compression/IJG
+-- -c:ijg:(0..100) : [pts] hint /Compression/IJG /Quality ...
+-- -c:g4 : [pts] equivalent to -c:fax:-1
+-- -c:g3 -c:g3:1d : [pts] equivalent to -c:fax:0, -c:fax
+-- -c:g3:2d : [pts] equivalent to -c:fax:-2
+-- -c:jai : [pts] hint /Compression/JAI
+
+-- -m:dpi:(dimen) : set /ImageDPI to `dimen'
+-- -m:(dimen) \ : set all margins (/TopMargin,/BottomMargin, /LeftMargin, /RightMargin) to `dimen'
+ -m:all:(dimen) \ : /LeftMargin, /RightMargin) to `dimen'
+ -m:a:(dimen) :
+-- -m:horiz:(dimen) \ : set /LeftMargin and /RightMargin to `dimen'
+ -m:h:(dimen) \ :
+ -m:x:(dimen) :
+-- -m:vert:(dimen) \ : set /TopMargin and /BottomMargin to `dimen'
+ -m:v:(dimen) \ :
+ -m:y:(dimen) :
+-- -m:left:(dimen) \ : set /LeftMargin to `dimen'
+ -m:l:(dimen) :
+-- -m:right:(dimen) \ : set /RightMargin to `dimen'
+ -m:r:(dimen) :
+-- -m:top:(dimen) \ : set /TopMargin to `dimen'
+ -m:t:(dimen) \ :
+ -m:up:(dimen) \ :
+ -m:u:(dimen) :
+-- -m:bottom:(dimen) \ : set /BottomMargin to `dimen'
+ -m:b:(dimen) \ :
+ -m:down:(dimen) \ :
+ -m:d:(dimen) :
+
+-- -- : if given as last arg, then OutputFile:=InputFile
+-- -- : if given earlier than last arg, then treat other args as filenames
+-- -transparent:(rgb) Change the all pixels having the specified RGB color
+ to transparent. Previously transparent pixels are not changed. See FAQ
+ answer A44 for an exampe.
+
+Default and fallback compression types for each file format:
+
+-- PSL1 PSLC : /RLE
+-- PSL2 PDFB1.0 PDF1.0 : /JAI /RLE
+-- PSL3 PDFB1.2 PDF1.2 : /JAI /ZIP
+-- GIF89a : /LZW
+-- XPM PNM PAM PIP Empty Meta : )/None)
+-- JPEG : /JAI /IJG
+-- TIFF : /JAI /LZW? /RLE
+-- PNG : /ZIP
+-- BMP : /RLE
+
+Overview of job mode
+~~~~~~~~~~~~~~~~~~~~
+In the ``job mode'' sam2p doesn't accept any command line options. It must be
+controlled from the ``job'' files. In ''job mode'' sam2p expects a single command
+line argument: the name of the Job file (file format described in section
+{Jobs}). sam2p runs that single job, prints debug, info, notice, warning and
+error messages (etc.), and creates a single output file: a PS or a PDF. For
+multiple jobs and/or multiple output files, one has to run sam2p multiple
+times.
+
+The details about the output file format (including standards-compliance,
+compression and transfer encoding) are specified in the Job file and other
+files. Thus, in order to make use of the (basic and) advanced
+features of sam2p in job mode, you have to:
+
+1. Understand the basic concepts (i.e read through this manual, and have a
+ look at the examples).
+2. Prepare the input raster (bitmap) graphics file in one of the supported
+ input formats (see section {Supported input formats}).
+3. Decide the name of the output file.
+4. Decide some or all details of the output format.
+5. Create a Job file that describes those details.
+6. Invoke the program `sam2p' with the name of the Job file as a single
+ command-line argument (or `-' if the Job file is fed on STDIN).
+7. Read warning and error messages (printed to STDOUT and STDERR), and retry
+ if necessary.
+
+Revision history, changes
+~~~~~~~~~~~~~~~~~~~~~~~~~
+See in the file debian/changelog.
+
+Known bugs and issues
+~~~~~~~~~~~~~~~~~~~~~
+Please see pending bugs on https://github.com/pts/sam2p/issues .
+Feel free to report any issue there if you encounter one! Your
+bug reports and contributions are very welcome.
+
+All of these old bugs had a follow-up elsewhere, or they don't need one:
+https://code.google.com/archive/p/sam2p/issues .
+
+If you are interested in fixed or closed bugs, please see them on
+https://github.com/pts/sam2p/issues?q=is%3Aissue%20is%3Aclosed .
+
+Requirements
+~~~~~~~~~~~~
+External software required for running sam2p:
+
+-- operting system: any of:
+ -- Linux
+ -- Mac OS X
+ -- Windows (any 32-bit Windows system released since 1995 will do;
+ for older systems, install Wordpad to get MSVCRT.DLL)
+ -- FreeBSD
+ -- any UNIX system with a fairly standard BSD or POSIX C library (C++
+ libraries are not required),
+-- optionally: the libjpeg `cjpeg' utility for /Compression/IJG
+-- optionally: the libjpeg `djpeg' utility for reading JPEG files
+-- optionally: tif22pnm (uses libtiff) for reading TIFF files
+-- optionally: png22pnm (uses libpng) for reading PNG files
+
+Installation on Linux from package
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+If you use Debian, Ubuntu or some other .deb-based distribution on an i386
+(x86) or amd64 (x86_64) system, download the latest .deb package from:
+
+ https://github.com/pts/sam2p/releases
+
+Install it like this:
+
+ $ sudo dpkg -i sam2p_0.49.3-1_i386.deb
+
+The executable in the .deb file doesn't have any library dependencies, it
+works on any version of Debian and Ubuntu.
+
+sam2p used to be included in Debian and Ubuntu for all architectures, but it
+isn't anymore as of 2017-07-12 (it disappeared in 2016-01-22, see
+https://tanguy.ortolo.eu/blog/article143/removing-sam2p-from-debian .)
+
+If you need PNG input support, download the latest png22pnm.exe from:
+
+ https://github.com/pts/tif22pnm/releases
+
+Then put it to the same directory where sam2p.exe is.
+
+If you need PNG input support, download the latest png22pnm.xstatic
+executable from:
+
+ https://github.com/pts/tif22pnm/releases
+
+Then put it to your $PATH as tif22pnm, something like this:
+
+ $ chmod 755 tif22pnm.xstatic
+ $ sudo mv tif22pnm.xstatic /usr/local/bin/tif22pnm
+
+Alternatively, tif22pnm may be available as a package on your Linux
+distribution.
+
+Using it on Linux without installation
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+If you use any Linux on an i386 (x86) or amd64 (x86_64) system, download the
+latest sam2p.xstatic executable from:
+
+ https://github.com/pts/sam2p/releases
+
+Run it like this:
+
+ $ mv sam2p.xstatic sam2p
+ $ chmod 755 sam2p
+ $ ./sam2p
+
+The executable doesn't have any library dependencies, it works on any Linux
+system.
+
+If you need PNG input support, download the latest png22pnm.xstatic
+executable from:
+
+ https://github.com/pts/tif22pnm/releases
+
+Then put it to your $PATH as tif22pnm, something like this:
+
+ $ chmod 755 tif22pnm.xstatic
+ $ sudo mv tif22pnm.xstatic /usr/local/bin/tif22pnm
+
+Using it on FreeBSD without installation
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+FreeBSD has a Linux subsystem, which is able to run sam2p. After activating
+it, follow the instructions in the section {Using it on Linux without
+installation}.
+
+Using it on Windows without installation
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+Download the latest sam2p.exe from:
+
+ https://github.com/pts/sam2p/releases
+
+Then copy sam2p.exe to the current directory, or to somewhere on your $PATH,
+and run it as `sam2p' (without the quotes).
+
+sam2p.exe has only standard Windows DLL dependencies, it works on any
+Windows systems (i386 and amd64). If MSVCRT.DLL is missing, install Wordpad.
+
+If you need PNG input support, download the latest png22pnm.exe from:
+
+ https://github.com/pts/tif22pnm/releases
+
+Then put it to the same directory where sam2p.exe is.
+
+Compilation on UNIX
+~~~~~~~~~~~~~~~~~~~
+For Win32 compilation, see later.
+
+Software required for UNIX compilation:
+
+-- a UNIX system
+-- a working, GNU-compatible C++ compiler (preferably GNU G++ >=2.91. Known
+ working compilers: g++-2.91 g++-2.95 g++-3.0 g++-3.1 g++-3.2)
+-- GNU Make (`make -v' should print `GNU Make')
+-- Perl >=5.004 (no external Perl modules are required)
+-- a Bourne-compatible shell (preferably GNU Bash >=2.0)
+-- the following libraries are _not_ required: libjpeg, libtiff, libpng,
+ libungif, PDFlib, zlib, libm, libstdc++
+-- optionally: GNU autoconf >=2.53 (version number is important, see
+ AC_C_CONST)
+
+Compilation:
+
+ # compile and install required programs
+ autoconf # optional, for experts only
+ export CC=gcc-3.2 CXX=g++-3.2 # optional, for experts only
+ ./configure --enable-gif --enable-lzw
+ make
+ # the stand-alone utility `./sam2p' is now built
+ make install # optional, may not work
+
+If installation doesn't work, please copy the file `sam2p' to somewhere in
+your $PATH, for example /usr/local/bin. Please also copy the README to a
+directory like /usr/share/doc/sam2p. There is no man page -- the
+documentation is the readme.
+
+Testing:
+
+ ./sam2p
+ ./sam2p examples/ptsbanner_zip.job
+ ./sam2p examples/pts2.pbm try.eps
+ gs test.ps
+ # try other examples: examples/*.job
+
+On Debian systems, you'll need GNU Make, Perl, GNU Bash and any of the
+following packages for compilation:
+
+ apt-get install libc6-dev gcc-2.95 g++-2.95
+ apt-get install libc6-dev gcc-3.0 g++-3.0
+ apt-get install libc6-dev gcc-3.1 g++-3.1
+ apt-get install libc6-dev gcc-3.2 g++-3.2
+ apt-get install libc6-dev gcc-3.3 g++-3.3
+ apt-get install libc6-dev gcc-3.4 g++-3.4
+
+Please also run any of the following before ./configure:
+
+ export CC=gcc-2.95 CXX=g++-2.95
+ export CC=gcc-3.0 CXX=g++-3.0 # or g++-3.1 etc.
+
+Optionally, you may install any of
+
+ apt-get install gccchecker
+ apt-get install autoconf
+
+sam2p has been tested with a wide variety of GNU C++ compilers, including
+g++-2.91, g++-2.95, g++-3.0, g++-3.1, g++-3.2, i386-uclibc-g++-2.95,
+checkerg++-2.95. The program must be compilable _without_ _warnings_ with
+any of g++-2.91, g++-2.95, g++-3.0, g++-3.1, g++-3.2. If there is a
+compilation error, send a brief e-mail to the author immediately!
+
+Portability
+~~~~~~~~~~~
+sam2p is quite portable on UNIX systems. It runs on:
+
+ Debian GNU/Linux Slink 2.2.13 glibc-2.0.7 (development platform)
+ Debian GNU/Linux Potato 2.2.18 glibc-2.1.3
+ Debian GNU/Linux Sid 2.4.17 glibc-2.2.5
+ Digital OSF1 V4.0 1229 alpha
+ Slackware 8.0/8.1 2.4.5 libc-2.2.3 gcc-2.95.3
+ SunOS 5.7 Generic_106541-17 sun4u sparc SUNW,Ultra-2 gcc-2.95.2
+ SunOS 5.8 Generic_108528-12 sun4u sparc gcc-3.0.4
+
+Also it runs on Win32 in command line (sam2p.exe) and GUI mode (vcsam2p.exe).
+Command line mode is stable and it is recommended on this platform.
+
+It should work on any Linux or BSD system without modification. Porting to
+other Unices should be quite easy. The author welcomes portability patches.
+
+Porting to non-UNIX systems may be hard. Reasons:
+
+-- Those systems might not have GNU Make, Perl or a Bourne-compatible shell
+ installed. So the Makefile supplied won't work, and many man hours of extra
+ work would be necessary.
+-- sam2p uses the popen(3) library call to communicate with external
+ processes. This call might not be available on non-UNIX systems.
+-- sam2p expects that the $PATH contains the external binaries. Some systems
+ tend to have empty or misconfigured $PATH. On some systems, `gs' is
+ called `gswin32c.exe' etc.
+
+sam2p 0.38 has been compiled and run successfully on:
+
+-- Linux 2.2.8 Debian Slink, g++-2.91
+-- Linux 2.4.18-ac3 Debian SID, g++-2.95, g++-3.0, g++-3.1, g++-3.2
+ Executable size: 318kB.
+-- Linux 2.4.2 Debian Potato, gcc version 2.95.2 20000220 (Debian GNU/Linux)
+ No warnings.
+ Compilation took 0:47, executable size: 330kB.
+-- Linux 2.2.16-3 Red Hat Linux release 6.2 (Zoot), gcc version egcs-2.91.66 19990314/Linux (egcs-1.1.2 release)
+ No warnings.
+ Compilation took 0:44, executable size: 324kB.
+-- OSF1 V4.0 564 alpha, gcc version 2.7.2.2
+ (tons of: warning: cast discards `const' from pointer target type,
+ tons of: warning: the meaning of `\x' varies with -traditional
+ tons of: warning: cast increases required alignment of target type)
+ Compilation took 5 minutes, executable size: 550kB.
+-- SunOS 5.7 Generic_106541-19 sun4u sparc SUNW,Ultra-2, gcc version 3.1
+ (some: warning: cast from `char*' to `int*' increases required alignment of target type)
+ Compilation took 2:50, executable size: 437kB.
+-- SunOS 5.8 Generic_108528-15 sun4u sparc, gcc version 3.1.1
+ (some: warning: cast from `char*' to `int*' increases required alignment of target type)
+ Compilation took 1:26, executable size: 437kB.
+-- Slackware 8.0/8.1, kernel 2.4.5, libc.6.so (libc-2.2.3) gcc-2.95.3
+
+sam2p 0.42 has been compiled and run successfully on:
+
+-- Windows 98, Visual C++ 6.0
+-- Windows 98, MSYS, MingGW, G++ 3.2
+
+Win32 compilation instructions for command-line mode
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+(These instructions are outdated.)
+
+To compile sam2p.exe, the Win32 equivalent of the UNIX utility sam2p, you
+have to install these build dependencies first:
+
+-- MinGW and MSYS, available from http://www.mingw.org
+
+-- Perl 5.004 or newer (only perl.exe and perl5*.dll are required), available
+ from http://www.perl.com. Note that this will be a long download and a
+ bloated install, but after that, just copy perl.exe and the single
+ perl5*.dll to your C:\WINDOWS directory, and uninstall the rest.
+
+To build sam2p:
+
+1. Install all the build dependencies.
+
+2. Open the MSYS terminal window from the start menu.
+
+3. Run `explorer .' to figure out what is the current working directory.
+ Let's call this directory the MSYS home.
+
+4. Download the sam2p sources (.tar.gz) into the MSYS home from:
+
+ https://github.com/pts/sam2p/releases
+
+5. Unpack the sources. Run:
+
+ tar xzvf sam2p-latest.tar.gz
+ tar xvf sam2p-latest.tar.gz # if the previous one doesn't work
+
+6. Run `cd sam2p-*.*' to enter the sam2p source directory. It should contain
+ a newer version of this README and the file sam2p_main.cpp.
+
+7. Run `perl -edie' to check whether Perl is correctly installed. It should
+ print a line beginning with `Died '. If no such line appears (or you get
+ a `command not found' error message), go and install Perl first. Run
+ `echo $PATH' to find out where MSYS is searching for perl.exe. Copy
+ perl.exe to one of those directories.
+
+8. Run
+
+ ./configure --enable-gif --enable-lzw
+ make
+
+9. The file sam2p.exe is now created in the current directory. Use it. You
+ may copy it to another directory right now:
+
+ cp sam2p.exe 'C:\Program Files'
+
+10. You should invoke sam2p.exe from the command line (COMMAND.COM or
+ CMD.EXE) with the _appropriate_ arguments, described elsewhere in
+ this document. Don't put it into the Start menu, it won't work.
+ (a window will flash in and disappear, showing an error message that you
+ haven't supplied the right arguments).
+
+11. The file bts2.tth is also created. It is an important file, because it
+ is required for the GUI compilation.
+
+12. Don't forget to install tif22pnm.exe to load TIFF files, djpeg.exe to
+ load JPEG files, cjpeg.exe to save JPEG files, and png22pnm.exe to load
+ PNG files. The installation instructions for these programs are not
+ given here.
+
+Win32 compilation instructions for GUI mode
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+(These instructions are outdated.)
+
+vcsam2p.exe is a preliminary, alpha-stage attempt to provide a Win32 GUI for
+sam2p.exe. Currently it can load and display images, but not cannot save
+them. vcsam2p.exe is not ready for production use. Feel free to enhance the
+code. Just remember to semd me copies.
+
+You'll need Visual Studio 6.0 installed.
+
+1. Download the sam2p sources (.tar.gz) from:
+
+ https://github.com/pts/sam2p/releases
+
+2. Download untarka.exe to be able to unpack the sources:
+
+ http://.../untarka.exe
+
+3. Unpack the sources. Run:
+
+ untarka.exe sam2p-latest.tar.gz
+
+ A directory sam2p-*.* will be created, containing a newer version of this
+ README and the file config-vc6.h
+
+4. You'll need bts2.tth. You can get an old, possibly outdated and buggy
+ version directly:
+
+ http://.../bts2.tth
+
+ Or, you may compile sam2p under Linux (or Win32 command-line), and copy
+ the generated bts2.tth from there.
+
+ Copy bts2.tth to the same directory as config-vc6.h
+
+5. Start the Visual C++ 6.0 environment.
+
+6. File / Open Workspace / File type: Projects
+ Filename: vcsam2p.dsp
+ Build / Set Active Configuration: vcsam2p - Win32 Release
+ Build / Build vcsam2p.exe
+ Build / Execute vcsam2p.exe
+
+7. Don't forget to install tif22pnm.exe to load TIFF files, djpeg.exe to
+ load JPEG files, cjpeg.exe to save JPEG files, and png22pnm.exe to load
+ PNG files. The installation instructions for these programs are not
+ given here.
+
+Please report and fix bugs in vcsam2p.exe
+
+Copyright
+~~~~~~~~~
+sam2p is written and owned by Szabó Péter <pts@fazekas.hu>. sam2p contains
+code from various people.
+
+sam2p may be used, modified and redistributed only under the terms of the
+GNU General Public License, found in the file COPYING in the distribution,
+or at
+
+ http://www.fsf.org/licenses/gpl.html
+
+Supported input formats
+~~~~~~~~~~~~~~~~~~~~~~~
+-- PNM, PBM, PGM, PPM (preferred formats for non-transparent images)
+-- PNM+PGM, PNM+PBM. The input is a concatenation of a PNM and a P[GB]M
+ file with the same dimensions. The second P[GB]M contains the alpha
+ channel.
+-- XPM (preferred formats for indexed images with transparency)
+-- BMP
+-- GIF, with transparency
+-- LBM (IFF ILBM), with transparency
+-- TGA (Targa)
+-- baseline JPEG JFIF (limited by /Compression/JAI)
+-- PCX
+-- JPEG, is supported with libjpeg/djpeg
+-- TIFF, is supported with the author's tif22pnm, with transparency; also
+ works in a limited way with tifftopnm (Debian package libtiff-tools)
+-- PNG, is supported with the author's png22pnm, with transparency
+ (part of the tif22pnm sources); also works in a limited way with
+ libpng/pngtopnm (Debian package graphics/pnmtopng); with transparency
+-- PS, EPS, PDF: Ghostscript is needed (`gs' or `gswin32c.exe'), see also FAQ
+ question Q39.
+
+Note that only the major features of these file formats are supported. sam2p
+is able to load most of these files, but not all of them.
+
+Important, but unsupported input formats:
+
+-- XBM
+-- XWD
+-- Utah RLE
+
+Input image model
+~~~~~~~~~~~~~~~~~
+A (sampled, raster, bitmap) image is a rectangular array of pixels (dots)
+plus some metadata. Each pixel is represented by an unsigned integer which
+is BPC (BitsPerComponent) and CPP (ComponentsPerPixel) wide. The image
+coordinate system (X,Y) is defined as: upper left corner is (0,0), upper
+right corner is (Width-1,0), lower right corner is (Width-1,Height-1).
+(Note that this is the natural, traditional top->down, left->right system,
+and it is different from PostScript and PDF!).
+
+Some pixels of the image may be without color: they're transparent. A
+transparent pixel is not painted, so whatever was left under it on the
+paper, remains visible. (On the other hand, a colored pixel overrides the
+pixel below unconditionally. E.g a white pixel overrides a black pixel, a
+half-gray pixel, and also another white pixel; but a transparent pixel
+leaves the original one visible.). Notions referring to transparent pixels
+are: transparency, opacity, transparent, opaque, alpha channel, matte
+channel.
+
+Images are read from image files on disk. The file format is autodetected
+(see section {Supported input formats}), and it can also be specified in the
+Job file (NOT implemented yet). Not all file formats are able to specify all
+pixel data and metadata, so additional hints (such as the transparent color
+or the name of the image author) can be specified in Job files.
+
+Sample formats
+~~~~~~~~~~~~~~
+The image pixels could be packed to bytes according to several sample
+formats. Each output file (both EPS and PDF) has its own SampleFormat
+(notation: capitals).
+
+A color is either transparent or it is an opaque RGB triplet (8*3 bits).
+
+The number of colors is the number of colors actually _used_. So unused
+palette entries, and e.g unused #555555 in gray-4 are not counted.
+
+If PSLC is required, but the printer is only PSL1, then the color image will
+be printed grayscale.
+
+When _choosing_ the output format, sam2p doesn't degrade image quality. For
+example, if an image has only two colors: #000001 and #ffffff, sam2p won't
+allow the gray-1 sample format, but with #000000 and #ffffff, it will. The
+user is expected to have an image editor in which she can adjust image
+colors precisely (such as in the Dialogs/(Indexed palette) dialog of The
+GIMP).
+
+Supported Sample Formats:
+
+Name:
+ Fast compatibility
+ Slow compatibility
+ Criteria for the image
+ -- Comment(...)
+
+transparent: (specialisation of mask)
+ all
+ -
+ the whole image is transparent
+ -- implemented with empty image body
+opaque: (specialisation of mask and indexed-1)
+ all
+ -
+ the whole image contains the same, opaque color
+ -- implemented with `setrgbcolor', `fill'
+mask: (specialisation of transparent-2)
+ all
+ -
+ a transparent and a non-transparent color (any may be missing)
+ -- display a Warning if the whole image is transparent or opaque,
+ because transparent or opaque would be a better choice
+ -- implemented with a single call to `imagemask'
+indexed-1:
+ all
+ -
+ exactly 2 non-transparent colors or 1 non-transparent color
+ -- display a Warning if only 1 non-transparent color, because
+ opaque would be a better choice
+ -- display a Notice if colors are in black (#000000) and white
+ (#ffffff), beacuse gray-1 would be a better choice
+ -- implemented with a `setrgbcolor', `fill', and a single call to
+ `imagemask'
+indexed-2:
+ PSL2, PDF1.0??
+ PSLC
+ 3 or 4 non-transparent colors or 1..2 non-transparent colors
+ -- display a Warning if only 1..2 non-transparent colors, because
+ opaque or indexed-1 would be a better choice
+ -- display a Notice if colors are in (#000000, #555555, #aaaaaa,
+ #ffffff), beacuse gray-2 would be a better choice
+ -- implemented with the /Indexed color space or colorimage +
+ manual palette lookup
+ -- users with a PSL1 printer without PSLC should use transparent-*
+indexed-4:
+ PSL2, PDF1.0??
+ PSLC
+ 5..16 non-transparent colors or 1..4 non-transparent colors
+ -- display a Warning if only 1..4 non-transparent colors, because
+ opaque, indexed-1 or indexed-2 would be a better choice
+ -- display a Warning if all components are #00 or #ff,
+ because rgb-1 would be a better choice (3 bits over 4 bits)
+ -- display a Notice if colors are in (#000000, #111111, ...,
+ #ffffff), beacuse gray-4 would be a better choice
+ -- implemented with the /Indexed color space or colorimage +
+ manual palette lookup
+ -- users with a PSL1 printer without PSLC should use transparent-*
+indexed-8:
+ PSL2, PDF1.0??
+ PSLC
+ 17..256 non-transparent colors or 1..16 non-transparent colors
+ -- display a Warning if only 1..16 non-transparent colors, because
+ opaque, indexed-1, indexed-2, indexed-4 would be a better
+ choice
+ -- display a Warning if all components are #00, #55, #aa or #ff,
+ because rgb-2 would be a better choice (6 bits over 8 bits)
+ -- display a Notice if all colors are gray, beacuse gray-8 would be
+ a better choice
+ -- implemented with the /Indexed color space or colorimage +
+ manual palette lookup
+ -- users with a PSL1 printer without PSLC should use transparent-*
+transparent-2:
+ all
+ -
+ 0..1 transparent and 1..3 non-transparent colors
+ -- display a Notice that color separation was done (which can
+ decrease speed and compression)
+ -- display a Warning if no transparent color, because `indexed-2'
+ would be a better choice
+ -- display a Warning if only 1 non-transparent color, because `mask'
+ would be a better choice
+ -- implemented with multiple calls to `setrgbcolor', `imagemask'
+transparent-4:
+ all
+ -
+ a transparent and 1..15 non-transparent colors
+ -- display a Notice that color separation was done (which can
+ seriously decrease speed and compression)
+ -- display a Warning if only 1..3 non-transparent colors, because
+ `mask' or `transparent-2' would be a better choice
+ -- implemented with multiple calls to `setrgbcolor', `imagemask'
+transparent-8:
+ all
+ -
+ a transparent and 1..255 non-transparent colors
+ -- display a Warning that color separation was done (which can
+ seriously decrease speed and compression)
+ -- display a Warning if only 1..15 non-transparent colors, because
+ `mask', `transparent-2' or `transparent-4' would be a better
+ choice
+ -- implemented with multiple calls to `setrgbcolor', `imagemask'
+gray-1:
+ all
+ -
+ colors are in black (#000000) and white (#ffffff)
+ -- display a Warning if only 1 color, because opaque would be a
+ better choice
+ -- implemented with the multiple-argument `image'
+gray-2:
+ all
+ -
+ colors are in (#000000, #555555, #aaaaaa, #ffffff)
+ -- display a Warning if only 1..2 colors, because opaque,
+ indexed-1, or gray-1 would be a better choice
+ -- implemented with the multiple-argument `image'
+gray-4:
+ all
+ -
+ colors are in (#000000, #111111, ..., #ffffff)
+ -- display a Warning if only 1..4 colors, because opaque,
+ indexed-1, gray-1, indexed-2 or gray-2 would be a better choice
+ -- implemented with the multiple-argument `image'
+gray-8:
+ all
+ -
+ colors must be gray
+ -- display a Warning if only 1..16 colors, because opaque,
+ indexed-1, gray-1, indexed-2, gray-2, indexed-4 or gray-4
+ would be a better choice
+ -- implemented with the multiple-argument `image'
+rgb-1:
+ PSLC, PDF1.0
+ -
+ color components must be #00 or #ff (8 colors max)
+ -- display a Warning if all colors are gray
+ -- display a Warning if only 1..4 colors, because opaque,
+ indexed-1, indexed-2 (or gray-*) would be a better choice
+ -- implemented with `colorimage'
+rgb-2:
+ PSLC, PDF1.0
+ -
+ color components must be #00, #55, #aa or #ff (64 colors max)
+ -- display a Warning if all colors are gray
+ -- display a Warning if only 1..16 colors, because opaque,
+ indexed-1, indexed-2 or indexed-4 (or gray-*) would be a better choice
+ choice (this includes the case when color components are in
+ #00, #ff)
+ -- implemented with `colorimage'
+rgb-4:
+ PSLC, PDF1.0
+ -
+ color components must be #00, #11, ... #ff (4096 colors max)
+ -- display a Warning if all colors are gray
+ -- display a Warning if only 1..256 colors, because opaque,
+ indexed-1, indexed-2, indexed-4 or indexed-8 (or gray-*) would be a better
+ choice (this includes the case when color components are in
+ #00, #55, #aa, #ff)
+ -- implemented with `colorimage'
+rgb-8:
+ PSLC, PDF1.0
+ -
+ no transparency
+ -- display a Warning if all colors are gray
+ -- display a Warning if only 1..256 colors, because opaque,
+ indexed-1, indexed-2, indexed-4 or indexed-8 (or gray-*) would be a better
+ choice
+ -- display a Warning if all color components are in
+ #00, #11, ... #ff, because rgb-4 would be a better choice
+ -- implemented with `colorimage'
+
+The following directed (acyclic) graph represents that some formats should
+be tried earlier than others to avoid most Warning and Notice messages. The
+graph was created according to the descriptions above.
+
+ EarlierFormat LaterFormat
+
+ transparent mask
+ opaque mask
+ opaque indexed-1
+ indexed-1 indexed-2
+ indexed-2 indexed-4
+ indexed-4 indexed-8
+ gray-1 gray-2
+ gray-2 gray-4
+ gray-4 gray-8
+ rgb-1 rgb-2
+ rgb-2 rgb-4
+ rgb-4 rgb-8
+ gray-1 indexed-1
+ gray-2 indexed-2
+ gray-4 indexed-4
+ gray-8 indexed-8
+ rgb-1 indexed-4
+ rgb-2 indexed-8
+ mask transparent-2
+ transparent-2 transparent-4
+ transparent-4 transparent-8
+ opaque gray-1
+ indexed-1 gray-2
+ indexed-2 gray-4
+ indexed-4 gray-8
+ opaque rgb-1
+ gray-1 rgb-1
+ gray-2 rgb-2
+ gray-4 rgb-4
+ gray-8 rgb-8
+ indexed-2 rgb-1
+ indexed-4 rgb-2
+ indexed-8 rgb-4
+ indexed-8 rgb-8
+
+Every directed acyclic graph (DAG) has a topological ordering on its nodes.
+Such an ordering can be computed by the UNIX (Version 7 AT&T UNIX) utility
+tsort(1). Its output on the author's machine:
+
+ opaque
+ transparent
+ gray-1
+ indexed-1
+ mask
+ transparent-2
+ gray-2
+ indexed-2
+ transparent-4
+ rgb-1
+ gray-4
+ indexed-4
+ transparent-8
+ rgb-2
+ gray-8
+ indexed-8
+ rgb-4
+ rgb-8
+
+This ordering should be taken into account when someone develops her
+Rule Profile. Rules having SampleFormats listed earlier should be earlier in
+the Rule Profile to avoid Warning and Notice messages.
+
+The availability (and also Warnings and Notices) of a Sample Format for a
+particular image can be easily decided after answering the following
+characteristic questions:
+
+-- Is transparency _used_?
+-- How many _used_ non-transparent colors are there? (257 if >=257)
+-- Is there a non-gray color?
+-- How many bits are required (maximum) for each component?
+
+Output rules
+~~~~~~~~~~~~
+Every detail of the output file format is precisely determined by the Output
+Rule. The Output Rule may be specified in the Job file, or is
+automatically chosen from several pre-defined output rules in the Output
+Profile (see section {Output profiles} elsewhere in this document).
+
+Output rule entries:
+
+-- FileFormat: enum (see section {Standards} for detailed information), no
+ default
+ /PSL1 -- PostScript Level1
+ /PSLC -- PostScript Level1 with the CMYK and `colorimage' extension
+ /PSL2 -- PostScript Level2 (default)
+ /PSL3 -- PostScript Level3
+ /PDFB1.0 -- PDF version 1.0, BI inline image, see 4.8.6 in PDFRef.pdf
+ /PDFB1.2 -- PDF version 1.2, BI inline image, see 4.8.6 in PDFRef.pdf
+ /PDF1.0 -- PDF version 1.0, XObject image, see 4.8.4 in PDFRef.pdf
+ /PDF1.2 -- PDF version 1.2, XObject image, see 4.8.4 in PDFRef.pdf
+ /GIF89a
+ /Empty
+ /Meta
+ /PNM
+ /PAM
+ /PIP
+ /TIFF
+ /JPEG
+ /PNG
+ /XPM
+
+-- SampleFormat: enum, no default, see section {Sample formats}
+ /Opaque
+ /Transparent
+ /Gray1
+ /Indexed1
+ /Mask
+ /Transparent2
+ /Gray2
+ /Indexed2
+ /Transparent4
+ /Rgb1
+ /Gray4
+ /Indexed4
+ /Transparent8
+ /Rgb2
+ /Gray8
+ /Indexed8
+ /Rgb4
+ /Rgb8
+ /Asis -- accept contents of the JAI file
+ /Bbox -- no image, only bounding box information
+-- WarningOK: boolean; this Output Rule is enabled iff WarningOK is true or
+ SampleFormat causes no warnings, default: true
+-- TransferEncoding: enum, no default
+ /Binary -- Binary (RawBits, see pbm(5), pgm(5), ppm(5)) (Binary integers
+ are stored in any byte order allowed by /FileFormat)
+ /ASCII -- ASCII (text, chars: 9,10,13,32..126), used with transparent and opaque
+ /Hex /AHx -- Hex ((PSL1), PDF1.0, PSL2 ASCIIHexEncode filter)
+ /A85 -- A85 (PSL2 PDF1.0, ASCII85Encode filter)
+ /MSBfirst -- Binary data with integers stored in MSB first byte order.
+ If 0x41424344 is represented as "ABCD", the byte order is called: big
+ endian, MSB, MSB first (preferred), most significant byte first, most
+ significant bit first, MSB-to-LSB, network byte order, m68k byte order.
+ QuarkXPress 3 can read only TIFF files with MSB-to-LSB byte order.
+ /LSBfirst -- Binary data with integers stored in LSB first byte order.
+ If 0x41424344 is represented as "DCBA", the byte order is called:
+ little endian, LSB, LSB first (preferred), least significant byte
+ first, least significant bit first, LSB-to-MSB, VAX byte order, PC
+ (i386) byte order.
+-- Compression: enum
+ /None -- None (default)
+ /LZW -- LZW (PSL2 PDF1.0 LZWEncode filter EarlyChange=true, UnitLength=8
+ LowBitFirst=false)
+ /ZIP /Flate /Fl -- ZIP (PSL3 PDF1.2 FlateEncode filter without options)
+ /RLE /RunLength /RunLengthEncoded /RL /PackBits -- RLE (PSL2 PDF1.0
+ RunLengthEncode filter, similar to TIFF PackBits)
+ /Fax /CCITTFax /CCF -- Fax (PSL2 PDF1.0 CCITTFaxEncode filter,
+ Uncompressed=true!, K=-1,0,1, EndOfLine=false, EncodedByteAlign=false,
+ Columns=..., Rows=0, EndOfBlock=true, BlackIs1=false,
+ DamagedRowsBeforeError=0)
+ /DCT -- DCT (PSL2 PDF1.0 DCTEncode, options in JPEG
+ stream)
+ /IJG /JPEG /JPG /JFIF -- IJG (PSL2 PDF1.0 DCTEncode, options in JPEG
+ stream; the IJG libjpeg library is used for compression, respecting the
+ quality value 0..100). This requires /SampleFormat/Rgb8 or
+ /SampleFormat/Gray8. This doesn't work with /SampleFormat/Asis.
+ /JAI -- JAI (PSL2 PDF1.0 DCTEncode, options in JPEG stream; JPEG-as-is: the
+ input file must be a JPEG file -- its contents are transferred
+ unmodified into the /DCTDecode JPEG stream). This requires
+ /SampleFormat/Asis, and doesn't work with any other /SampleFormats
+-- Predictor: enum (see later), default: 25, numbering same as PSL1 filter.
+ 1 -- no predictor. (default) Must be this unless Compression is /LZW or
+ /Flate
+ 2 -- TIFF predictor 2 (horizontal differencing)
+ 10 -- PNG predictor, None function
+ 11 -- PNG predictor, Sub function
+ 12 -- PNG predictor, Up function
+ 13 -- PNG predictor, Average function
+ 14 -- PNG predictor, Paeth function
+ 15 -- PNG predcitor, individually chosen for each line (absolute minimum)
+ This is the same as what libpng uses by default when creating PNG.
+ 25 -- Pick 15 or 1 based on the SampleFormat: use 15 for Gray8 and Rgb8,
+ and use 1 (no predictor) for everything else. This is the default.
+ 45 -- PNG predcitor, individually chosen for each line (unsigned minimum)
+ Don't use this, it is quite inefficient.
+ 55 -- PNG predcitor, individually chosen for each line (signed minimum)
+ Don't use this, it is quite inefficient.
+
+-- Transparent: color. Default: null. Specify a color forced to be
+ transparent. Old transparency, if exists, is blacked!
+-- Hints: dict
+ see below
+
+The Hints member of the Output Rule contains a dict with the following
+elements:
+
+-- TopMargin : dimen; desired vertical gap between the top line of the page
+ and the top line of the raster. Default: 0. Ignored unless for PS
+ and PDF output. See docs about `dimen' elsewhere in this document.
+-- BottomMargin : dimen; desired vertical gap between the bottom line of the
+ raster and the bottom line of the page. Default: 0. Ignored unless
+ for PS and PDF output. See docs about `dimen' elsewhere in this document.
+-- LeftMargin : dimen; desired horizontal gap between the left line of the page and
+ the left line of the raster. Default: 0. Ignored unless for PS and PDF
+ output. See docs about `dimen' elsewhere in this document.
+-- RightMargin : dimen; desired horizontal gap between the right line of the raster and
+ the right line of the page. Default: 0. Ignored unless for PS and PDF
+ output. See docs about `dimen' elsewhere in this document.
+-- ImageDPI : positive number; resolution of bitmap image in dots per inch.
+ Default: 72, which means no scaling.
+-- Scale : enum /None -- don't scale (zoom, magnify) the image (default)
+ /OK -- scale PS image to fit page (x factor == y factor)
+ /RotateOK -- scale and/or rotate PS image to fit page (x factor == y factor)
+-- EncoderBPL : int >=1 (bits per scanline, <= rlen)
+-- EncoderCoumns : int >=1 (pixels per scanline)
+-- EncoderRows : int >=1
+-- EncoderColors : int >=1
+-- PredictorColumns : uint; also used if compression is /Fax (reasonable default)
+-- PredictorColors : 1..3; number of color _components_ (reasonable default)
+-- PredictorBPC : 1, 2, 4, 8 (reasonable default), /BitsPerComponent entry in PS and PDF
+-- Effort : -1..9, must be -1 unless Compression is /ZIP (-1 means 5, default)
+-- RecordSize : uint, default: 0. Compression must be /RLE
+-- K : int, default: 0 (-2..infty). Compression must be /Fax.
+ -1 means G4 1d encoding,
+ 0 meangs G3 1D encoding,
+ -2 means G3 2D encoding with arbitrary height, positive value
+ means G3 2D encoding with that height.
+-- Quality : 0..100, used by IJG libjpeg when compression is /IJG. default: 75
+-- ColorTransform : 0..2. For IJG, this _must_ be 0 for Gray and 1 for RGB, so its value
+ is ignored. For DCT, its value is respected: use 0 or 1 only. See DCTEncode
+ in subsubsection 3.13.3 in PLRM.pdf, and for a better documentation: see the
+ sources and docs of libjpeg.
+-- TransferCPL : number of data characters per line. Must be positive when TransferEncoding is
+ /Hex or /A85, and must be zero otherwise. Default: 78
+-- DCT : dict, default: <<>>. Additional parameters for the /DCTEncode filter
+-- Comment : string, default: empty
+-- Title : string, default: empty
+-- Subject : string, default: empty
+-- Author : string, default: empty
+-- Creator : string, default: empty
+-- Producer : string, default: empty
+-- Created : string, default: now
+-- Produced : string: default: now
+
+Metric units
+""""""""""""
+Certain parameters have type `dimen'. This is a metric dimension, measured
+in any of the following real-word distance metric units:
+
+-- 1 bp = 1 bp (big point)
+-- 1 in = 72 bp (inch)
+-- 1 pt = 72/72.27 bp (point)
+-- 1 pc = 12*72/72.27 bp (pica)
+-- 1 dd = 1238/1157*72/72.27 bp (didot point) [about 1.06601110141206 bp]
+-- 1 cc = 12*1238/1157*72/72.27 bp (cicero)
+-- 1 sp = 72/72.27/65536 bp (scaled point)
+-- 1 cm = 72/2.54 bp (centimeter)
+-- 1 mm = 7.2/2.54 bp (millimeter)
+
+Note: If it helps: American typesetters use 72 points per US inch,
+thus 10 pt text will yield 72 chars per normal line of US Letter
+ (like an IBM Selectric)
+ 12 pt text will yield 65 chars per normal line of US Letter
+ (US normal typewritter).
+
+Each image pixel is assumed to be 1 bp wide and 1 bp tall. A dimen is an
+integer or real number, followed by optional whitespace and an optional unit
+(any of `bp', `in', `pt', `pc', `dd', `cc', `sp', `cm', `mm'). The default
+unit is `bp', i.e a bare number is a dimen measured in `bp'. The following
+dimens are all one inch long: `72', `72bp', `72 bp', `1in', `1 in',
+`2.54cm', `25.4mm', `72.27pt', `6pc', `4736286.72sp'.
+
+Note: MiniPS and TeX use the same units.
+
+OutputRule combinations
+~~~~~~~~~~~~~~~~~~~~~~~
+In the final version of sam2p, the following combinations will be supported:
+
+LZW >=2 Binary|Hex|A85 >=PSL2|>=PDF1.0 Mask|Gray*|RGB*|Indexed*
+LZW >=2 Binary|Hex|A85 >=PSL2|>=PDF1.0 Transparent+
+ZIP >=2 Binary|Hex|A85 >=PSL3|>=PDF1.2 Mask|Gray*|RGB*|Indexed*
+ZIP >=2 Binary|Hex|A85 >=PSL3|>=PDF1.2 Transparent+
+None|ZIP|LZW|RLE|Fax|DCT|IJG 1 Binary|Hex|A85 >=PSL2|>=PDF1.0 Mask|Gray*|RGB*|Indexed*
+None|ZIP|LZW|RLE|Fax|DCT|IJG 1 Binary|Hex|A85 >=PSL2|>=PDF1.0 Transparent+
+None 1 ASCII >=PSL1|>=PDF1.0 Opaque
+None 1 ASCII >=PSL1|>=PDF1.0 Transparent
+ZIP 1 Binary|Hex|A85 >=PSL1 Gray*|RGB*|Indexed*
+ZIP 1 Binary|Hex|A85 >=PSL1 Mask|Gray1|Indexed1
+ZIP 1 Binary|Hex|A85 >=PSL1 Transparent+
+None 1 Binary|Hex|A85 >=PSL1 Gray*|RGB*|Indexed*
+None 1 Binary|Hex|A85 >=PSL1 Mask|Gray1|Indexed1
+None 1 Binary|Hex|A85 >=PSL1 Transparent+
+RLE 1 Binary|Hex|A85 >=PSL1 Gray*|RGB*|Indexed*
+RLE 1 Binary|Hex|A85 >=PSL1 Mask|Gray1|Indexed1
+RLE 1 Binary|Hex|A85 >=PSL1 Transparent+
+JAI 1 Binary|Hex|A85 >=PSL2|>=PDF1.0 Asis
+
+TTM files
+~~~~~~~~~
+TTM stands for Template Toy Macro.
+
+A TTM file is a dirty hack for generating templates with auto-calculated
+lengths and offsets. Currently they are used for generating PDF output files
+(/FileFormat/PDFB10 etc.). The syntax
+of a TTM file is MiniPS (i.e a minimalistic PostScript, similar to .job
+files). The TTM file must contain a single MiniPS array.
+
+The elements of the array are called chunks. Each chunk causes some bytes
+to be appended to the output file. Data is appended in the order the
+chunks are listed in the TTM file, but the data calculation order may be
+different. This way it is possible to write (calc) the length of a chunk
+not written (filled in) yet. The very first chunk has number zero.
+different. This way it is possible to write the length of a chunk not
+written yet. The very first chunk has number zero.
+
+The chunk types:
+
+-- string: backtick-sequences will be substituted (e.g ``w' to the width of
+ the image, in pixels) by writeTemplate(). The result is appended to the
+ output file.
+-- positive integer: The offset (zero-based byte-position of the very first
+ character of chunk 0) of the specified chunk will be appended to
+ the output file. Only chunks already appearead may be specified this
+ way. If the specified chunk is an array, then printf("%10u") will be
+ called to print the number (this is useful for making PDF xref tables),
+ otherwise printf("%u") will be called.
+-- negative integer: The length (measured in bytes, after substitutions)
+ of the specified chunk will be appended to the output file, using
+ printf("%u"). Only chunks already calculated may be specified this way.
+-- zero: error
+-- array: the array is interpreted as a standalone TTM subfile, and the rules
+ are applied recursively. This subfile contains sub-chunks, and the
+ subchunks may be arrays themselves.
+-- other MiniPS types: error
+
+The chunks are calculated in the following order: first the array chunks are
+calculated (recursively) in order of appearance, followed by the non-array
+chunks in order of appearance.
+
+A TTM file can have up to 64 top-level chunks.
+
+Example:
+
+ [ 1 %0
+ [ (pts) ] %1.0
+ -1 %2
+ ]
+
+The output file will be: `3pts0000000001' since chunk 1 has length 3 and
+offset 1.
+
+Example job file
+~~~~~~~~~~~~~~~~
+ <<%sam2p job
+ % This is file (named test0.job).
+ /InputFile (test0.pbm)
+ /OutputFile (test0.pdf)
+ /Profile [
+ % This in-line profile is preferred over the defaults
+ << /FileFormat/PDF10 /SampleFormat/Gray1 /TransferEncoding/Binary
+ /Compression/Fax /Hints<</K 99>> >>
+ (pdf10.jib) run % elements found in external file
+ ]
+ >>
+
+See the directory examples/*.job in the sam2p sources.
+
+sam2p vs convert in 2017
+~~~~~~~~~~~~~~~~~~~~~~~~
+Several test runs were done on 2017-07-12 with the latest sam2p and the
+convert tool in ImageMagick 6.7.7-10 to compare the performance of both
+output file size and processing speed.
+
+Conclusions:
+
+-- Don't use convert for EPS output, because with `eps3:' it produces
+ an output file with non-ASCII characters, which is incompatible with many
+ systems, and with `eps:' it produces huge output files. Use e.g. sam2p
+ instead.
+-- For PDF output and JPEG or PNG input, the latest version of both convert
+ and sam2p are fast enough and produce an output of reasonable size.
+-- For PDF output and some PNG input (especially if the image has at most
+ 16 colors), sam2p can be faster and produce much smaller output than
+ convert. (This was not compared here.)
+
+Raw performance data:
+
+-- A run on a 4048x3036 landscape photo JPEG, file size 3009251 bytes:
+
+ $ time jpegtran -optimize -copy none <beach.jpg >beach.opt.jpg
+ 0.14s user 0.02s system 99% cpu 0.170 total
+ output file size: 2955545 bytes
+ (jpegtran removes some unnecessary markes from the JPEG)
+
+ $ time sam2p beach.jpg beach.jpg.sam2p.pdf
+ 0.00s user 0.01s system 90% cpu 0.011 total
+ output file size: 3009793 bytes
+ $ time convert beach.jpg beach.jpg.convert.pdf
+ 0.39s user 0.07s system 138% cpu 0.333 total
+ output file size: 2983807 bytes
+ (convert is a bit smarter removing unnecessary markers from the JPEG)
+ $ time convert beach.opt.jpg beach.opt.jpg.convert.pdf
+ 0.41s user 0.17s system 136% cpu 0.419 total
+ output file size: 2965683 bytes
+ $ time sam2p beach.opt.jpg beach.opt.jpg.sam2p.pdf
+ 0.00s user 0.01s system 90% cpu 0.014 total
+ output file size: 2956087 bytes
+ (now, without the unnecessary markers, the output of sam2p is smaller)
+
+ $ time sam2p beach.jpg beach.jpg.sam2p.eps
+ 0.02s user 0.01s system 96% cpu 0.035 total
+ output file size: 3809826 bytes
+ $ time convert beach.jpg eps3:beach.jpg.convert.eps
+ 0.27s user 0.04s system 86% cpu 0.359 total
+ output file size: 2979366 bytes
+ (the file is small, because convert doesn't apply /ASCII85Decode,
+ thus breaks the embedding of the EPS on some systems)
+ $ time sam2p -t:bin beach.opt.jpg beach.opt.jpg.sam2p_n.eps
+ 0.00s user 0.00s system 84% cpu 0.006 total
+ output file size: 2955974 bytes
+ (that's very close to the input JPEG file size, better than convert)
+
+-- A run on a 4048x3036 landscape photo PNG, file size 11508728 bytes:
+
+ $ time sam2p beach.png beach.png.sam2p.pdf
+ 4.07s user 0.15s system 99% cpu 4.223 total
+ output file size: 12471057 bytes
+ $ time convert beach.png beach.png.convert.pdf
+ 2.01s user 0.13s system 106% cpu 2.015 total
+ output file size: 18095807 bytes
+ (convert is faster, but its output PDF is much larger)
+
+ $ time sam2p beach.png beach.png.sam2p.eps
+ 2.63s user 0.18s system 99% cpu 2.812 total
+ output file size: 15734187 bytes
+ $ time convert beach.png eps3:beach.png.convert.eps
+ 1.87s user 0.06s system 99% cpu 1.933 total
+ output file size: 18079080 bytes
+ (the file is larger, but it's still not fair to compere,
+ because convert doesn't apply /ASCII85Decode,
+ thus breaks the embedding of the EPS on some systems)
+ (convert is faster because sam2p is slow to read PNG files)
+ $ time sam2p -t:bin beach.png beach.png.sam2p_n.eps
+ 2.52s user 0.24s system 99% cpu 2.761 total
+ output file size: 12428098 bytes
+ (that's the fair comparison of sizes)
+
+Some comments:
+
+-- Converting JPEG to PDF or EPS is fast for both sam2p and convert, because
+ JPEG decoding and encoding is not done. sam2p is even faster, because
+ it doesn't do lossless optimizations.
+-- When converting JPEG, convert removes some JPEG markers and does some
+ lossless optimizations (similar but less
+ than what `jpegtran -optimize -copy none' removes), thus the output of
+ convert is smaller than sam2p. However, if we run the jpegtran command
+ first, then the output of sam2p becomes smaller.
+-- When creating EPS files with convert, `eps3:' should be specified as
+ the output format, because `eps:' would create much larger files, mostly
+ because of worse compression algorithms and hex-encoding.
+-- Older versions of convert created much larger EPS files, mostly because
+ they included an uncompressed image preview.
+-- With the `eps3:' output format of convert, the EPS file will contain
+ non-ASCII characters, which is incompatible with some systems, and
+ it cannot be fixed with a command-line flag. sam2p applies /ASCII85Decode
+ (-t:a85) by default, producing an ASCII output file. Thus convert doesn't
+ have a good option: with `eps:' output files are huge; with `eps3:'
+ output files are incompatible with some systems.
+-- convert is generally slower than sam2p, except when reading PNG files
+ (for which sam2p is about 1.5 times slower). convert used to be much
+ slowen that it is now.
+-- sam2p has fewer dependencies and the total binary size is smaller than of
+ convert. This can make startup time faster, and it can make it easy to
+ install to systems without sam2p packaged.
+-- sam2p is smart and fast, and it produces small output with images with a
+ few colors only (2..16). (It doesn't matter if these colors are encoded
+ as a palette or RGB.) There were no such images in this test run.
+-- sam2p gives control to the user to fine-tune compression and other
+ settings for EPS and PDF, and convert doesn't. The defaults of sam2p are
+ tuned for the general use case though.
+
+FAQ
+~~~
+Q1. Should I care about /LoadHints (,asis,) when loading JPEG files?
+
+A1. No, sam2p guesses it by magic (in both job mode and one-liner mode).
+ However, you may want to set it manually in job mode:
+
+ /LoadHints () % use djpeg
+ /LoadHints (,asis,) % don't use djpeg
+ % nothing: automatic guess, based on /Compression/JAI
+
+Q2. How do I convert a JPEG file to PostScript Level2 EPS?
+
+A2. In one-liner mode, just run:
+
+ ./sam2p <INPUT.jpg> <OUTPUT.eps>
+ Example: ./sam2p try.jpg try.eps
+
+ In one-liner mode, if you have both the djpeg and cjpeg utilities
+ (budled with libjpeg from IJG (Independent JPEG Group)), _and_ you want
+ to adjust quality vs size of the output, just run:
+
+ ./sam2p -c:jpeg:<QUALITY> <INPUT.jpg> <OUTPUT.eps>
+ Example: ./sam2p -c:jpeg:60 try.jpg try.eps
+
+ In job mode, just run sam2p with the following .job file:
+
+ <<%sam2p-job;
+ % conversion is possible without external utilities cjpeg and djpeg
+ % No quality loss, just verbatim adata copying.
+ /InputFile (INPUT.jpg)
+ /OutputFile (OUTPUT.eps)
+ /Profile [
+ << /FileFormat/PSL2 /SampleFormat/Asis /TransferEncoding/A85
+ /Compression/JAI >>
+ ] >>
+
+ Alternatively, to adjust quality vs size, use the following .job file:
+
+ <<%sam2p-job;
+ % external utilities cjpeg and djpeg are required
+ % This uses a JPEG decompression (djpeg), plus lossy JPEG compression
+ % (cjpeg), so there might be quality loss!
+ /InputFile (INPUT.jpg)
+ /OutputFile (OUTPUT.eps)
+ /Profile [
+ << /FileFormat/PSL2 /SampleFormat/Rgb8 /TransferEncoding/A85
+ /Compression/IJG /Hints <<
+ /Quality 40 % 0..100 (should be at least around 30)
+ >> >>
+ ] >>
+
+Q3. How do I convert a GIF file to PostScript Level2 EPS?
+
+A3. Check that sam2p has been compiled with GIF support: run sam2p, and
+ examine its console output. It should contain a line:
+
+ Available Loaders: ... GIF ...
+
+ If GIF doesn't appear in the line, please recompile sam2p with:
+
+ make clean
+ ./configure --enable-gif --enable-lzw
+ make
+ cp sam2p /usr/local/bin
+
+ After that, run sam2p again, and check for the line above again.
+
+ In one-liner mode, just run:
+
+ ./sam2p <INPUT.gif> <OUTPUT.eps>
+ Example: ./sam2p try.gif try.eps
+
+ In job mode, if the GIF file doesn't have transparent pixels, run sam2p
+ with the following .job file:
+
+ <<%sam2p-job;
+ /InputFile (INPUT.gif)
+ /OutputFile (OUTPUT.eps)
+ /Profile [
+ << /FileFormat/PSL2 /SampleFormat/Indexed8 /TransferEncoding/A85
+ /Compression/None >>
+ ] >>
+
+ If the GIF file has transparent pixels, run sam2p with the following .job
+ file:
+
+ <<%sam2p-job;
+ /InputFile (INPUT.gif)
+ /OutputFile (OUTPUT.eps)
+ /Profile [
+ << /FileFormat/PSL2 /SampleFormat/Transparent8 /TransferEncoding/A85
+ /Compression/None >>
+ ] >>
+
+Q4. How do I covert a JPEG file to a TIFF/JPEG output file?
+
+A4. A TIFF/JPEG file is a TIFF file (_not_ a JPEG file!), in which the image
+ data is compressed with JPEG (DCTEncode compression). The Compression
+ TIFF tag value is 7. (There is also Compression==6, which corresponds to
+ the old, obsolete JPEG format defined in the old TIFF6.0 spec.)
+
+ In one-liner mode, autodetection is magical. Just run:
+
+ ./sam2p <INPUT.jpg> <OUTPUT.tiff>
+ Example: ./sam2p try.jpg try.tiff
+
+ In job mode, run sam2p with the following .job file:
+
+ <<%sam2p-job;
+ /InputFile (INPUT.jpg)
+ /OutputFile (OUTPUT.tiff)
+ %/LoadHints (asis) % default for /Compression/JAI
+ /Profile [
+ << /FileFormat/TIFF /SampleFormat/Asis /TransferEncoding/Binary
+ /Compression/JAI >>
+ ] >>
+
+ See also {FAQ question Q5} for compatibility notes.
+
+Q5. The TIFF/JPEG file generated by sam2p is invalid! I cannot read it with
+ any programs.
+
+A5. No, it isn't invalid, but most of the programs (including those found in
+ libtiff) cannot deal with TIFF files with JPEG compression.
+
+ Compatibility notes:
+
+ -- tif22pnm 0.03 (from the author of sam2p) can read TIFF/JPEG files
+ perfectly. That's because it calls the TIFFRGBAImageGet() function
+ of libtiff, which works.
+
+ -- sam2p 0.37 can read TIFF/JPEG files, beacuse it calls tif22pnm to do
+ the job. Sam2p can write TIFF/JPEG files as well.
+
+ -- GIMP 1.0.2: error message: `Unknown photometric number 6'. GIMP TIFF
+ import filter cannot deal with the YCbCr color space (which is the
+ most common and de facto standard color space in non-grayscale JPEG
+ files). It works, however, with grayscale JPEGs.
+
+ -- tifftopnm from libtiff-tools 3.4beta037-5.1: `unknown photometric:
+ 6'. Ditto. (Unfortunately tifftopnm doesn't call TIFFRGBAImageGet(),
+ it just tries to re-implement an obsolete version of the function.)
+
+ -- `tiffcp -c jpeg' from libtiff-tools 3.4beta037-5.1 creates a
+ perfectly legal TIFF/JPEG file.
+
+ -- tiffcp from libtiff-tools 3.4beta037-5.1 cannot load a file created
+ by itself (`tiffcp -c jpeg')! There is no problem with grayscale
+ images, but color images have one component removed.
+
+ -- xv 3.10a: Ditto.
+
+ -- display from ImageMagick 4.04: strange error message about libraries:
+ `JPEGLib: Wrong JPEG library version: library is 61, caller expects 62.'
+
+ Simple conclusion:
+
+ -- Use sam2p or `tiffcp -c jpeg' to create a TIFF/JPEG. (Be aware that
+ `tiffcp -c jpeg' cannot read a TIFF/JPEG: it can only create one.)
+ -- Use tif22pnm to load or decode a TIFF/JPEG.
+ -- In your own C programs, call the TIFFRGBAImageGet() function to read
+ TIFF image data.
+ -- Don't use anything else if you want to avoid compatibility problems.
+
+Q6. Does sam2p support transparency and alpha channels?
+
+A6. sam2p supports only bilevel transparency (i.e a pixel is either fully
+ opaque or fully transparent), and only with indexed images. Transparency
+ is supported when loading indexed PNG, TIFF, PNM, GIF, LBM and XPM files.
+ A PNM file with transparency is a regular PBM/PGM/PPM file with a
+ PBM image appended to it as the alpha channel (black pixel is
+ transparent).
+
+ For transparent output, the user has to specify /Transparent, /Mask,
+ /Transparent2, /Transparent4 or /Transparent8 as /SampleFormat. This
+ works with:
+
+ -- /FileFormat/PSL1+ /SampleFormat/Transparent
+ -- /FileFormat/PDF1.0+ /SampleFormat/Transparent
+ -- /FileFormat/PDFB1.0+ /SampleFormat/Transparent
+ -- /FileFormat/PSL1+ /SampleFormat/Mask
+ -- /FileFormat/PDF1.0+ /SampleFormat/Mask
+ -- /FileFormat/PDFB1.0+ /SampleFormat/Mask
+ -- /FileFormat/GIF89a /SampleFormat/Mask
+ -- /FileFormat/PNM /SampleFormat/Mask
+ -- /FileFormat/TIFF /SampleFormat/Mask
+ -- /FileFormat/PNG /SampleFormat/Mask
+ -- /FileFormat/XPM /SampleFormat/Mask
+ -- /FileFormat/PSL1+ /SampleFromat/Transparent+
+ -- /FileFormat/GIF89a /SampleFormat/Transparent+
+ -- /FileFormat/PNM /SampleFormat/Transparent+
+ -- /FileFormat/TIFF /SampleFormat/Transparent+
+ -- /FileFormat/PNG /SampleFormat/Transparent+
+ -- /FileFormat/XPM /SampleFormat/Transparent+
+
+Q7. How large is a pixel of PostScript and PDF files generated by sam2p in
+ real-world metric units (inches or centimeters)?
+
+A7. 72 big points == 1 inch == 2.54 centimeters
+
+ 1 pixel == 1 big point
+
+Q8. I have an image with transparent pixels. What happens if I convert it to
+ /Rgb* or /Gray*?
+
+A8. Either of the following will happen:
+
+ -- You get an error message, sam2p refuses to ignore transparency.
+ Please use /SampleFormat/Transparent+, or call an image manipulation
+ program to remove transparency from the image before feeding it to
+ sam2p.
+ -- Transparency information will be lost, and the color of formerly
+ transparent pixels will be undefined. This would be a bug in sam2p,
+ you should report it.
+
+ However, if you loaded a GIF file, and
+ transformed it to /Gray8 or /Rgb8, the original palette entry (RGB
+ triplet) is faithfully preserved.
+
+Q9. How do I generate a PostScript page ready for immediate printing with
+ margins and the image properly scaled to fit the page?
+ How do I create a PostScript file that will automatically scale the
+ image to the maximum when printed?
+
+
+A9. To print an image as a full PostScript page, call:
+
+ ./sam2p [MARGIN-SPECS] <INPUT.IMG> ps: - | lpr
+ Example: ./sam2p -m:1cm examples/pts2.pbm ps: - | lpr
+
+ To create a PostScript file for printing, call:
+
+ ./sam2p [MARGIN-SPECS] <INPUT.IMG> [ps:] <OUTPUT.ps>
+ Example: ./sam2p -m:1cm examples/pts2.pbm try.ps
+
+ The `-m' option above is sets all four margins to `1 cm'. You can
+ set the margins individually:
+
+ Example: ./sam2p -m:left:7mm -m:right:1cm -m:top:0.5in \
+ -m:bottom:18bp examples/pts2.pbm try.ps
+
+ As you can see in this example, you may specify dimensions in various
+ metric units, see subsection {Metric units}.
+
+ You are strongly encouraged to print raster images with sam2p. Be aware
+ that The GIMP 1.2 printing plugin has several weird contrast setting
+ problems (even for /Gray1 images); white pixels will be gray etc. Other
+ utilities may add unnecessary text banners or scale the image
+ inappropriately.
+
+ In one-liner mode, sam2p guesses from the file extension and the selector
+ (`ps:') whether the desired output file format is PostScript (fit single
+ page) or Encapsulated PostScript (leave size as-is, suitable for
+ inclusion into TeX documents).
+
+ In job mode, without /Scale/OK and /Scale/RotateOK in /Hints,
+ sam2p outputs EPS (Encapsulated PostScript) with /FileFormat/PSL*. EPS
+ files should be included as figures into other documents (such as TeX
+ and InDesign), not printed alone. If you just want to print a sampled
+ image alone, please use your favourite graphics manipulation program
+ instead of sam2p.
+
+ In job mode, create a .job file for the EPS file, and add /Hints. For
+ example:
+
+ <<%sam2p-job;
+ /InputFile (test.in)
+ /OutputFile (test.ps)
+ /Profile [
+ << /FileFormat/PSL2 /SampleFormat/Rgb8 /TransferEncoding/A85
+ /Compression/None /Predictor 1
+ /Hints << /Scale/OK % or /Scale/RotateOK
+ /LeftMargin 12 % measured as number/72 inches
+ /Rightargin 12 % measured as number/72 inches
+ /TopMargin 12 % measured as number/72 inches
+ /BottomMargin 12 % measured as number/72 inches
+ >>
+ >>
+ ]
+ >>
+
+Q10. Do the EPS files created by sam2p conform to some specifications?
+
+ The EPS output of sam2p conforms to the following Adobe specifications:
+
+ 5001.DSC_Spec.pdf
+ 5002.EPSF_Spec.pdf
+
+ DSC and ADSC are: Adobe Document Structuring Conventions. They are
+ comments with lines beginning with `%!' and `%%' in PS and EPS files.
+
+ An excerpt:
+
+ The following example illustrates the proper use of DSC comments in a
+ typical page description that an application might produce when including an
+ EPS file. For an EPS file that is represented as
+
+ %!PS-Adobe-3.0 EPSF-3.0
+ %%BoundingBox: 4 4 608 407
+ %%Title: (ARTWORK.EPS)
+ %%CreationDate: (10/17/89) (5:04 PM)
+ %%EndComments
+ ...PostScript code for illustration..
+ showpage
+ %%EOF
+
+ DSC comments discussion:
+
+ %!PS-Adobe-3.0 EPSF-3.0 (mandatory)
+ %%BoundingBox: ... ... ... ... (mandatory)
+
+ %%Extensions: CMYK (optional, for /PSLC)
+ %%LanguageLevel: 2 (optional, for /PSL2)
+ %%LanguageLevel: 3 (optional, for /PSL3)
+ %%Creation (strongly recommended)
+ %%Title (strongly recommended)
+ %%CreationDate (strongly recommended)
+ %%Trailer (optional)
+ %%EOF (optional)
+ %%DocumentData: Clean7Bit (optional)
+ %%DocumentData: Binary (optional)
+
+Q11. I get the error message `sam2p: Error: applyProfile: invalid
+ combination, no applicable OutputRule'. Help!
+
+A11. This error message means you have requested an invalid combination of
+ FileFormat, SampleFormat, Compression etc. parameters. If you use
+ one-liner mode, and you're sure that you've specified your will
+ correctly in the command line, please report this error message as a
+ sam2p bug (also specify -j in the command line). If you use job mode,
+ please read on.
+
+ Example 1:
+ /Compression/Fax is not allowed in /PSL1.
+
+ Solution 1:
+ specify /FileFormat/PSL2 /Compression/Fax.
+
+ Example 2:
+ /Compression/IJG requires /SampleFormat/Gray8 or /SampleFormat/Rgb8.
+ Please have a look at the messages `sam2p: Warning: check_rule: ...'
+ to get more specific information. After that, correct your request.
+
+ Solution 2:
+ specify /Compression/IJG /SampleFormat/Rgb8.
+
+ Another cause for this message is that your request cannot be applied
+ to the image you've specified. In this case, there is no relevant
+ `sam2p: Warning: check_rule: ...' message.
+
+ Example 1:
+ you've requested /SampleFormat/Indexed4,
+ but the input image has more than 16 colors.
+
+ Solution 1:
+ specify /SampleFormat/Rgb8.
+
+ Example 2:
+ you've requested /SampleFormat/Indexed4,
+ but the input image has transparency.
+
+ Solution 2:
+ specify /SampleFormat/Transparent8.
+
+ It is possible, but very unlikely that this error message is caused by
+ a bug in sam2p.
+
+Q12. Can I use /Compression/Fax when bits-per-pixel > 1 ?
+
+A12. With /FileFormat/PS* and /FileFormat/PDF*, you can (but you shouldn't,
+ because of the possibly poor compression ratio). With /FileFormat/TIFF,
+ you're not allowed to, because the TIFF specification forbids it.
+ Example one-liners:
+
+ sam2p -s:Indexed8 -c:fax test.gif test.pdf # OK
+ sam2p -s:Indexed8 -c:fax test.gif test.eps # OK
+ sam2p -s:Indexed8 -c:fax test.gif test.tiff # forbidden
+
+Q13. Bad luck?
+
+A13. Not for me.
+
+Q14. Can I use negative margins (i.e /TopMargin -20) to crop the output
+ image?
+
+A14. No. Margins are ignored by sam2p unless /FileFormat is /PSL* or /PDF*.
+ Even with these formats, the image is only moved, not cropped. Please
+ use an image manipulation program (e.g The GIMP) to crop your images
+ before feeding them to sam2p.
+
+Q15. When I try to print the PostScript output of sam2p, the edge of the
+ image is missing (white).
+
+A15. Many printers cannot print to the edge of the paper (so that region is
+ left white). Please increase the margins to a safe value, for example:
+
+ ./sam2p -m:7mm test.ppm test.ps
+ lpr test.ps
+
+ See also {FAQ question Q9} for more information about margins.
+
+Q16. How do I report a bug in sam2p?
+
+A16. Please send an e-mail to the author (pts@fazekas.hu, see more in
+ section {Copyright}) describing the problem. Don't forget to:
+
+ -- download the latest version of sam2p, and try it with the same image
+ -- describe what sam2p does (incorrectly)
+ -- describe what sam2p should do if there was no bug
+ -- run sam2p without arguments, and attach its output (STDOUT) to the
+ bug report
+ -- attach the exact command line with which you call sam2p to the bug
+ report
+ -- if you spot the bug in one-liner mode, specify the `-j' option in
+ the command line, and attach the messages printed by sam2p (both
+ STDOUT and STDERR) to the bug report
+ -- if you spot the bug in job mode, attach the .job file you are using
+ to the bug report
+ -- attach the input image file to the bug report. Try to attach a file
+ as small as possible.
+ -- if sam2p runs successfully (i.e it prints `Success.'), and it
+ creates an output image, but you think that the output image is
+ incorrect, attach the output image to your bug report
+ -- if you have a similar input image, for which sam2p works fine,
+ attach it to the bug report
+
+Q17. How long does the LZW patent held by Unisys last?
+
+A17. mcb@cloanto.com (author of http://lzw.info) wrote:
+
+ Thank you for your interest and mail. I must stress that the "exact"
+ answers you may be looking for may come only from lawyers and courts,
+ and I am none of these. If you consider the IBM, the BT and Unisys US
+ patents, then the last of the three would be the Unisys one, expiring,
+ as the article I think mentions, on June 19, 2003, 24:00. There cannot
+ be other (new) patents on LZW, as far as I know. Please let me know if
+ you find different information.
+
+Q18. I want to create an RGB PostScript image, but sam2p creates a Gray one,
+ or it gives me an error message.
+ For example: `./sam2p -1 -s:rgb1 examples/ptsbanner.gif test.eps'.
+
+A18. /PSL1 doesn't support RGB images. There are two solutions:
+
+ -- Use /PSLC or /PSL2 or /PSL3 instead or drop the '-1'
+ alltogether. Examples:
+
+ ./sam2p -1c -s:rgb1 examples/ptsbanner.gif test.eps # /PSLC
+ ./sam2p -2 -s:rgb1 examples/ptsbanner.gif test.eps # /PSL2
+ ./sam2p -s:rgb1 examples/ptsbanner.gif test.eps # /PSL2 or /PSL3
+
+ -- Use /Mask or /Transparent+. Note that you'll very probably get poor
+ compression ratio.
+
+ ./sam2p -1 -s:tr:stop examples/ptsbanner.gif test.eps # /PSL1
+
+ You can get more (and more useful) error messages from sam2p if you
+ specify the `-j:warn' option. You may also try specifying
+ `-s:rgb1:stop' instead of `-s:rgb1' to force sam2p try /SampleFormat/Rgb1
+ only.
+
+Q19. sam2p doesn't allow me to use /Compression /Fax. For example:
+ `./sam2p -c fax examples/ptsbanner.gif test.eps'. The same command
+ works fine without `-c fax'.
+
+A19. /Compression/Fax is intended to be used with images with 1 bit per
+ pixel. However, in PostScript and PDF, you can use it for any image
+ data, but compression ratio will be very poor for other than /Gray1,
+ /Indexed1 or /Mask, of course. You can force sam2p to use /Fax by
+ specifying the desired SampleFormat in option `-s'. Examples:
+
+ sam2p -s:Indexed8 -c:fax test.gif test.pdf # OK
+ sam2p -s:Indexed8 -c:fax test.gif test.eps # OK
+ sam2p -s:Indexed8 -c:fax test.gif test.tiff # forbidden by TIFF std
+
+ See {FAQ question Q12} for more information.
+
+Q20. Can sam2p convert images with transparency to PDF?
+
+A20. Only if the image has at most 1 non-transprent color
+ (/SampleFormat/Mask). See {FAQ question Q6} for details.
+
+ Although PDF-1.3 supports transparency masks for arbitrary PDF images,
+ sam2p 0.39 doesn't. That's because the author of sam2p hasn't
+ implemented it yet.
+
+Q21. I get the error message `sam2p: Warning: buildProfile: ignoring, no
+ handlers for OutputRule'. Help!
+
+A21. This means that sam2p doesn't know how to do the conversion you've
+ requested (and it even doesn't know whether the request is erroneous or
+ not). This might be because your request is bad (it is impossible to
+ be fulfilled), or your request is good, but sam2p doesn't know how to
+ deal with it. If you think that the latter is the case, please report
+ this message as a bug.
+
+ See {FAQ question Q11} for more information.
+
+Q22. How do I compile with G++ 3.2?
+
+A22. See the answer in section {Compilation and installation}. Don't forget
+
+ export CC=gcc-3.2 CXX=g++-3.2
+
+Q23. How do I do a `make dist' without running configure again?
+
+A23. Just issue
+
+ make MAKE_DIST=1 dist
+
+Q24. I cannot open a JPEG file in the Win32 version.
+
+A24. Make sure you have djpeg.exe on your PATH. Simply copy it to your
+ C:\WINDOWS directory.
+
+Q25. I cannot open a TIFF file in the Win32 version.
+
+A25. Make sure you have tif22pnm.exe on your PATH. Simply copy it to your
+ C:\WINDOWS directory.
+
+Q26. I cannot open a PNG file in the Win32 version.
+
+A26. Make sure you have png22pnm.exe on your PATH. Simply copy it to your
+ C:\WINDOWS directory.
+
+Q27. What is tif22pnm?
+
+A27. tif22pnm is a TIFF -> PNM converter written by the author of sam2p. It
+ can load more TIFF files correctly than tifftopnm, ImageMagick convert,
+ xv and The GIMP. The TIFF loader code is based on GIMP 1.3, but has
+ many bugfixes and improvements. sam2p uses tif22pnm to load TIFF files.
+ You can download tif22pnm from
+
+ https://github.com/pts/tif22pnm
+
+Q28. What is png22pnm?
+
+A28. png22pnm is a PNG -> PNM converter compiled by the author of sam2p. It
+ is based on the excellent pngtopnm utility, but doesn't depend on the
+ NetPBM library (only libpng). sam2p uses png22pnm (or, as a fallback:
+ pngtopm) to load PNG files. png22pnm is part of the tif22pnm package,
+ so you can download it from
+
+ https://github.com/pts/tif22pnm
+
+Q29. Can sam2p convert a transparent GIF to PDF?
+
+A29. The PDF-1.3 file format supports transparent images, but sam2p doesn't.
+ However, if the image contains at most two colors (including the
+ transparent pixel), sam2p can create a working PDF-1.2 file; use
+ Ghostscript to view it, because Acrobat Reader 5.0 is buggy. However,
+ sam2p supports generating transparent EPS, GIF, PNG, PNM, XPM and TIFF
+ files up to 256 colors.
+
+Q30. How do I build my own sam2p debian package?
+
+A30. Please download the newest sources (.tar.gz) from
+
+ https://github.com/pts/sam2p
+
+ As root, run
+
+ apt-get update
+ apt-get install debmake fakeroot dpkg
+ apt-get install make g++ gcc perl sed
+
+ As normal user, run (in the directory containing sam2p_main.cpp):
+
+ debian/rules clean
+ rm -f build*
+ debian/rules build
+ fakeroot debian/rules binary
+ ls -l ../sam2p_*.deb
+
+ As root, substitute X and Y, and run:
+
+ dpkg -i sam2p_X_Y.deb
+
+ Please also install the tif22pnm and png22pnm packages from the author
+ of sam2p (and the Debian standard libjpeg-progs package), available as
+ Debian source from:
+
+ https://github.com/pts/tif22pnm
+
+Q31. Why not use libjpeg/libtiff/libpng/zlib or any other library with
+ sam2p?
+
+A31. -- library and .h incompatibilities (the binary would be less portable
+ across Linux systems)
+ -- to avoid forced dependencies
+ -- checkergcc wouldn't work
+
+Q32. How do I specify the page size when printing a .ps file (-m and -e
+ command line options)?
+
+A32. You cannot. (Use -m to specify the margins.) The page size is
+ autodetected by your printer when the page is
+ printed. So you can print the same .ps file on different printers, and the
+ margins will be all right on all of them.
+
+ If you really have to specify the page size, edit the .ps file and
+ insert the `a4 ' or `letter ' command after the last line of the
+ first block of lines starting with %%. You may also use something like
+ `1 dict dup /PageSize [ 595 842 ] put setpagedevice ' to exactly specify
+ the page width and height in 1/72 inches.
+
+ For example, change the PostScript file
+
+ %!PS-Adobe-3.0
+ %%Pages: 1
+ %%DocumentData: Clean7Bit
+ %%LanguageLevel: 1
+ %%EndComments
+ %%Page: 1 1
+ save
+ ... % many lines omitted
+ %%Trailer
+ %%EOF
+
+ to
+
+ %!PS-Adobe-3.0
+ %%Pages: 1
+ %%DocumentData: Clean7Bit
+ %%LanguageLevel: 1
+ %%EndComments
+ %%Page: 1 1
+ 1 dict dup /PageSize [ 595 842 ] put setpagedevice
+ save
+ ... % many lines omitted
+ %%Trailer
+ %%EOF
+
+ Please note that PostScript is a programming language, so your changes
+ might be undone by instructions later in the file. You might find the
+ a2ping.pl utility (written by the author of sam2p) useful:
+
+ a2ping.pl -v --papersize=a4 in.ps out.ps
+
+Q33. How do I control ZIP compression ratio?
+
+A33. Use
+
+ sam2p -c:zip:1:0 in.img out.png # uncompressed ZIP carrier
+ sam2p -c:zip:1:1 in.img out.png # normal compression
+ sam2p -c:zip:1:9 in.img out.png # maximum compression
+
+Q34. ImageMagick convert creates smaller PNGs. Why?
+
+A34. I don't know the real reason. Probably because ImageMagick uses libpng,
+ which is smarter than sam2p.
+
+ You are probably trying to convert a JPEG or other true color photo to
+ PNG. Try one of the following compression options:
+
+ sam2p -c:zip:12:7 # 464727 bytes
+ sam2p -c:zip:12:8 # 454271 bytes
+ sam2p -c:zip:12:9 # 447525 bytes
+ sam2p -c:zip:13:9 # 488748 bytes
+ sam2p -c:zip:14:9 # 454182 bytes
+ sam2p -c:zip:15:9 # 453080 bytes
+ convert -quality ? # 454438 bytes
+
+Q35. Can sam2p convert large JPEGs to smaller ones (with loss of
+ quality and resolution)?
+
+A35. sam2p cannot resize or scale images. So the pixel width and height of
+ the input and output image cannot be changed. If you need that (for
+ example you want to create thumbnails), use the famous convert(1)
+ utility of ImageMagick. For example:
+
+ convert -scale 444 -quality 50 in.jpg out.jpg # specify out width
+ convert -scale x444 -quality 50 in.jpg out.jpg # specify out height
+ convert -scale "10%" -quality 50 in.jpg out.jpg # specify scale ratio
+
+ However, it is possible to specify the quality of the JPEG output of
+ sam2p. The quality of 0 means ugly output with small file size, and the
+ quality of 100 means nice output with big file sizes. You can specify
+ intermediate integer quality values (50 and 75 are recommended). Be
+ prepared that qualties above 30 (or so) may not work on all JPEG viewers.
+ For example:
+
+ sam2p -c ijg:10 large_input.jpg small_output.jpg
+
+ sam2p uses the cjpeg(1) and djpeg(1) utilities from libjpeg to write
+ and read JPEG files, respectively. If you need more control over your
+ JPEG output, then forget sam2p, and please consult the documentation of
+ those utilities.
+
+Q36. Can sam2p convert JPEG to GIF?
+
+A36. Yes, it can, but usually not directly. GIF allows a maximum of 256
+ different
+ colors in an image. A typical RGB JPEG image contains many more colors,
+ so it has to be quantized down to 256 colors first. For example, if the
+ console output of ``sam2p in.jpg out.gif'' contains ``applyProfile:
+ invalid combination, no applicable OutputRule'', then in.jpg must be
+ quantized first:
+
+ convert in.jpg out1.gif # does the quantization automatically
+ sam2p out1.gif out2.gif # compresses the output image further
+
+ From out1.gif and out2.gif keep the one with the smaller file size. It
+ is common that convert(1) creates huge GIF files because LZW compression
+ is disabled inside it. sam2p should be compiled with LZW compression
+ and GIF input/output enabled. To check this, run sam2p, and
+ examine its console output. It should contain a line:
+
+ Available Appliers: ... GIF89a+LZW ...
+
+ If GIF89a+LZW doesn't appear in the line, please recompile sam2p with:
+
+ make clean
+ ./configure --enable-gif --enable-lzw
+ make
+ cp sam2p /usr/local/bin
+
+ , and try again.
+
+Q37. I need to transform GIF images of 15 colors to BMPs of 256 colors not
+ compressed. sam2p converts it to BMP 16 colors...
+
+A37. Use
+
+ sam2p -c none -s rgb8 in.gif out.bmp
+
+ If you get an error message `Error: applyProfile: invalid combination,
+ no applicable OutputRule', it very probably means that your GIF is
+ transparent. Remove the transparent color within an image editor first.
+
+Q38. Can sam2p _load_ PDF or EPS files?
+
+A38. Yes, if you have Ghostscript installed, and your input EPS file is not
+ too exotic. This has been tested on Linux only. If you experience
+ problems loading EPS files, but no problems loading PDF files, please
+ run a2ping.pl written by the author of sam2p to make your EPS file more
+ compatible.
+
+Q39. Can sam2p load an EPS or PDF file with an arbitrary resoultion?
+
+A39. Yes. For example use one of
+
+ sam2p -l:gs=-r216 in.eps out.png
+ sam2p -l:gs=-r216 in.pdf out.png
+
+ to have resoultion 216 DPI (image scaled 3 times to both directions).
+ Without scaling, 72 DPI is the default.
+
+Q40. Can sam2p emit a multi-page PDF or a multi-page PS?
+
+A40. No, it can't. Emitting a multi-page document would need a fundamental
+ change of the sam2p architecture. (Should the 2nd page be compressed with
+ a different method? What if the 2nd contains too many colors? Should we
+ keep all previous pages in memory?)
+
+ I think another program should be written that is able to concatenate
+ EPS/PS or PDF files. I've already written a PDF-merger called pdfconcat,
+ available from https://raw.githubusercontent.com/pts/pdfconcat/master/pdfconcat.c
+ . An EPS-merger would be even easier. But I don't have time to
+ implement these features directly into sam2p soon.
+
+Q41. Can sam2p read a multi-page TIFF?
+
+A41. sam2p reads only the first page.
+
+ The auxilary utility tif22pnm could be patched so it extracts other
+ pages, and a new command line option can be added to sam2p that passes
+ the required page number to tif22pnm. But I don't have time to
+ implement these features soon.
+
+ By the way, multi-page TIFFs can be created with the following command:
+
+ tiffcp -c g4 d1.tiff d2.tiff d3.tiff output.tiff
+
+Q42. Can sam2p convert a multi-page TIFF to a multi-page PDF?
+
+A42. No. There are two main problems: See also Q40 and Q41.
+
+Q43. How do I convert a TIFF image to a 1-bit black-and-white PDF? Should I
+ use `sam2p -c:fax test.tif test.pdf'?
+
+A43. The above will ensure that fax compression is used. What you need for
+ ensuring that the output is 1-bit black-and-white is:
+
+ sam2p -s:gray1:stop test.tif test.pdf
+
+ You can also specify a compression algorithm (I recommend -c:zip):
+
+ sam2p -c:fax -s:gray1:stop test.tif test.pdf
+ sam2p -c:lzw -s:gray1:stop test.tif test.pdf
+ sam2p -c:zip -s:gray1:stop test.tif test.pdf
+
+ If you get the error message
+
+ sam2p: Error: applyProfile: invalid combination, no applicable OutputRule
+
+ then your input test.tif is not really black-and-white. Open it in an
+ image editing program and ensure that the colors are #000000 and
+ #ffffff only.
+
+ > The tiff is black and white, bilevel - I just want to avoid the
+ > test.pdf from using 8bpp by default (like it does in imagemagick)
+
+ The default for sam2p is not 8bpp. To see what the default is, run sam2p
+ with the `-j' option and check `OutputRule #1' on the console output.
+ What you are interested in is the /SampleFormat field.
+
+Q43. Acrobat Reader (5.0 and 6.0) cannot read the PDFs converted from a JPEG
+ with sam2p. I get the message: `There was an error processing a page.
+ Expected `EI' while parsing an image.'.
+ (The same problem happens with Ghostscript 6.50 with a different error
+ message. xpdf-1.0 reports: bad DCT trailer.)
+
+A43. Very probably the JPEG stream of your original input image file is
+ rejected by the PDF viewers. (In fact, Ghostscript 7.x doesn't
+ complain.) sam2p doesn't do strict JPEG validation when converting JPEG
+ to PDF -- it just blindly assumes that the JPEG file is correct. To
+ ensure this, you have to re-encode the JPEG.
+
+ Instead of this:
+
+ sam2p bad.jpeg bad.pdf
+
+ do this:
+
+ sam2p -c ijg:50 bad.jpeg good.pdf # much slower!
+
+ or this:
+
+ <bad.jpeg djpeg | cjpeg -quality 50 | sam2p - good.pdf
+
+ or this:
+
+ djpeg <bad.jpeg >temp.pnm
+ cjpeg -quality 50 <temp.pnm >temp.jpeg
+ sam2p temp.jpeg good.pdf
+
+ The real reason why Acrobat Reader rejects the JPEG is unknown to me.
+ I also don't know of any baseline JPEG compliance testing software.
+ (But if you re-encode with djpeg and cjpeg, it becomes compliant.)
+
+ (thanks to Thomas Kraemer for reporting the problem)
+
+Q44. How do I create an 1x1 transparent GIF and PNG?
+
+A44. Do
+
+ echo "P1 1 1 0" >one.pbm
+ sam2p -transparent:ffffff one.pbm one.gif
+ sam2p -transparent:ffffff one.pbm one.png
+
+Q45. Is it possible to specify a resolution other than 72 DPI, so that the
+ dimensions of the resulting PDF are accurate for print-resolution images?
+
+A45. Yes, it is. Use `-m:dpi:144' to have the output EPS or PDF scaled to
+ double size, or use `-m:dpi:<real>' to have it scaled by a factor of
+ <real>/72, or 72/-<real>, if <real> is negative.
+
+ If you know that your input image resolution is <res> DPI, and you want
+ to sam2p to create an EPS or PDF keeping the image resolution, you
+ should use `-m:dpi:-<res>'.
+
+ Note that this works only for EPS and PDF output. For all other
+ FileFormat{}s, `-m:dpi:' is ignored. The `-m:dpi:' option doesn't scale
+ the values specified for the other `-m:...' options.
+
+ Some image file formats such as PNG an JPEG can contain resolution
+ information. sam2p ignores this and assumes that the input image
+ resolution is 72 DPI). It would be possible to improve sam2p to use
+ this information, but it would be too much work.
+
+ To proper way of scaling an image, however, is
+ using your DTP or word processor program to resize it properly. For
+ example, after running `sam2p foo.png foo.pdf', in LaTeX, use
+
+ % \usepackage{graphicx}
+ \includegraphics[height=10cm]{foo}
+
+Q46. Is it legal to use LZW compression?
+
+A46. I think so. Also look at Q17.
+
+Q47. Help! I cannot compile it on SunOS/Solaris. I get
+
+ /usr/include/sys/wait.h:90: type specifier omitted for parameter
+ /usr/include/sys/wait.h:90: parse error before `*'
+
+A47. Until someone adds a test to ./configure, try adding the line
+
+ #define siginfo_t void
+
+ to the end of config2.h, just before running `make'.
+
+Q48. Should I run sam2p over all my EPS (or PDF) files, to see if they
+ would become smaller?
+
+A48. No! This is a bad idea in general, because you lose information, since
+ the EPS output of sam2p is always rasterized, so it is not scalable
+ anymore.
+
+ But you may run sam2p over all those EPS files which contain raster
+ graphics. But please be aware that sam2p re-renders everything at 72
+ DPI (can be overridden by `-l:gs=-r<DPI>', and the gs rendering
+ sometimes adjusts RGB color values slightly (+-2 on in the 0..255
+ domain), so there might be quality loss during the _reading_ of the
+ original EPS. There is absolutely no quality loss when sam2p _writes_
+ the EPS.
+
+Q49. Should I run sam2p over all my GIF, TIFF and XPM files, to see if they
+ would become smaller?
+
+A49. Yes, run `sam2p <filename> --' if you have a backup copy of the
+ original. Otherwise, choose a different filename for output.
+
+Q50. Should I run sam2p over all my PNG files, to see if they
+ would become smaller?
+
+A50. You might try it, there will be no quality loss, but the general
+ experience of the author is that the tools using libpng (e.g. pnmtopng)
+ produce slightly smaller PNG than sam2p. If you are an image
+ compression specialist, please help the author to find the reason of
+ this, and enhance sam2p.
+
+Q51. Should I run sam2p over all my JPEG files, to see if they
+ would become smaller?
+
+A51. sam2p doesn't change the file by default. Use the `-c:ijg' option
+ (possibly with a JPEG quality parameter, e.g. `-c:ijg:50') to make
+ sam2p re-encode the JPEG. This is a lossy operation, and the size of
+ the output file depends on quality parameter specified, so it might
+ actually become larger than the original. Please also note that JPEG
+ meta-information (such as EXIF tags inserted by digital cameras) gets
+ completely lost with `-c:ijg'.
+
+Q52. How do I use ZIP (Deflate) compression in LanguageLevel 2?
+
+A52. Run this:
+
+ sam2p -c:zip PSL2: in.image out.eps
+
+ This will make sam2p emit the image decoding procedure so the image
+ will be viewable (veeeery slowly) on LanguageLevel 2 devices, too. It
+ doesn't affect the rendering speed on LanguageLevel 3 devices.
+
+Q53. How do I create a GIF from an image with more than 256 colors?
+
+A53. You need the pnmquant utility too from NetPbm. Run this:
+
+ sam2p in.image PPM:- | pnmquant 256 | sam2p - out.gif
+
+ Or, if you have the convert utility from ImageMagick, run:
+
+ sam2p in.image PPM:- | convert - out.gif
+
+Q54. What is the maximum image size sam2p supports?
+
+A54. As of version 0.45, the following limits apply for input images:
+
+ -- Input image height times image width must be <= 2000000000 pixels.
+ Individual dimensions can be as high as necessary.
+ -- Input image memory must be <= 1000000000 bytes (1 GiB). The memory is
+ computed by multiplying image width, image height and BPC. BPC is
+ number of bytes per pixels. It is 3 for RGB images, 1 for grayscale
+ and indexed (256-color palette) images. For some temporary
+ calculations BPC might go up to 3 even if it is smaller than 3 in
+ the input image, so to be safe, always assume that BPC is 3 in image
+ memory calculations.
+ -- For JPEG input or ouput, image width and height must be <= 65535
+ pixels.
+ This is an inherent limitation in the JPEG file format.
+
+ In earlier versions (0.44 or below) the following additional limits
+ applied:
+
+ -- Image width must be <= 65535 pixels.
+ -- Image height must be <= 65535 pixels.
+
+ sam2p is a fast image conversion tool: it isn't unnecessarily slow on
+ large images. Its speed is predictable for uncompressed images: it
+ slows down proportionally to the input image memory (see the
+ calculation below).
+
+Q55. How do I get the smallest PNG output?
+
+A55. If your input image is truecolor, please consider a lossy compression
+ file format (such as JPEG), because the ZIP compression used in PNG is
+ not particularly well-suited for truecolor images.
+
+ If your input image has only a few colors, specify `-c zip:25:9', which
+ forces the ZIP compression whith a high effort (9) and predictor
+ autodetection (25). This is considerably slower than not specifying any
+ `-c' flag at all, and getting `-c zip:25', because the high effort (9)
+ is slower than the default effort. Please note that `-c zip:25:9'
+ disables the predictor unless the SampleFormat is Rgb8 or Gray8. (This
+ is the same what libpng-1.2.15 does by default.) For large images (of
+ Rgb{1,2,4,8} or Gray{1,2,4,8}), you may want to specify `-c zip:15:9'
+ to forcibly enable the predictor, being autodetected for each image
+ row.
+
+ Please also note that the free software ``optipng'' and the free-to-use
+ closed-source software PNGOUT (for Win32, Linux and Mac OS X) can
+ produce PNGs about 10% smaller than what sam2p produces -- but they are
+ a 100 times (or even more) slower than sam2p. The tool ``pnmtopng''
+ (tested with one linked to libpng 1.2.20) does not produce smaller PNGs
+ than sam2p >= 0.46. For older versionf of sam2p, the output of
+ ``pnmtopng'' was about 5--10% smaller.
+
+ Please also note that the the PNG output of Ghostscript -sDEVICE=pngmono
+ etc. is not optimal. Convert it with sam2p or the tools mentioned above
+ to reduce the file size.
+
+Q56. How do I get the smallest PDF output?
+
+A56. If your input image is truecolor, specify `-c jpeg', possibly tuning it
+ with a low quality parameter e.g. `-c jpeg:30'.
+
+ If your input image has only a few colors, specify `-c zip:25:9' or
+ `-c zip:15:9', see also Q55.
+
+ Please also have a look at Q55. Unfortunately, sam2p doesn't yet
+ support calling external PNG optimizers and converting their output to
+ PDF.
+
+Q57. Does sam2p convert images to canonical form, i.e. if I have two
+ source images with identical width, height and RGB8 pixel
+ representation, and I convert both with sam2p with the same flags,
+ will the two output image files be byte-by-byte identical?
+
+A57. Yes, since version 0.46-2.
+
+ The only code code needed for that was sorting the indexed palette.
+
+ For blackbox input images which sam2p doesn't decompress (e.g. JPEG
+ with /Compression/JAI), the output is only guaranteed to be
+ byte-byte-byte identical, if the input was byte-byte-byte identical.
+
+Q58. Can sam2p generate a PDF which is scaled proportionally (i.e. keeping
+ the aspect ratio) to a specified page size, and centered on the page?
+
+A58. No, but the Perl script sam2p_pdf_scale.pl bundled with sam2p can
+ post-process the file created by sam2p. For example, to scale and
+ center a PDF on an A4 paper, do:
+
+ $ sam2p input.img output.pdf
+ $ sam2p_pdf_scale.pl 595 842 output.pdf
+
+ Please also have a look at the LaTeX package pdfpages.sty for more
+ options. It can also be used to concatenate multiple PDFs.
+ Its documentation:
+ http://www.ctan.org/get/macros/latex/contrib/pdfpages/pdfpages.pdf
+
+ Example output.tex file:
+
+ \documentclass{article}
+ \pdfcompresslevel9
+ \paperwidth 21cm \pdfpagewidth\paperwidth
+ \paperheight29.7cm \pdfpageheight\paperheight
+ \usepackage{pdfpages}
+ \begin{document}
+ \includepdf{output_tmp.pdf}
+ \end{document}
+
+ How to compile the .tex file above:
+
+ $ sam2p input.img output_tmp.pdf
+ $ pdflatex output.tex
+
+ Please note that a2ping.pl or pdftk won't work either.
+
+Q59. How does sam2p detect the bounding box of PostScript and EPS input?
+
+A59. For PostScript input, the paper size specified in the PostScript code
+ is used, reverting to the system's default paper size if missing.
+ PostScript input is detected by finding `%!PS-Adobe-' at the beginning
+ of the file, but `EPSF-' missing from the first line. Paper size can be
+ specified in the PostScript code using `<</PageSize[...]>> setpagedevice', 'a4', `letter' etc.
+ The comments `%%BoundingBox:' etc. are ignored.
+
+ For EPS input, the `%%ExactBoundingBox:' is used, reverting to
+ `%%HiResBoundingBox:', reverting to `%%BoundingBox:', reverting to the
+ system's default paper size. The paper size specified in the PostScript
+ code is ignored. EPS input is detected by finding `%!PS-Adobe-' at the
+ beginning of the file and `EPSF-' in the first line. When converting to
+ PostScript, EPS or PDF, the (in.llx, in.lly) coordinates of the input
+ bounding box are not preserved: the output file will always have (0, 0)
+ as its lower left corner and (in.urx-in.llx, in.ury-in.lly) as its
+ upper right corner.
+
+Q60. When compiling sam2p, the ./configure command prints an error:
+ ``running make Makedep... error configure: error: cannot compute depends''
+
+A60. Please download the newest sam2p:
+
+ $ git clone https://github.com/pts/sam2p
+
+ , and run ./configure again. If it still
+ fails, please report the issue on https://github.com/pts/sam2p/issues ,
+ and attach the config.log file generated by ./configure to your report.
+
+ Some more detailed analysis: ./configure runs `make Makedep', which
+ runs `perl -x -S ./ccdep.pl --FAL=assert,no,yes,checker g++', which
+ runs g++ to analyze the dependencies between .cpp files, and analyzes
+ the error and warning messages printed by g++. Newer versions of g++
+ (and clang++, which is typically run instead of g++ on macOS) tend to
+ print more warnings, which ccdep.pl doesn't understand, and fails.
+
+ Work is being done to make ccdep.pl more resilient
+ (https://github.com/pts/sam2p/issues/5).
+
+Standards
+~~~~~~~~~
+-- PSL1 is PostScript LanguageLevel1, as defined by Adobe's PostScript
+ Language Reference Manual.
+-- PSLC is PSL1 with the CMYK extension (including the `colorimage'
+ operator). Supersedes PSL1.
+-- PSL2 is PostScript LanguageLevel2, as defined by Adobe's PostScript
+ Language Reference Manual. Supersedes PSLC.
+-- PSL3 is PostScript LanguageLevel3, as defined by Adobe's PostScript
+ Language Reference Manual (PLRM.pdf). Supersedes PSL2.
+-- PDF1.0 is PDF version 1.0, as defined by Adobe's PDF Reference.
+-- PDF1.1 is PDF version 1.1, as defined by Adobe's PDF Reference.
+ Supersedes PDF1.0.
+-- PDF1.2 is PDF version 1.2, as defined by Adobe's PDF Reference.
+ Supersedes PDF1.1.
+-- PDF1.3 is PDF version 1.3, as defined by Adobe's PDF Reference.
+ Supersedes PDF1.2.
+-- PDF1.4 is PDF version 1.4, as defined by Adobe's PDF Reference
+ (PDFRef.pdf). Supersedes PDF1.3.
+-- PDF1.5 is PDF version 1.4, as defined by Adobe's PDF Reference
+ (PDFRef.pdf). Supersedes PDF1.4.
+-- PBM is Portable Bitmap file format, as defined in NetPBM's pbm(5) UNIX
+ manual page.
+-- PGM is Portable Graymap file format, as defined in NetPBM's pgm(5) UNIX
+ manual page.
+-- PPM is Portable Pixmap file format, as defined in NetPBM's ppm(5) UNIX
+ manual page.
+-- PNM is Portable Anymap file format, as defined in NetPBM's pnm(5) UNIX
+ manual page. It is the union of PGM, PPM and PPM.
+-- PAM is the new, Portable ...map file format, as defined in NetPBM's pam(5)
+ UNIX manual page. We don't support it yet.
+-- TIFF is ... v6.0.
+-- JPEG is baseline JPEG JFIF file format as defined by the Joint Picture
+ Expert Group.
+-- PNG is Portable Network Graphics file format v1.0, as defined by
+ RFC 2083.
+
+Compatibility notes
+~~~~~~~~~~~~~~~~~~~
+by pts@fazekas.hu at Wed Nov 14 12:14:15 CET 2001
+Fri Mar 22 11:48:36 CET 2002
+Sat Apr 20 19:57:44 CEST 2002
+Fri Feb 7 11:15:39 CET 2003
+
+-- Ghostscript 6.50 has problems with /FileFormat/PDFB1.0
+ /SampleFormat/JAI|/IJG/DCT
+ (Error: /syntaxerror in ID). The problem has been fixed in Ghostscript
+ 7.04. With the buggy Ghostscript use /FileFormat/PDF1.0 instead.
+-- /FileFormat/PDF[B]1.0 /SampleFormat/Mask|/Indexed1 doesn't
+ work on Acrobat Reader 5.0 on Linux: a fully opaque, one-color rectangle is
+ painted. This works fine on gs 6.50 and xpdf 1.0, so Acrobat Reader is
+ assumed to be buggy.
+-- The GIMP 1.0 cannot load PlanarConfig Separated TIFF images of type
+ GrayA. (But can load PlanarConfig Contiguous GrayA.)
+-- xv cannot display gray TIFF images with transparency.
+ xv: Sorry, can not handle 2-channel images.
+-- (lib)tiff FAX compression an PS /CCITTFaxEncode have black and white the
+ opposite way. So `/CCITTFaxEncode <</BlackIs1 true>>' has to be applied
+ when creating a TIFF file.
+-- libtiff 3.5.4 doesn't read or write an indexed image with transparency:
+ Sorry, can not handle contiguous data with PhotometricInterpretation=1,
+ and Samples/pixel=2. (Doesn't work with convert or GIMP.)
+-- libtiff 3.5.4 doesn't read or write a gray with transparency:
+ Sorry, can not handle contiguous data with PhotometricInterpretation=2,
+ and Samples/pixel=2. (Doesn't work with convert, works with GIMP.)
+-- libtiff doesn't read or write TIFFTAG_SUBFILETYPE/FILETYPE_MASK +
+ TIFFTAG_PHOTOMETRIC/PHOTOMETRIC_MASK. One has to use TIFFTAG_EXTRASAMPLES
+ instead.
+-- libtiff (and the TIFF file format) supports only /Predictor 1 and
+ /Predictor 2, with /Compression/LZW and /Compression/ZIP.
+-- libtiff supports only bpc=8 and bpc=16 with /Predictor 2
+-- libtiff and most TIFF-handling utils have buggy support for TIFF/JPEG.
+ See FAQ answer Q4.
+-- libtiff supports only files with all components having the same
+ BitsPerSample.
+-- acroread 4.0 can display all possible /Predictor values with /Indexed1.
+-- Ghostscript 5.50 renders (PDF?) images inaccurately: the last bit of
+ the 8-bit palette sometimes gets wrong.
+-- Netscape Navigator 4.7 displays transparent PNG images with their bKGD
+ (or an arbitrary color if bKGD not present) as a solid background. This
+ is a bug.
+-- pdftops 0.92 has serious problems displaying images if /Predictor != 1.
+ The image will be obscured without an error message. Ghostscript 5.50 and
+ Acrobat Reader 4 do not have such problems.
+-- Ghostscript 5.50 cannot display a PDF with /ColorSpace[/Indexed/DeviceRGB
+ ...]. Acrobat Reader 4, Ghostscript 7.04 and pdftops 0.92 can.
+-- /Decode is not required in PDF.
+-- GIMP 1.0 completely ignores the PNG tRNS chunk! (Thus it won't recognise
+ such a transparency in PNG.) Use `pngtopnm -alpha' instead!
+-- pngtopnm honors the PNG bKGD chunk only if called as `pngtopnm -mix'
+ (and does mixing)
+-- convert honors the PNG bKGD chunk (and does mixing)
+-- display doesn't honor the PNG bKGD chunk, but has `-bg' command line option
+-- xv honors the PNG bKGD chunk (and does mixing)
+-- PDF procsets (subsection 8.1 of PDFRef.pdf)
+ /PDF
+ /Text
+ /ImageB Grayscale images or image masks
+ /ImageC Color images
+ /ImageI Indexed (color-table) images
+-- Ghostscript always requires the /Decode entry in image dicts
+-- /DCTEncode and /DCTDecode supports only BitsPerComponent==8.
+-- Actually PostScript supports 1,2,4,8,12 BitsPerComponent. PDF1.3 supports
+ only 1,2,4,8. We support only 1, 2, 4 and 8.
+-- PostScript also supports the CMYK color space, not just gray and RGB.
+ (And also the HSB, which can be transformed to RGB in an ugly way.)
+-- PostScript supports PNG predictors to enhance compression.
+-- The PLRM 4.10.6 describes a trick with patterns and imagemask to do
+ transparent images. Unfortunately this doesn't work in Ghostscript 5.50
+ and xpdf 0.92 (but it works in acroread 4.0), so we don't use it. That's
+ why we have only two *-transparent-* entries.
+-- ImageMagick EPSI is an EPS with preview (%%BeginPreview .. %%EndPreview)
+-- ImageMagick EPSF and EPS are equivalent
+-- ImageMagick EPS* is incredibly slooow because of the bad design, even for
+ LanguageLevel 2.
+-- ImageMagick EPS* cannot display color images without the colorimage
+ opertor. (We could do some trickery with multiple calls to imagemask.)
+-- tiff2ps cannot display color images without the colorimage
+ opertor. (We could do some trickery with multiple calls to imagemask.)
+-- Timing: 1495 x 935 RGB, gs -sDEVICE=bmp16m -sOutputFile=/dev/null
+ time gs -q -sDEVICE=ppmraw -sOutputFile=t.ppm $IN.eps </dev/null
+ ImageMagick 6620 ms user
+ tiff2ps-readhexstring 2320 ms user
+ currentfile-colorimage 2120 ms user
+ readstring-colorimage 2170 ms user
+ currentfile-/FlateDecode-colorimage 2670 ms user
+-- There is a NullEncode filter, but NullDecode doesn't exist
+-- speed conclusions:
+ 1. Use currentfile as data source (LanguageLevel2) if possible.
+ 2. /FlateDecode adds a 25% speed penalty. But it compresses quite well,
+ so use it!
+-- PostScript LanguageLevel2 supports the indexed color space:
+
+ /colormap colors 3 mul string def
+ currentfile colormap readhexstring pop pop
+ [ /Indexed /DeviceRGB colors 1 sub colormap ] setcolorspace
+
+-- EPS comments: (ImageMagick)
+
+ %%DocumentData: Clean7Bit
+ %%LanguageLevel: 1
+
+-- PSL1/PSL2 supports the following color setting operators: (all operands
+ are between 0.0 and 1.0)
+
+ <num> setgray currentgray % PSL1, 0.0=black 1.0=white
+ <hue> <saturation> <brightness> sethsbcolor % PSL1
+ <red> <green> <blue> setrgbcolor % PSL1
+ <cyan> <magenta> <yellow> <black> setcmykcolor % PSL2; not in PSL1
+
+__END__
diff --git a/graphics/sam2p/StdAfx.cpp b/graphics/sam2p/StdAfx.cpp
new file mode 100644
index 0000000000..0cb46aabd3
--- /dev/null
+++ b/graphics/sam2p/StdAfx.cpp
@@ -0,0 +1,8 @@
+// StdAfx.cpp : source file that includes just the standard includes
+// vcsam2p.pch will be the pre-compiled header
+// StdAfx.obj will contain the pre-compiled type information
+
+#include "StdAfx.h"
+
+// TODO: reference any additional headers you need in STDAFX.H
+// and not in this file
diff --git a/graphics/sam2p/StdAfx.h b/graphics/sam2p/StdAfx.h
new file mode 100644
index 0000000000..bb68251374
--- /dev/null
+++ b/graphics/sam2p/StdAfx.h
@@ -0,0 +1,39 @@
+// StdAfx.h : include file for standard system include files,
+// or project specific include files that are used frequently, but
+// are changed infrequently
+//
+
+#if !defined(AFX_STDAFX_H__A9DB83DB_A9FD_11D0_BFD1_444553540000__INCLUDED_)
+#define AFX_STDAFX_H__A9DB83DB_A9FD_11D0_BFD1_444553540000__INCLUDED_
+
+#if _MSC_VER > 1000
+#ifndef __clang__
+#pragma once
+#endif
+#endif // _MSC_VER > 1000
+
+#define WIN32_LEAN_AND_MEAN // Exclude rarely-used stuff from Windows headers
+
+
+// Windows Header Files:
+#include <windows.h>
+
+#include <process.h> /* _getpid() */
+#include <shellapi.h> /* ShellExecute() */
+
+// C RunTime Header Files
+#include <stdlib.h>
+#include <malloc.h>
+#include <memory.h>
+#include <tchar.h>
+#include <stdio.h> /* sprintf() */
+#include <oledlg.h> /* OPENFILENAME */
+
+// Local Header Files
+
+// TODO: reference additional headers your program requires here
+
+//{{AFX_INSERT_LOCATION}}
+// Microsoft Visual C++ will insert additional declarations immediately before the previous line.
+
+#endif // !defined(AFX_STDAFX_H__A9DB83DB_A9FD_11D0_BFD1_444553540000__INCLUDED_)
diff --git a/graphics/sam2p/aclocal.m4 b/graphics/sam2p/aclocal.m4
new file mode 100644
index 0000000000..fca23e9cb8
--- /dev/null
+++ b/graphics/sam2p/aclocal.m4
@@ -0,0 +1,1238 @@
+dnl
+dnl aclocal.m4, read by configure
+dnl by pts@fazekas.hu at Thu Nov 1 23:07:16 CET 2001
+dnl advanced integer checks Sat Apr 6 12:32:02 CEST 2002
+dnl
+dnl Imp: is shell `elif' compatible
+dnl Imp: less autoconf warnings
+dnl Dat: m4 SUXX, no normal error message for missing ')'
+dnl Dat: FILE *f=fopen("conftestval", "w"); is autoconf trad
+
+dnl autoconf-2.13 generates bad code for AC_C_CONST in g++-3.2
+dnl autoconf-2.54 is good (verified at Wed Dec 11 15:28:28 CET 2002)
+AC_PREREQ([2.14])
+
+dnl stupid autoconf-2.54 does #include <stdlib.h>
+m4_define([_AC_PROG_CXX_EXIT_DECLARATION],[:])
+
+AC_DEFUN([AC_PTS_CHECK_INTEGRALS],[
+dnl Checks for integral sizes.
+AC_REQUIRE([AC_HEADER_STDC])
+AC_PTS_C_CHAR_UNSIGNED
+dnl ^^^ eliminates autoconf warning `warning: AC_TRY_RUN called without default to allow cross compiling'
+
+dnl by pts@fazekas.hu at Sat Apr 6 12:43:48 CEST 2002
+dnl Run some tests in a single burst.
+if test x"$ac_cv_sizeof_char" = x; then
+AC_MSG_CHECKING(size of char)
+AC_CACHE_VAL(ac_cv_sizeof_char,
+[ac_cv_sizeof_char_p=-1;ac_cv_sizeof_short=-1;ac_cv_sizeof_int=-1
+ac_cv_sizeof_long=-1
+AC_TRY_RUN([
+#undef const
+#undef volatile
+#undef inline
+#include <stdio.h>
+int main(){FILE *f=fopen("conftestval", "w");
+ if (!f) return 1;
+ fprintf(f, "ac_cv_sizeof_char=%d\n", sizeof(char));
+ fprintf(f, "ac_cv_sizeof_char_p=%d\n", sizeof(char*));
+ fprintf(f, "ac_cv_sizeof_short=%d\n", sizeof(short));
+ fprintf(f, "ac_cv_sizeof_int=%d\n", sizeof(int));
+ fprintf(f, "ac_cv_sizeof_long=%d\n", sizeof(long));
+ return 0; /* exit(0); -- return is more portable */
+}], eval "`cat conftestval`", , ac_cv_sizeof_char=-1)])
+AC_MSG_RESULT($ac_cv_sizeof_char)
+AC_DEFINE_UNQUOTED(SIZEOF_CHAR, $ac_cv_sizeof_char)
+AC_DEFINE_UNQUOTED(SIZEOF_CHAR_P, $ac_cv_sizeof_char_p)
+AC_DEFINE_UNQUOTED(SIZEOF_SHORT, $ac_cv_sizeof_short)
+AC_DEFINE_UNQUOTED(SIZEOF_INT, $ac_cv_sizeof_int)
+AC_DEFINE_UNQUOTED(SIZEOF_LONG, $ac_cv_sizeof_long)
+fi
+dnl AC_PTS_CHECK_SIZEOF(char, -1)
+
+if test $ac_cv_sizeof_char = -1; then
+ AC_MSG_ERROR(cross compiling not supported by .._PTS_CHECK_INTEGRALS)
+fi
+AC_PTS_CHECK_SIZEOF(short, -1)
+AC_PTS_CHECK_SIZEOF(int, -1)
+AC_PTS_CHECK_SIZEOF(long, -1)
+AC_PTS_CHECK_SIZEOF(long long, -1)
+if test $ac_cv_sizeof_long_long = 8
+then ac_cv_sizeof___int64=0; ac_cv_sizeof_very_long=0; fi
+AC_PTS_CHECK_SIZEOF(very long, -1)
+if test $ac_cv_sizeof_very_long = 8; then ac_cv_sizeof___int64=0; fi
+AC_PTS_CHECK_SIZEOF(__int64, -1)
+dnl ^^^ very long type doesn't exit in any C standard.
+
+dnl Imp: make these cached
+# echo $ac_cv_sizeof_long_long
+if test $ac_cv_sizeof_char != 1; then
+ AC_MSG_ERROR(sizeof(char)!=1)
+fi
+if test $ac_cv_sizeof_short = 2; then
+ ac_cv_pts_int16_t=short
+elif test $ac_cv_sizeof_int = 2; then
+ ac_cv_pts_int16_t=int
+else
+ AC_MSG_ERROR(cannot find inttype: sizeof(inttype)==2)
+fi
+AC_DEFINE_UNQUOTED(PTS_INT16_T, $ac_cv_pts_int16_t)
+if test $ac_cv_sizeof_int = 4; then
+ ac_cv_pts_int32_t=int
+elif test $ac_cv_sizeof_long = 4; then
+ ac_cv_pts_int32_t=long
+elif test $ac_cv_sizeof_long -lt 4; then
+ AC_MSG_ERROR(sizeof(long)<4)
+else
+ AC_MSG_ERROR(cannot find inttype: sizeof(inttype)==4)
+fi
+AC_DEFINE_UNQUOTED(PTS_INT32_T, $ac_cv_pts_int32_t)
+if test $ac_cv_sizeof_long = 8; then
+ ac_cv_pts_int64_t=long
+elif test $ac_cv_sizeof_long_long = 8; then
+ ac_cv_pts_int64_t="long long"
+elif test $ac_cv_sizeof_very_long = 8; then
+ ac_cv_pts_int64_t="very long"
+elif test $ac_cv_sizeof___int64 = 8; then
+ ac_cv_pts_int64_t="__int64"
+else
+ dnl AC_DEFINE(PTS_INT64_T, 0) -- skip AC_DEFINE(); #undef is OK in aclocal.h
+ dnl Imp: put a real #undef into config.h (configure comments it out :-< )
+ ac_cv_pts_int64_t=0
+ AC_MSG_WARN(cannot find inttype: sizeof(inttype)==8)
+fi
+AC_DEFINE_UNQUOTED(PTS_INT64_T, $ac_cv_pts_int64_t)
+if test $ac_cv_sizeof_long = 16; then
+ ac_cv_pts_int128_t=long
+elif test $ac_cv_sizeof_long_long = 16; then
+ ac_cv_pts_int128_t="long long"
+elif test $ac_cv_sizeof_very_long = 16; then
+ ac_cv_pts_int128_t="very long"
+else
+ dnl AC_DEFINE(PTS_INT128_T, 0) -- skip AC_DEFINE(); #undef is OK in aclocal.h
+ dnl Imp: put a real #undef into config.h (configure comments it out :-< )
+ ac_cv_pts_int128_t=0
+ AC_MSG_WARN(cannot find inttype: sizeof(inttype)==16)
+fi
+AC_DEFINE_UNQUOTED(PTS_INT128_T, $ac_cv_pts_int128_t)
+])
+
+dnl ripped from autoconf-2.13 (ruined by autoconf-2.50)
+dnl by pts@fazekas.hu at Wed Dec 11 12:33:53 CET 2002
+dnl AC_PTS_CHECK_SIZEOF(TYPE [, CROSS-SIZE])
+AC_DEFUN(AC_PTS_CHECK_SIZEOF,
+[changequote(<<, >>)dnl
+dnl The name to #define.
+define(<<AC_TYPE_NAME>>, translit(sizeof_$1, [a-z *], [A-Z_P]))dnl
+dnl The cache variable name.
+define(<<AC_CV_NAME>>, translit(ac_cv_sizeof_$1, [ *], [_p]))dnl
+changequote([, ])dnl
+AC_MSG_CHECKING(size of $1)
+AC_CACHE_VAL(AC_CV_NAME,
+[AC_TRY_RUN([#include <stdio.h>
+#include <sys/types.h>
+int main() {
+ FILE *f=fopen("conftestval", "w");
+ if (!f) return 1;
+ fprintf(f, "%d\n", sizeof($1));
+ return 0;
+}], AC_CV_NAME=`cat conftestval`, AC_CV_NAME=0, ifelse([$2], , , AC_CV_NAME=$2))])dnl
+AC_MSG_RESULT($AC_CV_NAME)
+AC_DEFINE_UNQUOTED(AC_TYPE_NAME, $AC_CV_NAME)
+undefine([AC_TYPE_NAME])dnl
+undefine([AC_CV_NAME])dnl
+])
+
+
+
+AC_DEFUN([AC_PTS_CHECK_POINTERS],[
+AC_REQUIRE([AC_PTS_CHECK_INTEGRALS])
+AC_PTS_CHECK_SIZEOF(char *, -1)
+AC_PTS_CHECK_SIZEOF(void *, -1)
+dnl no need for checking for -1, AC_PTS_CHECK_INTEGRALS already did it
+AC_MSG_CHECKING(for an integral type to hold a ptr)
+AC_CACHE_VAL(ac_cv_pts_intp_t, [
+if test $ac_cv_sizeof_char_p != $ac_cv_sizeof_void_p; then
+ AC_MSG_ERROR($ac_cv_sizeof_char_p==sizeof(char*)!=sizeof(void*))
+fi
+if test $ac_cv_sizeof_char_p -le 2; then
+ ac_cv_pts_intp_t=$ac_cv_pts_int16_t
+elif test $ac_cv_sizeof_char_p -le 4; then
+ ac_cv_pts_intp_t=$ac_cv_pts_int32_t
+elif test $ac_cv_sizeof_char_p -le 8; then
+ ac_cv_pts_intp_t=$ac_cv_pts_int64_t
+elif test $ac_cv_sizeof_char_p -le 16; then
+ ac_cv_pts_intp_t=$ac_cv_pts_int128_t
+else
+ # :; fi; if true; then
+ AC_MSG_RESULT(not found!)
+ AC_MSG_ERROR(no integral type for sizeof(char*)==$ac_cv_sizeof_char_p)
+fi
+])dnl AC_CACHE_VAL
+AC_DEFINE_UNQUOTED(PTS_INTP_T, $ac_cv_pts_intp_t)
+AC_MSG_RESULT($ac_cv_pts_intp_t)
+AC_MSG_CHECKING(for ptr <-> integral conversion)
+AC_CACHE_VAL(ac_cv_pts_intp_ok, [
+ AC_TRY_RUN([
+/* #include "confdefs.h" -- automatic */
+int main
+#ifdef __STDC__
+(int argc, char **argv)
+#else
+(argc, argv) int argc; char **argv;
+#endif
+/* #ifndef __cplusplus; #define const; #endif -- automatic config.h */
+ {char const*p="The quick brown fox."+5;
+ PTS_INTP_T i;
+ while (*p!='r') p++; /* prevent compiler optimisations */
+ i=(PTS_INTP_T)p;
+ while (*p!='w') p++; /* prevent compiler optimisations */
+ return p!=(char*)(i+2); }
+ ], ac_cv_pts_intp_ok=yes, ac_cv_pts_intp_ok=no,
+ [AC_MSG_ERROR(cross compiling not supported by .._PTS_CHECK_POINTERS)]
+)])dnl AC_CACHE_VAL
+if test x"$ac_cv_pts_intp_ok" = xyes; then
+ AC_DEFINE(PTS_INTP_OK)
+fi
+AC_MSG_RESULT($ac_cv_pts_intp_ok)
+])
+
+dnl Ballast code elmiminated at Sat Apr 6 11:47:08 CEST 2002
+dnl [AC_MSG_RESULT(not found); AC_MSG_ERROR(This is fatal.)],
+dnl [AC_MSG_ERROR(cross compiling not supported by .._PTS_CHECK_INTEGRAL_TYPE)]
+dnl)
+dnlAC_MSG_RESULT($ac_cv_integral_type_$1)
+dnl])
+
+AC_DEFUN([AC_PTS_CHECK_INTEGRAL_TYPEX],[
+dnl @param $1: name of type
+dnl @param $2: substitution type
+dnl @param $3: stored name for the variable
+dnl errs out if specified type doesn't exist
+dnl please invoke AC_CHECK_HEADERS(unistd.h) 1st
+dnl Imp: make it work even if specified type doesn't exist
+dnl AC_TYPE_SIZE_T
+AC_REQUIRE([AC_HEADER_STDC])
+AC_MSG_CHECKING(for integral type $3)
+AC_CACHE_VAL(ac_cv_integral_type_$3, [
+AC_TRY_RUN([
+#include <stdio.h>
+/* #include "confdefs.h" -- automatic */
+#include <sys/types.h>
+#if STDC_HEADERS
+#include <stdlib.h>
+#include <stddef.h>
+#endif
+#include <stdio.h>
+#if HAVE_UNISTD_H
+#include <unistd.h>
+#endif
+#if HAVE_SYS_SOCKET_H
+#include <sys/socket.h>
+#endif
+#define MY_TYPE $1
+int main
+#ifdef __STDC__
+(int argc, char **argv)
+#else
+(argc, argv) int argc; char **argv;
+#endif
+{
+ FILE *f=fopen("conftestval", "w");
+ if (!f) return 1;
+ fprintf(f, 0<(MY_TYPE)-1 ? "unsigned " : "signed ");
+ if (sizeof(MY_TYPE)==1) fprintf(f, "char");
+ else if (sizeof(MY_TYPE)==sizeof(char)) fprintf(f, "char");
+ else if (sizeof(MY_TYPE)==sizeof(short)) fprintf(f, "short");
+ else if (sizeof(MY_TYPE)==sizeof(int)) fprintf(f, "int");
+ else if (sizeof(MY_TYPE)==sizeof(long)) fprintf(f, "long");
+ else if (sizeof(MY_TYPE)==sizeof(PTS_INT16_T)) fprintf(f, "PTS_INT16_T");
+ else if (sizeof(MY_TYPE)==sizeof(PTS_INT32_T)) fprintf(f, "PTS_INT32_T");
+ else if (sizeof(MY_TYPE)==sizeof(PTS_INT64_T)) fprintf(f, "PTS_INT64_T");
+ else if (sizeof(MY_TYPE)==sizeof(PTS_INT128_T)) fprintf(f, "PTS_INT128_T");
+ else return 3; /* fprintf(f, "???"); */
+ if (ferror(f)) return 2; /* printf("\n"); */
+ return 0;
+}],
+ [ac_cv_integral_type_$3="`cat conftestval`";
+ ],
+ dnl vvv Imp: make this a macro
+ [if test x"$2" = x; then AC_MSG_RESULT(not found); AC_MSG_ERROR(This is fatal.); fi
+ ac_cv_integral_type_$3="$2"
+ echo -n "substituting "
+ dnl ^^^ Imp: echo -n...
+ dnl AC_MSG_RESULT(substituting $2) # doesn't work because of AC_CACHE_VAL
+ ],
+ [AC_MSG_ERROR(cross compiling not supported by .._PTS_CHECK_INTEGRAL_TYPEX)]
+)
+])dnl AC_CACHE_VAL
+AC_DEFINE_UNQUOTED(PTS_$3, $ac_cv_integral_type_$3)
+AC_MSG_RESULT($ac_cv_integral_type_$3)
+])
+
+AC_DEFUN([AC_PTS_CHECK_INTEGRAL_TYPE],[
+ AC_PTS_CHECK_INTEGRAL_TYPEX($1,$2,$1)
+])
+
+AC_DEFUN([AC_PTS_TYPE_GETGROUPS], [
+ AC_REQUIRE([AC_TYPE_GETGROUPS])
+ dnl echo ,$ac_cv_type_getgroups,
+ AC_PTS_CHECK_INTEGRAL_TYPEX($ac_cv_type_getgroups, [], getgroups_t)
+])
+
+
+dnl ripped from ruby-1.6.2
+AC_DEFUN([AC_PTS_HAVE_PROTOTYPES], [
+ AC_CACHE_CHECK(whether cc supports prototypes, ac_cv_pts_have_prototypes, [
+ AC_TRY_COMPILE(
+ [int foo(int x) { return 0; }], [return foo(10);],
+ ac_cv_pts_have_prototypes=yes,
+ ac_cv_pts_have_prototypes=no
+ )
+ ])
+ if test x"$ac_cv_pts_have_prototypes" = xyes; then
+ AC_DEFINE(HAVE_PROTOTYPES)
+ fi
+])
+
+dnl by pts@fazekas.hu at Wed Dec 11 12:09:14 CET 2002
+AC_DEFUN([AC_PTS_HAVE_STATIC_CONST], [
+ AC_CACHE_CHECK(whether c++ supports static const, ac_cv_pts_have_static_const, [
+ AC_TRY_COMPILE(
+ [#undef const
+class A { public: static const int i=1; };], [return A::i==0;],
+ ac_cv_pts_have_static_const=yes,
+ ac_cv_pts_have_static_const=no
+ )
+ ])
+ if test x"$ac_cv_pts_have_static_const" = xyes; then
+ AC_DEFINE(HAVE_STATIC_CONST)
+ fi
+])
+class A { static const int i=1; };
+
+
+
+dnl by pts@fazekas.hu at Fri Nov 2 13:15:27 CET 2001
+AC_DEFUN([AC_PTS_HAVE_STDC], [
+dnl Check for working standard C (also called as ANSI C)
+dnl implies check for AC_PTS_HAVE_PROTOTYPES, AC_HEADER_STDC
+ AC_REQUIRE([AC_HEADER_STDC])
+ AC_REQUIRE([AC_PTS_HAVE_PROTOTYPES])
+ AC_CACHE_CHECK(whether cc compiles standard C, ac_cv_pts_have_stdc, [
+ AC_EGREP_CPP(nope, [
+#if defined(__STDC__) && __STDC__
+ /* note: the starting spaces are deliberate in the next line */
+ #if 0
+ nope
+ #endif
+#else
+#if defined(__cplusplus) && __cplusplus
+ #if 0
+ nope
+ #endif
+#else
+ nope
+#endif
+#endif
+ ], ac_cv_pts_have_stdc=no, [
+ if test x"$ac_cv_pts_have_prototypes" = xyes; then
+ ac_cv_pts_have_stdc=yes
+ else
+ ac_cv_pts_have_stdc=no
+ fi
+ ])
+ ])
+ if test x"$ac_cv_pts_have_stdc" = xyes; then
+ AC_DEFINE(HAVE_PTS_STDC)
+ fi
+])
+
+dnl by pts@fazekas.hu at Fri Nov 2 13:46:39 CET 2001
+AC_DEFUN([AC_PTS_C_VOLATILE], [
+ AC_CACHE_CHECK(for C keyword volatile, ac_cv_pts_have_volatile, [
+ AC_TRY_COMPILE(
+ [volatile int i;], [i=5; i++; return i-6;],
+ ac_cv_pts_have_volatile=yes,
+ ac_cv_pts_have_volatile=no
+ )
+ ])
+ if test x"$ac_cv_pts_have_volatile" = xno; then
+ AC_DEFINE(volatile, )
+ fi
+])
+
+AC_DEFUN([AC_PTS_CHECK_HEADER], [
+dnl @param $1 file to be #included
+dnl @param $2 function to be tested
+dnl @param $3 cache name, such as `strcpy_in_string'
+dnl @param $4 test code (main() function)
+dnl better than AC_CHECK_HEADERS because it undefines const and volatile
+dnl before including
+ AC_CACHE_CHECK(for working $2 in $1, ac_cv_pts_$3, [
+ AC_TRY_RUN([
+/* #include "confdefs.h" -- automatic */
+#undef const
+#undef volatile
+#undef inline
+#include <$1>
+#include "confdefs.h"
+int main
+#ifdef __STDC__
+(int argc, char **argv)
+#else
+(argc, argv) int argc; char **argv;
+#endif
+{
+ $4
+ return 1;
+}],
+ ac_cv_pts_$3=yes,
+ ac_cv_pts_$3=no,
+ [AC_MSG_ERROR(cross compiling not supported by .._PTS_CHECK_HEADER)]
+ )
+ ])
+ if test x"$ac_cv_pts_$3" = xyes; then
+ AC_DEFINE_UNQUOTED(HAVE_$3)
+ fi
+])
+
+dnl by pts@fazekas.hu at Fri Nov 2 15:05:19 CET 2001
+AC_DEFUN([AC_PTS_CHECK_STRING], [
+dnl defines ac_cv_pts_have_string
+dnl defines ac_cv_pts_have_memcmpy_builtin
+dnl defines ac_cv_pts_string_header
+ AC_PTS_CHECK_HEADER(string.h, strcpy, strcpy_in_string, [char s[42]="X"; strcpy(s, "Hello, World!"); return *s!='H';] )
+ ac_cv_pts_have_string=no
+ if test x"$ac_cv_pts_strcpy_in_string" = xyes; then
+ ac_cv_pts_have_string=yes
+ ac_cv_pts_string_header=string
+ else
+ AC_PTS_CHECK_HEADER(strings.h, strcpy, strcpy_in_strings, [char s[42]="X"; strcpy(s, "Hello, World!"); return *s!='H';] )
+ if test x"$ac_cv_pts_strcpy_in_strings" = xyes; then
+ ac_cv_pts_have_string=yes
+ ac_cv_pts_string_header=strings
+ fi
+ fi
+ if test x"$ac_cv_pts_have_string" = xyes; then
+ AC_DEFINE(HAVE_STRING)
+ fi
+ CC_bak="$CC"
+ CC="${CC:-cc} -Werror"
+ AC_PTS_CHECK_HEADER($ac_cv_pts_string_header.h, memcpy, memcpy_in_stringxs, [char s[42]="X"; memcpy(s, "Hello, World!", 2); return *s!='H'; ])
+ CC="$CC_bak"
+
+ AC_CACHE_CHECK(whether memcmp and memcpy are built-in, ac_cv_pts_have_memcmpy_builtin, [
+ ac_cv_pts_have_memcmpy_builtin=no
+ if test x"$ac_cv_pts_have_string" = xyes; then
+ dnl They are built-in for gcc 2.7.2.3 -traditional
+ if test x"$ac_cv_pts_memcpy_in_stringxs" = xno; then
+ AC_TRY_RUN([
+int main
+#ifdef __STDC__
+(int argc, char **argv)
+#else
+(argc, argv) int argc; char **argv;
+#endif
+{
+ char s[42]="X"; memcpy(s, "Hello, World!", 2); return memcmp(s, "H", 1)!=0;
+}],
+ [ac_cv_pts_have_memcmpy_builtin=yes],
+ [AC_MSG_ERROR(missing memcmp and memcpy)],
+ [AC_MSG_ERROR(cross compiling not supported by .._PTS_CHECK_STRING)]
+ )
+ fi
+ fi
+ ])
+ if test x"$ac_cv_pts_have_memcmpy_builtin" = xyes; then
+ AC_DEFINE(HAVE_MEMCMPY_BUILTIN)
+ fi
+])
+
+dnl by pts@fazekas.hu at Tue Sep 3 19:27:50 CEST 2002
+dnl g++-3.2: cc1plus: warning: ignoring command line option '-Wnested-externs'
+dnl Usage: AC_PTS_CHECK_IGNORING(nebfcmd,-Wnested-externs -Wbad-function-cast -Wmissing-declarations)
+AC_DEFUN([AC_PTS_CHECK_IGNORING], [
+ XTRA="$2"
+ CC_bak="$CC" CC="${CC:-cc} -Werror $2"
+ CXX_bak="$CXX" CXX="${CXX:-c++} -Werror $2"
+ AC_CACHE_CHECK([for ignored $2],ac_cv_pts_ignoring_$1, [
+ AC_TRY_COMPILE([],[],
+ ac_cv_pts_ignoring_$1=no,ac_cv_pts_ignoring_$1=yes)])
+ CC="$CC_bak"
+ CXX="$CXX_bak"
+])
+
+dnl by pts@fazekas.hu at Fri Nov 2 15:05:27 CET 2001
+AC_DEFUN([AC_PTS_CHECK_MALLOC], [
+dnl never fails
+ AC_PTS_CHECK_HEADER(stdlib.h, malloc, malloc_in_stdlib, [char *p=(char*)malloc(42); if (p!=0) free((void*)p); return p==0;])
+ if test x"$ac_cv_pts_malloc_in_stdlib" != xyes; then
+ AC_PTS_CHECK_HEADER(malloc.h, malloc, malloc_in_malloc, [char *p=malloc(42); if (p!=0) free(p); return p==0;])
+ fi
+])
+
+
+dnl by pts@fazekas.hu at Fri Nov 2 16:51:13 CET 2001
+AC_DEFUN([AC_PTS_HAVE_SWITCH_ENUM_BUG], [
+ AC_CACHE_CHECK(for switch(enum) bug, ac_cv_pts_have_switch_enum_bug, [
+ AC_TRY_RUN([
+enum what { foo, bar };
+int main
+#ifdef __STDC__
+(int argc, char **argv)
+#else
+(argc, argv) int argc; char **argv;
+#endif
+{
+ switch ((enum what)1) {
+ case foo: return 1;
+ case bar: return 0;
+ }
+ return 1;
+}],
+ [ac_cv_pts_have_switch_enum_bug=no],
+ [ac_cv_pts_have_switch_enum_bug=yes],
+ [AC_MSG_ERROR(cross compiling not supported by .._PTS_HAVE_SWITCH_ENUM_BUG)]
+ )
+ ])
+ if test x"$ac_cv_pts_have_switch_enum_bug" = xyes; then
+ AC_DEFINE(HAVE_SWITCH_ENUM_BUG)
+ fi
+])
+
+dnl by pts@fazekas.hu at Mon Mar 4 09:17:43 CET 2002
+AC_DEFUN([AC_PTS_HAVE_ASCII_SYSTEM], [
+ AC_CACHE_CHECK(for ASCII system, ac_cv_pts_have_ascii_system, [
+ AC_EGREP_CPP(ascii_yes,[
+#if 'a'!=97 || '!'!=33
+#error You need an ASCII system to compile this.
+#else
+ascii_yes
+#endif
+],
+ ac_cv_pts_have_ascii_system=yes, ac_cv_pts_have_ascii_system=no
+ )
+ ])
+ if test x"$ac_cv_pts_have_ascii_system" = xyes; then
+ AC_DEFINE(HAVE_ASCII_SYSTEM)
+ fi
+])
+
+AC_DEFUN([AC_PTS_ENSURE_ASCII_SYSTEM], [
+ AC_PTS_HAVE_ASCII_SYSTEM
+ if test x"$ac_cv_pts_have_ascii_system" != xyes; then
+ AC_MSG_ERROR(you need an ASCII system)
+ fi
+])
+
+dnl by pts@fazekas.hu at Fri Nov 2 16:51:13 CET 2001
+AC_DEFUN([AC_PTS_CFG_P_TMPDIR], [
+ AC_CACHE_CHECK(for tmpdir, ac_cv_pts_cfg_p_tmpdir, [
+ AC_TRY_RUN([
+#define __USE_SVID 1
+#define __USE_GNU 1
+#include <stdio.h>
+
+int main
+#ifdef __STDC__
+(int argc, char **argv)
+#else
+(argc, argv) int argc; char **argv;
+#endif
+{
+ FILE *f=fopen("conftestval","w");
+ if (!f) return 1;
+ fputs(P_tmpdir,f);
+ return 0;
+}],
+ [ac_cv_pts_cfg_p_tmpdir=\""`cat conftestval`"\"],
+ [ac_cv_pts_cfg_p_tmpdir=0],
+ [AC_MSG_ERROR(cross compiling not supported by .._PTS_CFG_P_TMPDIR)]
+ )
+ ])
+ AC_DEFINE_UNQUOTED(PTS_CFG_P_TMPDIR, $ac_cv_pts_cfg_p_tmpdir)
+])
+
+dnl by pts@fazekas.hu at Wed Oct 1 19:14:28 CEST 2003
+dnl on i386:
+dnl perl -e 'die sprintf"%.16f",(1/3)' ## 0.3333333333333333 (we chose 16)
+dnl perl -e 'die sprintf"%.17f",(1/3)' ## 0.33333333333333331
+AC_DEFUN([AC_PTS_CFG_PRINTFGLEN], [
+ AC_CACHE_CHECK(for width of printf .g, ac_cv_pts_cfg_printfglen, [
+ AC_TRY_RUN([
+#define __USE_SVID 1
+#define __USE_GNU 1
+#include <stdio.h>
+
+int main
+#ifdef __STDC__
+(int argc, char **argv)
+#else
+(argc, argv) int argc; char **argv;
+#endif
+{
+ unsigned i;
+ char tmp[64], pat[10], *p;
+ FILE *f=fopen("conftestval","w");
+ if (!f) return 1;
+ for (i=1;i<61;i++) {
+ sprintf(pat, "%%.%ug", i);
+ sprintf(tmp, pat, 1.0/3);
+ if (tmp[0]=='0' && tmp[1]=='.') {
+ p=tmp+2; while (*p=='3') p++;
+ if (*p!='\0') break;
+ }
+ }
+ if (i>1) fprintf(f,".%u",i-1);
+ return 0;
+}],
+ [ac_cv_pts_cfg_printfglen=\""`cat conftestval`"\"],
+ [ac_cv_pts_cfg_printfglen=""],
+ [AC_MSG_ERROR(cross compiling not supported by .._PTS_CFG_PRINTFGLEN)]
+ )
+ test x"$ac_cv_pts_cfg_printfglen" = x && ac_cv_pts_cfg_printfglen=no
+ ])
+ if test x"$ac_cv_pts_cfg_printfglen" = xno; then :; else
+ AC_DEFINE_UNQUOTED(PTS_CFG_PRINTFGLEN, $ac_cv_pts_cfg_printfglen)
+ fi
+])
+
+dnl by pts@fazekas.hu at Thu Dec 12 20:20:41 CET 2002
+AC_DEFUN([AC_PTS_HAVE_SYSTEMF], [
+ echo no-original >conftestval
+ AC_CACHE_CHECK(for working system(3), ac_cv_pts_systemf, [
+ AC_TRY_RUN([
+#include <stdio.h>
+#include <stdlib.h> /* system() */
+
+int main
+#ifdef __STDC__
+(int argc, char **argv)
+#else
+(argc, argv) int argc; char **argv;
+#endif
+{
+ (void)argc;
+ (void)argv;
+ if (0!=system("echo t >conftestval && echo \"let it\" be e >conftestval")) {
+ FILE *f=fopen("conftestval","w");
+ if (f) {
+ fprintf(f,"runtime-error\n");
+ fclose(f);
+ }
+ }
+ return 0;
+}
+], [ac_cv_pts_systemf="`cat conftestval`"; ac_cv_pts_systemf="${ac_cv_pts_systemf:-invalid}"],
+ [ac_cv_pts_systemf=compile-error],
+ [AC_MSG_ERROR(cross compiling not supported by .._PTS_HAVE_VSNPRINTF)]
+ )
+ # echo "($ac_cv_pts_systemf)"
+ # if test x"$ac_cv_pts_systemf" = x'"let it" be e '; then
+ if test x"$ac_cv_pts_systemf" = x't && echo "let it" be e '; then
+ # Win32 COMMAND.COM
+ ac_cv_pts_systemf=win32
+ elif test x"$ac_cv_pts_systemf" = x"let it be e"; then
+ # UNIX /bin/sh
+ ac_cv_pts_systemf=unix
+ fi
+ ])
+ if test x"$ac_cv_pts_systemf" = xwin32; then
+ ac_cv_pts_have_systemf=yes
+ AC_DEFINE(HAVE_PTS_SYSTEMF)
+ AC_DEFINE(HAVE_PTS_SYSTEMF_WIN32)
+ elif test x"$ac_cv_pts_systemf" = xunix; then
+ ac_cv_pts_have_systemf=yes
+ AC_DEFINE(HAVE_PTS_SYSTEMF)
+ AC_DEFINE(HAVE_PTS_SYSTEMF_UNIX)
+ elif test x"$ac_cv_pts_systemf" = x"invalid"; then
+ ac_cv_pts_have_systemf=no
+ elif test x"$ac_cv_pts_systemf" = x"compile-error"; then
+ ac_cv_pts_have_systemf=no
+ elif test x"$ac_cv_pts_systemf" = x"runtime-error"; then
+ ac_cv_pts_have_systemf=no
+ elif test x"$ac_cv_pts_systemf" = x"no-original"; then
+ ac_cv_pts_have_systemf=no
+ else
+ ac_cv_pts_have_systemf=yes
+ # ac_cv_pts_systemf=other
+ AC_DEFINE(HAVE_PTS_SYSTEMF)
+ AC_DEFINE(HAVE_PTS_SYSTEMF_OTHER)
+ fi
+])
+
+dnl by pts@fazekas.hu at Fri Mar 22 16:40:22 CET 2002
+AC_DEFUN([AC_PTS_HAVE_POPEN_B], [
+ AC_CACHE_CHECK(for binary popen_b, ac_cv_pts_have_popen_b, [
+ AC_TRY_RUN([
+#define _XOPEN_SOURCE 1 /* popen() on Digital UNIX */
+#define _POSIX_SOURCE 1 /* popen() */
+#define _POSIX_C_SOURCE 2 /* popen() */
+#include <stdio.h>
+
+int main
+#ifdef __STDC__
+(int argc, char **argv)
+#else
+(argc, argv) int argc; char **argv;
+#endif
+{ FILE *p=popen("echo Ko rt5","rb");
+ int i;
+ (void)argc; (void)argv;
+ if (p==0) return 1;
+ if (getc(p)!='K' || getc(p)!='o' || getc(p)!=' ') return 2;
+ if (getc(p)!='r' || getc(p)!='t') return 3;
+ if (getc(p)!='f'-'a'+'0') return 4;
+ if (getc(p)!='\n') return 5;
+ if (getc(p)!=-1) return 6;
+ if (0!=pclose(p)) return 7;
+
+ p=popen("cat >conftestval","wb");
+ if (p==0) return 31;
+ for (i=0;i<666;i++) putc(i,p);
+ if (ferror(p)) return 32;
+ if (0!=pclose(p)) return 33;
+ p=fopen("conftestval","rb");
+ if (p==0) return 34;
+ for (i=0;i<666;i++) if (getc(p)!=(i&255)) return 35;
+ if (fclose(p)!=0) return 36;
+
+ return 0;
+}
+], [ac_cv_pts_have_popen_b=yes],
+ [ac_cv_pts_have_popen_b=no],
+ [AC_MSG_ERROR(cross compiling not supported by .._PTS_HAVE_POPEN_B)]
+ )
+ ])
+dnl AC_DEFINE_UNQUOTED(HAVE_PTS_POPEN_B, $ac_cv_pts_have_popen_b)
+ if test x"$ac_cv_pts_have_popen_b" = xyes; then
+ AC_DEFINE(HAVE_PTS_POPEN_B)
+ fi
+])
+
+dnl by pts@fazekas.hu at Fri Mar 22 16:40:22 CET 2002
+AC_DEFUN([AC_PTS_HAVE_POPEN_], [
+ AC_CACHE_CHECK(for binary popen_, ac_cv_pts_have_popen_, [
+ AC_TRY_RUN([
+#define _XOPEN_SOURCE 1 /* popen() on Digital UNIX */
+#define _POSIX_SOURCE 1 /* popen() */
+#define _POSIX_C_SOURCE 2 /* popen() */
+#include <stdio.h>
+
+int main
+#ifdef __STDC__
+(int argc, char **argv)
+#else
+(argc, argv) int argc; char **argv;
+#endif
+{ FILE *p=popen("echo Ko rt5","r");
+ int i;
+ (void)argc; (void)argv;
+ if (p==0) return 1;
+ if (getc(p)!='K' || getc(p)!='o' || getc(p)!=' ') return 2;
+ if (getc(p)!='r' || getc(p)!='t') return 3;
+ if (getc(p)!='f'-'a'+'0') return 4;
+ if (getc(p)!='\n') return 5;
+ if (getc(p)!=-1) return 6;
+ if (0!=pclose(p)) return 7;
+
+ p=popen("cat >conftestval","w");
+ if (p==0) return 31;
+ for (i=0;i<666;i++) putc(i,p);
+ if (ferror(p)) return 32;
+ if (0!=pclose(p)) return 33;
+ p=fopen("conftestval","rb");
+ if (p==0) return 34;
+ for (i=0;i<666;i++) if (getc(p)!=(i&255)) return 35;
+ if (fclose(p)!=0) return 36;
+
+ return 0;
+}
+], [ac_cv_pts_have_popen_=yes],
+ [ac_cv_pts_have_popen_=no],
+ [AC_MSG_ERROR(cross compiling not supported by .._PTS_HAVE_POPEN_)]
+ )
+ ])
+dnl AC_DEFINE_UNQUOTED(HAVE_PTS_POPEN_, $ac_cv_pts_have_popen_)
+ if test x"$ac_cv_pts_have_popen_" = xyes; then
+ AC_DEFINE(HAVE_PTS_POPEN_)
+ fi
+])
+
+dnl by pts@fazekas.hu at Fri Mar 22 19:36:26 CET 2002
+dnl huge BUGFIX at Tue Jun 11 13:38:30 CEST 2002
+dnl on kempelen: ac_cv_pts_vsnprintf=bad
+AC_DEFUN([AC_PTS_HAVE_VSNPRINTF], [
+ AC_CACHE_CHECK(for working vsnprintf, ac_cv_pts_vsnprintf, [
+ AC_TRY_RUN([
+#if 0 /* autoconf-2.54 */
+ extern "C" void std::exit (int) throw (); using std::exit;
+ extern "C" void std::exit (int); using std::exit;
+ extern "C" void exit (int) throw ();
+ extern "C" void exit (int);
+ void exit (int);
+#endif
+#ifdef __cplusplus
+extern "C" void exit(int);
+#endif
+#define _BSD_SOURCE 1 /* vsnprintf */
+#define _POSIX_SOURCE 1
+#define _POSIX_C_SOURCE 2
+#include <stdio.h>
+#include <stdarg.h>
+#include <string.h>
+
+static int myprintf(int max, char *dstr, char *fmt, ...) {
+ int i;
+ va_list ap;
+ #if defined(__STDC__)
+ va_start(ap, fmt);
+ #else
+ va_start(ap);
+ #endif
+ i=vsnprintf(dstr, max, fmt, ap);
+ va_end(ap);
+ return i;
+}
+
+int c99t[]={13,9,10,10,10}, oldt[]={-1,9,-1,0,-1}, sun99t[]={13,9,10,-1,10};
+/* wincrtt[]={-1,9,10,-1,-1}, but it modifies the string in a completely
+ * bogus way (passes 1 test of 5)
+ */
+
+int main
+#ifdef __STDC__
+(int argc, char **argv)
+#else
+(argc, argv) int argc; char **argv;
+#endif
+{ char buf[40];
+ int i;
+ int g[5], gg;
+ int *t=oldt;
+ FILE *f=fopen("conftestval","w");
+ (void)argc;
+ (void)argv;
+
+ if (f) {
+ for (i=0;i<(int)sizeof(buf)-1;i++) buf[i]='X'; buf[i]='\0';
+ i=myprintf(10, buf, "%s-%ld", "Alma", -1234567L);
+ if (i==c99t[0]) t=c99t; /* oldt[0]!=c99t[0] */
+ g[0]=(i==t[0] && 0==memcmp(buf, "Alma--123\0X", 11));
+ /* printf("(%s) %d %d\n", buf, i, g[0]); */
+
+ for (i=0;i<(int)sizeof(buf)-1;i++) buf[i]='Y'; buf[i]='\0';
+ i=myprintf(10, buf, "%s-%ld", "Alma", -123L);
+ g[1]=(i==t[1] && 0==memcmp(buf, "Alma--123\0Y", 11));
+ /* printf("(%s) %d %d\n", buf, i, g[1]); */
+
+ for (i=0;i<(int)sizeof(buf)-1;i++) buf[i]='Z'; buf[i]='\0';
+ i=myprintf(10, buf, "%s-%ld", "Alma", -1234L);
+ g[2]=(i==t[2] && 0==memcmp(buf, "Alma--123\0Z", 11));
+ /* printf("(%s) %d %d\n", buf, i, g[2]); */
+
+ buf[0]='#';
+ i=myprintf(0, buf, "%s-%ld", "Alma", -1234L);
+ if (t==c99t && i==sun99t[3]) t=sun99t;
+ g[3]=(i==t[3] && buf[0]=='#');
+ /* printf("(%s) %d %d\n", buf, i, g[3]); */
+
+ buf[0]=buf[1]='$';
+ i=myprintf(1, buf, "%s-%ld", "Alma", -1234L);
+ g[4]=(i==t[4] && buf[0]=='\0' && buf[1]=='$');
+ /* printf("(%s) %d %d\n", buf, i, g[4]); */
+
+ gg=g[0] && g[1] && g[2] && g[3] && g[4];
+ fputs(!gg ? "bad\n" : t==oldt ? "old\n" : t==sun99t ? "sun99\n" : "c99\n", f);
+ fclose(f);
+ }
+ return 0;
+}
+], [ac_cv_pts_vsnprintf="`cat conftestval`"; ac_cv_pts_vsnprintf="${ac_cv_pts_vsnprintf:-invalid}"],
+ [ac_cv_pts_vsnprintf=no],
+ [AC_MSG_ERROR(cross compiling not supported by .._PTS_HAVE_VSNPRINTF)]
+ )
+ ])
+ if test x"$ac_cv_pts_vsnprintf" = xold; then
+ ac_cv_pts_have_vsnprintf=yes
+ AC_DEFINE(HAVE_PTS_VSNPRINTF)
+ AC_DEFINE(HAVE_PTS_VSNPRINTF_OLD)
+ elif test x"$ac_cv_pts_have_vsnprintf" = xc99; then
+ ac_cv_pts_have_vsnprintf=yes
+ AC_DEFINE(HAVE_PTS_VSNPRINTF)
+ AC_DEFINE(HAVE_PTS_VSNPRINTF_C99)
+ else
+ ac_cv_pts_have_vsnprintf=no
+ ac_cv_pts_vsnprintf=no
+ fi
+])
+
+dnl by pts@fazekas.hu at Sun Mar 31 17:26:01 CEST 2002
+AC_DEFUN([AC_PTS_HAVE_ERRNO_DECL], [
+ AC_CACHE_CHECK([for errno in errno.h],ac_cv_pts_errno_decl, [
+ AC_TRY_COMPILE([#include <errno.h>],[int i = errno],
+ ac_cv_pts_errno_decl=yes,ac_cv_pts_have_errno_decl=no)])
+ if test x"$ac_cv_pts_errno_decl" = x"yes"; then
+ AC_DEFINE(HAVE_ERRNO_DECL, 1, [ ])
+ fi
+])
+
+dnl by pts@fazekas.hu at Sun Mar 31 22:19:16 CEST 2002
+dnl modeled after Autoconf internal AC_EGREP_CPP
+dnl AC_PTS_SED_EGREP_CPP(SED-PATTERN, EGREP-PATTERN, PROGRAM, [ACTION-IF-FOUND [,
+dnl ACTION-IF-NOT-FOUND]])
+AC_DEFUN(AC_PTS_SED_EGREP_CPP,
+[AC_REQUIRE_CPP()dnl
+cat > conftest.$ac_ext <<EOF
+[#]line __oline__ "configure"
+#include "confdefs.h"
+[$3]
+EOF
+dnl eval is necessary to expand ac_cpp.
+dnl Ultrix and Pyramid sh refuse to redirect output of eval, so use subshell.
+if (eval "$ac_cpp conftest.$ac_ext") 2>&AC_FD_CC |
+dnl Prevent m4 from eating regexp character classes:
+changequote(, )dnl
+ sed -n '$1' | egrep '$2' >/dev/null 2>&1; then
+changequote([, ])dnl
+ ifelse([$4], , :, [rm -rf conftest*
+ $4])
+ifelse([$5], , , [else
+ rm -rf conftest*
+ $5
+])dnl
+fi
+rm -f conftest*
+])
+
+dnl by pts@fazekas.hu at Sun Mar 31 22:23:48 CEST 2002
+dnl Digital UNIX OSF/1 has it in _some_ cases.
+AC_DEFUN([AC_PTS_HAVE_GETSOCKNAME_SIZE_T], [
+ AC_CACHE_CHECK(whether getsockname accepts size_t, ac_cv_pts_have_getsockname_size_t, [
+ AC_PTS_SED_EGREP_CPP([/getsockname/,/)/p], [size_t],
+ [#include <sys/socket.h>],
+ [ac_cv_pts_have_getsockname_size_t=yes],
+ [ac_cv_pts_have_getsockname_size_t=no]
+ )
+ ])
+ if test x"$ac_cv_pts_have_getsockname_size_t" = xyes; then
+ AC_DEFINE(HAVE_PTS_GETSOCKNAME_SIZE_T)
+ fi
+])
+
+dnl by pts@fazekas.hu at Sun Mar 31 22:23:48 CEST 2002
+dnl Digital UNIX OSF/1 has it.
+AC_DEFUN([AC_PTS_HAVE_GETSOCKNAME_SOCKLEN_T], [
+ AC_CACHE_CHECK(whether getsockname accepts socklen_t, ac_cv_pts_have_getsockname_socklen_t, [
+ AC_PTS_SED_EGREP_CPP([/getsockname/,/)/p], [socklen_t],
+ [#include <sys/socket.h>],
+ [ac_cv_pts_have_getsockname_socklen_t=yes],
+ [ac_cv_pts_have_getsockname_socklen_t=no]
+ )
+ ])
+ if test x"$ac_cv_pts_have_getsockname_socklen_t" = xyes; then
+ AC_DEFINE(HAVE_PTS_GETSOCKNAME_SOCKLEN_T)
+ fi
+])
+
+dnl by pts@fazekas.hu at Sun Mar 31 23:50:05 CEST 2002
+dnl Digital UNIX OSF/1 has it.
+AC_DEFUN([AC_PTS_ENABLE_DEBUG], [
+ AC_MSG_CHECKING([for --enable-debug])
+ AC_SUBST(ENABLE_DEBUG)
+ AC_ARG_ENABLE(debug,
+ [ --enable-debug[=val] val: no, assert(default), yes, checker],
+ [], [])
+ ENABLE_DEBUG="$enable_debug"
+ if test x"$enable_debug" = xno; then
+ AC_MSG_RESULT(no)
+ elif test x"$enable_debug" = x || test x"$enable_debug" = xassert; then
+ AC_MSG_RESULT(assert)
+ ENABLE_DEBUG=assert
+ elif test x"$enable_debug" = xyes; then
+ AC_MSG_RESULT(yes)
+ elif test x"$enable_debug" = xchecker; then
+ AC_MSG_RESULT(checker)
+ else
+ AC_MSG_RESULT("?? $enable_debug")
+ AC_MSG_ERROR(Invalid --enable--debug option specified.)
+ fi
+])
+
+dnl by pts@fazekas.hu at Thu Apr 4 13:25:20 CEST 2002
+dnl Keeps conftest*
+AC_DEFUN(AC_PTS_TRY_COMPILE_NORM,
+[cat > conftest.$ac_ext <<EOF
+dnl vvv Dat: breaks newer autoconfs :-(
+dnl ifelse(AC_LANG, [FORTRAN77],
+ifelse(not_AC_LANG, [FORTRAN77],
+[ program main
+[$2]
+ end],
+[dnl This sometimes fails to find confdefs.h, for some reason.
+dnl [#]line __oline__ "[$]0"
+[#]line __oline__ "configure"
+#include "confdefs.h"
+[$1]
+int main() {
+[$2]
+; return 0; }
+])EOF
+if AC_TRY_EVAL(ac_compile); then
+ ifelse([$3], , :, [
+ $3])
+else
+ echo "configure: failed program was:" >&AC_FD_CC
+ cat conftest.$ac_ext >&AC_FD_CC
+ifelse([$4], , , [
+ $4
+])dnl
+fi
+rm -f conftest*])
+
+dnl by pts@fazekas.hu at Thu Apr 4 13:00:08 CEST 2002
+dnl Checks whether `gcc' can link C++ programs (and thus libstdc++ is
+dnl avoided).
+AC_DEFUN([AC_PTS_GCC_LINKS_CXX], [
+ AC_REQUIRE([AC_LANG_CPLUSPLUS])
+ AC_REQUIRE([AC_PROG_CXX])
+ AC_CACHE_CHECK(whether gcc can link C++ code, ac_cv_pts_gcc_links_cxx, [
+ CXX_saved="$CXX"
+ LIBS_saved="$LIBS"
+ CXX_new="$CXX"
+ ac_ext_saved="$ac_ext"
+ AC_PTS_TRY_COMPILE_NORM([
+ #include <stdio.h>
+ struct B { virtual int f()=0; int x() { return f(); } };
+ struct C1: public B { virtual int f() {return 1;}};
+ struct C2: public B { virtual int f() {return 2;}};
+ C1 global; /* global.x() will cause segfault in i386-uclibc-gcc */
+ ],[
+ /* vvv (B*) cast added for gcc-3.1 */
+ B *p=(ferror(stderr))?(B*)new C1():(B*)new C2(); /* Imp: argc... */
+ /* if (p==0) throw long(42); */ /* doesn't work with -fno-rtti */
+ int ok2=p->x()==2;
+ delete p;
+ return !(ok2 && global.x()==1);
+ ],[
+ case x"$CC" in
+ xgcc-*) CXX="$CC" ;; # gcc-3.2
+ x*-gcc-*) CXX="$CC" ;; #
+ x*-gcc) CXX="$CC" ;; # i386-uclibc-gcc
+ *) CXX=gcc ;;
+ esac
+ CXX_new="$CXX"
+ ac_ext="$ac_objext"
+ if AC_TRY_EVAL(ac_link) && test -s conftest${ac_exeext} && ./conftest${ac_exeext}
+ then ac_cv_pts_gcc_links_cxx=yes
+ else
+ LIBS="$LIBS_saved c_lgcc.cpp"
+ if AC_TRY_EVAL(ac_link) && test -s conftest${ac_exeext} && ./conftest${ac_exeext}
+ then ac_cv_pts_gcc_links_cxx=yes-with-help
+ else
+ LIBS="$LIBS_saved c_lgcc3.cpp"
+ if AC_TRY_EVAL(ac_link) && test -s conftest${ac_exeext} && ./conftest${ac_exeext}
+ then ac_cv_pts_gcc_links_cxx=yes-with-help3
+ else ac_cv_pts_gcc_links_cxx=no; CXX_new="$CXX_saved"; fi
+ fi
+ fi
+ ],[ac_cv_pts_gcc_links_cxx=compilation-failed])
+ CXX="$CXX_saved"
+ LIBS="$LIBS_saved"
+ ac_ext="$ac_ext_saved"
+ ])
+ AC_SUBST(LDXX)
+ case x"$ac_cv_pts_gcc_links_cxx" in
+ xyes-with-help) LDXX="$CXX_new"; AC_DEFINE(HAVE_PTS_C_LGCC_CPP_REQUIRED) ;;
+ xyes-with-help3) LDXX="$CXX_new"; AC_DEFINE(HAVE_PTS_C_LGCC3_CPP_REQUIRED) ;;
+ xyes) LDXX="$CXX_new" ;;
+ xno) LDXX="$CXX_new" ;;
+ *) AC_MSG_ERROR([Compilation failed, aborting.]) ;;
+ esac
+])
+
+dnl by pts@fazekas.hu at Sat Apr 6 10:56:48 CEST 2002
+dnl based on AC_PROG_CXX_G from acspecific.m4 of autoconf
+dnl Appends the specified flags to CXXFLAGS, so it will affect subsequent AC_*
+dnl tests.
+dnl Example: AC_PTS_PROG_CXXFLAGS(nrne, -fno-rtti -fno-exceptions)
+AC_DEFUN(AC_PTS_PROG_CXXFLAGS,
+[AC_REQUIRE([AC_PROG_CXX])
+AC_CACHE_CHECK(whether ${CXX-g++} accepts $2, ac_cv_prog_cxx_$1,
+[echo 'void f(void);void f(void){}' > conftest.cc
+if test -z "`${CXX-g++} $2 -c conftest.cc 2>&1`"
+then ac_cv_prog_cxx_$1=yes;
+else ac_cv_prog_cxx_$1=no; fi
+rm -f conftest*
+])
+if test $ac_cv_prog_cxx_$1 = yes; then CXXFLAGS="$CXXFLAGS $2"; fi
+])
+
+dnl by pts@fazekas.hu at Sat Apr 6 10:56:48 CEST 2002
+dnl based on AC_PROG_CXX_G from acspecific.m4 of autoconf
+dnl Appends the specified flags to CXXFLAGSB, so it won't affect subsequent
+dnl AC_* tests.
+dnl Example: AC_PTS_PROG_CXXFLAGSB(apwaw, -ansi -pedantic -Wall -W)
+AC_DEFUN(AC_PTS_PROG_CXXFLAGSB,
+[AC_REQUIRE([AC_PROG_CXX])
+AC_SUBST(CXXFLAGSB)
+AC_CACHE_CHECK(whether ${CXX-g++} accepts $2, ac_cv_prog_cxx_$1,
+[echo 'void f(void);void f(void){}' > conftest.cc
+if test -z "`${CXX-g++} $2 -c conftest.cc 2>&1`"
+then ac_cv_prog_cxx_$1=yes;
+else ac_cv_prog_cxx_$1=no; fi
+rm -f conftest*
+])
+if test $ac_cv_prog_cxx_$1 = yes; then CXXFLAGSB="$CXXFLAGSB $2"; fi
+])
+
+dnl by pts@fazekas.hu at Sat Apr 6 10:56:48 CEST 2002
+dnl based on AC_PROG_CXX_G from acspecific.m4 of autoconf
+dnl Appends the specified flags to CFLAGS, so it will affect subsequent AC_*
+dnl tests.
+dnl Example: AC_PTS_PROG_CFLAGS(nrne, -fno-rtti -fno-exceptions)
+AC_DEFUN(AC_PTS_PROG_CFLAGS,
+[AC_REQUIRE([AC_PROG_CC])
+AC_CACHE_CHECK(whether ${CC-gcc} accepts $2, ac_cv_prog_cc_$1,
+[echo 'void f(void);void f(void){}' > conftest.c
+if test -z "`${CC-gcc} $2 -c conftest.c 2>&1`"
+then ac_cv_prog_cc_$1=yes;
+else ac_cv_prog_cc_$1=no; fi
+rm -f conftest*
+])
+if test $ac_cv_prog_cc_$1 = yes; then CFLAGS="$CFLAGS $2"; fi
+])
+
+dnl by pts@fazekas.hu at Sat Apr 6 10:56:48 CEST 2002
+dnl based on AC_PROG_CXX_G from acspecific.m4 of autoconf
+dnl Appends the specified flags to CFLAGSB, so it won't affect subsequent
+dnl AC_* tests.
+dnl Example: AC_PTS_PROG_CFLAGSB(apwaw, -ansi -pedantic -Wall -W)
+AC_DEFUN(AC_PTS_PROG_CFLAGSB,
+[AC_REQUIRE([AC_PROG_CC])
+AC_SUBST(CFLAGSB)
+AC_CACHE_CHECK(whether ${CC-gcc} accepts $2, ac_cv_prog_cc_$1,
+[echo 'void f(void);void f(void){}' > conftest.c
+if test -z "`${CC-gcc} $2 -c conftest.c 2>&1`"
+then ac_cv_prog_cc_$1=yes;
+else ac_cv_prog_cc_$1=no; fi
+rm -f conftest*
+])
+if test $ac_cv_prog_cc_$1 = yes; then CFLAGSB="$CFLAGSB $2"; fi
+])
+
+dnl by pts@fazekas.hu at Sat Apr 6 11:49:59 CEST 2002
+dnl Similar to AC_C_CHAR_UNSIGNED, but without the
+dnl `warning: AC_TRY_RUN called without default to allow cross compiling'.
+AC_DEFUN(AC_PTS_C_CHAR_UNSIGNED,
+[AC_CACHE_CHECK(whether char is unsigned, ac_cv_c_char_unsigned,
+[if test "$GCC" = yes; then
+ # GCC predefines this symbol on systems where it applies.
+AC_EGREP_CPP(yes,
+[#ifdef __CHAR_UNSIGNED__
+ yes
+#endif
+], ac_cv_c_char_unsigned=yes, ac_cv_c_char_unsigned=no)
+else
+AC_TRY_RUN(
+[/* volatile prevents gcc2 from optimizing the test away on sparcs. */
+#if !defined(__STDC__) || __STDC__ != 1
+#define volatile
+#endif
+int main() {
+ volatile char c = 255; return(c < 0);
+}], ac_cv_c_char_unsigned=yes, ac_cv_c_char_unsigned=no,
+ [AC_MSG_ERROR(cross compiling not supported by .._PTS_C_CHAR_UNSIGNED)])
+fi])
+if test $ac_cv_c_char_unsigned = yes && test "$GCC" != yes; then
+ AC_DEFINE(__CHAR_UNSIGNED__)
+fi
+])
+
+dnl by pts@fazekas.hu at Sun Apr 14 22:08:04 CEST 2002
+
+dnl Ripped from autoconf's acgeneral.m4. Tests with `test -x'.
+dnl AC_PTS_PATH_XPROG(VARIABLE, PROG-TO-CHECK-FOR [, VALUE-IF-NOT-FOUND [, PATH]])
+AC_DEFUN(AC_PTS_PATH_XPROG,
+[# Extract the first word of "$2", so it can be a program name with args.
+set dummy $2; ac_word=[$]2
+AC_MSG_CHECKING([for $ac_word])
+AC_CACHE_VAL(ac_cv_path_$1,
+[case "[$]$1" in
+ /*)
+ ac_cv_path_$1="[$]$1" # Let the user override the test with a path.
+ ;;
+ ?:/*)
+ ac_cv_path_$1="[$]$1" # Let the user override the test with a dos path.
+ ;;
+ *)
+ IFS="${IFS= }"; ac_save_ifs="$IFS"; IFS=":"
+dnl $ac_dummy forces splitting on constant user-supplied paths.
+dnl POSIX.2 word splitting is done only on the output of word expansions,
+dnl not every word. This closes a longstanding sh security hole.
+ ac_dummy="ifelse([$4], , $PATH, [$4])"
+ for ac_dir in $ac_dummy; do
+ test -z "$ac_dir" && ac_dir=.
+ if test -x $ac_dir/$ac_word; then
+ ac_cv_path_$1="$ac_dir/$ac_word"
+ break
+ fi
+ done
+ IFS="$ac_save_ifs"
+dnl If no 3rd arg is given, leave the cache variable unset,
+dnl so AC_PATH_PROGS will keep looking.
+ifelse([$3], , , [ test -z "[$]ac_cv_path_$1" && ac_cv_path_$1="$3"
+])dnl
+ ;;
+esac])dnl
+$1="$ac_cv_path_$1"
+if test -n "[$]$1"; then
+ AC_MSG_RESULT([$]$1)
+else
+ AC_MSG_RESULT(no)
+fi
+AC_SUBST($1)dnl
+])
+
+dnl by pts@fazekas.hu at Sun Apr 14 21:50:13 CEST 2002
+
+dnl Usage: AC_PTS_WARN_PROG(zip, [zip might become useful for /Compression/ZIP])
+AC_DEFUN(AC_PTS_WARN_PROG,
+[AC_PTS_PATH_XPROG(pts_$1, $1)
+if test x"$ac_cv_path_pts_$1" = x; then
+ AC_MSG_WARN($1 would provide increased functionality to this program:)
+ AC_MSG_WARN($2)
+fi
+])
+dnl Usage: AC_PTS_ERR_PROG(make, [make is required for compiling this program])
+AC_DEFUN(AC_PTS_ERR_PROG,
+[AC_PTS_PATH_XPROG(pts_$1, $1)
+if test x"$ac_cv_path_pts_$1" = x; then
+ AC_MSG_WARN($1 is required:)
+ AC_MSG_ERROR($2)
+fi
+])
+
+dnl by pts@fazekas.hu at Sat Jun 1 15:00:44 CEST 2002
+dnl ac_n=... autoconf2.13 -> autoconf2.50
+dnl Usage: AC_PTS_RUN_OK(CMDLINE, ACTION-OF-EXITCODE-0, ACTION-IF-ERROR)
+AC_DEFUN(AC_PTS_RUN_OK,
+[ac_n="${ac_n:-$ECHO_N}"
+echo $ac_n "running $1""... $ac_c" 1>&AC_FD_MSG
+echo "configure:__oline__: running $1" >&AC_FD_CC
+if >&AC_FD_CC 2>&AC_FD_CC $1; then :
+ AC_MSG_RESULT(ok)
+ $2
+else
+ AC_MSG_RESULT(error)
+ $3
+fi
+])
+
+dnl by pts@fazekas.hu at Sat Jun 1 15:13:36 CEST 2002
+AC_DEFUN(AC_PTS_OK, [echo "configure:__oline__: all OK" >&AC_FD_CC
+])
+
+dnl __EOF__
diff --git a/graphics/sam2p/appliers.cpp b/graphics/sam2p/appliers.cpp
new file mode 100644
index 0000000000..2614ef4b45
--- /dev/null
+++ b/graphics/sam2p/appliers.cpp
@@ -0,0 +1,2255 @@
+/*
+ * appliers.cpp -- specific OutputRule implementations
+ * by pts@fazekas.hu at Sat Mar 16 14:45:02 CET 2002
+ * Blanca JAI additions at Tue May 21 13:18:26 CEST 2002
+ * TIFF output at Tue Jun 4 19:50:45 CEST 2002
+ */
+
+#ifdef __GNUC__
+#ifndef __clang__
+#pragma implementation
+#endif
+#endif
+
+#include "rule.hpp"
+#include "error.hpp"
+#include "encoder.hpp"
+#include "in_jai.hpp"
+#include "crc32.h" /* crc32() used by out_png_work() */
+#include <string.h>
+
+/** Appends 4 bytes in MSB first (network) byte order */
+static inline void mf32(char *&p, slen_t u32) {
+ p[0]=(u32>>24)&255;
+ p[1]=(u32>>16)&255;
+ p[2]=(u32>> 8)&255;
+ p[3]=(u32 )&255;
+ p+=4;
+}
+/** Appends 4 bytes in LSB first (PC) byte order */
+static inline void lf32(char *&p, slen_t u32) {
+ p[0]=(u32 )&255;
+ p[1]=(u32>> 8)&255;
+ p[2]=(u32>>16)&255;
+ p[3]=(u32>>24)&255;
+ p+=4;
+}
+/** Appends 2 bytes in LSB first (PC) byte order */
+static inline void lf16(char *&p, unsigned u16) {
+ p[0]=(u16 )&255;
+ p[1]=(u16>> 8)&255;
+ p+=2;
+}
+
+
+/* --- at Sat Mar 23 15:42:17 CET 2002, removed obsolete
+ * PostScript Level2 FlateEncode or LZWEncode filter, predictors supported
+ * written at Mar 16 14:48:27 CET 2002
+ */
+
+/* --- Sun Mar 17 15:43:20 CET 2002 */
+
+#if 0
+/* l1fa85g.tte was a special .tte that is not built in to bts.ttt, but I've
+ * integrated it into bts2.ttt at Sun Sep 22 00:48:21 CEST 2002. I've also
+ * integrated _l1fa85g_ to _l1c_ that day.
+ */
+static char *l1fa85g_tte=
+#include "l1fa85g.tth"
+
+/** PostScript Level1 FlateEncode, A85, without Predictor */
+Rule::Applier::cons_t out_l1fa85g_check_rule(Rule::OutputRule* or_) {
+ Rule::Cache *cache=&or_->cache;
+ if (!cache->isPS()
+ || cache->Compression!=Rule::Cache::CO_ZIP
+ || cache->hasPredictor()
+ || !cache->isGray()
+ || cache->TransferEncoding!=cache->TE_A85
+ || (!cache->WarningOK && !cache->isPSL3())
+ ) return Rule::Applier::DONT_KNOW;
+ return Rule::Applier::OK;
+}
+Rule::Applier::cons_t out_l1fa85g_work(GenBuffer::Writable& out, Rule::OutputRule*or_, Image::SampledInfo *sf) {
+ /* by pts@fazekas.hu at Sun Mar 17 15:52:48 CET 2002 */
+ // Imp: two other TransferEncodings [no more, since #if 0]
+ if (out_l1fa85g_check_rule(or_)!=Rule::Applier::OK) return Rule::Applier::DONT_KNOW;
+ if (!or_->cache.isPSL3())
+ Error::sev(Error::WARNING_DEFER) << "l1fa85g: /ZIP without /PSL3 will be slow" << (Error*)0;
+ or_->doSampleFormat(sf);
+ PSEncoder *bp=PSEncoder::newASCII85Encode(out, or_->cacheHints.TransferCPL);
+ PSEncoder *cp=PSEncoder::newFlateEncode(*bp, or_->cacheHints.Effort);
+ Rule::writeTTE(out, out, *cp, l1fa85g_tte, or_, sf, Rule::writeData);
+ delete bp;
+ delete cp;
+ return Rule::Applier::OK;
+}
+
+Rule::Applier out_l1fa85g_applier = { "l1fa85g", out_l1fa85g_check_rule, out_l1fa85g_work, 0 };
+#endif
+
+/* l2jbin --- Sun Mar 17 21:45:22 CET 2002
+ * p0jbin (integrated to p0jbin) --- Mon Apr 15 23:29:13 CEST 2002
+ */
+
+//static char *l2jbin_tte=
+//#include "l2jbin.tth"
+
+/** PostScript Level2 DCTEncode (Baseline JPEG), Binary */
+Rule::Applier::cons_t out_l2jbin_check_rule(Rule::OutputRule* or_) {
+ Rule::Cache *cache=&or_->cache;
+ if ((!cache->isPS() && !cache->isPDF())
+ || cache->Compression!=Rule::Cache::CO_JAI
+ ) return Rule::Applier::DONT_KNOW;
+ /* Dat: not unrequired anymore: cache->TransferEncoding!=cache->TE_Binary */
+ bool badp=false;
+ if (cache->isPS() && !cache->isPSL2()) {
+ Error::sev(Error::WARNING_DEFER) << "check_rule: /FileFormat/PSL* /Compression/JAI requires /PSL2+" << (Error*)0;
+ badp=true;
+ }
+ if (cache->SampleFormat!=Image::SF_Asis) {
+ Error::sev(Error::WARNING_DEFER) << "check_rule: /FileFormat/PSL*|PDF* /Compression/JAI requires /SampleFormat/Asis" << (Error*)0;
+ badp=true;
+ }
+ if (cache->hasPredictor()) {
+ Error::sev(Error::WARNING_DEFER) << "check_rule: /FileFormat/PSL*|PDF* /Compression/JAI requires /Predictor 1" << (Error*)0;
+ badp=true;
+ }
+ return (Rule::Applier::cons_t)(badp ? 0+Rule::Applier::BAD : 0+Rule::Applier::OK);
+ /* ^^^ 0+: pacify g++-3.1 */
+}
+Rule::Applier::cons_t out_l2jbin_work(GenBuffer::Writable& out, Rule::OutputRule*or_, Image::SampledInfo *sf) {
+ char const*strings[]={ (char const*)NULLP/*LanguageLevel, PDF-1.`0'*/, ""/*colorSpace*/ };
+ //, " F closefile T closefile"/*closes*/ };
+ // Error::sev(Error::WARNING_DEFER) << "l2jbin: /ZIP without /PSL3 will be slow" << (Error*)0;
+ if (out_l2jbin_check_rule(or_)!=Rule::Applier::OK) return Rule::Applier::DONT_KNOW;
+ assert(sf->getImg()->getBpc()==8);
+ or_->doSampleFormat(sf);
+ // PSEncoder *bp=PSEncoder::newASCII85Encode(out, or_->cacheHints.TransferCPL);
+ Rule::Cache *cache=&or_->cache;
+ Filter::VerbatimE outve(out); /* required since template /p0jbin is TTM */
+ GenBuffer::Writable *op=cache->isPDF() ? &outve : &out, *tp=op;
+ strings[0]=const_cast<char*>(cache->isPDF() ? (char const*)"0" : (char const*)"2");
+ if (cache->TransferEncoding==cache->TE_A85) tp=PSEncoder::newASCII85Encode (*op, or_->cacheHints.TransferCPL);
+ else if (cache->TransferEncoding==cache->TE_Hex) tp=PSEncoder::newASCIIHexEncode(*op, or_->cacheHints.TransferCPL);
+ // else strings[2]=" F closefile";
+ Rule::writeTTT(*op, *tp, *tp, !cache->isPDF()?"l2jbin":cache->isPDFB()?"p0jbb":"p0jbin", or_, sf, Rule::writePalData, strings);
+ if (tp!=op) delete tp;
+ /* Dat: outve is deleted by C++ scope */
+ // if (tp!=op) delete tp; /* BUGFIX at Thu Jan 20 15:04:47 CET 2005 */
+ return Rule::Applier::OK;
+}
+
+Rule::Applier out_l2jbin_applier = { "PSL2+PDF-JAI", out_l2jbin_check_rule, out_l2jbin_work, 0 };
+
+/* --- */
+
+#if 0 /* integrated to _l2jbin_ at Sun Sep 22 14:29:13 CEST 2002 */
+//static char *p0jbin_ttm=
+//#include "p0jbin.tth"
+
+/** PostScript Level2 DCTEncode (Baseline JPEG), Binary */
+Rule::Applier::cons_t out_p0jbin_check_rule(Rule::OutputRule* or_) {
+ Rule::Cache *cache=&or_->cache;
+ if (!cache->isPDF()
+ || cache->Compression!=Rule::Cache::CO_JAI
+ ) return Rule::Applier::DONT_KNOW;
+ /* Dat: not unrequired anymore: cache->TransferEncoding!=cache->TE_Binary */
+ bool badp=false;
+ if (cache->SampleFormat!=Image::SF_Asis) {
+ Error::sev(Error::WARNING_DEFER) << "check_rule: /FileFormat/PDF* /Compression/JAI requires /SampleFormat/Asis" << (Error*)0;
+ badp=true;
+ }
+ if (cache->hasPredictor()) {
+ Error::sev(Error::WARNING_DEFER) << "check_rule: /FileFormat/PDF* /Compression/JAI requires /Predictor 1" << (Error*)0;
+ badp=true;
+ }
+ if (badp) return Rule::Applier::BAD;
+ return Rule::Applier::OK;
+}
+Rule::Applier::cons_t out_p0jbin_work(GenBuffer::Writable& out, Rule::OutputRule*or_, Image::SampledInfo *sf) {
+ char *strings[]={ "0"/*PDF-1.`0'*/, ""/*colorSpace*/ };
+ // " F closefile"/*closes*/ };
+ if (out_p0jbin_check_rule(or_)!=Rule::Applier::OK) return Rule::Applier::DONT_KNOW;
+ assert(sf->getImg()->getBpc()==8);
+ or_->doSampleFormat(sf);
+ Rule::Cache *cache=&or_->cache;
+
+ Filter::VerbatimE outve(out); /* required since template /p0jbin is TTM */
+ GenBuffer::Writable *tp=&outve;
+ if (cache->TransferEncoding==cache->TE_A85) tp=PSEncoder::newASCII85Encode (outve, or_->cacheHints.TransferCPL);
+ else if (cache->TransferEncoding==cache->TE_Hex) tp=PSEncoder::newASCIIHexEncode(outve, or_->cacheHints.TransferCPL);
+ else strings[2]="";
+
+#if 0 /* old */
+ MiniPS::VALUE ttm;
+ { Filter::FlatR flatD(p0jbin_ttm);
+ MiniPS::Parser p(&flatD);
+ ttm=p.parse1();
+ if (p.parse1(p.EOF_ALLOWED)!=MiniPS::Qundef || MiniPS::getType(ttm)!=MiniPS::T_ARRAY)
+ Error::sev(Error::EERROR) << "TTM: the TTM file should contain a single array" << (Error*)0;
+ /* ^^^ Dat: the result of the second p.parse1() doesn't get delete0(...)d */
+ }
+ Filter::VerbatimE outve(out);
+ Rule::writeTTM(outve, outve, outve, MiniPS::RARRAY(ttm), or_, sf, Rule::writePalData, strings);
+ MiniPS::delete0(ttm);
+#else /* new */
+ Rule::writeTTT(outve, *tp, *tp, cache->isPDFB()?"p0jbb":"p0jbin", or_, sf, Rule::writePalData, strings);
+#endif
+ if (tp!=&outve)delete tp;
+ return Rule::Applier::OK;
+}
+
+Rule::Applier out_p0jbin_applier = { "PDF-JAI", out_p0jbin_check_rule, out_p0jbin_work, 0 };
+#endif
+
+/* --- Fri Mar 22 11:52:53 CET 2002 */
+/* PDF added at Sat Apr 20 20:07:34 CEST 2002 */
+/* Integrated l23ind1 at Sat Apr 20 20:24:21 CEST 2002 */
+
+//static char *l23_tte=
+//#include "l23.tth"
+
+/** PostScript Level2 and PDF generic non-transparent */
+Rule::Applier::cons_t out_l23_check_rule(Rule::OutputRule* or_) {
+ Rule::Cache *cache=&or_->cache;
+ unsigned char sf=cache->SampleFormat;
+ if (cache->hasPredictor() && cache->Compression!=Rule::Cache::CO_ZIP && cache->Compression!=Rule::Cache::CO_LZW) {
+ Error::sev(Error::WARNING_DEFER) << "check_rule: real /Predictor requires /ZIP or /LZW" << (Error*)0;
+ return Rule::Applier::BAD;
+ }
+
+ // assert(cache->isPSL2() && (sf==Image::SF_Transparent2 || sf==Image::SF_Transparent4 || sf==Image::SF_Transparent8));
+
+ if ((!cache->isPSL2() && !cache->isPDF())
+ || (sf!=Image::SF_Gray1 && sf!=Image::SF_Gray2 && sf!=Image::SF_Gray4 && sf!=Image::SF_Gray8
+ && sf!=Image::SF_Indexed1 && sf!=Image::SF_Indexed2 && sf!=Image::SF_Indexed4 && sf!=Image::SF_Indexed8
+ && sf!=Image::SF_Rgb1 && sf!=Image::SF_Rgb2 && sf!=Image::SF_Rgb4 && sf!=Image::SF_Rgb8
+ && sf!=Image::SF_Transparent2 && sf!=Image::SF_Transparent4 && sf!=Image::SF_Transparent8
+ && sf!=Image::SF_Mask)
+ || cache->TransferEncoding==cache->TE_ASCII
+ || !cache->isZIPOK()
+ ) return Rule::Applier::DONT_KNOW;
+ #if !HAVE_LZW
+ if (cache->Compression==Rule::Cache::CO_LZW) return Rule::Applier::DONT_KNOW;
+ #endif
+
+ // if (cache->isDCTE() && !cache->isRGB() && !cache->isGray()) {
+ bool badp=false;
+ if (cache->isDCTE() && cache->SampleFormat!=Image::SF_Rgb8 && cache->SampleFormat!=Image::SF_Gray8 && cache->SampleFormat!=Image::SF_Indexed8) {
+ Error::sev(Error::WARNING_DEFER) << "check_rule: /DCTEncode requires /Rgb8 or /Gray8 (or /Indexed8)" << (Error*)0;
+ badp=true;
+ }
+ if (sf==Image::SF_Transparent2 || sf==Image::SF_Transparent4 || sf==Image::SF_Transparent8) {
+ if (cache->isPDF()) {
+ Error::sev(Error::WARNING_DEFER) << "check_rule: unsupported /Transparent+ for /PDF*" << (Error*)0;
+ badp=true;
+ } else assert(cache->isPSL2());
+ }
+ return (Rule::Applier::cons_t)(badp ? 0+Rule::Applier::BAD : 0+Rule::Applier::OK);
+}
+Rule::Applier::cons_t out_l23_work(GenBuffer::Writable& out, Rule::OutputRule*or_, Image::SampledInfo *sf) {
+ Rule::stream_writer_t writeXData=Rule::writePalData;
+ char LanguageLevel[2]="2", closes[30];
+ SimBuffer::B colorSpace;
+ char const*strings[]={ LanguageLevel, (char*)NULLP /*colorSpace*/, closes };
+ Rule::Cache *cache=&or_->cache;
+ // assert(0);
+ if (out_l23_check_rule(or_)!=Rule::Applier::OK) return Rule::Applier::DONT_KNOW;
+ or_->doSampleFormat(sf, true);
+ if (cache->Compression==Rule::Cache::CO_ZIP) {
+ if (!cache->isPDF()) LanguageLevel[0]='3';
+ } else if (cache->isPDF()) LanguageLevel[0]='0';
+ if (cache->isIndexed() || cache->isTransparentM()) {
+ unsigned ncols=PTS_dynamic_cast(Image::Indexed*,sf->getImg())->getNcols();
+ colorSpace << "[/Indexed/DeviceRGB " << ncols-1;
+ if (ncols==0) { /* Avoid writing zero bytes to the filters */
+ /* Imp: verify this in Acrobat Reader */
+ colorSpace << "()]";
+ } else if (!cache->isPDF()) { /* Insert an in-line hexdump. No better way :-( */
+ /*sprintf(colorSpace, "[/Indexed/DeviceRGB %u T %u string readstring pop]", ncols-1, ncols*3); */
+ colorSpace << " T " << ncols*3 << " string readstring pop]";
+ } else { /* Insert an in-line hexdump. No shorter way for PDF */
+#if 0
+ colorSpace="/DeviceGray ";
+#else
+ /* SUXX: gs5.50 & PDF & /Indexed doesn't work */
+ colorSpace << "\n<";
+ GenBuffer::Writable *hp=PSEncoder::newASCIIHexEncode(colorSpace, or_->cacheHints.TransferCPL);
+ hp->vi_write(sf->getImg()->getHeadp(), ncols*3);
+ hp->vi_write(0,0);
+ colorSpace << ']'; /* Dat: '>' is appended by ASCIIHexEncode */
+#endif
+ writeXData=Rule::writeData; /* The palette has already been written. */
+ }
+ } else if (cache->isGray()) colorSpace="/DeviceGray ";
+ else { assert(cache->isRGB()); colorSpace="/DeviceRGB "; }
+ if (cache->SampleFormat==Image::SF_Mask || cache->SampleFormat==Image::SF_Indexed1) writeXData=Rule::writeData;
+
+ GenBuffer::Writable *vp=&out;
+ if (cache->isPDF()) vp=new Filter::VerbatimE(out); /* required since template /p02* is TTM */
+
+ GenBuffer::Writable *tp=vp;
+ if (cache->TransferEncoding==cache->TE_A85) tp=PSEncoder::newASCII85Encode (*vp, or_->cacheHints.TransferCPL);
+ else if (cache->TransferEncoding==cache->TE_Hex) tp=PSEncoder::newASCIIHexEncode(*vp, or_->cacheHints.TransferCPL);
+
+ GenBuffer::Writable *cp=tp;
+ switch (cache->Compression) {
+ case Rule::Cache::CO_None: break;
+ case Rule::Cache::CO_ZIP: cp=PSEncoder::newFlateEncode(*tp, or_->cacheHints.Effort); break;
+ case Rule::Cache::CO_LZW: cp=PSEncoder::newLZWEncode(*tp); break;
+ case Rule::Cache::CO_RLE: cp=PSEncoder::newRunLengthEncode(*tp, or_->cacheHints.RecordSize); break;
+ case Rule::Cache::CO_Fax: cp=PSEncoder::newCCITTFaxEncode(*tp, or_->cacheHints.K, or_->cacheHints.EncoderBPL, /*EndOfLine:*/ or_->cacheHints.K>0); break;
+ /* ^^^ getBpp() BUGFIX at Wed Jul 3 20:00:30 CEST 2002 */
+ /* ^^^ EndOfLine BUGFIX at Wed Jul 3 21:12:54 CEST 2002
+ * With EndOfLine==false, `sam2p -c:fax:1', acroread triggers the bug.
+ * With EndOfLine==false, `sam2p -c:fax:2', acroread and gs trigger the bug.
+ */
+
+ case Rule::Cache::CO_IJG: cp=PSEncoder::newDCTIJGEncode(*tp, or_->cacheHints.EncoderColumns, or_->cacheHints.EncoderRows, or_->cacheHints.EncoderColors, or_->cacheHints.Quality); break;
+ case Rule::Cache::CO_DCT: { SimBuffer::B other_parameters;
+ or_->cacheHints.DCT->dump(other_parameters, 0, false);
+ cp=PSEncoder::newDCTEncode(*tp, or_->cacheHints.EncoderColumns, or_->cacheHints.EncoderRows, or_->cacheHints.EncoderColors, or_->cacheHints.ColorTransform, other_parameters);
+ break; }
+ default: assert(0);
+ }
+
+ GenBuffer::Writable *pp=cp;
+ if (cache->hasPredictor()) pp=PSEncoder::newPredictor(*cp, cache->Predictor, or_->cacheHints.PredictorBPC, or_->cacheHints.PredictorColumns, or_->cacheHints.PredictorColors);
+
+ #if 0 /* Sun Sep 22 20:40:51 CEST 2002 */
+ if (cp!=tp) strcpy(closes," F closefile"); else closes[0]='\0';
+ if (tp!=vp) strcpy(closes+strlen(closes)," T closefile");
+ #endif
+
+ strings[1]=colorSpace.term0()();
+ Rule::writeTTT(*vp, *tp, *pp,
+ !cache->isPDF() ? (
+ cache->SampleFormat==Image::SF_Indexed1 ? "l23ind1" :
+ cache->SampleFormat==Image::SF_Mask ? "l23mask" :
+ cache->isTransparentM() ? "l23tran2" :
+ "l23"
+ ) : cache->isPDFB() ? (
+ cache->SampleFormat==Image::SF_Indexed1 ? "p02ind1bb" :
+ cache->SampleFormat==Image::SF_Mask ? "p02maskbb" :
+ "p02bb"
+ ) : (
+ cache->SampleFormat==Image::SF_Indexed1 ? "p02ind1" :
+ cache->SampleFormat==Image::SF_Mask ? "p02mask" :
+ "p02"
+ ), or_, sf, writeXData, strings);
+ if (pp!=cp) delete pp;
+ if (cp!=tp) delete cp;
+ if (tp!=vp) delete tp;
+ if (vp!=&out)delete vp;
+ return Rule::Applier::OK;
+}
+
+Rule::Applier out_l23_applier = { "PSL23+PDF", out_l23_check_rule, out_l23_work, 0 };
+
+/* --- Fri Mar 22 17:22:40 CET 2002 -- Sat Jun 15 16:03:06 CEST 2002 */
+
+/* integrated l1tr at Sat Jun 15 16:03:03 CEST 2002 */
+/* added /Bbox at Sat Jun 15 16:03:31 CEST 2002 */
+
+//static char *l1tr_tte=
+//#include "l1tr.tth"
+
+/** PostScript Level1 or PDF Fully transparent image */
+Rule::Applier::cons_t out_l1tr_check_rule(Rule::OutputRule* or_) {
+ Rule::Cache *cache=&or_->cache;
+ if (!(cache->isPS() || cache->isPDF())
+ || (cache->SampleFormat!=Image::SF_Transparent && cache->SampleFormat!=Image::SF_Bbox && cache->SampleFormat!=Image::SF_Opaque)
+ ) return Rule::Applier::DONT_KNOW;
+ return Rule::Applier::OK;
+}
+Rule::Applier::cons_t out_l1tr_work(GenBuffer::Writable& out, Rule::OutputRule*or_, Image::SampledInfo *sf) {
+ char t[]="....";
+ if (out_l1tr_check_rule(or_)!=Rule::Applier::OK) return Rule::Applier::DONT_KNOW;
+ or_->doSampleFormat(sf);
+ Rule::Cache *cache=&or_->cache;
+ Filter::VerbatimE outve(out); /* required since template /p0* is TTM */
+ if (cache->isPS()) { t[0]='l'; t[1]='1'; }
+ else { t[0]='p'; t[1]='0'; }
+ switch (cache->SampleFormat) {
+ case Image::SF_Transparent: t[2]='t'; t[3]='r'; break;
+ case Image::SF_Opaque: t[2]='o'; t[3]='p'; break;
+ case Image::SF_Bbox: t[2]='b'; t[3]='b'; break;
+ default: assert(0);
+ }
+ Rule::writeTTT(outve, outve, outve, t, or_, sf, 0/*NULLP*/);
+ return Rule::Applier::OK;
+}
+
+Rule::Applier out_l1tr_applier = { "P-TrOpBb", out_l1tr_check_rule, out_l1tr_work, 0 };
+
+/* --- */
+
+/* --- l23mask Fri Mar 22 18:11:12 CET 2002
+ * --- l23ind1 Fri Mar 22 18:11:12 CET 2002
+ * removed (integrated to l23) at Sat Apr 20 20:25:57 CEST 2002
+ */
+
+/* --- l1mask Fri Mar 22 18:33:01 CET 2002
+ * --- l1mashex Sun Apr 14 15:25:25 CEST 2002
+ * --- l1in1 Fri Mar 22 18:33:37 CET 2002
+ * --- l1in1hex Fri Mar 22 18:33:37 CET 2002
+ * removed (integrated to l1c) at Sat Apr 20 20:25:57 CEST 2002
+ * --- lcr Sat Jun 1 17:09:57 CEST 2002
+ * removed (integrated to l1c) at Sun Jun 2 16:48:31 CEST 2002
+ * --- l1gbh
+ * removed (integrated to l1c) at Sun Jun 2 16:48:31 CEST 2002
+ * --- l1fa85g.tte: PostScript Level1 FlateEncode, A85, without Predictor
+ * removed (integrated to l1c) at Sun Sep 22 00:48:21 CEST 2002
+ */
+
+/* --- Sun Jun 2 16:48:44 CEST 2002 */
+
+//static char *l1mask_tte=
+//#include "l1mask.tth"
+
+static void gen_tkey(char *tkey, GenBuffer::Writable& out, GenBuffer::Writable*&tp, GenBuffer::Writable*& cp, Rule::OutputRule*or_) {
+ Rule::Cache *cache=&or_->cache;
+ tp=&out;
+ if (cache->TransferEncoding==cache->TE_A85) { tkey[3]='8'; tp=PSEncoder::newASCII85Encode (out, or_->cacheHints.TransferCPL); }
+ else if (cache->TransferEncoding==cache->TE_Hex) { tkey[3]='h'; tp=PSEncoder::newASCIIHexEncode(out, or_->cacheHints.TransferCPL); }
+ else tkey[3]='b';
+ cp=tp;
+ if (cache->Compression==Rule::Cache::CO_RLE) { tkey[4]='r'; cp=PSEncoder::newRunLengthEncode(*tp, or_->cacheHints.RecordSize); }
+ else if (cache->Compression==Rule::Cache::CO_ZIP) { tkey[4]='z'; cp=PSEncoder::newFlateEncode(*tp, or_->cacheHints.Effort); }
+ else if (cache->Compression==Rule::Cache::CO_LZW) { tkey[4]='l'; cp=PSEncoder::newLZWEncode(*tp); }
+ else tkey[4]='n';
+ /* vvv removed 'm' and '1' at Sun Sep 22 17:53:08 CEST 2002 */
+ tkey[2]=// cache->SampleFormat==Image::SF_Mask ? 'm' :
+ // cache->SampleFormat==Image::SF_Indexed1 ? '1' :
+ cache->SampleFormat==Image::SF_Indexed2 ? '2' :
+ cache->SampleFormat==Image::SF_Indexed4 ? '4' :
+ cache->SampleFormat==Image::SF_Indexed8 ? '8' :
+ cache->SampleFormat==Image::SF_Transparent2 ? 't' :
+ cache->SampleFormat==Image::SF_Transparent4 ? 't' :
+ cache->SampleFormat==Image::SF_Transparent8 ? 't' :
+ 'g'; /* /Gray*, /Rgb*, /Mask, /Indexed1 */
+}
+
+/** PostScript Level1 uncompressed binary or hex */
+Rule::Applier::cons_t out_l1c_check_rule(Rule::OutputRule* or_) {
+ Rule::Cache *cache=&or_->cache;
+ if ((cache->FileFormat!=cache->FF_PSL1 && cache->FileFormat!=cache->FF_PSLC && cache->FileFormat!=cache->FF_PSL2)
+ || (cache->FileFormat==cache->FF_PSL2 && cache->Compression!=Rule::Cache::CO_ZIP)
+ || (cache->TransferEncoding!=cache->TE_Binary && cache->TransferEncoding!=cache->TE_Hex && cache->TransferEncoding!=cache->TE_A85)
+ || (cache->Compression!=Rule::Cache::CO_None && cache->Compression!=Rule::Cache::CO_RLE && cache->Compression!=Rule::Cache::CO_ZIP && cache->Compression!=Rule::Cache::CO_LZW)
+ || cache->hasPredictor()
+ || !(cache->isTransparentM() || cache->isIndexed() || cache->isGray() || cache->isRGB())
+ ) return Rule::Applier::DONT_KNOW;
+ bool badp=false;
+ if (cache->FileFormat==cache->FF_PSL1 && cache->SampleFormat!=Image::SF_Indexed1 && cache->isIndexed()) {
+ Error::sev(Error::WARNING_DEFER) << "check_rule: /SampleFormat/Indexed+ doesn't work with /FileFormat/PSL1 (use /PSLC or /PSL2)" << (Error*)0;
+ badp=true;
+ }
+ if (cache->FileFormat==cache->FF_PSL1 && cache->isRGB()) {
+ Error::sev(Error::WARNING_DEFER) << "check_rule: /SampleFormat/RGB* doesn't work with /FileFormat/PSL1 (use /PSLC or /PSL2)" << (Error*)0;
+ badp=true;
+ }
+ char tkey[]="l1..."; /* /l1{2,4,8,t}{8,h}{r,z,l} */
+ GenBuffer::Writable *tp0,*cp0,*out=(GenBuffer::Writable*)NULLP;
+ gen_tkey(tkey, *out, tp0, cp0, or_);
+ /* fprintf(stderr,"tkey=%s\n", tkey); */
+ if (!badp && Rule::Templates->get(tkey, strlen(tkey))==MiniPS::Qundef) return Rule::Applier::DONT_KNOW;
+ return (Rule::Applier::cons_t)(badp ? 0+Rule::Applier::BAD : 0+Rule::Applier::OK);
+ /* ^^^ Dat: 0+: pacify gcc-3.1 */
+}
+Rule::Applier::cons_t out_l1c_work(GenBuffer::Writable& out, Rule::OutputRule*or_, Image::SampledInfo *sf) {
+ if (out_l1c_check_rule(or_)!=Rule::Applier::OK) return Rule::Applier::DONT_KNOW;
+ /* Dat: only these have been defined so far: grep '^/l1[248tg][8h][rzl]' bts2.ttt
+ * /l1thr /l1g8r /l1ghr /l128r /l12hr /l148r /l14hr /l188r /l18hr /l1g8z /l1ghz /l1g8l /l1ghl
+ */
+ or_->doSampleFormat(sf, true); /* Dat: `true': because of /Transparent+ */
+ char tkey[]="l1..."; /* /l1{2,4,8,t}{8,h}{r,z,l} */
+ GenBuffer::Writable *tp, *cp;
+ gen_tkey(tkey, out, tp, cp, or_);
+ // fprintf(stderr, "tkey=(%s)\n", tkey);
+ Rule::writeTTT(out, *tp, *cp, tkey, or_, sf,
+ tkey[2]=='2' || tkey[2]=='4' || tkey[2]=='8' || tkey[2]=='t' ? Rule::writePalData : Rule::writeData
+ );
+ // Rule::writeTTT(out, *tp, *cp, tkey, or_, sf, Rule::writePalData);
+ if (cp!=tp) delete cp;
+ if (tp!=&out)delete tp;
+ return Rule::Applier::OK;
+}
+
+Rule::Applier out_l1c_applier = { "PSL1C", out_l1c_check_rule, out_l1c_work, 0 };
+
+/* lcrbin (lcrb) --- Sun Apr 14 16:50:14 CEST 2002
+ * lcrhex (lcr8, lcrh) --- Sun Apr 14 16:50:22 CEST 2002
+ * removed (integrated to _l1c_) at Sat Jun 1 17:09:52 CEST 2002
+ */
+
+#if 0
+/* --- Sat Jun 1 17:09:57 CEST 2002 */
+
+//static char *lcrbin_tte=
+//#include "lcrbin.tth"
+
+/** PostScript Level1+C uncompressed RGB image */
+Rule::Applier::cons_t out_lcr_check_rule(Rule::OutputRule* or_) {
+ Rule::Cache *cache=&or_->cache;
+ if (!cache->isPS()
+ || cache->FileFormat==cache->FF_PSL1
+ || (cache->TransferEncoding!=cache->TE_Binary && cache->TransferEncoding!=cache->TE_Hex && cache->TransferEncoding!=cache->TE_A85)
+ || cache->Compression!=Rule::Cache::CO_None
+ || cache->hasPredictor()
+ || !cache->isRGB()
+ ) return Rule::Applier::DONT_KNOW;
+ return Rule::Applier::OK;
+}
+Rule::Applier::cons_t out_lcr_work(GenBuffer::Writable& out, Rule::OutputRule*or_, Image::SampledInfo *sf) {
+ Rule::Cache *cache=&or_->cache;
+ if (out_lcr_check_rule(or_)!=Rule::Applier::OK) return Rule::Applier::DONT_KNOW;
+ or_->doSampleFormat(sf);
+ char tkey[]="lcr.";
+ GenBuffer::Writable *tp=&out;
+ if (cache->TransferEncoding==cache->TE_A85) { tkey[3]='8'; tp=PSEncoder::newASCII85Encode (out, or_->cacheHints.TransferCPL); }
+ else if (cache->TransferEncoding==cache->TE_Hex) { tkey[3]='h'; tp=PSEncoder::newASCIIHexEncode(out, or_->cacheHints.TransferCPL); }
+ else tkey[3]='b';
+ Rule::writeTTT(out, *tp, *tp, tkey, or_, sf, Rule::writeData);
+ if (tp!=&out)delete tp;
+ return Rule::Applier::OK;
+}
+
+Rule::Applier out_lcr_applier = { "PSLC-RGB", out_lcr_check_rule, out_lcr_work, 0 };
+#endif
+
+/* --- Sat Mar 23 12:37:04 CET 2002; Tue Jul 2 10:23:44 CEST 2002 */
+
+Rule::Applier::cons_t out_gif89a_check_rule(Rule::OutputRule* or_) {
+ Rule::Cache *cache=&or_->cache;
+ bool badp=false;
+ if (cache->FileFormat!=cache->FF_GIF89a
+ ) return Rule::Applier::DONT_KNOW;
+ if (!cache->isIndexed() && !cache->isTransparentM()) {
+ Error::sev(Error::WARNING_DEFER) << "check_rule: /GIF89a must be /Indexed*, /Mask or /Transparent+" << (Error*)0;
+ badp=true;
+ }
+ if (cache->TransferEncoding!=cache->TE_Binary) {
+ Error::sev(Error::WARNING_DEFER) << "check_rule: /GIF89a requires /Binary" << (Error*)0;
+ badp=true;
+ }
+ if (cache->Compression!=Rule::Cache::CO_None && cache->Compression!=Rule::Cache::CO_LZW) {
+ Error::sev(Error::WARNING_DEFER) << "check_rule: /GIF89a requires /LZW" << (Error*)0;
+ badp=true;
+ }
+ if (cache->hasPredictor()) {
+ Error::sev(Error::WARNING_DEFER) << "check_rule: /GIF89a requires /Predictor 1" << (Error*)0;
+ badp=true;
+ }
+ #if !USE_OUT_GIF
+ Error::sev(Error::WARNING_DEFER) << "check_rule: please `configure --enable-gif' for /GIF89a" << (Error*)0;
+ badp=true;
+ #endif
+ if (badp) return Rule::Applier::BAD;
+ or_->cache.WarningOK=true;
+ return Rule::Applier::OK;
+}
+#if USE_OUT_GIF
+ #if OBJDEP
+ # warning REQUIRES: out_gif.o
+ #endif
+ extern void out_gif_write(GenBuffer::Writable& out, Image::Indexed *img); /* out_gif.cpp */
+ Rule::Applier::cons_t out_gif89a_work(GenBuffer::Writable& out, Rule::OutputRule*or_, Image::SampledInfo *sf) {
+ if (out_gif89a_check_rule(or_)!=Rule::Applier::OK) return Rule::Applier::DONT_KNOW;
+ or_->cache.SampleFormat=(Image::sf_t)(or_->cache.isIndexed()? 0+Image::SF_Indexed8: 0+Image::SF_Transparent8);
+ /* ^^^ Dat: 0+: pacify gcc-3.1; (Image::sf_t): pacify VC6.0 */
+ or_->doSampleFormat(sf);
+ out_gif_write(out, PTS_dynamic_cast(Image::Indexed*,sf->getImg()));
+ return Rule::Applier::OK;
+ }
+#else
+/*# define out_gif89a_check_rule (Rule::Applier::check_rule_t)NULLP*/
+# define out_gif89a_work (Rule::Applier::work_t)0
+#endif
+
+Rule::Applier out_gif89a_applier = {
+#if HAVE_LZW
+ "GIF89a+LZW"
+#else
+ "GIF89a"
+#endif
+ , out_gif89a_check_rule, out_gif89a_work, 0 };
+
+/* --- Tue Jun 4 19:51:03 CEST 2002 */
+
+Rule::Applier::cons_t out_xpm_check_rule(Rule::OutputRule* or_) {
+ Rule::Cache *cache=&or_->cache;
+ bool badp=false;
+ if (cache->FileFormat!=cache->FF_XPM
+ ) return Rule::Applier::DONT_KNOW;
+ if (!cache->isIndexed() && !cache->isTransparentM()) {
+ Error::sev(Error::WARNING_DEFER) << "check_rule: /XPM must be /Indexed*, /Mask or /Transparent+" << (Error*)0;
+ badp=true;
+ }
+ if (cache->TransferEncoding!=cache->TE_ASCII && cache->TransferEncoding!=cache->TE_Binary) {
+ /* ^^^ && BUGFIX at Thu Jul 11 21:57:09 CEST 2002 */
+ Error::sev(Error::WARNING_DEFER) << "check_rule: /XPM requires /TransferEncoding/ASCII" << (Error*)0;
+ badp=true;
+ }
+ if (cache->Compression!=Rule::Cache::CO_None) {
+ Error::sev(Error::WARNING_DEFER) << "check_rule: /XPM requires /Compression/None" << (Error*)0;
+ badp=true;
+ }
+ if (cache->hasPredictor()) {
+ Error::sev(Error::WARNING_DEFER) << "check_rule: /XPM requires /Predictor 1" << (Error*)0;
+ badp=true;
+ }
+ if (badp) return Rule::Applier::BAD;
+ or_->cache.WarningOK=true;
+ return Rule::Applier::OK;
+}
+Rule::Applier::cons_t out_xpm_work(GenBuffer::Writable& out, Rule::OutputRule*or_, Image::SampledInfo *sf) {
+ if (out_xpm_check_rule(or_)!=Rule::Applier::OK) return Rule::Applier::DONT_KNOW;
+ or_->cache.SampleFormat=(Image::sf_t)(or_->cache.isIndexed()? 0+Image::SF_Indexed8: 0+Image::SF_Transparent8);
+ /* ^^^ force 8-bit; may trigger warnings... */
+ /* ^^^ Dat: 0+: pacify gcc-3.1 */
+ or_->doSampleFormat(sf);
+ Image::Indexed *iimg=PTS_dynamic_cast(Image::Indexed*,sf->getImg());
+ /* vvv 93 useful ASCII chars (+ '\0'), missing: " and \ ; plus a hextable */
+ static char const xpmc=93;
+ static char const xpms[xpmc+1]="0123456789abcdef !#$%&'()*+,-./:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[]^_`ghijklmnopqrstuvwxyz{|}~";
+
+ Image::Sampled::dimen_t wd=iimg->getWd(), htc=iimg->getHt();
+ bool pal2ch=iimg->getNcols()>xpmc;
+ // pal2ch=true;
+ out << "/* XPM */\nstatic char *sam2p_xpm[] = {\n"
+ "/* columns rows colors chars-per-pixel */\n\""
+ << wd << ' ' << htc << ' ' << iimg->getNcols()
+ << ' ' << (pal2ch?2:1) << "\",\n";
+ char const *p=iimg->getHeadp(), *pend=iimg->getRowbeg(), *phend;
+ char coline3[]="\".. c #ABCDEF\",\n";
+ char cotran3[]="\".. c None s None \",\n";
+ assert((pend-p)%3==0);
+ unsigned i=0;
+ bool transp=false;
+ if (iimg->getTransp()>=0) { pend-=3; assert((iimg->getTransp())*3+p==pend); transp=true; }
+ if (pal2ch) {
+ while (p!=pend) {
+ coline3[ 1]=xpms[i>>2];
+ coline3[ 2]=xpms[i++&3];
+ coline3[ 7]=xpms[*(unsigned char const*)p>>4];
+ coline3[ 8]=xpms[*(unsigned char const*)p++&15];
+ coline3[ 9]=xpms[*(unsigned char const*)p>>4];
+ coline3[10]=xpms[*(unsigned char const*)p++&15];
+ coline3[11]=xpms[*(unsigned char const*)p>>4];
+ coline3[12]=xpms[*(unsigned char const*)p++&15];
+ out << coline3;
+ }
+ if (transp) {
+ cotran3[ 1]=xpms[i>>2];
+ cotran3[ 2]=xpms[i++&3];
+ out << cotran3;
+ p+=3;
+ }
+ pend=iimg->getRowbeg()+wd*htc;
+ out << "/* Pixels */\n";
+ char *obuf=new char[4+2*wd], *op;
+ obuf[0]='"';
+ obuf[2*wd+1]='"';
+ obuf[2*wd+2]=','; /* Dat: it's OK to have a comma in the last line */
+ obuf[2*wd+3]='\n';
+ while (htc--!=0) {
+ phend=p+wd;
+ op=obuf;
+ while (p!=phend) { *++op=xpms[*p>>2]; *++op=xpms[*p++&3]; }
+ out.vi_write(obuf, 2*wd+4);
+ }
+ delete [] obuf;
+ } else {
+ coline3[1]='"';
+ while (p!=pend) {
+ coline3[ 2]=xpms[i++];
+ coline3[ 7]=xpms[*(unsigned char const*)p>>4];
+ coline3[ 8]=xpms[*(unsigned char const*)p++&15];
+ coline3[ 9]=xpms[*(unsigned char const*)p>>4];
+ coline3[10]=xpms[*(unsigned char const*)p++&15];
+ coline3[11]=xpms[*(unsigned char const*)p>>4];
+ coline3[12]=xpms[*(unsigned char const*)p++&15];
+ out << (coline3+1);
+ }
+ if (transp) {
+ cotran3[1]='"';
+ cotran3[ 2]=xpms[i];
+ out << (cotran3+1);
+ p+=3;
+ }
+ pend=iimg->getRowbeg()+wd*htc;
+ out << "/* Pixels */\n";
+ char *obuf=new char[4+wd], *op;
+ obuf[0]='"';
+ obuf[wd+1]='"';
+ obuf[wd+2]=','; /* Dat: it's OK to have a comma in the last line */
+ obuf[wd+3]='\n';
+ while (htc--!=0) {
+ phend=p+wd;
+ op=obuf;
+ while (p!=phend) *++op=xpms[0U+*p++];
+ out.vi_write(obuf, wd+4);
+ }
+ delete [] obuf;
+ }
+ assert(p==pend);
+ out << "};\n";
+ return Rule::Applier::OK;
+}
+
+Rule::Applier out_xpm_applier = { "XPM", out_xpm_check_rule, out_xpm_work, 0 };
+
+/* --- Sat Mar 23 13:18:07 CET 2002 */
+
+Rule::Applier::cons_t out_pnm_check_rule(Rule::OutputRule* or_) {
+ Rule::Cache *cache=&or_->cache;
+ if (cache->FileFormat!=cache->FF_PNM
+ ) return Rule::Applier::DONT_KNOW;
+ bool badp=false;
+ // if (cache->SampleFormat!=Image::SF_Rgb8 && cache->SampleFormat!=Image::SF_Gray8 && cache->SampleFormat!=Image::SF_Gray1) {
+ if (!cache->isGray() && !cache->isRGB() && !cache->isIndexed() && !cache->isTransparentM()) {
+ Error::sev(Error::WARNING_DEFER) << "check_rule: /PNM must be /Rgb8, /Gray8 or /Gray1" << (Error*)0;
+ badp=true;
+ }
+ if (cache->TransferEncoding!=cache->TE_Binary && cache->TransferEncoding!=cache->TE_ASCII) {
+ Error::sev(Error::WARNING_DEFER) << "check_rule: /PNM requires /Binary or /ASCII" << (Error*)0;
+ badp=true;
+ }
+ if (cache->Compression!=Rule::Cache::CO_None) {
+ Error::sev(Error::WARNING_DEFER) << "check_rule: /PNM requires /Compression/None" << (Error*)0;
+ badp=true;
+ }
+ if (cache->hasPredictor()) {
+ Error::sev(Error::WARNING_DEFER) << "check_rule: /PNM requires /Predictor 1" << (Error*)0;
+ badp=true;
+ }
+ if (badp) return Rule::Applier::BAD;
+ or_->cache.WarningOK=true;
+ return Rule::Applier::OK;
+}
+Rule::Applier::cons_t out_pnm_work(GenBuffer::Writable& out, Rule::OutputRule*or_, Image::SampledInfo *sf) {
+ /*static*/ char head[]={ 'P', 0, '\n', '#', ' ', 'b', 'y', ' ' };
+ /*static*/ char tmp[72];
+ Image::sf_t sfo=or_->cache.SampleFormat;
+ Image::Indexed *alphaChannel=(Image::Indexed*)NULLP;
+ if (out_pnm_check_rule(or_)!=Rule::Applier::OK) return Rule::Applier::DONT_KNOW;
+ if (or_->cache.SampleFormat==Image::SF_Gray1 || or_->cache.SampleFormat==Image::SF_Gray8) {
+ if (or_->cache.TransferEncoding==or_->cache.TE_ASCII) or_->cache.SampleFormat=Image::SF_Gray8;
+ } else if (or_->cache.SampleFormat==Image::SF_Gray2 || or_->cache.SampleFormat==Image::SF_Gray4) {
+ or_->cache.SampleFormat=Image::SF_Gray8;
+ } else if (or_->cache.isRGB()) {
+ or_->cache.SampleFormat=Image::SF_Rgb8;
+ } else {
+ assert(or_->cache.isIndexed() || or_->cache.isTransparentM());
+ if (or_->cache.isTransparentM()) {
+ alphaChannel=PTS_dynamic_cast(Image::Indexed*,sf->getImg())->calcAlpha();
+ sf->clearTransp(); /* BUGFIX at Tue Sep 17 10:05:47 CEST 2002 */
+ }
+ or_->cache.SampleFormat=(Image::sf_t)(
+ !sf->canGrayy() ? 0+Image::SF_Rgb8
+ : sf->minRGBBpcc()==1 ? 0+Image::SF_Gray1 : 0+Image::SF_Gray8);
+ /* ^^^ Dat: 0+: pacify gcc-3.1 */
+ }
+ if (or_->cache.SampleFormat==Image::SF_Gray1 && or_->cache.TransferEncoding==or_->cache.TE_ASCII)
+ or_->cache.SampleFormat=Image::SF_Gray8;
+ or_->doSampleFormat(sf);
+ sfo=or_->cache.SampleFormat;
+ head[1]=(sfo==Image::SF_Rgb8 ? '3' : sfo==Image::SF_Gray8 ? '2' : '1')
+ +(or_->cache.TransferEncoding==or_->cache.TE_Binary)*3;
+ out.vi_write(head, sizeof(head));
+ out << Error::banner0;
+ Image::Sampled *img=sf->getImg();
+ out << '\n' << img->getWd() << ' ' << img->getHt();
+ out << &(" 255\n"[sfo==Image::SF_Gray1?4:0]);
+ /* ^^^ SF_Gray1 BUGFIX at Tue Jun 4 21:44:17 CEST 2002 */
+ register char *p=img->getRowbeg(), *t=(char*)NULLP;
+ slen_t len=img->getRlen()*img->getHt();
+ // fprintf(stderr, "len=%u\n", len);
+ register unsigned smallen, i;
+ switch (head[1]) {
+ case '1': /* PBM ASCII */
+ while (len>=70) {
+ smallen=70; t=tmp; while (smallen--!=0) *t++=(*p++==0)?'1':'0';
+ /* ^^^ note the swapping of '0' and '1' above */
+ *t++='\n'; out.vi_write(tmp, 71);
+ len-=70;
+ }
+ while (len--!=0) *t++=(*p++==0)?'0':'1';
+ /* Dat: xv requires a whitespace just before EOF */
+ *t++='\n'; out.vi_write(tmp, t-tmp);
+ break;
+ case '2': case '3': /* PGM ASCII, PPM ASCII */
+ while (len!=0) {
+ if (len>17) { smallen=17; len-=17; } else { smallen=len; len=0; }
+ t=tmp; while (smallen--!=0) {
+ if ((i=*(unsigned char*)p++)<10) *t++=i+'0';
+ else if (i<100) { *t++=i/10+'0'; *t++=i%10+'0'; }
+ else if (i<200) { *t++='1'; *t++=(i-100)/10+'0'; *t++=i%10+'0'; }
+ else { *t++='2'; *t++=(i-200)/10+'0'; *t++=i%10+'0'; }
+ *t++=' ';
+ }
+ /* Dat: xv requires a whitespace just before EOF */
+ t[-1]='\n'; out.vi_write(tmp, t-tmp/*-(len==0)*/);
+ }
+ break;
+ case '4': /* PBM RAWBITS */
+ /* Invert the image */
+ while (len--!=0) *p++^=-1;
+ p=img->getRowbeg();
+ len=img->getRlen()*img->getHt();
+ /* fall through */
+ default: /* PBM RAWBITS, PGM RAWBITS, PPM RAWBITS */
+ /* fwrite(p, 1, len, stdout); */
+ out.vi_write(p, len);
+ }
+ if (alphaChannel!=NULLP) {
+ /* OK: don't always output rawbits PBM file */
+ assert(alphaChannel->getBpc()==1);
+ assert(alphaChannel->getWd()==img->getWd());
+ assert(alphaChannel->getHt()==img->getHt());
+ /* write PBM RAWBITS subfile (alpha channel) */
+ if (or_->cache.TransferEncoding==or_->cache.TE_Binary) {
+ out << "P4 " << img->getWd() << ' ' << img->getHt() << '\n';
+ out.vi_write(alphaChannel->getRowbeg(), alphaChannel->getRlen()*alphaChannel->getHt());
+ /* ^^^ BUGFIX at Tue Sep 17 10:18:28 CEST 2002 */
+ } else {
+ out << "P1 " << img->getWd() << ' ' << img->getHt() << '\n';
+ alphaChannel->to8();
+ p=alphaChannel->getRowbeg(); len=alphaChannel->getRlen()*alphaChannel->getHt();
+ while (len>=70) {
+ smallen=70; t=tmp; while (smallen--!=0) *t++=(*p++!=0)?'1':'0';
+ /* ^^^ note the non-swapping of '0' and '1' above */
+ *t++='\n'; out.vi_write(tmp, 71);
+ len-=70;
+ }
+ while (len--!=0) *t++=(*p++!=0)?'0':'1';
+ /* Dat: xv requires a whitespace just before EOF */
+ *t++='\n'; out.vi_write(tmp, t-tmp);
+ }
+ delete alphaChannel;
+ }
+ return Rule::Applier::OK;
+}
+
+Rule::Applier out_pnm_applier = { "PNM", out_pnm_check_rule, out_pnm_work, 0 };
+
+/* --- Sat Aug 10 22:18:33 CEST 2002 */
+
+Rule::Applier::cons_t out_xwd_check_rule(Rule::OutputRule* or_) {
+ Rule::Cache *cache=&or_->cache;
+ if (cache->FileFormat!=cache->FF_XWD
+ ) return Rule::Applier::DONT_KNOW;
+ bool badp=false;
+ if (cache->SampleFormat!=Image::SF_Rgb8 && cache->SampleFormat!=Image::SF_Gray8 && cache->SampleFormat!=Image::SF_Indexed8) {
+ Error::sev(Error::WARNING_DEFER) << "check_rule: /XWD must be /Rgb8, /Gray8 or /Indexed8" << (Error*)0;
+ return Rule::Applier::BAD;
+ }
+ if (cache->TransferEncoding!=cache->TE_Binary) {
+ Error::sev(Error::WARNING_DEFER) << "check_rule: /XWD requires /Binary" << (Error*)0;
+ badp=true;
+ }
+ if (cache->Compression!=Rule::Cache::CO_None) {
+ Error::sev(Error::WARNING_DEFER) << "check_rule: /XWD requires /Compression/None" << (Error*)0;
+ badp=true;
+ }
+ if (cache->hasPredictor()) {
+ Error::sev(Error::WARNING_DEFER) << "check_rule: /XWD requires /Predictor 1" << (Error*)0;
+ badp=true;
+ }
+ if (badp) return Rule::Applier::BAD;
+ return Rule::Applier::OK;
+}
+Rule::Applier::cons_t out_xwd_work(GenBuffer::Writable& out, Rule::OutputRule*or_, Image::SampledInfo *sf) {
+ static const unsigned
+ XWD_FILE_VERSION=7,
+ ZPixmap=2,
+ MSBFirst=1,
+ DirectColor=5,
+ PseudoColor=3,
+ //GrayScale=1,
+ StaticGray=0;
+ Image::sf_t sfo=or_->cache.SampleFormat;
+ if (out_xwd_check_rule(or_)!=Rule::Applier::OK) return Rule::Applier::DONT_KNOW;
+ or_->doSampleFormat(sf);
+ sfo=or_->cache.SampleFormat;
+ char head[101], *p=head;
+ Image::Sampled *img=sf->getImg();
+ slen_t bits_per_pixel, bitmap_pad, bytes_per_line;
+ unsigned ncolors;
+
+ memset(head, '\0', 101);
+ /*header_size*/ mf32(p,101);
+ /*file_version*/ (p+=4)[-1]=XWD_FILE_VERSION;
+ /*pixmap_format*/ (p+=4)[-1]=ZPixmap;
+ /*pixmap_depth*/ (p+=4)[-1]=sfo==Image::SF_Rgb8 ? 24 : 8;
+ /*pixmap_width */ mf32(p, img->getWd());
+ /*pixmap_height*/ mf32(p, img->getHt());
+ /*xoffset*/ p+=4;
+ /*byte_order*/ (p+=4)[-1]=MSBFirst;
+ /*bitmap_unit*/ (p+=4)[-1]=8; // sfo==Image::SF_Rgb8 ? 32 : 8;
+ /*bitmap_bit_order*/ (p+=4)[-1]=MSBFirst;
+ /*bitmap_pad*/ bitmap_pad=(p+=4)[-1]=8; // sfo==Image::SF_Rgb8 ? 32 : 8;
+ /* ^^^ force no padding at all */
+ /*bits_per_pixel*/ bits_per_pixel=(p+=4)[-1]=sfo==Image::SF_Rgb8 ? 24 : 8;
+ /*bytes_per_line*/ mf32(p, bytes_per_line=((bits_per_pixel*img->getWd()+bitmap_pad-1)&~(bitmap_pad-1))>>3);
+ /*visual_class*/ (p+=4)[-1]=sfo==Image::SF_Rgb8 ? DirectColor : sfo==Image::SF_Indexed8 ? PseudoColor : StaticGray;
+ /*red_mask */ (p+=4)[-3]=(char)(sfo==Image::SF_Rgb8 ? 255 : 0);
+ /*green_mask*/ (p+=4)[-2]=(char)(sfo==Image::SF_Rgb8 ? 255 : 0);
+ /*blue_mask */ (p+=4)[-1]=(char)(sfo==Image::SF_Rgb8 ? 255 : 0);
+ /*bits_per_rgb*/ (p+=4)[-1]=sfo==Image::SF_Rgb8 ? 24 : 8;
+ /*colormap_entries*/ (p+=4)[-2]=1; /*256*/
+ /*ncolors*/ mf32(p, ncolors=sfo==Image::SF_Rgb8 ? 0 : sfo==Image::SF_Indexed8 ? ((Image::Indexed*)img)->getNcols() : 256);
+ /*window_width */ mf32(p, img->getWd());
+ /*window_height*/ mf32(p, img->getHt());
+ assert(p+13==head+101);
+ /*window_x*/ /*0*/
+ /*window_y*/ /*0*/
+ /*window_bdrwidth*/ /*0*/
+ /*filename*/ /*""*/
+ out.vi_write(head, 101);
+
+ if (sfo!=Image::SF_Rgb8) {
+ char *pal=new char[ncolors*12], *pp=pal;
+ unsigned pixel;
+ if (sfo==Image::SF_Indexed8) {
+ char const* q=img->getHeadp();
+ for (pixel=0;pixel<ncolors;pixel++) {
+ *pp++=0; *pp++=0; *pp++=0; *pp++=pixel;
+ *pp++=*q; *pp++=*q++; /* red */
+ *pp++=*q; *pp++=*q++; /* green */
+ *pp++=*q; *pp++=*q++; /* blue */
+ *pp++=7;
+ *pp++=0;
+ }
+ } else { assert(sfo==Image::SF_Gray8);
+ for (pixel=0;pixel<ncolors;pixel++) {
+ *pp++=0; *pp++=0; *pp++=0; *pp++=pixel;
+ *pp++=pixel; *pp++=pixel; /* red */
+ *pp++=pixel; *pp++=pixel; /* green */
+ *pp++=pixel; *pp++=pixel; /* blue */
+ *pp++=7;
+ *pp++=0;
+ }
+ }
+ out.vi_write(pal, ncolors*12);
+ delete [] pal;
+ }
+
+ slen_t rlen=img->getRlen();
+ Image::Sampled::dimen_t htc=img->getHt();
+ char const* rp=img->getRowbeg();
+ unsigned scanline_pad=bytes_per_line-rlen;
+ // assert(*rp=='\xff');
+ if (scanline_pad!=0) {
+ assert(1<=scanline_pad && scanline_pad<=3);
+ while (htc--!=0) {
+ out.vi_write(rp, rlen);
+ rp+=rlen;
+ if (scanline_pad!=0) out.vi_write("\0\0", scanline_pad);
+ }
+ } else out.vi_write(rp, rlen*htc);
+
+ return Rule::Applier::OK;
+}
+
+Rule::Applier out_xwd_applier = { "XWD", out_xwd_check_rule, out_xwd_work, 0 };
+
+Rule::Applier out_x11_applier = { "X11", 0/*out_x11_check_rule*/, 0/*out_x11_work*/, 0 };
+
+/* --- Sat Apr 20 11:49:56 CEST 2002 */
+
+/** Baseline (lossy) JPEG */
+Rule::Applier::cons_t out_jpeg_check_rule(Rule::OutputRule* or_) {
+ Rule::Cache *cache=&or_->cache;
+ if (cache->FileFormat!=cache->FF_JPEG
+ || cache->Compression==Rule::Cache::CO_JAI
+ ) return Rule::Applier::DONT_KNOW;
+ bool badp=false;
+ if (cache->SampleFormat!=Image::SF_Rgb8 && cache->SampleFormat!=Image::SF_Gray8) {
+ Error::sev(Error::WARNING_DEFER) << "check_rule: /DCTEncode requires /Rgb8 or /Gray8" << (Error*)0;
+ badp=true;
+ }
+ if (cache->TransferEncoding!=cache->TE_Binary) {
+ Error::sev(Error::WARNING_DEFER) << "check_rule: /JPEG requires /Binary" << (Error*)0;
+ badp=true;
+ }
+ if (cache->Compression!=Rule::Cache::CO_None && cache->Compression!=Rule::Cache::CO_DCT && cache->Compression!=Rule::Cache::CO_IJG) {
+ Error::sev(Error::WARNING_DEFER) << "check_rule: /JPEG requires /DCT or /IJG" << (Error*)0;
+ badp=true;
+ }
+ if (cache->hasPredictor()) {
+ Error::sev(Error::WARNING_DEFER) << "check_rule: /JPEG requires /Predictor 1" << (Error*)0;
+ badp=true;
+ }
+ if (badp) return Rule::Applier::BAD;
+ or_->cache.WarningOK=true; /* ?? */
+ return Rule::Applier::OK;
+}
+Rule::Applier::cons_t out_jpeg_work(GenBuffer::Writable& out, Rule::OutputRule*or_, Image::SampledInfo *sf) {
+ Rule::Cache *cache=&or_->cache;
+ // assert(0);
+ if (out_jpeg_check_rule(or_)!=Rule::Applier::OK) return Rule::Applier::DONT_KNOW;
+ or_->doSampleFormat(sf);
+ // GenBuffer::Writable *tp=&out; /* always binary */
+ GenBuffer::Writable *cp=&out;
+ /* SUXX: cjpeg(1) won't create a color JPEG for a grayscale image */
+ if (cache->Compression==Rule::Cache::CO_DCT) {
+ SimBuffer::B other_parameters;
+ or_->cacheHints.DCT->dump(other_parameters, 0, false);
+ cp=PSEncoder::newDCTEncode(out, or_->cacheHints.EncoderColumns, or_->cacheHints.EncoderRows, or_->cacheHints.EncoderColors, or_->cacheHints.ColorTransform, other_parameters);
+ } else {
+ assert(cache->Compression==Rule::Cache::CO_None || cache->Compression==Rule::Cache::CO_IJG);
+ cp=PSEncoder::newDCTIJGEncode(out, or_->cacheHints.EncoderColumns, or_->cacheHints.EncoderRows, or_->cacheHints.EncoderColors, or_->cacheHints.Quality);
+ }
+ Rule::writePalData(out, *cp, sf);
+ delete cp;
+ return Rule::Applier::OK;
+}
+
+Rule::Applier out_jpeg_applier = { "JPEG", out_jpeg_check_rule, out_jpeg_work, 0 };
+
+/* --- Wed Apr 17 13:32:46 CEST 2002 */
+
+Rule::Applier::cons_t out_jpegjai_check_rule(Rule::OutputRule* or_) {
+ Rule::Cache *cache=&or_->cache;
+ if (cache->FileFormat!=cache->FF_JPEG
+ || cache->Compression!=Rule::Cache::CO_JAI
+ ) return Rule::Applier::DONT_KNOW;
+ bool badp=false;
+ if (cache->SampleFormat!=Image::SF_Asis) {
+ Error::sev(Error::WARNING_DEFER) << "check_rule: /FileFormat/JPEG /Compression/JAI requires /SampleFormat/Asis" << (Error*)0;
+ badp=true;
+ }
+ if (cache->TransferEncoding!=cache->TE_Binary) {
+ Error::sev(Error::WARNING_DEFER) << "check_rule: /FileFormat/JPEG /Compression/JAI requires /TransferEncoding/Binary" << (Error*)0;
+ badp=true;
+ }
+ if (cache->hasPredictor()) {
+ Error::sev(Error::WARNING_DEFER) << "check_rule: /FileFormat/JPEG /Compression/JAI requires /Predictor 1" << (Error*)0;
+ badp=true;
+ }
+ if (badp) return Rule::Applier::BAD;
+ return Rule::Applier::OK;
+}
+Rule::Applier::cons_t out_jpegjai_work(GenBuffer::Writable& out, Rule::OutputRule*or_, Image::SampledInfo *sf) {
+ /* This is the second simplest Applier I've ever written. */
+ if (out_jpegjai_check_rule(or_)!=Rule::Applier::OK) return Rule::Applier::DONT_KNOW;
+ Image::Sampled *img=sf->getImg();
+ // out.vi_write(img->getHeadp(), img->end_()-img->getHeadp());
+ /* ^^^ end_() BUGFIX by pts@fazekas.hu at Sun Jun 2 22:24:32 CEST 2002 */
+ /* ^^^ end_() contains 8 extra bytes */
+ out.vi_write(img->getHeadp(), img->getRowbeg()-img->getHeadp());
+ return Rule::Applier::OK;
+}
+
+Rule::Applier out_jpegjai_applier = { "JPEG-JAI", out_jpegjai_check_rule, out_jpegjai_work, 0 };
+
+/* --- Sun Jun 2 22:25:16 CEST 2002 */
+
+class TIFFPrinter {
+ GenBuffer::Writable& out;
+ /** true iff little endian == LSB first */
+ bool le;
+ SimBuffer::B s, dir;
+ public:
+ TIFFPrinter(GenBuffer::Writable &out_, bool le_);
+ inline SimBuffer::B& getS() { return s; }
+ inline SimBuffer::B const& getDir() const { return dir; }
+ void aSHORT(SimBuffer::B &s, unsigned count, unsigned short const*val);
+ void aLONG (SimBuffer::B &s, unsigned count, slen_t const*val);
+ void dirSHORT(unsigned short tag, slen_t count, unsigned short const*val);
+ void dirLONG(unsigned short tag, slen_t count, slen_t const*val);
+ void dirSL(unsigned short tag, slen_t val);
+ void dirLONG(unsigned short tag, slen_t val);
+ void dirRATIONAL(unsigned short tag, slen_t count, slen_t const*val);
+ void dirUNDEFINED(unsigned short tag, slen_t count, char const*val);
+ void dirUNDEFINED(unsigned short tag, slen_t count, char const*val, slen_t count2, char const*val2);
+ void dirClose();
+ BEGIN_STATIC_ENUM1(unsigned short)
+ EXTRASAMPLE_ASSOCALPHA=1, /* !associated alpha data */
+ EXTRASAMPLE_UNASSALPHA=2 /* !unassociated alpha data */
+ END_STATIC_ENUM()
+ BEGIN_STATIC_ENUM1(unsigned short)
+ COMPRESSION_NONE =1, /* dump mode */
+ COMPRESSION_CCITTRLE =2, /* CCITT modified Huffman RLE; unused in sam2p */
+ COMPRESSION_CCITTFAX3=3, /* CCITT Group 3 fax encoding */
+ COMPRESSION_CCITTFAX4=4, /* CCITT Group 4 fax encoding */
+ COMPRESSION_LZW =5, /* Lempel-Ziv & Welch */
+ COMPRESSION_OJPEG =6, /* !6.0 JPEG; obsolete, unused in sam2p */
+ COMPRESSION_JPEG =7, /* %JPEG DCT compression */
+ COMPRESSION_CCITTRLEW=32771,/* #1 w/ word alignment; unused in sam2p */
+ COMPRESSION_PACKBITS =32773,/* Macintosh RLE */
+ COMPRESSION_DEFLATE =32946 /* Deflate compression */
+ END_STATIC_ENUM()
+ BEGIN_STATIC_ENUM1(unsigned short)
+ PHOTOMETRIC_MINISBLACK=1,
+ PHOTOMETRIC_RGB=2,
+ PHOTOMETRIC_PALETTE=3,
+ PHOTOMETRIC_MASK=4,
+ PHOTOMETRIC_SEPARATED=5, /* possibly CMYK */
+ PHOTOMETRIC_YCBCR=6
+ END_STATIC_ENUM()
+ BEGIN_STATIC_ENUM1(unsigned short)
+ GROUP3OPT_2DENCODING=0x1,
+ GROUP3OPT_UNCOMPRESSED=0x2,
+ GROUP3OPT_FILLBITS=0x4,
+ GROUP4OPT_UNCOMPRESSED=0x2
+ END_STATIC_ENUM()
+ BEGIN_STATIC_ENUM1(unsigned short)
+ ImageWidth=256,
+ ImageLength=257,
+ BitsPerSample=258,
+ Compression=259,
+ Photometric=262,
+ FillOrder=266,
+ StripOffsets=273,
+ SamplesPerPixel=277,
+ RowsPerStrip=278,
+ StripByteCounts=279,
+ XResolution=282,
+ YResolution=283,
+ PlanarConfig=284,
+ Group3Options=292,
+ Group4Options=293,
+ ResolutionUnit=296,
+ Predictor=317,
+ ColorMap=320,
+ InkSet=332,
+ ExtraSamples=338,
+ JPEGTables=347,
+ YCbCrSubsampling=530,
+ ReferenceBlackWhite=532
+ END_STATIC_ENUM()
+};
+
+TIFFPrinter::TIFFPrinter(GenBuffer::Writable &out_, bool le_) :out(out_), le(le_) {
+ /* Directory now at unknown offset (will be set by .dirClose()) */
+ s.vi_write(le_ ? "II*\0\0\0\0\0" : "MM\0*\0\0\0\0", 8);
+ dir.vi_write("\0",2); /* initial number of directory entries */
+}
+
+void TIFFPrinter::aSHORT(SimBuffer::B &s, unsigned count, unsigned short const*val) {
+ if (le) while (count--!=0) { s << (char)(*val) << (char)(*val>>8); val++; }
+ else while (count--!=0) { s << (char)(*val>>8) << (char)(*val); val++; }
+}
+void TIFFPrinter::aLONG (SimBuffer::B &s, unsigned count, slen_t const*val) {
+ /* Imp: is vi_write(..., 4); faster ? */
+ if (le) while (count--!=0) { s << (char)(*val) << (char)(*val>>8) << (char)(*val>>16) << (char)(*val>>24); val++; }
+ else while (count--!=0) { s << (char)(*val>>24) << (char)(*val>>16) << (char)(*val>>8) << (char)(*val); val++; }
+}
+
+void TIFFPrinter::dirSHORT(unsigned short const tag, slen_t const count, unsigned short const*val) {
+ slen_t offs;
+ aSHORT(dir, 1U, &tag);
+ dir.vi_write(&("\0\3"[le?1:0]), 2);
+ aLONG(dir, 1U, &count);
+ switch (count) {
+ case 0: dir.vi_write("\0\0\0", 4); break;
+ case 1: aSHORT(dir, 1, val); dir.vi_write("\0", 2); break;
+ case 2: aSHORT(dir, 2, val); break;
+ default:offs=s.getLength(); aSHORT(s, count, val); aLONG(dir, 1, &offs);
+ }
+}
+void TIFFPrinter::dirLONG(unsigned short const tag, slen_t const count, slen_t const*val) {
+ slen_t offs;
+ aSHORT(dir, 1U, &tag);
+ dir.vi_write(&("\0\4"[le?1:0]), 2);
+ aLONG(dir, 1U, &count);
+ switch (count) {
+ case 0: dir.vi_write("\0\0\0", 4); break;
+ case 1: aLONG(dir, 1, val); break;
+ default:offs=s.getLength(); aLONG(s, count, val); aLONG(dir, 1, &offs);
+ }
+}
+void TIFFPrinter::dirRATIONAL(unsigned short tag, slen_t count, slen_t const*val) {
+ slen_t offs;
+ aSHORT(dir, 1U, &tag);
+ dir.vi_write(&("\0\5"[le?1:0]), 2);
+ aLONG(dir, 1U, &count);
+ switch (count) {
+ case 0: dir.vi_write("\0\0\0", 4); break;
+ default:offs=s.getLength(); aLONG(s, count*2, val); aLONG(dir, 1, &offs);
+ }
+}
+void TIFFPrinter::dirUNDEFINED(unsigned short tag, slen_t count, char const*val) {
+ slen_t offs;
+ aSHORT(dir, 1U, &tag);
+ dir.vi_write(&("\0\7"[le?1:0]), 2);
+ aLONG(dir, 1U, &count);
+ if (count<=4) {
+ dir.vi_write(val, count);
+ if (count!=4) dir.vi_write("\0\0\0", 4-count);
+ } else {
+ offs=s.getLength(); s.vi_write(val, count); aLONG(dir, 1, &offs);
+ }
+}
+void TIFFPrinter::dirUNDEFINED(unsigned short tag, slen_t count, char const*val, slen_t count2, char const*val2) {
+ slen_t offs, countx=count+count2;
+ aSHORT(dir, 1U, &tag);
+ dir.vi_write(&("\0\7"[le?1:0]), 2);
+ aLONG(dir, 1U, &countx);
+ if (countx<=4) {
+ dir.vi_write(val, count);
+ dir.vi_write(val2, count2);
+ if (countx!=4) dir.vi_write("\0\0\0", 4-countx);
+ } else {
+ offs=s.getLength();
+ s.vi_write(val, count);
+ s.vi_write(val2, count2);
+ aLONG(dir, 1, &offs);
+ }
+}
+void TIFFPrinter::dirSL(unsigned short tag, slen_t val) {
+ unsigned short sh;
+ if (val<1<<16U) { sh=val; dirSHORT(tag, 1, &sh); }
+ else dirLONG(tag, 1, &val);
+}
+void TIFFPrinter::dirLONG(unsigned short tag, slen_t val) {
+ dirLONG(tag, 1, &val);
+}
+void TIFFPrinter::dirClose() {
+ char *ss=s.begin_();
+ slen_t len=s.getLength();
+ if (le) { ss[4]=len; ss[5]=len>>8; ss[6]=len>>16; ss[7]=len>>24; }
+ else { ss[4]=len>>24; ss[5]=len>>16; ss[6]=len>>8; ss[7]=len; }
+ /* ^^^ dir offset: end of file */
+ out.vi_write(ss, len);
+ assert(dir.getLength()%12==2);
+ unsigned dirc=(dir.getLength()-2)/12;
+ ss=dir.begin_();
+ if (le) { ss[0]=dirc; ss[1]=dirc>>8; }
+ else { ss[0]=dirc>>8; ss[1]=dirc; }
+ out.vi_write(dir(), dir.getLength());
+ out.vi_write("", 0);
+}
+
+/* tiffjai --- Sun Jun 2 22:25:16 CEST 2002 */
+
+Rule::Applier::cons_t out_tiffjai_check_rule(Rule::OutputRule* or_) {
+ Rule::Cache *cache=&or_->cache;
+ if (cache->FileFormat!=cache->FF_TIFF
+ || cache->Compression!=Rule::Cache::CO_JAI
+ ) return Rule::Applier::DONT_KNOW;
+ bool badp=false;
+ if (cache->SampleFormat!=Image::SF_Asis) {
+ Error::sev(Error::WARNING_DEFER) << "check_rule: /FileFormat/TIFF /Compression/JAI requires /SampleFormat/Asis" << (Error*)0;
+ badp=true;
+ }
+ if (!cache->isBinSB()) {
+ Error::sev(Error::WARNING_DEFER) << "check_rule: /FileFormat/TIFF /TransferEncoding/Binary|/?SBFirst" << (Error*)0;
+ badp=true;
+ }
+ if (cache->hasPredictor()) {
+ Error::sev(Error::WARNING_DEFER) << "check_rule: /FileFormat/TIFF /Compression/JAI requires /Prediror 1" << (Error*)0;
+ badp=true;
+ }
+ if (badp) return Rule::Applier::BAD;
+ return Rule::Applier::OK;
+}
+Rule::Applier::cons_t out_tiffjai_work(GenBuffer::Writable& out, Rule::OutputRule*or_, Image::SampledInfo *sf) {
+ if (out_tiffjai_check_rule(or_)!=Rule::Applier::OK) return Rule::Applier::DONT_KNOW;
+ Image::Sampled *img=sf->getImg();
+ unsigned char cs=img->getCs(); /* color space */
+ if (cs!=Image::Sampled::CS_GRAYSCALE && cs!=Image::Sampled::CS_RGB && cs!=Image::Sampled::CS_YCbCr && cs!=Image::Sampled::CS_CMYK) {
+ /* Dat: CS_YCCK is supported by JPEG, but unsupported by TIFF-JPEG */
+ Error::sev(Error::WARNING_DEFER) << "check_rule: /FileFormat/TIFF /Compression/JAI doesn't support this color space" << (Error*)0;
+ return Rule::Applier::BAD;
+ }
+ /* Imp: test all CMYK TIFF tags */
+ /* Imp: test with RGB and CMYK images */
+ TIFFPrinter tp(out, or_->cache.TransferEncoding==or_->cache.TE_LSBfirst);
+ /* ^^^ Dat: Binary defaults to MSBfirst, beacuse QuarkXPress 3 can read only
+ * MSBfirst TIFF files.
+ */
+ char const *databeg=img->getHeadp()+img->getXoffs();
+ assert(databeg[-2]=='\xFF' && databeg[-1]=='\xC0');
+ slen_t datalen=img->getRowbeg()-databeg;
+ // printf("LEN=%u gl=%u datalen=%u\n", img->end_()-img->begin_(), img->getLength(), datalen);
+ tp.getS().vi_write("\xFF\xD8\xFF\xC0", 4); /* fake-SOI SOF0 */
+ tp.getS().vi_write(databeg, datalen); /* DataPart */
+ // tp.getS().vi_write("\xFF\xD9", 2); /* fake-EOI */
+ /* ^^^ there must be an EOI already */
+
+ unsigned phot=0; bool inks=false, refe=false;
+ switch (cs) {
+ case Image::Sampled::CS_GRAYSCALE: phot=tp.PHOTOMETRIC_MINISBLACK; break;
+ case Image::Sampled::CS_RGB: phot=tp.PHOTOMETRIC_RGB; break;
+ case Image::Sampled::CS_YCbCr: phot=tp.PHOTOMETRIC_YCBCR; refe=true; break; /* preferred to RGB */
+ case Image::Sampled::CS_CMYK: phot=tp.PHOTOMETRIC_SEPARATED; inks=true; break; /* preferred to RGB */
+ default: Error::sev(Error::EERROR) << "TIFF6-JAI: color space " << (unsigned)cs << " not supported in TIFF-JPEG" << (Error*)0;
+ }
+
+ /* Dat: TIFF tags must appear in increasing numerical order */
+ tp.dirSL(tp.ImageWidth, img->getWd());
+ tp.dirSL(tp.ImageLength, img->getHt());
+ unsigned short eights[]={8,8,8,8};
+ tp.dirSHORT(tp.BitsPerSample, img->cs2cpp[cs], eights);
+ tp.dirSL(tp.Compression, tp.COMPRESSION_JPEG); /* SHORT */
+ tp.dirSL(tp.Photometric, phot); /* SHORT */
+ tp.dirLONG(tp.StripOffsets, 8);
+ tp.dirSL(tp.SamplesPerPixel, img->cs2cpp[cs]); /* SHORT */
+ tp.dirSL(tp.RowsPerStrip, img->getHt());
+ tp.dirLONG(tp.StripByteCounts, datalen+6);
+ slen_t rats[]={1,1, 0,1, 255,1, 128,1, 255,1, 128,1, 255,1};
+ tp.dirRATIONAL(tp.XResolution, 1, rats);
+ tp.dirRATIONAL(tp.YResolution, 1, rats);
+ tp.dirSL(tp.PlanarConfig, 1); /* SHORT, PLANARCONFIG_CONTIG */
+ tp.dirSL(tp.ResolutionUnit, 1); /* SHORT */
+ if (inks) tp.dirSL(tp.InkSet, 1); /* SHORT */
+ tp.dirUNDEFINED(tp.JPEGTables, databeg-img->getHeadp()-2, img->getHeadp(), 2, "\xFF\xD9");
+ const unsigned char hvs=img->end_()[-1];
+ if (hvs!=0x22 && cs==Image::Sampled::CS_YCbCr) {
+ // printf("hvs=0x%02X\n", hvs);
+ const unsigned short horiz_vert[2]={ (unsigned short)((hvs+0U)>>4),
+ (unsigned short)(hvs&15U) };
+ tp.dirSHORT(tp.YCbCrSubsampling, 2, horiz_vert);
+ }
+ if (refe) tp.dirRATIONAL(tp.ReferenceBlackWhite, 6, rats+2);
+ tp.dirClose();
+ #if 0
+ { Files::FILEW f(fopen("t.hea","wb"));
+ f.vi_write(img->getHeadp(), databeg-img->getHeadp()-2); /* HeadPart */
+ f.vi_write("\xFF\xD9", 2);
+ f.close();
+ }
+ { Files::FILEW f(fopen("t.dat","wb"));
+ f.vi_write("\xFF\xD8\xFF\xC0", 4); /* fake-SOI SOF0 */
+ f.vi_write(databeg, datalen); /* DataPart */
+ f.close();
+ }
+ #endif
+ // out.vi_write(img->getHeadp(), img->getRowbeg()-img->getHeadp()); /* HeadPart */
+ // out.vi_write(img->getRowbeg(), img->end_()-img->getRowbeg()); /* DataPart */
+ return Rule::Applier::OK;
+ /* SUXX: see compatibility notes in FAQ (README) */
+}
+
+Rule::Applier out_tiffjai_applier = { "TIFF6-JAI", out_tiffjai_check_rule, out_tiffjai_work, 0 };
+
+/* tiff --- Tue Jun 4 16:23:48 CEST 2002 */
+
+/** by pts@fazekas.hu at Tue Jun 11 16:56:53 CEST 2002
+ * Reads a JPEG Baseline (SOF0) stream on input, and drops everything before
+ * the first SOF0 marker. Then writes an SOI marker, the SOF0 marker, and
+ * everything after the SOI marker. The last two bytes read must be an
+ * EOI marker (/\xFF\xD9/). The first thing to be read must be a SOI marker
+ * (/\xFF+\xD8/). The getJPEGTables() method can be used to retrieve the
+ * data read before the SOF0 marker. An SOS marker must be read after SOF0.
+ * Also retains some information (hvsamples[0]) from the SOF0 marker.
+ * Suitable for reading the output of cjpeg and Ghostscript /FlateEncode.
+ * This encoder would be much harder if we were not allowed to read the
+ * JPEG stream into memory.
+ */
+class JPEGSOF0Encode: public PSEncoder {
+ public:
+ /** @param maxcpl_: maximum # hex digits per line, should be even */
+ JPEGSOF0Encode(GenBuffer::Writable &out_);
+ virtual void vi_write(char const*buf, slen_t len);
+ SimBuffer::Flat const& getJPEGTables() const { return buf; }
+ unsigned char getColorSpace() const { return gi.colorspace; }
+ unsigned char getHVS() const { return gi.hvs; }
+ protected:
+ GenBuffer::Writable &out;
+ SimBuffer::B buf;
+ struct jai_gfxinfo gi;
+};
+
+JPEGSOF0Encode::JPEGSOF0Encode(GenBuffer::Writable &out_): out(out_) {}
+void JPEGSOF0Encode::vi_write(char const*bufr, slen_t len) {
+ if (len==0) {
+ { Filter::FlatD flatd(buf(), buf.getLength());
+ jai_parse_jpeg(&gi, &flatd);
+ }
+ slen_t len=buf.getLength();
+ if (gi.bad==0 && (len<4 || buf[len-2]!='\xFF' || buf[len-1]!='\xD9')) gi.bad=10;
+ if (gi.bad!=0)
+ Error::sev(Error::EERROR) << "JPEGS0F0: invalid JPEG stream: " << jai_errors[gi.bad] << (Error*)0;
+ out.vi_write("\xFF\xD8", 2); /* extra SOI */
+ out.vi_write(buf()+gi.SOF_offs-2, len-gi.SOF_offs+2); /* SOF0 and followers */
+ out.vi_write(0,0);
+ assert(buf[gi.SOF_offs-2]=='\xFF'); /* BUGFIX at 2002.12.02 */
+ buf[gi.SOF_offs-1]='\xD9'; /* extra EOI */
+ buf.keepLeft(gi.SOF_offs); /* keep only headers */
+ } else buf.vi_write(bufr, len);
+}
+
+
+Rule::Applier::cons_t out_tiff_check_rule(Rule::OutputRule* or_) {
+ Rule::Cache *cache=&or_->cache;
+ if (cache->FileFormat!=cache->FF_TIFF
+ || cache->Compression==Rule::Cache::CO_JAI
+ ) return Rule::Applier::DONT_KNOW;
+ bool badp=false;
+ /* Dat: acroread TIFF predictor2 OK. (examples/fishg_lzw2_pdf.job) */
+ /* Dat: /ZIP with /Predictor OK */
+ if (cache->Predictor!=cache->PR_None) {
+ if (cache->Predictor!=cache->PR_TIFF2) {
+ Error::sev(Error::WARNING_DEFER) << "check_rule: /FileFormat/TIFF requires /Predictor 1|2" << (Error*)0;
+ badp=true;
+ }
+ if (cache->Compression!=Rule::Cache::CO_ZIP && cache->Compression!=Rule::Cache::CO_LZW) {
+ Error::sev(Error::WARNING_DEFER) << "check_rule: real /Predictor requires /ZIP or /LZW" << (Error*)0;
+ badp=true;
+ }
+ }
+ #if !HAVE_LZW
+ if (cache->Compression==Rule::Cache::CO_LZW) {
+ Error::sev(Error::WARNING_DEFER) << "check_rule: `configure --enable-lzw' for /Compression/LZW with /FileFormat/TIFF" << (Error*)0;
+ badp=true;
+ }
+ #endif
+ if (cache->Compression==Rule::Cache::CO_Fax && !cache->isOneBit()) {
+ Error::sev(Error::WARNING_DEFER) << "check_rule: /FileFormat/TIFF /Compression/Fax requires a 1-bit /SampleFormat" << (Error*)0;
+ badp=true;
+ }
+ if (!cache->isGray() && !cache->isTransparentM() && !cache->isIndexed() && !cache->isRGB()) {
+ /* Dat: unsupported SampleFormats: /Opaque, /Transparent and /Asis. */
+ Error::sev(Error::WARNING_DEFER) << "check_rule: unsupported /SampleFormat for /FileFormat/TIFF" << (Error*)0;
+ badp=true;
+ }
+ if (!cache->isBinSB()) {
+ Error::sev(Error::WARNING_DEFER) << "check_rule: /FileFormat/TIFF requires /TransferEncoding/Binary|/?SBFirst" << (Error*)0;
+ badp=true;
+ }
+ if (cache->isDCTE() && cache->SampleFormat!=Image::SF_Rgb8 && cache->SampleFormat!=Image::SF_Gray8 && cache->SampleFormat!=Image::SF_Indexed8) {
+ Error::sev(Error::WARNING_DEFER) << "check_rule: /DCTEncode requires /Rgb8 or /Gray8 (or /Indexed8)" << (Error*)0;
+ badp=true;
+ }
+ if (!badp && cache->isTransparentM()) {
+ cache->origSampleFormat=cache->SampleFormat;
+ cache->SampleFormat=Image::SF_Transparent8;
+ }
+ return (Rule::Applier::cons_t)(badp ? 0+Rule::Applier::BAD : 0+Rule::Applier::OK);
+ /* ^^^ Dat: 0+: pacify g++-3.1 */
+}
+
+Rule::Applier::cons_t out_tiff_work(GenBuffer::Writable& out, Rule::OutputRule*or_, Image::SampledInfo *sf) {
+ Rule::Cache *cache=&or_->cache;
+ Image::sf_t origSampleFormat=cache->origSampleFormat;
+ if (out_tiff_check_rule(or_)!=Rule::Applier::OK) return Rule::Applier::DONT_KNOW;
+
+ assert(!sf->hasTranspp() || cache->isTransparentM());
+ /** Alpha channel or null. */
+ Image::Indexed *alpha=(Image::Indexed*)NULLP;
+ if (cache->isTransparentM()) {
+ // fprintf(stderr,"sf=%u osf=%u\n", cache->SampleFormat, origSampleFormat);
+ alpha=PTS_dynamic_cast(Image::Indexed*,sf->getImg())->calcAlpha();
+ PTS_dynamic_cast(Image::Indexed*,sf->getImg())->getClearTransp();
+ assert((alpha!=NULLP) == (sf->hasTranspp()==true));
+ sf->clearTransp();
+ static Image::sf_t const graytab[9]={Image::SF_None,Image::SF_Gray1,Image::SF_Gray2,Image::SF_None,Image::SF_Gray4,Image::SF_None,Image::SF_None,Image::SF_None,Image::SF_Gray8};
+ static Image::sf_t const rgbtab[9]={Image::SF_None,Image::SF_Rgb1,Image::SF_Rgb2,Image::SF_None,Image::SF_Rgb4,Image::SF_None,Image::SF_None,Image::SF_None,Image::SF_Rgb8};
+ static Image::sf_t const indexedtab[9]={Image::SF_None,Image::SF_Indexed1,Image::SF_Indexed2,Image::SF_None,Image::SF_Indexed4,Image::SF_None,Image::SF_None,Image::SF_None,Image::SF_Indexed8};
+ unsigned char minbpc=sf->minRGBBpcc();
+ // fprintf(stderr,"minbpc=%u\n",minbpc);
+ if (minbpc<8 && origSampleFormat==Image::SF_Transparent8) minbpc=8;
+ else if (minbpc<4 && origSampleFormat==Image::SF_Transparent4) minbpc=4;
+ else if (minbpc<2 && origSampleFormat==Image::SF_Transparent2) minbpc=2;
+ // fprintf(stderr,"minbpc=%u\n",minbpc);
+ // cacheHints.EncoderBPL=(slen_t)img->getWd()*img->getCpp()*img->getBpc();
+ /* ^^^ Dat: doSampleFormat will do it correctly */
+ // assert(saf!=Image::SF_max);
+ cache->SampleFormat=(alpha==NULLP ? indexedtab : sf->minGrayBpcc()==0 ? rgbtab : graytab)[minbpc];
+ }
+
+ or_->doSampleFormat(sf); /* No separations */
+ Image::Sampled *img=sf->getImg(); /* call this _after_ doSampleFormat()! */
+
+ TIFFPrinter tp(out, or_->cache.TransferEncoding==or_->cache.TE_LSBfirst);
+ /* ^^^ Dat: Binary defaults to MSBfirst, beacuse QuarkXPress 3 can read only
+ * MSBfirst TIFF files.
+ */
+ unsigned phot= cache->isRGB() ? 0+tp.PHOTOMETRIC_RGB
+ // : cache->SampleFormat==Image::SF_Mask ? tp.PHOTOMETRIC_MASK
+ : cache->isGray() ? 0+tp.PHOTOMETRIC_MINISBLACK
+ // : cache->isIndexed() ? tp.PHOTOMETRIC_PALETTE
+ : 0+tp.PHOTOMETRIC_PALETTE /* /Indexed*, /Mask, /Transparent+ */;
+ unsigned compr=tp.COMPRESSION_NONE;
+
+ Filter::VerbatimCountE vc(tp.getS());
+ GenBuffer::Writable *cp=&vc;
+ JPEGSOF0Encode *jp=(JPEGSOF0Encode*)NULLP;
+ // Dat: g++-3.4: Rule::Cache::CO_None: `cache cannot appear in a constant expression'
+ switch (cache->Compression) {
+ case Rule::Cache::CO_None: break;
+ case Rule::Cache::CO_ZIP: compr=tp.COMPRESSION_DEFLATE; cp=PSEncoder::newFlateEncode(*cp, or_->cacheHints.Effort); break;
+ case Rule::Cache::CO_LZW: compr=tp.COMPRESSION_LZW; cp=PSEncoder::newLZWEncode(*cp); break;
+ /* vvv Dat: RunLengthEncode EOD (char 128) is OK and ignored in TIFF PackBits streams */
+ case Rule::Cache::CO_RLE: compr=tp.COMPRESSION_PACKBITS; cp=PSEncoder::newRunLengthEncode(*cp, or_->cacheHints.RecordSize); break;
+ case Rule::Cache::CO_Fax:
+ if (or_->cacheHints.K<0) compr=tp.COMPRESSION_CCITTFAX4;
+ else if (or_->cacheHints.K==0) compr=tp.COMPRESSION_CCITTFAX3;
+ else { compr=tp.COMPRESSION_CCITTFAX3; or_->cacheHints.K=img->getHt(); }
+ cp=PSEncoder::newCCITTFaxEncode(*cp, or_->cacheHints.K, or_->cacheHints.EncoderBPL, /*EndOfLine:*/ compr==tp.COMPRESSION_CCITTFAX3, /*BlackIs1: !*/ true);
+ /* Dat: libtiff enforces EndOfLine==(compr==tp.COMPRESSION_CCITTFAX3) */
+ break;
+ case Rule::Cache::CO_IJG:
+ compr=tp.COMPRESSION_JPEG;
+ jp=new JPEGSOF0Encode(vc);
+ cp=PSEncoder::newDCTIJGEncode(*jp, or_->cacheHints.EncoderColumns, or_->cacheHints.EncoderRows, or_->cacheHints.EncoderColors, or_->cacheHints.Quality);
+ break;
+ case Rule::Cache::CO_DCT: compr=tp.COMPRESSION_JPEG; {
+ SimBuffer::B other_parameters;
+ or_->cacheHints.DCT->dump(other_parameters, 0, false);
+ jp=new JPEGSOF0Encode(vc);
+ cp=PSEncoder::newDCTEncode(*jp, or_->cacheHints.EncoderColumns, or_->cacheHints.EncoderRows, or_->cacheHints.EncoderColors, or_->cacheHints.ColorTransform, other_parameters);
+ break; }
+ default: assert(0);
+ }
+
+ GenBuffer::Writable *pp=cp;
+ if (cache->hasPredictor()) pp=PSEncoder::newPredictor(*cp, cache->Predictor, or_->cacheHints.PredictorBPC, or_->cacheHints.PredictorColumns, or_->cacheHints.PredictorColors);
+
+ slen_t rlenht=img->getRlen()*img->getHt();
+ Image::Sampled::dimen_t wd=img->getWd();
+ if (rlenht!=0) {
+ /* Dat: TIFF inserts extra sample bits... */
+ /* TIFF images with transparency are really inefficient. That's because
+ * libtiff doesn't read or write an indexed image with transparency:
+ * Sorry, can not handle contiguous data with PhotometricInterpretation=3,
+ * and Samples/pixel=2.
+ * So Indexed images are converted to RGB* or Gray* first, and then the
+ * alpha channel is added. The result is a big and inefficiently
+ * compressible TIFF file.
+ */
+
+ if (alpha!=NULLP) {
+ unsigned char bpc=img->getBpc();
+ slen_t rlen=img->getRlen();
+ slen_t writelen;
+ char *buf=(char*)NULLP;
+ char const*psave=img->getRowbeg(), *p, *ppend=psave+rlenht;
+ char const*r=alpha->getRowbeg();
+#ifndef NDEBUG
+ char const*rend;
+ Image::Sampled::dimen_t rlena=(wd+7)>>3;
+#endif
+ char *t;
+ register unsigned u;
+#ifndef NDEBUG
+ assert(rlena==alpha->getRlen());
+#endif
+ // printf("SF=%u\n", cache->SampleFormat);
+ if (cache->isGray()) {
+ /* works at Mon Dec 9 01:25:59 CET 2002 */
+ static unsigned char const szor1[16]={2*0,2*1,2*4,2*5,2*16,2*17,2*20,2*21,2*64,2*65,2*68,2*69,2*80,2*81,2*84,2*85};
+ static unsigned char const szor2[16]={85,84,81,80,69,68,65,64,21,20,17,16,5,4,1,0};
+ // static unsigned char const szor2[8]={0,1,16,17,64,65,80,81};
+ buf=new char[(writelen=((slen_t)wd*bpc+3)>>2)+24];
+#ifndef NDEBUG
+ assert(rlena*8>=rlen);
+#endif
+ while (psave!=ppend) {
+ t=buf;
+#ifndef NDEBUG
+ rend=r+rlena;
+#endif
+ p=psave; psave+=rlen;
+ assert(psave<=ppend);
+ u=(1<<16);
+ switch (bpc) {
+ case 8:
+ while (p!=psave) {
+ /* Dat: works at Tue Sep 10 22:45:52 CEST 2002 */
+ if (0!=(u&(1<<16))) u=*(unsigned char const*)r++|(1<<8);
+ *t++=*p++; *t++=-(0==(u&128));
+ u<<=1;
+ } break;
+ case 4:
+ while (p!=psave) {
+ if (0!=(u&(1<<16))) u=*(unsigned char const*)r++|(1<<8);
+ *t++=(p[0]&0xF0)|(0==(u&128)?15:0);
+ *t++=((p[0]&0xF)<<4)|(0==(u&64)?15:0);
+ p++; u<<=2;
+ } break;
+ case 2:
+ while (p!=psave) {
+ if (0!=(u&(1<<16))) u=*(unsigned char const*)r++|(1<<8);
+ *t++=(p[0]&0xC0 )|((u&128)!=0?0:48)|((p[0]&0x30)>>2)|((u&64)!=0?0:3);
+ *t++=((p[0]&0xC)<<4)|((u& 32)!=0?0:48)|((p[0]&0x3 )<<2)|((u&16)!=0?0:3);
+ p++; u<<=4;
+ } break;
+ case 1:
+ while (p!=psave) {
+ u=*(unsigned char const*)r++;
+ *t++=szor1[*(unsigned char const*)p>>4]|szor2[u>>4];
+ *t++=szor1[*(unsigned char const*)p&15]|szor2[u&15];
+ p++;
+ } break;
+ } /* SWITCH Gray bpc */
+ // assert(p-psave+0U==rlena*8U);
+ assert(p>=psave);
+ pp->vi_write(buf, writelen);
+ }
+ } else {
+ /* works at Sun Dec 8 23:30:17 CET 2002 */
+ assert(cache->isRGB());
+ buf=new char[(writelen=((slen_t)wd*bpc+1)>>1)+24];
+ while (psave!=ppend) {
+ t=buf;
+ p=psave; psave+=rlen;
+ assert(psave<=ppend);
+ u=(1<<16);
+#ifndef NDEBUG
+ rend=r+rlena; /* superfluous */
+#endif
+ switch (bpc) {
+ case 8:
+ while (p<psave) {
+ if (0!=(u&(1<<16))) u=*(unsigned char const*)r++|(1<<8);
+ *t++=*p++;
+ *t++=*p++;
+ *t++=*p++;
+ *t++=-(0==(u&128));
+ u<<=1;
+ } break;
+ case 4:
+ while (p<psave) {
+ if (0!=(u&(1<<16))) u=*(unsigned char const*)r++|(1<<8);
+ *t++=p[0]; /* R0 and G0 */
+ *t++=(p[1]&0xF0)|((u&128)!=0?0:15); /* B0 and A0 */
+ *t++=(p[1]<<4)|((p[2]>>4)&15); /* R1 and G1 */
+ *t++=(p[2]<<4)|((u&64)!=0?0:15); /* B1 and A1 */
+ p+=3; u<<=2;
+ } break;
+ case 2:
+ while (p<psave) {
+ if (0!=(u&(1<<16))) u=*(unsigned char const*)r++|(1<<8);
+ /* Dat: p[0]==R0G0B0R1 p[1]==G1B1R2G2 p[2]==B2R3G3B3 */
+ *t++=(p[0]&0xFC)|((u&128)!=0?0:3); /* R0G0B0 and A0 */
+ *t++=(p[0]<<6)|((p[1]>>2)&0x3C)|((u&64)!=0?0:3); /* R1 G1B1 A1 */
+ *t++=(p[1]<<4)|((p[2]>>4)&0x0C)|((u&32)!=0?0:3); /* R2G1 B1 A2 */
+ *t++=(p[2]<<2)|((u&16)!=0?0:3); /* R3G3B3 and A3 */
+ p+=3; u<<=4;
+ } break;
+ default: // case 1:
+ while (p<psave) {
+ u=*(unsigned char const*)r++;
+ /* Dat: p[0]==RGBRGBRG p[1]==BRGBRGBR p[2]==GBRGBRGB */
+ *t++=(p[0]&0xE0)|((u&128)!=0?0:16)
+ |((p[0]>>1)&0xE)|((u&64)!=0?0:1);
+ *t++=(p[0]<<6)|((p[1]>>2)&0x80)|((u&32)!=0?0:16)
+ |((p[1]>>3)&0xE)|((u&16)!=0?0:1);
+ *t++=((p[1]<<4)&0xE0)|((u&8)!=0?0:16)
+ |((p[1]<<3)&0x7)|((p[2]>>5)&0x06)|((u&4)!=0?0:1);
+ *t++=((p[2]<<2)&0xE0)|((u&2)!=0?0:16)
+ |((p[2]<<1)&0x0E)|((u&1)!=0?0:1);
+ p+=3;
+ }
+ break;
+ } /* SWITCH RGB bpc */
+#ifndef NDEBUG
+ assert(r==rend); // r=rend;
+#endif
+ pp->vi_write(buf, writelen);
+ }
+ }
+ delete [] buf;
+ } else pp->vi_write(img->getRowbeg(), rlenht);
+ }
+ pp->vi_write(0,0); /* flush all */
+ if (pp!=cp) delete pp;
+ if (cp!=&vc) delete cp;
+
+ bool refe=false;
+ if (compr==tp.COMPRESSION_JPEG) switch (jp->getColorSpace()) {
+ case Image::Sampled::CS_GRAYSCALE:
+ assert(phot==tp.PHOTOMETRIC_MINISBLACK || phot==tp.PHOTOMETRIC_PALETTE);
+ /* Dat: we don't change `phot' here, so JPEG compression can be applied
+ * to the palette indexes of indexed images :-)
+ */
+ break;
+ case Image::Sampled::CS_RGB: phot=tp.PHOTOMETRIC_RGB; break;
+ case Image::Sampled::CS_YCbCr: phot=tp.PHOTOMETRIC_YCBCR; refe=true; break; /* preferred to RGB */
+ // case Image::Sampled::CS_CMYK: phot=tp.PHOTOMETRIC_SEPARATED; inks=true; break; /* preferred to RGB */
+ default: Error::sev(Error::EERROR) << "TIFF6: color space " << (unsigned)jp->getColorSpace() << " not supported in TIFF-JPEG" << (Error*)0;
+ }
+
+ /* Dat: TIFF tags must appear in increasing numerical order */
+ tp.dirSL(tp.ImageWidth, wd);
+// tp.dirSL(tp.ImageWidth, img->getWd()/2);
+ tp.dirSL(tp.ImageLength, img->getHt());
+ unsigned short s4[]={img->getBpc(),img->getBpc(),img->getBpc(),img->getBpc()};
+ /* ^^^ these values may be different according to the TIFF6 spec, but
+ * libtiff can read TIFF files only with same BitsPerSamples.
+ */
+ unsigned sppa=img->getCpp()+(alpha!=NULLP ? 1:0);
+ tp.dirSHORT(tp.BitsPerSample, sppa, s4);
+ tp.dirSL(tp.Compression, compr); /* SHORT */
+ tp.dirSL(tp.Photometric, phot); /* SHORT */
+ if (cache->Compression==Rule::Cache::CO_Fax) tp.dirSL(tp.FillOrder, 1); /* byte abcdefgh is (a<<7)+...+h */
+ tp.dirLONG(tp.StripOffsets, 8);
+ if (!cache->isIndexed())
+ tp.dirSL(tp.SamplesPerPixel, sppa); /* SHORT */
+// tp.dirSL(tp.SamplesPerPixel, 2); /* SHORT */
+ tp.dirSL(tp.RowsPerStrip, img->getHt());
+ tp.dirLONG(tp.StripByteCounts, vc.getCount());
+ slen_t rats[]={1,1, 0,1, 255,1, 128,1, 255,1, 128,1, 255,1};
+ tp.dirRATIONAL(tp.XResolution, 1, rats);
+ tp.dirRATIONAL(tp.YResolution, 1, rats);
+ tp.dirSL(tp.PlanarConfig, 1); /* SHORT, PLANARCONFIG_CONTIG */
+ if (compr==tp.COMPRESSION_CCITTFAX3) tp.dirLONG(tp.Group3Options, (tp.GROUP3OPT_UNCOMPRESSED)|(or_->cacheHints.K!=0?tp.GROUP3OPT_2DENCODING:0));
+ if (compr==tp.COMPRESSION_CCITTFAX4) tp.dirLONG(tp.Group4Options, tp.GROUP4OPT_UNCOMPRESSED);
+ tp.dirSL(tp.ResolutionUnit, 1); /* SHORT */
+ if (cache->Predictor!=cache->PR_None) {
+ tp.dirSL(tp.Predictor, cache->Predictor); /* 1|2 */
+ if (img->getBpc()!=8)
+ Error::sev(Error::WARNING) << "TIFF6: libtiff supports /Predictor only with bpc=8 and bpc=16" << (Error*)0;
+ }
+
+ if (cache->isIndexed() || cache->isTransparentM()) {
+ unsigned colorlen=(1<<img->getBpc()), i=0;
+ unsigned short *r=new unsigned short[3*colorlen], *g=r+colorlen, *b=g+colorlen;
+ memset(r, '\0', 3*colorlen);
+ /** Image palette data */
+ char const *p=img->getHeadp(), *pend=img->getRowbeg();
+ assert((pend-p)%3==0);
+ assert(3*colorlen>=(unsigned)(pend-p));
+ while (p<pend) {
+ r[i ]=*(unsigned char const*)p++*257;
+ g[i ]=*(unsigned char const*)p++*257;
+ b[i++]=*(unsigned char const*)p++*257;
+ }
+ /* ^^^ In a TIFF palette (ColorMap) 0 is black, 65535 is lightest */
+ tp.dirSHORT(tp.ColorMap, colorlen*3, r);
+ delete [] r;
+ }
+ if (alpha!=NULLP) {
+ /* vvv Dat: GIMP 1.0 load fails with tp.EXTRASAMPLE_UNASSALPHA */
+ tp.dirSL(tp.ExtraSamples, tp.EXTRASAMPLE_ASSOCALPHA); /* SHORT */
+ delete alpha;
+ }
+ /* no tp.InkSet, because no CMYK */
+
+ if (compr==tp.COMPRESSION_JPEG) {
+ tp.dirUNDEFINED(tp.JPEGTables, jp->getJPEGTables().getLength(), jp->getJPEGTables()() /* , 2, "\xFF\xD9" */);
+ const unsigned char hvs=jp->getHVS();
+ if (hvs!=0x22 && phot==tp.PHOTOMETRIC_YCBCR) {
+ const unsigned short horiz_vert[2]={ (unsigned short)((hvs+0U)>>4),
+ (unsigned short)(hvs&15U) };
+ tp.dirSHORT(tp.YCbCrSubsampling, 2, horiz_vert);
+ }
+ if (refe) tp.dirRATIONAL(tp.ReferenceBlackWhite, 6, rats+2);
+ delete jp;
+ }
+
+ tp.dirClose();
+ return Rule::Applier::OK;
+}
+
+Rule::Applier out_tiff_applier = { "TIFF6", out_tiff_check_rule, out_tiff_work, 0 };
+
+
+/* --- Sat Apr 20 11:32:42 CEST 2002 -- Sat Apr 20 16:48:25 CEST 2002 */
+
+#if OBJDEP
+# warning REQUIRES: crc32.o
+# warning REQUIRES: crc32.o
+#endif
+/** Encodes 32-bit (data.length-minus), data, crc32. */
+class LenCRC32Encode: public PSEncoder {
+ public:
+ /** @param maxcpl_: maximum # hex digits per line, should be even */
+ LenCRC32Encode(GenBuffer::Writable &out_, unsigned minus_);
+ virtual void vi_write(char const*buf, slen_t len);
+
+ protected:
+ GenBuffer::Writable &out;
+ unsigned minus;
+ /** The length is not known in advance, so we have to buffer the whole output
+ * in memory.
+ */
+ SimBuffer::B sofar;
+};
+
+LenCRC32Encode::LenCRC32Encode(GenBuffer::Writable &out_, unsigned minus_): out(out_), minus(minus_), sofar("1234") {}
+void LenCRC32Encode::vi_write(char const*buf, slen_t len) {
+ if (len==0) {
+ char *s=const_cast<char*>(sofar());
+ slen_t slen=sofar.getLength();
+ unsigned PTS_INT32_T crc=crc32(CRC32_INITIAL, s+4, slen-4);
+ slen-=minus+4;
+ s[0]=slen>>24; s[1]=slen>>16; s[2]=slen>>8; s[3]=slen;
+ s=sofar.vi_mkend(4);
+ s[0]=crc >>24; s[1]=crc>>16; s[2]=crc>>8; s[3]=crc;
+ out.vi_write(sofar(), sofar.getLength());
+ out.vi_write(0,0);
+ } else sofar.vi_write(buf, len);
+}
+
+/** PNG output (RFC 2083) */
+Rule::Applier::cons_t out_png_check_rule(Rule::OutputRule* or_) {
+ /* Supported PNG types: /Gray1, /Gray2, /Gray4, /Gray8, /Rgb8,
+ * /Indexed1, /Indexed2, /Indexed4, /Indexed8.
+ * Unsupported PNG types: /Gray16, /Rgb16, /GrayA8, /GrayA16, /RgbA8,
+ * /RgbA16.
+ * /Indexed* supports transparency (via PNG chunk tRNS).
+ */
+ Rule::Cache *cache=&or_->cache;
+ if (cache->FileFormat!=cache->FF_PNG
+ ) return Rule::Applier::DONT_KNOW;
+ bool badp=false;
+ /* Dat: (by policy) we don't support /Transparent or /Opaque here; the
+ * user should not specify such SampleFormat in the .job file.
+ */
+ if (!cache->isGray()
+ && !cache->isTransparentM()
+ && !cache->isIndexed()
+ && cache->SampleFormat!=Image::SF_Rgb8) {
+ Error::sev(Error::WARNING_DEFER) << "check_rule: /PNG requires /Gray*, /Indexed*, /Mask, /Transparent+ or /Rgb8" << (Error*)0;
+ badp=true;
+ }
+ if (cache->TransferEncoding!=cache->TE_Binary) {
+ Error::sev(Error::WARNING_DEFER) << "check_rule: /PNG requires /Binary" << (Error*)0;
+ badp=true;
+ }
+ if (cache->Compression!=Rule::Cache::CO_None && cache->Compression!=Rule::Cache::CO_ZIP) {
+ Error::sev(Error::WARNING_DEFER) << "check_rule: /PNG requires /Compression/None or /ZIP" << (Error*)0;
+ badp=true;
+ }
+ if (cache->Predictor==cache->PR_TIFF2) {
+ Error::sev(Error::WARNING_DEFER) << "check_rule: /PNG requires /Predictor >=10" << (Error*)0;
+ badp=true;
+ }
+ if (badp) return Rule::Applier::BAD;
+ /* Now we are sure about Rule::Applier::OK. */
+ or_->cache.WarningOK=true; /* ?? */
+ return Rule::Applier::OK;
+}
+Rule::Applier::cons_t out_png_work(GenBuffer::Writable& out, Rule::OutputRule*or_, Image::SampledInfo *sf) {
+ Rule::Cache *cache=&or_->cache;
+ char tmp[64], colortype; register char*p;
+ unsigned PTS_INT32_T crc;
+
+ // assert(0);
+ if (out_png_check_rule(or_)!=Rule::Applier::OK) return Rule::Applier::DONT_KNOW;
+ or_->doSampleFormat(sf);
+ Image::Sampled *img=sf->getImg();
+ unsigned char bpc=img->getBpc(); /* set _after_ doSampleFormat */
+ Image::Sampled::dimen_t wd=img->getWd(), ht=img->getHt();
+
+ GenBuffer::Writable *rp=new LenCRC32Encode(out,4);
+ GenBuffer::Writable *cp=PSEncoder::newFlateEncode(*rp, (cache->Compression==Rule::Cache::CO_None) ? 0: or_->cacheHints.Effort);
+
+ /* Dat: PredictorColumns, PredictorBPC and PredictorColors are forced to
+ * match the image, because PNG requires it.
+ */
+ GenBuffer::Writable *pp=PSEncoder::newPredictor(
+ *cp,
+ cache->Predictor==cache->PR_None ? cache->PR_PNGNone : cache->Predictor,
+ bpc, /*or_->cacheHints.PredictorBPC*/
+ wd, /*or_->cacheHints.PredictorColumns*/
+ img->getCpp() /*or_->cacheHints.PredictorColors*/
+ );
+
+ /* Critical PNG chunks (capital 1st letter) and ancillary PNG chunks:
+ *
+ * -: zero, 1: exactly one, ?: 0 or 1, *: 0 or more, +: 1 or more
+ * Name Nr sam2p Ordering constraints
+ * IHDR 1 1 Must be first
+ * cHRM ? - Before PLTE and IDAT
+ * gAMA ? - Before PLTE and IDAT
+ * sBIT ? - Before PLTE and IDAT
+ * PLTE ? ? Before IDAT
+ * hIST ? - After PLTE; before IDAT
+ * tRNS ? ? After PLTE; before IDAT
+ * bKGD ? ? After PLTE; before IDAT
+ * pHYs ? - Before IDAT
+ * tIME ? - None
+ * tEXt * - None
+ * zTXt * - None
+ * IDAT + 1 After IHDR and PLTE, multiple IDATs must be consecutive
+ * IEND 1 1 Must be last
+ */
+
+ /* 0..3: PNG header */
+ /* 8..11: IHDR chunk length */
+ /* 12..15: IHDR chunk name */
+ memcpy(tmp,"\211PNG\r\n\032\n\0\0\0\015IHDR",16); /* ASCII charset is assumed. */
+ p=tmp+16;
+ *p++=wd>>24; *p++=wd>>16; *p++=wd>>8; *p++=wd; /* 16: Width */
+ *p++=ht>>24; *p++=ht>>16; *p++=ht>>8; *p++=ht; /* 20: Height */
+ *p++=bpc; /* 24: Bit depth */
+ colortype=*p++=cache->isGray()?0:cache->isRGB()?2:3; /* 25: Color type */
+ *p++=0; /* 26: Compression method: deflate/32K (forced by PNG spec), overcoming with Effort==0 */
+ *p++=0; /* 27: Filter type: adaptive filtering with 5 basic PNG filter types */
+ *p++=0; /* 28: Non-interlaced */
+ crc=crc32(CRC32_INITIAL, tmp+12, 17);
+ *p++=crc>>24;*p++=crc>>16;*p++=crc>>8;*p++=crc; /* 29: IHDR CRC */
+ out.vi_write(tmp, 33);
+ if (colortype==3) {
+ bool transp=cache->isTransparentM() && PTS_dynamic_cast(Image::Indexed*,img)->getTransp()>=0;
+ /* unsigned ncols=PTS_dynamic_cast(Image::Indexed*,img)->getNcols(); */
+ unsigned ncols3=img->getRowbeg()-img->getHeadp();
+
+ p=tmp;
+ *p++=0; *p++=0; *p++=ncols3>>8; *p++=ncols3; /* 0: PLTE chunk length */
+ *p++='P'; *p++='L'; *p++='T'; *p++='E'; /* 4: PLTE chunk name */
+ out.vi_write(tmp, 8);
+ if (transp) {
+ PTS_dynamic_cast(Image::Indexed*,img)->makeTranspZero();
+ p=img->getHeadp(); p[0]=p[1]=p[2]=(char)0; /* force black backround (for consistency) */
+ }
+ out.vi_write(img->getHeadp(), ncols3);
+ crc=crc32(crc32(CRC32_INITIAL,tmp+4,4), img->getHeadp(), ncols3);
+ p=tmp; *p++=crc>>24;*p++=crc>>16;*p++=crc>>8;*p++=crc; /* 0: PLTE CRC */
+ out.vi_write(tmp, 4);
+ if (transp) {
+ out.vi_write("\0\0\0\1tRNS\0@\346\330f", 13); /* color 0 is transparent */
+ //fprintf(stderr, "tRNS: 0x%08lx", (unsigned long)crc32(CRC32_INITIAL,"tRNS\0",5)); /* 0x40e6d866 */
+ out.vi_write("\0\0\0\1bKGD\0\210\5\35H", 13); /* color 0 is background color */
+ //out.vi_write("\0\0\0\1bKGD\2\x66\x0b\x7c\x64", 13); /* color 2 is background color */
+ //fprintf(stderr, "bKGD: 0x%08lx", (unsigned long)crc32(CRC32_INITIAL,"bKGD\2",5)); /* 0x88051d48 */
+ }
+ }
+
+ slen_t rlenht=img->getRlen()*img->getHt();
+ #if 0 /* Calculates _bad_ CRC (before compression etc.) */
+ p=tmp;
+ *p++=rlenht>>24; *p++=rlenht>>16; *p++=rlenht>>8; *p++=rlenht; /* 0: IDAT chunk length */
+ *p++='I'; *p++='D'; *p++='A'; *p++='T'; /* 4: IDAT chunk name */
+ out.vi_write(tmp, 8);
+ if (rlenht!=0) pp->vi_write(img->getRowbeg(), rlenht);
+ pp->vi_write(0,0); /* flush all, write CRC */
+ crc=crc32(crc32(CRC32_INITIAL,tmp+4,4), img->getRowbeg(), rlenht);
+ p=tmp; *p++=crc>>24;*p++=crc>>16;*p++=crc>>8;*p++=crc; /* 0: IDAT CRC */
+ out.vi_write(tmp, 4);
+ #else
+ rp->vi_write("IDAT",4);
+ if (rlenht!=0) pp->vi_write(img->getRowbeg(), rlenht);
+ pp->vi_write(0,0); /* flush all, write CRC */
+ #endif
+
+ out.vi_write("\0\0\0\0IEND\256B`\202",12); /* IEND chunk */
+ delete pp;
+ delete cp;
+ delete rp;
+
+ return Rule::Applier::OK;
+}
+
+Rule::Applier out_png_applier = { "PNG", out_png_check_rule, out_png_work, 0 };
+
+/* --- Sat Jun 15 19:30:41 CEST 2002 */
+
+/** BMP RLE compression, type 1. Seems to be optimal.
+ * @param dst buffer with enough place for compressed data. The caller must
+ * pre-allocate >=(send-sbeg)+(send-sbeg+128)*2/255.
+ * @param sbeg first raw data char to compress
+ * @param send char to finish compression just before
+ * @return dst+(number of characters occupied by compressed data)
+ *
+ * in-memory implementation Sun Jun 23 20:02:41 CEST 2002
+ */
+
+static char *bmp_compress1_row(char *dst, char const *sbeg, char const *send) {
+ #if 0
+ # define BMP_ASSERT(x) assert(x)
+ #else
+ # define BMP_ASSERT(x)
+ #endif
+ #undef BUF
+ #define BUF(x) (*(x))
+ #undef PUTCH__
+ #define PUTCH__(c) (*dst++=(c))
+ char c, c2;
+ char const *beg, *end, *rend, *q, *r, *best;
+ signed bestca, rca; /* both must fit into -255..255 */
+ slen_t frl, efrl;
+ int ci;
+ // bool oddp;
+
+ beg=sbeg;
+ end=(send-sbeg>255) ? beg+255 : send;
+
+ while (beg!=end) { /* there is still unprocessed data in the buffer */
+ c=BUF(beg++);
+ if (beg==end) { PUTCH__(1); PUTCH__(c); break; } /* last char */
+ if (c==BUF(beg)) { /* sure r chunk */
+ ci=2; beg++;
+ rep:
+ while (beg!=end && c==BUF(beg)) { beg++; ci++; }
+ PUTCH__(ci); PUTCH__(c); /* r chunk */
+ } else { /* possible c chunk */
+ rend=end;
+ BMP_ASSERT(end-beg<=254);
+ if (end!=send) { /* read an extra char as the terminator of the last run-length of c, buf:0..254 */
+ end++;
+ BMP_ASSERT(end-beg==255); /* buffer is full (255 chars) */
+ }
+
+ best=r=beg;
+ bestca=rca=-1; /* best and current advantage of c over r */
+
+ while (r!=rend) { /* c chunk should stop only at run-length boundaries */
+ BMP_ASSERT(-255<=rca && rca<=255);
+ BMP_ASSERT(-255<=bestca && bestca<=255);
+ q=r; r=q+1; ci=1; while (r!=end && BUF(r)==BUF(q)) { r++; ci++; }
+ if (r==end && end!=rend) break;
+ if (((r-beg)&1)==0) { /* odd (!) copy length */
+ rca+=3-ci;
+ if (rca<=bestca-1) { r--; break; } /* fix-5 (instead of rule-4): `xyz|bbbbb|xyz|', `abcdef|gggggggg|abababababab|', `abcdef|ggg|hhh|ggg|hhh|ggg|hhh|ggg|hhh|abababababab|' */
+ if (bestca<rca) { bestca=rca; best=r-1; } /* make c as short as possible */
+ rca--;
+ } else { /* even copy length */
+ rca+=2-ci;
+ if (rca<=bestca-2) break; /* fix-5 (instead of rule-4): `xyz|bbbbb|xyz|', `abcdef|gggggggg|abababababab|', `abcdef|ggg|hhh|ggg|hhh|ggg|hhh|ggg|hhh|abababababab|' */
+ if (bestca<rca) { bestca=rca; best=r; } /* make c as short as possible */
+ }
+ }
+ BMP_ASSERT(-255<=rca && rca<=255);
+ BMP_ASSERT(-255<=bestca && bestca<=255);
+ if (bestca<=0 /* no possible positive advantage */
+ || best-beg<=1 /* 1: c is one char, plus 1 char in buf. Imp: ==1?! */
+ ) { ci=1; goto rep; }
+ r=best; /* Imp: get rid of this assignment */
+ BMP_ASSERT(beg!=r);
+ BMP_ASSERT(((r-beg)&1)==1); /* even copy length */
+
+ if (end==r) { /* no followers, last chunk */
+ /* BMP_ASSERT(had_eof); */
+ // oddp=(1+(r-beg)&1)==1;
+ PUTCH__(0);
+ PUTCH__((r-beg)+1);
+ PUTCH__(c);
+ while (beg!=r) { PUTCH__(BUF(beg)); beg++; } /* emit c chunk */
+ // if (oddp) PUTCH__(0); /* Imp: padding breaks optimality */
+ } else {
+ BMP_ASSERT(r!=end);
+ /* BMP_ASSERT(r!=rend); */ /* r==rend is possible here */
+ c2=BUF(r); frl=1; q=r+1;
+ while (q!=end && c2==BUF(q)) { q++; frl++; } /* count follower run length */
+ efrl=frl; ci=-2; if (q==end) { /* Imp: get rid of -2 (-2 -> -1) */
+ BMP_ASSERT(q==end);
+ while ((ci=(q==send)?-1:(unsigned char)*q++)!=-1 && (char)ci==c2) efrl++;
+ }
+
+ /* printf("clen=%u\n", clen); */
+ if (1+(r>beg ? r-beg : 256+beg-r)<255 && efrl>=256 && efrl%255==1) { r++; efrl--; } /* make the c chunk one char longer if appropriate */
+
+ // oddp=(1+(r-beg)&1)==1;
+ PUTCH__(0);
+ PUTCH__(1+(r-beg));
+ PUTCH__(c);
+ while (beg!=r) { PUTCH__(BUF(beg)); beg++; } /* emit c chunk */
+ // if (oddp) PUTCH__(0); /* Imp: padding breaks optimality */
+
+ beg=q; /* remove beginning of the r chunk from the buffer */
+ if (ci>=0) { beg--; BMP_ASSERT((unsigned char)BUF(beg)==ci); }
+
+ while (efrl>=255) { PUTCH__('\377'); PUTCH__(c2); efrl-=255; } /* emit full r chunks */
+ if (efrl>=2) { /* emit last r chunk */
+ PUTCH__(efrl); PUTCH__(c2);
+ } else if (efrl!=0) {
+ BMP_ASSERT(efrl==1);
+ beg--; /* leave a single instance of c2 in beginning of the buffer */
+ BMP_ASSERT(BUF(beg)==c2);
+ }
+ } /* IF c chunk has followers */
+ } /* IF r or c chunk */
+ end=(send-beg>255) ? beg+255 : send;
+ } /* WHILE main loop */
+ return dst;
+ #undef BUF
+ #undef PUTCH__
+}
+
+
+/** Windows Bitmap BMP output */
+Rule::Applier::cons_t out_bmp_check_rule(Rule::OutputRule* or_) {
+ /* Supported BMP types: /Rgb8,
+ * /Indexed1, /Indexed4, /Indexed8.
+ */
+ Rule::Cache *cache=&or_->cache;
+ if (cache->FileFormat!=cache->FF_BMP
+ ) return Rule::Applier::DONT_KNOW;
+ bool badp=false;
+ /* Dat: (by policy) we don't support /Transparent or /Opaque here; the
+ * user should not specify such SampleFormat in the .job file.
+ */
+ if (cache->SampleFormat!=Image::SF_Indexed1
+ /* Dat: /Indexed2 is not supported by /BMP */
+ && cache->SampleFormat!=Image::SF_Indexed4
+ && cache->SampleFormat!=Image::SF_Indexed8
+ && cache->SampleFormat!=Image::SF_Rgb8) {
+ Error::sev(Error::WARNING_DEFER) << "check_rule: /BMP requires /Indexed1, /Indexed4, /Indexed8 or /Rgb8" << (Error*)0;
+ badp=true;
+ }
+ if (cache->TransferEncoding!=cache->TE_Binary) {
+ Error::sev(Error::WARNING_DEFER) << "check_rule: /BMP requires /Binary" << (Error*)0;
+ badp=true;
+ }
+ if (cache->Compression!=Rule::Cache::CO_None && cache->Compression!=Rule::Cache::CO_RLE) {
+ Error::sev(Error::WARNING_DEFER) << "check_rule: /BMP requires /Compression/None or /RLE" << (Error*)0;
+ badp=true;
+ }
+ if (cache->Compression==Rule::Cache::CO_RLE && cache->SampleFormat!=Image::SF_Indexed8) {
+ /* !! Imp: Implement compr==2 for /Indexed4 */
+ Error::sev(Error::WARNING_DEFER) << "check_rule: /BMP/RLE requires /Indexed8" << (Error*)0;
+ badp=true;
+ }
+ if (cache->hasPredictor()) {
+ Error::sev(Error::WARNING_DEFER) << "check_rule: /BMP requires /Predictor 1" << (Error*)0;
+ badp=true;
+ }
+ if (badp) return Rule::Applier::BAD;
+ /* Now we are sure about Rule::Applier::OK. */
+ return Rule::Applier::OK;
+}
+Rule::Applier::cons_t out_bmp_work(GenBuffer::Writable& out, Rule::OutputRule*or_, Image::SampledInfo *sf) {
+ if (out_bmp_check_rule(or_)!=Rule::Applier::OK) return Rule::Applier::DONT_KNOW;
+ or_->doSampleFormat(sf);
+ Image::Sampled *img=sf->getImg();
+ Image::Sampled::dimen_t wd=img->getWd(), ht=img->getHt(), htc=ht;
+ slen_t rlen=img->getRlen();
+ char const*pend=img->getRowbeg()+rlen*ht;
+ char const*palbeg=img->getHeadp(), *palend=img->getRowbeg();
+ slen_t ncols4=(palend-palbeg)/3*4;
+ unsigned biCompr=or_->cache.Compression!=or_->cache.CO_RLE ? 0
+ : or_->cache.SampleFormat==Image::SF_Indexed4 ? 2 : 1;
+
+ SimBuffer::B data;
+ slen_t crowsize=2+ rlen+(rlen+128)*2/255; /* !! Imp: real upper bound? */
+ char *crow=new char[crowsize];
+ /* !! GIMP compatibility */
+ if (or_->cache.Compression==or_->cache.CO_RLE) {
+ /* Imp: bmp_compress2_row */
+ char *crow2;
+ while (htc--!=0) { /* BMP stores rows from down */
+ crow2=bmp_compress1_row(crow, pend-rlen, pend);
+#if 0
+ crow2=crow;
+ *crow2++=10;
+ *crow2++=1;
+ *crow2++=10;
+ *crow2++=2;
+ *crow2++=10;
+ *crow2++=3;
+ *crow2++=10;
+ *crow2++=4;
+ *crow2++=10;
+ *crow2++=5;
+ *crow2++=10;
+ *crow2++=6;
+#endif
+
+ assert((slen_t)(crow2-crow)<=crowsize-2);
+ pend-=rlen;
+ *crow2++='\0'; *crow2++='\0'; /* signal end of compressed data row */
+ /* fprintf(stderr, "htc=%u cl=%u\n", htc, crow2-crow); */
+ data.vi_write(crow, crow2-crow);
+ }
+ data.vi_write("\0\1", 2); /* signal end of bitmap */
+ } else {
+ unsigned pad=(4-(rlen&3))&3; /* Dat: pad rows to 32 bits */
+ if (or_->cache.SampleFormat==Image::SF_Rgb8) { /* SWAP RGB values */
+ /* BUGFIX at Thu Dec 12 21:36:57 CET 2002 */
+ char *buf=new char[rlen];
+ while (htc--!=0) { /* BMP stores rows from down */
+ char const*pxend=pend, *px=pend-=rlen;
+ char *q=buf;
+ while (px!=pxend) {
+ *q++=px[2];
+ *q++=px[1];
+ *q++=px[3];
+ px+=3;
+ }
+ data.vi_write(buf, rlen);
+ if (pad!=0) data.vi_write("\0\0\0", pad);
+ }
+ delete [] buf;
+ } else {
+ while (htc--!=0) { /* BMP stores rows from down */
+ data.vi_write(pend-=rlen, rlen);
+ if (pad!=0) data.vi_write("\0\0\0", pad);
+ }
+ }
+ }
+ assert(pend==img->getRowbeg());
+ delete [] crow;
+ /* Now data is ready. */
+
+ char *bmphead=new char[54+ncols4+data.getLength()], *p=bmphead;
+ *p++='B'; *p++='M'; /* magic number header */
+ lf32(p, 54+ncols4+data.getLength()); /* bfSize */
+ lf32(p, 0); /* zzHotX, zzHotY */
+ lf32(p, 54+ncols4); /* bfOffs */
+ lf32(p, 40); /* biSize==40 => Windows 3.x style BMP file */
+ lf32(p, wd); /* biWidth */
+ lf32(p, ht); /* biHeight */
+ lf16(p, 1); /* biPlanes, must be 1 */
+ lf16(p, img->getBpc()*img->getCpp()); /* biBitCnt: bits per pixel (1, 4, 8: /Indexed*; 24: /Rgb8) */
+ lf32(p, biCompr); /* biCompr */
+ lf32(p, 0); /* biSizeIm */
+ lf32(p, 0); /* biXPels */
+ lf32(p, 0); /* biYPels */
+ lf32(p, (palend-palbeg)/3); /* biClrUsed */
+ lf32(p, (palend-palbeg)/3); /* biClrImp */
+ /* vvv Now comes the palette (zero length for /Rgb) */
+ while (palbeg!=palend) {
+ *p++=palbeg[2]; *p++=palbeg[1]; *p++=palbeg[0]; *p++='\0';
+ palbeg+=3;
+ }
+ assert((slen_t)(p-bmphead)==54+ncols4);
+
+ out.vi_write(bmphead, p-bmphead); delete [] bmphead;
+#if 0
+ out.vi_write("XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX",
+ 100);
+ out.vi_write("XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX",
+ 100);
+ out.vi_write("XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX",
+ 100);
+ out.vi_write("XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX",
+ 100);
+ out.vi_write("XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX",
+ 100);
+#endif
+ out << data;
+ out.vi_write(0,0); /* signal EOF */
+
+ return Rule::Applier::OK;
+}
+
+Rule::Applier out_bmp_applier = { "BMP", out_bmp_check_rule, out_bmp_work, 0 };
+
+/* --- Sun Mar 24 13:48:57 CET 2002 */
+
+/** The Empty applier produces an empty output file. */
+Rule::Applier::cons_t out_empty_check_rule(Rule::OutputRule* or_) {
+ Rule::Cache *cache=&or_->cache;
+ if (cache->FileFormat!=cache->FF_Empty
+ ) return Rule::Applier::DONT_KNOW;
+ return Rule::Applier::OK;
+}
+Rule::Applier::cons_t out_empty_work(GenBuffer::Writable& out, Rule::OutputRule*or_, Image::SampledInfo *sf) {
+ (void)out;
+ (void)sf;
+ if (out_empty_check_rule(or_)!=Rule::Applier::OK) return Rule::Applier::DONT_KNOW;
+ return Rule::Applier::OK;
+}
+
+Rule::Applier out_empty_applier = { "Empty", out_empty_check_rule, out_empty_work, 0 };
+
+/* --- Sun Mar 24 13:48:57 CET 2002 */
+
+/** The Meta applier writes some meta-information into the output file */
+Rule::Applier::cons_t out_meta_check_rule(Rule::OutputRule* or_) {
+ Rule::Cache *cache=&or_->cache;
+ if (cache->FileFormat!=cache->FF_Meta
+ ) return Rule::Applier::DONT_KNOW;
+ // return Rule::Applier::OK; /* Imp: implement the applier */
+ return Rule::Applier::BAD;
+}
+Rule::Applier::cons_t out_meta_work(GenBuffer::Writable& out, Rule::OutputRule*or_, Image::SampledInfo *sf) {
+ (void)out;
+ (void)sf;
+ if (out_meta_check_rule(or_)!=Rule::Applier::OK) return Rule::Applier::DONT_KNOW;
+ /* Imp: real content here */
+ return Rule::Applier::OK;
+}
+
+Rule::Applier out_meta_applier = { "Meta", out_meta_check_rule, out_meta_work, 0 };
+
+/* __END__ */
diff --git a/graphics/sam2p/at_bitmap.h b/graphics/sam2p/at_bitmap.h
new file mode 100644
index 0000000000..e76dc91207
--- /dev/null
+++ b/graphics/sam2p/at_bitmap.h
@@ -0,0 +1,73 @@
+/* This code is ripped from Autotrace-0.29, but modified by pts. */
+
+/* bitmap.h: definition for a bitmap type. No packing is done by
+ default; each pixel is represented by an entire byte. Among other
+ things, this means the type can be used for both grayscale and binary
+ images. */
+
+#ifndef AT_BITMAP_H
+#define AT_BITMAP_H
+
+#ifdef __GNUC__
+#ifndef __clang__
+#pragma interface
+#endif
+#endif
+
+#define PTS_SAM2P 1
+#define FATALP(m) Error::sev(Error::EERROR) << m << (Error*)0;
+#define WARNINGP(m) Error::sev(Error::WARNING) << m << (Error*)0;
+#define FATALP1(m,a) Error::sev(Error::EERROR) << m << a << (Error*)0;
+#define WARNINGP1(m,a) Error::sev(Error::WARNING) << m << a << (Error*)0;
+#define FATALP3(m,a,n,b,o,c,p) Error::sev(Error::EERROR) << m << a << n << b << o << c << p << (Error*)0;
+#define WARNINGP3(m,a,n,b,o,c,p) Error::sev(Error::WARNING) << m << n << b << o << c << p << (Error*)0;
+
+#define XMALLOCT(var,typep,size) var=(typep)new char[size]
+#define XFREE(p) delete [] (char*)(p)
+/* ^^^ Imp: arrays?? */
+
+typedef unsigned at_dimen_t; /**** pts ****/
+
+/* #include "autotrace.h" */
+typedef char *at_string;
+typedef struct _at_bitmap_type {
+ at_dimen_t height;
+ at_dimen_t width;
+ unsigned char *bitmap;
+ unsigned int np;
+} at_bitmap_type;
+
+#include <stdio.h>
+
+#define xfclose(fd,dummy) fclose(fd)
+
+/* The basic structure and macros to access it. */
+typedef at_bitmap_type bitmap_type;
+
+/* The number of color planes of each pixel */
+#define BITMAP_PLANES(b) ((b).np)
+
+/* The pixels, represented as an array of bytes (in contiguous storage).
+ Each pixel is represented by np bytes. */
+#define BITMAP_BITS(b) ((b).bitmap)
+
+/* These are convenient abbreviations for geting inside the members. */
+#define BITMAP_WIDTH(b) ((b).width)
+#define BITMAP_HEIGHT(b) ((b).height)
+
+/* This is the pixel at [ROW,COL]. */
+#define BITMAP_PIXEL(b, row, col) \
+ ((BITMAP_BITS (b) + (row) * BITMAP_PLANES (b) * BITMAP_WIDTH (b) \
+ + (col) * BITMAP_PLANES(b)))
+
+#define BITMAP_VALID_PIXEL(b, row, col) \
+ ((row) < BITMAP_HEIGHT (b) && (col) < BITMAP_WIDTH (b))
+
+/* Allocate storage for the bits, set them all to white, and return an
+ initialized structure. */
+extern bitmap_type new_bitmap (at_dimen_t, at_dimen_t);
+
+/* Free that storage. */
+extern void free_bitmap (bitmap_type *);
+
+#endif /* not AT_BITMAP_H */
diff --git a/graphics/sam2p/bts.ttt b/graphics/sam2p/bts.ttt
new file mode 100644
index 0000000000..a2dadcc885
--- /dev/null
+++ b/graphics/sam2p/bts.ttt
@@ -0,0 +1,1602 @@
+%
+% bts.ttt -- Built-in TemplateS, contains most .tte and .ttm files
+% by pts@math.bme.hu at Wed Apr 17 10:37:42 CEST 2002
+% Sat Jun 1 18:40:04 CEST 2002
+% ADSC fixups at Sun Jun 23 18:16:29 CEST 2002
+% fixed %%EndComments, bts2.ttt at Sun Sep 22 14:25:45 CEST 2002
+% /l148z, /l1thl at ...
+%
+% These OutputFile-generation templates will be built in to the sam2p
+% executable at compile time. The contents of this file can be referenced as
+% `(%bts) run' in .job files.
+%
+
+% _l23_
+/l23 (%!PS-Adobe-3.0`E
+%%Pages: 1
+`X%%DocumentData: `B
+%%LanguageLevel: `0
+%%EndComments
+%%Page: 1 1
+save`s 9 dict begin
+{/T currentfile`T def`1setcolorspace
+/F T`F def
+<</ImageType 1/Width `w/Height `h/BitsPerComponent
+`b/ImageMatrix[1 0 0 -1 0 `h]/Decode
+[`D]/DataSource F>> image
+`t}
+%%BeginData:;
+exec
+`S
+%%EndData
+end restore showpage
+%%Trailer
+%%EOF\n)
+
+% _l23_
+/l23mask (%!PS-Adobe-3.0`E
+%%Pages: 1
+`X%%DocumentData: `B
+%%LanguageLevel: `0
+%%EndComments
+%%Page: 1 1
+save`s 9 dict begin
+{`r setrgbcolor
+/T currentfile`T def
+/F T`F def
+`w `h false[1 0 0 -1 0 `h]F imagemask
+`t}
+%%BeginData:;
+exec
+`S
+%%EndData
+end restore showpage
+%%Trailer
+%%EOF\n)
+
+% _l23_
+/l23ind1 (%!PS-Adobe-3.0`E
+%%Pages: 1
+`X%%DocumentData: `B
+%%LanguageLevel: `0
+%%EndComments
+%%Page: 1 1
+save`s 9 dict begin
+{`R/T currentfile`T def
+/F T`F def
+`w `h true[1 0 0 -1 0 `h]F imagemask
+`t}
+%%BeginData:;
+exec
+`S
+%%EndData
+end restore showpage
+%%Trailer
+%%EOF\n)
+
+% Dat: vvv last color not necessarily transparent
+% T `P string readstring pop dup length 0 exch 3 sub getinterval
+% Used by /Transparent2, /Transparent4 and /Transparent8.
+% This implemetation does:
+% rgb-palette imagemask-newcompress-transfer
+% Alternative implementation (not this one!):
+% ( rgb-transfer imagemask-newcompress-transfer )*
+% It would be tedious to flush buffers etc.
+% Doesn't work with JPEG compressions, because JPEG requires a bit depth of
+% 8. Works with any other /Compression and any /Predictor.
+% _l23_
+/l23tran2 (%!PS-Adobe-3.0`E
+%%Pages: 1
+`X%%DocumentData: `B
+%%LanguageLevel: `0
+%%EndComments
+%%Page: 1 1
+save`s 9 dict begin
+{/T currentfile`T def
+T `P string readstring pop 0 `p getinterval
+/F T`F def
+/m 0 def
+{255 div m 1 add dup 3 eq{pop setrgbcolor
+`w `h false[1 0 0 -1 0 `h]F imagemask
+0}if/m exch def}forall
+`t}
+%%BeginData:;
+exec
+`S
+%%EndData
+end restore showpage
+%%Trailer
+%%EOF\n)
+
+% _l23_
+% With old (pre-Wed Feb 5 17:46:59 CET 2003) PDF code, /Length was one less,
+% because it hasn't counted the last \n newline in the content stream. This
+% made a problem with pdfTeX 0.12 shipped with Debian Slink.
+% Old code (focus on the \n's)
+%[ (3 0 obj\n<</Length ) ] %1
+%-4 %2: length of chunk 4
+%(>>\nstream\n) %3
+%[ (q`s\n`w 0 0 `h 0 0 cm /S Do Q) ] %4.0
+%(\nendstream\nendobj\n) %5
+% At Fri Feb 7 11:56:14 CET 2003 modified all /MediaBox specifications to
+% precede the image data, and be in a separate line, to ease parsing.
+% vvv tested at Sat Jan 8 12:31:00 CET 2005
+/p02 [%sam2p-ttm; by pts@fazekas.hu at Sat Apr 20 18:33:30 CEST 2002
+(%PDF-1.`0\n`B) %0
+[ (2 0 obj\n<</Type/Pages/Kids[5 0 R]/Count 1>>\nendobj\n) ] %1
+[ (3 0 obj\n<</Length ) ] %2
+-5 %3: length of chunk 5
+(>>\nstream\n) %4
+[ (q`s\n`w 0 0 `h 0 0 cm /S Do Q\n) ] %5.0
+(endstream\nendobj\n) %6
+[ (1 0 obj\n<</Type/Catalog/Pages 2 0 R>>\nendobj\n) ] %7.0
+[ (4 0 obj\n<</Length ) ] %8.0
+-11 %9
+(/Interpolate false/Type/XObject/Name/S/Subtype/Image/ColorSpace`1/Width
+`w/Height `h/BitsPerComponent `b`F>>stream\n) %10
+[ (`S) ] %11
+(\nendstream\nendobj\n) %12
+[ (5 0 obj\n<</Type/Page/MediaBox[`X]
+/CropBox[`X]/Parent 2 0 R/Resources<</XObject<</S
+4 0 R>>/ProcSet[/PDF`C]>>/Contents 3 0 R>>\n endobj\n) ] % 13
+(xref\n0 6\n0000000000 65535 f \n) %14
+7 %15
+( 00000 n \n) %16
+1 %17
+( 00000 n \n) %18
+2 %19
+( 00000 n \n) %20
+8 %21
+( 00000 n \n) %22
+13 %23
+( 00000 n \ntrailer\n<</Size 6/Root 1 0 R>>\nstartxref\n) %24
+14 %25
+(\n%%EOF\n) %26
+]
+
+% _l23_
+% vvv tested at Sat Jan 8 12:31:00 CET 2005
+/p02mask [%sam2p-ttm; by pts@fazekas.hu at Sat Apr 20 20:34:35 CEST 2002
+(%PDF-1.`0\n`B) %0
+[ (2 0 obj\n<</Type/Pages/Kids[5 0 R]/Count 1>>\nendobj\n) ] %1
+[ (3 0 obj\n<</Length ) ] %2
+-5 %3: length of chunk 5
+(>>\nstream\n) %4
+[ (q`s\n`g rg `w 0 0 `h 0 0 cm /S Do Q\n) ] %5.0
+(endstream\nendobj\n) %6
+[ (1 0 obj\n<</Type/Catalog/Pages 2 0 R>>\nendobj\n) ] %7.0
+[ (4 0 obj\n<</Length ) ] %8.0
+-11 %9
+(/Interpolate false/Type/XObject/Name/S/Subtype/Image/ImageMask
+true/BitsPerComponent 1/Width `w/Height `h`F>>stream\n) %10
+[ (`S) ] %11
+(\nendstream\nendobj\n) %12
+[ (5 0 obj\n<</Type/Page
+/MediaBox[`X]
+/CropBox[`X]/Parent 2 0 R/Resources<</XObject<</S
+4 0 R>>/ProcSet[/PDF`C]>>/Contents
+3 0 R>>\nendobj\n) ] %14
+(xref\n0 6\n0000000000 65535 f \n) %15
+7 %16
+( 00000 n \n) %17
+1 %18
+( 00000 n \n) %19
+2 %20
+( 00000 n \n) %21
+8 %22
+( 00000 n \n) %21
+13 %22
+( 00000 n \ntrailer\n<</Size 6/Root 1 0 R>>\nstartxref\n) %23
+14 %24
+(\n%%EOF\n) %25
+]
+
+% _l23_
+% vvv tested at Sat Jan 8 12:31:00 CET 2005
+/p02maskbb [%sam2p-ttm; by pts@fazekas.hu at Sat Apr 20 18:36:35 CEST 2002
+(%PDF-1.`0\n`B) %0
+[ (2 0 obj\n<</Type/Pages/Kids[4 0 R]/Count 1>>\nendobj\n) ] %1
+[ (3 0 obj\n<</Length ) ] %2
+-5 %3: length of chunk 5
+(>>\nstream\n) %4
+[ (q`s\n`g rg `w 0 0 `h 0 0 cm\nBI/W `w/H `h/ImageMask true/BPC 1`F ID
+`S
+EI\nQ\n) ] %5.0
+(endstream\nendobj\n) %6
+[ (1 0 obj\n<</Type/Catalog/Pages 2 0 R>>\nendobj\n) ] %7.0
+[ (4 0 obj\n<</Type/Page/MediaBox[`X]
+/CropBox[`X]/Parent 2 0 R/Resources<</ProcSet[/PDF`C]>>/Contents
+3 0 R>>\nendobj\n) ] %8
+(xref\n0 5\n0000000000 65535 f \n) %9
+7 %10: offset of chunk 7, printf("%010u")
+( 00000 n \n) %11
+1 %12
+( 00000 n \n) %13
+2 %14
+( 00000 n \n) %15
+8 %16
+( 00000 n \ntrailer\n<</Size 5/Root 1 0 R>>\nstartxref\n) %17
+9 %18
+(\n%%EOF\n) %19
+]
+
+% _l23_
+/p02ind1 [%sam2p-ttm; by pts@fazekas.hu at Sat Apr 20 20:34:35 CEST 2002
+% vvv tested at Sat Jan 8 12:31:00 CET 2005
+(%PDF-1.`0\n`B) %0
+[ (2 0 obj\n<</Type/Pages/Kids[5 0 R]/Count 1>>\nendobj\n) ] %1
+[ (3 0 obj\n<</Length ) ] %2
+-5 %3: length of chunk 5
+(>>\nstream\n) %4
+% `G rg 0 0 `w `h re B
+[ (q`s
+`G rg 0 0 m `w 0 l `w `h l 0 `h l F
+`g rg
+`w 0 0 `h 0 0 cm /S Do Q\n) ] %5.0
+(endstream\nendobj\n) %6
+[ (1 0 obj\n<</Type/Catalog/Pages 2 0 R>>\nendobj\n) ] %7.0
+[ (4 0 obj\n<</Length ) ] %8.0
+-11 %9
+(/Interpolate false/Type/XObject/Name/S/Subtype/Image/ImageMask
+true/BitsPerComponent 1/Width `w/Height `h`F>>stream\n) %10
+[ (`S) ] %11
+(\nendstream\nendobj\n) %12
+[ (5 0 obj\n<</Type/Page
+/MediaBox[`X]
+/CropBox[`X]/Parent 2 0 R/Resources<</XObject<</S
+4 0 R>>/ProcSet[/PDF`C]>>/Contents
+3 0 R>>\nendobj\n) ] %13
+(xref\n0 6\n0000000000 65535 f \n) %14
+7 %15
+( 00000 n \n) %16
+1 %16
+( 00000 n \n) %17
+2 %18
+( 00000 n \n) %18
+8 %19
+( 00000 n \n) %20
+13 %21
+( 00000 n \ntrailer\n<</Size 6/Root 1 0 R>>\nstartxref\n) %22
+14 %23
+(\n%%EOF\n) %24
+]
+
+% _l23_
+% vvv tested at Sat Jan 8 12:31:00 CET 2005
+/p02ind1bb [%sam2p-ttm; by pts@fazekas.hu at Sat Apr 20 18:36:35 CEST 2002
+(%PDF-1.`0\n`B) %0
+[ (2 0 obj\n<</Type/Pages/Kids[4 0 R]/Count 1>>\nendobj\n) ] %1
+[ (3 0 obj\n<</Length ) ] %2
+-5 %3: length of chunk 5
+(>>\nstream\n) %4
+% `G rg 0 0 `w `h re B
+[ (q`s
+`G rg 0 0 m `w 0 l `w `h l 0 `h l F
+`g rg `w 0 0 `h 0 0 cm\nBI/W `w/H `h/ImageMask true/BPC 1`F ID
+`S
+EI\nQ\n) ] %5.0
+(endstream\nendobj\n) %6
+[ (1 0 obj\n<</Type/Catalog/Pages 2 0 R>>\nendobj\n) ] %7.0
+[ (4 0 obj\n<</Type/Page
+/MediaBox[`X]
+/CropBox[`X]/Parent 2 0 R/Resources<</ProcSet[/PDF`C]>>/Contents
+3 0 R>>\nendobj\n) ] %8
+(xref\n0 5\n0000000000 65535 f \n) %9
+7 %10: offset of chunk 7, printf("%010u")
+( 00000 n \n) %11
+1 %12
+( 00000 n \n) %13
+2 %14
+( 00000 n \n) %15
+8 %16
+( 00000 n \ntrailer\n<</Size 5/Root 1 0 R>>\nstartxref\n) %17
+9 %18
+(\n%%EOF\n) %19
+]
+
+% _l23_
+% vvv tested at Sat Jan 8 12:31:00 CET 2005
+/p02bb [%sam2p-ttm; by pts@fazekas.hu at Sat Apr 20 18:36:35 CEST 2002
+(%PDF-1.`0\n`B) %0
+[ (2 0 obj\n<</Type/Pages/Kids[4 0 R]/Count 1>>\nendobj\n) ] %1
+[ (3 0 obj\n<</Length ) ] %2
+-5 %3: length of chunk 5
+(>>\nstream\n) %4
+[ (q`s\n`w 0 0 `h 0 0 cm\nBI/Interpolate false/W `w/H `h/CS`1/BPC `b`F ID
+`S
+EI\nQ\n) ] %5.0
+(endstream\nendobj\n) %6
+[ (1 0 obj\n<</Type/Catalog/Pages 2 0 R>>\nendobj\n) ] %7.0
+[ (4 0 obj\n<</Type/Page/MediaBox[`X]
+/CropBox[`X]/Parent 2 0 R/Resources<</ProcSet[/PDF`C]>>/Contents
+3 0 R>>\nendobj\n) ] %8
+(xref\n0 5\n0000000000 65535 f \n) %9
+7 %10: offset of chunk 7, printf("%010u")
+( 00000 n \n) %11
+1 %12
+( 00000 n \n) %13
+2 %14
+( 00000 n \n) %15
+8 %16
+( 00000 n \ntrailer\n<</Size 5/Root 1 0 R>>\nstartxref\n) %17
+9 %18
+(\n%%EOF\n) %19
+]
+
+% Dat: /Kids with direct objects are not valid PDF
+% (reported by Sid Steward)
+% The PDF Reference 1.5 (and 1.3) actually describes the page Kids array
+% as: "An array of indirect references to the immediate children of this
+% node. The children may be page objects or other page tree nodes."
+%/pd02bb [%sam2p-ttm; by pts@fazekas.hu at Sat Apr 20 18:36:35 CEST 2002
+%(%PDF-1.`0\n`B) %0
+%[ (2 0 obj\n<</Type/Pages/Kids[<</Type/Page
+%/MediaBox[`X]
+%/CropBox[`X]/Parent 2 0 R/Resources<</ProcSet[/PDF`C]>>/Contents
+%3 0 R>>]/Count 1>>\nendobj\n) ] %1
+%[ (3 0 obj\n<</Length ) ] %2
+%-5 %3: length of chunk 5
+%(>>\nstream\n) %4
+%[ (q`s\n`w 0 0 `h 0 0 cm\nBI/Interpolate false/W `w/H `h/CS`1/BPC `b`F ID
+%`S
+%EI\nQ\n) ] %5.0
+%(endstream\nendobj\n) %6
+%[ (1 0 obj\n<</Type/Catalog/Pages 2 0 R>>\nendobj\n) ] %7.0
+%(xref\n0 4\n0000000000 65535 f \n) %8
+%7 %9: offset of chunk 7, printf("%010u")
+%( 00000 n \n) %10
+%1 %11
+%( 00000 n \n) %12
+%2 %13
+%( 00000 n \ntrailer\n<</Size 4/Root 1 0 R>>\nstartxref\n) %14
+%8 %15
+%(\n%%EOF\n) %16
+%]
+
+% ---
+
+% _l2jbin_
+/l2jbin (%!PS-Adobe-3.0`E
+%%Pages: 1
+`X%%DocumentData: `B
+%%LanguageLevel: 2
+%%EndComments
+%%Page: 1 1
+save`s 2 dict begin
+{/Device`d setcolorspace
+/T currentfile`T def
+/F T/DCTDecode filter def
+<</ImageType 1/Width `w/Height `h/BitsPerComponent
+`b/ImageMatrix[1 0 0 -1 0 `h]/Decode
+[`D]/DataSource F>> image`t}
+%%BeginData:;
+exec
+`S
+%%EndData
+end restore showpage
+%%Trailer
+%%EOF\n)
+
+% _l2jbin_
+/p0jbin [%sam2p-ttm; by pts@fazekas.hu at Mon Apr 15 21:58:26 CEST 2002
+(%PDF-1.`0\n`B) %0
+[ (2 0 obj\n<</Type/Pages/Kids[5 0 R]/Count 1>>\nendobj\n) ] %1
+[ (3 0 obj\n<</Length ) ] %2
+-5 %3: length of chunk 5
+(>>\nstream\n) %4
+[ (q`s\n`w 0 0 `h 0 0 cm /S Do Q\n) ] %5.0
+(endstream\nendobj\n) %6
+[ (1 0 obj\n<</Type/Catalog/Pages 2 0 R>>\nendobj\n) ] %7.0
+[ (4 0 obj\n<</Length ) ] %8.0
+-11 %9
+(/Type/XObject/Name/S/Subtype/Image/ColorSpace/Device`d/Width
+`w/Height `h/BitsPerComponent `b`F>>stream\n) %10
+[ (`S) ] %11
+(\nendstream\nendobj\n) %12
+[ (5 0 obj\n<</Type/Page
+/MediaBox[`X]
+/CropBox[`X]/Parent 2 0 R/Resources<</XObject<</S
+4 0 R>>/ProcSet[/PDF`C]>>/Contents
+3 0 R>>\nendobj\n) ] %13
+(xref\n0 6\n0000000000 65535 f \n) %14
+7 %15
+( 00000 n \n) %16
+1 %17
+( 00000 n \n) %18
+2 %19
+( 00000 n \n) %20
+8 %21
+( 00000 n \n) %22
+13 %23
+( 00000 n \ntrailer\n<</Size 6/Root 1 0 R>>\nstartxref\n) %24
+14 %25
+(\n%%EOF\n) %26
+]
+
+% _l2jbin_
+/p0jbb [%sam2p-ttm; by pts@fazekas.hu at Mon Apr 15 21:58:26 CEST 2002
+% Dat: CropBox is required by buggy gs/gv viewer code
+(%PDF-1.`0\n`B) %0
+[ (2 0 obj\n<</Type/Pages/Kids[4 0 R]/Count 1>>\nendobj\n) ] %1
+[ (3 0 obj\n<</Length ) ] %2
+-5 %3: length of chunk 5
+(>>\nstream\n) %4
+[ (q`s\n`w 0 0 `h 0 0 cm\nBI/W `w/H `h/CS/Device`d/BPC `b`F ID
+`S
+EI\nQ\n) ] %5.0
+(endstream\nendobj\n) %6
+[ (1 0 obj\n<</Type/Catalog/Pages 2 0 R>>\nendobj\n) ] %7.0
+[ (4 0 obj\n<</Type/Page/MediaBox[`X]
+/CropBox[`X]/Parent 2 0 R/Resources<</ProcSet[/PDF`C]>>/Contents
+3 0 R>>\nendobj\n) ] %8
+(xref\n0 5\n0000000000 65535 f \n) %9
+7 %10: offset of chunk 7, printf("%010u")
+( 00000 n \n) %11
+1 %12
+( 00000 n \n) %13
+2 %14
+( 00000 n \n) %15
+8 %16
+( 00000 n \ntrailer\n<</Size 5/Root 1 0 R>>\nstartxref\n) %17
+9 %18
+(\n%%EOF\n) %19
+]
+
+% ---
+
+% _l1tr_
+/l1tr (%!PS-Adobe-3.0`E
+%%Pages: 1
+`X%%DocumentData: `B
+%%LanguageLevel: 1
+%%EndComments
+%%Page: 1 1
+showpage
+%%Trailer
+%%EOF\n)
+
+% _l1tr_
+/l1op (%!PS-Adobe-3.0`E
+%%Pages: 1
+`X%%DocumentData: `B
+%%LanguageLevel: 1
+%%EndComments
+%%Page: 1 1
+save`s
+`r setrgbcolor
+0 0 moveto
+`w 0 lineto
+0 `h rlineto
+-`w 0 rlineto
+closepath fill
+restore showpage
+%%Trailer
+%%EOF\n)
+
+% by pts@fazekas.hu at Sat Jun 15 16:09:25 CEST 2002
+% _l1tr_
+/l1bb (%!PS-Adobe-3.0`E
+%%Pages: 1
+`X%%DocumentData: `B
+%%LanguageLevel: 1
+%%EndComments
+%%Page: 1 1
+save`s
+0 0 moveto
+`w 0 lineto
+0 `h rlineto
+-`w 0 rlineto
+closepath stroke
+restore showpage
+%%Trailer
+%%EOF\n)
+
+% _l1tr_
+/p0op [%sam2p-ttm; by pts@fazekas.hu at Wed Apr 17 10:34:36 CEST 2002
+(%PDF-1.0\n) %0
+[ (2 0 obj\n<</Type/Pages/Kids[4 0 R]/Count 1>>\nendobj\n) ] %1
+[ (3 0 obj\n<</Length ) ] %2
+-5 %3: length of chunk 5
+(>>\nstream\n) %4
+% [ (q `g rg 0 0 `w `h re B Q) ] %4.0
+% ^^^ SUXX `re' draws a rectangle with black border in acroread :-(
+[ (q `g rg 0 0 m `w 0 l `w `h l 0 `h l F Q\n) ] %5.0
+(endstream\nendobj\n) %6
+[ (1 0 obj\n<</Type/Catalog/Pages 2 0 R>>\nendobj\n) ] %7.0
+[ (4 0 obj\n<</Type/Page/MediaBox[`X]
+/CropBox[`X]/Parent 2 0 R/Resources<</ProcSet[/PDF`C]>>/Contents
+3 0 R>>\nendobj\n) ] %8
+(xref\n0 5\n0000000000 65535 f \n) %9
+7 %10: offset of chunk 7, printf("%010u")
+( 00000 n \n) %11
+1 %12
+( 00000 n \n) %13
+2 %14
+( 00000 n \n) %15
+8 %16
+( 00000 n \ntrailer\n<</Size 5/Root 1 0 R>>\nstartxref\n) %17
+9 %18
+(\n%%EOF\n) %19
+]
+
+% /p0bb: draws the bounding box (./sam2p -s:bbox examples/yellow.gif test.pdf),
+% see also /l1bb. Half of the linewidth is cropped by /MediaBox
+/p0bb [%sam2p-ttm; by pts@fazekas.hu at Sat Jun 15 16:08:38 CEST 2002
+(%PDF-1.0\n) %0
+[ (2 0 obj\n<</Type/Pages/Kids[4 0 R]/Count 1>>\nendobj\n) ] %1
+[ (3 0 obj\n<</Length ) ] %2
+-5 %3: length of chunk 5
+(>>\nstream\n) %4
+[ (q`s `g rg 0 0 m `w 0 l `w `h l 0 `h l S Q\n) ] %5.0
+(endstream\nendobj\n) %6
+[ (1 0 obj\n<</Type/Catalog/Pages 2 0 R>>\nendobj\n) ] %7.0
+[ (4 0 obj\n<</Type/Page/MediaBox[`X]
+/CropBox[`X]/Parent 2 0 R/Resources<</ProcSet[/PDF`C]>>/Contents
+3 0 R>>\nendobj\n) ] %8
+(xref\n0 5\n0000000000 65535 f \n) %9
+7 %10: offset of chunk 7, printf("%010u")
+( 00000 n \n) %11
+1 %12
+( 00000 n \n) %13
+2 %14
+( 00000 n \n) %15
+8 %16
+( 00000 n \ntrailer\n<</Size 5/Root 1 0 R>>\nstartxref\n) %17
+9 %18
+(\n%%EOF\n) %19
+]
+
+% _l1tr_
+/p0tr [%sam2p-ttm; by pts@fazekas.hu at Wed Apr 17 10:34:36 CEST 2002
+(%PDF-1.0\n) %0
+[ (2 0 obj\n<</Type/Pages/Kids[4 0 R]/Count 1>>\nendobj\n) ] %1
+[ (3 0 obj\n<</Length ) ] %2
+-5 %3: length of chunk 5
+(>>\nstream\n) %4
+[ ] %5.0
+(endstream\nendobj\n) %6
+[ (1 0 obj\n<</Type/Catalog/Pages 2 0 R>>\nendobj\n) ] %7.0
+[ (4 0 obj\n<</Type/Page
+/MediaBox[`X]
+/CropBox[`X]/Parent 2 0 R/Resources<</ProcSet[/PDF`C]>>/Contents
+3 0 R>>\nendobj\n) ] %8
+(xref\n0 5\n0000000000 65535 f \n) %9
+7 %10: offset of chunk 7, printf("%010u")
+( 00000 n \n) %11
+1 %12
+( 00000 n \n) %13
+2 %14
+( 00000 n \n) %14
+8 %15
+( 00000 n \ntrailer\n<</Size 5/Root 1 0 R>>\nstartxref\n) %17
+9 %18
+(\n%%EOF\n) %19
+]
+
+% ---
+
+% at Sun Jun 2 15:49:39 CEST 2002
+% derived from /l1m8r
+% _l1c_
+/l1t8r (%!PS-Adobe-3.0`E
+%%Pages: 1
+`X%%DocumentData: `B
+%%LanguageLevel: 1
+%%EndComments
+%%Page: 1 1
+save`s 36 dict begin
+`r setrgbcolor
+/x{load def}def/E/def x/A/currentfile x/c/exch x/i/ifelse x/S 32 E/D 0 E/C 0 E
+/;/getinterval x/p/putinterval x/b/bitshift x/+/add x/O/pop x/*/mul x/u/dup x
+/-/sub x/"/string x/?/length x/y/copy x{
+{mark A/ASCII85Decode filter/T exch def}stopped
+/B exch def cleartomark B{{
+/d{{27 S ge{exit}if A read not{511}if u 122 eq{/S 27 E/D 0 E/C 0 E}{u 117 gt{
+A read{O}if/S 54 S - E}{u 33 ge{S 32 eq{u/C c E/D -1670420001 E}{u 117 -{1 85
+7225 614125}S 28 - get * D +/D c E}i/S S 1 - E}if}i}i O}loop S 22 eq{511}{C
+1868977 * D + S 24 and neg b 23 S lt{C 3 * +}if 255 and/S S 3 eq{32}{S 7 mod 3
+eq{22}{S 8 -}i}i E}i}E
+/B `? " E/L 128 " E/Ex()E
+`P " u ? 1 - 0 c 1 c{d 3 y put O O}for 0 `p ;/m
+0 E{255 div m 1 + u 3 eq{O setrgbcolor
+`w `h false[1 0 0 -1 0 `h]{B Ex{2 y ? c ? ge{2 y c ? 0 c ; 2 index y ? 2 y c
+? c - ;/Ex c E O exit}{2 y c y O ? 2 y c ? c - ;}i d u 128 le{L c 0 c 1 + ; u ?
+1 - 0 c 1 c{d 3 y put O O}for}{L c d c 257 c - 3 y 1 - -1 0{3 y c put O}for O O
+c O 0 c ;}i}loop B}imagemask 0}if/m c E}forall d O d O}bind exec}{
+T `P " readstring O 0 `p ;/m 0 E/F T/RunLengthDecode filter E
+{255 div m 1 + u 3 eq{O setrgbcolor
+`w `h false[1 0 0 -1 0 `h]F imagemask 0}if/m c E}forall
+F closefile T closefile}i}
+%%BeginData:;
+exec
+`S
+%%EndData
+end restore showpage
+%%Trailer
+%%EOF\n)
+
+% at Sun Jun 2 15:49:46 CEST 2002
+% derived from /l1mhr
+% _l1c_
+/l1thr (%!PS-Adobe-3.0`E
+%%Pages: 1
+`X%%DocumentData: `B
+%%LanguageLevel: 1
+%%EndComments
+%%Page: 1 1
+save`s 36 dict begin
+`r setrgbcolor
+/x{load def}def/E/def x/A/currentfile x/c/exch x/i/ifelse x/S/readhexstring x
+/;/getinterval x/p/putinterval x/b/bitshift x/+/add x/O/pop x/*/mul x/u/dup x
+/-/sub x/"/string x/?/length x/y/copy x{
+{mark A/ASCIIHexDecode filter/T exch def}stopped
+/B exch def cleartomark B{{
+/C(.)E/d{A C S O 0 get}E
+/B `? " E/L 128 " E/Ex()E
+A `P " S O 0 `p ;/m 0 E{255 div m 1 + u 3 eq{O setrgbcolor
+`w `h false[1 0 0 -1 0 `h]{B Ex{2 y ? c ? ge{2 y c ? 0 c ; 2 index y ? 2 y c
+? c - ;/Ex c E O exit}{2 y c y O ? 2 y c ? c - ;}i d u 128 le{L c 0 c 1 + ;
+A c S O}{L c d c 257 c - 3 y 1 - -1 0{3 y c put O}for O O
+c O 0 c ;}i}loop B}imagemask 0}if/m c E}forall
+d O A read O O}bind exec}{
+T `P " readstring O 0 `p ;/m 0 E/F T/RunLengthDecode filter E
+{255 div m 1 + u 3 eq{O setrgbcolor
+`w `h false[1 0 0 -1 0 `h]F imagemask 0}if/m c E}forall
+F closefile T closefile}i}
+%%BeginData:;
+exec
+`S
+%%EndData
+end restore showpage
+%%Trailer
+%%EOF\n)
+
+% at Sun Jun 2 15:49:59 CEST 2002
+% derived from /l1mbr
+% _l1c_
+/l1tbr (%!PS-Adobe-3.0`E
+%%Pages: 1
+`X%%DocumentData: `B
+%%LanguageLevel: 1
+%%EndComments
+%%Page: 1 1
+save`s 36 dict begin
+`r setrgbcolor
+/x{load def}def/E/def x/A/currentfile x/c/exch x/i/ifelse x/S/readstring x
+/;/getinterval x/p/putinterval x/b/bitshift x/+/add x/O/pop x/*/mul x/u/dup x
+/-/sub x/"/string x/?/length x/y/copy x{
+/filter where not{{
+/B `? " E/L 128 " E/Ex()E
+A `P " S O 0 `p ;/m 0 E{255 div m 1 + u 3 eq{O setrgbcolor
+`w `h false[1 0 0 -1 0 `h]{B Ex{2 y ? c ? ge{2 y c ? 0 c ; 2 index y ? 2 y c ?
+c - ;/Ex c E O exit}{2 y c y O ? 2 y c ? c - ;}i A read O u 128 le{L c 0 c 1 +
+; A c S O}{L c A read O c 257 c - 3 y 1 - -1 0{3 y c put O}for O O c
+O 0 c ;}i}loop B}imagemask 0}if/m c E}forall A read O O}bind exec}{
+O/F A/RunLengthDecode filter E
+A `P " S O 0 `p ;/m 0 E{255 div m 1 + u 3 eq{O setrgbcolor
+`w `h false[1 0 0 -1 0 `h]F imagemask 0}if/m c E}forall F closefile}i}
+%%BeginData:;
+exec
+`S
+%%EndData
+end restore showpage
+%%Trailer
+%%EOF\n)
+
+% PSL1 implementation of /l23tran2 /A85
+% _l1c_
+/l1t8n (%!PS-Adobe-3.0`E
+%%Pages: 1
+`X%%DocumentData: `B
+%%LanguageLevel: 1
+%%EndComments
+%%Page: 1 1
+save`s 16 dict begin
+/x{load def}def/E/def x/A/currentfile x/c/exch x/i/ifelse x/S 32 E/D 0 E/C 0 E
+/d{{27 S ge{exit}if A read not{511}if dup 122 eq{/S 27 E/D 0 E/C 0 E}{dup 117
+gt{A read{pop}if/S 54 S sub E}{dup 33 ge{S 32 eq{dup/C c E/D -1670420001 E}{dup
+117 sub{1 85 7225 614125}S 28 sub get mul D add/D c E}i/S S 1 sub E}if}i}i pop}
+loop S 22 eq{511}{C 1868977 mul D add S 24 and neg bitshift 23 S lt{C 3 mul add
+}if 255 and/S S 3 eq{32}{S 7 mod 3 eq{22}{S 8 sub}i}i E}i}bind E
+/s `? string E
+{`P string dup length 1 sub 0 c 1 c{d 3 copy put pop pop}for
+0 `p getinterval
+/m 0 E
+{255 div m 1 add dup 3 eq{pop setrgbcolor
+`w `h false[1 0 0 -1 0 `h]
+{s dup length 1 sub 0 c 1 c{d 3 copy put pop pop}for}imagemask
+0}if/m exch def}forall
+d pop}bind
+%%BeginData:;
+exec
+`S
+%%EndData
+end restore showpage
+%%Trailer
+%%EOF\n)
+
+% PSL1 implementation of /l23tran2 /Hex
+% _l1c_
+/l1thn (%!PS-Adobe-3.0`E
+%%Pages: 1
+`X%%DocumentData: `B
+%%LanguageLevel: 1
+%%EndComments
+%%Page: 1 1
+save`s 2 dict begin
+/s `? string def
+{currentfile `P string readhexstring pop
+0 `p getinterval
+/m 0 def
+{255 div m 1 add dup 3 eq{pop setrgbcolor
+`w `h false[1 0 0 -1 0 `h]
+{currentfile s readhexstring pop}imagemask
+0}if/m exch def}forall
+currentfile read pop pop}bind
+%%BeginData:;
+exec
+`S
+%%EndData
+end restore showpage
+%%Trailer
+%%EOF\n)
+
+% PSL1 implementation of /l23tran2 /Binary
+% Used by /Transparent2, /Transparent4 and /Transparent8.
+% This implemetation does:
+% rgb-palette imagemask-newcompress-transfer
+% _l1c_
+/l1tbn (%!PS-Adobe-3.0`E
+%%Pages: 1
+`X%%DocumentData: `B
+%%LanguageLevel: 1
+%%EndComments
+%%Page: 1 1
+save`s 2 dict begin
+/s `? string def
+{currentfile `P string readstring pop
+0 `p getinterval
+/m 0 def
+{255 div m 1 add dup 3 eq{pop setrgbcolor
+`w `h false[1 0 0 -1 0 `h]
+{currentfile s readstring pop}imagemask
+0}if/m exch def}forall}bind
+%%BeginData:;
+exec
+`S
+%%EndData
+end restore showpage
+%%Trailer
+%%EOF\n)
+
+
+% at Sun Jun 2 15:21:53 CEST 2002
+% derived from /l118r
+% l1g8r: /Compression/RLE /TransferEncoding/A85 /SampleFormat/Gray* /FileFormat/PSL1
+% _l1c_
+/l1g8r (%!PS-Adobe-3.0`E
+%%Pages: 1
+`X%%DocumentData: `B
+%%LanguageLevel: 1
+`I%%EndComments
+%%Page: 1 1
+save`s `R26 dict begin
+/x{load def}def/E/def x/A/currentfile x/c/exch x/i/ifelse x/S 32 E/D 0 E/C 0 E
+/;/getinterval x/p/putinterval x/b/bitshift x/+/add x/O/pop x/*/mul x/u/dup x
+/-/sub x/"/string x/?/length x/y/copy x{
+{mark A/ASCII85Decode filter/T exch def}stopped
+/B exch def cleartomark B{{
+/d{{27 S ge{exit}if A read not{511}if u 122 eq{/S 27 E/D 0 E/C 0 E}{u 117 gt{
+A read{O}if/S 54 S - E}{u 33 ge{S 32 eq{u/C c E/D -1670420001 E}{u 117 -{1 85
+7225 614125}S 28 - get * D +/D c E}i/S S 1 - E}if}i}i O}loop S 22 eq{511}{C
+1868977 * D + S 24 and neg b 23 S lt{C 3 * +}if 255 and/S S 3 eq{32}{S 7 mod 3
+eq{22}{S 8 -}i}i E}i}E
+/B `? " E/L 128 " E/Ex()E
+`w `h `b[1 0 0 -1 0 `h]{B Ex{2 y ? c ? ge{2 y c ? 0 c ; 2 index y ? 2 y c
+? c - ;/Ex c E O exit}{2 y c y O ? 2 y c ? c - ;}i d u 128 le{L c 0 c 1 + ; u ?
+1 - 0 c 1 c{d 3 y put O O}for}{L c d c 257 c - 3 y 1 - -1 0{3 y c put O}for O O
+c O 0 c ;}i}loop B}`i
+d O d O}bind exec}{
+/F T/RunLengthDecode filter def
+`w `h `b[1 0 0 -1 0 `h]F `i F closefile T closefile}i}
+%%BeginData:;
+exec
+`S
+%%EndData
+end restore showpage
+%%Trailer
+%%EOF\n)
+
+% at Sun Jun 2 15:22:10 CEST 2002
+% derived from /l1ghr
+% _l1c_
+/l1ghr (%!PS-Adobe-3.0`E
+%%Pages: 1
+`X%%DocumentData: `B
+%%LanguageLevel: 1
+`I%%EndComments
+%%Page: 1 1
+save`s `R26 dict begin
+/x{load def}def/E/def x/A/currentfile x/c/exch x/i/ifelse x/S/readhexstring x
+/;/getinterval x/p/putinterval x/b/bitshift x/+/add x/O/pop x/*/mul x/u/dup x
+/-/sub x/"/string x/?/length x/y/copy x{
+{mark A/ASCIIHexDecode filter/T exch def}stopped
+/B exch def cleartomark B{{
+/C(.)E/d{A C S O 0 get}E
+/B `? " E/L 128 " E/Ex()E
+`w `h `b[1 0 0 -1 0 `h]{B Ex{2 y ? c ? ge{2 y c ? 0 c ; 2 index y ? 2 y c
+? c - ;/Ex c E O exit}{2 y c y O ? 2 y c ? c - ;}i d u 128 le{L c 0 c 1 + ;
+A c S O}{L c d c 257 c - 3 y 1 - -1 0{3 y c put O}for O O
+c O 0 c ;}i}loop B}`i
+d O A read O O}bind exec}{
+/F T/RunLengthDecode filter def
+`w `h `b[1 0 0 -1 0 `h]F `i F closefile T closefile}i}
+%%BeginData:;
+exec
+`S
+%%EndData
+end restore showpage
+%%Trailer
+%%EOF\n)
+
+% at Sun Jun 2 15:22:21 CEST 2002
+% derived from /l11br
+% _l1c_
+/l1gbr (%!PS-Adobe-3.0`E
+%%Pages: 1
+`X%%DocumentData: `B
+%%LanguageLevel: 1
+`I%%EndComments
+%%Page: 1 1
+save`s `R26 dict begin
+/x{load def}def/E/def x/A/currentfile x/c/exch x/i/ifelse x/S/readstring x
+/;/getinterval x/p/putinterval x/b/bitshift x/+/add x/O/pop x/*/mul x/u/dup x
+/-/sub x/"/string x/?/length x/y/copy x{
+{mark A/RunLengthDecode filter/F exch def}stopped
+/B exch def cleartomark B{{
+/B `? " E/L 128 " E/Ex()E
+`w `h `b[1 0 0 -1 0 `h]{B Ex{2 y ? c ? ge{2 y c ? 0 c ; 2 index y ? 2 y c ?
+c - ;/Ex c E O exit}{2 y c y O ? 2 y c ? c - ;}i A read O u 128 le{L c 0 c 1 +
+; A c S O}{L c A read O c 257 c - 3 y 1 - -1 0{3 y c put O}for O O c
+O 0 c ;}i}loop B}`i A read O O}bind exec}{
+`w `h `b[1 0 0 -1 0 `h]F `i F closefile}i}
+%%BeginData:;
+exec
+`S
+%%EndData
+end restore showpage
+%%Trailer
+%%EOF\n)
+
+% l1g8n: /Compression/None /TransferEncoding/A85 /SampleFormat/Gray* /FileFormat/PSL1
+% _l1c_
+/l1g8n (%!PS-Adobe-3.0`E
+%%Pages: 1
+`X%%DocumentData: `B
+%%LanguageLevel: 1
+`I%%EndComments
+%%Page: 1 1
+save`s `R16 dict begin
+/x{load def}def/E/def x/A/currentfile x/c/exch x/i/ifelse x/S 32 E/D 0 E/C 0 E{
+{mark A/ASCII85Decode filter/F exch def}stopped
+/B exch def cleartomark B{{
+/d{{27 S ge{exit}if A read not{511}if dup 122 eq{/S 27 E/D 0 E/C 0 E}{dup 117
+gt{A read{pop}if/S 54 S sub E}{dup 33 ge{S 32 eq{dup/C c E/D -1670420001 E}{dup
+117 sub{1 85 7225 614125}S 28 sub get mul D add/D c E}i/S S 1 sub E}if}i}i pop}
+loop S 22 eq{511}{C 1868977 mul D add S 24 and neg bitshift 23 S lt{C 3 mul add
+}if 255 and/S S 3 eq{32}{S 7 mod 3 eq{22}{S 8 sub}i}i E}i}bind E
+/s `? string E
+`w `h `b[1 0 0 -1 0 `h]
+{s dup length 1 sub 0 c 1 c{d 3 copy put pop pop}for}`i
+d pop}bind exec}{
+`w `h `b[1 0 0 -1 0 `h]F `i F closefile}i}
+%%BeginData:;
+exec
+`S
+%%EndData
+end restore showpage
+%%Trailer
+%%EOF\n)
+
+% _l1c_
+/l1ghn (%!PS-Adobe-3.0`E
+%%Pages: 1
+`X%%DocumentData: `B
+%%LanguageLevel: 1
+`I%%EndComments
+%%Page: 1 1
+save`s `R1 dict begin
+/s `? string def
+{`w `h `b[1 0 0 -1 0 `h]{currentfile s readhexstring pop}`i
+currentfile read pop pop}bind
+%%BeginData:;
+exec
+`S
+%%EndData
+end restore showpage
+%%Trailer
+%%EOF\n)
+
+% _l1c_
+/l1gbn (%!PS-Adobe-3.0`E
+%%Pages: 1
+`X%%DocumentData: `B
+%%LanguageLevel: 1
+`I%%EndComments
+%%Page: 1 1
+save`s `R1 dict begin
+/s `? string def
+{`w `h `b[1 0 0 -1 0 `h]{currentfile s readstring pop}`i}bind
+%%BeginData:;
+exec
+`S
+%%EndData
+end restore showpage
+%%Trailer
+%%EOF\n)
+
+
+% at Sat Jun 1 21:19:30 CEST 2002
+% _l1c_
+/l128r (%!PS-Adobe-3.0`E
+%%Pages: 1
+`X%%DocumentData: `B
+%%LanguageLevel: 1
+`I%%EndComments
+%%Page: 1 1
+save`s 36 dict begin
+/x{load def}def/E/def x/A/currentfile x/c/exch x/i/ifelse x/S 32 E/D 0 E/C 0 E
+/;/getinterval x/p/putinterval x/b/bitshift x/+/add x/O/pop x/*/mul x/u/dup x
+/-/sub x/"/string x/?/length x/y/copy x{
+{mark A/ASCII85Decode filter/T exch def}stopped
+/B exch def cleartomark B{{
+/d{{27 S ge{exit}if A read not{511}if u 122 eq{/S 27 E/D 0 E/C 0 E}{u 117 gt{
+A read{O}if/S 54 S - E}{u 33 ge{S 32 eq{u/C c E/D -1670420001 E}{u 117 -{1 85
+7225 614125}S 28 - get * D +/D c E}i/S S 1 - E}if}i}i O}loop S 22 eq{511}{C
+1868977 * D + S 24 and neg b 23 S lt{C 3 * +}if 255 and/S S 3 eq{32}{S 7 mod 3
+eq{22}{S 8 -}i}i E}i}E
+12 " u/B c E 0 `p ; u ? 1 - 0 c 1 c{d 3 y put O O}for O/H 3072 " E/R 0 E
+0 1 255{u -6 b B c 3 * 3 ; H c R c p/R R 3 + E
+u -4 b 3 and B c 3 * 3 ; H c R c p/R R 3 + E
+u -2 b 3 and B c 3 * 3 ; H c R c p/R R 3 + E
+3 and B c 3 * 3 ; H c R c p/R R 3 + E
+}for/B `w 3 + -2 b " E/B3 B ? 2 b 3 * " E/R B3 0 `w 3 * ; E/L 128 " E/Ex()E
+`w `h 8[1 0 0 -1 0 `h]{B3 0 B Ex{2 y ? c ? ge{2 y c ? 0 c ; 2 index y ? 2 y c ?
+c - ;/Ex c E O exit}{2 y c y O ? 2 y c ? c - ;}i d u 128 le{L c 0 c 1 + ; u ? 1
+- 0 c 1 c{d 3 y put O O}for}{L c d c 257 c - 3 y 1 - -1 0{3 y c put O}for O O c
+O 0 c ;}i}loop B{12 * H c 12 ; 3 y p O 12 +}forall O O R}false 3 colorimage
+d O d O}bind exec}{
+[/Indexed/DeviceRGB `# 1 - T `p " readstring O]setcolorspace
+/F T/RunLengthDecode filter def<</ImageType 1/Width `w/Height `h
+/BitsPerComponent `b/ImageMatrix[1 0 0 -1 0 `h]/Decode[`D]/DataSource F>>
+image F closefile T closefile
+}ifelse}
+%%BeginData:;
+exec
+`S
+%%EndData
+end restore showpage
+%%Trailer
+%%EOF\n)
+
+% at Sun Jun 2 14:19:02 CEST 2002
+% derived from /l128r
+% _l1c_
+/l12hr (%!PS-Adobe-3.0`E
+%%Pages: 1
+`X%%DocumentData: `B
+%%LanguageLevel: 1
+`I%%EndComments
+%%Page: 1 1
+save`s 36 dict begin
+/x{load def}def/E/def x/A/currentfile x/c/exch x/i/ifelse x/S/readhexstring x
+/;/getinterval x/p/putinterval x/b/bitshift x/+/add x/O/pop x/*/mul x/u/dup x
+/-/sub x/"/string x/?/length x/y/copy x{
+{mark A/ASCIIHexDecode filter/T exch def}stopped
+/B exch def cleartomark B{{
+/C(.)E/d{A C S O 0 get}E
+A 12 " u/B c E 0 `p ; S O O/H 3072 " E/R 0 E
+0 1 255{u -6 b B c 3 * 3 ; H c R c p/R R 3 + E
+u -4 b 3 and B c 3 * 3 ; H c R c p/R R 3 + E
+u -2 b 3 and B c 3 * 3 ; H c R c p/R R 3 + E
+3 and B c 3 * 3 ; H c R c p/R R 3 + E
+}for/B `w 3 + -2 b " E/B3 B ? 2 b 3 * " E/R B3 0 `w 3 * ; E/L 128 " E/Ex()E
+`w `h 8[1 0 0 -1 0 `h]{B3 0 B Ex{2 y ? c ? ge{2 y c ? 0 c ; 2 index y ? 2 y c ?
+c - ;/Ex c E O exit}{2 y c y O ? 2 y c ? c - ;}i d u 128 le{L c 0 c 1 + ;
+A c S O}{L c d c 257 c - 3 y 1 - -1 0{3 y c put O}for O O c
+O 0 c ;}i}loop B{12 * H c 12 ; 3 y p O 12 +}forall O O R}false 3 colorimage
+d O A read O O}bind exec}{
+[/Indexed/DeviceRGB `# 1 - T `p " readstring O]setcolorspace
+/F T/RunLengthDecode filter def<</ImageType 1/Width `w/Height `h
+/BitsPerComponent `b/ImageMatrix[1 0 0 -1 0 `h]/Decode[`D]/DataSource F>>
+image F closefile T closefile
+}ifelse}
+%%BeginData:;
+exec
+`S
+%%EndData
+end restore showpage
+%%Trailer
+%%EOF\n)
+
+% at Sun Jun 2 14:41:59 CEST 2002
+% derived from /l12hr
+% _l1c_
+/l12br (%!PS-Adobe-3.0`E
+%%Pages: 1
+`X%%DocumentData: `B
+%%LanguageLevel: 1
+`I%%EndComments
+%%Page: 1 1
+save`s 36 dict begin
+/x{load def}def/E/def x/A/currentfile x/c/exch x/i/ifelse x/S/readstring x
+/;/getinterval x/p/putinterval x/b/bitshift x/+/add x/O/pop x/*/mul x/u/dup x
+/-/sub x/"/string x/?/length x/y/copy x{
+{mark A/ASCII85Decode filter}stopped
+/B exch def cleartomark B{{
+A 12 " u/B c E 0 `p ; S O O/H 3072 " E/R 0 E
+0 1 255{u -6 b B c 3 * 3 ; H c R c p/R R 3 + E
+u -4 b 3 and B c 3 * 3 ; H c R c p/R R 3 + E
+u -2 b 3 and B c 3 * 3 ; H c R c p/R R 3 + E
+3 and B c 3 * 3 ; H c R c p/R R 3 + E
+}for/B `w 3 + -2 b " E/B3 B ? 2 b 3 * " E/R B3 0 `w 3 * ; E/L 128 " E/Ex()E
+`w `h 8[1 0 0 -1 0 `h]{B3 0 B Ex{2 y ? c ? ge{2 y c ? 0 c ; 2 index y ? 2 y c ?
+c - ;/Ex c E O exit}{2 y c y O ? 2 y c ? c - ;}i A read O u 128 le{L c 0 c 1 +
+; A c S O}{L c A read O c 257 c - 3 y 1 - -1 0{3 y c put O}for O O c
+O 0 c ;}i}loop B{12 * H c 12 ; 3 y p O 12 +}forall O O R}false 3 colorimage
+A read O O}bind exec}{
+[/Indexed/DeviceRGB `# 1 - A `p " S O]setcolorspace
+/F A/RunLengthDecode filter def<</ImageType 1/Width `w/Height `h
+/BitsPerComponent `b/ImageMatrix[1 0 0 -1 0 `h]/Decode[`D]/DataSource F>>
+image F closefile}ifelse}
+%%BeginData:;
+exec
+`S
+%%EndData
+end restore showpage
+%%Trailer
+%%EOF\n)
+
+% at Sun Jun 2 12:00:13 CEST 2002
+% _l1c_
+/l128n (%!PS-Adobe-3.0`E
+%%Pages: 1
+`X%%DocumentData: `B
+%%LanguageLevel: 1
+`I%%EndComments
+%%Page: 1 1
+save`s 36 dict begin
+/x{load def}def/E/def x/A/currentfile x/c/exch x/i/ifelse x/S 32 E/D 0 E/C 0 E
+/;/getinterval x/p/putinterval x/b/bitshift x/+/add x/O/pop x/*/mul x/u/dup x
+/-/sub x/"/string x/?/length x/y/copy x{
+{mark A/ASCII85Decode filter/T exch def}stopped
+/B exch def cleartomark B{{
+/d{{27 S ge{exit}if A read not{511}if u 122 eq{/S 27 E/D 0 E/C 0 E}{u 117 gt{
+A read{O}if/S 54 S - E}{u 33 ge{S 32 eq{u/C c E/D -1670420001 E}{u 117 -{1 85
+7225 614125}S 28 - get * D +/D c E}i/S S 1 - E}if}i}i O}loop S 22 eq{511}{C
+1868977 * D + S 24 and neg b 23 S lt{C 3 * +}if 255 and/S S 3 eq{32}{S 7 mod 3
+eq{22}{S 8 -}i}i E}i}E
+12 " u/B c E 0 `p ; u ? 1 - 0 c 1 c{d 3 y put O O}for O/H 3072 " E/R 0 E
+0 1 255{u -6 b B c 3 * 3 ; H c R c p/R R 3 + E
+u -4 b 3 and B c 3 * 3 ; H c R c p/R R 3 + E
+u -2 b 3 and B c 3 * 3 ; H c R c p/R R 3 + E
+3 and B c 3 * 3 ; H c R c p/R R 3 + E
+}for/B `w 3 + -2 b " E/B3 B ? 2 b 3 * " E/R B3 0 `w 3 * ; E
+`w `h 8[1 0 0 -1 0 `h]{B3 0 B u ? 1 - 0 c 1 c{d 3 y put O O}for
+{12 * H c 12 ; 3 y p O 12 +}forall O O R}false 3 colorimage
+d O}bind exec}{
+[/Indexed/DeviceRGB `# 1 - T `p " readstring O]setcolorspace
+<</ImageType 1/Width `w/Height `h/BitsPerComponent `b/ImageMatrix[1 0 0 -1 0
+`h]/Decode[`D]/DataSource T>>image T closefile}ifelse}
+%%BeginData:;
+exec
+`S
+%%EndData
+end restore showpage
+%%Trailer
+%%EOF\n)
+
+% at Sun Jun 2 14:31:07 CEST 2002
+% derived from /l128n
+% _l1c_
+/l12hn (%!PS-Adobe-3.0`E
+%%Pages: 1
+`X%%DocumentData: `B
+%%LanguageLevel: 1
+`I%%EndComments
+%%Page: 1 1
+save`s 36 dict begin
+/x{load def}def/E/def x/A/currentfile x/c/exch x/i/ifelse x/S/readhexstring x
+/;/getinterval x/p/putinterval x/b/bitshift x/+/add x/O/pop x/*/mul x/u/dup x
+/-/sub x/"/string x/?/length x/y/copy x{
+{mark A/ASCIIHexDecode filter/T exch def}stopped
+/B exch def cleartomark B{{
+A 12 " u/B c E 0 `p ; S O O/H 3072 " E/R 0 E
+0 1 255{u -6 b B c 3 * 3 ; H c R c p/R R 3 + E
+u -4 b 3 and B c 3 * 3 ; H c R c p/R R 3 + E
+u -2 b 3 and B c 3 * 3 ; H c R c p/R R 3 + E
+3 and B c 3 * 3 ; H c R c p/R R 3 + E
+}for/B `w 3 + -2 b " E/B3 B ? 2 b 3 * " E/R B3 0 `w 3 * ; E
+`w `h 8[1 0 0 -1 0 `h]{B3 0 A B S O
+{12 * H c 12 ; 3 y p O 12 +}forall O O R}false 3 colorimage
+A read O O}bind exec}{
+[/Indexed/DeviceRGB `# 1 - T `p " readstring O]setcolorspace
+<</ImageType 1/Width `w/Height `h/BitsPerComponent `b/ImageMatrix[1 0 0 -1 0
+`h]/Decode[`D]/DataSource T>>image T closefile}ifelse}
+%%BeginData:;
+exec
+`S
+%%EndData
+end restore showpage
+%%Trailer
+%%EOF\n)
+
+
+% at Sun Jun 2 00:05:36 CEST 2002
+% _l1c_
+/l148r (%!PS-Adobe-3.0`E
+%%Pages: 1
+`X%%DocumentData: `B
+%%LanguageLevel: 1
+`I%%EndComments
+%%Page: 1 1
+save`s 36 dict begin
+/x{load def}def/E/def x/A/currentfile x/c/exch x/i/ifelse x/S 32 E/D 0 E/C 0 E
+/;/getinterval x/p/putinterval x/b/bitshift x/+/add x/O/pop x/*/mul x/u/dup x
+/-/sub x/"/string x/?/length x/y/copy x{
+{mark A/ASCII85Decode filter/T exch def}stopped
+/B exch def cleartomark B{{
+/d{{27 S ge{exit}if A read not{511}if u 122 eq{/S 27 E/D 0 E/C 0 E}{u 117 gt{
+A read{O}if/S 54 S - E}{u 33 ge{S 32 eq{u/C c E/D -1670420001 E}{u 117 -{1 85
+7225 614125}S 28 - get * D +/D c E}i/S S 1 - E}if}i}i O}loop S 22 eq{511}{C
+1868977 * D + S 24 and neg b 23 S lt{C 3 * +}if 255 and/S S 3 eq{32}{S 7 mod 3
+eq{22}{S 8 -}i}i E}i}E
+48 " u/B c E 0 `p ; u ? 1 - 0 c 1 c{d 3 y put O O}for O/H 1536 " E/R 0 E
+0 1 255{u -4 b B c 3 * 3 ; H c R c p/R R 3 + E
+15 and B c 3 * 3 ; H c R c p/R R 3 + E
+}for/B `w 1 + -1 b " E/B3 B ? 1 b 3 * " E/R B3 0 `w 3 * ; E/L 128 " E/Ex()E
+`w `h 8[1 0 0 -1 0 `h]{B3 0 B Ex{2 y ? c ? ge{2 y c ? 0 c ; 2 index y ? 2 y c ?
+c - ;/Ex c E O exit}{2 y c y O ? 2 y c ? c - ;}i d u 128 le{L c 0 c 1 + ; u ? 1
+- 0 c 1 c{d 3 y put O O}for}{L c d c 257 c - 3 y 1 - -1 0{3 y c put O}for O O c
+O 0 c ;}i}loop B{6 * H c 6 ; 3 y p O 6 +}forall O O R}false 3 colorimage
+d O d O}bind exec}{
+[/Indexed/DeviceRGB `# 1 - T `p " readstring O]setcolorspace
+/F T/RunLengthDecode filter def<</ImageType 1/Width `w/Height `h
+/BitsPerComponent `b/ImageMatrix[1 0 0 -1 0 `h]/Decode[`D]/DataSource F>>
+image F closefile T closefile
+}ifelse}
+%%BeginData:;
+exec
+`S
+%%EndData
+end restore showpage
+%%Trailer
+%%EOF\n)
+
+% at Sun Jun 2 14:26:37 CEST 2002
+% derived from /l148r
+% _l1c_
+/l14hr (%!PS-Adobe-3.0`E
+%%Pages: 1
+`X%%DocumentData: `B
+%%LanguageLevel: 1
+`I%%EndComments
+%%Page: 1 1
+save`s 36 dict begin
+/x{load def}def/E/def x/A/currentfile x/c/exch x/i/ifelse x/S/readhexstring x
+/;/getinterval x/p/putinterval x/b/bitshift x/+/add x/O/pop x/*/mul x/u/dup x
+/-/sub x/"/string x/?/length x/y/copy x{
+{mark A/ASCIIHexDecode filter/T exch def}stopped
+/B exch def cleartomark B{{
+/C(.)E/d{A C S O 0 get}E
+A 48 " u/B c E 0 `p ; S O O/H 1536 " E/R 0 E
+0 1 255{u -4 b B c 3 * 3 ; H c R c p/R R 3 + E
+15 and B c 3 * 3 ; H c R c p/R R 3 + E
+}for/B `w 1 + -1 b " E/B3 B ? 1 b 3 * " E/R B3 0 `w 3 * ; E/L 128 " E/Ex()E
+`w `h 8[1 0 0 -1 0 `h]{B3 0 B Ex{2 y ? c ? ge{2 y c ? 0 c ; 2 index y ? 2 y c ?
+c - ;/Ex c E O exit}{2 y c y O ? 2 y c ? c - ;}i d u 128 le{L c 0 c 1 + ;
+A c S O}{L c d c 257 c - 3 y 1 - -1 0{3 y c put O}for O O c
+O 0 c ;}i}loop B{6 * H c 6 ; 3 y p O 6 +}forall O O R}false 3 colorimage
+d O A read O O}bind exec}{
+[/Indexed/DeviceRGB `# 1 - T `p " readstring O]setcolorspace
+/F T/RunLengthDecode filter def<</ImageType 1/Width `w/Height `h
+/BitsPerComponent `b/ImageMatrix[1 0 0 -1 0 `h]/Decode[`D]/DataSource F>>
+image F closefile T closefile
+}ifelse}
+%%BeginData:;
+exec
+`S
+%%EndData
+end restore showpage
+%%Trailer
+%%EOF\n)
+
+% at Sun Jun 2 14:49:40 CEST 2002
+% derived from /l14hr
+% _l1c_
+/l14br (%!PS-Adobe-3.0`E
+%%Pages: 1
+`X%%DocumentData: `B
+%%LanguageLevel: 1
+`I%%EndComments
+%%Page: 1 1
+save`s 36 dict begin
+/x{load def}def/E/def x/A/currentfile x/c/exch x/i/ifelse x/S/readstring x
+/;/getinterval x/p/putinterval x/b/bitshift x/+/add x/O/pop x/*/mul x/u/dup x
+/-/sub x/"/string x/?/length x/y/copy x{
+/filter where not{{
+A 48 " u/B c E 0 `p ; S O O/H 1536 " E/R 0 E
+0 1 255{u -4 b B c 3 * 3 ; H c R c p/R R 3 + E
+15 and B c 3 * 3 ; H c R c p/R R 3 + E
+}for/B `w 1 + -1 b " E/B3 B ? 1 b 3 * " E/R B3 0 `w 3 * ; E/L 128 " E/Ex()E
+`w `h 8[1 0 0 -1 0 `h]{B3 0 B Ex{2 y ? c ? ge{2 y c ? 0 c ; 2 index y ? 2 y c ?
+c - ;/Ex c E O exit}{2 y c y O ? 2 y c ? c - ;}i A read O u 128 le{L c 0 c 1 +
+; A c S O}{L c A read O c 257 c - 3 y 1 - -1 0{3 y c put O}for O O c
+O 0 c ;}i}loop B{6 * H c 6 ; 3 y p O 6 +}forall O O R}false 3 colorimage
+A read O O}bind exec}{
+O[/Indexed/DeviceRGB `# 1 - A `p " S O]setcolorspace
+/F A/RunLengthDecode filter def<</ImageType 1/Width `w/Height `h
+/BitsPerComponent `b/ImageMatrix[1 0 0 -1 0 `h]/Decode[`D]/DataSource F>>
+image F closefile}ifelse}
+%%BeginData:;
+exec
+`S
+%%EndData
+end restore showpage
+%%Trailer
+%%EOF\n)
+
+% at Sun Jun 2 12:13:50 CEST 2002
+% _l1c_
+/l148n (%!PS-Adobe-3.0`E
+%%Pages: 1
+`X%%DocumentData: `B
+%%LanguageLevel: 1
+`I%%EndComments
+%%Page: 1 1
+save`s 36 dict begin
+/x{load def}def/E/def x/A/currentfile x/c/exch x/i/ifelse x/S 32 E/D 0 E/C 0 E
+/;/getinterval x/p/putinterval x/b/bitshift x/+/add x/O/pop x/*/mul x/u/dup x
+/-/sub x/"/string x/?/length x/y/copy x{
+{mark A/ASCII85Decode filter/T exch def}stopped
+/B exch def cleartomark B{{
+/d{{27 S ge{exit}if A read not{511}if u 122 eq{/S 27 E/D 0 E/C 0 E}{u 117 gt{
+A read{O}if/S 54 S - E}{u 33 ge{S 32 eq{u/C c E/D -1670420001 E}{u 117 -{1 85
+7225 614125}S 28 - get * D +/D c E}i/S S 1 - E}if}i}i O}loop S 22 eq{511}{C
+1868977 * D + S 24 and neg b 23 S lt{C 3 * +}if 255 and/S S 3 eq{32}{S 7 mod 3
+eq{22}{S 8 -}i}i E}i}E
+48 " u/B c E 0 `p ; u ? 1 - 0 c 1 c{d 3 y put O O}for O/H 1536 " E/R 0 E
+0 1 255{u -4 b B c 3 * 3 ; H c R c p/R R 3 + E
+15 and B c 3 * 3 ; H c R c p/R R 3 + E
+}for/B `w 1 + -1 b " E/B3 B ? 1 b 3 * " E/R B3 0 `w 3 * ; E
+`w `h 8[1 0 0 -1 0 `h]{B3 0 B u ? 1 - 0 c 1 c{d 3 y put O O}for
+{6 * H c 6 ; 3 y p O 6 +}forall O O R}false 3 colorimage
+d O}bind exec}{
+[/Indexed/DeviceRGB `# 1 - T `p " readstring O]setcolorspace
+<</ImageType 1/Width `w/Height `h/BitsPerComponent `b/ImageMatrix[1 0 0 -1 0
+`h]/Decode[`D]/DataSource T>>image T closefile}ifelse}
+%%BeginData:;
+exec
+`S
+%%EndData
+end restore showpage
+%%Trailer
+%%EOF\n)
+
+% at Sun Jun 2 14:34:26 CEST 2002
+% derived from /l148n
+% _l1c_
+/l14hn (%!PS-Adobe-3.0`E
+%%Pages: 1
+`X%%DocumentData: `B
+%%LanguageLevel: 1
+`I%%EndComments
+%%Page: 1 1
+save`s 36 dict begin
+/x{load def}def/E/def x/A/currentfile x/c/exch x/i/ifelse x/S/readhexstring x
+/;/getinterval x/p/putinterval x/b/bitshift x/+/add x/O/pop x/*/mul x/u/dup x
+/-/sub x/"/string x/?/length x/y/copy x{
+{mark A/ASCIIHexDecode filter/T exch def}stopped
+/B exch def cleartomark B{{
+A 48 " u/B c E 0 `p ; S O O/H 1536 " E/R 0 E
+0 1 255{u -4 b B c 3 * 3 ; H c R c p/R R 3 + E
+15 and B c 3 * 3 ; H c R c p/R R 3 + E
+}for/B `w 1 + -1 b " E/B3 B ? 1 b 3 * " E/R B3 0 `w 3 * ; E
+`w `h 8[1 0 0 -1 0 `h]{B3 0 A B S O
+{6 * H c 6 ; 3 y p O 6 +}forall O O R}false 3 colorimage
+A read O O}bind exec}{
+[/Indexed/DeviceRGB `# 1 - T `p " readstring O]setcolorspace
+<</ImageType 1/Width `w/Height `h/BitsPerComponent `b/ImageMatrix[1 0 0 -1 0
+`h]/Decode[`D]/DataSource T>>image T closefile}ifelse}
+%%BeginData:;
+exec
+`S
+%%EndData
+end restore showpage
+%%Trailer
+%%EOF\n)
+
+
+
+% at Sun Jun 2 00:05:36 CEST 2002
+% _l1c_
+/l188r (%!PS-Adobe-3.0`E
+%%Pages: 1
+`X%%DocumentData: `B
+%%LanguageLevel: 1
+`I%%EndComments
+%%Page: 1 1
+save`s 36 dict begin
+/x{load def}def/E/def x/A/currentfile x/c/exch x/i/ifelse x/S 32 E/D 0 E/C 0 E
+/;/getinterval x/p/putinterval x/b/bitshift x/+/add x/O/pop x/*/mul x/u/dup x
+/-/sub x/"/string x/?/length x/y/copy x{
+{mark A/ASCII85Decode filter/T exch def}stopped
+/B exch def cleartomark B{{
+/d{{27 S ge{exit}if A read not{511}if u 122 eq{/S 27 E/D 0 E/C 0 E}{u 117 gt{
+A read{O}if/S 54 S - E}{u 33 ge{S 32 eq{u/C c E/D -1670420001 E}{u 117 -{1 85
+7225 614125}S 28 - get * D +/D c E}i/S S 1 - E}if}i}i O}loop S 22 eq{511}{C
+1868977 * D + S 24 and neg b 23 S lt{C 3 * +}if 255 and/S S 3 eq{32}{S 7 mod 3
+eq{22}{S 8 -}i}i E}i}E
+768 " u/H c E 0 `p ; u ? 1 - 0 c 1 c{d 3 y put O O}for O
+/B `w " E/R `w 3 * " E/L 128 " E/Ex()E
+`w `h 8[1 0 0 -1 0 `h]{R 0 B Ex{2 y ? c ? ge{2 y c ? 0 c ; 2 index y ? 2 y c ?
+c - ;/Ex c E O exit}{2 y c y O ? 2 y c ? c - ;}i d u 128 le{L c 0 c 1 + ; u ? 1
+- 0 c 1 c{d 3 y put O O}for}{L c d c 257 c - 3 y 1 - -1 0{3 y c put O}for O O c
+O 0 c ;}i}loop B{3 * H c 3 ; 3 y p O 3 +}forall O O R}false 3 colorimage
+d O d O}bind exec}{
+[/Indexed/DeviceRGB `# 1 - T `p " readstring O]setcolorspace
+/F T/RunLengthDecode filter def<</ImageType 1/Width `w/Height `h
+/BitsPerComponent `b/ImageMatrix[1 0 0 -1 0 `h]/Decode[`D]/DataSource F>>
+image F closefile T closefile
+}ifelse}
+%%BeginData:;
+exec
+`S
+%%EndData
+end restore showpage
+%%Trailer
+%%EOF\n)
+
+% at Sun Jun 2 00:05:36 CEST 2002
+% derived from /l188r
+% _l1c_
+/l18hr (%!PS-Adobe-3.0`E
+%%Pages: 1
+`X%%DocumentData: `B
+%%LanguageLevel: 1
+`I%%EndComments
+%%Page: 1 1
+save`s 36 dict begin
+/x{load def}def/E/def x/A/currentfile x/c/exch x/i/ifelse x/S/readhexstring x
+/;/getinterval x/p/putinterval x/b/bitshift x/+/add x/O/pop x/*/mul x/u/dup x
+/-/sub x/"/string x/?/length x/y/copy x{
+{mark A/ASCIIHexDecode filter/T exch def}stopped
+/B exch def cleartomark B{{
+/C(.)E/d{A C S O 0 get}E
+A 768 " u/H c E 0 `p ; S O O/B `w " E/R `w 3 * " E/L 128 " E/Ex()E
+`w `h 8[1 0 0 -1 0 `h]{R 0 B Ex{2 y ? c ? ge{2 y c ? 0 c ; 2 index y ? 2 y c ?
+c - ;/Ex c E O exit}{2 y c y O ? 2 y c ? c - ;}i d u 128 le{L c 0 c 1 + ;
+A c S O}{L c d c 257 c - 3 y 1 - -1 0{3 y c put O}for O O c
+O 0 c ;}i}loop B{3 * H c 3 ; 3 y p O 3 +}forall O O R}false 3 colorimage
+d O A read O O}bind exec}{
+[/Indexed/DeviceRGB `# 1 - T `p " readstring O]setcolorspace
+/F T/RunLengthDecode filter def<</ImageType 1/Width `w/Height `h
+/BitsPerComponent `b/ImageMatrix[1 0 0 -1 0 `h]/Decode[`D]/DataSource F>>
+image F closefile T closefile
+}ifelse}
+%%BeginData:;
+exec
+`S
+%%EndData
+end restore showpage
+%%Trailer
+%%EOF\n)
+
+% at Sun Jun 2 00:05:36 CEST 2002
+% derived from /l18hr
+% _l1c_
+/l18br (%!PS-Adobe-3.0`E
+%%Pages: 1
+`X%%DocumentData: `B
+%%LanguageLevel: 1
+`I%%EndComments
+%%Page: 1 1
+save`s 36 dict begin
+/x{load def}def/E/def x/A/currentfile x/c/exch x/i/ifelse x/S/readstring x
+/;/getinterval x/p/putinterval x/b/bitshift x/+/add x/O/pop x/*/mul x/u/dup x
+/-/sub x/"/string x/?/length x/y/copy x{
+/filter where not{{
+A 768 " u/H c E 0 `p ; S O O/B `w " E/R `w 3 * " E/L 128 " E/Ex()E
+`w `h 8[1 0 0 -1 0 `h]{R 0 B Ex{2 y ? c ? ge{2 y c ? 0 c ; 2 index y ? 2 y c ?
+c - ;/Ex c E O exit}{2 y c y O ? 2 y c ? c - ;}i A read O u 128 le{L c 0 c 1 +
+; A c S O}{L c A read O c 257 c - 3 y 1 - -1 0{3 y c put O}for O O c
+O 0 c ;}i}loop B{3 * H c 3 ; 3 y p O 3 +}forall O O R}false 3 colorimage
+A read O O}bind exec}{
+O[/Indexed/DeviceRGB `# 1 - A `p " S O]setcolorspace
+/F A/RunLengthDecode filter def<</ImageType 1/Width `w/Height `h
+/BitsPerComponent `b/ImageMatrix[1 0 0 -1 0 `h]/Decode[`D]/DataSource F>>
+image F closefile}ifelse}
+%%BeginData:;
+exec
+`S
+%%EndData
+end restore showpage
+%%Trailer
+%%EOF\n)
+
+% at Sun Jun 2 12:14:04 CEST 2002
+% derived from /l188r
+% _l1c_
+/l188n (%!PS-Adobe-3.0`E
+%%Pages: 1
+`X%%DocumentData: `B
+%%LanguageLevel: 1
+`I%%EndComments
+%%Page: 1 1
+save`s 36 dict begin
+/x{load def}def/E/def x/A/currentfile x/c/exch x/i/ifelse x/S 32 E/D 0 E/C 0 E
+/;/getinterval x/p/putinterval x/b/bitshift x/+/add x/O/pop x/*/mul x/u/dup x
+/-/sub x/"/string x/?/length x/y/copy x{
+{mark A/ASCII85Decode filter/T exch def}stopped
+/B exch def cleartomark B{{
+/d{{27 S ge{exit}if A read not{511}if u 122 eq{/S 27 E/D 0 E/C 0 E}{u 117 gt{
+A read{O}if/S 54 S - E}{u 33 ge{S 32 eq{u/C c E/D -1670420001 E}{u 117 -{1 85
+7225 614125}S 28 - get * D +/D c E}i/S S 1 - E}if}i}i O}loop S 22 eq{511}{C
+1868977 * D + S 24 and neg b 23 S lt{C 3 * +}if 255 and/S S 3 eq{32}{S 7 mod 3
+eq{22}{S 8 -}i}i E}i}E
+768 " u/H c E 0 `p ; u ? 1 - 0 c 1 c{d 3 y put O O}for O/B `w " E/R `w 3 *
+" E `w `h 8[1 0 0 -1 0 `h]{R 0 B u ? 1 - 0 c 1 c{d 3 y put O O}for
+{3 * H c 3 ; 3 y p O 3 +}forall O O R}false 3 colorimage
+d O}bind exec}{
+[/Indexed/DeviceRGB `# 1 - T `p " readstring O]setcolorspace
+<</ImageType 1/Width `w/Height `h/BitsPerComponent `b/ImageMatrix[1 0 0 -1 0
+`h]/Decode[`D]/DataSource T>>image T closefile}ifelse}
+%%BeginData:;
+exec
+`S
+%%EndData
+end restore showpage
+%%Trailer
+%%EOF\n)
+
+% at Sun Jun 2 12:25:13 CEST 2002
+% derived from l188n
+% _l1c_
+/l18hn (%!PS-Adobe-3.0`E
+%%Pages: 1
+`X%%DocumentData: `B
+%%LanguageLevel: 1
+`I%%EndComments
+%%Page: 1 1
+save`s 36 dict begin
+/x{load def}def/E/def x/A/currentfile x/c/exch x/i/ifelse x/d/readhexstring x
+/;/getinterval x/p/putinterval x/b/bitshift x/+/add x/O/pop x/*/mul x/u/dup x
+/-/sub x/"/string x/?/length x/y/copy x{
+{mark A/ASCIIHexDecode filter/T exch def}stopped
+/B exch def cleartomark B{{
+A 768 " u/H c E 0 `p ; d O O/B `w " E/R `w 3 *
+" E `w `h 8[1 0 0 -1 0 `h]{R 0 A B d O
+{3 * H c 3 ; 3 y p O 3 +}forall O O R}false 3 colorimage
+A read O O}bind exec}{
+[/Indexed/DeviceRGB `# 1 - T `p " readstring O]setcolorspace
+<</ImageType 1/Width `w/Height `h/BitsPerComponent `b/ImageMatrix[1 0 0 -1 0
+`h]/Decode[`D]/DataSource T>>image T closefile}ifelse}
+%%BeginData:;
+exec
+`S
+%%EndData
+end restore showpage
+%%Trailer
+%%EOF\n)
+
+% at Sun Jun 2 14:45:14 CEST 2002
+% derived from /l12hn
+% _l1c_
+/l12bn (%!PS-Adobe-3.0`E
+%%Pages: 1
+`X%%DocumentData: `B
+%%LanguageLevel: 1
+`I%%EndComments
+%%Page: 1 1
+save`s 36 dict begin
+/x{load def}def/E/def x/A/currentfile x/c/exch x/i/ifelse x/S/readstring x
+/;/getinterval x/p/putinterval x/b/bitshift x/+/add x/O/pop x/*/mul x/u/dup x
+/-/sub x/"/string x/?/length x/y/copy x{
+/filter where not{{
+A 12 " u/B c E 0 `p ; S O O/H 3072 " E/R 0 E
+0 1 255{u -6 b B c 3 * 3 ; H c R c p/R R 3 + E
+u -4 b 3 and B c 3 * 3 ; H c R c p/R R 3 + E
+u -2 b 3 and B c 3 * 3 ; H c R c p/R R 3 + E
+3 and B c 3 * 3 ; H c R c p/R R 3 + E
+}for/B `w 3 + -2 b " E/B3 B ? 2 b 3 * " E/R B3 0 `w 3 * ; E
+`w `h 8[1 0 0 -1 0 `h]{B3 0 A B S O
+{12 * H c 12 ; 3 y p O 12 +}forall O O R}false 3 colorimage}bind exec}{
+O[/Indexed/DeviceRGB `# 1 - A `p " S O]setcolorspace
+<</ImageType 1/Width `w/Height `h/BitsPerComponent `b/ImageMatrix[1 0 0 -1 0
+`h]/Decode[`D]/DataSource A>>image}ifelse}
+%%BeginData:;
+exec
+`S
+%%EndData
+end restore showpage
+%%Trailer
+%%EOF\n)
+
+% at Sun Jun 2 14:47:31 CEST 2002
+% derived from /l14hn
+% _l1c_
+/l14bn (%!PS-Adobe-3.0`E
+%%Pages: 1
+`X%%DocumentData: `B
+%%LanguageLevel: 1
+`I%%EndComments
+%%Page: 1 1
+save`s 36 dict begin
+/x{load def}def/E/def x/A/currentfile x/c/exch x/i/ifelse x/S/readstring x
+/;/getinterval x/p/putinterval x/b/bitshift x/+/add x/O/pop x/*/mul x/u/dup x
+/-/sub x/"/string x/?/length x/y/copy x{
+/filter where not{{
+A 48 " u/B c E 0 `p ; S O O/H 1536 " E/R 0 E
+0 1 255{u -4 b B c 3 * 3 ; H c R c p/R R 3 + E
+15 and B c 3 * 3 ; H c R c p/R R 3 + E
+}for/B `w 1 + -1 b " E/B3 B ? 1 b 3 * " E/R B3 0 `w 3 * ; E
+`w `h 8[1 0 0 -1 0 `h]{B3 0 A B S O
+{6 * H c 6 ; 3 y p O 6 +}forall O O R}false 3 colorimage}bind exec}{
+O[/Indexed/DeviceRGB `# 1 - A `p " S O]setcolorspace
+<</ImageType 1/Width `w/Height `h/BitsPerComponent `b/ImageMatrix[1 0 0 -1 0
+`h]/Decode[`D]/DataSource A>>image}ifelse}
+%%BeginData:;
+exec
+`S
+%%EndData
+end restore showpage
+%%Trailer
+%%EOF\n)
+
+% at Sun Jun 2 12:25:13 CEST 2002
+% BUGFIX at Sun Sep 22 20:02:47 CEST 2002
+% derived from l18hn
+% _l1c_
+/l18bn (%!PS-Adobe-3.0`E
+%%Pages: 1
+`X%%DocumentData: `B
+%%LanguageLevel: 1
+`I%%EndComments
+%%Page: 1 1
+save`s 36 dict begin
+/x{load def}def/E/def x/A/currentfile x/c/exch x/i/ifelse x/d/readstring x
+/;/getinterval x/p/putinterval x/b/bitshift x/+/add x/O/pop x/*/mul x/u/dup x
+/-/sub x/"/string x/?/length x/y/copy x{
+/filter where not{{
+A 768 " u/H c E 0 `p ; d O O/B `w " E/R `w 3 *
+" E `w `h 8[1 0 0 -1 0 `h]{R 0 A B d O
+{3 * H c 3 ; 3 y p O 3 +}forall O O R}false 3 colorimage}bind exec}{
+O[/Indexed/DeviceRGB `# 1 - A `p " d O]setcolorspace
+<</ImageType 1/Width `w/Height `h/BitsPerComponent `b/ImageMatrix[1 0 0 -1 0
+`h]/Decode[`D]/DataSource A>>image}ifelse}
+%%BeginData:;
+exec
+`S
+%%EndData
+end restore showpage
+%%Trailer
+%%EOF\n)
+
+% long before Sun Sep 22 13:57:08 CEST 2002
+% /lcrb -> l1gbn
+% /lcr8 -> l1g8n
+% /lcrh -> l1ghn
+
+% ---
+
+% Templates missing from this file:
+% l1g8z: /Compression/ZIP /TransferEncoding/A85 /SampleFormat/Gray* /FileFormat/PSL1
+% (formerly l1fa85g.tte, now: l1zip.psm)
+% l1ghz: /Compression/ZIP /TransferEncoding/Hex /SampleFormat/Gray* /FileFormat/PSL1
+% l1gbz: /Compression/ZIP /TransferEncoding/Binary /SampleFormat/Gray* /FileFormat/PSL1
+% l1g8l: /Compression/LZW /TransferEncoding/A85 /SampleFormat/Gray* /FileFormat/PSL1
+% (formerly l1fa85g.tte, now: l1lzw.psm)
+% l1ghl: /Compression/LZW /TransferEncoding/Hex /SampleFormat/Gray* /FileFormat/PSL1
+% l1gbl: /Compression/LZW /TransferEncoding/Binary /SampleFormat/Gray* /FileFormat/PSL1
+
+%%EOF
diff --git a/graphics/sam2p/c_lgcc.cpp b/graphics/sam2p/c_lgcc.cpp
new file mode 100644
index 0000000000..e7cbcc00af
--- /dev/null
+++ b/graphics/sam2p/c_lgcc.cpp
@@ -0,0 +1,66 @@
+/* c_lgcc.cpp -- make C++ programs linkable with gcc
+ * by pts@fazekas.hu at Tue Sep 3 18:31:58 CEST 2002
+ *
+ * This file is not sam2p-specific. See also AC_PTS_GCC_LINKS_CXX in file
+ * aclocal.m4.
+ */
+
+#include <stdlib.h>
+#include <unistd.h> /* for write(), also available on Windows */
+#include <sys/types.h> /* size_t */
+
+/* Sat Jul 6 16:39:19 CEST 2002
+ * empirical checkerg++ helper routines for gcc version 2.95.2 20000220 (Debian GNU/Linux)
+ */
+#ifdef __CHECKER__
+void* __builtin_vec_new XMALLOC_CODE()
+void __builtin_vec_delete XFREE_CODE()
+void* __builtin_new XMALLOC_CODE()
+void __builtin_delete XFREE_CODE()
+void __rtti_user() { abort(); }
+void __rtti_si() { abort(); }
+void terminate() { abort(); }
+/* void* __pure_virtual=0; -- doesn't work */
+extern "C" void __pure_virtual(); void __pure_virtual() { abort(); }
+
+#else
+
+/* at Tue Sep 3 18:24:26 CEST 2002:
+ * empirical g++-3.2 helper routines for gcc version 3.2.1 20020830 (Debian prerelease)
+ * at Sun Dec 19 19:25:31 CET 2010:
+ * works for g++-4.2.1 and g++-4.4.1 as well
+ * removed dependency on stdio, so we get more reliable OOM reporting
+ */
+static void* emulate_cc_new(unsigned len) { \
+ void *p = malloc(len);
+ if (p == 0) {
+ /* Don't use stdio (e.g. fputs), because that may want to allocate more
+ * memory.
+ */
+ (void)!write(2, "out of memory\n", 14);
+ abort();
+ }
+ return p;
+}
+static void emulate_cc_delete(void* p) {
+ if (p!=0) free(p);
+}
+#if USE_ATTRIBUTE_ALIAS
+void* operator new (size_t len) __attribute__((alias("emulate_cc_new")));
+void* operator new[](size_t len) __attribute__((alias("emulate_cc_new")));
+void operator delete (void* p) __attribute__((alias("emulate_cc_delete")));
+void operator delete[](void* p) __attribute__((alias("emulate_cc_delete")));
+#else /* Darwin o32-clang doesn't have it. */
+void* operator new (size_t len) { return emulate_cc_new(len); }
+void* operator new[](size_t len) { return emulate_cc_new(len); }
+void operator delete (void* p) { return emulate_cc_delete(p); }
+void operator delete[](void* p) { return emulate_cc_delete(p); }
+#endif
+
+void* __cxa_pure_virtual = 0;
+#if 0 /* Needed only if this is not used: -fno-use-cxa-atexit */
+extern "C" void __dso_handle();
+void __dso_handle() {} /* Defined in crtbeginT.o for xstatic. */
+#endif
+
+#endif
diff --git a/graphics/sam2p/c_lgcc3.cpp b/graphics/sam2p/c_lgcc3.cpp
new file mode 100644
index 0000000000..e076ffd74d
--- /dev/null
+++ b/graphics/sam2p/c_lgcc3.cpp
@@ -0,0 +1,31 @@
+/* c_lgcc3.cpp -- make g++-3.2 programs linkable with gcc-2.95
+ * by pts@fazekas.hu at Wed Dec 11 16:33:03 CET 2002
+ *
+ * This file is not sam2p-specific. See also AC_PTS_GCC_LINKS_CXX in file
+ * aclocal.m4.
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+
+/* vvv make these a macro to make them fast */
+#define XMALLOC_CODE() (unsigned len) { \
+ void *p=malloc(len); \
+ if (p==0) { fputs("out of memory\n",stderr); abort(); } \
+ return p; \
+}
+#define XFREE_CODE() (void* p) { if (p!=0) free(p); }
+
+/* at Wed Dec 11 16:31:42 CET 2002
+ * This helper is here for gcc-2.95: c_lgcc3.cpp should be compiled by
+ * gcc-2.95, remaining files are compiled by g++-3.2
+ */
+void* __cxa_pure_virtual=0;
+extern "C" void _ZdlPv (void*);
+extern "C" void* _Znwj (unsigned);
+extern "C" void _ZdaPv (void*);
+extern "C" void* _Znaj (unsigned);
+void _ZdlPv XFREE_CODE()
+void* _Znwj XMALLOC_CODE()
+void _ZdaPv XFREE_CODE()
+void* _Znaj XMALLOC_CODE()
diff --git a/graphics/sam2p/ccdep.pl b/graphics/sam2p/ccdep.pl
new file mode 100644
index 0000000000..987951aadc
--- /dev/null
+++ b/graphics/sam2p/ccdep.pl
@@ -0,0 +1,397 @@
+#! /bin/sh --
+eval '(exit $?0)' && eval 'PERL_BADLANG=x;export PERL_BADLANG;: \
+;exec perl -T -S -- "$0" ${1+"$@"};#'if 0;
+eval 'setenv PERL_BADLANG x;exec perl -x -S -- "$0" $argv:q;#'.q
+#!perl -w
++($0=~/(.*)/s);do$1;die$@if$@;__END__+if 0;
+# Don't touch/remove lines 1--7: http://www.inf.bme.hu/~pts/Magic.Perl.Header
+#
+# ccdep.pl v0.32 -- semiautomatic dependency discovery for C/C++ programs
+# by pts@math.bme.hu at Fri May 31 13:36:29 CEST 2002
+# 0.31 by pts@math.bme.hu at Sat Jun 1 15:19:55 CEST 2002
+# 0.32 by pts@math.bme.hu at Tue Sep 3 19:12:20 CEST 2002
+# 0.33 by pts@math.bme.hu at Thu Oct 31 09:47:25 CET 2002
+#
+# Dat: no -T (tainting checks) anymore, does bad to our readpipe()
+# OK : emit `TARGETS_yes = ...'
+# Imp: make #warning etc. in *.h files work as expected
+# OK : generated.h
+# Imp: add external libraries (-L...)
+# Imp: abort if gcc command not found...
+# Imp: abort if not all .o are mentioned in gcc output
+# Imp: avoid $ etc. in Makefile
+# OK : all 8 combinations of PROVIDES|REQUIRES|CONFLICTS
+#
+BEGIN { eval { require integer; import integer } }
+BEGIN { eval { require strict ; import strict } }
+
+# Typical invocation: ccdep.pl --FAL=assert,no,yes,checker $(CXX)
+my @FAL=();
+if (@ARGV and $ARGV[0]=~/\A--FAL=(.*)/s) { @FAL=split/\W+/,$1; shift@ARGV }
+my $GCCP; # 'g++' or 'gcc': C/C++ preproc with `-E -MG' switches
+$GCCP="@ARGV";
+$GCCP="gcc" if $GCCP!~y/ \t//c;
+
+# Make sure we get English error messages from gcc.
+delete $ENV{LANG};
+delete $ENV{LANGUAGE};
+$ENV{LC_ALL} = "C";
+
+# ---
+
+# Returns true iff the passed filename is a C or C++ source file (and not .o
+# or .h or anything else).
+sub is_ds($) {
+ my $FN = $_[0];
+ return $FN =~ /\.(c(|c|xx|pp|[+][+])|C)\Z(?!\n)/;
+}
+
+sub find_ds() {
+ #** @return a list of .ds file in the current directory
+ my @L; my $E;
+ die unless opendir DIR, '.';
+ while (defined($E=readdir DIR)) {
+ push @L, $E if is_ds($E) and -f $E;
+ }
+ @L
+}
+
+sub expand_glob($$ $) {
+ #** @param $_[0] string containing globs (? and *)
+ #** @param $_[1] listref of names
+ #** @param $_[2] dest listref
+ my $S=quotemeta($_[0]);
+ if (0==($S=~s@\\([?*])@.$1@g)) { push @{$_[2]}, $_[0]; return }
+ my $RE=eval"+sub{\$_[0]=~/$S/}";
+ die$@if$@;
+ for my $E (@{$_[1]}) { push @{$_[2]}, $E if $RE->($E) }
+}
+
+sub mustbe_subset_of($$ $$) {
+ #** A must be a subset (sublist) of B
+ #** @param $_[0] caption A
+ #** @param $_[1] ref(array(string)) A
+ #** @param $_[2] caption B
+ #** @param $_[3] ref(array(string)) B
+ my @A=sort @{$_[1]};
+ my @B=sort @{$_[3]};
+ my($AV,$BV);
+ while (defined($AV=pop@A)) {
+ 1 while defined($BV=pop@B) and $BV gt $AV;
+ if (!defined($BV) or $BV ne $AV) {
+ print STDERR "$0: $_[0] are: @{$_[1]}\n";
+ print STDERR "$0: $_[2] are: @{$_[3]}\n";
+ die "$0: $_[0] must be a subset of $_[2]\n";
+ }
+ }
+}
+
+# ---
+
+print "$0: running.\n";
+
+sub unix_shq($) {
+ my $S=$_[0];
+ $S=~s@'@'\\''@g;
+ "'$S'"
+}
+
+sub shq($) {
+ my $S=$_[0];
+ return $S if $S!~/[^\w.-]/;
+ if ($^O =~ /(?:win32|win64|windows)/i) { # $^O eq 'MSWin32'
+ # assume the called program is CygWin/Ming32; see later
+ # Arguments are delimited by white space, which is either a space or a tab.
+ # . A string surrounded by double quotation marks is interpreted as a
+ # single argument, regardless of white space contained within. A quoted
+ # string can be embedded in an argument. Note that the caret (^) is not
+ # recognized as an escape character or delimiter.
+ # . A double quotation mark preceded by a backslash, \", is interpreted as
+ # a literal double quotation mark (").
+ # . Backslashes are interpreted literally, unless they immediately precede
+ # a double quotation mark.
+ # . If an even number of backslashes is followed by a double quotation
+ # mark, then one backslash (\) is placed in the argv array for every pair
+ # of backslashes (\\), and the double quotation mark (") is interpreted as
+ # a string delimiter.
+ # . If an odd number of backslashes is followed by a double quotation
+ # mark, then one backslash (\) is placed in the argv array for every pair
+ # of backslashes (\\) and the double quotation mark is interpreted as an
+ # escape sequence by the remaining backslash, causing a literal double
+ # quotation mark (") to be placed in argv.
+ $S =~ s@(\\+)(?="|\Z(?!\n))@$1$1@;
+ $S=~s@"@\\"@g; return qq{"$S"}
+ } else {
+ $S=~s@'@'\\''@g; return qq{'$S'}
+ }
+}
+#die shq(q{foo\b"ar\\}) eq q{"foo\b\"ar\\\\"}; # For Win32.
+
+sub backtick(@) {
+ my $S=$_[0];
+ if ($^O eq 'MSWin32') {
+ # assume the called program is CygWin/Ming32; and we have proper /bin/sh
+ $S="sh -c ".unix_shq($S); # /bin/sh can handle IO-redirections such as `2>&1' right
+ } else {
+ # assume UNIX
+ }
+ print "+ $S\n";
+ #die unless $ENV{PATH}=~/(.*)/s; # Dat: untaint()
+ #$ENV{PATH}=$1;
+ #die "$ENV{PATH}";
+ # Dat: if `.' is part of $ENV{PATH}, `Insecure directory...' is reported
+ #die unless $S=~/(.*)/s; # Dat: untaint()
+ readpipe $S # `` qx``
+}
+
+my @DS=find_ds();
+my @DSQ=map{shq$_}@DS;
+# g++-4.6 has it, clang++-3.4 doesn't but we don't care to rerun.
+my $DIAG = "";
+my $Q="$GCCP -DOBJDEP$DIAG -M -MG -E 2>&1 @DSQ";
+my $R=backtick($Q);
+
+if ($R!~/#\s*warning\s/) {
+ # config2.h:314:4: warning: #warning REQUIRES: c_lgcc3.o
+ # Dat: g++-3.3 and g++-4.8 omit #warning (implicit -w) with -M -MG -E.
+ # clang++-3.4 still emits warnings, so no need to rerun here.
+ $R.="\n".backtick("$GCCP -DOBJDEP$DIAG -E 2>&1 >/dev/null @DSQ");
+}
+
+$R =~ s@\\\n@@g; # Merge line continuations emitted by `gcc -M -MG'.
+
+#** $idep{"x.ds"} contains the .h and .ds dependency line for x.ds
+my %idep;
+#** $odep{"x.o"} is "x.ds"
+my %odep;
+my $included_from;
+
+my @instructions;
+
+while ($R=~/\G(.*)\n?/g) {
+ my $S=$1;
+
+ if ($S=~/\AIn file included from (?:[.]\/)*([^:]+)/) {
+ # If foo.cpp includes foo.hpp, which includes bar.hpp, then
+ # clang++-3.4 emits these in a row: foo.cpp, ./foo.hpp, and no bar.hpp.
+ # We want to keep only foo.cpp, hence we check
+ # `if !defined($included_from)'.
+ $included_from=$1 if !defined($included_from);
+ # Bottommost includer.
+ } elsif ($S=~/\A\s{3,}from (?:[.]\/)*([^:]+)/) { # From gcc-3.2.
+ $included_from=$1; # Higher includer, we override the previous one, because we need the topmost one.
+ } elsif ($S=~/\A(?:[.]\/)*([^:]+):\d+:(\d+:)? warning: (?:#warning )?([A-Z][-A-Z]{2,}):(.*)\Z/) {
+ # ^^^ (\d+:)? added for gcc-3.1
+ # ^^^ clang: appliers.cpp:554:6: warning: REQUIRES: out_gif.o [-W#warnings]
+ my($DS,$B,$features)=($1, $3, $4); # $B is e.g. 'PROVIDES'.
+ if (defined $included_from) { $DS=$included_from; undef $included_from }
+ die "$0: #include detection broken: expected non-header source file, got $DS in line: $S\n" if
+ not is_ds($DS);
+ die "$0: unknown dependency verb $B in line: $S\n" if
+ $B !~ m@\A(NULL-PROVIDES|PROVIDES|CONFLICTS|REQUIRES)\Z(?!\n)@;
+ for my $feature (split ' ',$features) {
+ if ($feature !~ m@\A\[-W@) { # g++-4.8 generates extra [-Wcpp] lines.
+ #print "INSTR $DS $B $feature\n";
+ push @instructions, [$DS, $B, $feature];
+ }
+ }
+ } elsif ($S=~/\A([^: ]+)\.o:( ([^: ]+?)\.([^ \n]+).*)\Z/s and $1 eq $3) {
+ # Dependency output of `gcc -M -MG'.
+
+ # $O: The .o file.
+ # $B: All the source dependencies (.cpp, .cxx, .cc, .C, .c, .ci etc.).
+ # $DS: The .ds file: the source file corresponding to the .o file, e.g.
+ # $O is 'encoder.o', $DS is 'encoder.cpp'.
+ my($O,$B,$DS)=("$1.o",$2,"$3.$4");
+ # ^^^ Dat: maybe both t.c and t.cxx
+ $B =~ s@ /[^ ]+@@g; # remove absolute pathnames
+ $B =~ s@\s+@ @g; $B =~ s@\A\s*@ @; $B =~ s@\s*\Z(?!\n)@ @;
+ die "$0: .o file in sources for $DS: $B" if $B =~ m@ [.]o @;
+ # Example reason: foo.c and foo.cpp both present as source files.
+ die "$0: .o file generated from multiple sources: $O and $odep{$O}" if
+ exists $odep{$O};
+ die if exists $idep{$DS}; # Shouldn't happen, $odep{$O} would exist first.
+ $odep{$O}=$DS;
+ $idep{$DS}=$B;
+ push @instructions, [$DS, 'PROVIDES', $O];
+ undef $included_from;
+ } elsif ($S=~/: (?:warning|error|fatal error|fatal):/) {
+ undef $included_from;
+ } else {
+ # Be resilient, and just ignore every other possible message here. This is
+ # for future compatibility with compilers. The infamous `invalid depret'
+ # error by ccdep.pl used to be here, but now it's gone.
+ }
+}
+undef $included_from; # Save memory.
+%odep=(); # Save memory.
+
+#** $pro{"x.ds"} is the list of features provided by "x.ds"; multiplicity
+my %pro;
+#** $req{"x.ds"} is the list of features required by "x.ds"; multiplicity
+my %req;
+#** $con{"x.ds"} is the list of features conflicted by "x.ds"; multiplicity
+my %con;
+#** $repro{"feature"} is a hash=>1 of .ds that provide "feature"
+my %repro;
+#** $mapro{"executable"} eq "x.ds" if "x.ds" provides main() for "executable".
+#** It looks like values are never used.
+my %mapro;
+#** hash=>1 of "feature"s of NULL-PROVIDES
+my %nullpro;
+for my $instruction (@instructions) {
+ my($DS, $verb, $feature) = @$instruction;
+ if ($verb eq 'NULL-PROVIDES') {
+ $nullpro{$feature} = 1;
+ } elsif ($verb eq 'PROVIDES') {
+ push @{$pro{$DS}}, $feature;
+ push @{$con{$DS}}, $feature;
+ $repro{$feature}{$DS}=1;
+ if ($feature=~/\A(.*)_main\Z/) { $mapro{$1}=$DS }
+ } elsif ($verb eq 'REQUIRES') {
+ push @{$req{$DS}}, $feature;
+ } elsif ($verb eq 'CONFLICTS') {
+ push @{$con{$DS}}, $feature;
+ } else {
+ die "$0: unknown verb in instruction: @$instruction\n"; # Never happens.
+ }
+}
+@instructions=(); # Save memory.
+
+mustbe_subset_of "providers"=>[sort keys(%pro)], "dep_sources"=>[sort keys(%idep)];
+mustbe_subset_of "dep_sources"=>[sort keys(%idep)], "sources"=>\@DS;
+
+{ my @K=keys %repro;
+ for my $DS (sort keys%con) {
+ my $L = $con{$DS};
+ my @R=();
+ for my $feature (@$L) { expand_glob $feature, \@K, \@R }
+ # ^^^ multiplicity remains
+ $con{$DS}=\@R;
+ }
+}
+
+my $outfn = "Makedep";
+die unless open MD, "> $outfn";
+die unless print MD '
+ifndef CCALL
+CCALL=$(CC) $(CFLAGS) $(CFLAGSB) $(CPPFLAGS) $(INCLUDES)
+endif
+ifndef CXXALL
+CXXALL=$(CXX) $(CXXFLAGS) $(CXXFLAGSB) $(CPPFLAGS) $(INCLUDES)
+endif
+ifndef LDALL
+LDALL=$(LDY) $(LDFLAGS) $(LIBS)
+endif
+ifndef CC
+CC=gcc
+endif
+ifndef CXX
+CXX=g++
+endif
+ifndef LD
+LD=$(CC) -s
+endif
+ifndef LDXX
+LDXX=$(CXX) -s
+endif
+ifndef LDY
+LDY=$(LD)
+endif
+ifndef CFLAGS
+CFLAGS=-O2 -W -Wall -fsigned-char
+endif
+ifndef CXXFLAGS
+CXXFLAGS=-O2 -W -Wall -fsigned-char
+endif
+ifndef GLOBFILES
+GLOBFILES=Makefile $outfn
+endif
+';
+
+die unless print MD "ALL +=", join(' ',sort keys%mapro), "\n";
+die unless print MD "TARGETS =", join(' ',sort keys%mapro), "\n";
+
+# vvv Thu Oct 31 09:49:02 CET 2002
+# (not required)
+#my %targets_fal;
+#for my $FA (@FAL) { $targets_fal{$FA}="TARGETS_$FA =" }
+
+for my $EXE (sort keys%mapro) {
+ print "exe $EXE\n";
+ my @REQO = (); # Will be list of .o files required by $EXE.
+ my @REQDS = (); # Will be list of .ds files required $EXE.
+ my @REQH = (); # Will be list of .h files required $EXE.
+
+ # Find the transitive dependencies of $EXE, save to @REQO, @REQDS, @REQH.
+ {
+ my %CON=(); # hash=>1 of features already conflicted
+ my %PRO=%nullpro; # hash=>1 of features already provided
+ my $feature;
+ my @features_to_analyze=("${EXE}_main");
+ while (defined($feature=pop@features_to_analyze)) {
+ next if exists $PRO{$feature};
+ #print "feat $feature (@features_to_analyze)\n"; ##
+ # vvv Dat: r.b.e == required by executable
+ die "$0: feature $feature r.b.e $EXE conflicts\n" if exists $CON{$feature};
+ my @L=sort keys%{$repro{$feature}};
+ die "$0: feature $feature r.b.e $EXE unprovided\n" if!@L;
+ die "$0: feature $feature r.b.e $EXE overprovided: @L\n" if$#L>=1;
+ # Now: $L[0] is a .ds providing the feature
+ push @REQDS, $L[0];
+ my $O=$L[0]; $O=~s@\.[^.]+\Z@.o@;
+ push @REQO, $O;
+
+ $PRO{$feature}=1;
+ for my $feature2 (@{$pro{$L[0]}}) {
+ die "$0: extra feature $feature2 r.b.e $EXE conflicts\n" if exists $CON{$feature2} and not exists $PRO{$feature2};
+ $PRO{$feature2}=1;
+ }
+ for my $feature2 (@{$req{$L[0]}}) {
+ push @features_to_analyze, $feature2 if!exists $PRO{$feature2}
+ }
+ for my $feature2 (@{$con{$L[0]}}) { $CON{$feature2}=1 }
+ # die if! exists $PRO{$feature}; # assert
+ }
+ my %REQH;
+ for my $DS (@REQDS) {
+ for my $HDS (split' ', $idep{$DS}) {
+ $REQH{$HDS} = 1 if !is_ds($HDS);
+ }
+ }
+ push @REQH, sort keys %REQH;
+ }
+
+ die unless print MD "${EXE}_DS=@REQDS\n${EXE}_H=@REQH\n".
+ "$EXE: \$(GLOBFILES) @REQO\n\t\$(LDALL) @REQO -o $EXE\n\t".
+ q!@echo "Created executable file: !.$EXE.
+ q! (size: `perl -e 'print -s "!.$EXE.q!"'`)."!. "\n";
+ # vvv Sat Jun 1 15:40:19 CEST 2002
+ for my $FA (@FAL) {
+ die unless print MD
+ "$EXE.$FA: \$(GLOBFILES) \$(${EXE}_DS) \$(${EXE}_H)\n\t".
+ "\$(CXD_$FA) \$(CXDFAL) \$(${EXE}_DS) -o $EXE.$FA\n";
+ # $targets_fal{$FA}.=" $EXE.$FA";
+ }
+}
+print MD "\n";
+
+# vvv Thu Oct 31 09:49:02 CET 2002
+# (not required)
+# for my $FA (@FAL) { print MD "$targets_fal{$FA}\n" }
+# print MD "\n";
+
+for my $K (sort keys%idep) {
+ my $V = $idep{$K};
+ my $O=$K; $O=~s@\.([^.]+)\Z@.o@; my $srcext = $1;
+ my @V = sort split' ', $V;
+ my $compiler = $srcext eq'c'?"CC":"CXX";
+ print MD "$O: \$(GLOBFILES) @V\n\t\$(${compiler}ALL) -c $K\n"
+}
+print MD "\n";
+
+die unless close MD;
+
+print "$0: done, created $outfn\n";
+
+__END__
diff --git a/graphics/sam2p/cgif.c b/graphics/sam2p/cgif.c
new file mode 100644
index 0000000000..428327ed3a
--- /dev/null
+++ b/graphics/sam2p/cgif.c
@@ -0,0 +1,1568 @@
+/* cgif.c -- a merge of some GIF-decoding files from giflib by E.S.Raymond
+ * by pts@fazekas.hu at Wed Feb 27 13:18:04 CET 2002
+
+The GIFLIB distribution is Copyright (c) 1997 Eric S. Raymond
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+THE SOFTWARE.
+ */
+
+/*The creators of the GIF format require the following
+ acknowledgement:
+ The Graphics Interchange Format(c) is the Copyright property of
+ CompuServe Incorporated. GIF(sm) is a Service Mark property of
+ CompuServe Incorporated.
+*/
+
+#ifdef __GNUC__
+#ifndef __clang__
+#pragma implementation
+#endif
+#endif
+
+/**** pts: not an ANSI C function */
+#undef EXTERN_C
+#ifdef __cplusplus
+#define EXTERN_C extern "C"
+#define CGIFFF CGIF::
+#else
+#define EXTERN_C extern
+#define CGIFFF
+#endif
+#if OBJDEP
+# warning PROVIDES: cgif
+#endif
+
+#if 0
+EXTERN_C FILE *fdopen (int fildes, const char *mode); /* GCC 3.0 SUXX */
+#else
+#undef _POSIX_SOURCE
+#define _POSIX_SOURCE 1
+#undef _POSIX_C_SOURCE
+#define _POSIX_C_SOURCE 2
+#endif
+
+/* --- gifalloc.c */
+
+/*****************************************************************************
+* "Gif-Lib" - Yet another gif library. *
+* *
+* Written by: Gershon Elber Ver 0.1, Jun. 1989 *
+* Extensively hacked by: Eric S. Raymond Ver 1.?, Sep 1992 *
+******************************************************************************
+* GIF construction tools *
+******************************************************************************
+* History: *
+* 15 Sep 92 - Version 1.0 by Eric Raymond. *
+*****************************************************************************/
+
+// #undef __STRICT_ANSI__ /* for MINGW32 open() !! */
+#include <stdio.h>
+#include "cgif.h"
+
+/**** pts ****/
+#include <stdlib.h> /* malloc(), calloc(), free(), realloc() */
+#include <string.h> /* memset() */
+
+
+//#include <unistd.h>
+
+#if USE_CGIF_FDOPEN
+#include <fcntl.h> /* open() */
+#include <sys/types.h>
+#include <sys/stat.h>
+# if defined(__MINGW32__) || defined(__CYGWIN__) || defined(_MSC_VER)
+# undef __STRICT_ANSI__
+# include <io.h>
+ /*#define open _open*/
+# endif
+#endif
+
+/* --- gif_err.c */
+
+/*****************************************************************************
+* "Gif-Lib" - Yet another gif library. *
+* *
+* Written by: Gershon Elber IBM PC Ver 0.1, Jun. 1989 *
+******************************************************************************
+* Handle error reporting for the GIF library. *
+******************************************************************************
+* History: *
+* 17 Jun 89 - Version 1.0 by Gershon Elber. *
+*****************************************************************************/
+
+/* #include <stdio.h> already */
+/* #include "gif_lib.h" already */
+
+/* --- dgif_lib.c */
+
+/******************************************************************************
+* "Gif-Lib" - Yet another gif library. *
+* *
+* Written by: Gershon Elber IBM PC Ver 1.1, Aug. 1990 *
+*******************************************************************************
+* The kernel of the GIF Decoding process can be found here. *
+*******************************************************************************
+* History: *
+* 16 Jun 89 - Version 1.0 by Gershon Elber. *
+* 3 Sep 90 - Version 1.1 by Gershon Elber (Support for Gif89, Unique names). *
+******************************************************************************/
+
+#ifdef __MSDOS__
+#include <io.h>
+#include <alloc.h>
+#include <stdlib.h>
+#include <sys\stat.h>
+#else
+#include <sys/types.h>
+#include <sys/stat.h>
+#endif /* __MSDOS__ */
+
+#include <fcntl.h>
+/* #include <stdio.h> already */
+/* #include <string.h> already */
+/* #include "gif_lib.h" already */
+
+/* #include <stdlib.h> already */ /* malloc(), free() */
+#include <assert.h>
+
+/* ---- */
+
+/* --- gif_err.c */
+
+/* #define PROGRAM_NAME "GIF_LIBRARY" */
+
+int CGIFFF _GifError = 0;
+
+/*****************************************************************************
+* Return the last GIF error (0 if none) and reset the error. *
+*****************************************************************************/
+int CGIFFF GifLastError(void)
+{
+ int i = _GifError;
+
+ _GifError = 0;
+
+ return i;
+}
+
+/**** pts ****/
+/** May return NULL. */
+PTS_const char *CGIFFF GetGifError(void)
+{
+ PTS_const char *Err;
+
+ switch(_GifError) {
+#if 0 /**** pts ****/
+ case E_GIF_ERR_OPEN_FAILED:
+ Err = "Failed to open given file";
+ break;
+ case E_GIF_ERR_WRITE_FAILED:
+ Err = "Failed to Write to given file";
+ break;
+ case E_GIF_ERR_HAS_SCRN_DSCR:
+ Err = "Screen Descriptor already been set";
+ break;
+ case E_GIF_ERR_HAS_IMAG_DSCR:
+ Err = "Image Descriptor is still active";
+ break;
+ case E_GIF_ERR_NO_COLOR_MAP:
+ Err = "Neither Global Nor Local color map";
+ break;
+ case E_GIF_ERR_DATA_TOO_BIG:
+ Err = "#Pixels bigger than Width * Height";
+ break;
+ case E_GIF_ERR_NOT_ENOUGH_MEM:
+ Err = "Fail to allocate required memory";
+ break;
+ case E_GIF_ERR_DISK_IS_FULL:
+ Err = "Write failed (disk full?)";
+ break;
+ case E_GIF_ERR_CLOSE_FAILED:
+ Err = "Failed to close given file";
+ break;
+ case E_GIF_ERR_NOT_WRITEABLE:
+ Err = "Given file was not opened for write";
+ break;
+#endif
+ case D_GIF_ERR_OPEN_FAILED:
+ Err = "Failed to open given file";
+ break;
+ case D_GIF_ERR_READ_FAILED:
+ Err = "Failed to Read from given file";
+ break;
+ case D_GIF_ERR_NOT_GIF_FILE:
+ Err = "Given file is NOT GIF file";
+ break;
+ case D_GIF_ERR_NO_SCRN_DSCR:
+ Err = "No Screen Descriptor detected";
+ break;
+ case D_GIF_ERR_NO_IMAG_DSCR:
+ Err = "No Image Descriptor detected";
+ break;
+ case D_GIF_ERR_NO_COLOR_MAP:
+ Err = "Neither Global Nor Local color map";
+ break;
+ case D_GIF_ERR_WRONG_RECORD:
+ Err = "Wrong record type detected";
+ break;
+ case D_GIF_ERR_DATA_TOO_BIG:
+ Err = "#Pixels bigger than Width * Height";
+ break;
+ case D_GIF_ERR_NOT_ENOUGH_MEM:
+ Err = "Fail to allocate required memory";
+ break;
+ case D_GIF_ERR_CLOSE_FAILED:
+ Err = "Failed to close given file";
+ break;
+ case D_GIF_ERR_NOT_READABLE:
+ Err = "Given file was not opened for read";
+ break;
+ case D_GIF_ERR_IMAGE_DEFECT:
+ Err = "Image is defective, decoding aborted";
+ break;
+ case D_GIF_ERR_EOF_TOO_SOON:
+ Err = "Image EOF detected, before image complete";
+ break;
+ default:
+ Err = NULL;
+ break;
+ }
+ return Err;
+}
+
+/*****************************************************************************
+* Print the last GIF error to stderr. *
+*****************************************************************************/
+void CGIFFF PrintGifError(void)
+{
+ PTS_const char *Err=GetGifError();
+ if (Err != NULL)
+ fprintf(stderr, "\nGIF-LIB error: %s.\n", Err);
+ else
+ fprintf(stderr, "\nGIF-LIB undefined error %d.\n", _GifError);
+}
+
+/* --- gifalloc.c */
+
+#define MAXGIF(x, y) (((x) > (y)) ? (x) : (y))
+
+/******************************************************************************
+* Miscellaneous utility functions *
+******************************************************************************/
+
+static int BitSize(int n)
+/* return smallest bitfield size n will fit in */
+{
+ register int i;
+
+ for (i = 1; i <= 8; i++)
+ if ((1 << i) >= n)
+ break;
+ return(i);
+}
+
+
+/******************************************************************************
+* Color map object functions *
+******************************************************************************/
+
+CGIFFF ColorMapObject *CGIFFF MakeMapObject(int ColorCount, GifColorType *ColorMap)
+/*
+ * Allocate a color map of given size; initialize with contents of
+ * ColorMap if that pointer is non-NULL.
+ */
+{
+ ColorMapObject *Object;
+
+ if (ColorCount != (1 << BitSize(ColorCount)))
+ return((ColorMapObject *)NULL);
+
+ Object = (ColorMapObject *)malloc(sizeof(ColorMapObject));
+ if (Object == (ColorMapObject *)NULL)
+ return((ColorMapObject *)NULL);
+
+ Object->Colors = (GifColorType *)calloc(ColorCount, sizeof(GifColorType));
+ if (Object->Colors == (GifColorType *)NULL)
+ return((ColorMapObject *)NULL);
+
+ Object->ColorCount = ColorCount;
+ Object->BitsPerPixel = BitSize(ColorCount);
+
+ if (ColorMap)
+ memcpy((char *)Object->Colors,
+ (char *)ColorMap, ColorCount * sizeof(GifColorType));
+
+ return(Object);
+}
+
+void CGIFFF FreeMapObject(CGIFFF ColorMapObject *Object)
+/*
+ * Free a color map object
+ */
+{
+ free(Object->Colors);
+ free(Object);
+}
+
+#if 0
+void DumpColorMap(ColorMapObject *Object, FILE *fp)
+{
+ if (Object)
+ {
+ int i, j, Len = Object->ColorCount;
+
+ for (i = 0; i < Len; i+=4) {
+ for (j = 0; j < 4 && j < Len; j++) {
+ fprintf(fp,
+ "%3d: %02x %02x %02x ", i + j,
+ Object->Colors[i + j].Red,
+ Object->Colors[i + j].Green,
+ Object->Colors[i + j].Blue);
+ }
+ fprintf(fp, "\n");
+ }
+ }
+}
+#endif /* DEBUG */
+
+#if 0
+ColorMapObject *CGIFFF UnionColorMap(
+ ColorMapObject *ColorIn1,
+ ColorMapObject *ColorIn2,
+ GifPixelType ColorTransIn2[])
+/*
+ * Compute the union of two given color maps and return it. If result can't
+ * fit into 256 colors, NULL is returned, the allocated union otherwise.
+ * ColorIn1 is copied as is to ColorUnion, while colors from ColorIn2 are
+ * copied iff they didn't exist before. ColorTransIn2 maps the old
+ * ColorIn2 into ColorUnion color map table.
+ */
+{
+ int i, j, CrntSlot, RoundUpTo, NewBitSize;
+ ColorMapObject *ColorUnion;
+
+ /*
+ * Allocate table which will hold the result for sure.
+ */
+ ColorUnion
+ = MakeMapObject(MAXGIF(ColorIn1->ColorCount,ColorIn2->ColorCount)*2,NULL);
+
+ if (ColorUnion == NULL)
+ return(NULL);
+
+ /* Copy ColorIn1 to ColorUnionSize; */
+ for (i = 0; i < ColorIn1->ColorCount; i++)
+ ColorUnion->Colors[i] = ColorIn1->Colors[i];
+ CrntSlot = ColorIn1->ColorCount;
+
+ /*
+ * Potentially obnoxious hack:
+ *
+ * Back CrntSlot down past all contiguous {0, 0, 0} slots at the end
+ * of table 1. This is very useful if your display is limited to
+ * 16 colors.
+ */
+ while (ColorIn1->Colors[CrntSlot-1].Red == 0
+ && ColorIn1->Colors[CrntSlot-1].Green == 0
+ && ColorIn1->Colors[CrntSlot-1].Red == 0)
+ CrntSlot--;
+
+ /* Copy ColorIn2 to ColorUnionSize (use old colors if they exist): */
+ for (i = 0; i < ColorIn2->ColorCount && CrntSlot<=256; i++)
+ {
+ /* Let's see if this color already exists: */
+ for (j = 0; j < ColorIn1->ColorCount; j++)
+ if (memcmp(&ColorIn1->Colors[j], &ColorIn2->Colors[i], sizeof(GifColorType)) == 0)
+ break;
+
+ if (j < ColorIn1->ColorCount)
+ ColorTransIn2[i] = j; /* color exists in Color1 */
+ else
+ {
+ /* Color is new - copy it to a new slot: */
+ ColorUnion->Colors[CrntSlot] = ColorIn2->Colors[i];
+ ColorTransIn2[i] = CrntSlot++;
+ }
+ }
+
+ if (CrntSlot > 256)
+ {
+ FreeMapObject(ColorUnion);
+ return((ColorMapObject *)NULL);
+ }
+
+ NewBitSize = BitSize(CrntSlot);
+ RoundUpTo = (1 << NewBitSize);
+
+ if (RoundUpTo != ColorUnion->ColorCount)
+ {
+ register GifColorType *Map = ColorUnion->Colors;
+
+ /*
+ * Zero out slots up to next power of 2.
+ * We know these slots exist because of the way ColorUnion's
+ * start dimension was computed.
+ */
+ for (j = CrntSlot; j < RoundUpTo; j++)
+ Map[j].Red = Map[j].Green = Map[j].Blue = 0;
+
+ /* perhaps we can shrink the map? */
+ if (RoundUpTo < ColorUnion->ColorCount)
+ ColorUnion->Colors
+ = (GifColorType *)realloc(Map, sizeof(GifColorType)*RoundUpTo);
+ }
+
+ ColorUnion->ColorCount = RoundUpTo;
+ ColorUnion->BitsPerPixel = NewBitSize;
+
+ return(ColorUnion);
+}
+void ApplyTranslation(SavedImage *Image, GifPixelType Translation[])
+/*
+ * Apply a given color translation to the raster bits of an image
+ */
+{
+ register int i;
+ register int RasterSize = Image->ImageDesc.Height * Image->ImageDesc.Width;
+
+ for (i = 0; i < RasterSize; i++)
+ Image->RasterBits[i] = Translation[Image->RasterBits[i]];
+}
+#endif
+
+/******************************************************************************
+* Extension record functions *
+******************************************************************************/
+
+#if 0 /**** pts ****/
+void MakeExtension(SavedImage *New, int Function)
+{
+ New->Function = Function;
+ /*
+ * Someday we might have to deal with multiple extensions.
+ */
+}
+#endif
+
+int CGIFFF AddExtensionBlock(CGIFFF SavedImage *New, int Len, CGIFFF GifByteType ExtData[])
+{
+ ExtensionBlock *ep;
+
+ if (New->ExtensionBlocks == NULL)
+ New->ExtensionBlocks = (ExtensionBlock *)malloc(sizeof(ExtensionBlock));
+ else
+ New->ExtensionBlocks =
+ (ExtensionBlock *)realloc(New->ExtensionBlocks,
+ sizeof(ExtensionBlock) * (New->ExtensionBlockCount + 1));
+
+ if (New->ExtensionBlocks == NULL)
+ return(GIF_ERROR);
+
+ ep = &New->ExtensionBlocks[New->ExtensionBlockCount++];
+
+ if ((ep->Bytes = (GifByteType *)malloc(ep->ByteCount = Len)) == NULL)
+ return(GIF_ERROR);
+
+ if (ExtData)
+ memcpy(ep->Bytes, ExtData, Len);
+
+ return(GIF_OK);
+}
+
+void CGIFFF FreeExtension(CGIFFF SavedImage *Image)
+{
+ ExtensionBlock *ep;
+
+ for (ep = Image->ExtensionBlocks;
+ ep < Image->ExtensionBlocks + Image->ExtensionBlockCount;
+ ep++)
+ (void) free((char *)ep->Bytes);
+ free((char *)Image->ExtensionBlocks);
+ Image->ExtensionBlocks = NULL;
+}
+
+/******************************************************************************
+* Image block allocation functions *
+******************************************************************************/
+CGIFFF SavedImage *CGIFFF MakeSavedImage(CGIFFF GifFileType *GifFile, CGIFFF SavedImage *CopyFrom)
+/*
+ * Append an image block to the SavedImages array
+ */
+{
+ SavedImage *sp;
+
+ if (GifFile->SavedImages == NULL)
+ GifFile->SavedImages = (SavedImage *)malloc(sizeof(SavedImage));
+ else
+ GifFile->SavedImages = (SavedImage *)realloc(GifFile->SavedImages,
+ sizeof(SavedImage) * (GifFile->ImageCount+1));
+
+ if (GifFile->SavedImages == NULL)
+ return((SavedImage *)NULL);
+ else
+ {
+ sp = &GifFile->SavedImages[GifFile->ImageCount++];
+ memset((char *)sp, '\0', sizeof(SavedImage));
+
+ if (CopyFrom)
+ {
+ memcpy((char *)sp, CopyFrom, sizeof(SavedImage));
+
+ /*
+ * Make our own allocated copies of the heap fields in the
+ * copied record. This guards against potential aliasing
+ * problems.
+ */
+
+ /* first, the local color map */
+ if (sp->ImageDesc.ColorMap)
+ sp->ImageDesc.ColorMap =
+ MakeMapObject(CopyFrom->ImageDesc.ColorMap->ColorCount,
+ CopyFrom->ImageDesc.ColorMap->Colors);
+
+ /* next, the raster */
+ sp->RasterBits = (GifPixelType *)malloc(sizeof(GifPixelType)
+ * CopyFrom->ImageDesc.Height
+ * CopyFrom->ImageDesc.Width);
+ memcpy(sp->RasterBits,
+ CopyFrom->RasterBits,
+ sizeof(GifPixelType)
+ * CopyFrom->ImageDesc.Height
+ * CopyFrom->ImageDesc.Width);
+
+ /* finally, the extension blocks */
+ if (sp->ExtensionBlocks)
+ {
+ sp->ExtensionBlocks
+ = (ExtensionBlock*)malloc(sizeof(ExtensionBlock)
+ * CopyFrom->ExtensionBlockCount);
+ memcpy(sp->ExtensionBlocks,
+ CopyFrom->ExtensionBlocks,
+ sizeof(ExtensionBlock)
+ * CopyFrom->ExtensionBlockCount);
+
+ /*
+ * For the moment, the actual blocks can take their
+ * chances with free(). We'll fix this later.
+ */
+ }
+ }
+
+ return(sp);
+ }
+}
+
+void CGIFFF FreeSavedImages(CGIFFF GifFileType *GifFile)
+{
+ SavedImage *sp;
+
+ for (sp = GifFile->SavedImages;
+ sp < GifFile->SavedImages + GifFile->ImageCount;
+ sp++)
+ {
+ if (sp->ImageDesc.ColorMap)
+ FreeMapObject(sp->ImageDesc.ColorMap);
+
+ if (sp->RasterBits)
+ free((char *)sp->RasterBits);
+
+ if (sp->ExtensionBlocks)
+ FreeExtension(sp);
+ }
+ free((char *) GifFile->SavedImages);
+}
+
+/* --- dgif_lib.c */
+
+#define GIF_FILE_BUFFER_SIZE 16384 /* Files uses bigger buffers than usual. */
+
+/* #define PROGRAM_NAME "GIFLIB" */
+
+#define COMMENT_EXT_FUNC_CODE 0xfe /* Extension function code for comment. */
+#define GIF_STAMP "GIFVER" /* First chars in file - GIF stamp. */
+#define GIF_STAMP_LEN sizeof(GIF_STAMP) - 1
+#define GIF_VERSION_POS 3 /* Version first character in stamp. */
+
+#define LZ_MAX_CODE 4095 /* Biggest code possible in 12 bits. */
+#define LZ_BITS 12
+
+#define FILE_STATE_READ 0x01/* 1 write, 0 read - EGIF_LIB compatible.*/
+
+#define FLUSH_OUTPUT 4096 /* Impossible code, to signal flush. */
+#define FIRST_CODE 4097 /* Impossible code, to signal first. */
+#define NO_SUCH_CODE 4098 /* Impossible code, to signal empty. */
+
+#define IS_READABLE(Private) (!(Private->FileState & FILE_STATE_READ))
+
+typedef struct GifFilePrivateType {
+ int FileState,
+ /*FileHandle,*/ /* Where all this data goes to! */
+ BitsPerPixel, /* Bits per pixel (Codes uses at list this + 1). */
+ ClearCode, /* The CLEAR LZ code. */
+ EOFCode, /* The EOF LZ code. */
+ RunningCode, /* The next code algorithm can generate. */
+ RunningBits,/* The number of bits required to represent RunningCode. */
+ MaxCode1, /* 1 bigger than max. possible code, in RunningBits bits. */
+ LastCode, /* The code before the current code. */
+ CrntCode, /* Current algorithm code. */
+ StackPtr, /* For character stack (see below). */
+ CrntShiftState; /* Number of bits in CrntShiftDWord. */
+ unsigned long CrntShiftDWord; /* For bytes decomposition into codes. */
+ unsigned long PixelCount; /* Number of pixels in image. */
+ FILE *File; /* File as stream. */
+ CGIFFF GifByteType Buf[256]; /* Compressed input is buffered here. */
+ CGIFFF GifByteType Stack[LZ_MAX_CODE]; /* Decoded pixels are stacked here. */
+ CGIFFF GifByteType Suffix[LZ_MAX_CODE+1]; /* So we can trace the codes. */
+ unsigned int Prefix[LZ_MAX_CODE+1];
+} GifFilePrivateType;
+
+/* extern int _GifError; */
+
+static int DGifGetWord(FILE *File, int *Word);
+static int DGifSetupDecompress(CGIFFF GifFileType *GifFile);
+static int DGifDecompressLine(CGIFFF GifFileType *GifFile, CGIFFF GifPixelType *Line,
+ int LineLen);
+static int DGifGetPrefixChar(unsigned int *Prefix, int Code, int ClearCode);
+static int DGifDecompressInput(GifFilePrivateType *Private, int *Code);
+static int DGifBufferedInput(FILE *File, CGIFFF GifByteType *Buf,
+ CGIFFF GifByteType *NextByte);
+
+/******************************************************************************
+* Open a new gif file for read, given by its name. *
+* Returns GifFileType pointer dynamically allocated which serves as the gif *
+* info record. _GifError is cleared if succesfull. *
+******************************************************************************/
+CGIFFF GifFileType *CGIFFF DGifOpenFileName(const char *FileName) {
+#if 0 /**** pts ****/
+CGIFFF GifFileType *CGIFFF DGifOpenFileName(const char *FileName)
+{
+ int FileHandle;
+
+ if ((FileHandle = open(FileName, O_RDONLY
+#ifdef __MSDOS__
+ | O_BINARY
+#endif /* __MSDOS__ */
+ )) == -1) {
+ _GifError = D_GIF_ERR_OPEN_FAILED;
+ return NULL;
+ }
+
+ return DGifOpenFileHandle(FileHandle);
+#else
+ FILE *f;
+ if (NULL==(f=fopen(FileName,"rb"))) { _GifError=D_GIF_ERR_OPEN_FAILED; return NULL; }
+ return DGifOpenFILE(f);
+#endif
+}
+
+#if USE_CGIF_FDOPEN
+
+/******************************************************************************
+* Update a new gif file, given its file handle. *
+* Returns GifFileType pointer dynamically allocated which serves as the gif *
+* info record. _GifError is cleared if succesfull. *
+******************************************************************************/
+CGIFFF GifFileType *CGIFFF DGifOpenFileHandle(int FileHandle)
+{
+ FILE *f;
+
+#ifdef __MSDOS__
+ setmode(FileHandle, O_BINARY); /* Make sure it is in binary mode. */
+ f = fdopen(FileHandle, "rb"); /* Make it into a stream: */
+ setvbuf(f, NULL, _IOFBF, GIF_FILE_BUFFER_SIZE);/* And inc. stream buffer.*/
+#else
+ f = fdopen(FileHandle, "rb"); /* Make it into a stream: */
+#endif /* __MSDOS__ */
+ return DGifOpenFILE(f);
+}
+#endif
+
+/**** pts ****/
+CGIFFF GifFileType *CGIFFF DGifOpenFILE(void/*FILE*/ *f) {
+ char Buf[GIF_STAMP_LEN+1];
+ GifFileType *GifFile;
+ GifFilePrivateType *Private;
+ if ((GifFile = (GifFileType *) malloc(sizeof(GifFileType))) == NULL) {
+ _GifError = D_GIF_ERR_NOT_ENOUGH_MEM;
+ return NULL;
+ }
+
+ memset(GifFile, '\0', sizeof(GifFileType));
+
+ if ((Private = (GifFilePrivateType *) malloc(sizeof(GifFilePrivateType)))
+ == NULL) {
+ _GifError = D_GIF_ERR_NOT_ENOUGH_MEM;
+ free((char *) GifFile);
+ return NULL;
+ }
+ GifFile->Private = (VoidPtr) Private;
+ /* Private->FileHandle = FileHandle; */
+ Private->File = (FILE*)f;
+ Private->FileState = 0; /* Make sure bit 0 = 0 (File open for read). */
+
+ /* Let's see if this is a GIF file: */
+ if (fread(Buf, 1, GIF_STAMP_LEN, Private->File) != GIF_STAMP_LEN) {
+ _GifError = D_GIF_ERR_READ_FAILED;
+ free((char *) Private);
+ free((char *) GifFile);
+ return NULL;
+ }
+
+ /* The GIF Version number is ignored at this time. Maybe we should do */
+ /* something more useful with it. */
+ Buf[GIF_STAMP_LEN] = 0;
+ if (strncmp(GIF_STAMP, Buf, GIF_VERSION_POS) != 0) {
+ _GifError = D_GIF_ERR_NOT_GIF_FILE;
+ free((char *) Private);
+ free((char *) GifFile);
+ return NULL;
+ }
+
+ if (DGifGetScreenDesc(GifFile) == GIF_ERROR) {
+ free((char *) Private);
+ free((char *) GifFile);
+ return NULL;
+ }
+
+ _GifError = 0;
+
+ return GifFile;
+}
+
+/******************************************************************************
+* This routine should be called before any other DGif calls. Note that *
+* this routine is called automatically from DGif file open routines. *
+******************************************************************************/
+int CGIFFF DGifGetScreenDesc(CGIFFF GifFileType *GifFile)
+{
+ int i, BitsPerPixel;
+ GifByteType Buf[3];
+ GifFilePrivateType *Private = (GifFilePrivateType *) GifFile->Private;
+
+ if (!IS_READABLE(Private)) {
+ /* This file was NOT open for reading: */
+ _GifError = D_GIF_ERR_NOT_READABLE;
+ return GIF_ERROR;
+ }
+
+ /* Put the screen descriptor into the file: */
+ if (DGifGetWord(Private->File, &GifFile->SWidth) == GIF_ERROR ||
+ DGifGetWord(Private->File, &GifFile->SHeight) == GIF_ERROR)
+ return GIF_ERROR;
+
+ if (fread(Buf, 1, 3, Private->File) != 3) {
+ _GifError = D_GIF_ERR_READ_FAILED;
+ return GIF_ERROR;
+ }
+ GifFile->SColorResolution = (((Buf[0] & 0x70) + 1) >> 4) + 1;
+ BitsPerPixel = (Buf[0] & 0x07) + 1;
+ GifFile->SBackGroundColor = Buf[1];
+ // fprintf(stderr, "colres=%d bpp=%d bgcol=%d\n", GifFile->SColorResolution, BitsPerPixel, GifFile->SBackGroundColor);
+ if (Buf[0] & 0x80) { /* Do we have global color map? */
+ // fprintf(stderr, "have gcolormap\n");
+ GifFile->SColorMap = MakeMapObject(1 << BitsPerPixel, NULL);
+
+ /* Get the global color map: */
+ for (i = 0; i < GifFile->SColorMap->ColorCount; i++) {
+ if (fread(Buf, 1, 3, Private->File) != 3) {
+ _GifError = D_GIF_ERR_READ_FAILED;
+ return GIF_ERROR;
+ }
+ GifFile->SColorMap->Colors[i].Red = Buf[0];
+ GifFile->SColorMap->Colors[i].Green = Buf[1];
+ GifFile->SColorMap->Colors[i].Blue = Buf[2];
+ }
+ }
+
+ return GIF_OK;
+}
+
+/******************************************************************************
+* This routine should be called before any attemp to read an image. *
+******************************************************************************/
+int CGIFFF DGifGetRecordType(CGIFFF GifFileType *GifFile, CGIFFF GifRecordType *Type)
+{
+ GifByteType Buf;
+ GifFilePrivateType *Private = (GifFilePrivateType *) GifFile->Private;
+
+ if (!IS_READABLE(Private)) {
+ /* This file was NOT open for reading: */
+ _GifError = D_GIF_ERR_NOT_READABLE;
+ return GIF_ERROR;
+ }
+
+ if (fread(&Buf, 1, 1, Private->File) != 1) {
+ _GifError = D_GIF_ERR_READ_FAILED;
+ return GIF_ERROR;
+ }
+
+ // fprintf(stderr, "record %d at offset %ld\n", Buf&255, ftell(Private->File));
+ switch (Buf) {
+ case ',': *Type = IMAGE_DESC_RECORD_TYPE; break;
+ case '!': *Type = EXTENSION_RECORD_TYPE; break;
+ case ';': *Type = TERMINATE_RECORD_TYPE; break;
+ default: *Type = UNDEFINED_RECORD_TYPE;
+ // fprintf(stderr, "wrong record %d at offset %ld\n", Buf&255, ftell(Private->File));
+ _GifError = D_GIF_ERR_WRONG_RECORD;
+ return GIF_ERROR;
+ }
+
+ return GIF_OK;
+}
+
+/******************************************************************************
+* This routine should be called before any attemp to read an image. *
+* Note it is assumed the Image desc. header (',') has been read. *
+******************************************************************************/
+int CGIFFF DGifGetImageDesc(CGIFFF GifFileType *GifFile)
+{
+ int i, BitsPerPixel;
+ GifByteType Buf[3];
+ GifImageDesc Image;
+ GifFilePrivateType *Private = (GifFilePrivateType *) GifFile->Private;
+ memset(&Image, 0, sizeof(Image));
+
+ if (!IS_READABLE(Private)) {
+ /* This file was NOT open for reading: */
+ _GifError = D_GIF_ERR_NOT_READABLE;
+ return GIF_ERROR;
+ }
+
+ if (DGifGetWord(Private->File, &Image.Left) == GIF_ERROR ||
+ DGifGetWord(Private->File, &Image.Top) == GIF_ERROR ||
+ DGifGetWord(Private->File, &Image.Width) == GIF_ERROR ||
+ DGifGetWord(Private->File, &Image.Height) == GIF_ERROR)
+ return GIF_ERROR;
+ if (fread(Buf, 1, 1, Private->File) != 1) {
+ _GifError = D_GIF_ERR_READ_FAILED;
+ return GIF_ERROR;
+ }
+ BitsPerPixel = (Buf[0] & 0x07) + 1;
+ Image.Interlace = (Buf[0] & 0x40);
+ if (Buf[0] & 0x80) { /* Does this image have local color map? */
+
+ if (Image.ColorMap && GifFile->SavedImages == NULL)
+ FreeMapObject(Image.ColorMap);
+
+ Image.ColorMap = MakeMapObject(1 << BitsPerPixel, NULL);
+
+ /* Get the image local color map: */
+ for (i = 0; i < Image.ColorMap->ColorCount; i++) {
+ if (fread(Buf, 1, 3, Private->File) != 3) {
+ _GifError = D_GIF_ERR_READ_FAILED;
+ return GIF_ERROR;
+ }
+ Image.ColorMap->Colors[i].Red = Buf[0];
+ Image.ColorMap->Colors[i].Green = Buf[1];
+ Image.ColorMap->Colors[i].Blue = Buf[2];
+ }
+ }
+
+ /**** pts ****/
+ if (NULL!=GifFile->SavedImages) {
+ GifFile->SavedImages = (SavedImage *)realloc(GifFile->SavedImages,
+ sizeof(SavedImage) * (GifFile->ImageCount + 1));
+ } else {
+ assert(GifFile->ImageCount==0);
+ GifFile->SavedImages = (SavedImage *)malloc(sizeof(SavedImage));
+ }
+ if (NULL==GifFile->SavedImages) {
+ _GifError = D_GIF_ERR_NOT_ENOUGH_MEM;
+ return GIF_ERROR;
+ }
+
+ {
+ SavedImage *sp;
+ sp = &GifFile->SavedImages[GifFile->ImageCount];
+ memcpy(&sp->ImageDesc, &Image, sizeof(GifImageDesc));
+ sp->RasterBits = (GifPixelType *)NULL;
+ sp->ExtensionBlockCount = 0;
+ sp->ExtensionBlocks = (ExtensionBlock *)NULL;
+ sp->delay=0;
+ sp->dispose=0;
+ sp->iter=1;
+ sp->transp=(-1);
+ }
+
+ GifFile->ImageCount++;
+
+ Private->PixelCount = (long) Image.Width *
+ (long) Image.Height;
+
+ DGifSetupDecompress(GifFile); /* Reset decompress algorithm parameters. */
+
+ return GIF_OK;
+}
+
+/******************************************************************************
+* Get one full scanned line (Line) of length LineLen from GIF file. *
+******************************************************************************/
+int CGIFFF DGifGetLine(CGIFFF GifFileType *GifFile, CGIFFF GifPixelType *Line, int LineLen)
+{
+ GifByteType *Dummy;
+ GifFilePrivateType *Private = (GifFilePrivateType *) GifFile->Private;
+
+ if (!IS_READABLE(Private)) {
+ /* This file was NOT open for reading: */
+ _GifError = D_GIF_ERR_NOT_READABLE;
+ return GIF_ERROR;
+ }
+
+ /**** pts ****/
+ /* if (!LineLen) LineLen = GifFile->Image.Width; */
+
+#if defined(__MSDOS__) || defined(__GNUC__)
+ if ((Private->PixelCount -= LineLen) > 0xffff0000UL) {
+#else
+ if ((Private->PixelCount -= LineLen) > 0xffff0000) {
+#endif /* __MSDOS__ */
+ _GifError = D_GIF_ERR_DATA_TOO_BIG;
+ return GIF_ERROR;
+ }
+
+ if (DGifDecompressLine(GifFile, Line, LineLen) == GIF_OK) {
+ if (Private->PixelCount == 0) {
+ /* We probably would not be called any more, so lets clean */
+ /* everything before we return: need to flush out all rest of */
+ /* image until empty block (size 0) detected. We use GetCodeNext.*/
+ do if (DGifGetCodeNext(GifFile, &Dummy) == GIF_ERROR)
+ return GIF_ERROR;
+ while (Dummy != NULL);
+ }
+ return GIF_OK;
+ }
+ else
+ return GIF_ERROR;
+}
+
+/******************************************************************************
+* Put one pixel (Pixel) into GIF file. *
+******************************************************************************/
+int CGIFFF DGifGetPixel(CGIFFF GifFileType *GifFile, CGIFFF GifPixelType Pixel)
+{
+ GifByteType *Dummy;
+ GifFilePrivateType *Private = (GifFilePrivateType *) GifFile->Private;
+
+ if (!IS_READABLE(Private)) {
+ /* This file was NOT open for reading: */
+ _GifError = D_GIF_ERR_NOT_READABLE;
+ return GIF_ERROR;
+ }
+
+#if defined(__MSDOS__) || defined(__GNUC__)
+ if (--Private->PixelCount > 0xffff0000UL)
+#else
+ if (--Private->PixelCount > 0xffff0000)
+#endif /* __MSDOS__ */
+ {
+ _GifError = D_GIF_ERR_DATA_TOO_BIG;
+ return GIF_ERROR;
+ }
+
+ if (DGifDecompressLine(GifFile, &Pixel, 1) == GIF_OK) {
+ if (Private->PixelCount == 0) {
+ /* We probably would not be called any more, so lets clean */
+ /* everything before we return: need to flush out all rest of */
+ /* image until empty block (size 0) detected. We use GetCodeNext.*/
+ do if (DGifGetCodeNext(GifFile, &Dummy) == GIF_ERROR)
+ return GIF_ERROR;
+ while (Dummy != NULL);
+ }
+ return GIF_OK;
+ }
+ else
+ return GIF_ERROR;
+}
+
+/******************************************************************************
+* Get an extension block (see GIF manual) from gif file. This routine only *
+* returns the first data block, and DGifGetExtensionNext shouldbe called *
+* after this one until NULL extension is returned. *
+* The Extension should NOT be freed by the user (not dynamically allocated).*
+* Note it is assumed the Extension desc. header ('!') has been read. *
+******************************************************************************/
+int CGIFFF DGifGetExtension(CGIFFF GifFileType *GifFile, int *ExtCode,
+ CGIFFF GifByteType **Extension)
+{
+ GifByteType Buf;
+ GifFilePrivateType *Private = (GifFilePrivateType *) GifFile->Private;
+
+
+ if (!IS_READABLE(Private)) {
+ /* This file was NOT open for reading: */
+ _GifError = D_GIF_ERR_NOT_READABLE;
+ return GIF_ERROR;
+ }
+
+ if (fread(&Buf, 1, 1, Private->File) != 1) {
+ _GifError = D_GIF_ERR_READ_FAILED;
+ return GIF_ERROR;
+ }
+ *ExtCode = Buf;
+
+ return DGifGetExtensionNext(GifFile, Extension);
+}
+
+/******************************************************************************
+* Get a following extension block (see GIF manual) from gif file. This *
+* routine sould be called until NULL Extension is returned. *
+* The Extension should NOT be freed by the user (not dynamically allocated).*
+******************************************************************************/
+int CGIFFF DGifGetExtensionNext(CGIFFF GifFileType *GifFile, CGIFFF GifByteType **Extension)
+{
+ GifByteType Buf;
+ GifFilePrivateType *Private = (GifFilePrivateType *) GifFile->Private;
+
+ if (fread(&Buf, 1, 1, Private->File) != 1) {
+ _GifError = D_GIF_ERR_READ_FAILED;
+ return GIF_ERROR;
+ }
+ if (Buf > 0) {
+ *Extension = Private->Buf; /* Use private unused buffer. */
+ (*Extension)[0] = Buf; /* Pascal strings notation (pos. 0 is len.). */
+ if (fread(&((*Extension)[1]), 1, Buf, Private->File) != Buf) {
+ _GifError = D_GIF_ERR_READ_FAILED;
+ return GIF_ERROR;
+ }
+ }
+ else
+ *Extension = NULL;
+
+ return GIF_OK;
+}
+
+/******************************************************************************
+* This routine should be called last, to close the GIF file. *
+******************************************************************************/
+int CGIFFF DGifCloseFile(CGIFFF GifFileType *GifFile)
+{
+ GifFilePrivateType *Private;
+
+ if (GifFile == NULL) return GIF_ERROR;
+
+ Private = (GifFilePrivateType *) GifFile->Private;
+
+ if (!IS_READABLE(Private)) {
+ /* This file was NOT open for reading: */
+ _GifError = D_GIF_ERR_NOT_READABLE;
+ return GIF_ERROR;
+ }
+
+ #if 0 /**** pts ****/
+ if (GifFile->Image.ColorMap)
+ FreeMapObject(GifFile->Image.ColorMap);
+ #endif
+ if (GifFile->SColorMap)
+ FreeMapObject(GifFile->SColorMap);
+ if (Private)
+ free((char *) Private);
+ if (GifFile->SavedImages)
+ FreeSavedImages(GifFile);
+ free(GifFile);
+
+#if 0 /**** pts ****/
+ if (fclose(File) != 0) {
+ _GifError = D_GIF_ERR_CLOSE_FAILED;
+ return GIF_ERROR;
+ }
+#endif
+ return GIF_OK;
+}
+
+/******************************************************************************
+* Get 2 bytes (word) from the given file: *
+******************************************************************************/
+static int DGifGetWord(FILE *File, int *Word)
+{
+ unsigned char c[2];
+
+ if (fread(c, 1, 2, File) != 2) {
+ CGIFFF _GifError = D_GIF_ERR_READ_FAILED;
+ return GIF_ERROR;
+ }
+
+ *Word = (((unsigned int) c[1]) << 8) + c[0];
+ return GIF_OK;
+}
+
+/******************************************************************************
+* Get the image code in compressed form. his routine can be called if the *
+* information needed to be piped out as is. Obviously this is much faster *
+* than decoding and encoding again. This routine should be followed by calls *
+* to DGifGetCodeNext, until NULL block is returned. *
+* The block should NOT be freed by the user (not dynamically allocated). *
+******************************************************************************/
+int CGIFFF DGifGetCode(CGIFFF GifFileType *GifFile, int *CodeSize, CGIFFF GifByteType **CodeBlock)
+{
+ GifFilePrivateType *Private = (GifFilePrivateType *) GifFile->Private;
+
+ if (!IS_READABLE(Private)) {
+ /* This file was NOT open for reading: */
+ _GifError = D_GIF_ERR_NOT_READABLE;
+ return GIF_ERROR;
+ }
+
+ *CodeSize = Private->BitsPerPixel;
+
+ return DGifGetCodeNext(GifFile, CodeBlock);
+}
+
+/******************************************************************************
+* Continue to get the image code in compressed form. This routine should be *
+* called until NULL block is returned. *
+* The block should NOT be freed by the user (not dynamically allocated). *
+******************************************************************************/
+int CGIFFF DGifGetCodeNext(CGIFFF GifFileType *GifFile, CGIFFF GifByteType **CodeBlock)
+{
+ GifByteType Buf;
+ GifFilePrivateType *Private = (GifFilePrivateType *) GifFile->Private;
+
+ if (fread(&Buf, 1, 1, Private->File) != 1) {
+ _GifError = D_GIF_ERR_READ_FAILED;
+ return GIF_ERROR;
+ }
+
+ if (Buf > 0) {
+ *CodeBlock = Private->Buf; /* Use private unused buffer. */
+ (*CodeBlock)[0] = Buf; /* Pascal strings notation (pos. 0 is len.). */
+ if (fread(&((*CodeBlock)[1]), 1, Buf, Private->File) != Buf) {
+ _GifError = D_GIF_ERR_READ_FAILED;
+ return GIF_ERROR;
+ }
+ }
+ else {
+ *CodeBlock = NULL;
+ Private->Buf[0] = 0; /* Make sure the buffer is empty! */
+ Private->PixelCount = 0; /* And local info. indicate image read. */
+ }
+
+ return GIF_OK;
+}
+
+/******************************************************************************
+* Setup the LZ decompression for this image: *
+******************************************************************************/
+static int DGifSetupDecompress(CGIFFF GifFileType *GifFile)
+{
+ int i, BitsPerPixel;
+ CGIFFF GifByteType CodeSize;
+ unsigned int *Prefix;
+ GifFilePrivateType *Private = (GifFilePrivateType *) GifFile->Private;
+
+ if (fread(&CodeSize, 1, 1, Private->File) != 1) /* Read Code size from file. */
+ return GIF_ERROR;
+ BitsPerPixel = CodeSize;
+
+ Private->Buf[0] = 0; /* Input Buffer empty. */
+ Private->BitsPerPixel = BitsPerPixel;
+ Private->ClearCode = (1 << BitsPerPixel);
+ Private->EOFCode = Private->ClearCode + 1;
+ Private->RunningCode = Private->EOFCode + 1;
+ Private->RunningBits = BitsPerPixel + 1; /* Number of bits per code. */
+ Private->MaxCode1 = 1 << Private->RunningBits; /* Max. code + 1. */
+ Private->StackPtr = 0; /* No pixels on the pixel stack. */
+ Private->LastCode = NO_SUCH_CODE;
+ Private->CrntShiftState = 0; /* No information in CrntShiftDWord. */
+ Private->CrntShiftDWord = 0;
+
+ Prefix = Private->Prefix;
+ for (i = 0; i <= LZ_MAX_CODE; i++) Prefix[i] = NO_SUCH_CODE;
+
+ return GIF_OK;
+}
+
+/******************************************************************************
+* The LZ decompression routine: *
+* This version decompress the given gif file into Line of length LineLen. *
+* This routine can be called few times (one per scan line, for example), in *
+* order the complete the whole image. *
+******************************************************************************/
+static int DGifDecompressLine(CGIFFF GifFileType *GifFile, CGIFFF GifPixelType *Line,
+ int LineLen)
+{
+ int i = 0, j, CrntCode, EOFCode, ClearCode, CrntPrefix, LastCode, StackPtr;
+ CGIFFF GifByteType *Stack, *Suffix;
+ unsigned int *Prefix;
+ GifFilePrivateType *Private = (GifFilePrivateType *) GifFile->Private;
+
+ StackPtr = Private->StackPtr;
+ Prefix = Private->Prefix;
+ Suffix = Private->Suffix;
+ Stack = Private->Stack;
+ EOFCode = Private->EOFCode;
+ ClearCode = Private->ClearCode;
+ LastCode = Private->LastCode;
+
+ if (StackPtr != 0) {
+ /* Let pop the stack off before continueing to read the gif file: */
+ while (StackPtr != 0 && i < LineLen) Line[i++] = Stack[--StackPtr];
+ }
+
+ while (i < LineLen) { /* Decode LineLen items. */
+ if (DGifDecompressInput(Private, &CrntCode) == GIF_ERROR)
+ return GIF_ERROR;
+
+ /*fprintf(stderr,"CrntCode=0x%x\n",CrntCode);*/
+ if (CrntCode == EOFCode) {
+ /* Note however that usually we will not be here as we will stop */
+ /* decoding as soon as we got all the pixel, or EOF code will */
+ /* not be read at all, and DGifGetLine/Pixel clean everything. */
+ if (i != LineLen - 1 || Private->PixelCount != 0) {
+ CGIFFF _GifError = D_GIF_ERR_EOF_TOO_SOON;
+ return GIF_ERROR;
+ }
+ i++;
+ }
+ else if (CrntCode == ClearCode) {
+ /* We need to start over again: */
+ for (j = 0; j <= LZ_MAX_CODE; j++) Prefix[j] = NO_SUCH_CODE;
+ Private->RunningCode = Private->EOFCode + 1;
+ Private->RunningBits = Private->BitsPerPixel + 1;
+ Private->MaxCode1 = 1 << Private->RunningBits;
+ LastCode = Private->LastCode = NO_SUCH_CODE;
+ }
+ else {
+ /* Its regular code - if in pixel range simply add it to output */
+ /* stream, otherwise trace to codes linked list until the prefix */
+ /* is in pixel range: */
+ if (CrntCode < ClearCode) {
+ /* This is simple - its pixel scalar, so add it to output: */
+ Line[i++] = CrntCode;
+ }
+ else {
+ /* Its a code to needed to be traced: trace the linked list */
+ /* until the prefix is a pixel, while pushing the suffix */
+ /* pixels on our stack. If we done, pop the stack in reverse */
+ /* (thats what stack is good for!) order to output. */
+ if (Prefix[CrntCode] == NO_SUCH_CODE) {
+ /* Only allowed if CrntCode is exactly the running code: */
+ /* In that case CrntCode = XXXCode, CrntCode or the */
+ /* prefix code is last code and the suffix char is */
+ /* exactly the prefix of last code! */
+ if (CrntCode == Private->RunningCode - 2) {
+ CrntPrefix = LastCode;
+ Suffix[Private->RunningCode - 2] =
+ Stack[StackPtr++] = DGifGetPrefixChar(Prefix,
+ LastCode, ClearCode);
+ }
+ else {
+ CGIFFF _GifError = D_GIF_ERR_IMAGE_DEFECT;
+ return GIF_ERROR;
+ }
+ }
+ else
+ CrntPrefix = CrntCode;
+
+ /* Now (if image is O.K.) we should not get an NO_SUCH_CODE */
+ /* During the trace. As we might loop forever, in case of */
+ /* defective image, we count the number of loops we trace */
+ /* and stop if we got LZ_MAX_CODE. obviously we can not */
+ /* loop more than that. */
+ j = 0;
+ while (j++ <= LZ_MAX_CODE &&
+ CrntPrefix > ClearCode &&
+ CrntPrefix <= LZ_MAX_CODE) {
+ Stack[StackPtr++] = Suffix[CrntPrefix];
+ CrntPrefix = Prefix[CrntPrefix];
+ }
+ if (j >= LZ_MAX_CODE || CrntPrefix > LZ_MAX_CODE) {
+ CGIFFF _GifError = D_GIF_ERR_IMAGE_DEFECT;
+ return GIF_ERROR;
+ }
+ /* Push the last character on stack: */
+ Stack[StackPtr++] = CrntPrefix;
+
+ /* Now lets pop all the stack into output: */
+ while (StackPtr != 0 && i < LineLen)
+ Line[i++] = Stack[--StackPtr];
+ }
+ if (LastCode != NO_SUCH_CODE) {
+ Prefix[Private->RunningCode - 2] = LastCode;
+
+ if (CrntCode == Private->RunningCode - 2) {
+ /* Only allowed if CrntCode is exactly the running code: */
+ /* In that case CrntCode = XXXCode, CrntCode or the */
+ /* prefix code is last code and the suffix char is */
+ /* exactly the prefix of last code! */
+ Suffix[Private->RunningCode - 2] =
+ DGifGetPrefixChar(Prefix, LastCode, ClearCode);
+ }
+ else {
+ Suffix[Private->RunningCode - 2] =
+ DGifGetPrefixChar(Prefix, CrntCode, ClearCode);
+ }
+ }
+ LastCode = CrntCode;
+ }
+ }
+
+ Private->LastCode = LastCode;
+ Private->StackPtr = StackPtr;
+
+ return GIF_OK;
+}
+
+/******************************************************************************
+* Routine to trace the Prefixes linked list until we get a prefix which is *
+* not code, but a pixel value (less than ClearCode). Returns that pixel value.*
+* If image is defective, we might loop here forever, so we limit the loops to *
+* the maximum possible if image O.k. - LZ_MAX_CODE times. *
+******************************************************************************/
+static int DGifGetPrefixChar(unsigned int *Prefix, int Code, int ClearCode)
+{
+ int i = 0;
+
+ while (Code > ClearCode && i++ <= LZ_MAX_CODE) Code = Prefix[Code];
+ return Code;
+}
+
+/******************************************************************************
+* Interface for accessing the LZ codes directly. Set Code to the real code *
+* (12bits), or to -1 if EOF code is returned. *
+******************************************************************************/
+int CGIFFF DGifGetLZCodes(CGIFFF GifFileType *GifFile, int *Code)
+{
+ GifByteType *CodeBlock;
+ GifFilePrivateType *Private = (GifFilePrivateType *) GifFile->Private;
+
+ if (!IS_READABLE(Private)) {
+ /* This file was NOT open for reading: */
+ _GifError = D_GIF_ERR_NOT_READABLE;
+ return GIF_ERROR;
+ }
+
+ if (DGifDecompressInput(Private, Code) == GIF_ERROR)
+ return GIF_ERROR;
+
+ if (*Code == Private->EOFCode) {
+ /* Skip rest of codes (hopefully only NULL terminating block): */
+ do if (DGifGetCodeNext(GifFile, &CodeBlock) == GIF_ERROR)
+ return GIF_ERROR;
+ while (CodeBlock != NULL);
+
+ *Code = -1;
+ }
+ else if (*Code == Private->ClearCode) {
+ /* We need to start over again: */
+ Private->RunningCode = Private->EOFCode + 1;
+ Private->RunningBits = Private->BitsPerPixel + 1;
+ Private->MaxCode1 = 1 << Private->RunningBits;
+ }
+
+ return GIF_OK;
+}
+
+/******************************************************************************
+* The LZ decompression input routine: *
+* This routine is responsable for the decompression of the bit stream from *
+* 8 bits (bytes) packets, into the real codes. *
+* Returns GIF_OK if read succesfully. *
+******************************************************************************/
+static int DGifDecompressInput(GifFilePrivateType *Private, int *Code)
+{
+ CGIFFF GifByteType NextByte;
+ static unsigned int CodeMasks[] = {
+ 0x0000, 0x0001, 0x0003, 0x0007,
+ 0x000f, 0x001f, 0x003f, 0x007f,
+ 0x00ff, 0x01ff, 0x03ff, 0x07ff,
+ 0x0fff
+ };
+
+ while (Private->CrntShiftState < Private->RunningBits) {
+ /* Needs to get more bytes from input stream for next code: */
+ if (DGifBufferedInput(Private->File, Private->Buf, &NextByte)
+ == GIF_ERROR) {
+ return GIF_ERROR;
+ }
+ Private->CrntShiftDWord |=
+ ((unsigned long) NextByte) << Private->CrntShiftState;
+ Private->CrntShiftState += 8;
+ }
+ *Code = Private->CrntShiftDWord & CodeMasks[Private->RunningBits];
+
+ Private->CrntShiftDWord >>= Private->RunningBits;
+ Private->CrntShiftState -= Private->RunningBits;
+
+ /* If code cannt fit into RunningBits bits, must raise its size. Note */
+ /* however that codes above 4095 are used for special signaling. */
+ if (++Private->RunningCode > Private->MaxCode1 &&
+ Private->RunningBits < LZ_BITS) {
+ Private->MaxCode1 <<= 1;
+ Private->RunningBits++;
+ }
+ return GIF_OK;
+}
+
+/******************************************************************************
+* This routines read one gif data block at a time and buffers it internally *
+* so that the decompression routine could access it. *
+* The routine returns the next byte from its internal buffer (or read next *
+* block in if buffer empty) and returns GIF_OK if succesful. *
+******************************************************************************/
+static int DGifBufferedInput(FILE *File, CGIFFF GifByteType *Buf,
+ CGIFFF GifByteType *NextByte)
+{
+ if (Buf[0] == 0) {
+ /* Needs to read the next buffer - this one is empty: */
+ if (fread(Buf, 1, 1, File) != 1)
+ {
+ CGIFFF _GifError = D_GIF_ERR_READ_FAILED;
+ return GIF_ERROR;
+ }
+ if (fread(&Buf[1], 1, Buf[0], File) != Buf[0])
+ {
+ CGIFFF _GifError = D_GIF_ERR_READ_FAILED;
+ return GIF_ERROR;
+ }
+ *NextByte = Buf[1];
+ Buf[1] = 2; /* We use now the second place as last char read! */
+ Buf[0]--;
+ }
+ else {
+ *NextByte = Buf[Buf[1]++];
+ Buf[0]--;
+ }
+
+ return GIF_OK;
+}
+
+/******************************************************************************
+* This routine reads an entire GIF into core, hanging all its state info off *
+* the GifFileType pointer. Call DGifOpenFileName() or DGifOpenFileHandle() *
+* first to initialize I/O. Its inverse is EGifSpew(). *
+******************************************************************************/
+int CGIFFF DGifSlurp(CGIFFF GifFileType *GifFile)
+{
+ static unsigned InterlacedOffset[] = { 0, 4, 2, 1 }, /* The way Interlaced image should. */
+ InterlacedJumps[] = { 8, 8, 4, 2 }; /* be read - offsets and jumps... */
+ /**** pts: unused vars ****/
+ /* int i, j, Error, ImageSize; */
+ int ext_code;
+
+ GifRecordType RecordType;
+ /**** pts ****/
+ SavedImage *sp=0; /**** pts: avoid gcc warning */
+ /** Extension info of next SavedImage */
+ SavedImage ext;
+ /** No-extension info */
+ SavedImage noext;
+
+ GifByteType *ExtData;
+
+ /**** pts ****/
+ memset(&noext, 0, sizeof(noext));
+ noext.delay=0;
+ noext.dispose=0;
+ noext.iter=1;
+ noext.transp=(-1);
+ noext.ExtensionBlocks=NULL;
+ noext.ExtensionBlockCount=0;
+ ext=noext;
+
+ /**** pts ****/
+ GifFile->SavedImages=0;
+
+ do {
+ if (DGifGetRecordType(GifFile, &RecordType) == GIF_ERROR)
+ return(GIF_ERROR);
+
+ switch (RecordType) {
+ case IMAGE_DESC_RECORD_TYPE:
+ if (DGifGetImageDesc(GifFile) == GIF_ERROR)
+ return(GIF_ERROR);
+
+ /**** pts: DGifGetImageDesc has already allocated the mem ****/
+ sp = &GifFile->SavedImages[GifFile->ImageCount-1];
+ /**** pts: apply extensions to the image just read */
+ ext.RasterBits=sp->RasterBits;
+ ext.ImageDesc=sp->ImageDesc;
+ *sp=ext;
+ ext=noext;
+
+ /**** pts ****/
+ sp->RasterBits = (GifPixelType*) malloc((0L+sp->ImageDesc.Width) * sp->ImageDesc.Height * sizeof(GifPixelType));
+ if (sp->RasterBits==NULL) { _GifError=D_GIF_ERR_NOT_ENOUGH_MEM; return GIF_ERROR; }
+ if (sp->ImageDesc.Interlace) {
+ unsigned i, j, Height=sp->ImageDesc.Height, Width=sp->ImageDesc.Width;
+ /* Need to perform 4 passes on the images: */
+ for (i = 0; i < 4; i++)
+ for (j = InterlacedOffset[i]; j < Height; j += InterlacedJumps[i])
+ if (DGifGetLine(GifFile, sp->RasterBits+Width*j, Width) != GIF_OK) return GIF_ERROR;
+ } else {
+ if (DGifGetLine(GifFile, sp->RasterBits, (0L+sp->ImageDesc.Width) * sp->ImageDesc.Height)
+ == GIF_ERROR)
+ return(GIF_ERROR);
+ }
+ break;
+
+ case EXTENSION_RECORD_TYPE:
+
+ if (DGifGetExtension(GifFile,&ext_code,&ExtData)==GIF_ERROR)
+ return(GIF_ERROR);
+ if (ExtData!=NULL) {
+ #if 0 /**** pts ****/
+ ep = &ext.ExtensionBlocks[ext.ExtensionBlockCount++];
+ ep->ByteCount = ExtData[0];
+ ep->Bytes = (GifByteType *)malloc(ep->ByteCount * sizeof(GifByteType));
+ memcpy(ep->Bytes, ExtData, ep->ByteCount * sizeof(char));
+ #else
+ /**** pts ****/
+ if (0xf9==(unsigned char)(ext_code)) {
+ assert(ExtData[0]>=4);
+ ext.dispose=ExtData[1]>>2;
+ ext.delay=(ExtData[3] << 8) | ExtData[2];
+ if ((ExtData[1] & 0x01) == 1) ext.transp=ExtData[4];
+ } else if (0xff==(unsigned char)(ext_code)) {
+ assert(ExtData[0]>=3);
+ ext.iter=(ExtData[3] << 8) | ExtData[2];
+ } else {
+ AddExtensionBlock(&ext, ExtData[0], ExtData+1);
+ ext.ExtensionBlocks[ext.ExtensionBlockCount-1].code=ext_code;
+ }
+ #endif
+ while (1) {
+ if (DGifGetExtensionNext(GifFile, &ExtData) == GIF_ERROR)
+ return(GIF_ERROR);
+ #if 0 /**** pts ****/
+ ep = &ext.ExtensionBlocks[ext.ExtensionBlockCount++];
+ ep->ByteCount = ExtData[0];
+ ep->Bytes = (GifByteType *)malloc(ep->ByteCount * sizeof(GifByteType));
+ memcpy(ep->Bytes,ExtData,ep->ByteCount * sizeof(char));
+ #else
+ if (ExtData==NULL) break;
+ AddExtensionBlock(sp, ExtData[0], ExtData+1);
+ #endif
+ }
+ }
+ break;
+
+ case TERMINATE_RECORD_TYPE:
+ break;
+
+ default: /* Should be trapped by DGifGetRecordType */
+ break;
+ }
+ }
+ while
+ (RecordType != TERMINATE_RECORD_TYPE);
+
+ return(GIF_OK);
+}
+
+/* __END__ */
diff --git a/graphics/sam2p/cgif.h b/graphics/sam2p/cgif.h
new file mode 100644
index 0000000000..c2be83f75b
--- /dev/null
+++ b/graphics/sam2p/cgif.h
@@ -0,0 +1,257 @@
+/* cgif.h -- a merge of some GIF-decoding files from giflib by E.S.Raymond
+ * by pts@fazekas.hu at Wed Feb 27 13:18:04 CET 2002
+
+The GIFLIB distribution is Copyright (c) 1997 Eric S. Raymond
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+THE SOFTWARE.
+ */
+
+/******************************************************************************
+* In order to make life a little bit easier when using the GIF file format, *
+* this library was written, and which does all the dirty work... *
+* *
+* Written by Gershon Elber, Jun. 1989 *
+* Hacks by Eric S. Raymond, Sep. 1992 *
+*******************************************************************************
+* History: *
+* 14 Jun 89 - Version 1.0 by Gershon Elber. *
+* 3 Sep 90 - Version 1.1 by Gershon Elber (Support for Gif89, Unique names). *
+* 15 Sep 90 - Version 2.0 by Eric S. Raymond (Changes to suoport GIF slurp) *
+* 26 Jun 96 - Version 3.0 by Eric S. Raymond (Full GIF89 support)
+******************************************************************************/
+
+#ifndef CGIF_H
+#define CGIF_H
+
+#ifdef __GNUC__
+#ifndef __clang__
+#pragma interface
+#endif
+#endif
+
+#include "config2.h" /* PTS_const */
+
+#define GIF_LIB_VERSION " Version 3.0, "
+
+#define GIF_ERROR 0
+#define GIF_OK 1
+
+#ifndef TRUE
+#define TRUE 1
+#define FALSE 0
+#endif
+
+#ifndef NULL
+#define NULL 0
+#endif /* NULL */
+
+#if _MSC_VER > 1000
+# undef __PROTOTYPES__
+# define __PROTOTYPES__ 1
+# pragma warning(disable: 4127) /* conditional expression is constant */
+# pragma warning(disable: 4244) /* =' : conversion from 'int ' to 'unsigned char ', possible loss of data */
+#endif
+
+/* at Wed Dec 11 15:33:22 CET 2002 */
+/* #define USE_CGIF_FDOPEN 1 */
+#undef USE_CGIF_FDOPEN
+
+#ifdef __cplusplus
+class CGIF { public:
+#define EXTERN static
+#else
+#define EXTERN extern
+#endif
+
+typedef int GifBooleanType;
+typedef unsigned char GifPixelType;
+typedef unsigned char * GifRowType;
+typedef unsigned char GifByteType;
+
+#define GIF_MESSAGE(Msg) fprintf(stderr, "\n%s: %s\n", PROGRAM_NAME, Msg)
+#define GIF_EXIT(Msg) { GIF_MESSAGE(Msg); exit(-3); }
+
+#ifdef SYSV
+#define VoidPtr char *
+#else
+#define VoidPtr void *
+#endif /* SYSV */
+
+typedef struct GifColorType {
+ GifByteType Red, Green, Blue;
+} GifColorType;
+
+typedef struct ColorMapObject
+{
+ int ColorCount;
+ int BitsPerPixel;
+ GifColorType *Colors; /* on malloc(3) heap */
+}
+ColorMapObject;
+
+typedef struct GifImageDesc {
+ int Left, Top, Width, Height, /* Current image dimensions. */
+ Interlace; /* Sequential/Interlaced lines. */
+ ColorMapObject *ColorMap; /* The local color map */
+} GifImageDesc;
+
+struct SavedImage;
+typedef struct GifFileType {
+ int SWidth, SHeight, /* Screen dimensions. */
+ SColorResolution, /* How many colors can we generate? */
+ SBackGroundColor; /* I hope you understand this one... */
+ ColorMapObject *SColorMap; /* NULL if not exists. */
+ int ImageCount; /* Number of current image */
+ /*GifImageDesc Image; */ /* Block describing current image */
+ struct SavedImage *SavedImages; /* Use this to accumulate file state */
+ VoidPtr Private; /* Don't mess with this! */
+} GifFileType;
+
+typedef enum {
+ UNDEFINED_RECORD_TYPE,
+ SCREEN_DESC_RECORD_TYPE,
+ IMAGE_DESC_RECORD_TYPE, /* Begin with ',' */
+ EXTENSION_RECORD_TYPE, /* Begin with '!' */
+ TERMINATE_RECORD_TYPE /* Begin with ';' */
+} GifRecordType;
+
+/******************************************************************************
+* GIF89 extension function codes *
+******************************************************************************/
+
+#define COMMENT_EXT_FUNC_CODE 0xfe /* comment */
+#define GRAPHICS_EXT_FUNC_CODE 0xf9 /* graphics control */
+#define PLAINTEXT_EXT_FUNC_CODE 0x01 /* plaintext */
+#define APPLICATION_EXT_FUNC_CODE 0xff /* application block */
+
+/******************************************************************************
+* O.K., here are the routines one can access in order to decode GIF file: *
+* (GIF_LIB file DGIF_LIB.C). *
+******************************************************************************/
+
+EXTERN GifFileType *DGifOpenFileName(const char *GifFileName);
+#if USE_CGIF_FDOPEN
+EXTERN GifFileType *DGifOpenFileHandle(int GifFileHandle);
+#endif
+EXTERN GifFileType *DGifOpenFILE(void/*FILE*/ *f);
+EXTERN int DGifSlurp(GifFileType *GifFile);
+EXTERN int DGifGetScreenDesc(GifFileType *GifFile);
+EXTERN int DGifGetRecordType(GifFileType *GifFile, GifRecordType *GifType);
+EXTERN int DGifGetImageDesc(GifFileType *GifFile);
+EXTERN int DGifGetLine(GifFileType *GifFile, GifPixelType *GifLine, int GifLineLen);
+EXTERN int DGifGetPixel(GifFileType *GifFile, GifPixelType GifPixel);
+EXTERN int DGifGetComment(GifFileType *GifFile, char *GifComment);
+EXTERN int DGifGetExtension(GifFileType *GifFile, int *GifExtCode,
+ GifByteType **GifExtension);
+EXTERN int DGifGetExtensionNext(GifFileType *GifFile, GifByteType **GifExtension);
+EXTERN int DGifGetCode(GifFileType *GifFile, int *GifCodeSize,
+ GifByteType **GifCodeBlock);
+EXTERN int DGifGetCodeNext(GifFileType *GifFile, GifByteType **GifCodeBlock);
+EXTERN int DGifGetLZCodes(GifFileType *GifFile, int *GifCode);
+EXTERN int DGifCloseFile(GifFileType *GifFile);
+
+#define D_GIF_ERR_OPEN_FAILED 101 /* And DGif possible errors. */
+#define D_GIF_ERR_READ_FAILED 102
+#define D_GIF_ERR_NOT_GIF_FILE 103
+#define D_GIF_ERR_NO_SCRN_DSCR 104
+#define D_GIF_ERR_NO_IMAG_DSCR 105
+#define D_GIF_ERR_NO_COLOR_MAP 106
+#define D_GIF_ERR_WRONG_RECORD 107
+#define D_GIF_ERR_DATA_TOO_BIG 108
+#define D_GIF_ERR_NOT_ENOUGH_MEM 109
+#define D_GIF_ERR_CLOSE_FAILED 110
+#define D_GIF_ERR_NOT_READABLE 111
+#define D_GIF_ERR_IMAGE_DEFECT 112
+#define D_GIF_ERR_EOF_TOO_SOON 113
+
+
+/******************************************************************************
+* O.K., here are the routines from GIF_LIB file GIF_ERR.C. *
+******************************************************************************/
+EXTERN void PrintGifError(void);
+EXTERN PTS_const char *GetGifError(void);
+EXTERN int GifLastError(void);
+
+/*****************************************************************************
+ *
+ * Everything below this point is new after version 1.2, supporting `slurp
+ * mode' for doing I/O in two big belts with all the image-bashing in core.
+ *
+ *****************************************************************************/
+
+/******************************************************************************
+* Color Map handling from ALLOCGIF.C *
+******************************************************************************/
+
+EXTERN ColorMapObject *MakeMapObject(int ColorCount, GifColorType *ColorMap);
+EXTERN void FreeMapObject(ColorMapObject *Object);
+
+/******************************************************************************
+* Support for the in-core structures allocation (slurp mode). *
+******************************************************************************/
+
+/* This is the in-core version of an extension record */
+typedef struct {
+ /** Extension code:
+ * 0xf9 Graphics Control extension (not stored!)
+ * 0xfe Comment extension
+ * 0xff Netscape Loop extension (not stored!)
+ * .... ???
+ */
+ int code;
+ int ByteCount;
+ /**** pts ****/
+ GifByteType *Bytes; /* on malloc(3) heap */
+} ExtensionBlock;
+
+/* This holds an image header, its unpacked raster bits, and extensions */
+typedef struct SavedImage {
+ GifImageDesc ImageDesc;
+
+ /**** pts ****/
+ GifPixelType *RasterBits; /* on malloc(3) heap */
+ int ExtensionBlockCount;
+ ExtensionBlock *ExtensionBlocks; /* on malloc(3) heap */
+
+ /**** pts ****/
+ /** from Graphics Control extension: 0..63 */
+ unsigned char dispose;
+ /** from Graphics Control extension: 0..65535 */
+ unsigned short delay;
+ /** from Graphics Control extension: transparency index: -1 or 0..255 */
+ signed short transp;
+ /** from Netscape Loop extension: iteration count: 0..65535 */
+ unsigned short iter;
+} SavedImage;
+
+EXTERN void MakeExtension(SavedImage *New, int Function);
+EXTERN int AddExtensionBlock(SavedImage *New, int Len, GifByteType ExtData[]);
+EXTERN void FreeExtension(SavedImage *Image);
+
+EXTERN SavedImage *MakeSavedImage(GifFileType *GifFile, SavedImage *CopyFrom);
+EXTERN void FreeSavedImages(GifFileType *GifFile);
+
+#ifdef __cplusplus
+ static int _GifError;
+};
+#else
+ extern int _GifError;
+#endif
+
+#endif /* CGIF_H */
diff --git a/graphics/sam2p/cols2.pl b/graphics/sam2p/cols2.pl
new file mode 100644
index 0000000000..b6f09cca91
--- /dev/null
+++ b/graphics/sam2p/cols2.pl
@@ -0,0 +1,311 @@
+#! /bin/sh --
+eval '(exit $?0)' && eval 'PERL_BADLANG=x;export PERL_BADLANG;: \
+;exec perl -x -S -- "$0" ${1+"$@"};#'if 0;
+eval 'setenv PERL_BADLANG x;exec perl -x -S -- "$0" $argv:q;#'.q
+#!perl -w
++($0=~/(.*)/s);do$1;die$@if$@;__END__+if 0;
+# Don't touch/remove lines 1--7: http://www.inf.bme.hu/~pts/Magic.Perl.Header
+
+#
+# cols2.pl -- create a read-only C hash table from hash function
+# by pts@fazekas.hu at Fri Mar 1 09:24:46 CET 2002
+# minor VC6.0 updates at Thu Dec 12 19:01:06 CET 2002
+#
+BEGIN{$^W=1}
+BEGIN { eval { require integer; import integer } }
+BEGIN { eval { require strict ; import strict } }
+
+my @L=( # imagemagick's ColorList.h
+ [ "None", 3, 2, 1 ],
+ [ "AliceBlue", 240, 248, 255 ],
+ [ "AntiqueWhite", 250, 235, 215 ],
+ [ "Aquamarine", 50, 191, 193 ],
+ [ "Azure", 240, 255, 255 ],
+ [ "Beige", 245, 245, 220 ],
+ [ "Bisque", 255, 228, 196 ],
+ [ "Black", 0, 0, 0 ],
+ [ "BlanchedAlmond", 255, 235, 205 ],
+ [ "Blue", 0, 0, 255 ],
+ [ "BlueViolet", 138, 43, 226 ],
+ [ "Brown", 165, 42, 42 ],
+ [ "burlywood", 222, 184, 135 ],
+ [ "CadetBlue", 95, 146, 158 ],
+ [ "chartreuse", 127, 255, 0 ],
+ [ "chocolate", 210, 105, 30 ],
+ [ "Coral", 255, 114, 86 ],
+ [ "CornflowerBlue", 34, 34, 152 ],
+ [ "cornsilk", 255, 248, 220 ],
+ [ "Cyan", 0, 255, 255 ],
+ [ "DarkGoldenrod", 184, 134, 11 ],
+ [ "DarkGreen", 0, 86, 45 ],
+ [ "DarkKhaki", 189, 183, 107 ],
+ [ "DarkOliveGreen", 85, 86, 47 ],
+ [ "DarkOrange", 255, 140, 0 ],
+ [ "DarkOrchid", 139, 32, 139 ],
+ [ "DarkSalmon", 233, 150, 122 ],
+ [ "DarkSeaGreen", 143, 188, 143 ],
+ [ "DarkSlateBlue", 56, 75, 102 ],
+ [ "DarkSlateGray", 47, 79, 79 ],
+ [ "DarkTurquoise", 0, 166, 166 ],
+ [ "DarkViolet", 148, 0, 211 ],
+ [ "DeepPink", 255, 20, 147 ],
+ [ "DeepSkyBlue", 0, 191, 255 ],
+ [ "DimGray", 84, 84, 84 ],
+ [ "DodgerBlue", 30, 144, 255 ],
+ [ "Firebrick", 142, 35, 35 ],
+ [ "FloralWhite", 255, 250, 240 ],
+ [ "ForestGreen", 80, 159, 105 ],
+ [ "gainsboro", 220, 220, 220 ],
+ [ "GhostWhite", 248, 248, 255 ],
+ [ "Gold", 218, 170, 0 ],
+ [ "Goldenrod", 239, 223, 132 ],
+ [ "Gray", 126, 126, 126 ],
+ [ "Green", 0, 255, 0 ],
+ [ "GreenYellow", 173, 255, 47 ],
+ [ "honeydew", 240, 255, 240 ],
+ [ "HotPink", 255, 105, 180 ],
+ [ "IndianRed", 107, 57, 57 ],
+ [ "ivory", 255, 255, 240 ],
+ [ "Khaki", 179, 179, 126 ],
+ [ "lavender", 230, 230, 250 ],
+ [ "LavenderBlush", 255, 240, 245 ],
+ [ "LawnGreen", 124, 252, 0 ],
+ [ "LemonChiffon", 255, 250, 205 ],
+ [ "LightBlue", 176, 226, 255 ],
+ [ "LightCoral", 240, 128, 128 ],
+ [ "LightCyan", 224, 255, 255 ],
+ [ "LightGoldenrod", 238, 221, 130 ],
+ [ "LightGoldenrodYellow", 250, 250, 210 ],
+ [ "LightGray", 168, 168, 168 ],
+ [ "LightPink", 255, 182, 193 ],
+ [ "LightSalmon", 255, 160, 122 ],
+ [ "LightSeaGreen", 32, 178, 170 ],
+ [ "LightSkyBlue", 135, 206, 250 ],
+ [ "LightSlateBlue", 132, 112, 255 ],
+ [ "LightSlateGray", 119, 136, 153 ],
+ [ "LightSteelBlue", 124, 152, 211 ],
+ [ "LightYellow", 255, 255, 224 ],
+ [ "LimeGreen", 0, 175, 20 ],
+ [ "linen", 250, 240, 230 ],
+ [ "Magenta", 255, 0, 255 ],
+ [ "Maroon", 143, 0, 82 ],
+ [ "MediumAquamarine", 0, 147, 143 ],
+ [ "MediumBlue", 50, 50, 204 ],
+ [ "MediumForestGreen", 50, 129, 75 ],
+ [ "MediumGoldenrod", 209, 193, 102 ],
+ [ "MediumOrchid", 189, 82, 189 ],
+ [ "MediumPurple", 147, 112, 219 ],
+ [ "MediumSeaGreen", 52, 119, 102 ],
+ [ "MediumSlateBlue", 106, 106, 141 ],
+ [ "MediumSpringGreen", 35, 142, 35 ],
+ [ "MediumTurquoise", 0, 210, 210 ],
+ [ "MediumVioletRed", 213, 32, 121 ],
+ [ "MidnightBlue", 47, 47, 100 ],
+ [ "MintCream", 245, 255, 250 ],
+ [ "MistyRose", 255, 228, 225 ],
+ [ "moccasin", 255, 228, 181 ],
+ [ "NavajoWhite", 255, 222, 173 ],
+ [ "Navy", 35, 35, 117 ],
+ [ "NavyBlue", 35, 35, 117 ],
+ [ "OldLace", 253, 245, 230 ],
+ [ "OliveDrab", 107, 142, 35 ],
+ [ "Orange", 255, 135, 0 ],
+ [ "OrangeRed", 255, 69, 0 ],
+ [ "Orchid", 239, 132, 239 ],
+ [ "PaleGoldenrod", 238, 232, 170 ],
+ [ "PaleGreen", 115, 222, 120 ],
+ [ "PaleTurquoise", 175, 238, 238 ],
+ [ "PaleVioletRed", 219, 112, 147 ],
+ [ "PapayaWhip", 255, 239, 213 ],
+ [ "PeachPuff", 255, 218, 185 ],
+ [ "peru", 205, 133, 63 ],
+ [ "Pink", 255, 181, 197 ],
+ [ "Plum", 197, 72, 155 ],
+ [ "PowderBlue", 176, 224, 230 ],
+ [ "purple", 160, 32, 240 ],
+ [ "Red", 255, 0, 0 ],
+ [ "RosyBrown", 188, 143, 143 ],
+ [ "RoyalBlue", 65, 105, 225 ],
+ [ "SaddleBrown", 139, 69, 19 ],
+ [ "Salmon", 233, 150, 122 ],
+ [ "SandyBrown", 244, 164, 96 ],
+ [ "SeaGreen", 82, 149, 132 ],
+ [ "seashell", 255, 245, 238 ],
+ [ "Sienna", 150, 82, 45 ],
+ [ "SkyBlue", 114, 159, 255 ],
+ [ "SlateBlue", 126, 136, 171 ],
+ [ "SlateGray", 112, 128, 144 ],
+ [ "snow", 255, 250, 250 ],
+ [ "SpringGreen", 65, 172, 65 ],
+ [ "SteelBlue", 84, 112, 170 ],
+ [ "Tan", 222, 184, 135 ],
+ [ "Thistle", 216, 191, 216 ],
+ [ "tomato", 255, 99, 71 ],
+ [ "Transparent", 0, 0, 1 ],
+ [ "Turquoise", 25, 204, 223 ],
+ [ "Violet", 156, 62, 206 ],
+ [ "VioletRed", 243, 62, 150 ],
+ [ "Wheat", 245, 222, 179 ],
+ [ "White", 255, 255, 255 ],
+ [ "WhiteSmoke", 245, 245, 245 ],
+ [ "Yellow", 255, 255, 0 ],
+ [ "YellowGreen", 50, 216, 56 ],
+ [ "Gray0", 0, 0, 0 ],
+ [ "Gray1", 3, 3, 3 ],
+ [ "Gray10", 26, 26, 26 ],
+ [ "Gray100", 255, 255, 255 ],
+ [ "Gray11", 28, 28, 28 ],
+ [ "Gray12", 31, 31, 31 ],
+ [ "Gray13", 33, 33, 33 ],
+ [ "Gray14", 36, 36, 36 ],
+ [ "Gray15", 38, 38, 38 ],
+ [ "Gray16", 41, 41, 41 ],
+ [ "Gray17", 43, 43, 43 ],
+ [ "Gray18", 46, 46, 46 ],
+ [ "Gray19", 48, 48, 48 ],
+ [ "Gray2", 5, 5, 5 ],
+ [ "Gray20", 51, 51, 51 ],
+ [ "Gray21", 54, 54, 54 ],
+ [ "Gray22", 56, 56, 56 ],
+ [ "Gray23", 59, 59, 59 ],
+ [ "Gray24", 61, 61, 61 ],
+ [ "Gray25", 64, 64, 64 ],
+ [ "Gray26", 66, 66, 66 ],
+ [ "Gray27", 69, 69, 69 ],
+ [ "Gray28", 71, 71, 71 ],
+ [ "Gray29", 74, 74, 74 ],
+ [ "Gray3", 8, 8, 8 ],
+ [ "Gray30", 77, 77, 77 ],
+ [ "Gray31", 79, 79, 79 ],
+ [ "Gray32", 82, 82, 82 ],
+ [ "Gray33", 84, 84, 84 ],
+ [ "Gray34", 87, 87, 87 ],
+ [ "Gray35", 89, 89, 89 ],
+ [ "Gray36", 92, 92, 92 ],
+ [ "Gray37", 94, 94, 94 ],
+ [ "Gray38", 97, 97, 97 ],
+ [ "Gray39", 99, 99, 99 ],
+ [ "Gray4", 10, 10, 10 ],
+ [ "Gray40", 102, 102, 102 ],
+ [ "Gray41", 105, 105, 105 ],
+ [ "Gray42", 107, 107, 107 ],
+ [ "Gray43", 110, 110, 110 ],
+ [ "Gray44", 112, 112, 112 ],
+ [ "Gray45", 115, 115, 115 ],
+ [ "Gray46", 117, 117, 117 ],
+ [ "Gray47", 120, 120, 120 ],
+ [ "Gray48", 122, 122, 122 ],
+ [ "Gray49", 125, 125, 125 ],
+ [ "Gray5", 13, 13, 13 ],
+ [ "Gray50", 127, 127, 127 ],
+ [ "Gray51", 130, 130, 130 ],
+ [ "Gray52", 133, 133, 133 ],
+ [ "Gray53", 135, 135, 135 ],
+ [ "Gray54", 138, 138, 138 ],
+ [ "Gray55", 140, 140, 140 ],
+ [ "Gray56", 143, 143, 143 ],
+ [ "Gray57", 145, 145, 145 ],
+ [ "Gray58", 148, 148, 148 ],
+ [ "Gray59", 150, 150, 150 ],
+ [ "Gray6", 15, 15, 15 ],
+ [ "Gray60", 153, 153, 153 ],
+ [ "Gray61", 156, 156, 156 ],
+ [ "Gray62", 158, 158, 158 ],
+ [ "Gray63", 161, 161, 161 ],
+ [ "Gray64", 163, 163, 163 ],
+ [ "Gray65", 166, 166, 166 ],
+ [ "Gray66", 168, 168, 168 ],
+ [ "Gray67", 171, 171, 171 ],
+ [ "Gray68", 173, 173, 173 ],
+ [ "Gray69", 176, 176, 176 ],
+ [ "Gray7", 18, 18, 18 ],
+ [ "Gray70", 179, 179, 179 ],
+ [ "Gray71", 181, 181, 181 ],
+ [ "Gray72", 184, 184, 184 ],
+ [ "Gray73", 186, 186, 186 ],
+ [ "Gray74", 189, 189, 189 ],
+ [ "Gray75", 191, 191, 191 ],
+ [ "Gray76", 194, 194, 194 ],
+ [ "Gray77", 196, 196, 196 ],
+ [ "Gray78", 199, 199, 199 ],
+ [ "Gray79", 201, 201, 201 ],
+ [ "Gray8", 20, 20, 20 ],
+ [ "Gray80", 204, 204, 204 ],
+ [ "Gray81", 207, 207, 207 ],
+ [ "Gray82", 209, 209, 209 ],
+ [ "Gray83", 212, 212, 212 ],
+ [ "Gray84", 214, 214, 214 ],
+ [ "Gray85", 217, 217, 217 ],
+ [ "Gray86", 219, 219, 219 ],
+ [ "Gray87", 222, 222, 222 ],
+ [ "Gray88", 224, 224, 224 ],
+ [ "Gray89", 227, 227, 227 ],
+ [ "Gray9", 23, 23, 23 ],
+ [ "Gray90", 229, 229, 229 ],
+ [ "Gray91", 232, 232, 232 ],
+ [ "Gray92", 235, 235, 235 ],
+ [ "Gray93", 237, 237, 237 ],
+ [ "Gray94", 240, 240, 240 ],
+ [ "Gray95", 242, 242, 242 ],
+ [ "Gray96", 245, 245, 245 ],
+ [ "Gray97", 247, 247, 247 ],
+ [ "Gray98", 250, 250, 250 ],
+ [ "Gray99", 252, 252, 252 ],
+);
+
+# quote all [^!-~]|[^\\
+sub cq($) {
+ # @return param octal-quoted as a C source string
+ my $S=$_[0];
+ $S=~s@([\\"])@\\$1@g;
+ $S=~s@([^!-~])@sprintf"\\%03o",ord$1@ge;
+ $S=~s@\\([0-7][0-7][0-7])(?=[0-9])@\\$1""@g; # pacify VC6.0 warning
+ $S
+}
+
+my @P;
+sub hash0($) {
+ my $N=0;
+ for(split'',$_[0][0]) { $N=$N*95+(223&ord); }
+ $N&=65535;
+ $N%=1109;
+ push @{$P[$N]}, $_[0];
+}
+
+@P=(undef)x1109;
+for (@L) { hash0($_); }
+# my $S="";
+# die @P;
+print STDERR "Collisions:\n";
+for (@P) { print STDERR "X@$_.\n" if defined($_) and $#$_>=1 }
+print STDERR "---\n";
+
+my $S="\000"; # contains strings
+my $H=""; # contains the hash table indices, offsets to $S
+for (@P) {
+ if (defined($_)) {
+ $H.=length($S).",";
+ for (@$_) {
+ # $S.=$_->[0]."#".$_->[1].",".$_->[2].",".$_->[3].";"
+ $S.=$_->[0]."\000".chr($_->[1]).chr($_->[2]).chr($_->[3]);
+ }
+ # substr($S,-1,1)="\000";
+ $S.="\000";
+ } else { $H.="0,"; }
+# print STDERR "X@$_.\n" if defined($_) and $#$_>=1 }
+}
+$S=~s@\000\Z(?!\n)@@;
+print "#define xpmColors_mul 95\n";
+print "#define xpmColors_mod 1109\n";
+print "unsigned short xpmColors_ofs[]={$H};\n";
+print "char xpmColors_dat[]=\"".cq($S)."\";\n";
+
+# 357, 2048
+# 189, 3457
+# 175, 3823
+# 973 (222), 1993
+# 751 (22), 1997
+# 439 (2), 2053
+# 79 (222222), 1229
+# 539 (22222), 1201
+# 287 (222), 1163
diff --git a/graphics/sam2p/config-vc6.h b/graphics/sam2p/config-vc6.h
new file mode 100644
index 0000000000..ae59ea039c
--- /dev/null
+++ b/graphics/sam2p/config-vc6.h
@@ -0,0 +1,197 @@
+/* config-vc6.h. config.h replacement for MS Visual C++ 6.0 */
+/* config.h.in. Generated automatically from configure.in by autoheader. */
+
+/* Define if using alloca.c. */
+/* #undef C_ALLOCA */
+
+/* Define if type char is unsigned and you are not using gcc. */
+#ifndef __CHAR_UNSIGNED__
+/* #undef __CHAR_UNSIGNED__ */
+#endif
+
+/* Define to empty if the keyword does not work. */
+/* #undef const */
+
+/* Define to one of _getb67, GETB67, getb67 for Cray-2 and Cray-YMP systems.
+ This function is required for alloca.c support on those systems. */
+/* #undef CRAY_STACKSEG_END */
+
+/* Define if you have alloca, as a function or macro. */
+#define HAVE_ALLOCA 1
+
+/* Define if you have <alloca.h> and it should be used (not on Ultrix). */
+/* #undef HAVE_ALLOCA_H */
+
+/* Define if you have the ANSI # stringizing operator in cpp. */
+/* #undef HAVE_STRINGIZE */
+
+/* Define to `unsigned' if <sys/types.h> doesn't define. */
+/* #undef size_t */
+
+/* If using the C implementation of alloca, define if you know the
+ direction of stack growth for your system; otherwise it will be
+ automatically deduced at run-time.
+ STACK_DIRECTION > 0 => grows toward higher addresses
+ STACK_DIRECTION < 0 => grows toward lower addresses
+ STACK_DIRECTION = 0 => direction of growth unknown
+ */
+/* #undef STACK_DIRECTION */
+
+/* Define if you have the ANSI C header files. */
+/* #undef STDC_HEADERS */
+
+/* A type name of a signed integral type of exactly 16 bits. Always defined.
+ */
+#define PTS_INT16_T short
+
+/* A type name of a signed integral type of exactly 32 bits. Always defined.
+ */
+#define PTS_INT32_T int
+
+/* A type name of a signed integral type of exactly 64 bits. Maybe left
+ * 0-defined.
+ */
+#define PTS_INT64_T long long
+
+/* A type name of a signed integral type of exactly 128 bits. Maybe left
+ * 0-defined.
+ */
+#define PTS_INT128_T 0
+
+/* A type name of a signed integral type which has space to hold a pointer.
+ * Always defined.
+ */
+#define PTS_INTP_T int
+
+/* Imp: document this
+ */
+#define PTS_INTP_OK 1
+
+/* Imp: document this
+ */
+/* #undef PTS_mode_t */
+
+/* Imp: document this
+ */
+/* #undef PTS_off_t */
+
+/* Imp: document this
+ */
+/* #undef PTS_pid_t */
+
+/* Imp: document this
+ */
+#define PTS_size_t unsigned int
+
+/* Just a dummy, non-existent type.
+ */
+/* #undef PTS_size_tt */
+
+/* Imp: document this
+ */
+/* #undef PTS_uid_t */
+
+/* Imp: document this
+ */
+/* #undef PTS_gid_t */
+
+/* Imp: document this
+ */
+/* #undef PTS_dev_t */
+
+/* Does the C compiler support prototypes?
+ */
+#define HAVE_PROTOTYPES 1
+
+/* Define to empty if the keyword does not work.
+ */
+/* #undef volatile */
+
+/* Imp: document this
+ */
+#define HAVE_strcpy_in_string 1
+
+/* Imp: document this
+ */
+/* #undef HAVE_strcpy_in_strings */
+
+/* Imp: document these
+ */
+/* #undef HAVE_MEMCMPY_BUILTIN */
+#define HAVE_getc_in_stdio 1
+#define HAVE_fgetc_in_stdio 1
+#define HAVE_putc_in_stdio 1
+#define HAVE_fputc_in_stdio 1
+#define HAVE_atoi_in_stdlib 1
+/* #undef HAVE_malloc_in_malloc */
+#define HAVE_malloc_in_stdlib 1
+#define HAVE_memcpy_in_stringxs 1
+#define HAVE_sprintf_in_stdio 1
+#define HAVE_write_in_unistd 1
+#define HAVE_system_in_stdlib 1
+/* #undef HAVE_lstat_in_sys_stat */
+#define HAVE_PTS_STDC 1
+/* #undef HAVE_SWITCH_ENUM_BUG */
+#define HAVE_ASCII_SYSTEM 1
+#define PTS_CFG_P_TMPDIR 0
+
+/* Is the file c_gcc.cpp required for gcc when linking C++ programs? */
+#define HAVE_PTS_C_LGCC_CPP_REQUIRED 1
+/* #undef HAVE_PTS_C_LGCC3_CPP_REQUIRED */
+
+/** Does the C library have a working vsnprintf()? */
+/* #undef HAVE_PTS_VSNPRINTF */
+/* #undef HAVE_PTS_VSNPRINTF_OLD */
+/* #undef HAVE_PTS_VSNPRINTF_C99 */
+
+/** What shell does the C library system(3) function call? */
+#define HAVE_PTS_SYSTEMF 1
+#define HAVE_PTS_SYSTEMF_WIN32 1
+/* #undef HAVE_PTS_SYSTEMF_UNIX */
+/* #undef HAVE_PTS_SYSTEMF_OTHER */
+
+/** popen("...","wb") and "rb" works binary */
+/* #undef HAVE_PTS_POPEN_B */
+
+/** popen("...","w") and "r" works binary */
+/* #undef HAVE_PTS_POPEN_ */
+
+/* The number of bytes in a __int64. */
+#define SIZEOF___INT64 0
+
+/* The number of bytes in a bool. */
+#define SIZEOF_BOOL 1
+
+/* The number of bytes in a char. */
+#define SIZEOF_CHAR 1
+
+/* The number of bytes in a char *. */
+#define SIZEOF_CHAR_P 4
+
+/* The number of bytes in a int. */
+#define SIZEOF_INT 4
+
+/* The number of bytes in a long. */
+#define SIZEOF_LONG 4
+
+/* The number of bytes in a long long. */
+#define SIZEOF_LONG_LONG 8
+
+/* The number of bytes in a short. */
+#define SIZEOF_SHORT 2
+
+/* The number of bytes in a very long. */
+#define SIZEOF_VERY_LONG 0
+
+/* The number of bytes in a void *. */
+#define SIZEOF_VOID_P 4
+
+/* Can have static const int VARNAME=1; inside a class { ... } ? */
+/* #undef HAVE_STATIC_CONST */
+
+/* sam2p-specific */
+#define USE_BUILTIN_ZIP 1
+#define USE_BUILTIN_FAXE 1
+#define USE_BUILTIN_LZW 1
+#define USE_IN_GIF 1
+#define USE_OUT_GIF 1
diff --git a/graphics/sam2p/config.h.in b/graphics/sam2p/config.h.in
new file mode 100644
index 0000000000..9322e64c19
--- /dev/null
+++ b/graphics/sam2p/config.h.in
@@ -0,0 +1,201 @@
+/* config.h.in. Generated automatically from configure.in by autoheader. */
+
+/* Define if using alloca.c. */
+#undef C_ALLOCA
+
+/* Define if type char is unsigned and you are not using gcc. */
+#ifndef __CHAR_UNSIGNED__
+#undef __CHAR_UNSIGNED__
+#endif
+
+/* Define to empty if the keyword does not work. */
+#undef const
+
+/* Define to one of _getb67, GETB67, getb67 for Cray-2 and Cray-YMP systems.
+ This function is required for alloca.c support on those systems. */
+#undef CRAY_STACKSEG_END
+
+/* Define if you have alloca, as a function or macro. */
+#undef HAVE_ALLOCA
+
+/* Define if you have <alloca.h> and it should be used (not on Ultrix). */
+#undef HAVE_ALLOCA_H
+
+/* Define if you have the ANSI # stringizing operator in cpp. */
+#undef HAVE_STRINGIZE
+
+/* Define to `unsigned' if <sys/types.h> doesn't define. */
+#undef size_t
+
+/* If using the C implementation of alloca, define if you know the
+ direction of stack growth for your system; otherwise it will be
+ automatically deduced at run-time.
+ STACK_DIRECTION > 0 => grows toward higher addresses
+ STACK_DIRECTION < 0 => grows toward lower addresses
+ STACK_DIRECTION = 0 => direction of growth unknown
+ */
+#undef STACK_DIRECTION
+
+/* Define if you have the ANSI C header files. */
+#undef STDC_HEADERS
+
+/* A type name of a signed integral type of exactly 16 bits. Always defined.
+ */
+#undef PTS_INT16_T
+
+/* A type name of a signed integral type of exactly 32 bits. Always defined.
+ */
+#undef PTS_INT32_T
+
+/* A type name of a signed integral type of exactly 64 bits. Maybe left
+ * 0-defined.
+ */
+#undef PTS_INT64_T
+
+/* A type name of a signed integral type of exactly 128 bits. Maybe left
+ * 0-defined.
+ */
+#undef PTS_INT128_T
+
+/* A type name of a signed integral type which has space to hold a pointer.
+ * Always defined.
+ */
+#undef PTS_INTP_T
+
+/* Imp: document this
+ */
+#undef PTS_INTP_OK
+
+/* Imp: document this
+ */
+#undef PTS_mode_t
+
+/* Imp: document this
+ */
+#undef PTS_off_t
+
+/* Imp: document this
+ */
+#undef PTS_pid_t
+
+/* Imp: document this
+ */
+#undef PTS_size_t
+
+/* Just a dummy, non-existent type.
+ */
+#undef PTS_size_tt
+
+/* Imp: document this
+ */
+#undef PTS_uid_t
+
+/* Imp: document this
+ */
+#undef PTS_gid_t
+
+/* Imp: document this
+ */
+#undef PTS_dev_t
+
+/* Does the C compiler support prototypes?
+ */
+#undef HAVE_PROTOTYPES
+
+/* Define to empty if the keyword does not work.
+ */
+#undef volatile
+
+/* Imp: document this
+ */
+#undef HAVE_strcpy_in_string
+
+/* Imp: document this
+ */
+#undef HAVE_strcpy_in_strings
+
+/* Imp: document these
+ */
+#undef HAVE_MEMCMPY_BUILTIN
+#undef HAVE_getc_in_stdio
+#undef HAVE_fgetc_in_stdio
+#undef HAVE_putc_in_stdio
+#undef HAVE_fputc_in_stdio
+#undef HAVE_atoi_in_stdlib
+#undef HAVE_malloc_in_malloc
+#undef HAVE_malloc_in_stdlib
+#undef HAVE_memcpy_in_stringxs
+#undef HAVE_sprintf_in_stdio
+#undef HAVE_write_in_unistd
+#undef HAVE_system_in_stdlib
+#undef HAVE_lstat_in_sys_stat
+#undef HAVE_PTS_STDC
+#undef HAVE_SWITCH_ENUM_BUG
+#undef HAVE_ASCII_SYSTEM
+#undef PTS_CFG_P_TMPDIR
+
+/** "" or ".16", so composing "%.16g" for printing doubles with printf(3)
+ * will just print enough digits
+ */
+#define PTS_CFG_PRINTFGLEN ".16"
+
+/* Is the file c_gcc.cpp required for gcc when linking C++ programs? */
+#undef HAVE_PTS_C_LGCC_CPP_REQUIRED
+#undef HAVE_PTS_C_LGCC3_CPP_REQUIRED
+
+/** Does the C library have a working vsnprintf()? */
+#undef HAVE_PTS_VSNPRINTF
+#undef HAVE_PTS_VSNPRINTF_OLD
+#undef HAVE_PTS_VSNPRINTF_C99
+
+/** What shell does the C library system(3) function call? */
+#undef HAVE_PTS_SYSTEMF
+#undef HAVE_PTS_SYSTEMF_WIN32
+#undef HAVE_PTS_SYSTEMF_UNIX
+#undef HAVE_PTS_SYSTEMF_OTHER
+
+/** popen("...","wb") and "rb" works binary */
+#undef HAVE_PTS_POPEN_B
+
+/** popen("...","w") and "r" works binary */
+#undef HAVE_PTS_POPEN_
+
+/* The number of bytes in a __int64. */
+#undef SIZEOF___INT64
+
+/* The number of bytes in a bool. */
+#undef SIZEOF_BOOL
+
+/* The number of bytes in a char. */
+#undef SIZEOF_CHAR
+
+/* The number of bytes in a char *. */
+#undef SIZEOF_CHAR_P
+
+/* The number of bytes in a int. */
+#undef SIZEOF_INT
+
+/* The number of bytes in a long. */
+#undef SIZEOF_LONG
+
+/* The number of bytes in a long long. */
+#undef SIZEOF_LONG_LONG
+
+/* The number of bytes in a short. */
+#undef SIZEOF_SHORT
+
+/* The number of bytes in a very long. */
+#undef SIZEOF_VERY_LONG
+
+/* The number of bytes in a void *. */
+#undef SIZEOF_VOID_P
+
+/* Can have static const int VARNAME=1; inside a class { ... } ? */
+#undef HAVE_STATIC_CONST
+
+/* sam2p-specific */
+#undef USE_BUILTIN_ZIP
+#undef USE_BUILTIN_FAXE
+#undef USE_BUILTIN_LZW
+#undef USE_IN_GIF
+#undef USE_OUT_GIF
diff --git a/graphics/sam2p/config2.h b/graphics/sam2p/config2.h
new file mode 100644
index 0000000000..f4913d2b03
--- /dev/null
+++ b/graphics/sam2p/config2.h
@@ -0,0 +1,349 @@
+#ifndef CONFIG2_H
+#define CONFIG2_H 1
+
+#include <assert.h> /* NDEBUG==1 means: no assertions */
+#if NDEBUG
+# define ASSERT_SIDE(x) x /* assert with side effect */
+# define ASSERT_SIDE2(x,y) x /* assert with side effect */
+#else
+# define ASSERT_SIDE(x) assert(x)
+# define ASSERT_SIDE2(x,y) assert(x y)
+#endif
+
+#if _MSC_VER > 1000
+# include "config-vc6.h"
+#elif USE_CONFIG_MINGW_H
+# include "config-mingw.h"
+#elif USE_CONFIG_UCLIBC_H
+# include "config-uclibc.h"
+#else
+# include "config.h"
+#endif
+
+#if 0
+/* vvv i386 Debian slink gcc */
+#define SIZEOF_SHORT 2
+#define SIZEOF_INT 4
+#define SIZEOF_LONG 4
+#define SIZEOF_LONG_LONG 8
+#endif
+
+#if SIZEOF_CHAR_P!=SIZEOF_LONG && SIZEOF_INT>=4
+ typedef unsigned slen_t;
+ typedef signed slendiff_t;
+# define SIZEOF_SLEN_T SIZEOF_INT
+# define SLEN_P ""
+#else
+ typedef unsigned long slen_t;
+ typedef signed long slendiff_t;
+# define SIZEOF_SLEN_T SIZEOF_LONG
+# define SLEN_P "l"
+#endif
+
+#if SIZEOF___INT64>SIZEOF_LONG
+# define HAVE_LONG_LONG 1
+# define PTS_CFG_LONGEST __int64 /* may be used as signed CFG_LONGEST */
+# define SIZEOF_CFG_LONGEST SIZEOF___INT64
+#elif SIZEOF_LONG_LONG>SIZEOF_LONG
+# define HAVE_LONG_LONG 1
+# define PTS_CFG_LONGEST long long /* may be used as signed CFG_LONGEST */
+# define SIZEOF_CFG_LONGEST SIZEOF_LONG_LONG
+#elif SIZEOF_VERY_LONG>SIZEOF_LONG
+# define HAVE_LONG_LONG 1
+# define PTS_CFG_LONGEST very long /* may be used as signed CFG_LONGEST */
+# define SIZEOF_CFG_LONGEST SIZEOF_VERY_LONG
+#else
+# undef HAVE_LONG_LONG
+# define PTS_CFG_LONGEST long
+# define SIZEOF_CFG_LONGEST SIZEOF_LONG
+#endif
+
+#define NULLP ((void*)0)
+
+#define USE_IN_TIFF 1
+#define USE_IN_JPEG 1
+#define USE_IN_PNG 1
+#define USE_IN_PCX 1
+#define USE_IN_XPM 1
+/* #define USE_IN_GIF 1 -- defined in */
+#define USE_IN_PNM 1
+#define USE_IN_BMP 1
+#define USE_IN_PIP 1 /* simple paletted format defined by pts, but not implemented */
+#define USE_IN_TGA 1
+#define USE_IN_LBM 1
+#define USE_IN_JAI 1
+#define USE_IN_PDF 1
+#define USE_IN_PS 1
+/* #define USE_OUT_GIF 1 -- moved to config.h */
+#define USE_IN_XPM_MAPPING 1
+#define USE_BIG_MEMORY 1
+#define USE_DICT_MAPPING 1
+/* at Tue Jan 18 16:18:34 CET 2005 */
+#define USE_ZLIB_MEM 1
+
+/** Quotes a filename to be displayed in error messages */
+/* #define FNQ(str) (str) */
+#define FNQ(filename) SimBuffer::B().appendFnq(SimBuffer::Static(filename))
+#define FNQ2(beg,len) SimBuffer::B().appendFnq(SimBuffer::Static(beg,len),true)
+#define FNQ2STDOK(beg,len) SimBuffer::B().appendFnq(SimBuffer::Static(beg,len),false)
+
+
+#define param_assert assert
+
+#undef __VA_START_STDC__
+#ifdef __STDC__
+# define __VA_START_STDC__ 1
+#endif
+#if _MSC_VER > 1000
+# undef __PROTOTYPES__
+# define __PROTOTYPES__ 1
+# undef __VA_START_STDC__
+# define __VA_START_STDC__ 1
+# pragma warning(disable: 4127) /* conditional expression is constant */
+# pragma warning(disable: 4244) /* =' : conversion from 'int ' to 'unsigned char ', possible loss of data */
+# pragma warning(disable: 4250) /* 'SimBuffer::B' : inherits 'SimBuffer::Flat::getLength' via dominance */
+# pragma warning(disable: 4514) /* 'each_char' : unreferenced inline function has been removed */
+# pragma warning(disable: 4512) /* 'PipeE' : assignment operator could not be generated */
+# pragma warning(disable: 4310) /* cast truncates constant value */
+# pragma warning(disable: 4355) /* 'this' : used in base member initializer list */
+#endif
+
+#if __VA_START_STDC__
+# define PTS_va_start(ap, fmt) va_start(ap, fmt)
+#else
+# define PTS_va_start(ap, fmt) va_start(ap)
+#endif
+
+#if HAVE_STATIC_CONST
+# define BEGIN_STATIC_ENUM(basetype,type) typedef basetype type; static const type
+# define BEGIN_STATIC_ENUM1(type) static const type
+# define END_STATIC_ENUM() ;
+#else /* VC6.0 */
+# define BEGIN_STATIC_ENUM(basetype,type) enum type {
+# define BEGIN_STATIC_ENUM1(type) enum {
+# define END_STATIC_ENUM() };
+#endif
+
+#if ((defined(__STDC__) || defined(__PROTOTYPES__)) && !defined(NO_PROTO)) || defined(__cplusplus)
+# define _(args) args
+# define OF(args) args
+# define ___(arg2s,arg1s,argafter) arg2s /* Dat: no direct comma allowed in args :-( */
+#else
+# define _(args) ()
+# define OF(args) ()
+# define ___(arg2s,arg1s,argafter) arg1s argafter /* Dat: no direct comma allowed in args :-( */
+#endif
+
+#if SIZEOF_BOOL!=1
+#define bool PTS_bool
+#define true 1
+#define false 0
+typedef unsigned char bool;
+#endif
+
+#ifdef const
+# undef const
+# define PTS_const
+# undef HAVE_CONST
+#else
+# define PTS_const const
+# define HAVE_CONST 1
+#endif
+
+#ifdef volatile
+# undef volatile
+# define PTS_volatile
+# undef HAVE_VOLATILE
+#else
+# define PTS_volatile volatile
+# define HAVE_VOLATILE 1
+#endif
+
+#ifdef NEED_STRING_H
+/* We use: memset(), memmove(), strncpy(), memcpy(), memcmp() */
+#if HAVE_MEMCMPY_BUILTIN
+# undef memcpy
+# define memcpy dummy_memcpy
+# undef memcmp
+# define memcmp dummy_memcmp
+#endif
+#ifdef HAVE_strcpy_in_string
+# include <string.h>
+#elif HAVE_strcpy_in_strings
+# include <strings.h>
+#else
+# error no strcpy
+#endif
+#if HAVE_MEMCMPY_BUILTIN
+# undef memcmp
+# undef memcpy
+#endif
+#endif
+
+#ifdef NEED_MALLOC
+#if HAVE_malloc_in_stdlib
+# include <stdlib.h>
+#elif HAVE_PTS_STDC && HAVE_malloc_in_malloc
+# include <malloc.h>
+#elif HAVE_PTS_STDC
+# error malloc() not found
+#elif HAVE_PROTOTYPES
+ void *malloc(PTS_size_t size);
+ void *realloc(void *ptr, PTS_size_t size);
+ void free(void *ptr);
+#else
+ void *malloc();
+ void *realloc();
+ void free();
+#endif
+#endif
+
+#ifdef NEED_ALLOCA
+/* Make alloca work the best possible way.
+ * Imp: AIX requires this to be the 1st thing in the file??
+ */
+#ifdef __GNUC__
+# ifndef atarist
+# ifndef alloca
+# define alloca __builtin_alloca
+# endif
+# endif /* atarist */
+#elif defined(__BORLANDC__)
+# include <malloc.h>
+#elif HAVE_ALLOCA_H
+# include <alloca.h>
+#elif defined(_AIX)
+ #pragma alloca /* indented to avoid choking of pre-ANSI compilers */
+#elif !defined alloca /* predefined by HP cc +Olibcalls */
+char *alloca ();
+#endif
+#endif /* NEED_ALLOCA */
+
+#ifdef NEED_SIGN_EXTEND_CHAR
+/* We remove any previous definition of `SIGN_EXTEND_CHAR',
+ since ours (we hope) works properly with all combinations of
+ machines, compilers, `char' and `unsigned char' argument types.
+ (Per Bothner suggested the basic approach.) */
+#undef SIGN_EXTEND_CHAR
+#if HAVE_PTS_STDC
+# define SIGN_EXTEND_CHAR(c) ((signed char)(c))
+#else /* not __STDC__ */
+/* As in Harbison and Steele. */
+# define SIGN_EXTEND_CHAR(c) ((((unsigned char)(c)) ^ 128) - 128)
+#endif
+#endif
+
+/* by pts@fazekas.hu at Fri Mar 22 17:01:27 CET 2002 */
+#if defined(HAVE_PTS_POPEN_)
+# define HAVE_PTS_POPEN 1
+# define CFG_PTS_POPEN_B ""
+#elif defined(HAVE_PTS_POPEN_B)
+# define HAVE_PTS_POPEN 1
+# define CFG_PTS_POPEN_B "b"
+#else
+# undef HAVE_PTS_POPEN
+#endif
+
+#undef NEED_LONG_LONG
+#undef NEED_LONG_DOUBLE
+
+/** Filename, directory and quoting conventions for the host OS.
+ * 0: UNIX
+ * 1: DOS/Win3.1
+ * 2: WinNT
+ * 3: Win9X
+ * 4: VMS
+ * 5: Mac
+ * 6...
+ *
+ * Imp: implement other than UNIX
+ */
+#define COTY_UNIX 0
+#define COTY_DOS 1
+#define COTY_WINNT 2
+#define COTY_WIN9X 3
+#define COTY_VMS 4
+#define COTY_MAC 5
+#define COTY_OTHER 6
+
+#if HAVE_PTS_SYSTEMF_UNIX
+# define OS_COTY COTY_UNIX
+#else
+# if HAVE_PTS_SYSTEMF_WIN32
+# define OS_COTY COTY_WIN9X
+# else
+# define OS_COTY COTY_OTHER
+# endif
+#endif
+
+/* vvv Imp: autodetect this */
+#if defined(__MSDOS__) || defined(__CYGWIN__) || defined(__MINGW32__) || _MSC_VER > 1000
+# define HAVE_DOS_BINARY 1
+#else
+# undef HAVE_DOS_BINARY
+#endif
+
+/* #define PTS_dynamic_cast(ptrtype,ptr) dynamic_cast<ptrtype>(ptr) -- would include special G++ symbols into .o */
+#define PTS_dynamic_cast(ptrtype,ptr) ((ptrtype)(ptr))
+
+/** Suppress effect of -Wcast-align warning */
+#define PTS_align_cast(ptrtype,ptr) ((ptrtype)(void*)(ptr))
+/** Suppress effect of -Wcast-align warning */
+#define PTS_calign_cast(ptrtype,ptr) ((ptrtype)(void const*)(ptr))
+
+
+#undef HAVE_LZW
+#if USE_BUILTIN_LZW
+# define HAVE_LZW 1
+#else
+# define HAVE_LZW 1 /* try to use external lzw_codec */
+#endif
+/* #define USE_BUILTIN_FAXE 1 */ /* in config.h */
+#undef USE_BUILTIN_FAXD /* sure */
+/* #define USE_BUILTIN_FAXD 1 */ /* in config.h */
+
+#ifndef __cplusplus
+#undef true
+#undef false
+#ifdef __BEOS__
+typedef unsigned char bool;
+#else
+typedef int bool;
+#endif
+#define true ((bool)1)
+#define false ((bool)0)
+#endif
+
+/* by pts@fazekas.hu at Tue Sep 3 18:47:47 CEST 2002 */
+#if OBJDEP && defined(__cplusplus) && HAVE_PTS_C_LGCC_CPP_REQUIRED
+# warning REQUIRES: c_lgcc.o
+#endif
+#if OBJDEP && defined(__cplusplus) && HAVE_PTS_C_LGCC3_CPP_REQUIRED
+# warning REQUIRES: c_lgcc3.o
+#endif
+
+/* at Wed Aug 21 18:28:24 CEST 2002 */
+#if HAVE_getc_in_stdio
+# define MACRO_GETC getc
+#else
+# if HAVE_fgetc_in_stdio
+# define MACRO_GETC fgetc
+# else
+# error getc() or fgetc() is required
+# endif
+#endif
+#if HAVE_putc_in_stdio
+# define MACRO_PUTC putc
+#else
+# if HAVE_fputc_in_stdio
+# define MACRO_PUTC fputc
+# else
+# error putc() or fputc() is required
+# endif
+#endif
+
+#ifndef USE_ATTRIBUTE_ALIAS
+#define USE_ATTRIBUTE_ALIAS 1
+#endif
+
+#endif /* config2.h */
diff --git a/graphics/sam2p/configure b/graphics/sam2p/configure
new file mode 100755
index 0000000000..a11eb3c74f
--- /dev/null
+++ b/graphics/sam2p/configure
@@ -0,0 +1,7538 @@
+#! /bin/sh
+# Guess values for system-dependent variables and create Makefiles.
+# Generated by GNU Autoconf 2.57.
+#
+# Copyright 1992, 1993, 1994, 1995, 1996, 1998, 1999, 2000, 2001, 2002
+# Free Software Foundation, Inc.
+# This configure script is free software; the Free Software Foundation
+# gives unlimited permission to copy, distribute and modify it.
+## --------------------- ##
+## M4sh Initialization. ##
+## --------------------- ##
+
+# Be Bourne compatible
+if test -n "${ZSH_VERSION+set}" && (emulate sh) >/dev/null 2>&1; then
+ emulate sh
+ NULLCMD=:
+ # Zsh 3.x and 4.x performs word splitting on ${1+"$@"}, which
+ # is contrary to our usage. Disable this feature.
+ alias -g '${1+"$@"}'='"$@"'
+elif test -n "${BASH_VERSION+set}" && (set -o posix) >/dev/null 2>&1; then
+ set -o posix
+fi
+
+# Support unset when possible.
+if (FOO=FOO; unset FOO) >/dev/null 2>&1; then
+ as_unset=unset
+else
+ as_unset=false
+fi
+
+
+# Work around bugs in pre-3.0 UWIN ksh.
+$as_unset ENV MAIL MAILPATH
+PS1='$ '
+PS2='> '
+PS4='+ '
+
+# NLS nuisances.
+for as_var in \
+ LANG LANGUAGE LC_ADDRESS LC_ALL LC_COLLATE LC_CTYPE LC_IDENTIFICATION \
+ LC_MEASUREMENT LC_MESSAGES LC_MONETARY LC_NAME LC_NUMERIC LC_PAPER \
+ LC_TELEPHONE LC_TIME
+do
+ if (set +x; test -n "`(eval $as_var=C; export $as_var) 2>&1`"); then
+ eval $as_var=C; export $as_var
+ else
+ $as_unset $as_var
+ fi
+done
+
+# Required to use basename.
+if expr a : '\(a\)' >/dev/null 2>&1; then
+ as_expr=expr
+else
+ as_expr=false
+fi
+
+if (basename /) >/dev/null 2>&1 && test "X`basename / 2>&1`" = "X/"; then
+ as_basename=basename
+else
+ as_basename=false
+fi
+
+
+# Name of the executable.
+as_me=`$as_basename "$0" ||
+$as_expr X/"$0" : '.*/\([^/][^/]*\)/*$' \| \
+ X"$0" : 'X\(//\)$' \| \
+ X"$0" : 'X\(/\)$' \| \
+ . : '\(.\)' 2>/dev/null ||
+echo X/"$0" |
+ sed '/^.*\/\([^/][^/]*\)\/*$/{ s//\1/; q; }
+ /^X\/\(\/\/\)$/{ s//\1/; q; }
+ /^X\/\(\/\).*/{ s//\1/; q; }
+ s/.*/./; q'`
+
+
+# PATH needs CR, and LINENO needs CR and PATH.
+# Avoid depending upon Character Ranges.
+as_cr_letters='abcdefghijklmnopqrstuvwxyz'
+as_cr_LETTERS='ABCDEFGHIJKLMNOPQRSTUVWXYZ'
+as_cr_Letters=$as_cr_letters$as_cr_LETTERS
+as_cr_digits='0123456789'
+as_cr_alnum=$as_cr_Letters$as_cr_digits
+
+# The user is always right.
+if test "${PATH_SEPARATOR+set}" != set; then
+ echo "#! /bin/sh" >conf$$.sh
+ echo "exit 0" >>conf$$.sh
+ chmod +x conf$$.sh
+ if (PATH="/nonexistent;."; conf$$.sh) >/dev/null 2>&1; then
+ PATH_SEPARATOR=';'
+ else
+ PATH_SEPARATOR=:
+ fi
+ rm -f conf$$.sh
+fi
+
+
+ as_lineno_1=$LINENO
+ as_lineno_2=$LINENO
+ as_lineno_3=`(expr $as_lineno_1 + 1) 2>/dev/null`
+ test "x$as_lineno_1" != "x$as_lineno_2" &&
+ test "x$as_lineno_3" = "x$as_lineno_2" || {
+ # Find who we are. Look in the path if we contain no path at all
+ # relative or not.
+ case $0 in
+ *[\\/]* ) as_myself=$0 ;;
+ *) as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+ IFS=$as_save_IFS
+ test -z "$as_dir" && as_dir=.
+ test -r "$as_dir/$0" && as_myself=$as_dir/$0 && break
+done
+
+ ;;
+ esac
+ # We did not find ourselves, most probably we were run as `sh COMMAND'
+ # in which case we are not to be found in the path.
+ if test "x$as_myself" = x; then
+ as_myself=$0
+ fi
+ if test ! -f "$as_myself"; then
+ { echo "$as_me: error: cannot find myself; rerun with an absolute path" >&2
+ { (exit 1); exit 1; }; }
+ fi
+ case $CONFIG_SHELL in
+ '')
+ as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in /bin$PATH_SEPARATOR/usr/bin$PATH_SEPARATOR$PATH
+do
+ IFS=$as_save_IFS
+ test -z "$as_dir" && as_dir=.
+ for as_base in sh bash ksh sh5; do
+ case $as_dir in
+ /*)
+ if ("$as_dir/$as_base" -c '
+ as_lineno_1=$LINENO
+ as_lineno_2=$LINENO
+ as_lineno_3=`(expr $as_lineno_1 + 1) 2>/dev/null`
+ test "x$as_lineno_1" != "x$as_lineno_2" &&
+ test "x$as_lineno_3" = "x$as_lineno_2" ') 2>/dev/null; then
+ $as_unset BASH_ENV || test "${BASH_ENV+set}" != set || { BASH_ENV=; export BASH_ENV; }
+ $as_unset ENV || test "${ENV+set}" != set || { ENV=; export ENV; }
+ CONFIG_SHELL=$as_dir/$as_base
+ export CONFIG_SHELL
+ exec "$CONFIG_SHELL" "$0" ${1+"$@"}
+ fi;;
+ esac
+ done
+done
+;;
+ esac
+
+ # Create $as_me.lineno as a copy of $as_myself, but with $LINENO
+ # uniformly replaced by the line number. The first 'sed' inserts a
+ # line-number line before each line; the second 'sed' does the real
+ # work. The second script uses 'N' to pair each line-number line
+ # with the numbered line, and appends trailing '-' during
+ # substitution so that $LINENO is not a special case at line end.
+ # (Raja R Harinath suggested sed '=', and Paul Eggert wrote the
+ # second 'sed' script. Blame Lee E. McMahon for sed's syntax. :-)
+ sed '=' <$as_myself |
+ sed '
+ N
+ s,$,-,
+ : loop
+ s,^\(['$as_cr_digits']*\)\(.*\)[$]LINENO\([^'$as_cr_alnum'_]\),\1\2\1\3,
+ t loop
+ s,-$,,
+ s,^['$as_cr_digits']*\n,,
+ ' >$as_me.lineno &&
+ chmod +x $as_me.lineno ||
+ { echo "$as_me: error: cannot create $as_me.lineno; rerun with a POSIX shell" >&2
+ { (exit 1); exit 1; }; }
+
+ # Don't try to exec as it changes $[0], causing all sort of problems
+ # (the dirname of $[0] is not the place where we might find the
+ # original and so on. Autoconf is especially sensible to this).
+ . ./$as_me.lineno
+ # Exit status is that of the last command.
+ exit
+}
+
+
+case `echo "testing\c"; echo 1,2,3`,`echo -n testing; echo 1,2,3` in
+ *c*,-n*) ECHO_N= ECHO_C='
+' ECHO_T=' ' ;;
+ *c*,* ) ECHO_N=-n ECHO_C= ECHO_T= ;;
+ *) ECHO_N= ECHO_C='\c' ECHO_T= ;;
+esac
+
+if expr a : '\(a\)' >/dev/null 2>&1; then
+ as_expr=expr
+else
+ as_expr=false
+fi
+
+rm -f conf$$ conf$$.exe conf$$.file
+echo >conf$$.file
+if ln -s conf$$.file conf$$ 2>/dev/null; then
+ # We could just check for DJGPP; but this test a) works b) is more generic
+ # and c) will remain valid once DJGPP supports symlinks (DJGPP 2.04).
+ if test -f conf$$.exe; then
+ # Don't use ln at all; we don't have any links
+ as_ln_s='cp -p'
+ else
+ as_ln_s='ln -s'
+ fi
+elif ln conf$$.file conf$$ 2>/dev/null; then
+ as_ln_s=ln
+else
+ as_ln_s='cp -p'
+fi
+rm -f conf$$ conf$$.exe conf$$.file
+
+if mkdir -p . 2>/dev/null; then
+ as_mkdir_p=:
+else
+ as_mkdir_p=false
+fi
+
+as_executable_p="test -f"
+
+# Sed expression to map a string onto a valid CPP name.
+as_tr_cpp="sed y%*$as_cr_letters%P$as_cr_LETTERS%;s%[^_$as_cr_alnum]%_%g"
+
+# Sed expression to map a string onto a valid variable name.
+as_tr_sh="sed y%*+%pp%;s%[^_$as_cr_alnum]%_%g"
+
+
+# IFS
+# We need space, tab and new line, in precisely that order.
+as_nl='
+'
+IFS=" $as_nl"
+
+# CDPATH.
+$as_unset CDPATH
+
+
+# Name of the host.
+# hostname on some systems (SVR3.2, Linux) returns a bogus exit status,
+# so uname gets run too.
+ac_hostname=`(hostname || uname -n) 2>/dev/null | sed 1q`
+
+exec 6>&1
+
+#
+# Initializations.
+#
+ac_default_prefix=/usr/local
+ac_config_libobj_dir=.
+cross_compiling=no
+subdirs=
+MFLAGS=
+MAKEFLAGS=
+SHELL=${CONFIG_SHELL-/bin/sh}
+
+# Maximum number of lines to put in a shell here document.
+# This variable seems obsolete. It should probably be removed, and
+# only ac_max_sed_lines should be used.
+: ${ac_max_here_lines=38}
+
+# Identity of this package.
+PACKAGE_NAME=
+PACKAGE_TARNAME=
+PACKAGE_VERSION=
+PACKAGE_STRING=
+PACKAGE_BUGREPORT=
+
+ac_unique_file="gensi.cpp"
+ac_subst_vars='SHELL PATH_SEPARATOR PACKAGE_NAME PACKAGE_TARNAME PACKAGE_VERSION PACKAGE_STRING PACKAGE_BUGREPORT exec_prefix prefix program_transform_name bindir sbindir libexecdir datadir sysconfdir sharedstatedir localstatedir libdir includedir oldincludedir infodir mandir build_alias host_alias target_alias DEFS ECHO_C ECHO_N ECHO_T LIBS ENABLE_DEBUG CXX CXXFLAGS LDFLAGS CPPFLAGS ac_ct_CXX EXEEXT OBJEXT GFLAG CXXFLAGSB LDXX pts_cjpeg pts_djpeg pts_tif22pnm pts_tifftopnm pts_pngtopnm pts_gs pts_lzw_codec pts_gzip pts_zip pts_bash pts_make pts_perl CXXCPP EGREP ALLOCA LIBOBJS LTLIBOBJS'
+ac_subst_files=''
+
+# Initialize some variables set by options.
+ac_init_help=
+ac_init_version=false
+# The variables have the same names as the options, with
+# dashes changed to underlines.
+cache_file=/dev/null
+exec_prefix=NONE
+no_create=
+no_recursion=
+prefix=NONE
+program_prefix=NONE
+program_suffix=NONE
+program_transform_name=s,x,x,
+silent=
+site=
+srcdir=
+verbose=
+x_includes=NONE
+x_libraries=NONE
+
+# Installation directory options.
+# These are left unexpanded so users can "make install exec_prefix=/foo"
+# and all the variables that are supposed to be based on exec_prefix
+# by default will actually change.
+# Use braces instead of parens because sh, perl, etc. also accept them.
+bindir='${exec_prefix}/bin'
+sbindir='${exec_prefix}/sbin'
+libexecdir='${exec_prefix}/libexec'
+datadir='${prefix}/share'
+sysconfdir='${prefix}/etc'
+sharedstatedir='${prefix}/com'
+localstatedir='${prefix}/var'
+libdir='${exec_prefix}/lib'
+includedir='${prefix}/include'
+oldincludedir='/usr/include'
+infodir='${prefix}/info'
+mandir='${prefix}/man'
+
+ac_prev=
+for ac_option
+do
+ # If the previous option needs an argument, assign it.
+ if test -n "$ac_prev"; then
+ eval "$ac_prev=\$ac_option"
+ ac_prev=
+ continue
+ fi
+
+ ac_optarg=`expr "x$ac_option" : 'x[^=]*=\(.*\)'`
+
+ # Accept the important Cygnus configure options, so we can diagnose typos.
+
+ case $ac_option in
+
+ -bindir | --bindir | --bindi | --bind | --bin | --bi)
+ ac_prev=bindir ;;
+ -bindir=* | --bindir=* | --bindi=* | --bind=* | --bin=* | --bi=*)
+ bindir=$ac_optarg ;;
+
+ -build | --build | --buil | --bui | --bu)
+ ac_prev=build_alias ;;
+ -build=* | --build=* | --buil=* | --bui=* | --bu=*)
+ build_alias=$ac_optarg ;;
+
+ -cache-file | --cache-file | --cache-fil | --cache-fi \
+ | --cache-f | --cache- | --cache | --cach | --cac | --ca | --c)
+ ac_prev=cache_file ;;
+ -cache-file=* | --cache-file=* | --cache-fil=* | --cache-fi=* \
+ | --cache-f=* | --cache-=* | --cache=* | --cach=* | --cac=* | --ca=* | --c=*)
+ cache_file=$ac_optarg ;;
+
+ --config-cache | -C)
+ cache_file=config.cache ;;
+
+ -datadir | --datadir | --datadi | --datad | --data | --dat | --da)
+ ac_prev=datadir ;;
+ -datadir=* | --datadir=* | --datadi=* | --datad=* | --data=* | --dat=* \
+ | --da=*)
+ datadir=$ac_optarg ;;
+
+ -disable-* | --disable-*)
+ ac_feature=`expr "x$ac_option" : 'x-*disable-\(.*\)'`
+ # Reject names that are not valid shell variable names.
+ expr "x$ac_feature" : ".*[^-_$as_cr_alnum]" >/dev/null &&
+ { echo "$as_me: error: invalid feature name: $ac_feature" >&2
+ { (exit 1); exit 1; }; }
+ ac_feature=`echo $ac_feature | sed 's/-/_/g'`
+ eval "enable_$ac_feature=no" ;;
+
+ -enable-* | --enable-*)
+ ac_feature=`expr "x$ac_option" : 'x-*enable-\([^=]*\)'`
+ # Reject names that are not valid shell variable names.
+ expr "x$ac_feature" : ".*[^-_$as_cr_alnum]" >/dev/null &&
+ { echo "$as_me: error: invalid feature name: $ac_feature" >&2
+ { (exit 1); exit 1; }; }
+ ac_feature=`echo $ac_feature | sed 's/-/_/g'`
+ case $ac_option in
+ *=*) ac_optarg=`echo "$ac_optarg" | sed "s/'/'\\\\\\\\''/g"`;;
+ *) ac_optarg=yes ;;
+ esac
+ eval "enable_$ac_feature='$ac_optarg'" ;;
+
+ -exec-prefix | --exec_prefix | --exec-prefix | --exec-prefi \
+ | --exec-pref | --exec-pre | --exec-pr | --exec-p | --exec- \
+ | --exec | --exe | --ex)
+ ac_prev=exec_prefix ;;
+ -exec-prefix=* | --exec_prefix=* | --exec-prefix=* | --exec-prefi=* \
+ | --exec-pref=* | --exec-pre=* | --exec-pr=* | --exec-p=* | --exec-=* \
+ | --exec=* | --exe=* | --ex=*)
+ exec_prefix=$ac_optarg ;;
+
+ -gas | --gas | --ga | --g)
+ # Obsolete; use --with-gas.
+ with_gas=yes ;;
+
+ -help | --help | --hel | --he | -h)
+ ac_init_help=long ;;
+ -help=r* | --help=r* | --hel=r* | --he=r* | -hr*)
+ ac_init_help=recursive ;;
+ -help=s* | --help=s* | --hel=s* | --he=s* | -hs*)
+ ac_init_help=short ;;
+
+ -host | --host | --hos | --ho)
+ ac_prev=host_alias ;;
+ -host=* | --host=* | --hos=* | --ho=*)
+ host_alias=$ac_optarg ;;
+
+ -includedir | --includedir | --includedi | --included | --include \
+ | --includ | --inclu | --incl | --inc)
+ ac_prev=includedir ;;
+ -includedir=* | --includedir=* | --includedi=* | --included=* | --include=* \
+ | --includ=* | --inclu=* | --incl=* | --inc=*)
+ includedir=$ac_optarg ;;
+
+ -infodir | --infodir | --infodi | --infod | --info | --inf)
+ ac_prev=infodir ;;
+ -infodir=* | --infodir=* | --infodi=* | --infod=* | --info=* | --inf=*)
+ infodir=$ac_optarg ;;
+
+ -libdir | --libdir | --libdi | --libd)
+ ac_prev=libdir ;;
+ -libdir=* | --libdir=* | --libdi=* | --libd=*)
+ libdir=$ac_optarg ;;
+
+ -libexecdir | --libexecdir | --libexecdi | --libexecd | --libexec \
+ | --libexe | --libex | --libe)
+ ac_prev=libexecdir ;;
+ -libexecdir=* | --libexecdir=* | --libexecdi=* | --libexecd=* | --libexec=* \
+ | --libexe=* | --libex=* | --libe=*)
+ libexecdir=$ac_optarg ;;
+
+ -localstatedir | --localstatedir | --localstatedi | --localstated \
+ | --localstate | --localstat | --localsta | --localst \
+ | --locals | --local | --loca | --loc | --lo)
+ ac_prev=localstatedir ;;
+ -localstatedir=* | --localstatedir=* | --localstatedi=* | --localstated=* \
+ | --localstate=* | --localstat=* | --localsta=* | --localst=* \
+ | --locals=* | --local=* | --loca=* | --loc=* | --lo=*)
+ localstatedir=$ac_optarg ;;
+
+ -mandir | --mandir | --mandi | --mand | --man | --ma | --m)
+ ac_prev=mandir ;;
+ -mandir=* | --mandir=* | --mandi=* | --mand=* | --man=* | --ma=* | --m=*)
+ mandir=$ac_optarg ;;
+
+ -nfp | --nfp | --nf)
+ # Obsolete; use --without-fp.
+ with_fp=no ;;
+
+ -no-create | --no-create | --no-creat | --no-crea | --no-cre \
+ | --no-cr | --no-c | -n)
+ no_create=yes ;;
+
+ -no-recursion | --no-recursion | --no-recursio | --no-recursi \
+ | --no-recurs | --no-recur | --no-recu | --no-rec | --no-re | --no-r)
+ no_recursion=yes ;;
+
+ -oldincludedir | --oldincludedir | --oldincludedi | --oldincluded \
+ | --oldinclude | --oldinclud | --oldinclu | --oldincl | --oldinc \
+ | --oldin | --oldi | --old | --ol | --o)
+ ac_prev=oldincludedir ;;
+ -oldincludedir=* | --oldincludedir=* | --oldincludedi=* | --oldincluded=* \
+ | --oldinclude=* | --oldinclud=* | --oldinclu=* | --oldincl=* | --oldinc=* \
+ | --oldin=* | --oldi=* | --old=* | --ol=* | --o=*)
+ oldincludedir=$ac_optarg ;;
+
+ -prefix | --prefix | --prefi | --pref | --pre | --pr | --p)
+ ac_prev=prefix ;;
+ -prefix=* | --prefix=* | --prefi=* | --pref=* | --pre=* | --pr=* | --p=*)
+ prefix=$ac_optarg ;;
+
+ -program-prefix | --program-prefix | --program-prefi | --program-pref \
+ | --program-pre | --program-pr | --program-p)
+ ac_prev=program_prefix ;;
+ -program-prefix=* | --program-prefix=* | --program-prefi=* \
+ | --program-pref=* | --program-pre=* | --program-pr=* | --program-p=*)
+ program_prefix=$ac_optarg ;;
+
+ -program-suffix | --program-suffix | --program-suffi | --program-suff \
+ | --program-suf | --program-su | --program-s)
+ ac_prev=program_suffix ;;
+ -program-suffix=* | --program-suffix=* | --program-suffi=* \
+ | --program-suff=* | --program-suf=* | --program-su=* | --program-s=*)
+ program_suffix=$ac_optarg ;;
+
+ -program-transform-name | --program-transform-name \
+ | --program-transform-nam | --program-transform-na \
+ | --program-transform-n | --program-transform- \
+ | --program-transform | --program-transfor \
+ | --program-transfo | --program-transf \
+ | --program-trans | --program-tran \
+ | --progr-tra | --program-tr | --program-t)
+ ac_prev=program_transform_name ;;
+ -program-transform-name=* | --program-transform-name=* \
+ | --program-transform-nam=* | --program-transform-na=* \
+ | --program-transform-n=* | --program-transform-=* \
+ | --program-transform=* | --program-transfor=* \
+ | --program-transfo=* | --program-transf=* \
+ | --program-trans=* | --program-tran=* \
+ | --progr-tra=* | --program-tr=* | --program-t=*)
+ program_transform_name=$ac_optarg ;;
+
+ -q | -quiet | --quiet | --quie | --qui | --qu | --q \
+ | -silent | --silent | --silen | --sile | --sil)
+ silent=yes ;;
+
+ -sbindir | --sbindir | --sbindi | --sbind | --sbin | --sbi | --sb)
+ ac_prev=sbindir ;;
+ -sbindir=* | --sbindir=* | --sbindi=* | --sbind=* | --sbin=* \
+ | --sbi=* | --sb=*)
+ sbindir=$ac_optarg ;;
+
+ -sharedstatedir | --sharedstatedir | --sharedstatedi \
+ | --sharedstated | --sharedstate | --sharedstat | --sharedsta \
+ | --sharedst | --shareds | --shared | --share | --shar \
+ | --sha | --sh)
+ ac_prev=sharedstatedir ;;
+ -sharedstatedir=* | --sharedstatedir=* | --sharedstatedi=* \
+ | --sharedstated=* | --sharedstate=* | --sharedstat=* | --sharedsta=* \
+ | --sharedst=* | --shareds=* | --shared=* | --share=* | --shar=* \
+ | --sha=* | --sh=*)
+ sharedstatedir=$ac_optarg ;;
+
+ -site | --site | --sit)
+ ac_prev=site ;;
+ -site=* | --site=* | --sit=*)
+ site=$ac_optarg ;;
+
+ -srcdir | --srcdir | --srcdi | --srcd | --src | --sr)
+ ac_prev=srcdir ;;
+ -srcdir=* | --srcdir=* | --srcdi=* | --srcd=* | --src=* | --sr=*)
+ srcdir=$ac_optarg ;;
+
+ -sysconfdir | --sysconfdir | --sysconfdi | --sysconfd | --sysconf \
+ | --syscon | --sysco | --sysc | --sys | --sy)
+ ac_prev=sysconfdir ;;
+ -sysconfdir=* | --sysconfdir=* | --sysconfdi=* | --sysconfd=* | --sysconf=* \
+ | --syscon=* | --sysco=* | --sysc=* | --sys=* | --sy=*)
+ sysconfdir=$ac_optarg ;;
+
+ -target | --target | --targe | --targ | --tar | --ta | --t)
+ ac_prev=target_alias ;;
+ -target=* | --target=* | --targe=* | --targ=* | --tar=* | --ta=* | --t=*)
+ target_alias=$ac_optarg ;;
+
+ -v | -verbose | --verbose | --verbos | --verbo | --verb)
+ verbose=yes ;;
+
+ -version | --version | --versio | --versi | --vers | -V)
+ ac_init_version=: ;;
+
+ -with-* | --with-*)
+ ac_package=`expr "x$ac_option" : 'x-*with-\([^=]*\)'`
+ # Reject names that are not valid shell variable names.
+ expr "x$ac_package" : ".*[^-_$as_cr_alnum]" >/dev/null &&
+ { echo "$as_me: error: invalid package name: $ac_package" >&2
+ { (exit 1); exit 1; }; }
+ ac_package=`echo $ac_package| sed 's/-/_/g'`
+ case $ac_option in
+ *=*) ac_optarg=`echo "$ac_optarg" | sed "s/'/'\\\\\\\\''/g"`;;
+ *) ac_optarg=yes ;;
+ esac
+ eval "with_$ac_package='$ac_optarg'" ;;
+
+ -without-* | --without-*)
+ ac_package=`expr "x$ac_option" : 'x-*without-\(.*\)'`
+ # Reject names that are not valid shell variable names.
+ expr "x$ac_package" : ".*[^-_$as_cr_alnum]" >/dev/null &&
+ { echo "$as_me: error: invalid package name: $ac_package" >&2
+ { (exit 1); exit 1; }; }
+ ac_package=`echo $ac_package | sed 's/-/_/g'`
+ eval "with_$ac_package=no" ;;
+
+ --x)
+ # Obsolete; use --with-x.
+ with_x=yes ;;
+
+ -x-includes | --x-includes | --x-include | --x-includ | --x-inclu \
+ | --x-incl | --x-inc | --x-in | --x-i)
+ ac_prev=x_includes ;;
+ -x-includes=* | --x-includes=* | --x-include=* | --x-includ=* | --x-inclu=* \
+ | --x-incl=* | --x-inc=* | --x-in=* | --x-i=*)
+ x_includes=$ac_optarg ;;
+
+ -x-libraries | --x-libraries | --x-librarie | --x-librari \
+ | --x-librar | --x-libra | --x-libr | --x-lib | --x-li | --x-l)
+ ac_prev=x_libraries ;;
+ -x-libraries=* | --x-libraries=* | --x-librarie=* | --x-librari=* \
+ | --x-librar=* | --x-libra=* | --x-libr=* | --x-lib=* | --x-li=* | --x-l=*)
+ x_libraries=$ac_optarg ;;
+
+ -*) { echo "$as_me: error: unrecognized option: $ac_option
+Try \`$0 --help' for more information." >&2
+ { (exit 1); exit 1; }; }
+ ;;
+
+ *=*)
+ ac_envvar=`expr "x$ac_option" : 'x\([^=]*\)='`
+ # Reject names that are not valid shell variable names.
+ expr "x$ac_envvar" : ".*[^_$as_cr_alnum]" >/dev/null &&
+ { echo "$as_me: error: invalid variable name: $ac_envvar" >&2
+ { (exit 1); exit 1; }; }
+ ac_optarg=`echo "$ac_optarg" | sed "s/'/'\\\\\\\\''/g"`
+ eval "$ac_envvar='$ac_optarg'"
+ export $ac_envvar ;;
+
+ *)
+ # FIXME: should be removed in autoconf 3.0.
+ echo "$as_me: WARNING: you should use --build, --host, --target" >&2
+ expr "x$ac_option" : ".*[^-._$as_cr_alnum]" >/dev/null &&
+ echo "$as_me: WARNING: invalid host type: $ac_option" >&2
+ : ${build_alias=$ac_option} ${host_alias=$ac_option} ${target_alias=$ac_option}
+ ;;
+
+ esac
+done
+
+if test -n "$ac_prev"; then
+ ac_option=--`echo $ac_prev | sed 's/_/-/g'`
+ { echo "$as_me: error: missing argument to $ac_option" >&2
+ { (exit 1); exit 1; }; }
+fi
+
+# Be sure to have absolute paths.
+for ac_var in exec_prefix prefix
+do
+ eval ac_val=$`echo $ac_var`
+ case $ac_val in
+ [\\/$]* | ?:[\\/]* | NONE | '' ) ;;
+ *) { echo "$as_me: error: expected an absolute directory name for --$ac_var: $ac_val" >&2
+ { (exit 1); exit 1; }; };;
+ esac
+done
+
+# Be sure to have absolute paths.
+for ac_var in bindir sbindir libexecdir datadir sysconfdir sharedstatedir \
+ localstatedir libdir includedir oldincludedir infodir mandir
+do
+ eval ac_val=$`echo $ac_var`
+ case $ac_val in
+ [\\/$]* | ?:[\\/]* ) ;;
+ *) { echo "$as_me: error: expected an absolute directory name for --$ac_var: $ac_val" >&2
+ { (exit 1); exit 1; }; };;
+ esac
+done
+
+# There might be people who depend on the old broken behavior: `$host'
+# used to hold the argument of --host etc.
+# FIXME: To remove some day.
+build=$build_alias
+host=$host_alias
+target=$target_alias
+
+# FIXME: To remove some day.
+if test "x$host_alias" != x; then
+ if test "x$build_alias" = x; then
+ cross_compiling=maybe
+ echo "$as_me: WARNING: If you wanted to set the --build type, don't use --host.
+ If a cross compiler is detected then cross compile mode will be used." >&2
+ elif test "x$build_alias" != "x$host_alias"; then
+ cross_compiling=yes
+ fi
+fi
+
+ac_tool_prefix=
+test -n "$host_alias" && ac_tool_prefix=$host_alias-
+
+test "$silent" = yes && exec 6>/dev/null
+
+
+# Find the source files, if location was not specified.
+if test -z "$srcdir"; then
+ ac_srcdir_defaulted=yes
+ # Try the directory containing this script, then its parent.
+ ac_confdir=`(dirname "$0") 2>/dev/null ||
+$as_expr X"$0" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \
+ X"$0" : 'X\(//\)[^/]' \| \
+ X"$0" : 'X\(//\)$' \| \
+ X"$0" : 'X\(/\)' \| \
+ . : '\(.\)' 2>/dev/null ||
+echo X"$0" |
+ sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ s//\1/; q; }
+ /^X\(\/\/\)[^/].*/{ s//\1/; q; }
+ /^X\(\/\/\)$/{ s//\1/; q; }
+ /^X\(\/\).*/{ s//\1/; q; }
+ s/.*/./; q'`
+ srcdir=$ac_confdir
+ if test ! -r $srcdir/$ac_unique_file; then
+ srcdir=..
+ fi
+else
+ ac_srcdir_defaulted=no
+fi
+if test ! -r $srcdir/$ac_unique_file; then
+ if test "$ac_srcdir_defaulted" = yes; then
+ { echo "$as_me: error: cannot find sources ($ac_unique_file) in $ac_confdir or .." >&2
+ { (exit 1); exit 1; }; }
+ else
+ { echo "$as_me: error: cannot find sources ($ac_unique_file) in $srcdir" >&2
+ { (exit 1); exit 1; }; }
+ fi
+fi
+(cd $srcdir && test -r ./$ac_unique_file) 2>/dev/null ||
+ { echo "$as_me: error: sources are in $srcdir, but \`cd $srcdir' does not work" >&2
+ { (exit 1); exit 1; }; }
+srcdir=`echo "$srcdir" | sed 's%\([^\\/]\)[\\/]*$%\1%'`
+ac_env_build_alias_set=${build_alias+set}
+ac_env_build_alias_value=$build_alias
+ac_cv_env_build_alias_set=${build_alias+set}
+ac_cv_env_build_alias_value=$build_alias
+ac_env_host_alias_set=${host_alias+set}
+ac_env_host_alias_value=$host_alias
+ac_cv_env_host_alias_set=${host_alias+set}
+ac_cv_env_host_alias_value=$host_alias
+ac_env_target_alias_set=${target_alias+set}
+ac_env_target_alias_value=$target_alias
+ac_cv_env_target_alias_set=${target_alias+set}
+ac_cv_env_target_alias_value=$target_alias
+ac_env_CXX_set=${CXX+set}
+ac_env_CXX_value=$CXX
+ac_cv_env_CXX_set=${CXX+set}
+ac_cv_env_CXX_value=$CXX
+ac_env_CXXFLAGS_set=${CXXFLAGS+set}
+ac_env_CXXFLAGS_value=$CXXFLAGS
+ac_cv_env_CXXFLAGS_set=${CXXFLAGS+set}
+ac_cv_env_CXXFLAGS_value=$CXXFLAGS
+ac_env_LDFLAGS_set=${LDFLAGS+set}
+ac_env_LDFLAGS_value=$LDFLAGS
+ac_cv_env_LDFLAGS_set=${LDFLAGS+set}
+ac_cv_env_LDFLAGS_value=$LDFLAGS
+ac_env_CPPFLAGS_set=${CPPFLAGS+set}
+ac_env_CPPFLAGS_value=$CPPFLAGS
+ac_cv_env_CPPFLAGS_set=${CPPFLAGS+set}
+ac_cv_env_CPPFLAGS_value=$CPPFLAGS
+ac_env_CXXCPP_set=${CXXCPP+set}
+ac_env_CXXCPP_value=$CXXCPP
+ac_cv_env_CXXCPP_set=${CXXCPP+set}
+ac_cv_env_CXXCPP_value=$CXXCPP
+
+#
+# Report the --help message.
+#
+if test "$ac_init_help" = "long"; then
+ # Omit some internal or obsolete options to make the list less imposing.
+ # This message is too long to be a string in the A/UX 3.1 sh.
+ cat <<_ACEOF
+\`configure' configures this package to adapt to many kinds of systems.
+
+Usage: $0 [OPTION]... [VAR=VALUE]...
+
+To assign environment variables (e.g., CC, CFLAGS...), specify them as
+VAR=VALUE. See below for descriptions of some of the useful variables.
+
+Defaults for the options are specified in brackets.
+
+Configuration:
+ -h, --help display this help and exit
+ --help=short display options specific to this package
+ --help=recursive display the short help of all the included packages
+ -V, --version display version information and exit
+ -q, --quiet, --silent do not print \`checking...' messages
+ --cache-file=FILE cache test results in FILE [disabled]
+ -C, --config-cache alias for \`--cache-file=config.cache'
+ -n, --no-create do not create output files
+ --srcdir=DIR find the sources in DIR [configure dir or \`..']
+
+_ACEOF
+
+ cat <<_ACEOF
+Installation directories:
+ --prefix=PREFIX install architecture-independent files in PREFIX
+ [$ac_default_prefix]
+ --exec-prefix=EPREFIX install architecture-dependent files in EPREFIX
+ [PREFIX]
+
+By default, \`make install' will install all the files in
+\`$ac_default_prefix/bin', \`$ac_default_prefix/lib' etc. You can specify
+an installation prefix other than \`$ac_default_prefix' using \`--prefix',
+for instance \`--prefix=\$HOME'.
+
+For better control, use the options below.
+
+Fine tuning of the installation directories:
+ --bindir=DIR user executables [EPREFIX/bin]
+ --sbindir=DIR system admin executables [EPREFIX/sbin]
+ --libexecdir=DIR program executables [EPREFIX/libexec]
+ --datadir=DIR read-only architecture-independent data [PREFIX/share]
+ --sysconfdir=DIR read-only single-machine data [PREFIX/etc]
+ --sharedstatedir=DIR modifiable architecture-independent data [PREFIX/com]
+ --localstatedir=DIR modifiable single-machine data [PREFIX/var]
+ --libdir=DIR object code libraries [EPREFIX/lib]
+ --includedir=DIR C header files [PREFIX/include]
+ --oldincludedir=DIR C header files for non-gcc [/usr/include]
+ --infodir=DIR info documentation [PREFIX/info]
+ --mandir=DIR man documentation [PREFIX/man]
+_ACEOF
+
+ cat <<\_ACEOF
+_ACEOF
+fi
+
+if test -n "$ac_init_help"; then
+
+ cat <<\_ACEOF
+
+Optional Features:
+ --disable-FEATURE do not include FEATURE (same as --enable-FEATURE=no)
+ --enable-FEATURE[=ARG] include FEATURE [ARG=yes]
+ --enable-debug=val val: no, assert(default), yes, checker
+ --enable-lzw enable built-in LZW (de)compression (def: no)
+ --enable-zip enable built-in ZIP compression (def: yes)
+ --enable-fax enable built-in Fax compression (def: yes)
+ --enable-gif enable reading and writing GIF images (def: no)
+
+Some influential environment variables:
+ CXX C++ compiler command
+ CXXFLAGS C++ compiler flags
+ LDFLAGS linker flags, e.g. -L<lib dir> if you have libraries in a
+ nonstandard directory <lib dir>
+ CPPFLAGS C/C++ preprocessor flags, e.g. -I<include dir> if you have
+ headers in a nonstandard directory <include dir>
+ CXXCPP C++ preprocessor
+
+Use these variables to override the choices made by `configure' or to help
+it to find libraries and programs with nonstandard names/locations.
+
+_ACEOF
+fi
+
+if test "$ac_init_help" = "recursive"; then
+ # If there are subdirs, report their specific --help.
+ ac_popdir=`pwd`
+ for ac_dir in : $ac_subdirs_all; do test "x$ac_dir" = x: && continue
+ test -d $ac_dir || continue
+ ac_builddir=.
+
+if test "$ac_dir" != .; then
+ ac_dir_suffix=/`echo "$ac_dir" | sed 's,^\.[\\/],,'`
+ # A "../" for each directory in $ac_dir_suffix.
+ ac_top_builddir=`echo "$ac_dir_suffix" | sed 's,/[^\\/]*,../,g'`
+else
+ ac_dir_suffix= ac_top_builddir=
+fi
+
+case $srcdir in
+ .) # No --srcdir option. We are building in place.
+ ac_srcdir=.
+ if test -z "$ac_top_builddir"; then
+ ac_top_srcdir=.
+ else
+ ac_top_srcdir=`echo $ac_top_builddir | sed 's,/$,,'`
+ fi ;;
+ [\\/]* | ?:[\\/]* ) # Absolute path.
+ ac_srcdir=$srcdir$ac_dir_suffix;
+ ac_top_srcdir=$srcdir ;;
+ *) # Relative path.
+ ac_srcdir=$ac_top_builddir$srcdir$ac_dir_suffix
+ ac_top_srcdir=$ac_top_builddir$srcdir ;;
+esac
+# Don't blindly perform a `cd "$ac_dir"/$ac_foo && pwd` since $ac_foo can be
+# absolute.
+ac_abs_builddir=`cd "$ac_dir" && cd $ac_builddir && pwd`
+ac_abs_top_builddir=`cd "$ac_dir" && cd ${ac_top_builddir}. && pwd`
+ac_abs_srcdir=`cd "$ac_dir" && cd $ac_srcdir && pwd`
+ac_abs_top_srcdir=`cd "$ac_dir" && cd $ac_top_srcdir && pwd`
+
+ cd $ac_dir
+ # Check for guested configure; otherwise get Cygnus style configure.
+ if test -f $ac_srcdir/configure.gnu; then
+ echo
+ $SHELL $ac_srcdir/configure.gnu --help=recursive
+ elif test -f $ac_srcdir/configure; then
+ echo
+ $SHELL $ac_srcdir/configure --help=recursive
+ elif test -f $ac_srcdir/configure.ac ||
+ test -f $ac_srcdir/configure.in; then
+ echo
+ $ac_configure --help
+ else
+ echo "$as_me: WARNING: no configuration information is in $ac_dir" >&2
+ fi
+ cd $ac_popdir
+ done
+fi
+
+test -n "$ac_init_help" && exit 0
+if $ac_init_version; then
+ cat <<\_ACEOF
+
+Copyright 1992, 1993, 1994, 1995, 1996, 1998, 1999, 2000, 2001, 2002
+Free Software Foundation, Inc.
+This configure script is free software; the Free Software Foundation
+gives unlimited permission to copy, distribute and modify it.
+_ACEOF
+ exit 0
+fi
+exec 5>config.log
+cat >&5 <<_ACEOF
+This file contains any messages produced by compilers while
+running configure, to aid debugging if configure makes a mistake.
+
+It was created by $as_me, which was
+generated by GNU Autoconf 2.57. Invocation command line was
+
+ $ $0 $@
+
+_ACEOF
+{
+cat <<_ASUNAME
+## --------- ##
+## Platform. ##
+## --------- ##
+
+hostname = `(hostname || uname -n) 2>/dev/null | sed 1q`
+uname -m = `(uname -m) 2>/dev/null || echo unknown`
+uname -r = `(uname -r) 2>/dev/null || echo unknown`
+uname -s = `(uname -s) 2>/dev/null || echo unknown`
+uname -v = `(uname -v) 2>/dev/null || echo unknown`
+
+/usr/bin/uname -p = `(/usr/bin/uname -p) 2>/dev/null || echo unknown`
+/bin/uname -X = `(/bin/uname -X) 2>/dev/null || echo unknown`
+
+/bin/arch = `(/bin/arch) 2>/dev/null || echo unknown`
+/usr/bin/arch -k = `(/usr/bin/arch -k) 2>/dev/null || echo unknown`
+/usr/convex/getsysinfo = `(/usr/convex/getsysinfo) 2>/dev/null || echo unknown`
+hostinfo = `(hostinfo) 2>/dev/null || echo unknown`
+/bin/machine = `(/bin/machine) 2>/dev/null || echo unknown`
+/usr/bin/oslevel = `(/usr/bin/oslevel) 2>/dev/null || echo unknown`
+/bin/universe = `(/bin/universe) 2>/dev/null || echo unknown`
+
+_ASUNAME
+
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+ IFS=$as_save_IFS
+ test -z "$as_dir" && as_dir=.
+ echo "PATH: $as_dir"
+done
+
+} >&5
+
+cat >&5 <<_ACEOF
+
+
+## ----------- ##
+## Core tests. ##
+## ----------- ##
+
+_ACEOF
+
+
+# Keep a trace of the command line.
+# Strip out --no-create and --no-recursion so they do not pile up.
+# Strip out --silent because we don't want to record it for future runs.
+# Also quote any args containing shell meta-characters.
+# Make two passes to allow for proper duplicate-argument suppression.
+ac_configure_args=
+ac_configure_args0=
+ac_configure_args1=
+ac_sep=
+ac_must_keep_next=false
+for ac_pass in 1 2
+do
+ for ac_arg
+ do
+ case $ac_arg in
+ -no-create | --no-c* | -n | -no-recursion | --no-r*) continue ;;
+ -q | -quiet | --quiet | --quie | --qui | --qu | --q \
+ | -silent | --silent | --silen | --sile | --sil)
+ continue ;;
+ *" "*|*" "*|*[\[\]\~\#\$\^\&\*\(\)\{\}\\\|\;\<\>\?\"\']*)
+ ac_arg=`echo "$ac_arg" | sed "s/'/'\\\\\\\\''/g"` ;;
+ esac
+ case $ac_pass in
+ 1) ac_configure_args0="$ac_configure_args0 '$ac_arg'" ;;
+ 2)
+ ac_configure_args1="$ac_configure_args1 '$ac_arg'"
+ if test $ac_must_keep_next = true; then
+ ac_must_keep_next=false # Got value, back to normal.
+ else
+ case $ac_arg in
+ *=* | --config-cache | -C | -disable-* | --disable-* \
+ | -enable-* | --enable-* | -gas | --g* | -nfp | --nf* \
+ | -q | -quiet | --q* | -silent | --sil* | -v | -verb* \
+ | -with-* | --with-* | -without-* | --without-* | --x)
+ case "$ac_configure_args0 " in
+ "$ac_configure_args1"*" '$ac_arg' "* ) continue ;;
+ esac
+ ;;
+ -* ) ac_must_keep_next=true ;;
+ esac
+ fi
+ ac_configure_args="$ac_configure_args$ac_sep'$ac_arg'"
+ # Get rid of the leading space.
+ ac_sep=" "
+ ;;
+ esac
+ done
+done
+$as_unset ac_configure_args0 || test "${ac_configure_args0+set}" != set || { ac_configure_args0=; export ac_configure_args0; }
+$as_unset ac_configure_args1 || test "${ac_configure_args1+set}" != set || { ac_configure_args1=; export ac_configure_args1; }
+
+# When interrupted or exit'd, cleanup temporary files, and complete
+# config.log. We remove comments because anyway the quotes in there
+# would cause problems or look ugly.
+# WARNING: Be sure not to use single quotes in there, as some shells,
+# such as our DU 5.0 friend, will then `close' the trap.
+trap 'exit_status=$?
+ # Save into config.log some information that might help in debugging.
+ {
+ echo
+
+ cat <<\_ASBOX
+## ---------------- ##
+## Cache variables. ##
+## ---------------- ##
+_ASBOX
+ echo
+ # The following way of writing the cache mishandles newlines in values,
+{
+ (set) 2>&1 |
+ case `(ac_space='"'"' '"'"'; set | grep ac_space) 2>&1` in
+ *ac_space=\ *)
+ sed -n \
+ "s/'"'"'/'"'"'\\\\'"'"''"'"'/g;
+ s/^\\([_$as_cr_alnum]*_cv_[_$as_cr_alnum]*\\)=\\(.*\\)/\\1='"'"'\\2'"'"'/p"
+ ;;
+ *)
+ sed -n \
+ "s/^\\([_$as_cr_alnum]*_cv_[_$as_cr_alnum]*\\)=\\(.*\\)/\\1=\\2/p"
+ ;;
+ esac;
+}
+ echo
+
+ cat <<\_ASBOX
+## ----------------- ##
+## Output variables. ##
+## ----------------- ##
+_ASBOX
+ echo
+ for ac_var in $ac_subst_vars
+ do
+ eval ac_val=$`echo $ac_var`
+ echo "$ac_var='"'"'$ac_val'"'"'"
+ done | sort
+ echo
+
+ if test -n "$ac_subst_files"; then
+ cat <<\_ASBOX
+## ------------- ##
+## Output files. ##
+## ------------- ##
+_ASBOX
+ echo
+ for ac_var in $ac_subst_files
+ do
+ eval ac_val=$`echo $ac_var`
+ echo "$ac_var='"'"'$ac_val'"'"'"
+ done | sort
+ echo
+ fi
+
+ if test -s confdefs.h; then
+ cat <<\_ASBOX
+## ----------- ##
+## confdefs.h. ##
+## ----------- ##
+_ASBOX
+ echo
+ sed "/^$/d" confdefs.h | sort
+ echo
+ fi
+ test "$ac_signal" != 0 &&
+ echo "$as_me: caught signal $ac_signal"
+ echo "$as_me: exit $exit_status"
+ } >&5
+ rm -f core core.* *.core &&
+ rm -rf conftest* confdefs* conf$$* $ac_clean_files &&
+ exit $exit_status
+ ' 0
+for ac_signal in 1 2 13 15; do
+ trap 'ac_signal='$ac_signal'; { (exit 1); exit 1; }' $ac_signal
+done
+ac_signal=0
+
+# confdefs.h avoids OS command line length limits that DEFS can exceed.
+rm -rf conftest* confdefs.h
+# AIX cpp loses on an empty file, so make sure it contains at least a newline.
+echo >confdefs.h
+
+# Predefined preprocessor variables.
+
+cat >>confdefs.h <<_ACEOF
+#define PACKAGE_NAME "$PACKAGE_NAME"
+_ACEOF
+
+
+cat >>confdefs.h <<_ACEOF
+#define PACKAGE_TARNAME "$PACKAGE_TARNAME"
+_ACEOF
+
+
+cat >>confdefs.h <<_ACEOF
+#define PACKAGE_VERSION "$PACKAGE_VERSION"
+_ACEOF
+
+
+cat >>confdefs.h <<_ACEOF
+#define PACKAGE_STRING "$PACKAGE_STRING"
+_ACEOF
+
+
+cat >>confdefs.h <<_ACEOF
+#define PACKAGE_BUGREPORT "$PACKAGE_BUGREPORT"
+_ACEOF
+
+
+# Let the site file select an alternate cache file if it wants to.
+# Prefer explicitly selected file to automatically selected ones.
+if test -z "$CONFIG_SITE"; then
+ if test "x$prefix" != xNONE; then
+ CONFIG_SITE="$prefix/share/config.site $prefix/etc/config.site"
+ else
+ CONFIG_SITE="$ac_default_prefix/share/config.site $ac_default_prefix/etc/config.site"
+ fi
+fi
+for ac_site_file in $CONFIG_SITE; do
+ if test -r "$ac_site_file"; then
+ { echo "$as_me:$LINENO: loading site script $ac_site_file" >&5
+echo "$as_me: loading site script $ac_site_file" >&6;}
+ sed 's/^/| /' "$ac_site_file" >&5
+ . "$ac_site_file"
+ fi
+done
+
+if test -r "$cache_file"; then
+ # Some versions of bash will fail to source /dev/null (special
+ # files actually), so we avoid doing that.
+ if test -f "$cache_file"; then
+ { echo "$as_me:$LINENO: loading cache $cache_file" >&5
+echo "$as_me: loading cache $cache_file" >&6;}
+ case $cache_file in
+ [\\/]* | ?:[\\/]* ) . $cache_file;;
+ *) . ./$cache_file;;
+ esac
+ fi
+else
+ { echo "$as_me:$LINENO: creating cache $cache_file" >&5
+echo "$as_me: creating cache $cache_file" >&6;}
+ >$cache_file
+fi
+
+# Check that the precious variables saved in the cache have kept the same
+# value.
+ac_cache_corrupted=false
+for ac_var in `(set) 2>&1 |
+ sed -n 's/^ac_env_\([a-zA-Z_0-9]*\)_set=.*/\1/p'`; do
+ eval ac_old_set=\$ac_cv_env_${ac_var}_set
+ eval ac_new_set=\$ac_env_${ac_var}_set
+ eval ac_old_val="\$ac_cv_env_${ac_var}_value"
+ eval ac_new_val="\$ac_env_${ac_var}_value"
+ case $ac_old_set,$ac_new_set in
+ set,)
+ { echo "$as_me:$LINENO: error: \`$ac_var' was set to \`$ac_old_val' in the previous run" >&5
+echo "$as_me: error: \`$ac_var' was set to \`$ac_old_val' in the previous run" >&2;}
+ ac_cache_corrupted=: ;;
+ ,set)
+ { echo "$as_me:$LINENO: error: \`$ac_var' was not set in the previous run" >&5
+echo "$as_me: error: \`$ac_var' was not set in the previous run" >&2;}
+ ac_cache_corrupted=: ;;
+ ,);;
+ *)
+ if test "x$ac_old_val" != "x$ac_new_val"; then
+ { echo "$as_me:$LINENO: error: \`$ac_var' has changed since the previous run:" >&5
+echo "$as_me: error: \`$ac_var' has changed since the previous run:" >&2;}
+ { echo "$as_me:$LINENO: former value: $ac_old_val" >&5
+echo "$as_me: former value: $ac_old_val" >&2;}
+ { echo "$as_me:$LINENO: current value: $ac_new_val" >&5
+echo "$as_me: current value: $ac_new_val" >&2;}
+ ac_cache_corrupted=:
+ fi;;
+ esac
+ # Pass precious variables to config.status.
+ if test "$ac_new_set" = set; then
+ case $ac_new_val in
+ *" "*|*" "*|*[\[\]\~\#\$\^\&\*\(\)\{\}\\\|\;\<\>\?\"\']*)
+ ac_arg=$ac_var=`echo "$ac_new_val" | sed "s/'/'\\\\\\\\''/g"` ;;
+ *) ac_arg=$ac_var=$ac_new_val ;;
+ esac
+ case " $ac_configure_args " in
+ *" '$ac_arg' "*) ;; # Avoid dups. Use of quotes ensures accuracy.
+ *) ac_configure_args="$ac_configure_args '$ac_arg'" ;;
+ esac
+ fi
+done
+if $ac_cache_corrupted; then
+ { echo "$as_me:$LINENO: error: changes in the environment can compromise the build" >&5
+echo "$as_me: error: changes in the environment can compromise the build" >&2;}
+ { { echo "$as_me:$LINENO: error: run \`make distclean' and/or \`rm $cache_file' and start over" >&5
+echo "$as_me: error: run \`make distclean' and/or \`rm $cache_file' and start over" >&2;}
+ { (exit 1); exit 1; }; }
+fi
+
+ac_ext=c
+ac_cpp='$CPP $CPPFLAGS'
+ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
+ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_c_compiler_gnu
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ ac_config_headers="$ac_config_headers config.h"
+
+
+ echo "$as_me:$LINENO: checking for --enable-debug" >&5
+echo $ECHO_N "checking for --enable-debug... $ECHO_C" >&6
+
+ # Check whether --enable-debug or --disable-debug was given.
+if test "${enable_debug+set}" = set; then
+ enableval="$enable_debug"
+
+fi;
+ ENABLE_DEBUG="$enable_debug"
+ if test x"$enable_debug" = xno; then
+ echo "$as_me:$LINENO: result: no" >&5
+echo "${ECHO_T}no" >&6
+ elif test x"$enable_debug" = x || test x"$enable_debug" = xassert; then
+ echo "$as_me:$LINENO: result: assert" >&5
+echo "${ECHO_T}assert" >&6
+ ENABLE_DEBUG=assert
+ elif test x"$enable_debug" = xyes; then
+ echo "$as_me:$LINENO: result: yes" >&5
+echo "${ECHO_T}yes" >&6
+ elif test x"$enable_debug" = xchecker; then
+ echo "$as_me:$LINENO: result: checker" >&5
+echo "${ECHO_T}checker" >&6
+ else
+ echo "$as_me:$LINENO: result: \"?? $enable_debug\"" >&5
+echo "${ECHO_T}\"?? $enable_debug\"" >&6
+ { { echo "$as_me:$LINENO: error: Invalid --enable--debug option specified." >&5
+echo "$as_me: error: Invalid --enable--debug option specified." >&2;}
+ { (exit 1); exit 1; }; }
+ fi
+
+
+echo "$as_me:$LINENO: checking for --enable-lzw" >&5
+echo $ECHO_N "checking for --enable-lzw... $ECHO_C" >&6
+# Check whether --enable-lzw or --disable-lzw was given.
+if test "${enable_lzw+set}" = set; then
+ enableval="$enable_lzw"
+
+fi;
+if test x1 = x"`perl -e 'print time>1056165811'`"; then
+ # After 19 June 2003: default: yes
+ if test x"$enable_lzw" = x"no"; then
+ echo "$as_me:$LINENO: result: no" >&5
+echo "${ECHO_T}no" >&6
+ else
+ echo "$as_me:$LINENO: result: yes" >&5
+echo "${ECHO_T}yes" >&6
+ cat >>confdefs.h <<\_ACEOF
+#define USE_BUILTIN_LZW 1
+_ACEOF
+
+ fi
+else
+ if test x"$enable_lzw" = x"yes"; then
+ echo "$as_me:$LINENO: result: yes" >&5
+echo "${ECHO_T}yes" >&6
+ cat >>confdefs.h <<\_ACEOF
+#define USE_BUILTIN_LZW 1
+_ACEOF
+
+ { echo "$as_me:$LINENO: WARNING: LZW is patented till 19 June 2003; ask permission from Unisys to use it!" >&5
+echo "$as_me: WARNING: LZW is patented till 19 June 2003; ask permission from Unisys to use it!" >&2;}
+ else
+ echo "$as_me:$LINENO: result: no" >&5
+echo "${ECHO_T}no" >&6
+ fi
+fi
+
+echo "$as_me:$LINENO: checking for --enable-zip" >&5
+echo $ECHO_N "checking for --enable-zip... $ECHO_C" >&6
+# Check whether --enable-zip or --disable-zip was given.
+if test "${enable_zip+set}" = set; then
+ enableval="$enable_zip"
+
+fi;
+if test x"$enable_zip" = x"no"; then
+ echo "$as_me:$LINENO: result: no" >&5
+echo "${ECHO_T}no" >&6
+else
+ echo "$as_me:$LINENO: result: yes" >&5
+echo "${ECHO_T}yes" >&6
+ cat >>confdefs.h <<\_ACEOF
+#define USE_BUILTIN_ZIP 1
+_ACEOF
+
+fi
+
+echo "$as_me:$LINENO: checking for --enable-fax" >&5
+echo $ECHO_N "checking for --enable-fax... $ECHO_C" >&6
+# Check whether --enable-fax or --disable-fax was given.
+if test "${enable_fax+set}" = set; then
+ enableval="$enable_fax"
+
+fi;
+if test x"$enable_fax" = x"no"; then
+ echo "$as_me:$LINENO: result: no" >&5
+echo "${ECHO_T}no" >&6
+else
+ echo "$as_me:$LINENO: result: yes" >&5
+echo "${ECHO_T}yes" >&6
+ cat >>confdefs.h <<\_ACEOF
+#define USE_BUILTIN_FAXE 1
+_ACEOF
+
+fi
+
+echo "$as_me:$LINENO: checking for --enable-gif" >&5
+echo $ECHO_N "checking for --enable-gif... $ECHO_C" >&6
+# Check whether --enable-gif or --disable-gif was given.
+if test "${enable_gif+set}" = set; then
+ enableval="$enable_gif"
+
+fi;
+if test x"$enable_gif" = x"yes"; then
+ echo "$as_me:$LINENO: result: yes" >&5
+echo "${ECHO_T}yes" >&6
+ cat >>confdefs.h <<\_ACEOF
+#define USE_IN_GIF 1
+_ACEOF
+
+ cat >>confdefs.h <<\_ACEOF
+#define USE_OUT_GIF 1
+_ACEOF
+
+ { echo "$as_me:$LINENO: WARNING: GIF is a resistered trademark of Compuserve; ask permission from them to use it!" >&5
+echo "$as_me: WARNING: GIF is a resistered trademark of Compuserve; ask permission from them to use it!" >&2;}
+else
+ echo "$as_me:$LINENO: result: no" >&5
+echo "${ECHO_T}no" >&6
+fi
+
+ac_ext=cc
+ac_cpp='$CXXCPP $CPPFLAGS'
+ac_compile='$CXX -c $CXXFLAGS $CPPFLAGS conftest.$ac_ext >&5'
+ac_link='$CXX -o conftest$ac_exeext $CXXFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_cxx_compiler_gnu
+
+CXXFLAGS=" "
+CCC="$CCC g++"
+ac_ext=cc
+ac_cpp='$CXXCPP $CPPFLAGS'
+ac_compile='$CXX -c $CXXFLAGS $CPPFLAGS conftest.$ac_ext >&5'
+ac_link='$CXX -o conftest$ac_exeext $CXXFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_cxx_compiler_gnu
+if test -n "$ac_tool_prefix"; then
+ for ac_prog in $CCC g++ c++ gpp aCC CC cxx cc++ cl FCC KCC RCC xlC_r xlC
+ do
+ # Extract the first word of "$ac_tool_prefix$ac_prog", so it can be a program name with args.
+set dummy $ac_tool_prefix$ac_prog; ac_word=$2
+echo "$as_me:$LINENO: checking for $ac_word" >&5
+echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6
+if test "${ac_cv_prog_CXX+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ if test -n "$CXX"; then
+ ac_cv_prog_CXX="$CXX" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+ IFS=$as_save_IFS
+ test -z "$as_dir" && as_dir=.
+ for ac_exec_ext in '' $ac_executable_extensions; do
+ if $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+ ac_cv_prog_CXX="$ac_tool_prefix$ac_prog"
+ echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5
+ break 2
+ fi
+done
+done
+
+fi
+fi
+CXX=$ac_cv_prog_CXX
+if test -n "$CXX"; then
+ echo "$as_me:$LINENO: result: $CXX" >&5
+echo "${ECHO_T}$CXX" >&6
+else
+ echo "$as_me:$LINENO: result: no" >&5
+echo "${ECHO_T}no" >&6
+fi
+
+ test -n "$CXX" && break
+ done
+fi
+if test -z "$CXX"; then
+ ac_ct_CXX=$CXX
+ for ac_prog in $CCC g++ c++ gpp aCC CC cxx cc++ cl FCC KCC RCC xlC_r xlC
+do
+ # Extract the first word of "$ac_prog", so it can be a program name with args.
+set dummy $ac_prog; ac_word=$2
+echo "$as_me:$LINENO: checking for $ac_word" >&5
+echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6
+if test "${ac_cv_prog_ac_ct_CXX+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ if test -n "$ac_ct_CXX"; then
+ ac_cv_prog_ac_ct_CXX="$ac_ct_CXX" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+ IFS=$as_save_IFS
+ test -z "$as_dir" && as_dir=.
+ for ac_exec_ext in '' $ac_executable_extensions; do
+ if $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+ ac_cv_prog_ac_ct_CXX="$ac_prog"
+ echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5
+ break 2
+ fi
+done
+done
+
+fi
+fi
+ac_ct_CXX=$ac_cv_prog_ac_ct_CXX
+if test -n "$ac_ct_CXX"; then
+ echo "$as_me:$LINENO: result: $ac_ct_CXX" >&5
+echo "${ECHO_T}$ac_ct_CXX" >&6
+else
+ echo "$as_me:$LINENO: result: no" >&5
+echo "${ECHO_T}no" >&6
+fi
+
+ test -n "$ac_ct_CXX" && break
+done
+test -n "$ac_ct_CXX" || ac_ct_CXX="g++"
+
+ CXX=$ac_ct_CXX
+fi
+
+
+# Provide some information about the compiler.
+echo "$as_me:$LINENO:" \
+ "checking for C++ compiler version" >&5
+ac_compiler=`set X $ac_compile; echo $2`
+{ (eval echo "$as_me:$LINENO: \"$ac_compiler --version </dev/null >&5\"") >&5
+ (eval $ac_compiler --version </dev/null >&5) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }
+{ (eval echo "$as_me:$LINENO: \"$ac_compiler -v </dev/null >&5\"") >&5
+ (eval $ac_compiler -v </dev/null >&5) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }
+{ (eval echo "$as_me:$LINENO: \"$ac_compiler -V </dev/null >&5\"") >&5
+ (eval $ac_compiler -V </dev/null >&5) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }
+
+cat >conftest.$ac_ext <<_ACEOF
+#line $LINENO "configure"
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+
+int
+main ()
+{
+
+ ;
+ return 0;
+}
+_ACEOF
+ac_clean_files_save=$ac_clean_files
+ac_clean_files="$ac_clean_files a.out a.exe b.out"
+# Try to create an executable without -o first, disregard a.out.
+# It will help us diagnose broken compilers, and finding out an intuition
+# of exeext.
+echo "$as_me:$LINENO: checking for C++ compiler default output" >&5
+echo $ECHO_N "checking for C++ compiler default output... $ECHO_C" >&6
+ac_link_default=`echo "$ac_link" | sed 's/ -o *conftest[^ ]*//'`
+if { (eval echo "$as_me:$LINENO: \"$ac_link_default\"") >&5
+ (eval $ac_link_default) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; then
+ # Find the output, starting from the most likely. This scheme is
+# not robust to junk in `.', hence go to wildcards (a.*) only as a last
+# resort.
+
+# Be careful to initialize this variable, since it used to be cached.
+# Otherwise an old cache value of `no' led to `EXEEXT = no' in a Makefile.
+ac_cv_exeext=
+# b.out is created by i960 compilers.
+for ac_file in a_out.exe a.exe conftest.exe a.out conftest a.* conftest.* b.out
+do
+ test -f "$ac_file" || continue
+ case $ac_file in
+ *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.o | *.obj )
+ ;;
+ conftest.$ac_ext )
+ # This is the source file.
+ ;;
+ [ab].out )
+ # We found the default executable, but exeext='' is most
+ # certainly right.
+ break;;
+ *.* )
+ ac_cv_exeext=`expr "$ac_file" : '[^.]*\(\..*\)'`
+ # FIXME: I believe we export ac_cv_exeext for Libtool,
+ # but it would be cool to find out if it's true. Does anybody
+ # maintain Libtool? --akim.
+ export ac_cv_exeext
+ break;;
+ * )
+ break;;
+ esac
+done
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+{ { echo "$as_me:$LINENO: error: C++ compiler cannot create executables
+See \`config.log' for more details." >&5
+echo "$as_me: error: C++ compiler cannot create executables
+See \`config.log' for more details." >&2;}
+ { (exit 77); exit 77; }; }
+fi
+
+ac_exeext=$ac_cv_exeext
+echo "$as_me:$LINENO: result: $ac_file" >&5
+echo "${ECHO_T}$ac_file" >&6
+
+# Check the compiler produces executables we can run. If not, either
+# the compiler is broken, or we cross compile.
+echo "$as_me:$LINENO: checking whether the C++ compiler works" >&5
+echo $ECHO_N "checking whether the C++ compiler works... $ECHO_C" >&6
+# FIXME: These cross compiler hacks should be removed for Autoconf 3.0
+# If not cross compiling, check that we can run a simple program.
+if test "$cross_compiling" != yes; then
+ if { ac_try='./$ac_file'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; }; then
+ cross_compiling=no
+ else
+ if test "$cross_compiling" = maybe; then
+ cross_compiling=yes
+ else
+ { { echo "$as_me:$LINENO: error: cannot run C++ compiled programs.
+If you meant to cross compile, use \`--host'.
+See \`config.log' for more details." >&5
+echo "$as_me: error: cannot run C++ compiled programs.
+If you meant to cross compile, use \`--host'.
+See \`config.log' for more details." >&2;}
+ { (exit 1); exit 1; }; }
+ fi
+ fi
+fi
+echo "$as_me:$LINENO: result: yes" >&5
+echo "${ECHO_T}yes" >&6
+
+rm -f a.out a.exe conftest$ac_cv_exeext b.out
+ac_clean_files=$ac_clean_files_save
+# Check the compiler produces executables we can run. If not, either
+# the compiler is broken, or we cross compile.
+echo "$as_me:$LINENO: checking whether we are cross compiling" >&5
+echo $ECHO_N "checking whether we are cross compiling... $ECHO_C" >&6
+echo "$as_me:$LINENO: result: $cross_compiling" >&5
+echo "${ECHO_T}$cross_compiling" >&6
+
+echo "$as_me:$LINENO: checking for suffix of executables" >&5
+echo $ECHO_N "checking for suffix of executables... $ECHO_C" >&6
+if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5
+ (eval $ac_link) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; then
+ # If both `conftest.exe' and `conftest' are `present' (well, observable)
+# catch `conftest.exe'. For instance with Cygwin, `ls conftest' will
+# work properly (i.e., refer to `conftest.exe'), while it won't with
+# `rm'.
+for ac_file in conftest.exe conftest conftest.*; do
+ test -f "$ac_file" || continue
+ case $ac_file in
+ *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.o | *.obj ) ;;
+ *.* ) ac_cv_exeext=`expr "$ac_file" : '[^.]*\(\..*\)'`
+ export ac_cv_exeext
+ break;;
+ * ) break;;
+ esac
+done
+else
+ { { echo "$as_me:$LINENO: error: cannot compute suffix of executables: cannot compile and link
+See \`config.log' for more details." >&5
+echo "$as_me: error: cannot compute suffix of executables: cannot compile and link
+See \`config.log' for more details." >&2;}
+ { (exit 1); exit 1; }; }
+fi
+
+rm -f conftest$ac_cv_exeext
+echo "$as_me:$LINENO: result: $ac_cv_exeext" >&5
+echo "${ECHO_T}$ac_cv_exeext" >&6
+
+rm -f conftest.$ac_ext
+EXEEXT=$ac_cv_exeext
+ac_exeext=$EXEEXT
+echo "$as_me:$LINENO: checking for suffix of object files" >&5
+echo $ECHO_N "checking for suffix of object files... $ECHO_C" >&6
+if test "${ac_cv_objext+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ cat >conftest.$ac_ext <<_ACEOF
+#line $LINENO "configure"
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+
+int
+main ()
+{
+
+ ;
+ return 0;
+}
+_ACEOF
+rm -f conftest.o conftest.obj
+if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
+ (eval $ac_compile) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; then
+ for ac_file in `(ls conftest.o conftest.obj; ls conftest.*) 2>/dev/null`; do
+ case $ac_file in
+ *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg ) ;;
+ *) ac_cv_objext=`expr "$ac_file" : '.*\.\(.*\)'`
+ break;;
+ esac
+done
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+{ { echo "$as_me:$LINENO: error: cannot compute suffix of object files: cannot compile
+See \`config.log' for more details." >&5
+echo "$as_me: error: cannot compute suffix of object files: cannot compile
+See \`config.log' for more details." >&2;}
+ { (exit 1); exit 1; }; }
+fi
+
+rm -f conftest.$ac_cv_objext conftest.$ac_ext
+fi
+echo "$as_me:$LINENO: result: $ac_cv_objext" >&5
+echo "${ECHO_T}$ac_cv_objext" >&6
+OBJEXT=$ac_cv_objext
+ac_objext=$OBJEXT
+echo "$as_me:$LINENO: checking whether we are using the GNU C++ compiler" >&5
+echo $ECHO_N "checking whether we are using the GNU C++ compiler... $ECHO_C" >&6
+if test "${ac_cv_cxx_compiler_gnu+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ cat >conftest.$ac_ext <<_ACEOF
+#line $LINENO "configure"
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+
+int
+main ()
+{
+#ifndef __GNUC__
+ choke me
+#endif
+
+ ;
+ return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext
+if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
+ (eval $ac_compile) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } &&
+ { ac_try='test -s conftest.$ac_objext'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; }; then
+ ac_compiler_gnu=yes
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ac_compiler_gnu=no
+fi
+rm -f conftest.$ac_objext conftest.$ac_ext
+ac_cv_cxx_compiler_gnu=$ac_compiler_gnu
+
+fi
+echo "$as_me:$LINENO: result: $ac_cv_cxx_compiler_gnu" >&5
+echo "${ECHO_T}$ac_cv_cxx_compiler_gnu" >&6
+GXX=`test $ac_compiler_gnu = yes && echo yes`
+ac_test_CXXFLAGS=${CXXFLAGS+set}
+ac_save_CXXFLAGS=$CXXFLAGS
+CXXFLAGS="-g"
+echo "$as_me:$LINENO: checking whether $CXX accepts -g" >&5
+echo $ECHO_N "checking whether $CXX accepts -g... $ECHO_C" >&6
+if test "${ac_cv_prog_cxx_g+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ cat >conftest.$ac_ext <<_ACEOF
+#line $LINENO "configure"
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+
+int
+main ()
+{
+
+ ;
+ return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext
+if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
+ (eval $ac_compile) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } &&
+ { ac_try='test -s conftest.$ac_objext'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; }; then
+ ac_cv_prog_cxx_g=yes
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ac_cv_prog_cxx_g=no
+fi
+rm -f conftest.$ac_objext conftest.$ac_ext
+fi
+echo "$as_me:$LINENO: result: $ac_cv_prog_cxx_g" >&5
+echo "${ECHO_T}$ac_cv_prog_cxx_g" >&6
+if test "$ac_test_CXXFLAGS" = set; then
+ CXXFLAGS=$ac_save_CXXFLAGS
+elif test $ac_cv_prog_cxx_g = yes; then
+ if test "$GXX" = yes; then
+ CXXFLAGS="-g -O2"
+ else
+ CXXFLAGS="-g"
+ fi
+else
+ if test "$GXX" = yes; then
+ CXXFLAGS="-O2"
+ else
+ CXXFLAGS=
+ fi
+fi
+:
+ac_ext=cc
+ac_cpp='$CXXCPP $CPPFLAGS'
+ac_compile='$CXX -c $CXXFLAGS $CPPFLAGS conftest.$ac_ext >&5'
+ac_link='$CXX -o conftest$ac_exeext $CXXFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_cxx_compiler_gnu
+
+
+
+if test x"$ac_cv_prog_cxx_g" = xyes; then GFLAG=-g; else GFLAG=""; fi
+
+
+echo "$as_me:$LINENO: checking whether ${CXX-g++} accepts -fsigned-char" >&5
+echo $ECHO_N "checking whether ${CXX-g++} accepts -fsigned-char... $ECHO_C" >&6
+if test "${ac_cv_prog_cxx_fs+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ echo 'void f(void);void f(void){}' > conftest.cc
+if test -z "`${CXX-g++} -fsigned-char -c conftest.cc 2>&1`"
+then ac_cv_prog_cxx_fs=yes;
+else ac_cv_prog_cxx_fs=no; fi
+rm -f conftest*
+
+fi
+echo "$as_me:$LINENO: result: $ac_cv_prog_cxx_fs" >&5
+echo "${ECHO_T}$ac_cv_prog_cxx_fs" >&6
+if test $ac_cv_prog_cxx_fs = yes; then CXXFLAGS="$CXXFLAGS -fsigned-char"; fi
+
+
+echo "$as_me:$LINENO: checking whether ${CXX-g++} accepts -fno-rtti -fno-exceptions" >&5
+echo $ECHO_N "checking whether ${CXX-g++} accepts -fno-rtti -fno-exceptions... $ECHO_C" >&6
+if test "${ac_cv_prog_cxx_nrne+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ echo 'void f(void);void f(void){}' > conftest.cc
+if test -z "`${CXX-g++} -fno-rtti -fno-exceptions -c conftest.cc 2>&1`"
+then ac_cv_prog_cxx_nrne=yes;
+else ac_cv_prog_cxx_nrne=no; fi
+rm -f conftest*
+
+fi
+echo "$as_me:$LINENO: result: $ac_cv_prog_cxx_nrne" >&5
+echo "${ECHO_T}$ac_cv_prog_cxx_nrne" >&6
+if test $ac_cv_prog_cxx_nrne = yes; then CXXFLAGS="$CXXFLAGS -fno-rtti -fno-exceptions"; fi
+
+
+
+echo "$as_me:$LINENO: checking whether ${CXX-g++} accepts -ansi -pedantic -Wall -W" >&5
+echo $ECHO_N "checking whether ${CXX-g++} accepts -ansi -pedantic -Wall -W... $ECHO_C" >&6
+if test "${ac_cv_prog_cxx_apwaw+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ echo 'void f(void);void f(void){}' > conftest.cc
+if test -z "`${CXX-g++} -ansi -pedantic -Wall -W -c conftest.cc 2>&1`"
+then ac_cv_prog_cxx_apwaw=yes;
+else ac_cv_prog_cxx_apwaw=no; fi
+rm -f conftest*
+
+fi
+echo "$as_me:$LINENO: result: $ac_cv_prog_cxx_apwaw" >&5
+echo "${ECHO_T}$ac_cv_prog_cxx_apwaw" >&6
+if test $ac_cv_prog_cxx_apwaw = yes; then CXXFLAGSB="$CXXFLAGSB -ansi -pedantic -Wall -W"; fi
+
+
+
+echo "$as_me:$LINENO: checking whether ${CXX-g++} accepts -Wextra" >&5
+echo $ECHO_N "checking whether ${CXX-g++} accepts -Wextra... $ECHO_C" >&6
+if test "${ac_cv_prog_cxx_wextra+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ echo 'void f(void);void f(void){}' > conftest.cc
+if test -z "`${CXX-g++} -Wextra -c conftest.cc 2>&1`"
+then ac_cv_prog_cxx_wextra=yes;
+else ac_cv_prog_cxx_wextra=no; fi
+rm -f conftest*
+
+fi
+echo "$as_me:$LINENO: result: $ac_cv_prog_cxx_wextra" >&5
+echo "${ECHO_T}$ac_cv_prog_cxx_wextra" >&6
+if test $ac_cv_prog_cxx_wextra = yes; then CXXFLAGSB="$CXXFLAGSB -Wextra"; fi
+
+
+
+echo "$as_me:$LINENO: checking whether ${CXX-g++} accepts -felide-constructors -Wstrict-prototypes -Wpointer-arith -Wcast-align -Winline -Wcast-qual -Wmissing-prototypes" >&5
+echo $ECHO_N "checking whether ${CXX-g++} accepts -felide-constructors -Wstrict-prototypes -Wpointer-arith -Wcast-align -Winline -Wcast-qual -Wmissing-prototypes... $ECHO_C" >&6
+if test "${ac_cv_prog_cxx_ptscxxopts+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ echo 'void f(void);void f(void){}' > conftest.cc
+if test -z "`${CXX-g++} -felide-constructors -Wstrict-prototypes -Wpointer-arith -Wcast-align -Winline -Wcast-qual -Wmissing-prototypes -c conftest.cc 2>&1`"
+then ac_cv_prog_cxx_ptscxxopts=yes;
+else ac_cv_prog_cxx_ptscxxopts=no; fi
+rm -f conftest*
+
+fi
+echo "$as_me:$LINENO: result: $ac_cv_prog_cxx_ptscxxopts" >&5
+echo "${ECHO_T}$ac_cv_prog_cxx_ptscxxopts" >&6
+if test $ac_cv_prog_cxx_ptscxxopts = yes; then CXXFLAGSB="$CXXFLAGSB -felide-constructors -Wstrict-prototypes -Wpointer-arith -Wcast-align -Winline -Wcast-qual -Wmissing-prototypes"; fi
+
+
+
+ XTRA="-W -Wall -Wnested-externs -Wbad-function-cast -Wmissing-declarations"
+ CC_bak="$CC" CC="${CC:-cc} -Werror -W -Wall -Wnested-externs -Wbad-function-cast -Wmissing-declarations"
+ CXX_bak="$CXX" CXX="${CXX:-c++} -Werror -W -Wall -Wnested-externs -Wbad-function-cast -Wmissing-declarations"
+ echo "$as_me:$LINENO: checking for ignored -W -Wall -Wnested-externs -Wbad-function-cast -Wmissing-declarations" >&5
+echo $ECHO_N "checking for ignored -W -Wall -Wnested-externs -Wbad-function-cast -Wmissing-declarations... $ECHO_C" >&6
+if test "${ac_cv_pts_ignoring_nebfcmd+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+
+ cat >conftest.$ac_ext <<_ACEOF
+#line $LINENO "configure"
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+
+int
+main ()
+{
+
+ ;
+ return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext
+if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
+ (eval $ac_compile) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } &&
+ { ac_try='test -s conftest.$ac_objext'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; }; then
+ ac_cv_pts_ignoring_nebfcmd=no
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ac_cv_pts_ignoring_nebfcmd=yes
+fi
+rm -f conftest.$ac_objext conftest.$ac_ext
+fi
+echo "$as_me:$LINENO: result: $ac_cv_pts_ignoring_nebfcmd" >&5
+echo "${ECHO_T}$ac_cv_pts_ignoring_nebfcmd" >&6
+ CC="$CC_bak"
+ CXX="$CXX_bak"
+
+if test x"$ac_cv_pts_ignoring_nebfcmd" = xyes
+then ac_cv_prog_cxx_nebfcmd=no
+fi
+
+
+echo "$as_me:$LINENO: checking whether ${CXX-g++} accepts -Wnested-externs -Wbad-function-cast -Wmissing-declarations" >&5
+echo $ECHO_N "checking whether ${CXX-g++} accepts -Wnested-externs -Wbad-function-cast -Wmissing-declarations... $ECHO_C" >&6
+if test "${ac_cv_prog_cxx_nebfcmd+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ echo 'void f(void);void f(void){}' > conftest.cc
+if test -z "`${CXX-g++} -Wnested-externs -Wbad-function-cast -Wmissing-declarations -c conftest.cc 2>&1`"
+then ac_cv_prog_cxx_nebfcmd=yes;
+else ac_cv_prog_cxx_nebfcmd=no; fi
+rm -f conftest*
+
+fi
+echo "$as_me:$LINENO: result: $ac_cv_prog_cxx_nebfcmd" >&5
+echo "${ECHO_T}$ac_cv_prog_cxx_nebfcmd" >&6
+if test $ac_cv_prog_cxx_nebfcmd = yes; then CXXFLAGSB="$CXXFLAGSB -Wnested-externs -Wbad-function-cast -Wmissing-declarations"; fi
+
+
+
+
+ echo "$as_me:$LINENO: checking whether gcc can link C++ code" >&5
+echo $ECHO_N "checking whether gcc can link C++ code... $ECHO_C" >&6
+if test "${ac_cv_pts_gcc_links_cxx+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+
+ CXX_saved="$CXX"
+ LIBS_saved="$LIBS"
+ CXX_new="$CXX"
+ ac_ext_saved="$ac_ext"
+ cat > conftest.$ac_ext <<EOF
+#line 1964 "configure"
+#include "confdefs.h"
+
+ #include <stdio.h>
+ struct B { virtual int f()=0; int x() { return f(); } };
+ struct C1: public B { virtual int f() {return 1;}};
+ struct C2: public B { virtual int f() {return 2;}};
+ C1 global; /* global.x() will cause segfault in i386-uclibc-gcc */
+
+int main() {
+
+ /* vvv (B*) cast added for gcc-3.1 */
+ B *p=(ferror(stderr))?(B*)new C1():(B*)new C2(); /* Imp: argc... */
+ /* if (p==0) throw long(42); */ /* doesn't work with -fno-rtti */
+ int ok2=p->x()==2;
+ delete p;
+ return !(ok2 && global.x()==1);
+
+; return 0; }
+EOF
+if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
+ (eval $ac_compile) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; then
+
+
+ case x"$CC" in
+ xgcc-*) CXX="$CC" ;; # gcc-3.2
+ x*-gcc-*) CXX="$CC" ;; #
+ x*-gcc) CXX="$CC" ;; # i386-uclibc-gcc
+ *) CXX=gcc ;;
+ esac
+ CXX_new="$CXX"
+ ac_ext="$ac_objext"
+ if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5
+ (eval $ac_link) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } && test -s conftest${ac_exeext} && ./conftest${ac_exeext}
+ then ac_cv_pts_gcc_links_cxx=yes
+ else
+ LIBS="$LIBS_saved c_lgcc.cpp"
+ if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5
+ (eval $ac_link) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } && test -s conftest${ac_exeext} && ./conftest${ac_exeext}
+ then ac_cv_pts_gcc_links_cxx=yes-with-help
+ else
+ LIBS="$LIBS_saved c_lgcc3.cpp"
+ if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5
+ (eval $ac_link) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } && test -s conftest${ac_exeext} && ./conftest${ac_exeext}
+ then ac_cv_pts_gcc_links_cxx=yes-with-help3
+ else ac_cv_pts_gcc_links_cxx=no; CXX_new="$CXX_saved"; fi
+ fi
+ fi
+
+else
+ echo "configure: failed program was:" >&5
+ cat conftest.$ac_ext >&5
+
+ ac_cv_pts_gcc_links_cxx=compilation-failed
+fi
+rm -f conftest*
+ CXX="$CXX_saved"
+ LIBS="$LIBS_saved"
+ ac_ext="$ac_ext_saved"
+
+fi
+echo "$as_me:$LINENO: result: $ac_cv_pts_gcc_links_cxx" >&5
+echo "${ECHO_T}$ac_cv_pts_gcc_links_cxx" >&6
+
+ case x"$ac_cv_pts_gcc_links_cxx" in
+ xyes-with-help) LDXX="$CXX_new"; cat >>confdefs.h <<\_ACEOF
+#define HAVE_PTS_C_LGCC_CPP_REQUIRED 1
+_ACEOF
+ ;;
+ xyes-with-help3) LDXX="$CXX_new"; cat >>confdefs.h <<\_ACEOF
+#define HAVE_PTS_C_LGCC3_CPP_REQUIRED 1
+_ACEOF
+ ;;
+ xyes) LDXX="$CXX_new" ;;
+ xno) LDXX="$CXX_new" ;;
+ *) { { echo "$as_me:$LINENO: error: Compilation failed, aborting." >&5
+echo "$as_me: error: Compilation failed, aborting." >&2;}
+ { (exit 1); exit 1; }; } ;;
+ esac
+
+
+# Extract the first word of "cjpeg", so it can be a program name with args.
+set dummy cjpeg; ac_word=$2
+echo "$as_me:$LINENO: checking for $ac_word" >&5
+echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6
+if test "${ac_cv_path_pts_cjpeg+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ case "$pts_cjpeg" in
+ /*)
+ ac_cv_path_pts_cjpeg="$pts_cjpeg" # Let the user override the test with a path.
+ ;;
+ ?:/*)
+ ac_cv_path_pts_cjpeg="$pts_cjpeg" # Let the user override the test with a dos path.
+ ;;
+ *)
+ IFS="${IFS= }"; ac_save_ifs="$IFS"; IFS=":"
+ ac_dummy="$PATH"
+ for ac_dir in $ac_dummy; do
+ test -z "$ac_dir" && ac_dir=.
+ if test -x $ac_dir/$ac_word; then
+ ac_cv_path_pts_cjpeg="$ac_dir/$ac_word"
+ break
+ fi
+ done
+ IFS="$ac_save_ifs"
+ ;;
+esac
+fi
+pts_cjpeg="$ac_cv_path_pts_cjpeg"
+if test -n "$pts_cjpeg"; then
+ echo "$as_me:$LINENO: result: $pts_cjpeg" >&5
+echo "${ECHO_T}$pts_cjpeg" >&6
+else
+ echo "$as_me:$LINENO: result: no" >&5
+echo "${ECHO_T}no" >&6
+fi
+
+if test x"$ac_cv_path_pts_cjpeg" = x; then
+ { echo "$as_me:$LINENO: WARNING: cjpeg would provide increased functionality to this program:" >&5
+echo "$as_me: WARNING: cjpeg would provide increased functionality to this program:" >&2;}
+ { echo "$as_me:$LINENO: WARNING: cjpeg is required for /Compression/IJG" >&5
+echo "$as_me: WARNING: cjpeg is required for /Compression/IJG" >&2;}
+fi
+
+# Extract the first word of "djpeg", so it can be a program name with args.
+set dummy djpeg; ac_word=$2
+echo "$as_me:$LINENO: checking for $ac_word" >&5
+echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6
+if test "${ac_cv_path_pts_djpeg+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ case "$pts_djpeg" in
+ /*)
+ ac_cv_path_pts_djpeg="$pts_djpeg" # Let the user override the test with a path.
+ ;;
+ ?:/*)
+ ac_cv_path_pts_djpeg="$pts_djpeg" # Let the user override the test with a dos path.
+ ;;
+ *)
+ IFS="${IFS= }"; ac_save_ifs="$IFS"; IFS=":"
+ ac_dummy="$PATH"
+ for ac_dir in $ac_dummy; do
+ test -z "$ac_dir" && ac_dir=.
+ if test -x $ac_dir/$ac_word; then
+ ac_cv_path_pts_djpeg="$ac_dir/$ac_word"
+ break
+ fi
+ done
+ IFS="$ac_save_ifs"
+ ;;
+esac
+fi
+pts_djpeg="$ac_cv_path_pts_djpeg"
+if test -n "$pts_djpeg"; then
+ echo "$as_me:$LINENO: result: $pts_djpeg" >&5
+echo "${ECHO_T}$pts_djpeg" >&6
+else
+ echo "$as_me:$LINENO: result: no" >&5
+echo "${ECHO_T}no" >&6
+fi
+
+if test x"$ac_cv_path_pts_djpeg" = x; then
+ { echo "$as_me:$LINENO: WARNING: djpeg would provide increased functionality to this program:" >&5
+echo "$as_me: WARNING: djpeg would provide increased functionality to this program:" >&2;}
+ { echo "$as_me:$LINENO: WARNING: djpeg is required for loading JPEG files" >&5
+echo "$as_me: WARNING: djpeg is required for loading JPEG files" >&2;}
+fi
+
+# Extract the first word of "tif22pnm", so it can be a program name with args.
+set dummy tif22pnm; ac_word=$2
+echo "$as_me:$LINENO: checking for $ac_word" >&5
+echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6
+if test "${ac_cv_path_pts_tif22pnm+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ case "$pts_tif22pnm" in
+ /*)
+ ac_cv_path_pts_tif22pnm="$pts_tif22pnm" # Let the user override the test with a path.
+ ;;
+ ?:/*)
+ ac_cv_path_pts_tif22pnm="$pts_tif22pnm" # Let the user override the test with a dos path.
+ ;;
+ *)
+ IFS="${IFS= }"; ac_save_ifs="$IFS"; IFS=":"
+ ac_dummy="$PATH"
+ for ac_dir in $ac_dummy; do
+ test -z "$ac_dir" && ac_dir=.
+ if test -x $ac_dir/$ac_word; then
+ ac_cv_path_pts_tif22pnm="$ac_dir/$ac_word"
+ break
+ fi
+ done
+ IFS="$ac_save_ifs"
+ ;;
+esac
+fi
+pts_tif22pnm="$ac_cv_path_pts_tif22pnm"
+if test -n "$pts_tif22pnm"; then
+ echo "$as_me:$LINENO: result: $pts_tif22pnm" >&5
+echo "${ECHO_T}$pts_tif22pnm" >&6
+else
+ echo "$as_me:$LINENO: result: no" >&5
+echo "${ECHO_T}no" >&6
+fi
+
+if test x"$ac_cv_path_pts_tif22pnm" = x; then
+ { echo "$as_me:$LINENO: WARNING: tif22pnm would provide increased functionality to this program:" >&5
+echo "$as_me: WARNING: tif22pnm would provide increased functionality to this program:" >&2;}
+ { echo "$as_me:$LINENO: WARNING: tif22pnm is required for loading TIFF files" >&5
+echo "$as_me: WARNING: tif22pnm is required for loading TIFF files" >&2;}
+fi
+
+# Extract the first word of "tifftopnm", so it can be a program name with args.
+set dummy tifftopnm; ac_word=$2
+echo "$as_me:$LINENO: checking for $ac_word" >&5
+echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6
+if test "${ac_cv_path_pts_tifftopnm+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ case "$pts_tifftopnm" in
+ /*)
+ ac_cv_path_pts_tifftopnm="$pts_tifftopnm" # Let the user override the test with a path.
+ ;;
+ ?:/*)
+ ac_cv_path_pts_tifftopnm="$pts_tifftopnm" # Let the user override the test with a dos path.
+ ;;
+ *)
+ IFS="${IFS= }"; ac_save_ifs="$IFS"; IFS=":"
+ ac_dummy="$PATH"
+ for ac_dir in $ac_dummy; do
+ test -z "$ac_dir" && ac_dir=.
+ if test -x $ac_dir/$ac_word; then
+ ac_cv_path_pts_tifftopnm="$ac_dir/$ac_word"
+ break
+ fi
+ done
+ IFS="$ac_save_ifs"
+ ;;
+esac
+fi
+pts_tifftopnm="$ac_cv_path_pts_tifftopnm"
+if test -n "$pts_tifftopnm"; then
+ echo "$as_me:$LINENO: result: $pts_tifftopnm" >&5
+echo "${ECHO_T}$pts_tifftopnm" >&6
+else
+ echo "$as_me:$LINENO: result: no" >&5
+echo "${ECHO_T}no" >&6
+fi
+
+if test x"$ac_cv_path_pts_tifftopnm" = x; then
+ { echo "$as_me:$LINENO: WARNING: tifftopnm would provide increased functionality to this program:" >&5
+echo "$as_me: WARNING: tifftopnm would provide increased functionality to this program:" >&2;}
+ { echo "$as_me:$LINENO: WARNING: tifftopnm might become useful for loading TIFF files" >&5
+echo "$as_me: WARNING: tifftopnm might become useful for loading TIFF files" >&2;}
+fi
+
+# Extract the first word of "pngtopnm", so it can be a program name with args.
+set dummy pngtopnm; ac_word=$2
+echo "$as_me:$LINENO: checking for $ac_word" >&5
+echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6
+if test "${ac_cv_path_pts_pngtopnm+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ case "$pts_pngtopnm" in
+ /*)
+ ac_cv_path_pts_pngtopnm="$pts_pngtopnm" # Let the user override the test with a path.
+ ;;
+ ?:/*)
+ ac_cv_path_pts_pngtopnm="$pts_pngtopnm" # Let the user override the test with a dos path.
+ ;;
+ *)
+ IFS="${IFS= }"; ac_save_ifs="$IFS"; IFS=":"
+ ac_dummy="$PATH"
+ for ac_dir in $ac_dummy; do
+ test -z "$ac_dir" && ac_dir=.
+ if test -x $ac_dir/$ac_word; then
+ ac_cv_path_pts_pngtopnm="$ac_dir/$ac_word"
+ break
+ fi
+ done
+ IFS="$ac_save_ifs"
+ ;;
+esac
+fi
+pts_pngtopnm="$ac_cv_path_pts_pngtopnm"
+if test -n "$pts_pngtopnm"; then
+ echo "$as_me:$LINENO: result: $pts_pngtopnm" >&5
+echo "${ECHO_T}$pts_pngtopnm" >&6
+else
+ echo "$as_me:$LINENO: result: no" >&5
+echo "${ECHO_T}no" >&6
+fi
+
+if test x"$ac_cv_path_pts_pngtopnm" = x; then
+ { echo "$as_me:$LINENO: WARNING: pngtopnm would provide increased functionality to this program:" >&5
+echo "$as_me: WARNING: pngtopnm would provide increased functionality to this program:" >&2;}
+ { echo "$as_me:$LINENO: WARNING: pngtopnm might become useful for loading PNG files" >&5
+echo "$as_me: WARNING: pngtopnm might become useful for loading PNG files" >&2;}
+fi
+
+# Extract the first word of "gs", so it can be a program name with args.
+set dummy gs; ac_word=$2
+echo "$as_me:$LINENO: checking for $ac_word" >&5
+echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6
+if test "${ac_cv_path_pts_gs+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ case "$pts_gs" in
+ /*)
+ ac_cv_path_pts_gs="$pts_gs" # Let the user override the test with a path.
+ ;;
+ ?:/*)
+ ac_cv_path_pts_gs="$pts_gs" # Let the user override the test with a dos path.
+ ;;
+ *)
+ IFS="${IFS= }"; ac_save_ifs="$IFS"; IFS=":"
+ ac_dummy="$PATH"
+ for ac_dir in $ac_dummy; do
+ test -z "$ac_dir" && ac_dir=.
+ if test -x $ac_dir/$ac_word; then
+ ac_cv_path_pts_gs="$ac_dir/$ac_word"
+ break
+ fi
+ done
+ IFS="$ac_save_ifs"
+ ;;
+esac
+fi
+pts_gs="$ac_cv_path_pts_gs"
+if test -n "$pts_gs"; then
+ echo "$as_me:$LINENO: result: $pts_gs" >&5
+echo "${ECHO_T}$pts_gs" >&6
+else
+ echo "$as_me:$LINENO: result: no" >&5
+echo "${ECHO_T}no" >&6
+fi
+
+if test x"$ac_cv_path_pts_gs" = x; then
+ { echo "$as_me:$LINENO: WARNING: gs would provide increased functionality to this program:" >&5
+echo "$as_me: WARNING: gs would provide increased functionality to this program:" >&2;}
+ { echo "$as_me:$LINENO: WARNING: gs is recommended for viewing PS files, and might become recommended for /Compression/ZIP" >&5
+echo "$as_me: WARNING: gs is recommended for viewing PS files, and might become recommended for /Compression/ZIP" >&2;}
+fi
+
+# Extract the first word of "lzw_codec", so it can be a program name with args.
+set dummy lzw_codec; ac_word=$2
+echo "$as_me:$LINENO: checking for $ac_word" >&5
+echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6
+if test "${ac_cv_path_pts_lzw_codec+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ case "$pts_lzw_codec" in
+ /*)
+ ac_cv_path_pts_lzw_codec="$pts_lzw_codec" # Let the user override the test with a path.
+ ;;
+ ?:/*)
+ ac_cv_path_pts_lzw_codec="$pts_lzw_codec" # Let the user override the test with a dos path.
+ ;;
+ *)
+ IFS="${IFS= }"; ac_save_ifs="$IFS"; IFS=":"
+ ac_dummy="$PATH"
+ for ac_dir in $ac_dummy; do
+ test -z "$ac_dir" && ac_dir=.
+ if test -x $ac_dir/$ac_word; then
+ ac_cv_path_pts_lzw_codec="$ac_dir/$ac_word"
+ break
+ fi
+ done
+ IFS="$ac_save_ifs"
+ ;;
+esac
+fi
+pts_lzw_codec="$ac_cv_path_pts_lzw_codec"
+if test -n "$pts_lzw_codec"; then
+ echo "$as_me:$LINENO: result: $pts_lzw_codec" >&5
+echo "${ECHO_T}$pts_lzw_codec" >&6
+else
+ echo "$as_me:$LINENO: result: no" >&5
+echo "${ECHO_T}no" >&6
+fi
+
+if test x"$ac_cv_path_pts_lzw_codec" = x; then
+ { echo "$as_me:$LINENO: WARNING: lzw_codec would provide increased functionality to this program:" >&5
+echo "$as_me: WARNING: lzw_codec would provide increased functionality to this program:" >&2;}
+ { echo "$as_me:$LINENO: WARNING: lzw_codec might become recommended for /Compression/LZW" >&5
+echo "$as_me: WARNING: lzw_codec might become recommended for /Compression/LZW" >&2;}
+fi
+
+# Extract the first word of "gzip", so it can be a program name with args.
+set dummy gzip; ac_word=$2
+echo "$as_me:$LINENO: checking for $ac_word" >&5
+echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6
+if test "${ac_cv_path_pts_gzip+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ case "$pts_gzip" in
+ /*)
+ ac_cv_path_pts_gzip="$pts_gzip" # Let the user override the test with a path.
+ ;;
+ ?:/*)
+ ac_cv_path_pts_gzip="$pts_gzip" # Let the user override the test with a dos path.
+ ;;
+ *)
+ IFS="${IFS= }"; ac_save_ifs="$IFS"; IFS=":"
+ ac_dummy="$PATH"
+ for ac_dir in $ac_dummy; do
+ test -z "$ac_dir" && ac_dir=.
+ if test -x $ac_dir/$ac_word; then
+ ac_cv_path_pts_gzip="$ac_dir/$ac_word"
+ break
+ fi
+ done
+ IFS="$ac_save_ifs"
+ ;;
+esac
+fi
+pts_gzip="$ac_cv_path_pts_gzip"
+if test -n "$pts_gzip"; then
+ echo "$as_me:$LINENO: result: $pts_gzip" >&5
+echo "${ECHO_T}$pts_gzip" >&6
+else
+ echo "$as_me:$LINENO: result: no" >&5
+echo "${ECHO_T}no" >&6
+fi
+
+if test x"$ac_cv_path_pts_gzip" = x; then
+ { echo "$as_me:$LINENO: WARNING: gzip would provide increased functionality to this program:" >&5
+echo "$as_me: WARNING: gzip would provide increased functionality to this program:" >&2;}
+ { echo "$as_me:$LINENO: WARNING: gzip might become useful for /Compression/ZIP" >&5
+echo "$as_me: WARNING: gzip might become useful for /Compression/ZIP" >&2;}
+fi
+
+# Extract the first word of "zip", so it can be a program name with args.
+set dummy zip; ac_word=$2
+echo "$as_me:$LINENO: checking for $ac_word" >&5
+echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6
+if test "${ac_cv_path_pts_zip+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ case "$pts_zip" in
+ /*)
+ ac_cv_path_pts_zip="$pts_zip" # Let the user override the test with a path.
+ ;;
+ ?:/*)
+ ac_cv_path_pts_zip="$pts_zip" # Let the user override the test with a dos path.
+ ;;
+ *)
+ IFS="${IFS= }"; ac_save_ifs="$IFS"; IFS=":"
+ ac_dummy="$PATH"
+ for ac_dir in $ac_dummy; do
+ test -z "$ac_dir" && ac_dir=.
+ if test -x $ac_dir/$ac_word; then
+ ac_cv_path_pts_zip="$ac_dir/$ac_word"
+ break
+ fi
+ done
+ IFS="$ac_save_ifs"
+ ;;
+esac
+fi
+pts_zip="$ac_cv_path_pts_zip"
+if test -n "$pts_zip"; then
+ echo "$as_me:$LINENO: result: $pts_zip" >&5
+echo "${ECHO_T}$pts_zip" >&6
+else
+ echo "$as_me:$LINENO: result: no" >&5
+echo "${ECHO_T}no" >&6
+fi
+
+if test x"$ac_cv_path_pts_zip" = x; then
+ { echo "$as_me:$LINENO: WARNING: zip would provide increased functionality to this program:" >&5
+echo "$as_me: WARNING: zip would provide increased functionality to this program:" >&2;}
+ { echo "$as_me:$LINENO: WARNING: zip might become useful for /Compression/ZIP" >&5
+echo "$as_me: WARNING: zip might become useful for /Compression/ZIP" >&2;}
+fi
+
+# Extract the first word of "bash", so it can be a program name with args.
+set dummy bash; ac_word=$2
+echo "$as_me:$LINENO: checking for $ac_word" >&5
+echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6
+if test "${ac_cv_path_pts_bash+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ case "$pts_bash" in
+ /*)
+ ac_cv_path_pts_bash="$pts_bash" # Let the user override the test with a path.
+ ;;
+ ?:/*)
+ ac_cv_path_pts_bash="$pts_bash" # Let the user override the test with a dos path.
+ ;;
+ *)
+ IFS="${IFS= }"; ac_save_ifs="$IFS"; IFS=":"
+ ac_dummy="$PATH"
+ for ac_dir in $ac_dummy; do
+ test -z "$ac_dir" && ac_dir=.
+ if test -x $ac_dir/$ac_word; then
+ ac_cv_path_pts_bash="$ac_dir/$ac_word"
+ break
+ fi
+ done
+ IFS="$ac_save_ifs"
+ ;;
+esac
+fi
+pts_bash="$ac_cv_path_pts_bash"
+if test -n "$pts_bash"; then
+ echo "$as_me:$LINENO: result: $pts_bash" >&5
+echo "${ECHO_T}$pts_bash" >&6
+else
+ echo "$as_me:$LINENO: result: no" >&5
+echo "${ECHO_T}no" >&6
+fi
+
+if test x"$ac_cv_path_pts_bash" = x; then
+ { echo "$as_me:$LINENO: WARNING: bash is required:" >&5
+echo "$as_me: WARNING: bash is required:" >&2;}
+ { { echo "$as_me:$LINENO: error: bash is required for compiling this program" >&5
+echo "$as_me: error: bash is required for compiling this program" >&2;}
+ { (exit 1); exit 1; }; }
+fi
+
+# Extract the first word of "make", so it can be a program name with args.
+set dummy make; ac_word=$2
+echo "$as_me:$LINENO: checking for $ac_word" >&5
+echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6
+if test "${ac_cv_path_pts_make+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ case "$pts_make" in
+ /*)
+ ac_cv_path_pts_make="$pts_make" # Let the user override the test with a path.
+ ;;
+ ?:/*)
+ ac_cv_path_pts_make="$pts_make" # Let the user override the test with a dos path.
+ ;;
+ *)
+ IFS="${IFS= }"; ac_save_ifs="$IFS"; IFS=":"
+ ac_dummy="$PATH"
+ for ac_dir in $ac_dummy; do
+ test -z "$ac_dir" && ac_dir=.
+ if test -x $ac_dir/$ac_word; then
+ ac_cv_path_pts_make="$ac_dir/$ac_word"
+ break
+ fi
+ done
+ IFS="$ac_save_ifs"
+ ;;
+esac
+fi
+pts_make="$ac_cv_path_pts_make"
+if test -n "$pts_make"; then
+ echo "$as_me:$LINENO: result: $pts_make" >&5
+echo "${ECHO_T}$pts_make" >&6
+else
+ echo "$as_me:$LINENO: result: no" >&5
+echo "${ECHO_T}no" >&6
+fi
+
+if test x"$ac_cv_path_pts_make" = x; then
+ { echo "$as_me:$LINENO: WARNING: make is required:" >&5
+echo "$as_me: WARNING: make is required:" >&2;}
+ { { echo "$as_me:$LINENO: error: make is required for compiling this program" >&5
+echo "$as_me: error: make is required for compiling this program" >&2;}
+ { (exit 1); exit 1; }; }
+fi
+
+# Extract the first word of "perl", so it can be a program name with args.
+set dummy perl; ac_word=$2
+echo "$as_me:$LINENO: checking for $ac_word" >&5
+echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6
+if test "${ac_cv_path_pts_perl+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ case "$pts_perl" in
+ /*)
+ ac_cv_path_pts_perl="$pts_perl" # Let the user override the test with a path.
+ ;;
+ ?:/*)
+ ac_cv_path_pts_perl="$pts_perl" # Let the user override the test with a dos path.
+ ;;
+ *)
+ IFS="${IFS= }"; ac_save_ifs="$IFS"; IFS=":"
+ ac_dummy="$PATH"
+ for ac_dir in $ac_dummy; do
+ test -z "$ac_dir" && ac_dir=.
+ if test -x $ac_dir/$ac_word; then
+ ac_cv_path_pts_perl="$ac_dir/$ac_word"
+ break
+ fi
+ done
+ IFS="$ac_save_ifs"
+ ;;
+esac
+fi
+pts_perl="$ac_cv_path_pts_perl"
+if test -n "$pts_perl"; then
+ echo "$as_me:$LINENO: result: $pts_perl" >&5
+echo "${ECHO_T}$pts_perl" >&6
+else
+ echo "$as_me:$LINENO: result: no" >&5
+echo "${ECHO_T}no" >&6
+fi
+
+if test x"$ac_cv_path_pts_perl" = x; then
+ { echo "$as_me:$LINENO: WARNING: perl is required:" >&5
+echo "$as_me: WARNING: perl is required:" >&2;}
+ { { echo "$as_me:$LINENO: error: perl is required for compiling this program" >&5
+echo "$as_me: error: perl is required for compiling this program" >&2;}
+ { (exit 1); exit 1; }; }
+fi
+
+
+#AC_CHECK_PROG(ac_pts_cjpeg, cjpeg, yes)
+
+ac_ext=cc
+ac_cpp='$CXXCPP $CPPFLAGS'
+ac_compile='$CXX -c $CXXFLAGS $CPPFLAGS conftest.$ac_ext >&5'
+ac_link='$CXX -o conftest$ac_exeext $CXXFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_cxx_compiler_gnu
+echo "$as_me:$LINENO: checking how to run the C++ preprocessor" >&5
+echo $ECHO_N "checking how to run the C++ preprocessor... $ECHO_C" >&6
+if test -z "$CXXCPP"; then
+ if test "${ac_cv_prog_CXXCPP+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ # Double quotes because CXXCPP needs to be expanded
+ for CXXCPP in "$CXX -E" "/lib/cpp"
+ do
+ ac_preproc_ok=false
+for ac_cxx_preproc_warn_flag in '' yes
+do
+ # Use a header file that comes with gcc, so configuring glibc
+ # with a fresh cross-compiler works.
+ # Prefer <limits.h> to <assert.h> if __STDC__ is defined, since
+ # <limits.h> exists even on freestanding compilers.
+ # On the NeXT, cc -E runs the code through the compiler's parser,
+ # not just through cpp. "Syntax error" is here to catch this case.
+ cat >conftest.$ac_ext <<_ACEOF
+#line $LINENO "configure"
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+#ifdef __STDC__
+# include <limits.h>
+#else
+# include <assert.h>
+#endif
+ Syntax error
+_ACEOF
+if { (eval echo "$as_me:$LINENO: \"$ac_cpp conftest.$ac_ext\"") >&5
+ (eval $ac_cpp conftest.$ac_ext) 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } >/dev/null; then
+ if test -s conftest.err; then
+ ac_cpp_err=$ac_cxx_preproc_warn_flag
+ else
+ ac_cpp_err=
+ fi
+else
+ ac_cpp_err=yes
+fi
+if test -z "$ac_cpp_err"; then
+ :
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ # Broken: fails on valid input.
+continue
+fi
+rm -f conftest.err conftest.$ac_ext
+
+ # OK, works on sane cases. Now check whether non-existent headers
+ # can be detected and how.
+ cat >conftest.$ac_ext <<_ACEOF
+#line $LINENO "configure"
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+#include <ac_nonexistent.h>
+_ACEOF
+if { (eval echo "$as_me:$LINENO: \"$ac_cpp conftest.$ac_ext\"") >&5
+ (eval $ac_cpp conftest.$ac_ext) 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } >/dev/null; then
+ if test -s conftest.err; then
+ ac_cpp_err=$ac_cxx_preproc_warn_flag
+ else
+ ac_cpp_err=
+ fi
+else
+ ac_cpp_err=yes
+fi
+if test -z "$ac_cpp_err"; then
+ # Broken: success on invalid input.
+continue
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ # Passes both tests.
+ac_preproc_ok=:
+break
+fi
+rm -f conftest.err conftest.$ac_ext
+
+done
+# Because of `break', _AC_PREPROC_IFELSE's cleaning code was skipped.
+rm -f conftest.err conftest.$ac_ext
+if $ac_preproc_ok; then
+ break
+fi
+
+ done
+ ac_cv_prog_CXXCPP=$CXXCPP
+
+fi
+ CXXCPP=$ac_cv_prog_CXXCPP
+else
+ ac_cv_prog_CXXCPP=$CXXCPP
+fi
+echo "$as_me:$LINENO: result: $CXXCPP" >&5
+echo "${ECHO_T}$CXXCPP" >&6
+ac_preproc_ok=false
+for ac_cxx_preproc_warn_flag in '' yes
+do
+ # Use a header file that comes with gcc, so configuring glibc
+ # with a fresh cross-compiler works.
+ # Prefer <limits.h> to <assert.h> if __STDC__ is defined, since
+ # <limits.h> exists even on freestanding compilers.
+ # On the NeXT, cc -E runs the code through the compiler's parser,
+ # not just through cpp. "Syntax error" is here to catch this case.
+ cat >conftest.$ac_ext <<_ACEOF
+#line $LINENO "configure"
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+#ifdef __STDC__
+# include <limits.h>
+#else
+# include <assert.h>
+#endif
+ Syntax error
+_ACEOF
+if { (eval echo "$as_me:$LINENO: \"$ac_cpp conftest.$ac_ext\"") >&5
+ (eval $ac_cpp conftest.$ac_ext) 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } >/dev/null; then
+ if test -s conftest.err; then
+ ac_cpp_err=$ac_cxx_preproc_warn_flag
+ else
+ ac_cpp_err=
+ fi
+else
+ ac_cpp_err=yes
+fi
+if test -z "$ac_cpp_err"; then
+ :
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ # Broken: fails on valid input.
+continue
+fi
+rm -f conftest.err conftest.$ac_ext
+
+ # OK, works on sane cases. Now check whether non-existent headers
+ # can be detected and how.
+ cat >conftest.$ac_ext <<_ACEOF
+#line $LINENO "configure"
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+#include <ac_nonexistent.h>
+_ACEOF
+if { (eval echo "$as_me:$LINENO: \"$ac_cpp conftest.$ac_ext\"") >&5
+ (eval $ac_cpp conftest.$ac_ext) 2>conftest.er1
+ ac_status=$?
+ grep -v '^ *+' conftest.er1 >conftest.err
+ rm -f conftest.er1
+ cat conftest.err >&5
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } >/dev/null; then
+ if test -s conftest.err; then
+ ac_cpp_err=$ac_cxx_preproc_warn_flag
+ else
+ ac_cpp_err=
+ fi
+else
+ ac_cpp_err=yes
+fi
+if test -z "$ac_cpp_err"; then
+ # Broken: success on invalid input.
+continue
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ # Passes both tests.
+ac_preproc_ok=:
+break
+fi
+rm -f conftest.err conftest.$ac_ext
+
+done
+# Because of `break', _AC_PREPROC_IFELSE's cleaning code was skipped.
+rm -f conftest.err conftest.$ac_ext
+if $ac_preproc_ok; then
+ :
+else
+ { { echo "$as_me:$LINENO: error: C++ preprocessor \"$CXXCPP\" fails sanity check
+See \`config.log' for more details." >&5
+echo "$as_me: error: C++ preprocessor \"$CXXCPP\" fails sanity check
+See \`config.log' for more details." >&2;}
+ { (exit 1); exit 1; }; }
+fi
+
+ac_ext=cc
+ac_cpp='$CXXCPP $CPPFLAGS'
+ac_compile='$CXX -c $CXXFLAGS $CPPFLAGS conftest.$ac_ext >&5'
+ac_link='$CXX -o conftest$ac_exeext $CXXFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_cxx_compiler_gnu
+
+
+echo "$as_me:$LINENO: checking for egrep" >&5
+echo $ECHO_N "checking for egrep... $ECHO_C" >&6
+if test "${ac_cv_prog_egrep+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ if echo a | (grep -E '(a|b)') >/dev/null 2>&1
+ then ac_cv_prog_egrep='grep -E'
+ else ac_cv_prog_egrep='egrep'
+ fi
+fi
+echo "$as_me:$LINENO: result: $ac_cv_prog_egrep" >&5
+echo "${ECHO_T}$ac_cv_prog_egrep" >&6
+ EGREP=$ac_cv_prog_egrep
+
+
+echo "$as_me:$LINENO: checking for ANSI C header files" >&5
+echo $ECHO_N "checking for ANSI C header files... $ECHO_C" >&6
+if test "${ac_cv_header_stdc+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ cat >conftest.$ac_ext <<_ACEOF
+#line $LINENO "configure"
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+#include <stdlib.h>
+#include <stdarg.h>
+#include <string.h>
+#include <float.h>
+
+int
+main ()
+{
+
+ ;
+ return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext
+if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
+ (eval $ac_compile) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } &&
+ { ac_try='test -s conftest.$ac_objext'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; }; then
+ ac_cv_header_stdc=yes
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ac_cv_header_stdc=no
+fi
+rm -f conftest.$ac_objext conftest.$ac_ext
+
+if test $ac_cv_header_stdc = yes; then
+ # SunOS 4.x string.h does not declare mem*, contrary to ANSI.
+ cat >conftest.$ac_ext <<_ACEOF
+#line $LINENO "configure"
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+#include <string.h>
+
+_ACEOF
+if (eval "$ac_cpp conftest.$ac_ext") 2>&5 |
+ $EGREP "memchr" >/dev/null 2>&1; then
+ :
+else
+ ac_cv_header_stdc=no
+fi
+rm -f conftest*
+
+fi
+
+if test $ac_cv_header_stdc = yes; then
+ # ISC 2.0.2 stdlib.h does not declare free, contrary to ANSI.
+ cat >conftest.$ac_ext <<_ACEOF
+#line $LINENO "configure"
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+#include <stdlib.h>
+
+_ACEOF
+if (eval "$ac_cpp conftest.$ac_ext") 2>&5 |
+ $EGREP "free" >/dev/null 2>&1; then
+ :
+else
+ ac_cv_header_stdc=no
+fi
+rm -f conftest*
+
+fi
+
+if test $ac_cv_header_stdc = yes; then
+ # /bin/cc in Irix-4.0.5 gets non-ANSI ctype macros unless using -ansi.
+ if test "$cross_compiling" = yes; then
+ :
+else
+ cat >conftest.$ac_ext <<_ACEOF
+#line $LINENO "configure"
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+#include <ctype.h>
+#if ((' ' & 0x0FF) == 0x020)
+# define ISLOWER(c) ('a' <= (c) && (c) <= 'z')
+# define TOUPPER(c) (ISLOWER(c) ? 'A' + ((c) - 'a') : (c))
+#else
+# define ISLOWER(c) \
+ (('a' <= (c) && (c) <= 'i') \
+ || ('j' <= (c) && (c) <= 'r') \
+ || ('s' <= (c) && (c) <= 'z'))
+# define TOUPPER(c) (ISLOWER(c) ? ((c) | 0x40) : (c))
+#endif
+
+#define XOR(e, f) (((e) && !(f)) || (!(e) && (f)))
+int
+main ()
+{
+ int i;
+ for (i = 0; i < 256; i++)
+ if (XOR (islower (i), ISLOWER (i))
+ || toupper (i) != TOUPPER (i))
+ exit(2);
+ exit (0);
+}
+_ACEOF
+rm -f conftest$ac_exeext
+if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5
+ (eval $ac_link) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } && { ac_try='./conftest$ac_exeext'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; }; then
+ :
+else
+ echo "$as_me: program exited with status $ac_status" >&5
+echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+( exit $ac_status )
+ac_cv_header_stdc=no
+fi
+rm -f core core.* *.core gmon.out bb.out conftest$ac_exeext conftest.$ac_objext conftest.$ac_ext
+fi
+fi
+fi
+echo "$as_me:$LINENO: result: $ac_cv_header_stdc" >&5
+echo "${ECHO_T}$ac_cv_header_stdc" >&6
+if test $ac_cv_header_stdc = yes; then
+
+cat >>confdefs.h <<\_ACEOF
+#define STDC_HEADERS 1
+_ACEOF
+
+fi
+
+
+ echo "$as_me:$LINENO: checking whether cc supports prototypes" >&5
+echo $ECHO_N "checking whether cc supports prototypes... $ECHO_C" >&6
+if test "${ac_cv_pts_have_prototypes+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+
+ cat >conftest.$ac_ext <<_ACEOF
+#line $LINENO "configure"
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+int foo(int x) { return 0; }
+int
+main ()
+{
+return foo(10);
+ ;
+ return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext
+if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
+ (eval $ac_compile) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } &&
+ { ac_try='test -s conftest.$ac_objext'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; }; then
+ ac_cv_pts_have_prototypes=yes
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ac_cv_pts_have_prototypes=no
+
+fi
+rm -f conftest.$ac_objext conftest.$ac_ext
+
+fi
+echo "$as_me:$LINENO: result: $ac_cv_pts_have_prototypes" >&5
+echo "${ECHO_T}$ac_cv_pts_have_prototypes" >&6
+ if test x"$ac_cv_pts_have_prototypes" = xyes; then
+ cat >>confdefs.h <<\_ACEOF
+#define HAVE_PROTOTYPES 1
+_ACEOF
+
+ fi
+
+
+
+
+ echo "$as_me:$LINENO: checking whether cc compiles standard C" >&5
+echo $ECHO_N "checking whether cc compiles standard C... $ECHO_C" >&6
+if test "${ac_cv_pts_have_stdc+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+
+ cat >conftest.$ac_ext <<_ACEOF
+#line $LINENO "configure"
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+
+#if defined(__STDC__) && __STDC__
+ /* note: the starting spaces are deliberate in the next line */
+ #if 0
+ nope
+ #endif
+#else
+#if defined(__cplusplus) && __cplusplus
+ #if 0
+ nope
+ #endif
+#else
+ nope
+#endif
+#endif
+
+_ACEOF
+if (eval "$ac_cpp conftest.$ac_ext") 2>&5 |
+ $EGREP "nope" >/dev/null 2>&1; then
+ ac_cv_pts_have_stdc=no
+else
+
+ if test x"$ac_cv_pts_have_prototypes" = xyes; then
+ ac_cv_pts_have_stdc=yes
+ else
+ ac_cv_pts_have_stdc=no
+ fi
+
+fi
+rm -f conftest*
+
+
+fi
+echo "$as_me:$LINENO: result: $ac_cv_pts_have_stdc" >&5
+echo "${ECHO_T}$ac_cv_pts_have_stdc" >&6
+ if test x"$ac_cv_pts_have_stdc" = xyes; then
+ cat >>confdefs.h <<\_ACEOF
+#define HAVE_PTS_STDC 1
+_ACEOF
+
+ fi
+
+
+ echo "$as_me:$LINENO: checking for switch(enum) bug" >&5
+echo $ECHO_N "checking for switch(enum) bug... $ECHO_C" >&6
+if test "${ac_cv_pts_have_switch_enum_bug+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+
+ if test "$cross_compiling" = yes; then
+ { { echo "$as_me:$LINENO: error: cross compiling not supported by .._PTS_HAVE_SWITCH_ENUM_BUG" >&5
+echo "$as_me: error: cross compiling not supported by .._PTS_HAVE_SWITCH_ENUM_BUG" >&2;}
+ { (exit 1); exit 1; }; }
+
+else
+ cat >conftest.$ac_ext <<_ACEOF
+#line $LINENO "configure"
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+
+enum what { foo, bar };
+int main
+#ifdef __STDC__
+(int argc, char **argv)
+#else
+(argc, argv) int argc; char **argv;
+#endif
+{
+ switch ((enum what)1) {
+ case foo: return 1;
+ case bar: return 0;
+ }
+ return 1;
+}
+_ACEOF
+rm -f conftest$ac_exeext
+if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5
+ (eval $ac_link) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } && { ac_try='./conftest$ac_exeext'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; }; then
+ ac_cv_pts_have_switch_enum_bug=no
+else
+ echo "$as_me: program exited with status $ac_status" >&5
+echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+( exit $ac_status )
+ac_cv_pts_have_switch_enum_bug=yes
+fi
+rm -f core core.* *.core gmon.out bb.out conftest$ac_exeext conftest.$ac_objext conftest.$ac_ext
+fi
+
+fi
+echo "$as_me:$LINENO: result: $ac_cv_pts_have_switch_enum_bug" >&5
+echo "${ECHO_T}$ac_cv_pts_have_switch_enum_bug" >&6
+ if test x"$ac_cv_pts_have_switch_enum_bug" = xyes; then
+ cat >>confdefs.h <<\_ACEOF
+#define HAVE_SWITCH_ENUM_BUG 1
+_ACEOF
+
+ fi
+
+
+
+ echo "$as_me:$LINENO: checking for ASCII system" >&5
+echo $ECHO_N "checking for ASCII system... $ECHO_C" >&6
+if test "${ac_cv_pts_have_ascii_system+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+
+ cat >conftest.$ac_ext <<_ACEOF
+#line $LINENO "configure"
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+
+#if 'a'!=97 || '!'!=33
+#error You need an ASCII system to compile this.
+#else
+ascii_yes
+#endif
+
+_ACEOF
+if (eval "$ac_cpp conftest.$ac_ext") 2>&5 |
+ $EGREP "ascii_yes" >/dev/null 2>&1; then
+ ac_cv_pts_have_ascii_system=yes
+else
+ ac_cv_pts_have_ascii_system=no
+
+fi
+rm -f conftest*
+
+
+fi
+echo "$as_me:$LINENO: result: $ac_cv_pts_have_ascii_system" >&5
+echo "${ECHO_T}$ac_cv_pts_have_ascii_system" >&6
+ if test x"$ac_cv_pts_have_ascii_system" = xyes; then
+ cat >>confdefs.h <<\_ACEOF
+#define HAVE_ASCII_SYSTEM 1
+_ACEOF
+
+ fi
+
+ if test x"$ac_cv_pts_have_ascii_system" != xyes; then
+ { { echo "$as_me:$LINENO: error: you need an ASCII system" >&5
+echo "$as_me: error: you need an ASCII system" >&2;}
+ { (exit 1); exit 1; }; }
+ fi
+
+echo "$as_me:$LINENO: checking for an ANSI C-conforming const" >&5
+echo $ECHO_N "checking for an ANSI C-conforming const... $ECHO_C" >&6
+if test "${ac_cv_c_const+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ cat >conftest.$ac_ext <<_ACEOF
+#line $LINENO "configure"
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+
+int
+main ()
+{
+/* FIXME: Include the comments suggested by Paul. */
+#ifndef __cplusplus
+ /* Ultrix mips cc rejects this. */
+ typedef int charset[2];
+ const charset x;
+ /* SunOS 4.1.1 cc rejects this. */
+ char const *const *ccp;
+ char **p;
+ /* NEC SVR4.0.2 mips cc rejects this. */
+ struct point {int x, y;};
+ static struct point const zero = {0,0};
+ /* AIX XL C 1.02.0.0 rejects this.
+ It does not let you subtract one const X* pointer from another in
+ an arm of an if-expression whose if-part is not a constant
+ expression */
+ const char *g = "string";
+ ccp = &g + (g ? g-g : 0);
+ /* HPUX 7.0 cc rejects these. */
+ ++ccp;
+ p = (char**) ccp;
+ ccp = (char const *const *) p;
+ { /* SCO 3.2v4 cc rejects this. */
+ char *t;
+ char const *s = 0 ? (char *) 0 : (char const *) 0;
+
+ *t++ = 0;
+ }
+ { /* Someone thinks the Sun supposedly-ANSI compiler will reject this. */
+ int x[] = {25, 17};
+ const int *foo = &x[0];
+ ++foo;
+ }
+ { /* Sun SC1.0 ANSI compiler rejects this -- but not the above. */
+ typedef const int *iptr;
+ iptr p = 0;
+ ++p;
+ }
+ { /* AIX XL C 1.02.0.0 rejects this saying
+ "k.c", line 2.27: 1506-025 (S) Operand must be a modifiable lvalue. */
+ struct s { int j; const int *ap[3]; };
+ struct s *b; b->j = 5;
+ }
+ { /* ULTRIX-32 V3.1 (Rev 9) vcc rejects this */
+ const int foo = 10;
+ }
+#endif
+
+ ;
+ return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext
+if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
+ (eval $ac_compile) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } &&
+ { ac_try='test -s conftest.$ac_objext'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; }; then
+ ac_cv_c_const=yes
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ac_cv_c_const=no
+fi
+rm -f conftest.$ac_objext conftest.$ac_ext
+fi
+echo "$as_me:$LINENO: result: $ac_cv_c_const" >&5
+echo "${ECHO_T}$ac_cv_c_const" >&6
+if test $ac_cv_c_const = no; then
+
+cat >>confdefs.h <<\_ACEOF
+#define const
+_ACEOF
+
+fi
+
+
+ echo "$as_me:$LINENO: checking for C keyword volatile" >&5
+echo $ECHO_N "checking for C keyword volatile... $ECHO_C" >&6
+if test "${ac_cv_pts_have_volatile+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+
+ cat >conftest.$ac_ext <<_ACEOF
+#line $LINENO "configure"
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+volatile int i;
+int
+main ()
+{
+i=5; i++; return i-6;
+ ;
+ return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext
+if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
+ (eval $ac_compile) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } &&
+ { ac_try='test -s conftest.$ac_objext'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; }; then
+ ac_cv_pts_have_volatile=yes
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ac_cv_pts_have_volatile=no
+
+fi
+rm -f conftest.$ac_objext conftest.$ac_ext
+
+fi
+echo "$as_me:$LINENO: result: $ac_cv_pts_have_volatile" >&5
+echo "${ECHO_T}$ac_cv_pts_have_volatile" >&6
+ if test x"$ac_cv_pts_have_volatile" = xno; then
+ cat >>confdefs.h <<\_ACEOF
+#define volatile
+_ACEOF
+
+ fi
+
+
+ echo "$as_me:$LINENO: checking whether c++ supports static const" >&5
+echo $ECHO_N "checking whether c++ supports static const... $ECHO_C" >&6
+if test "${ac_cv_pts_have_static_const+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+
+ cat >conftest.$ac_ext <<_ACEOF
+#line $LINENO "configure"
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+#undef const
+class A { public: static const int i=1; };
+int
+main ()
+{
+return A::i==0;
+ ;
+ return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext
+if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
+ (eval $ac_compile) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } &&
+ { ac_try='test -s conftest.$ac_objext'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; }; then
+ ac_cv_pts_have_static_const=yes
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ac_cv_pts_have_static_const=no
+
+fi
+rm -f conftest.$ac_objext conftest.$ac_ext
+
+fi
+echo "$as_me:$LINENO: result: $ac_cv_pts_have_static_const" >&5
+echo "${ECHO_T}$ac_cv_pts_have_static_const" >&6
+ if test x"$ac_cv_pts_have_static_const" = xyes; then
+ cat >>confdefs.h <<\_ACEOF
+#define HAVE_STATIC_CONST 1
+_ACEOF
+
+ fi
+
+
+
+
+CXXFLAGS_save="$CXXFLAGS"
+CXXFLAGS="$CXXFLAGS -ansi"
+
+ echo "$as_me:$LINENO: checking for working getc in stdio.h" >&5
+echo $ECHO_N "checking for working getc in stdio.h... $ECHO_C" >&6
+if test "${ac_cv_pts_getc_in_stdio+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+
+ if test "$cross_compiling" = yes; then
+ { { echo "$as_me:$LINENO: error: cross compiling not supported by .._PTS_CHECK_HEADER" >&5
+echo "$as_me: error: cross compiling not supported by .._PTS_CHECK_HEADER" >&2;}
+ { (exit 1); exit 1; }; }
+
+else
+ cat >conftest.$ac_ext <<_ACEOF
+#line $LINENO "configure"
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+
+/* #include "confdefs.h" -- automatic */
+#undef const
+#undef volatile
+#undef inline
+#include <stdio.h>
+#include "confdefs.h"
+int main
+#ifdef __STDC__
+(int argc, char **argv)
+#else
+(argc, argv) int argc; char **argv;
+#endif
+{
+ return argc>42? getc(stdin)*0+1:0;
+ return 1;
+}
+_ACEOF
+rm -f conftest$ac_exeext
+if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5
+ (eval $ac_link) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } && { ac_try='./conftest$ac_exeext'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; }; then
+ ac_cv_pts_getc_in_stdio=yes
+else
+ echo "$as_me: program exited with status $ac_status" >&5
+echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+( exit $ac_status )
+ac_cv_pts_getc_in_stdio=no
+fi
+rm -f core core.* *.core gmon.out bb.out conftest$ac_exeext conftest.$ac_objext conftest.$ac_ext
+fi
+
+fi
+echo "$as_me:$LINENO: result: $ac_cv_pts_getc_in_stdio" >&5
+echo "${ECHO_T}$ac_cv_pts_getc_in_stdio" >&6
+ if test x"$ac_cv_pts_getc_in_stdio" = xyes; then
+ cat >>confdefs.h <<_ACEOF
+#define HAVE_getc_in_stdio 1
+_ACEOF
+
+ fi
+
+
+ echo "$as_me:$LINENO: checking for working fgetc in stdio.h" >&5
+echo $ECHO_N "checking for working fgetc in stdio.h... $ECHO_C" >&6
+if test "${ac_cv_pts_fgetc_in_stdio+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+
+ if test "$cross_compiling" = yes; then
+ { { echo "$as_me:$LINENO: error: cross compiling not supported by .._PTS_CHECK_HEADER" >&5
+echo "$as_me: error: cross compiling not supported by .._PTS_CHECK_HEADER" >&2;}
+ { (exit 1); exit 1; }; }
+
+else
+ cat >conftest.$ac_ext <<_ACEOF
+#line $LINENO "configure"
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+
+/* #include "confdefs.h" -- automatic */
+#undef const
+#undef volatile
+#undef inline
+#include <stdio.h>
+#include "confdefs.h"
+int main
+#ifdef __STDC__
+(int argc, char **argv)
+#else
+(argc, argv) int argc; char **argv;
+#endif
+{
+ return argc>42?fgetc(stdin)*0+1:0;
+ return 1;
+}
+_ACEOF
+rm -f conftest$ac_exeext
+if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5
+ (eval $ac_link) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } && { ac_try='./conftest$ac_exeext'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; }; then
+ ac_cv_pts_fgetc_in_stdio=yes
+else
+ echo "$as_me: program exited with status $ac_status" >&5
+echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+( exit $ac_status )
+ac_cv_pts_fgetc_in_stdio=no
+fi
+rm -f core core.* *.core gmon.out bb.out conftest$ac_exeext conftest.$ac_objext conftest.$ac_ext
+fi
+
+fi
+echo "$as_me:$LINENO: result: $ac_cv_pts_fgetc_in_stdio" >&5
+echo "${ECHO_T}$ac_cv_pts_fgetc_in_stdio" >&6
+ if test x"$ac_cv_pts_fgetc_in_stdio" = xyes; then
+ cat >>confdefs.h <<_ACEOF
+#define HAVE_fgetc_in_stdio 1
+_ACEOF
+
+ fi
+
+
+ echo "$as_me:$LINENO: checking for working putc in stdio.h" >&5
+echo $ECHO_N "checking for working putc in stdio.h... $ECHO_C" >&6
+if test "${ac_cv_pts_putc_in_stdio+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+
+ if test "$cross_compiling" = yes; then
+ { { echo "$as_me:$LINENO: error: cross compiling not supported by .._PTS_CHECK_HEADER" >&5
+echo "$as_me: error: cross compiling not supported by .._PTS_CHECK_HEADER" >&2;}
+ { (exit 1); exit 1; }; }
+
+else
+ cat >conftest.$ac_ext <<_ACEOF
+#line $LINENO "configure"
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+
+/* #include "confdefs.h" -- automatic */
+#undef const
+#undef volatile
+#undef inline
+#include <stdio.h>
+#include "confdefs.h"
+int main
+#ifdef __STDC__
+(int argc, char **argv)
+#else
+(argc, argv) int argc; char **argv;
+#endif
+{
+ return argc>42? putc(' ',stdout)*0+1:0;
+ return 1;
+}
+_ACEOF
+rm -f conftest$ac_exeext
+if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5
+ (eval $ac_link) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } && { ac_try='./conftest$ac_exeext'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; }; then
+ ac_cv_pts_putc_in_stdio=yes
+else
+ echo "$as_me: program exited with status $ac_status" >&5
+echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+( exit $ac_status )
+ac_cv_pts_putc_in_stdio=no
+fi
+rm -f core core.* *.core gmon.out bb.out conftest$ac_exeext conftest.$ac_objext conftest.$ac_ext
+fi
+
+fi
+echo "$as_me:$LINENO: result: $ac_cv_pts_putc_in_stdio" >&5
+echo "${ECHO_T}$ac_cv_pts_putc_in_stdio" >&6
+ if test x"$ac_cv_pts_putc_in_stdio" = xyes; then
+ cat >>confdefs.h <<_ACEOF
+#define HAVE_putc_in_stdio 1
+_ACEOF
+
+ fi
+
+
+ echo "$as_me:$LINENO: checking for working fputc in stdio.h" >&5
+echo $ECHO_N "checking for working fputc in stdio.h... $ECHO_C" >&6
+if test "${ac_cv_pts_fputc_in_stdio+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+
+ if test "$cross_compiling" = yes; then
+ { { echo "$as_me:$LINENO: error: cross compiling not supported by .._PTS_CHECK_HEADER" >&5
+echo "$as_me: error: cross compiling not supported by .._PTS_CHECK_HEADER" >&2;}
+ { (exit 1); exit 1; }; }
+
+else
+ cat >conftest.$ac_ext <<_ACEOF
+#line $LINENO "configure"
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+
+/* #include "confdefs.h" -- automatic */
+#undef const
+#undef volatile
+#undef inline
+#include <stdio.h>
+#include "confdefs.h"
+int main
+#ifdef __STDC__
+(int argc, char **argv)
+#else
+(argc, argv) int argc; char **argv;
+#endif
+{
+ return argc>42?fputc(' ',stdout)*0+1:0;
+ return 1;
+}
+_ACEOF
+rm -f conftest$ac_exeext
+if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5
+ (eval $ac_link) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } && { ac_try='./conftest$ac_exeext'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; }; then
+ ac_cv_pts_fputc_in_stdio=yes
+else
+ echo "$as_me: program exited with status $ac_status" >&5
+echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+( exit $ac_status )
+ac_cv_pts_fputc_in_stdio=no
+fi
+rm -f core core.* *.core gmon.out bb.out conftest$ac_exeext conftest.$ac_objext conftest.$ac_ext
+fi
+
+fi
+echo "$as_me:$LINENO: result: $ac_cv_pts_fputc_in_stdio" >&5
+echo "${ECHO_T}$ac_cv_pts_fputc_in_stdio" >&6
+ if test x"$ac_cv_pts_fputc_in_stdio" = xyes; then
+ cat >>confdefs.h <<_ACEOF
+#define HAVE_fputc_in_stdio 1
+_ACEOF
+
+ fi
+
+CXXFLAGS="$CXXFLAGS_save"
+
+
+ echo "$as_me:$LINENO: checking for working sprintf in stdio.h" >&5
+echo $ECHO_N "checking for working sprintf in stdio.h... $ECHO_C" >&6
+if test "${ac_cv_pts_sprintf_in_stdio+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+
+ if test "$cross_compiling" = yes; then
+ { { echo "$as_me:$LINENO: error: cross compiling not supported by .._PTS_CHECK_HEADER" >&5
+echo "$as_me: error: cross compiling not supported by .._PTS_CHECK_HEADER" >&2;}
+ { (exit 1); exit 1; }; }
+
+else
+ cat >conftest.$ac_ext <<_ACEOF
+#line $LINENO "configure"
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+
+/* #include "confdefs.h" -- automatic */
+#undef const
+#undef volatile
+#undef inline
+#include <stdio.h>
+#include "confdefs.h"
+int main
+#ifdef __STDC__
+(int argc, char **argv)
+#else
+(argc, argv) int argc; char **argv;
+#endif
+{
+ char s[42]="X"; sprintf(s, "Hello, World!"); return *s!='H';
+ return 1;
+}
+_ACEOF
+rm -f conftest$ac_exeext
+if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5
+ (eval $ac_link) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } && { ac_try='./conftest$ac_exeext'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; }; then
+ ac_cv_pts_sprintf_in_stdio=yes
+else
+ echo "$as_me: program exited with status $ac_status" >&5
+echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+( exit $ac_status )
+ac_cv_pts_sprintf_in_stdio=no
+fi
+rm -f core core.* *.core gmon.out bb.out conftest$ac_exeext conftest.$ac_objext conftest.$ac_ext
+fi
+
+fi
+echo "$as_me:$LINENO: result: $ac_cv_pts_sprintf_in_stdio" >&5
+echo "${ECHO_T}$ac_cv_pts_sprintf_in_stdio" >&6
+ if test x"$ac_cv_pts_sprintf_in_stdio" = xyes; then
+ cat >>confdefs.h <<_ACEOF
+#define HAVE_sprintf_in_stdio 1
+_ACEOF
+
+ fi
+
+
+ echo "$as_me:$LINENO: checking for working atoi in stdlib.h" >&5
+echo $ECHO_N "checking for working atoi in stdlib.h... $ECHO_C" >&6
+if test "${ac_cv_pts_atoi_in_stdlib+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+
+ if test "$cross_compiling" = yes; then
+ { { echo "$as_me:$LINENO: error: cross compiling not supported by .._PTS_CHECK_HEADER" >&5
+echo "$as_me: error: cross compiling not supported by .._PTS_CHECK_HEADER" >&2;}
+ { (exit 1); exit 1; }; }
+
+else
+ cat >conftest.$ac_ext <<_ACEOF
+#line $LINENO "configure"
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+
+/* #include "confdefs.h" -- automatic */
+#undef const
+#undef volatile
+#undef inline
+#include <stdlib.h>
+#include "confdefs.h"
+int main
+#ifdef __STDC__
+(int argc, char **argv)
+#else
+(argc, argv) int argc; char **argv;
+#endif
+{
+ return atoi("42")!=42;
+ return 1;
+}
+_ACEOF
+rm -f conftest$ac_exeext
+if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5
+ (eval $ac_link) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } && { ac_try='./conftest$ac_exeext'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; }; then
+ ac_cv_pts_atoi_in_stdlib=yes
+else
+ echo "$as_me: program exited with status $ac_status" >&5
+echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+( exit $ac_status )
+ac_cv_pts_atoi_in_stdlib=no
+fi
+rm -f core core.* *.core gmon.out bb.out conftest$ac_exeext conftest.$ac_objext conftest.$ac_ext
+fi
+
+fi
+echo "$as_me:$LINENO: result: $ac_cv_pts_atoi_in_stdlib" >&5
+echo "${ECHO_T}$ac_cv_pts_atoi_in_stdlib" >&6
+ if test x"$ac_cv_pts_atoi_in_stdlib" = xyes; then
+ cat >>confdefs.h <<_ACEOF
+#define HAVE_atoi_in_stdlib 1
+_ACEOF
+
+ fi
+
+
+ echo "$as_me:$LINENO: checking for working write in unistd.h" >&5
+echo $ECHO_N "checking for working write in unistd.h... $ECHO_C" >&6
+if test "${ac_cv_pts_write_in_unistd+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+
+ if test "$cross_compiling" = yes; then
+ { { echo "$as_me:$LINENO: error: cross compiling not supported by .._PTS_CHECK_HEADER" >&5
+echo "$as_me: error: cross compiling not supported by .._PTS_CHECK_HEADER" >&2;}
+ { (exit 1); exit 1; }; }
+
+else
+ cat >conftest.$ac_ext <<_ACEOF
+#line $LINENO "configure"
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+
+/* #include "confdefs.h" -- automatic */
+#undef const
+#undef volatile
+#undef inline
+#include <unistd.h>
+#include "confdefs.h"
+int main
+#ifdef __STDC__
+(int argc, char **argv)
+#else
+(argc, argv) int argc; char **argv;
+#endif
+{
+ return write(1,"what",0)!=0;
+ return 1;
+}
+_ACEOF
+rm -f conftest$ac_exeext
+if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5
+ (eval $ac_link) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } && { ac_try='./conftest$ac_exeext'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; }; then
+ ac_cv_pts_write_in_unistd=yes
+else
+ echo "$as_me: program exited with status $ac_status" >&5
+echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+( exit $ac_status )
+ac_cv_pts_write_in_unistd=no
+fi
+rm -f core core.* *.core gmon.out bb.out conftest$ac_exeext conftest.$ac_objext conftest.$ac_ext
+fi
+
+fi
+echo "$as_me:$LINENO: result: $ac_cv_pts_write_in_unistd" >&5
+echo "${ECHO_T}$ac_cv_pts_write_in_unistd" >&6
+ if test x"$ac_cv_pts_write_in_unistd" = xyes; then
+ cat >>confdefs.h <<_ACEOF
+#define HAVE_write_in_unistd 1
+_ACEOF
+
+ fi
+
+
+ echo "$as_me:$LINENO: checking for working system in stdlib.h" >&5
+echo $ECHO_N "checking for working system in stdlib.h... $ECHO_C" >&6
+if test "${ac_cv_pts_system_in_stdlib+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+
+ if test "$cross_compiling" = yes; then
+ { { echo "$as_me:$LINENO: error: cross compiling not supported by .._PTS_CHECK_HEADER" >&5
+echo "$as_me: error: cross compiling not supported by .._PTS_CHECK_HEADER" >&2;}
+ { (exit 1); exit 1; }; }
+
+else
+ cat >conftest.$ac_ext <<_ACEOF
+#line $LINENO "configure"
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+
+/* #include "confdefs.h" -- automatic */
+#undef const
+#undef volatile
+#undef inline
+#include <stdlib.h>
+#include "confdefs.h"
+int main
+#ifdef __STDC__
+(int argc, char **argv)
+#else
+(argc, argv) int argc; char **argv;
+#endif
+{
+ /*>255 OK*/return system("true")!=0;
+ return 1;
+}
+_ACEOF
+rm -f conftest$ac_exeext
+if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5
+ (eval $ac_link) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } && { ac_try='./conftest$ac_exeext'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; }; then
+ ac_cv_pts_system_in_stdlib=yes
+else
+ echo "$as_me: program exited with status $ac_status" >&5
+echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+( exit $ac_status )
+ac_cv_pts_system_in_stdlib=no
+fi
+rm -f core core.* *.core gmon.out bb.out conftest$ac_exeext conftest.$ac_objext conftest.$ac_ext
+fi
+
+fi
+echo "$as_me:$LINENO: result: $ac_cv_pts_system_in_stdlib" >&5
+echo "${ECHO_T}$ac_cv_pts_system_in_stdlib" >&6
+ if test x"$ac_cv_pts_system_in_stdlib" = xyes; then
+ cat >>confdefs.h <<_ACEOF
+#define HAVE_system_in_stdlib 1
+_ACEOF
+
+ fi
+
+
+ echo "$as_me:$LINENO: checking for working lstat in sys/stat.h" >&5
+echo $ECHO_N "checking for working lstat in sys/stat.h... $ECHO_C" >&6
+if test "${ac_cv_pts_lstat_in_sys_stat+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+
+ if test "$cross_compiling" = yes; then
+ { { echo "$as_me:$LINENO: error: cross compiling not supported by .._PTS_CHECK_HEADER" >&5
+echo "$as_me: error: cross compiling not supported by .._PTS_CHECK_HEADER" >&2;}
+ { (exit 1); exit 1; }; }
+
+else
+ cat >conftest.$ac_ext <<_ACEOF
+#line $LINENO "configure"
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+
+/* #include "confdefs.h" -- automatic */
+#undef const
+#undef volatile
+#undef inline
+#include <sys/stat.h>
+#include "confdefs.h"
+int main
+#ifdef __STDC__
+(int argc, char **argv)
+#else
+(argc, argv) int argc; char **argv;
+#endif
+{
+ struct stat st; return 0!=lstat("/",&st);
+ return 1;
+}
+_ACEOF
+rm -f conftest$ac_exeext
+if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5
+ (eval $ac_link) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } && { ac_try='./conftest$ac_exeext'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; }; then
+ ac_cv_pts_lstat_in_sys_stat=yes
+else
+ echo "$as_me: program exited with status $ac_status" >&5
+echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+( exit $ac_status )
+ac_cv_pts_lstat_in_sys_stat=no
+fi
+rm -f core core.* *.core gmon.out bb.out conftest$ac_exeext conftest.$ac_objext conftest.$ac_ext
+fi
+
+fi
+echo "$as_me:$LINENO: result: $ac_cv_pts_lstat_in_sys_stat" >&5
+echo "${ECHO_T}$ac_cv_pts_lstat_in_sys_stat" >&6
+ if test x"$ac_cv_pts_lstat_in_sys_stat" = xyes; then
+ cat >>confdefs.h <<_ACEOF
+#define HAVE_lstat_in_sys_stat 1
+_ACEOF
+
+ fi
+
+
+
+ echo "$as_me:$LINENO: checking for working strcpy in string.h" >&5
+echo $ECHO_N "checking for working strcpy in string.h... $ECHO_C" >&6
+if test "${ac_cv_pts_strcpy_in_string+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+
+ if test "$cross_compiling" = yes; then
+ { { echo "$as_me:$LINENO: error: cross compiling not supported by .._PTS_CHECK_HEADER" >&5
+echo "$as_me: error: cross compiling not supported by .._PTS_CHECK_HEADER" >&2;}
+ { (exit 1); exit 1; }; }
+
+else
+ cat >conftest.$ac_ext <<_ACEOF
+#line $LINENO "configure"
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+
+/* #include "confdefs.h" -- automatic */
+#undef const
+#undef volatile
+#undef inline
+#include <string.h>
+#include "confdefs.h"
+int main
+#ifdef __STDC__
+(int argc, char **argv)
+#else
+(argc, argv) int argc; char **argv;
+#endif
+{
+ char s[42]="X"; strcpy(s, "Hello, World!"); return *s!='H';
+ return 1;
+}
+_ACEOF
+rm -f conftest$ac_exeext
+if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5
+ (eval $ac_link) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } && { ac_try='./conftest$ac_exeext'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; }; then
+ ac_cv_pts_strcpy_in_string=yes
+else
+ echo "$as_me: program exited with status $ac_status" >&5
+echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+( exit $ac_status )
+ac_cv_pts_strcpy_in_string=no
+fi
+rm -f core core.* *.core gmon.out bb.out conftest$ac_exeext conftest.$ac_objext conftest.$ac_ext
+fi
+
+fi
+echo "$as_me:$LINENO: result: $ac_cv_pts_strcpy_in_string" >&5
+echo "${ECHO_T}$ac_cv_pts_strcpy_in_string" >&6
+ if test x"$ac_cv_pts_strcpy_in_string" = xyes; then
+ cat >>confdefs.h <<_ACEOF
+#define HAVE_strcpy_in_string 1
+_ACEOF
+
+ fi
+
+ ac_cv_pts_have_string=no
+ if test x"$ac_cv_pts_strcpy_in_string" = xyes; then
+ ac_cv_pts_have_string=yes
+ ac_cv_pts_string_header=string
+ else
+
+ echo "$as_me:$LINENO: checking for working strcpy in strings.h" >&5
+echo $ECHO_N "checking for working strcpy in strings.h... $ECHO_C" >&6
+if test "${ac_cv_pts_strcpy_in_strings+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+
+ if test "$cross_compiling" = yes; then
+ { { echo "$as_me:$LINENO: error: cross compiling not supported by .._PTS_CHECK_HEADER" >&5
+echo "$as_me: error: cross compiling not supported by .._PTS_CHECK_HEADER" >&2;}
+ { (exit 1); exit 1; }; }
+
+else
+ cat >conftest.$ac_ext <<_ACEOF
+#line $LINENO "configure"
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+
+/* #include "confdefs.h" -- automatic */
+#undef const
+#undef volatile
+#undef inline
+#include <strings.h>
+#include "confdefs.h"
+int main
+#ifdef __STDC__
+(int argc, char **argv)
+#else
+(argc, argv) int argc; char **argv;
+#endif
+{
+ char s[42]="X"; strcpy(s, "Hello, World!"); return *s!='H';
+ return 1;
+}
+_ACEOF
+rm -f conftest$ac_exeext
+if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5
+ (eval $ac_link) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } && { ac_try='./conftest$ac_exeext'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; }; then
+ ac_cv_pts_strcpy_in_strings=yes
+else
+ echo "$as_me: program exited with status $ac_status" >&5
+echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+( exit $ac_status )
+ac_cv_pts_strcpy_in_strings=no
+fi
+rm -f core core.* *.core gmon.out bb.out conftest$ac_exeext conftest.$ac_objext conftest.$ac_ext
+fi
+
+fi
+echo "$as_me:$LINENO: result: $ac_cv_pts_strcpy_in_strings" >&5
+echo "${ECHO_T}$ac_cv_pts_strcpy_in_strings" >&6
+ if test x"$ac_cv_pts_strcpy_in_strings" = xyes; then
+ cat >>confdefs.h <<_ACEOF
+#define HAVE_strcpy_in_strings 1
+_ACEOF
+
+ fi
+
+ if test x"$ac_cv_pts_strcpy_in_strings" = xyes; then
+ ac_cv_pts_have_string=yes
+ ac_cv_pts_string_header=strings
+ fi
+ fi
+ if test x"$ac_cv_pts_have_string" = xyes; then
+ cat >>confdefs.h <<\_ACEOF
+#define HAVE_STRING 1
+_ACEOF
+
+ fi
+ CC_bak="$CC"
+ CC="${CC:-cc} -Werror"
+
+ echo "$as_me:$LINENO: checking for working memcpy in $ac_cv_pts_string_header.h" >&5
+echo $ECHO_N "checking for working memcpy in $ac_cv_pts_string_header.h... $ECHO_C" >&6
+if test "${ac_cv_pts_memcpy_in_stringxs+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+
+ if test "$cross_compiling" = yes; then
+ { { echo "$as_me:$LINENO: error: cross compiling not supported by .._PTS_CHECK_HEADER" >&5
+echo "$as_me: error: cross compiling not supported by .._PTS_CHECK_HEADER" >&2;}
+ { (exit 1); exit 1; }; }
+
+else
+ cat >conftest.$ac_ext <<_ACEOF
+#line $LINENO "configure"
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+
+/* #include "confdefs.h" -- automatic */
+#undef const
+#undef volatile
+#undef inline
+#include <$ac_cv_pts_string_header.h>
+#include "confdefs.h"
+int main
+#ifdef __STDC__
+(int argc, char **argv)
+#else
+(argc, argv) int argc; char **argv;
+#endif
+{
+ char s[42]="X"; memcpy(s, "Hello, World!", 2); return *s!='H';
+ return 1;
+}
+_ACEOF
+rm -f conftest$ac_exeext
+if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5
+ (eval $ac_link) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } && { ac_try='./conftest$ac_exeext'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; }; then
+ ac_cv_pts_memcpy_in_stringxs=yes
+else
+ echo "$as_me: program exited with status $ac_status" >&5
+echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+( exit $ac_status )
+ac_cv_pts_memcpy_in_stringxs=no
+fi
+rm -f core core.* *.core gmon.out bb.out conftest$ac_exeext conftest.$ac_objext conftest.$ac_ext
+fi
+
+fi
+echo "$as_me:$LINENO: result: $ac_cv_pts_memcpy_in_stringxs" >&5
+echo "${ECHO_T}$ac_cv_pts_memcpy_in_stringxs" >&6
+ if test x"$ac_cv_pts_memcpy_in_stringxs" = xyes; then
+ cat >>confdefs.h <<_ACEOF
+#define HAVE_memcpy_in_stringxs 1
+_ACEOF
+
+ fi
+
+ CC="$CC_bak"
+
+ echo "$as_me:$LINENO: checking whether memcmp and memcpy are built-in" >&5
+echo $ECHO_N "checking whether memcmp and memcpy are built-in... $ECHO_C" >&6
+if test "${ac_cv_pts_have_memcmpy_builtin+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+
+ ac_cv_pts_have_memcmpy_builtin=no
+ if test x"$ac_cv_pts_have_string" = xyes; then
+ if test x"$ac_cv_pts_memcpy_in_stringxs" = xno; then
+ if test "$cross_compiling" = yes; then
+ { { echo "$as_me:$LINENO: error: cross compiling not supported by .._PTS_CHECK_STRING" >&5
+echo "$as_me: error: cross compiling not supported by .._PTS_CHECK_STRING" >&2;}
+ { (exit 1); exit 1; }; }
+
+else
+ cat >conftest.$ac_ext <<_ACEOF
+#line $LINENO "configure"
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+
+int main
+#ifdef __STDC__
+(int argc, char **argv)
+#else
+(argc, argv) int argc; char **argv;
+#endif
+{
+ char s[42]="X"; memcpy(s, "Hello, World!", 2); return memcmp(s, "H", 1)!=0;
+}
+_ACEOF
+rm -f conftest$ac_exeext
+if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5
+ (eval $ac_link) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } && { ac_try='./conftest$ac_exeext'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; }; then
+ ac_cv_pts_have_memcmpy_builtin=yes
+else
+ echo "$as_me: program exited with status $ac_status" >&5
+echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+( exit $ac_status )
+{ { echo "$as_me:$LINENO: error: missing memcmp and memcpy" >&5
+echo "$as_me: error: missing memcmp and memcpy" >&2;}
+ { (exit 1); exit 1; }; }
+fi
+rm -f core core.* *.core gmon.out bb.out conftest$ac_exeext conftest.$ac_objext conftest.$ac_ext
+fi
+ fi
+ fi
+
+fi
+echo "$as_me:$LINENO: result: $ac_cv_pts_have_memcmpy_builtin" >&5
+echo "${ECHO_T}$ac_cv_pts_have_memcmpy_builtin" >&6
+ if test x"$ac_cv_pts_have_memcmpy_builtin" = xyes; then
+ cat >>confdefs.h <<\_ACEOF
+#define HAVE_MEMCMPY_BUILTIN 1
+_ACEOF
+
+ fi
+
+
+
+ echo "$as_me:$LINENO: checking for working malloc in stdlib.h" >&5
+echo $ECHO_N "checking for working malloc in stdlib.h... $ECHO_C" >&6
+if test "${ac_cv_pts_malloc_in_stdlib+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+
+ if test "$cross_compiling" = yes; then
+ { { echo "$as_me:$LINENO: error: cross compiling not supported by .._PTS_CHECK_HEADER" >&5
+echo "$as_me: error: cross compiling not supported by .._PTS_CHECK_HEADER" >&2;}
+ { (exit 1); exit 1; }; }
+
+else
+ cat >conftest.$ac_ext <<_ACEOF
+#line $LINENO "configure"
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+
+/* #include "confdefs.h" -- automatic */
+#undef const
+#undef volatile
+#undef inline
+#include <stdlib.h>
+#include "confdefs.h"
+int main
+#ifdef __STDC__
+(int argc, char **argv)
+#else
+(argc, argv) int argc; char **argv;
+#endif
+{
+ char *p=(char*)malloc(42); if (p!=0) free((void*)p); return p==0;
+ return 1;
+}
+_ACEOF
+rm -f conftest$ac_exeext
+if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5
+ (eval $ac_link) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } && { ac_try='./conftest$ac_exeext'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; }; then
+ ac_cv_pts_malloc_in_stdlib=yes
+else
+ echo "$as_me: program exited with status $ac_status" >&5
+echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+( exit $ac_status )
+ac_cv_pts_malloc_in_stdlib=no
+fi
+rm -f core core.* *.core gmon.out bb.out conftest$ac_exeext conftest.$ac_objext conftest.$ac_ext
+fi
+
+fi
+echo "$as_me:$LINENO: result: $ac_cv_pts_malloc_in_stdlib" >&5
+echo "${ECHO_T}$ac_cv_pts_malloc_in_stdlib" >&6
+ if test x"$ac_cv_pts_malloc_in_stdlib" = xyes; then
+ cat >>confdefs.h <<_ACEOF
+#define HAVE_malloc_in_stdlib 1
+_ACEOF
+
+ fi
+
+ if test x"$ac_cv_pts_malloc_in_stdlib" != xyes; then
+
+ echo "$as_me:$LINENO: checking for working malloc in malloc.h" >&5
+echo $ECHO_N "checking for working malloc in malloc.h... $ECHO_C" >&6
+if test "${ac_cv_pts_malloc_in_malloc+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+
+ if test "$cross_compiling" = yes; then
+ { { echo "$as_me:$LINENO: error: cross compiling not supported by .._PTS_CHECK_HEADER" >&5
+echo "$as_me: error: cross compiling not supported by .._PTS_CHECK_HEADER" >&2;}
+ { (exit 1); exit 1; }; }
+
+else
+ cat >conftest.$ac_ext <<_ACEOF
+#line $LINENO "configure"
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+
+/* #include "confdefs.h" -- automatic */
+#undef const
+#undef volatile
+#undef inline
+#include <malloc.h>
+#include "confdefs.h"
+int main
+#ifdef __STDC__
+(int argc, char **argv)
+#else
+(argc, argv) int argc; char **argv;
+#endif
+{
+ char *p=malloc(42); if (p!=0) free(p); return p==0;
+ return 1;
+}
+_ACEOF
+rm -f conftest$ac_exeext
+if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5
+ (eval $ac_link) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } && { ac_try='./conftest$ac_exeext'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; }; then
+ ac_cv_pts_malloc_in_malloc=yes
+else
+ echo "$as_me: program exited with status $ac_status" >&5
+echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+( exit $ac_status )
+ac_cv_pts_malloc_in_malloc=no
+fi
+rm -f core core.* *.core gmon.out bb.out conftest$ac_exeext conftest.$ac_objext conftest.$ac_ext
+fi
+
+fi
+echo "$as_me:$LINENO: result: $ac_cv_pts_malloc_in_malloc" >&5
+echo "${ECHO_T}$ac_cv_pts_malloc_in_malloc" >&6
+ if test x"$ac_cv_pts_malloc_in_malloc" = xyes; then
+ cat >>confdefs.h <<_ACEOF
+#define HAVE_malloc_in_malloc 1
+_ACEOF
+
+ fi
+
+ fi
+
+# The Ultrix 4.2 mips builtin alloca declared by alloca.h only works
+# for constant arguments. Useless!
+echo "$as_me:$LINENO: checking for working alloca.h" >&5
+echo $ECHO_N "checking for working alloca.h... $ECHO_C" >&6
+if test "${ac_cv_working_alloca_h+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ cat >conftest.$ac_ext <<_ACEOF
+#line $LINENO "configure"
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+#include <alloca.h>
+int
+main ()
+{
+char *p = (char *) alloca (2 * sizeof (int));
+ ;
+ return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext conftest$ac_exeext
+if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5
+ (eval $ac_link) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } &&
+ { ac_try='test -s conftest$ac_exeext'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; }; then
+ ac_cv_working_alloca_h=yes
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ac_cv_working_alloca_h=no
+fi
+rm -f conftest.$ac_objext conftest$ac_exeext conftest.$ac_ext
+fi
+echo "$as_me:$LINENO: result: $ac_cv_working_alloca_h" >&5
+echo "${ECHO_T}$ac_cv_working_alloca_h" >&6
+if test $ac_cv_working_alloca_h = yes; then
+
+cat >>confdefs.h <<\_ACEOF
+#define HAVE_ALLOCA_H 1
+_ACEOF
+
+fi
+
+echo "$as_me:$LINENO: checking for alloca" >&5
+echo $ECHO_N "checking for alloca... $ECHO_C" >&6
+if test "${ac_cv_func_alloca_works+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ cat >conftest.$ac_ext <<_ACEOF
+#line $LINENO "configure"
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+#ifdef __GNUC__
+# define alloca __builtin_alloca
+#else
+# ifdef _MSC_VER
+# include <malloc.h>
+# define alloca _alloca
+# else
+# if HAVE_ALLOCA_H
+# include <alloca.h>
+# else
+# ifdef _AIX
+ #pragma alloca
+# else
+# ifndef alloca /* predefined by HP cc +Olibcalls */
+char *alloca ();
+# endif
+# endif
+# endif
+# endif
+#endif
+
+int
+main ()
+{
+char *p = (char *) alloca (1);
+ ;
+ return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext conftest$ac_exeext
+if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5
+ (eval $ac_link) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } &&
+ { ac_try='test -s conftest$ac_exeext'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; }; then
+ ac_cv_func_alloca_works=yes
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ac_cv_func_alloca_works=no
+fi
+rm -f conftest.$ac_objext conftest$ac_exeext conftest.$ac_ext
+fi
+echo "$as_me:$LINENO: result: $ac_cv_func_alloca_works" >&5
+echo "${ECHO_T}$ac_cv_func_alloca_works" >&6
+
+if test $ac_cv_func_alloca_works = yes; then
+
+cat >>confdefs.h <<\_ACEOF
+#define HAVE_ALLOCA 1
+_ACEOF
+
+else
+ # The SVR3 libPW and SVR4 libucb both contain incompatible functions
+# that cause trouble. Some versions do not even contain alloca or
+# contain a buggy version. If you still want to use their alloca,
+# use ar to extract alloca.o from them instead of compiling alloca.c.
+
+ALLOCA=alloca.$ac_objext
+
+cat >>confdefs.h <<\_ACEOF
+#define C_ALLOCA 1
+_ACEOF
+
+
+echo "$as_me:$LINENO: checking whether \`alloca.c' needs Cray hooks" >&5
+echo $ECHO_N "checking whether \`alloca.c' needs Cray hooks... $ECHO_C" >&6
+if test "${ac_cv_os_cray+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ cat >conftest.$ac_ext <<_ACEOF
+#line $LINENO "configure"
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+#if defined(CRAY) && ! defined(CRAY2)
+webecray
+#else
+wenotbecray
+#endif
+
+_ACEOF
+if (eval "$ac_cpp conftest.$ac_ext") 2>&5 |
+ $EGREP "webecray" >/dev/null 2>&1; then
+ ac_cv_os_cray=yes
+else
+ ac_cv_os_cray=no
+fi
+rm -f conftest*
+
+fi
+echo "$as_me:$LINENO: result: $ac_cv_os_cray" >&5
+echo "${ECHO_T}$ac_cv_os_cray" >&6
+if test $ac_cv_os_cray = yes; then
+ for ac_func in _getb67 GETB67 getb67; do
+ as_ac_var=`echo "ac_cv_func_$ac_func" | $as_tr_sh`
+echo "$as_me:$LINENO: checking for $ac_func" >&5
+echo $ECHO_N "checking for $ac_func... $ECHO_C" >&6
+if eval "test \"\${$as_ac_var+set}\" = set"; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ cat >conftest.$ac_ext <<_ACEOF
+#line $LINENO "configure"
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+/* System header to define __stub macros and hopefully few prototypes,
+ which can conflict with char $ac_func (); below.
+ Prefer <limits.h> to <assert.h> if __STDC__ is defined, since
+ <limits.h> exists even on freestanding compilers. */
+#ifdef __STDC__
+# include <limits.h>
+#else
+# include <assert.h>
+#endif
+/* Override any gcc2 internal prototype to avoid an error. */
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+/* We use char because int might match the return type of a gcc2
+ builtin and then its argument prototype would still apply. */
+char $ac_func ();
+/* The GNU C library defines this for functions which it implements
+ to always fail with ENOSYS. Some functions are actually named
+ something starting with __ and the normal name is an alias. */
+#if defined (__stub_$ac_func) || defined (__stub___$ac_func)
+choke me
+#else
+char (*f) () = $ac_func;
+#endif
+#ifdef __cplusplus
+}
+#endif
+
+int
+main ()
+{
+return f != $ac_func;
+ ;
+ return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext conftest$ac_exeext
+if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5
+ (eval $ac_link) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } &&
+ { ac_try='test -s conftest$ac_exeext'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; }; then
+ eval "$as_ac_var=yes"
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+eval "$as_ac_var=no"
+fi
+rm -f conftest.$ac_objext conftest$ac_exeext conftest.$ac_ext
+fi
+echo "$as_me:$LINENO: result: `eval echo '${'$as_ac_var'}'`" >&5
+echo "${ECHO_T}`eval echo '${'$as_ac_var'}'`" >&6
+if test `eval echo '${'$as_ac_var'}'` = yes; then
+
+cat >>confdefs.h <<_ACEOF
+#define CRAY_STACKSEG_END $ac_func
+_ACEOF
+
+ break
+fi
+
+ done
+fi
+
+echo "$as_me:$LINENO: checking stack direction for C alloca" >&5
+echo $ECHO_N "checking stack direction for C alloca... $ECHO_C" >&6
+if test "${ac_cv_c_stack_direction+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ if test "$cross_compiling" = yes; then
+ ac_cv_c_stack_direction=0
+else
+ cat >conftest.$ac_ext <<_ACEOF
+#line $LINENO "configure"
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+int
+find_stack_direction ()
+{
+ static char *addr = 0;
+ auto char dummy;
+ if (addr == 0)
+ {
+ addr = &dummy;
+ return find_stack_direction ();
+ }
+ else
+ return (&dummy > addr) ? 1 : -1;
+}
+
+int
+main ()
+{
+ exit (find_stack_direction () < 0);
+}
+_ACEOF
+rm -f conftest$ac_exeext
+if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5
+ (eval $ac_link) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } && { ac_try='./conftest$ac_exeext'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; }; then
+ ac_cv_c_stack_direction=1
+else
+ echo "$as_me: program exited with status $ac_status" >&5
+echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+( exit $ac_status )
+ac_cv_c_stack_direction=-1
+fi
+rm -f core core.* *.core gmon.out bb.out conftest$ac_exeext conftest.$ac_objext conftest.$ac_ext
+fi
+fi
+echo "$as_me:$LINENO: result: $ac_cv_c_stack_direction" >&5
+echo "${ECHO_T}$ac_cv_c_stack_direction" >&6
+
+cat >>confdefs.h <<_ACEOF
+#define STACK_DIRECTION $ac_cv_c_stack_direction
+_ACEOF
+
+
+fi
+
+
+ echo "$as_me:$LINENO: checking for width of printf .g" >&5
+echo $ECHO_N "checking for width of printf .g... $ECHO_C" >&6
+if test "${ac_cv_pts_cfg_printfglen+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+
+ if test "$cross_compiling" = yes; then
+ { { echo "$as_me:$LINENO: error: cross compiling not supported by .._PTS_CFG_PRINTFGLEN" >&5
+echo "$as_me: error: cross compiling not supported by .._PTS_CFG_PRINTFGLEN" >&2;}
+ { (exit 1); exit 1; }; }
+
+else
+ cat >conftest.$ac_ext <<_ACEOF
+#line $LINENO "configure"
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+
+#define __USE_SVID 1
+#define __USE_GNU 1
+#include <stdio.h>
+
+int main
+#ifdef __STDC__
+(int argc, char **argv)
+#else
+(argc, argv) int argc; char **argv;
+#endif
+{
+ unsigned i;
+ char tmp[64], pat[10], *p;
+ FILE *f=fopen("conftestval","w");
+ if (!f) return 1;
+ for (i=1;i<61;i++) {
+ sprintf(pat, "%%.%ug", i);
+ sprintf(tmp, pat, 1.0/3);
+ if (tmp[0]=='0' && tmp[1]=='.') {
+ p=tmp+2; while (*p=='3') p++;
+ if (*p!='\0') break;
+ }
+ }
+ if (i>1) fprintf(f,".%u",i-1);
+ return 0;
+}
+_ACEOF
+rm -f conftest$ac_exeext
+if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5
+ (eval $ac_link) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } && { ac_try='./conftest$ac_exeext'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; }; then
+ ac_cv_pts_cfg_printfglen=\""`cat conftestval`"\"
+else
+ echo "$as_me: program exited with status $ac_status" >&5
+echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+( exit $ac_status )
+ac_cv_pts_cfg_printfglen=""
+fi
+rm -f core core.* *.core gmon.out bb.out conftest$ac_exeext conftest.$ac_objext conftest.$ac_ext
+fi
+ test x"$ac_cv_pts_cfg_printfglen" = x && ac_cv_pts_cfg_printfglen=no
+
+fi
+echo "$as_me:$LINENO: result: $ac_cv_pts_cfg_printfglen" >&5
+echo "${ECHO_T}$ac_cv_pts_cfg_printfglen" >&6
+ if test x"$ac_cv_pts_cfg_printfglen" = xno; then :; else
+ cat >>confdefs.h <<_ACEOF
+#define PTS_CFG_PRINTFGLEN $ac_cv_pts_cfg_printfglen
+_ACEOF
+
+ fi
+
+
+ echo "$as_me:$LINENO: checking for tmpdir" >&5
+echo $ECHO_N "checking for tmpdir... $ECHO_C" >&6
+if test "${ac_cv_pts_cfg_p_tmpdir+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+
+ if test "$cross_compiling" = yes; then
+ { { echo "$as_me:$LINENO: error: cross compiling not supported by .._PTS_CFG_P_TMPDIR" >&5
+echo "$as_me: error: cross compiling not supported by .._PTS_CFG_P_TMPDIR" >&2;}
+ { (exit 1); exit 1; }; }
+
+else
+ cat >conftest.$ac_ext <<_ACEOF
+#line $LINENO "configure"
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+
+#define __USE_SVID 1
+#define __USE_GNU 1
+#include <stdio.h>
+
+int main
+#ifdef __STDC__
+(int argc, char **argv)
+#else
+(argc, argv) int argc; char **argv;
+#endif
+{
+ FILE *f=fopen("conftestval","w");
+ if (!f) return 1;
+ fputs(P_tmpdir,f);
+ return 0;
+}
+_ACEOF
+rm -f conftest$ac_exeext
+if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5
+ (eval $ac_link) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } && { ac_try='./conftest$ac_exeext'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; }; then
+ ac_cv_pts_cfg_p_tmpdir=\""`cat conftestval`"\"
+else
+ echo "$as_me: program exited with status $ac_status" >&5
+echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+( exit $ac_status )
+ac_cv_pts_cfg_p_tmpdir=0
+fi
+rm -f core core.* *.core gmon.out bb.out conftest$ac_exeext conftest.$ac_objext conftest.$ac_ext
+fi
+
+fi
+echo "$as_me:$LINENO: result: $ac_cv_pts_cfg_p_tmpdir" >&5
+echo "${ECHO_T}$ac_cv_pts_cfg_p_tmpdir" >&6
+ cat >>confdefs.h <<_ACEOF
+#define PTS_CFG_P_TMPDIR $ac_cv_pts_cfg_p_tmpdir
+_ACEOF
+
+
+
+ echo "$as_me:$LINENO: checking for binary popen_" >&5
+echo $ECHO_N "checking for binary popen_... $ECHO_C" >&6
+if test "${ac_cv_pts_have_popen_+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+
+ if test "$cross_compiling" = yes; then
+ { { echo "$as_me:$LINENO: error: cross compiling not supported by .._PTS_HAVE_POPEN_" >&5
+echo "$as_me: error: cross compiling not supported by .._PTS_HAVE_POPEN_" >&2;}
+ { (exit 1); exit 1; }; }
+
+else
+ cat >conftest.$ac_ext <<_ACEOF
+#line $LINENO "configure"
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+
+#define _XOPEN_SOURCE 1 /* popen() on Digital UNIX */
+#define _POSIX_SOURCE 1 /* popen() */
+#define _POSIX_C_SOURCE 2 /* popen() */
+#include <stdio.h>
+
+int main
+#ifdef __STDC__
+(int argc, char **argv)
+#else
+(argc, argv) int argc; char **argv;
+#endif
+{ FILE *p=popen("echo Ko rt5","r");
+ int i;
+ (void)argc; (void)argv;
+ if (p==0) return 1;
+ if (getc(p)!='K' || getc(p)!='o' || getc(p)!=' ') return 2;
+ if (getc(p)!='r' || getc(p)!='t') return 3;
+ if (getc(p)!='f'-'a'+'0') return 4;
+ if (getc(p)!='\n') return 5;
+ if (getc(p)!=-1) return 6;
+ if (0!=pclose(p)) return 7;
+
+ p=popen("cat >conftestval","w");
+ if (p==0) return 31;
+ for (i=0;i<666;i++) putc(i,p);
+ if (ferror(p)) return 32;
+ if (0!=pclose(p)) return 33;
+ p=fopen("conftestval","rb");
+ if (p==0) return 34;
+ for (i=0;i<666;i++) if (getc(p)!=(i&255)) return 35;
+ if (fclose(p)!=0) return 36;
+
+ return 0;
+}
+
+_ACEOF
+rm -f conftest$ac_exeext
+if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5
+ (eval $ac_link) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } && { ac_try='./conftest$ac_exeext'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; }; then
+ ac_cv_pts_have_popen_=yes
+else
+ echo "$as_me: program exited with status $ac_status" >&5
+echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+( exit $ac_status )
+ac_cv_pts_have_popen_=no
+fi
+rm -f core core.* *.core gmon.out bb.out conftest$ac_exeext conftest.$ac_objext conftest.$ac_ext
+fi
+
+fi
+echo "$as_me:$LINENO: result: $ac_cv_pts_have_popen_" >&5
+echo "${ECHO_T}$ac_cv_pts_have_popen_" >&6
+ if test x"$ac_cv_pts_have_popen_" = xyes; then
+ cat >>confdefs.h <<\_ACEOF
+#define HAVE_PTS_POPEN_ 1
+_ACEOF
+
+ fi
+
+if test $ac_cv_pts_have_popen_ = yes; then
+ ac_cv_pts_have_popen_b=no
+fi
+
+ echo "$as_me:$LINENO: checking for binary popen_b" >&5
+echo $ECHO_N "checking for binary popen_b... $ECHO_C" >&6
+if test "${ac_cv_pts_have_popen_b+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+
+ if test "$cross_compiling" = yes; then
+ { { echo "$as_me:$LINENO: error: cross compiling not supported by .._PTS_HAVE_POPEN_B" >&5
+echo "$as_me: error: cross compiling not supported by .._PTS_HAVE_POPEN_B" >&2;}
+ { (exit 1); exit 1; }; }
+
+else
+ cat >conftest.$ac_ext <<_ACEOF
+#line $LINENO "configure"
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+
+#define _XOPEN_SOURCE 1 /* popen() on Digital UNIX */
+#define _POSIX_SOURCE 1 /* popen() */
+#define _POSIX_C_SOURCE 2 /* popen() */
+#include <stdio.h>
+
+int main
+#ifdef __STDC__
+(int argc, char **argv)
+#else
+(argc, argv) int argc; char **argv;
+#endif
+{ FILE *p=popen("echo Ko rt5","rb");
+ int i;
+ (void)argc; (void)argv;
+ if (p==0) return 1;
+ if (getc(p)!='K' || getc(p)!='o' || getc(p)!=' ') return 2;
+ if (getc(p)!='r' || getc(p)!='t') return 3;
+ if (getc(p)!='f'-'a'+'0') return 4;
+ if (getc(p)!='\n') return 5;
+ if (getc(p)!=-1) return 6;
+ if (0!=pclose(p)) return 7;
+
+ p=popen("cat >conftestval","wb");
+ if (p==0) return 31;
+ for (i=0;i<666;i++) putc(i,p);
+ if (ferror(p)) return 32;
+ if (0!=pclose(p)) return 33;
+ p=fopen("conftestval","rb");
+ if (p==0) return 34;
+ for (i=0;i<666;i++) if (getc(p)!=(i&255)) return 35;
+ if (fclose(p)!=0) return 36;
+
+ return 0;
+}
+
+_ACEOF
+rm -f conftest$ac_exeext
+if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5
+ (eval $ac_link) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } && { ac_try='./conftest$ac_exeext'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; }; then
+ ac_cv_pts_have_popen_b=yes
+else
+ echo "$as_me: program exited with status $ac_status" >&5
+echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+( exit $ac_status )
+ac_cv_pts_have_popen_b=no
+fi
+rm -f core core.* *.core gmon.out bb.out conftest$ac_exeext conftest.$ac_objext conftest.$ac_ext
+fi
+
+fi
+echo "$as_me:$LINENO: result: $ac_cv_pts_have_popen_b" >&5
+echo "${ECHO_T}$ac_cv_pts_have_popen_b" >&6
+ if test x"$ac_cv_pts_have_popen_b" = xyes; then
+ cat >>confdefs.h <<\_ACEOF
+#define HAVE_PTS_POPEN_B 1
+_ACEOF
+
+ fi
+
+
+ echo "$as_me:$LINENO: checking for working vsnprintf" >&5
+echo $ECHO_N "checking for working vsnprintf... $ECHO_C" >&6
+if test "${ac_cv_pts_vsnprintf+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+
+ if test "$cross_compiling" = yes; then
+ { { echo "$as_me:$LINENO: error: cross compiling not supported by .._PTS_HAVE_VSNPRINTF" >&5
+echo "$as_me: error: cross compiling not supported by .._PTS_HAVE_VSNPRINTF" >&2;}
+ { (exit 1); exit 1; }; }
+
+else
+ cat >conftest.$ac_ext <<_ACEOF
+#line $LINENO "configure"
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+
+#if 0 /* autoconf-2.54 */
+ extern "C" void std::exit (int) throw (); using std::exit;
+ extern "C" void std::exit (int); using std::exit;
+ extern "C" void exit (int) throw ();
+ extern "C" void exit (int);
+ void exit (int);
+#endif
+#ifdef __cplusplus
+extern "C" void exit(int);
+#endif
+#define _BSD_SOURCE 1 /* vsnprintf */
+#define _POSIX_SOURCE 1
+#define _POSIX_C_SOURCE 2
+#include <stdio.h>
+#include <stdarg.h>
+#include <string.h>
+
+static int myprintf(int max, char *dstr, char *fmt, ...) {
+ int i;
+ va_list ap;
+ #if defined(__STDC__)
+ va_start(ap, fmt);
+ #else
+ va_start(ap);
+ #endif
+ i=vsnprintf(dstr, max, fmt, ap);
+ va_end(ap);
+ return i;
+}
+
+int c99t[]={13,9,10,10,10}, oldt[]={-1,9,-1,0,-1}, sun99t[]={13,9,10,-1,10};
+/* wincrtt[]={-1,9,10,-1,-1}, but it modifies the string in a completely
+ * bogus way (passes 1 test of 5)
+ */
+
+int main
+#ifdef __STDC__
+(int argc, char **argv)
+#else
+(argc, argv) int argc; char **argv;
+#endif
+{ char buf[40];
+ int i;
+ int g[5], gg;
+ int *t=oldt;
+ FILE *f=fopen("conftestval","w");
+ (void)argc;
+ (void)argv;
+
+ if (f) {
+ for (i=0;i<(int)sizeof(buf)-1;i++) buf[i]='X'; buf[i]='\0';
+ i=myprintf(10, buf, "%s-%ld", "Alma", -1234567L);
+ if (i==c99t[0]) t=c99t; /* oldt[0]!=c99t[0] */
+ g[0]=(i==t[0] && 0==memcmp(buf, "Alma--123\0X", 11));
+ /* printf("(%s) %d %d\n", buf, i, g[0]); */
+
+ for (i=0;i<(int)sizeof(buf)-1;i++) buf[i]='Y'; buf[i]='\0';
+ i=myprintf(10, buf, "%s-%ld", "Alma", -123L);
+ g[1]=(i==t[1] && 0==memcmp(buf, "Alma--123\0Y", 11));
+ /* printf("(%s) %d %d\n", buf, i, g[1]); */
+
+ for (i=0;i<(int)sizeof(buf)-1;i++) buf[i]='Z'; buf[i]='\0';
+ i=myprintf(10, buf, "%s-%ld", "Alma", -1234L);
+ g[2]=(i==t[2] && 0==memcmp(buf, "Alma--123\0Z", 11));
+ /* printf("(%s) %d %d\n", buf, i, g[2]); */
+
+ buf[0]='#';
+ i=myprintf(0, buf, "%s-%ld", "Alma", -1234L);
+ if (t==c99t && i==sun99t[3]) t=sun99t;
+ g[3]=(i==t[3] && buf[0]=='#');
+ /* printf("(%s) %d %d\n", buf, i, g[3]); */
+
+ buf[0]=buf[1]='$';
+ i=myprintf(1, buf, "%s-%ld", "Alma", -1234L);
+ g[4]=(i==t[4] && buf[0]=='\0' && buf[1]=='$');
+ /* printf("(%s) %d %d\n", buf, i, g[4]); */
+
+ gg=g[0] && g[1] && g[2] && g[3] && g[4];
+ fputs(!gg ? "bad\n" : t==oldt ? "old\n" : t==sun99t ? "sun99\n" : "c99\n", f);
+ fclose(f);
+ }
+ return 0;
+}
+
+_ACEOF
+rm -f conftest$ac_exeext
+if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5
+ (eval $ac_link) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } && { ac_try='./conftest$ac_exeext'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; }; then
+ ac_cv_pts_vsnprintf="`cat conftestval`"; ac_cv_pts_vsnprintf="${ac_cv_pts_vsnprintf:-invalid}"
+else
+ echo "$as_me: program exited with status $ac_status" >&5
+echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+( exit $ac_status )
+ac_cv_pts_vsnprintf=no
+fi
+rm -f core core.* *.core gmon.out bb.out conftest$ac_exeext conftest.$ac_objext conftest.$ac_ext
+fi
+
+fi
+echo "$as_me:$LINENO: result: $ac_cv_pts_vsnprintf" >&5
+echo "${ECHO_T}$ac_cv_pts_vsnprintf" >&6
+ if test x"$ac_cv_pts_vsnprintf" = xold; then
+ ac_cv_pts_have_vsnprintf=yes
+ cat >>confdefs.h <<\_ACEOF
+#define HAVE_PTS_VSNPRINTF 1
+_ACEOF
+
+ cat >>confdefs.h <<\_ACEOF
+#define HAVE_PTS_VSNPRINTF_OLD 1
+_ACEOF
+
+ elif test x"$ac_cv_pts_have_vsnprintf" = xc99; then
+ ac_cv_pts_have_vsnprintf=yes
+ cat >>confdefs.h <<\_ACEOF
+#define HAVE_PTS_VSNPRINTF 1
+_ACEOF
+
+ cat >>confdefs.h <<\_ACEOF
+#define HAVE_PTS_VSNPRINTF_C99 1
+_ACEOF
+
+ else
+ ac_cv_pts_have_vsnprintf=no
+ ac_cv_pts_vsnprintf=no
+ fi
+
+
+ echo no-original >conftestval
+ echo "$as_me:$LINENO: checking for working system(3)" >&5
+echo $ECHO_N "checking for working system(3)... $ECHO_C" >&6
+if test "${ac_cv_pts_systemf+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+
+ if test "$cross_compiling" = yes; then
+ { { echo "$as_me:$LINENO: error: cross compiling not supported by .._PTS_HAVE_VSNPRINTF" >&5
+echo "$as_me: error: cross compiling not supported by .._PTS_HAVE_VSNPRINTF" >&2;}
+ { (exit 1); exit 1; }; }
+
+else
+ cat >conftest.$ac_ext <<_ACEOF
+#line $LINENO "configure"
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+
+#include <stdio.h>
+#include <stdlib.h> /* system() */
+
+int main
+#ifdef __STDC__
+(int argc, char **argv)
+#else
+(argc, argv) int argc; char **argv;
+#endif
+{
+ (void)argc;
+ (void)argv;
+ if (0!=system("echo t >conftestval && echo \"let it\" be e >conftestval")) {
+ FILE *f=fopen("conftestval","w");
+ if (f) {
+ fprintf(f,"runtime-error\n");
+ fclose(f);
+ }
+ }
+ return 0;
+}
+
+_ACEOF
+rm -f conftest$ac_exeext
+if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5
+ (eval $ac_link) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } && { ac_try='./conftest$ac_exeext'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; }; then
+ ac_cv_pts_systemf="`cat conftestval`"; ac_cv_pts_systemf="${ac_cv_pts_systemf:-invalid}"
+else
+ echo "$as_me: program exited with status $ac_status" >&5
+echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+( exit $ac_status )
+ac_cv_pts_systemf=compile-error
+fi
+rm -f core core.* *.core gmon.out bb.out conftest$ac_exeext conftest.$ac_objext conftest.$ac_ext
+fi
+ # echo "($ac_cv_pts_systemf)"
+ # if test x"$ac_cv_pts_systemf" = x'"let it" be e '; then
+ if test x"$ac_cv_pts_systemf" = x't && echo "let it" be e '; then
+ # Win32 COMMAND.COM
+ ac_cv_pts_systemf=win32
+ elif test x"$ac_cv_pts_systemf" = x"let it be e"; then
+ # UNIX /bin/sh
+ ac_cv_pts_systemf=unix
+ fi
+
+fi
+echo "$as_me:$LINENO: result: $ac_cv_pts_systemf" >&5
+echo "${ECHO_T}$ac_cv_pts_systemf" >&6
+ if test x"$ac_cv_pts_systemf" = xwin32; then
+ ac_cv_pts_have_systemf=yes
+ cat >>confdefs.h <<\_ACEOF
+#define HAVE_PTS_SYSTEMF 1
+_ACEOF
+
+ cat >>confdefs.h <<\_ACEOF
+#define HAVE_PTS_SYSTEMF_WIN32 1
+_ACEOF
+
+ elif test x"$ac_cv_pts_systemf" = xunix; then
+ ac_cv_pts_have_systemf=yes
+ cat >>confdefs.h <<\_ACEOF
+#define HAVE_PTS_SYSTEMF 1
+_ACEOF
+
+ cat >>confdefs.h <<\_ACEOF
+#define HAVE_PTS_SYSTEMF_UNIX 1
+_ACEOF
+
+ elif test x"$ac_cv_pts_systemf" = x"invalid"; then
+ ac_cv_pts_have_systemf=no
+ elif test x"$ac_cv_pts_systemf" = x"compile-error"; then
+ ac_cv_pts_have_systemf=no
+ elif test x"$ac_cv_pts_systemf" = x"runtime-error"; then
+ ac_cv_pts_have_systemf=no
+ elif test x"$ac_cv_pts_systemf" = x"no-original"; then
+ ac_cv_pts_have_systemf=no
+ else
+ ac_cv_pts_have_systemf=yes
+ # ac_cv_pts_systemf=other
+ cat >>confdefs.h <<\_ACEOF
+#define HAVE_PTS_SYSTEMF 1
+_ACEOF
+
+ cat >>confdefs.h <<\_ACEOF
+#define HAVE_PTS_SYSTEMF_OTHER 1
+_ACEOF
+
+ fi
+
+
+
+
+
+
+echo "$as_me:$LINENO: checking whether char is unsigned" >&5
+echo $ECHO_N "checking whether char is unsigned... $ECHO_C" >&6
+if test "${ac_cv_c_char_unsigned+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ if test "$GCC" = yes; then
+ # GCC predefines this symbol on systems where it applies.
+cat >conftest.$ac_ext <<_ACEOF
+#line $LINENO "configure"
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+#ifdef __CHAR_UNSIGNED__
+ yes
+#endif
+
+_ACEOF
+if (eval "$ac_cpp conftest.$ac_ext") 2>&5 |
+ $EGREP "yes" >/dev/null 2>&1; then
+ ac_cv_c_char_unsigned=yes
+else
+ ac_cv_c_char_unsigned=no
+fi
+rm -f conftest*
+
+else
+if test "$cross_compiling" = yes; then
+ { { echo "$as_me:$LINENO: error: cross compiling not supported by .._PTS_C_CHAR_UNSIGNED" >&5
+echo "$as_me: error: cross compiling not supported by .._PTS_C_CHAR_UNSIGNED" >&2;}
+ { (exit 1); exit 1; }; }
+else
+ cat >conftest.$ac_ext <<_ACEOF
+#line $LINENO "configure"
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+/* volatile prevents gcc2 from optimizing the test away on sparcs. */
+#if !defined(__STDC__) || __STDC__ != 1
+#define volatile
+#endif
+int main() {
+ volatile char c = 255; return(c < 0);
+}
+_ACEOF
+rm -f conftest$ac_exeext
+if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5
+ (eval $ac_link) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } && { ac_try='./conftest$ac_exeext'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; }; then
+ ac_cv_c_char_unsigned=yes
+else
+ echo "$as_me: program exited with status $ac_status" >&5
+echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+( exit $ac_status )
+ac_cv_c_char_unsigned=no
+fi
+rm -f core core.* *.core gmon.out bb.out conftest$ac_exeext conftest.$ac_objext conftest.$ac_ext
+fi
+fi
+fi
+echo "$as_me:$LINENO: result: $ac_cv_c_char_unsigned" >&5
+echo "${ECHO_T}$ac_cv_c_char_unsigned" >&6
+if test $ac_cv_c_char_unsigned = yes && test "$GCC" != yes; then
+ cat >>confdefs.h <<\_ACEOF
+#define __CHAR_UNSIGNED__ 1
+_ACEOF
+
+fi
+
+
+if test x"$ac_cv_sizeof_char" = x; then
+echo "$as_me:$LINENO: checking size of char" >&5
+echo $ECHO_N "checking size of char... $ECHO_C" >&6
+if test "${ac_cv_sizeof_char+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ ac_cv_sizeof_char_p=-1;ac_cv_sizeof_short=-1;ac_cv_sizeof_int=-1
+ac_cv_sizeof_long=-1
+if test "$cross_compiling" = yes; then
+ ac_cv_sizeof_char=-1
+else
+ cat >conftest.$ac_ext <<_ACEOF
+#line $LINENO "configure"
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+
+#undef const
+#undef volatile
+#undef inline
+#include <stdio.h>
+int main(){FILE *f=fopen("conftestval", "w");
+ if (!f) return 1;
+ fprintf(f, "ac_cv_sizeof_char=%d\n", sizeof(char));
+ fprintf(f, "ac_cv_sizeof_char_p=%d\n", sizeof(char*));
+ fprintf(f, "ac_cv_sizeof_short=%d\n", sizeof(short));
+ fprintf(f, "ac_cv_sizeof_int=%d\n", sizeof(int));
+ fprintf(f, "ac_cv_sizeof_long=%d\n", sizeof(long));
+ return 0; /* exit(0); -- return is more portable */
+}
+_ACEOF
+rm -f conftest$ac_exeext
+if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5
+ (eval $ac_link) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } && { ac_try='./conftest$ac_exeext'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; }; then
+ eval "`cat conftestval`"
+else
+ echo "$as_me: program exited with status $ac_status" >&5
+echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+fi
+rm -f core core.* *.core gmon.out bb.out conftest$ac_exeext conftest.$ac_objext conftest.$ac_ext
+fi
+fi
+
+echo "$as_me:$LINENO: result: $ac_cv_sizeof_char" >&5
+echo "${ECHO_T}$ac_cv_sizeof_char" >&6
+cat >>confdefs.h <<_ACEOF
+#define SIZEOF_CHAR $ac_cv_sizeof_char
+_ACEOF
+
+cat >>confdefs.h <<_ACEOF
+#define SIZEOF_CHAR_P $ac_cv_sizeof_char_p
+_ACEOF
+
+cat >>confdefs.h <<_ACEOF
+#define SIZEOF_SHORT $ac_cv_sizeof_short
+_ACEOF
+
+cat >>confdefs.h <<_ACEOF
+#define SIZEOF_INT $ac_cv_sizeof_int
+_ACEOF
+
+cat >>confdefs.h <<_ACEOF
+#define SIZEOF_LONG $ac_cv_sizeof_long
+_ACEOF
+
+fi
+
+if test $ac_cv_sizeof_char = -1; then
+ { { echo "$as_me:$LINENO: error: cross compiling not supported by .._PTS_CHECK_INTEGRALS" >&5
+echo "$as_me: error: cross compiling not supported by .._PTS_CHECK_INTEGRALS" >&2;}
+ { (exit 1); exit 1; }; }
+fi
+echo "$as_me:$LINENO: checking size of short" >&5
+echo $ECHO_N "checking size of short... $ECHO_C" >&6
+if test "${ac_cv_sizeof_short+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ if test "$cross_compiling" = yes; then
+ ac_cv_sizeof_short=-1
+else
+ cat >conftest.$ac_ext <<_ACEOF
+#line $LINENO "configure"
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+#include <stdio.h>
+#include <sys/types.h>
+int main() {
+ FILE *f=fopen("conftestval", "w");
+ if (!f) return 1;
+ fprintf(f, "%d\n", sizeof(short));
+ return 0;
+}
+_ACEOF
+rm -f conftest$ac_exeext
+if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5
+ (eval $ac_link) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } && { ac_try='./conftest$ac_exeext'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; }; then
+ ac_cv_sizeof_short=`cat conftestval`
+else
+ echo "$as_me: program exited with status $ac_status" >&5
+echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+( exit $ac_status )
+ac_cv_sizeof_short=0
+fi
+rm -f core core.* *.core gmon.out bb.out conftest$ac_exeext conftest.$ac_objext conftest.$ac_ext
+fi
+fi
+echo "$as_me:$LINENO: result: $ac_cv_sizeof_short" >&5
+echo "${ECHO_T}$ac_cv_sizeof_short" >&6
+cat >>confdefs.h <<_ACEOF
+#define SIZEOF_SHORT $ac_cv_sizeof_short
+_ACEOF
+
+
+echo "$as_me:$LINENO: checking size of int" >&5
+echo $ECHO_N "checking size of int... $ECHO_C" >&6
+if test "${ac_cv_sizeof_int+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ if test "$cross_compiling" = yes; then
+ ac_cv_sizeof_int=-1
+else
+ cat >conftest.$ac_ext <<_ACEOF
+#line $LINENO "configure"
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+#include <stdio.h>
+#include <sys/types.h>
+int main() {
+ FILE *f=fopen("conftestval", "w");
+ if (!f) return 1;
+ fprintf(f, "%d\n", sizeof(int));
+ return 0;
+}
+_ACEOF
+rm -f conftest$ac_exeext
+if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5
+ (eval $ac_link) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } && { ac_try='./conftest$ac_exeext'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; }; then
+ ac_cv_sizeof_int=`cat conftestval`
+else
+ echo "$as_me: program exited with status $ac_status" >&5
+echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+( exit $ac_status )
+ac_cv_sizeof_int=0
+fi
+rm -f core core.* *.core gmon.out bb.out conftest$ac_exeext conftest.$ac_objext conftest.$ac_ext
+fi
+fi
+echo "$as_me:$LINENO: result: $ac_cv_sizeof_int" >&5
+echo "${ECHO_T}$ac_cv_sizeof_int" >&6
+cat >>confdefs.h <<_ACEOF
+#define SIZEOF_INT $ac_cv_sizeof_int
+_ACEOF
+
+
+echo "$as_me:$LINENO: checking size of long" >&5
+echo $ECHO_N "checking size of long... $ECHO_C" >&6
+if test "${ac_cv_sizeof_long+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ if test "$cross_compiling" = yes; then
+ ac_cv_sizeof_long=-1
+else
+ cat >conftest.$ac_ext <<_ACEOF
+#line $LINENO "configure"
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+#include <stdio.h>
+#include <sys/types.h>
+int main() {
+ FILE *f=fopen("conftestval", "w");
+ if (!f) return 1;
+ fprintf(f, "%d\n", sizeof(long));
+ return 0;
+}
+_ACEOF
+rm -f conftest$ac_exeext
+if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5
+ (eval $ac_link) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } && { ac_try='./conftest$ac_exeext'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; }; then
+ ac_cv_sizeof_long=`cat conftestval`
+else
+ echo "$as_me: program exited with status $ac_status" >&5
+echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+( exit $ac_status )
+ac_cv_sizeof_long=0
+fi
+rm -f core core.* *.core gmon.out bb.out conftest$ac_exeext conftest.$ac_objext conftest.$ac_ext
+fi
+fi
+echo "$as_me:$LINENO: result: $ac_cv_sizeof_long" >&5
+echo "${ECHO_T}$ac_cv_sizeof_long" >&6
+cat >>confdefs.h <<_ACEOF
+#define SIZEOF_LONG $ac_cv_sizeof_long
+_ACEOF
+
+
+echo "$as_me:$LINENO: checking size of long long" >&5
+echo $ECHO_N "checking size of long long... $ECHO_C" >&6
+if test "${ac_cv_sizeof_long_long+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ if test "$cross_compiling" = yes; then
+ ac_cv_sizeof_long_long=-1
+else
+ cat >conftest.$ac_ext <<_ACEOF
+#line $LINENO "configure"
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+#include <stdio.h>
+#include <sys/types.h>
+int main() {
+ FILE *f=fopen("conftestval", "w");
+ if (!f) return 1;
+ fprintf(f, "%d\n", sizeof(long long));
+ return 0;
+}
+_ACEOF
+rm -f conftest$ac_exeext
+if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5
+ (eval $ac_link) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } && { ac_try='./conftest$ac_exeext'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; }; then
+ ac_cv_sizeof_long_long=`cat conftestval`
+else
+ echo "$as_me: program exited with status $ac_status" >&5
+echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+( exit $ac_status )
+ac_cv_sizeof_long_long=0
+fi
+rm -f core core.* *.core gmon.out bb.out conftest$ac_exeext conftest.$ac_objext conftest.$ac_ext
+fi
+fi
+echo "$as_me:$LINENO: result: $ac_cv_sizeof_long_long" >&5
+echo "${ECHO_T}$ac_cv_sizeof_long_long" >&6
+cat >>confdefs.h <<_ACEOF
+#define SIZEOF_LONG_LONG $ac_cv_sizeof_long_long
+_ACEOF
+
+
+if test $ac_cv_sizeof_long_long = 8
+then ac_cv_sizeof___int64=0; ac_cv_sizeof_very_long=0; fi
+echo "$as_me:$LINENO: checking size of very long" >&5
+echo $ECHO_N "checking size of very long... $ECHO_C" >&6
+if test "${ac_cv_sizeof_very_long+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ if test "$cross_compiling" = yes; then
+ ac_cv_sizeof_very_long=-1
+else
+ cat >conftest.$ac_ext <<_ACEOF
+#line $LINENO "configure"
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+#include <stdio.h>
+#include <sys/types.h>
+int main() {
+ FILE *f=fopen("conftestval", "w");
+ if (!f) return 1;
+ fprintf(f, "%d\n", sizeof(very long));
+ return 0;
+}
+_ACEOF
+rm -f conftest$ac_exeext
+if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5
+ (eval $ac_link) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } && { ac_try='./conftest$ac_exeext'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; }; then
+ ac_cv_sizeof_very_long=`cat conftestval`
+else
+ echo "$as_me: program exited with status $ac_status" >&5
+echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+( exit $ac_status )
+ac_cv_sizeof_very_long=0
+fi
+rm -f core core.* *.core gmon.out bb.out conftest$ac_exeext conftest.$ac_objext conftest.$ac_ext
+fi
+fi
+echo "$as_me:$LINENO: result: $ac_cv_sizeof_very_long" >&5
+echo "${ECHO_T}$ac_cv_sizeof_very_long" >&6
+cat >>confdefs.h <<_ACEOF
+#define SIZEOF_VERY_LONG $ac_cv_sizeof_very_long
+_ACEOF
+
+
+if test $ac_cv_sizeof_very_long = 8; then ac_cv_sizeof___int64=0; fi
+echo "$as_me:$LINENO: checking size of __int64" >&5
+echo $ECHO_N "checking size of __int64... $ECHO_C" >&6
+if test "${ac_cv_sizeof___int64+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ if test "$cross_compiling" = yes; then
+ ac_cv_sizeof___int64=-1
+else
+ cat >conftest.$ac_ext <<_ACEOF
+#line $LINENO "configure"
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+#include <stdio.h>
+#include <sys/types.h>
+int main() {
+ FILE *f=fopen("conftestval", "w");
+ if (!f) return 1;
+ fprintf(f, "%d\n", sizeof(__int64));
+ return 0;
+}
+_ACEOF
+rm -f conftest$ac_exeext
+if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5
+ (eval $ac_link) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } && { ac_try='./conftest$ac_exeext'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; }; then
+ ac_cv_sizeof___int64=`cat conftestval`
+else
+ echo "$as_me: program exited with status $ac_status" >&5
+echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+( exit $ac_status )
+ac_cv_sizeof___int64=0
+fi
+rm -f core core.* *.core gmon.out bb.out conftest$ac_exeext conftest.$ac_objext conftest.$ac_ext
+fi
+fi
+echo "$as_me:$LINENO: result: $ac_cv_sizeof___int64" >&5
+echo "${ECHO_T}$ac_cv_sizeof___int64" >&6
+cat >>confdefs.h <<_ACEOF
+#define SIZEOF___INT64 $ac_cv_sizeof___int64
+_ACEOF
+
+
+
+# echo $ac_cv_sizeof_long_long
+if test $ac_cv_sizeof_char != 1; then
+ { { echo "$as_me:$LINENO: error: sizeof(char)!=1" >&5
+echo "$as_me: error: sizeof(char)!=1" >&2;}
+ { (exit 1); exit 1; }; }
+fi
+if test $ac_cv_sizeof_short = 2; then
+ ac_cv_pts_int16_t=short
+elif test $ac_cv_sizeof_int = 2; then
+ ac_cv_pts_int16_t=int
+else
+ { { echo "$as_me:$LINENO: error: cannot find inttype: sizeof(inttype)==2" >&5
+echo "$as_me: error: cannot find inttype: sizeof(inttype)==2" >&2;}
+ { (exit 1); exit 1; }; }
+fi
+cat >>confdefs.h <<_ACEOF
+#define PTS_INT16_T $ac_cv_pts_int16_t
+_ACEOF
+
+if test $ac_cv_sizeof_int = 4; then
+ ac_cv_pts_int32_t=int
+elif test $ac_cv_sizeof_long = 4; then
+ ac_cv_pts_int32_t=long
+elif test $ac_cv_sizeof_long -lt 4; then
+ { { echo "$as_me:$LINENO: error: sizeof(long)<4" >&5
+echo "$as_me: error: sizeof(long)<4" >&2;}
+ { (exit 1); exit 1; }; }
+else
+ { { echo "$as_me:$LINENO: error: cannot find inttype: sizeof(inttype)==4" >&5
+echo "$as_me: error: cannot find inttype: sizeof(inttype)==4" >&2;}
+ { (exit 1); exit 1; }; }
+fi
+cat >>confdefs.h <<_ACEOF
+#define PTS_INT32_T $ac_cv_pts_int32_t
+_ACEOF
+
+if test $ac_cv_sizeof_long = 8; then
+ ac_cv_pts_int64_t=long
+elif test $ac_cv_sizeof_long_long = 8; then
+ ac_cv_pts_int64_t="long long"
+elif test $ac_cv_sizeof_very_long = 8; then
+ ac_cv_pts_int64_t="very long"
+elif test $ac_cv_sizeof___int64 = 8; then
+ ac_cv_pts_int64_t="__int64"
+else
+ ac_cv_pts_int64_t=0
+ { echo "$as_me:$LINENO: WARNING: cannot find inttype: sizeof(inttype)==8" >&5
+echo "$as_me: WARNING: cannot find inttype: sizeof(inttype)==8" >&2;}
+fi
+cat >>confdefs.h <<_ACEOF
+#define PTS_INT64_T $ac_cv_pts_int64_t
+_ACEOF
+
+if test $ac_cv_sizeof_long = 16; then
+ ac_cv_pts_int128_t=long
+elif test $ac_cv_sizeof_long_long = 16; then
+ ac_cv_pts_int128_t="long long"
+elif test $ac_cv_sizeof_very_long = 16; then
+ ac_cv_pts_int128_t="very long"
+else
+ ac_cv_pts_int128_t=0
+ { echo "$as_me:$LINENO: WARNING: cannot find inttype: sizeof(inttype)==16" >&5
+echo "$as_me: WARNING: cannot find inttype: sizeof(inttype)==16" >&2;}
+fi
+cat >>confdefs.h <<_ACEOF
+#define PTS_INT128_T $ac_cv_pts_int128_t
+_ACEOF
+
+
+
+
+echo "$as_me:$LINENO: checking size of char *" >&5
+echo $ECHO_N "checking size of char *... $ECHO_C" >&6
+if test "${ac_cv_sizeof_char_p+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ if test "$cross_compiling" = yes; then
+ ac_cv_sizeof_char_p=-1
+else
+ cat >conftest.$ac_ext <<_ACEOF
+#line $LINENO "configure"
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+#include <stdio.h>
+#include <sys/types.h>
+int main() {
+ FILE *f=fopen("conftestval", "w");
+ if (!f) return 1;
+ fprintf(f, "%d\n", sizeof(char *));
+ return 0;
+}
+_ACEOF
+rm -f conftest$ac_exeext
+if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5
+ (eval $ac_link) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } && { ac_try='./conftest$ac_exeext'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; }; then
+ ac_cv_sizeof_char_p=`cat conftestval`
+else
+ echo "$as_me: program exited with status $ac_status" >&5
+echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+( exit $ac_status )
+ac_cv_sizeof_char_p=0
+fi
+rm -f core core.* *.core gmon.out bb.out conftest$ac_exeext conftest.$ac_objext conftest.$ac_ext
+fi
+fi
+echo "$as_me:$LINENO: result: $ac_cv_sizeof_char_p" >&5
+echo "${ECHO_T}$ac_cv_sizeof_char_p" >&6
+cat >>confdefs.h <<_ACEOF
+#define SIZEOF_CHAR_P $ac_cv_sizeof_char_p
+_ACEOF
+
+
+echo "$as_me:$LINENO: checking size of void *" >&5
+echo $ECHO_N "checking size of void *... $ECHO_C" >&6
+if test "${ac_cv_sizeof_void_p+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ if test "$cross_compiling" = yes; then
+ ac_cv_sizeof_void_p=-1
+else
+ cat >conftest.$ac_ext <<_ACEOF
+#line $LINENO "configure"
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+#include <stdio.h>
+#include <sys/types.h>
+int main() {
+ FILE *f=fopen("conftestval", "w");
+ if (!f) return 1;
+ fprintf(f, "%d\n", sizeof(void *));
+ return 0;
+}
+_ACEOF
+rm -f conftest$ac_exeext
+if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5
+ (eval $ac_link) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } && { ac_try='./conftest$ac_exeext'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; }; then
+ ac_cv_sizeof_void_p=`cat conftestval`
+else
+ echo "$as_me: program exited with status $ac_status" >&5
+echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+( exit $ac_status )
+ac_cv_sizeof_void_p=0
+fi
+rm -f core core.* *.core gmon.out bb.out conftest$ac_exeext conftest.$ac_objext conftest.$ac_ext
+fi
+fi
+echo "$as_me:$LINENO: result: $ac_cv_sizeof_void_p" >&5
+echo "${ECHO_T}$ac_cv_sizeof_void_p" >&6
+cat >>confdefs.h <<_ACEOF
+#define SIZEOF_VOID_P $ac_cv_sizeof_void_p
+_ACEOF
+
+
+echo "$as_me:$LINENO: checking for an integral type to hold a ptr" >&5
+echo $ECHO_N "checking for an integral type to hold a ptr... $ECHO_C" >&6
+if test "${ac_cv_pts_intp_t+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+
+if test $ac_cv_sizeof_char_p != $ac_cv_sizeof_void_p; then
+ { { echo "$as_me:$LINENO: error: $ac_cv_sizeof_char_p==sizeof(char*)!=sizeof(void*)" >&5
+echo "$as_me: error: $ac_cv_sizeof_char_p==sizeof(char*)!=sizeof(void*)" >&2;}
+ { (exit 1); exit 1; }; }
+fi
+if test $ac_cv_sizeof_char_p -le 2; then
+ ac_cv_pts_intp_t=$ac_cv_pts_int16_t
+elif test $ac_cv_sizeof_char_p -le 4; then
+ ac_cv_pts_intp_t=$ac_cv_pts_int32_t
+elif test $ac_cv_sizeof_char_p -le 8; then
+ ac_cv_pts_intp_t=$ac_cv_pts_int64_t
+elif test $ac_cv_sizeof_char_p -le 16; then
+ ac_cv_pts_intp_t=$ac_cv_pts_int128_t
+else
+ # :; fi; if true; then
+ echo "$as_me:$LINENO: result: not found!" >&5
+echo "${ECHO_T}not found!" >&6
+ { { echo "$as_me:$LINENO: error: no integral type for sizeof(char*)==$ac_cv_sizeof_char_p" >&5
+echo "$as_me: error: no integral type for sizeof(char*)==$ac_cv_sizeof_char_p" >&2;}
+ { (exit 1); exit 1; }; }
+fi
+
+fi
+cat >>confdefs.h <<_ACEOF
+#define PTS_INTP_T $ac_cv_pts_intp_t
+_ACEOF
+
+echo "$as_me:$LINENO: result: $ac_cv_pts_intp_t" >&5
+echo "${ECHO_T}$ac_cv_pts_intp_t" >&6
+echo "$as_me:$LINENO: checking for ptr <-> integral conversion" >&5
+echo $ECHO_N "checking for ptr <-> integral conversion... $ECHO_C" >&6
+if test "${ac_cv_pts_intp_ok+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+
+ if test "$cross_compiling" = yes; then
+ { { echo "$as_me:$LINENO: error: cross compiling not supported by .._PTS_CHECK_POINTERS" >&5
+echo "$as_me: error: cross compiling not supported by .._PTS_CHECK_POINTERS" >&2;}
+ { (exit 1); exit 1; }; }
+
+else
+ cat >conftest.$ac_ext <<_ACEOF
+#line $LINENO "configure"
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+
+/* #include "confdefs.h" -- automatic */
+int main
+#ifdef __STDC__
+(int argc, char **argv)
+#else
+(argc, argv) int argc; char **argv;
+#endif
+/* #ifndef __cplusplus; #define const; #endif -- automatic config.h */
+ {char const*p="The quick brown fox."+5;
+ PTS_INTP_T i;
+ while (*p!='r') p++; /* prevent compiler optimisations */
+ i=(PTS_INTP_T)p;
+ while (*p!='w') p++; /* prevent compiler optimisations */
+ return p!=(char*)(i+2); }
+
+_ACEOF
+rm -f conftest$ac_exeext
+if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5
+ (eval $ac_link) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } && { ac_try='./conftest$ac_exeext'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; }; then
+ ac_cv_pts_intp_ok=yes
+else
+ echo "$as_me: program exited with status $ac_status" >&5
+echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+( exit $ac_status )
+ac_cv_pts_intp_ok=no
+fi
+rm -f core core.* *.core gmon.out bb.out conftest$ac_exeext conftest.$ac_objext conftest.$ac_ext
+fi
+fi
+if test x"$ac_cv_pts_intp_ok" = xyes; then
+ cat >>confdefs.h <<\_ACEOF
+#define PTS_INTP_OK 1
+_ACEOF
+
+fi
+echo "$as_me:$LINENO: result: $ac_cv_pts_intp_ok" >&5
+echo "${ECHO_T}$ac_cv_pts_intp_ok" >&6
+
+
+
+
+
+
+
+echo "$as_me:$LINENO: checking for integral type size_t" >&5
+echo $ECHO_N "checking for integral type size_t... $ECHO_C" >&6
+if test "${ac_cv_integral_type_size_t+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+
+if test "$cross_compiling" = yes; then
+ { { echo "$as_me:$LINENO: error: cross compiling not supported by .._PTS_CHECK_INTEGRAL_TYPEX" >&5
+echo "$as_me: error: cross compiling not supported by .._PTS_CHECK_INTEGRAL_TYPEX" >&2;}
+ { (exit 1); exit 1; }; }
+
+else
+ cat >conftest.$ac_ext <<_ACEOF
+#line $LINENO "configure"
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+
+#include <stdio.h>
+/* #include "confdefs.h" -- automatic */
+#include <sys/types.h>
+#if STDC_HEADERS
+#include <stdlib.h>
+#include <stddef.h>
+#endif
+#include <stdio.h>
+#if HAVE_UNISTD_H
+#include <unistd.h>
+#endif
+#if HAVE_SYS_SOCKET_H
+#include <sys/socket.h>
+#endif
+#define MY_TYPE size_t
+int main
+#ifdef __STDC__
+(int argc, char **argv)
+#else
+(argc, argv) int argc; char **argv;
+#endif
+{
+ FILE *f=fopen("conftestval", "w");
+ if (!f) return 1;
+ fprintf(f, 0<(MY_TYPE)-1 ? "unsigned " : "signed ");
+ if (sizeof(MY_TYPE)==1) fprintf(f, "char");
+ else if (sizeof(MY_TYPE)==sizeof(char)) fprintf(f, "char");
+ else if (sizeof(MY_TYPE)==sizeof(short)) fprintf(f, "short");
+ else if (sizeof(MY_TYPE)==sizeof(int)) fprintf(f, "int");
+ else if (sizeof(MY_TYPE)==sizeof(long)) fprintf(f, "long");
+ else if (sizeof(MY_TYPE)==sizeof(PTS_INT16_T)) fprintf(f, "PTS_INT16_T");
+ else if (sizeof(MY_TYPE)==sizeof(PTS_INT32_T)) fprintf(f, "PTS_INT32_T");
+ else if (sizeof(MY_TYPE)==sizeof(PTS_INT64_T)) fprintf(f, "PTS_INT64_T");
+ else if (sizeof(MY_TYPE)==sizeof(PTS_INT128_T)) fprintf(f, "PTS_INT128_T");
+ else return 3; /* fprintf(f, "???"); */
+ if (ferror(f)) return 2; /* printf("\n"); */
+ return 0;
+}
+_ACEOF
+rm -f conftest$ac_exeext
+if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5
+ (eval $ac_link) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } && { ac_try='./conftest$ac_exeext'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; }; then
+ ac_cv_integral_type_size_t="`cat conftestval`";
+
+else
+ echo "$as_me: program exited with status $ac_status" >&5
+echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+( exit $ac_status )
+ if test x"unsigned" = x; then echo "$as_me:$LINENO: result: not found" >&5
+echo "${ECHO_T}not found" >&6; { { echo "$as_me:$LINENO: error: This is fatal." >&5
+echo "$as_me: error: This is fatal." >&2;}
+ { (exit 1); exit 1; }; }; fi
+ ac_cv_integral_type_size_t="unsigned"
+ echo -n "substituting "
+
+fi
+rm -f core core.* *.core gmon.out bb.out conftest$ac_exeext conftest.$ac_objext conftest.$ac_ext
+fi
+
+fi
+cat >>confdefs.h <<_ACEOF
+#define PTS_size_t $ac_cv_integral_type_size_t
+_ACEOF
+
+echo "$as_me:$LINENO: result: $ac_cv_integral_type_size_t" >&5
+echo "${ECHO_T}$ac_cv_integral_type_size_t" >&6
+
+
+echo "$as_me:$LINENO: checking size of bool" >&5
+echo $ECHO_N "checking size of bool... $ECHO_C" >&6
+if test "${ac_cv_sizeof_bool+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ if test "$cross_compiling" = yes; then
+ ac_cv_sizeof_bool=-1
+else
+ cat >conftest.$ac_ext <<_ACEOF
+#line $LINENO "configure"
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+#include <stdio.h>
+#include <sys/types.h>
+int main() {
+ FILE *f=fopen("conftestval", "w");
+ if (!f) return 1;
+ fprintf(f, "%d\n", sizeof(bool));
+ return 0;
+}
+_ACEOF
+rm -f conftest$ac_exeext
+if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5
+ (eval $ac_link) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } && { ac_try='./conftest$ac_exeext'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; }; then
+ ac_cv_sizeof_bool=`cat conftestval`
+else
+ echo "$as_me: program exited with status $ac_status" >&5
+echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+( exit $ac_status )
+ac_cv_sizeof_bool=0
+fi
+rm -f core core.* *.core gmon.out bb.out conftest$ac_exeext conftest.$ac_objext conftest.$ac_ext
+fi
+fi
+echo "$as_me:$LINENO: result: $ac_cv_sizeof_bool" >&5
+echo "${ECHO_T}$ac_cv_sizeof_bool" >&6
+cat >>confdefs.h <<_ACEOF
+#define SIZEOF_BOOL $ac_cv_sizeof_bool
+_ACEOF
+
+
+
+
+
+ ac_config_files="$ac_config_files Makehelp"
+cat >confcache <<\_ACEOF
+# This file is a shell script that caches the results of configure
+# tests run on this system so they can be shared between configure
+# scripts and configure runs, see configure's option --config-cache.
+# It is not useful on other systems. If it contains results you don't
+# want to keep, you may remove or edit it.
+#
+# config.status only pays attention to the cache file if you give it
+# the --recheck option to rerun configure.
+#
+# `ac_cv_env_foo' variables (set or unset) will be overridden when
+# loading this file, other *unset* `ac_cv_foo' will be assigned the
+# following values.
+
+_ACEOF
+
+# The following way of writing the cache mishandles newlines in values,
+# but we know of no workaround that is simple, portable, and efficient.
+# So, don't put newlines in cache variables' values.
+# Ultrix sh set writes to stderr and can't be redirected directly,
+# and sets the high bit in the cache file unless we assign to the vars.
+{
+ (set) 2>&1 |
+ case `(ac_space=' '; set | grep ac_space) 2>&1` in
+ *ac_space=\ *)
+ # `set' does not quote correctly, so add quotes (double-quote
+ # substitution turns \\\\ into \\, and sed turns \\ into \).
+ sed -n \
+ "s/'/'\\\\''/g;
+ s/^\\([_$as_cr_alnum]*_cv_[_$as_cr_alnum]*\\)=\\(.*\\)/\\1='\\2'/p"
+ ;;
+ *)
+ # `set' quotes correctly as required by POSIX, so do not add quotes.
+ sed -n \
+ "s/^\\([_$as_cr_alnum]*_cv_[_$as_cr_alnum]*\\)=\\(.*\\)/\\1=\\2/p"
+ ;;
+ esac;
+} |
+ sed '
+ t clear
+ : clear
+ s/^\([^=]*\)=\(.*[{}].*\)$/test "${\1+set}" = set || &/
+ t end
+ /^ac_cv_env/!s/^\([^=]*\)=\(.*\)$/\1=${\1=\2}/
+ : end' >>confcache
+if diff $cache_file confcache >/dev/null 2>&1; then :; else
+ if test -w $cache_file; then
+ test "x$cache_file" != "x/dev/null" && echo "updating cache $cache_file"
+ cat confcache >$cache_file
+ else
+ echo "not updating unwritable cache $cache_file"
+ fi
+fi
+rm -f confcache
+
+test "x$prefix" = xNONE && prefix=$ac_default_prefix
+# Let make expand exec_prefix.
+test "x$exec_prefix" = xNONE && exec_prefix='${prefix}'
+
+# VPATH may cause trouble with some makes, so we remove $(srcdir),
+# ${srcdir} and @srcdir@ from VPATH if srcdir is ".", strip leading and
+# trailing colons and then remove the whole line if VPATH becomes empty
+# (actually we leave an empty line to preserve line numbers).
+if test "x$srcdir" = x.; then
+ ac_vpsub='/^[ ]*VPATH[ ]*=/{
+s/:*\$(srcdir):*/:/;
+s/:*\${srcdir}:*/:/;
+s/:*@srcdir@:*/:/;
+s/^\([^=]*=[ ]*\):*/\1/;
+s/:*$//;
+s/^[^=]*=[ ]*$//;
+}'
+fi
+
+DEFS=-DHAVE_CONFIG_H
+
+ac_libobjs=
+ac_ltlibobjs=
+for ac_i in : $LIBOBJS; do test "x$ac_i" = x: && continue
+ # 1. Remove the extension, and $U if already installed.
+ ac_i=`echo "$ac_i" |
+ sed 's/\$U\././;s/\.o$//;s/\.obj$//'`
+ # 2. Add them.
+ ac_libobjs="$ac_libobjs $ac_i\$U.$ac_objext"
+ ac_ltlibobjs="$ac_ltlibobjs $ac_i"'$U.lo'
+done
+LIBOBJS=$ac_libobjs
+
+LTLIBOBJS=$ac_ltlibobjs
+
+
+
+: ${CONFIG_STATUS=./config.status}
+ac_clean_files_save=$ac_clean_files
+ac_clean_files="$ac_clean_files $CONFIG_STATUS"
+{ echo "$as_me:$LINENO: creating $CONFIG_STATUS" >&5
+echo "$as_me: creating $CONFIG_STATUS" >&6;}
+cat >$CONFIG_STATUS <<_ACEOF
+#! $SHELL
+# Generated by $as_me.
+# Run this file to recreate the current configuration.
+# Compiler output produced by configure, useful for debugging
+# configure, is in config.log if it exists.
+
+debug=false
+ac_cs_recheck=false
+ac_cs_silent=false
+SHELL=\${CONFIG_SHELL-$SHELL}
+_ACEOF
+
+cat >>$CONFIG_STATUS <<\_ACEOF
+## --------------------- ##
+## M4sh Initialization. ##
+## --------------------- ##
+
+# Be Bourne compatible
+if test -n "${ZSH_VERSION+set}" && (emulate sh) >/dev/null 2>&1; then
+ emulate sh
+ NULLCMD=:
+ # Zsh 3.x and 4.x performs word splitting on ${1+"$@"}, which
+ # is contrary to our usage. Disable this feature.
+ alias -g '${1+"$@"}'='"$@"'
+elif test -n "${BASH_VERSION+set}" && (set -o posix) >/dev/null 2>&1; then
+ set -o posix
+fi
+
+# Support unset when possible.
+if (FOO=FOO; unset FOO) >/dev/null 2>&1; then
+ as_unset=unset
+else
+ as_unset=false
+fi
+
+
+# Work around bugs in pre-3.0 UWIN ksh.
+$as_unset ENV MAIL MAILPATH
+PS1='$ '
+PS2='> '
+PS4='+ '
+
+# NLS nuisances.
+for as_var in \
+ LANG LANGUAGE LC_ADDRESS LC_ALL LC_COLLATE LC_CTYPE LC_IDENTIFICATION \
+ LC_MEASUREMENT LC_MESSAGES LC_MONETARY LC_NAME LC_NUMERIC LC_PAPER \
+ LC_TELEPHONE LC_TIME
+do
+ if (set +x; test -n "`(eval $as_var=C; export $as_var) 2>&1`"); then
+ eval $as_var=C; export $as_var
+ else
+ $as_unset $as_var
+ fi
+done
+
+# Required to use basename.
+if expr a : '\(a\)' >/dev/null 2>&1; then
+ as_expr=expr
+else
+ as_expr=false
+fi
+
+if (basename /) >/dev/null 2>&1 && test "X`basename / 2>&1`" = "X/"; then
+ as_basename=basename
+else
+ as_basename=false
+fi
+
+
+# Name of the executable.
+as_me=`$as_basename "$0" ||
+$as_expr X/"$0" : '.*/\([^/][^/]*\)/*$' \| \
+ X"$0" : 'X\(//\)$' \| \
+ X"$0" : 'X\(/\)$' \| \
+ . : '\(.\)' 2>/dev/null ||
+echo X/"$0" |
+ sed '/^.*\/\([^/][^/]*\)\/*$/{ s//\1/; q; }
+ /^X\/\(\/\/\)$/{ s//\1/; q; }
+ /^X\/\(\/\).*/{ s//\1/; q; }
+ s/.*/./; q'`
+
+
+# PATH needs CR, and LINENO needs CR and PATH.
+# Avoid depending upon Character Ranges.
+as_cr_letters='abcdefghijklmnopqrstuvwxyz'
+as_cr_LETTERS='ABCDEFGHIJKLMNOPQRSTUVWXYZ'
+as_cr_Letters=$as_cr_letters$as_cr_LETTERS
+as_cr_digits='0123456789'
+as_cr_alnum=$as_cr_Letters$as_cr_digits
+
+# The user is always right.
+if test "${PATH_SEPARATOR+set}" != set; then
+ echo "#! /bin/sh" >conf$$.sh
+ echo "exit 0" >>conf$$.sh
+ chmod +x conf$$.sh
+ if (PATH="/nonexistent;."; conf$$.sh) >/dev/null 2>&1; then
+ PATH_SEPARATOR=';'
+ else
+ PATH_SEPARATOR=:
+ fi
+ rm -f conf$$.sh
+fi
+
+
+ as_lineno_1=$LINENO
+ as_lineno_2=$LINENO
+ as_lineno_3=`(expr $as_lineno_1 + 1) 2>/dev/null`
+ test "x$as_lineno_1" != "x$as_lineno_2" &&
+ test "x$as_lineno_3" = "x$as_lineno_2" || {
+ # Find who we are. Look in the path if we contain no path at all
+ # relative or not.
+ case $0 in
+ *[\\/]* ) as_myself=$0 ;;
+ *) as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+ IFS=$as_save_IFS
+ test -z "$as_dir" && as_dir=.
+ test -r "$as_dir/$0" && as_myself=$as_dir/$0 && break
+done
+
+ ;;
+ esac
+ # We did not find ourselves, most probably we were run as `sh COMMAND'
+ # in which case we are not to be found in the path.
+ if test "x$as_myself" = x; then
+ as_myself=$0
+ fi
+ if test ! -f "$as_myself"; then
+ { { echo "$as_me:$LINENO: error: cannot find myself; rerun with an absolute path" >&5
+echo "$as_me: error: cannot find myself; rerun with an absolute path" >&2;}
+ { (exit 1); exit 1; }; }
+ fi
+ case $CONFIG_SHELL in
+ '')
+ as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in /bin$PATH_SEPARATOR/usr/bin$PATH_SEPARATOR$PATH
+do
+ IFS=$as_save_IFS
+ test -z "$as_dir" && as_dir=.
+ for as_base in sh bash ksh sh5; do
+ case $as_dir in
+ /*)
+ if ("$as_dir/$as_base" -c '
+ as_lineno_1=$LINENO
+ as_lineno_2=$LINENO
+ as_lineno_3=`(expr $as_lineno_1 + 1) 2>/dev/null`
+ test "x$as_lineno_1" != "x$as_lineno_2" &&
+ test "x$as_lineno_3" = "x$as_lineno_2" ') 2>/dev/null; then
+ $as_unset BASH_ENV || test "${BASH_ENV+set}" != set || { BASH_ENV=; export BASH_ENV; }
+ $as_unset ENV || test "${ENV+set}" != set || { ENV=; export ENV; }
+ CONFIG_SHELL=$as_dir/$as_base
+ export CONFIG_SHELL
+ exec "$CONFIG_SHELL" "$0" ${1+"$@"}
+ fi;;
+ esac
+ done
+done
+;;
+ esac
+
+ # Create $as_me.lineno as a copy of $as_myself, but with $LINENO
+ # uniformly replaced by the line number. The first 'sed' inserts a
+ # line-number line before each line; the second 'sed' does the real
+ # work. The second script uses 'N' to pair each line-number line
+ # with the numbered line, and appends trailing '-' during
+ # substitution so that $LINENO is not a special case at line end.
+ # (Raja R Harinath suggested sed '=', and Paul Eggert wrote the
+ # second 'sed' script. Blame Lee E. McMahon for sed's syntax. :-)
+ sed '=' <$as_myself |
+ sed '
+ N
+ s,$,-,
+ : loop
+ s,^\(['$as_cr_digits']*\)\(.*\)[$]LINENO\([^'$as_cr_alnum'_]\),\1\2\1\3,
+ t loop
+ s,-$,,
+ s,^['$as_cr_digits']*\n,,
+ ' >$as_me.lineno &&
+ chmod +x $as_me.lineno ||
+ { { echo "$as_me:$LINENO: error: cannot create $as_me.lineno; rerun with a POSIX shell" >&5
+echo "$as_me: error: cannot create $as_me.lineno; rerun with a POSIX shell" >&2;}
+ { (exit 1); exit 1; }; }
+
+ # Don't try to exec as it changes $[0], causing all sort of problems
+ # (the dirname of $[0] is not the place where we might find the
+ # original and so on. Autoconf is especially sensible to this).
+ . ./$as_me.lineno
+ # Exit status is that of the last command.
+ exit
+}
+
+
+case `echo "testing\c"; echo 1,2,3`,`echo -n testing; echo 1,2,3` in
+ *c*,-n*) ECHO_N= ECHO_C='
+' ECHO_T=' ' ;;
+ *c*,* ) ECHO_N=-n ECHO_C= ECHO_T= ;;
+ *) ECHO_N= ECHO_C='\c' ECHO_T= ;;
+esac
+
+if expr a : '\(a\)' >/dev/null 2>&1; then
+ as_expr=expr
+else
+ as_expr=false
+fi
+
+rm -f conf$$ conf$$.exe conf$$.file
+echo >conf$$.file
+if ln -s conf$$.file conf$$ 2>/dev/null; then
+ # We could just check for DJGPP; but this test a) works b) is more generic
+ # and c) will remain valid once DJGPP supports symlinks (DJGPP 2.04).
+ if test -f conf$$.exe; then
+ # Don't use ln at all; we don't have any links
+ as_ln_s='cp -p'
+ else
+ as_ln_s='ln -s'
+ fi
+elif ln conf$$.file conf$$ 2>/dev/null; then
+ as_ln_s=ln
+else
+ as_ln_s='cp -p'
+fi
+rm -f conf$$ conf$$.exe conf$$.file
+
+if mkdir -p . 2>/dev/null; then
+ as_mkdir_p=:
+else
+ as_mkdir_p=false
+fi
+
+as_executable_p="test -f"
+
+# Sed expression to map a string onto a valid CPP name.
+as_tr_cpp="sed y%*$as_cr_letters%P$as_cr_LETTERS%;s%[^_$as_cr_alnum]%_%g"
+
+# Sed expression to map a string onto a valid variable name.
+as_tr_sh="sed y%*+%pp%;s%[^_$as_cr_alnum]%_%g"
+
+
+# IFS
+# We need space, tab and new line, in precisely that order.
+as_nl='
+'
+IFS=" $as_nl"
+
+# CDPATH.
+$as_unset CDPATH
+
+exec 6>&1
+
+# Open the log real soon, to keep \$[0] and so on meaningful, and to
+# report actual input values of CONFIG_FILES etc. instead of their
+# values after options handling. Logging --version etc. is OK.
+exec 5>>config.log
+{
+ echo
+ sed 'h;s/./-/g;s/^.../## /;s/...$/ ##/;p;x;p;x' <<_ASBOX
+## Running $as_me. ##
+_ASBOX
+} >&5
+cat >&5 <<_CSEOF
+
+This file was extended by $as_me, which was
+generated by GNU Autoconf 2.57. Invocation command line was
+
+ CONFIG_FILES = $CONFIG_FILES
+ CONFIG_HEADERS = $CONFIG_HEADERS
+ CONFIG_LINKS = $CONFIG_LINKS
+ CONFIG_COMMANDS = $CONFIG_COMMANDS
+ $ $0 $@
+
+_CSEOF
+echo "on `(hostname || uname -n) 2>/dev/null | sed 1q`" >&5
+echo >&5
+_ACEOF
+
+# Files that config.status was made for.
+if test -n "$ac_config_files"; then
+ echo "config_files=\"$ac_config_files\"" >>$CONFIG_STATUS
+fi
+
+if test -n "$ac_config_headers"; then
+ echo "config_headers=\"$ac_config_headers\"" >>$CONFIG_STATUS
+fi
+
+if test -n "$ac_config_links"; then
+ echo "config_links=\"$ac_config_links\"" >>$CONFIG_STATUS
+fi
+
+if test -n "$ac_config_commands"; then
+ echo "config_commands=\"$ac_config_commands\"" >>$CONFIG_STATUS
+fi
+
+cat >>$CONFIG_STATUS <<\_ACEOF
+
+ac_cs_usage="\
+\`$as_me' instantiates files from templates according to the
+current configuration.
+
+Usage: $0 [OPTIONS] [FILE]...
+
+ -h, --help print this help, then exit
+ -V, --version print version number, then exit
+ -q, --quiet do not print progress messages
+ -d, --debug don't remove temporary files
+ --recheck update $as_me by reconfiguring in the same conditions
+ --file=FILE[:TEMPLATE]
+ instantiate the configuration file FILE
+ --header=FILE[:TEMPLATE]
+ instantiate the configuration header FILE
+
+Configuration files:
+$config_files
+
+Configuration headers:
+$config_headers
+
+Report bugs to <bug-autoconf@gnu.org>."
+_ACEOF
+
+cat >>$CONFIG_STATUS <<_ACEOF
+ac_cs_version="\\
+config.status
+configured by $0, generated by GNU Autoconf 2.57,
+ with options \\"`echo "$ac_configure_args" | sed 's/[\\""\`\$]/\\\\&/g'`\\"
+
+Copyright 1992, 1993, 1994, 1995, 1996, 1998, 1999, 2000, 2001
+Free Software Foundation, Inc.
+This config.status script is free software; the Free Software Foundation
+gives unlimited permission to copy, distribute and modify it."
+srcdir=$srcdir
+_ACEOF
+
+cat >>$CONFIG_STATUS <<\_ACEOF
+# If no file are specified by the user, then we need to provide default
+# value. By we need to know if files were specified by the user.
+ac_need_defaults=:
+while test $# != 0
+do
+ case $1 in
+ --*=*)
+ ac_option=`expr "x$1" : 'x\([^=]*\)='`
+ ac_optarg=`expr "x$1" : 'x[^=]*=\(.*\)'`
+ ac_shift=:
+ ;;
+ -*)
+ ac_option=$1
+ ac_optarg=$2
+ ac_shift=shift
+ ;;
+ *) # This is not an option, so the user has probably given explicit
+ # arguments.
+ ac_option=$1
+ ac_need_defaults=false;;
+ esac
+
+ case $ac_option in
+ # Handling of the options.
+_ACEOF
+cat >>$CONFIG_STATUS <<\_ACEOF
+ -recheck | --recheck | --rechec | --reche | --rech | --rec | --re | --r)
+ ac_cs_recheck=: ;;
+ --version | --vers* | -V )
+ echo "$ac_cs_version"; exit 0 ;;
+ --he | --h)
+ # Conflict between --help and --header
+ { { echo "$as_me:$LINENO: error: ambiguous option: $1
+Try \`$0 --help' for more information." >&5
+echo "$as_me: error: ambiguous option: $1
+Try \`$0 --help' for more information." >&2;}
+ { (exit 1); exit 1; }; };;
+ --help | --hel | -h )
+ echo "$ac_cs_usage"; exit 0 ;;
+ --debug | --d* | -d )
+ debug=: ;;
+ --file | --fil | --fi | --f )
+ $ac_shift
+ CONFIG_FILES="$CONFIG_FILES $ac_optarg"
+ ac_need_defaults=false;;
+ --header | --heade | --head | --hea )
+ $ac_shift
+ CONFIG_HEADERS="$CONFIG_HEADERS $ac_optarg"
+ ac_need_defaults=false;;
+ -q | -quiet | --quiet | --quie | --qui | --qu | --q \
+ | -silent | --silent | --silen | --sile | --sil | --si | --s)
+ ac_cs_silent=: ;;
+
+ # This is an error.
+ -*) { { echo "$as_me:$LINENO: error: unrecognized option: $1
+Try \`$0 --help' for more information." >&5
+echo "$as_me: error: unrecognized option: $1
+Try \`$0 --help' for more information." >&2;}
+ { (exit 1); exit 1; }; } ;;
+
+ *) ac_config_targets="$ac_config_targets $1" ;;
+
+ esac
+ shift
+done
+
+ac_configure_extra_args=
+
+if $ac_cs_silent; then
+ exec 6>/dev/null
+ ac_configure_extra_args="$ac_configure_extra_args --silent"
+fi
+
+_ACEOF
+cat >>$CONFIG_STATUS <<_ACEOF
+if \$ac_cs_recheck; then
+ echo "running $SHELL $0 " $ac_configure_args \$ac_configure_extra_args " --no-create --no-recursion" >&6
+ exec $SHELL $0 $ac_configure_args \$ac_configure_extra_args --no-create --no-recursion
+fi
+
+_ACEOF
+
+
+
+
+
+cat >>$CONFIG_STATUS <<\_ACEOF
+for ac_config_target in $ac_config_targets
+do
+ case "$ac_config_target" in
+ # Handling of arguments.
+ "Makehelp" ) CONFIG_FILES="$CONFIG_FILES Makehelp" ;;
+ "config.h" ) CONFIG_HEADERS="$CONFIG_HEADERS config.h" ;;
+ *) { { echo "$as_me:$LINENO: error: invalid argument: $ac_config_target" >&5
+echo "$as_me: error: invalid argument: $ac_config_target" >&2;}
+ { (exit 1); exit 1; }; };;
+ esac
+done
+
+# If the user did not use the arguments to specify the items to instantiate,
+# then the envvar interface is used. Set only those that are not.
+# We use the long form for the default assignment because of an extremely
+# bizarre bug on SunOS 4.1.3.
+if $ac_need_defaults; then
+ test "${CONFIG_FILES+set}" = set || CONFIG_FILES=$config_files
+ test "${CONFIG_HEADERS+set}" = set || CONFIG_HEADERS=$config_headers
+fi
+
+# Have a temporary directory for convenience. Make it in the build tree
+# simply because there is no reason to put it here, and in addition,
+# creating and moving files from /tmp can sometimes cause problems.
+# Create a temporary directory, and hook for its removal unless debugging.
+$debug ||
+{
+ trap 'exit_status=$?; rm -rf $tmp && exit $exit_status' 0
+ trap '{ (exit 1); exit 1; }' 1 2 13 15
+}
+
+# Create a (secure) tmp directory for tmp files.
+
+{
+ tmp=`(umask 077 && mktemp -d -q "./confstatXXXXXX") 2>/dev/null` &&
+ test -n "$tmp" && test -d "$tmp"
+} ||
+{
+ tmp=./confstat$$-$RANDOM
+ (umask 077 && mkdir $tmp)
+} ||
+{
+ echo "$me: cannot create a temporary directory in ." >&2
+ { (exit 1); exit 1; }
+}
+
+_ACEOF
+
+cat >>$CONFIG_STATUS <<_ACEOF
+
+#
+# CONFIG_FILES section.
+#
+
+# No need to generate the scripts if there are no CONFIG_FILES.
+# This happens for instance when ./config.status config.h
+if test -n "\$CONFIG_FILES"; then
+ # Protect against being on the right side of a sed subst in config.status.
+ sed 's/,@/@@/; s/@,/@@/; s/,;t t\$/@;t t/; /@;t t\$/s/[\\\\&,]/\\\\&/g;
+ s/@@/,@/; s/@@/@,/; s/@;t t\$/,;t t/' >\$tmp/subs.sed <<\\CEOF
+s,@SHELL@,$SHELL,;t t
+s,@PATH_SEPARATOR@,$PATH_SEPARATOR,;t t
+s,@PACKAGE_NAME@,$PACKAGE_NAME,;t t
+s,@PACKAGE_TARNAME@,$PACKAGE_TARNAME,;t t
+s,@PACKAGE_VERSION@,$PACKAGE_VERSION,;t t
+s,@PACKAGE_STRING@,$PACKAGE_STRING,;t t
+s,@PACKAGE_BUGREPORT@,$PACKAGE_BUGREPORT,;t t
+s,@exec_prefix@,$exec_prefix,;t t
+s,@prefix@,$prefix,;t t
+s,@program_transform_name@,$program_transform_name,;t t
+s,@bindir@,$bindir,;t t
+s,@sbindir@,$sbindir,;t t
+s,@libexecdir@,$libexecdir,;t t
+s,@datadir@,$datadir,;t t
+s,@sysconfdir@,$sysconfdir,;t t
+s,@sharedstatedir@,$sharedstatedir,;t t
+s,@localstatedir@,$localstatedir,;t t
+s,@libdir@,$libdir,;t t
+s,@includedir@,$includedir,;t t
+s,@oldincludedir@,$oldincludedir,;t t
+s,@infodir@,$infodir,;t t
+s,@mandir@,$mandir,;t t
+s,@build_alias@,$build_alias,;t t
+s,@host_alias@,$host_alias,;t t
+s,@target_alias@,$target_alias,;t t
+s,@DEFS@,$DEFS,;t t
+s,@ECHO_C@,$ECHO_C,;t t
+s,@ECHO_N@,$ECHO_N,;t t
+s,@ECHO_T@,$ECHO_T,;t t
+s,@LIBS@,$LIBS,;t t
+s,@ENABLE_DEBUG@,$ENABLE_DEBUG,;t t
+s,@CXX@,$CXX,;t t
+s,@CXXFLAGS@,$CXXFLAGS,;t t
+s,@LDFLAGS@,$LDFLAGS,;t t
+s,@CPPFLAGS@,$CPPFLAGS,;t t
+s,@ac_ct_CXX@,$ac_ct_CXX,;t t
+s,@EXEEXT@,$EXEEXT,;t t
+s,@OBJEXT@,$OBJEXT,;t t
+s,@GFLAG@,$GFLAG,;t t
+s,@CXXFLAGSB@,$CXXFLAGSB,;t t
+s,@LDXX@,$LDXX,;t t
+s,@pts_cjpeg@,$pts_cjpeg,;t t
+s,@pts_djpeg@,$pts_djpeg,;t t
+s,@pts_tif22pnm@,$pts_tif22pnm,;t t
+s,@pts_tifftopnm@,$pts_tifftopnm,;t t
+s,@pts_pngtopnm@,$pts_pngtopnm,;t t
+s,@pts_gs@,$pts_gs,;t t
+s,@pts_lzw_codec@,$pts_lzw_codec,;t t
+s,@pts_gzip@,$pts_gzip,;t t
+s,@pts_zip@,$pts_zip,;t t
+s,@pts_bash@,$pts_bash,;t t
+s,@pts_make@,$pts_make,;t t
+s,@pts_perl@,$pts_perl,;t t
+s,@CXXCPP@,$CXXCPP,;t t
+s,@EGREP@,$EGREP,;t t
+s,@ALLOCA@,$ALLOCA,;t t
+s,@LIBOBJS@,$LIBOBJS,;t t
+s,@LTLIBOBJS@,$LTLIBOBJS,;t t
+CEOF
+
+_ACEOF
+
+ cat >>$CONFIG_STATUS <<\_ACEOF
+ # Split the substitutions into bite-sized pieces for seds with
+ # small command number limits, like on Digital OSF/1 and HP-UX.
+ ac_max_sed_lines=48
+ ac_sed_frag=1 # Number of current file.
+ ac_beg=1 # First line for current file.
+ ac_end=$ac_max_sed_lines # Line after last line for current file.
+ ac_more_lines=:
+ ac_sed_cmds=
+ while $ac_more_lines; do
+ if test $ac_beg -gt 1; then
+ sed "1,${ac_beg}d; ${ac_end}q" $tmp/subs.sed >$tmp/subs.frag
+ else
+ sed "${ac_end}q" $tmp/subs.sed >$tmp/subs.frag
+ fi
+ if test ! -s $tmp/subs.frag; then
+ ac_more_lines=false
+ else
+ # The purpose of the label and of the branching condition is to
+ # speed up the sed processing (if there are no `@' at all, there
+ # is no need to browse any of the substitutions).
+ # These are the two extra sed commands mentioned above.
+ (echo ':t
+ /@[a-zA-Z_][a-zA-Z_0-9]*@/!b' && cat $tmp/subs.frag) >$tmp/subs-$ac_sed_frag.sed
+ if test -z "$ac_sed_cmds"; then
+ ac_sed_cmds="sed -f $tmp/subs-$ac_sed_frag.sed"
+ else
+ ac_sed_cmds="$ac_sed_cmds | sed -f $tmp/subs-$ac_sed_frag.sed"
+ fi
+ ac_sed_frag=`expr $ac_sed_frag + 1`
+ ac_beg=$ac_end
+ ac_end=`expr $ac_end + $ac_max_sed_lines`
+ fi
+ done
+ if test -z "$ac_sed_cmds"; then
+ ac_sed_cmds=cat
+ fi
+fi # test -n "$CONFIG_FILES"
+
+_ACEOF
+cat >>$CONFIG_STATUS <<\_ACEOF
+for ac_file in : $CONFIG_FILES; do test "x$ac_file" = x: && continue
+ # Support "outfile[:infile[:infile...]]", defaulting infile="outfile.in".
+ case $ac_file in
+ - | *:- | *:-:* ) # input from stdin
+ cat >$tmp/stdin
+ ac_file_in=`echo "$ac_file" | sed 's,[^:]*:,,'`
+ ac_file=`echo "$ac_file" | sed 's,:.*,,'` ;;
+ *:* ) ac_file_in=`echo "$ac_file" | sed 's,[^:]*:,,'`
+ ac_file=`echo "$ac_file" | sed 's,:.*,,'` ;;
+ * ) ac_file_in=$ac_file.in ;;
+ esac
+
+ # Compute @srcdir@, @top_srcdir@, and @INSTALL@ for subdirectories.
+ ac_dir=`(dirname "$ac_file") 2>/dev/null ||
+$as_expr X"$ac_file" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \
+ X"$ac_file" : 'X\(//\)[^/]' \| \
+ X"$ac_file" : 'X\(//\)$' \| \
+ X"$ac_file" : 'X\(/\)' \| \
+ . : '\(.\)' 2>/dev/null ||
+echo X"$ac_file" |
+ sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ s//\1/; q; }
+ /^X\(\/\/\)[^/].*/{ s//\1/; q; }
+ /^X\(\/\/\)$/{ s//\1/; q; }
+ /^X\(\/\).*/{ s//\1/; q; }
+ s/.*/./; q'`
+ { if $as_mkdir_p; then
+ mkdir -p "$ac_dir"
+ else
+ as_dir="$ac_dir"
+ as_dirs=
+ while test ! -d "$as_dir"; do
+ as_dirs="$as_dir $as_dirs"
+ as_dir=`(dirname "$as_dir") 2>/dev/null ||
+$as_expr X"$as_dir" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \
+ X"$as_dir" : 'X\(//\)[^/]' \| \
+ X"$as_dir" : 'X\(//\)$' \| \
+ X"$as_dir" : 'X\(/\)' \| \
+ . : '\(.\)' 2>/dev/null ||
+echo X"$as_dir" |
+ sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ s//\1/; q; }
+ /^X\(\/\/\)[^/].*/{ s//\1/; q; }
+ /^X\(\/\/\)$/{ s//\1/; q; }
+ /^X\(\/\).*/{ s//\1/; q; }
+ s/.*/./; q'`
+ done
+ test ! -n "$as_dirs" || mkdir $as_dirs
+ fi || { { echo "$as_me:$LINENO: error: cannot create directory \"$ac_dir\"" >&5
+echo "$as_me: error: cannot create directory \"$ac_dir\"" >&2;}
+ { (exit 1); exit 1; }; }; }
+
+ ac_builddir=.
+
+if test "$ac_dir" != .; then
+ ac_dir_suffix=/`echo "$ac_dir" | sed 's,^\.[\\/],,'`
+ # A "../" for each directory in $ac_dir_suffix.
+ ac_top_builddir=`echo "$ac_dir_suffix" | sed 's,/[^\\/]*,../,g'`
+else
+ ac_dir_suffix= ac_top_builddir=
+fi
+
+case $srcdir in
+ .) # No --srcdir option. We are building in place.
+ ac_srcdir=.
+ if test -z "$ac_top_builddir"; then
+ ac_top_srcdir=.
+ else
+ ac_top_srcdir=`echo $ac_top_builddir | sed 's,/$,,'`
+ fi ;;
+ [\\/]* | ?:[\\/]* ) # Absolute path.
+ ac_srcdir=$srcdir$ac_dir_suffix;
+ ac_top_srcdir=$srcdir ;;
+ *) # Relative path.
+ ac_srcdir=$ac_top_builddir$srcdir$ac_dir_suffix
+ ac_top_srcdir=$ac_top_builddir$srcdir ;;
+esac
+# Don't blindly perform a `cd "$ac_dir"/$ac_foo && pwd` since $ac_foo can be
+# absolute.
+ac_abs_builddir=`cd "$ac_dir" && cd $ac_builddir && pwd`
+ac_abs_top_builddir=`cd "$ac_dir" && cd ${ac_top_builddir}. && pwd`
+ac_abs_srcdir=`cd "$ac_dir" && cd $ac_srcdir && pwd`
+ac_abs_top_srcdir=`cd "$ac_dir" && cd $ac_top_srcdir && pwd`
+
+
+
+ if test x"$ac_file" != x-; then
+ { echo "$as_me:$LINENO: creating $ac_file" >&5
+echo "$as_me: creating $ac_file" >&6;}
+ rm -f "$ac_file"
+ fi
+ # Let's still pretend it is `configure' which instantiates (i.e., don't
+ # use $as_me), people would be surprised to read:
+ # /* config.h. Generated by config.status. */
+ if test x"$ac_file" = x-; then
+ configure_input=
+ else
+ configure_input="$ac_file. "
+ fi
+ configure_input=$configure_input"Generated from `echo $ac_file_in |
+ sed 's,.*/,,'` by configure."
+
+ # First look for the input files in the build tree, otherwise in the
+ # src tree.
+ ac_file_inputs=`IFS=:
+ for f in $ac_file_in; do
+ case $f in
+ -) echo $tmp/stdin ;;
+ [\\/$]*)
+ # Absolute (can't be DOS-style, as IFS=:)
+ test -f "$f" || { { echo "$as_me:$LINENO: error: cannot find input file: $f" >&5
+echo "$as_me: error: cannot find input file: $f" >&2;}
+ { (exit 1); exit 1; }; }
+ echo $f;;
+ *) # Relative
+ if test -f "$f"; then
+ # Build tree
+ echo $f
+ elif test -f "$srcdir/$f"; then
+ # Source tree
+ echo $srcdir/$f
+ else
+ # /dev/null tree
+ { { echo "$as_me:$LINENO: error: cannot find input file: $f" >&5
+echo "$as_me: error: cannot find input file: $f" >&2;}
+ { (exit 1); exit 1; }; }
+ fi;;
+ esac
+ done` || { (exit 1); exit 1; }
+_ACEOF
+cat >>$CONFIG_STATUS <<_ACEOF
+ sed "$ac_vpsub
+$extrasub
+_ACEOF
+cat >>$CONFIG_STATUS <<\_ACEOF
+:t
+/@[a-zA-Z_][a-zA-Z_0-9]*@/!b
+s,@configure_input@,$configure_input,;t t
+s,@srcdir@,$ac_srcdir,;t t
+s,@abs_srcdir@,$ac_abs_srcdir,;t t
+s,@top_srcdir@,$ac_top_srcdir,;t t
+s,@abs_top_srcdir@,$ac_abs_top_srcdir,;t t
+s,@builddir@,$ac_builddir,;t t
+s,@abs_builddir@,$ac_abs_builddir,;t t
+s,@top_builddir@,$ac_top_builddir,;t t
+s,@abs_top_builddir@,$ac_abs_top_builddir,;t t
+" $ac_file_inputs | (eval "$ac_sed_cmds") >$tmp/out
+ rm -f $tmp/stdin
+ if test x"$ac_file" != x-; then
+ mv $tmp/out $ac_file
+ else
+ cat $tmp/out
+ rm -f $tmp/out
+ fi
+
+done
+_ACEOF
+cat >>$CONFIG_STATUS <<\_ACEOF
+
+#
+# CONFIG_HEADER section.
+#
+
+# These sed commands are passed to sed as "A NAME B NAME C VALUE D", where
+# NAME is the cpp macro being defined and VALUE is the value it is being given.
+#
+# ac_d sets the value in "#define NAME VALUE" lines.
+ac_dA='s,^\([ ]*\)#\([ ]*define[ ][ ]*\)'
+ac_dB='[ ].*$,\1#\2'
+ac_dC=' '
+ac_dD=',;t'
+# ac_u turns "#undef NAME" without trailing blanks into "#define NAME VALUE".
+ac_uA='s,^\([ ]*\)#\([ ]*\)undef\([ ][ ]*\)'
+ac_uB='$,\1#\2define\3'
+ac_uC=' '
+ac_uD=',;t'
+
+for ac_file in : $CONFIG_HEADERS; do test "x$ac_file" = x: && continue
+ # Support "outfile[:infile[:infile...]]", defaulting infile="outfile.in".
+ case $ac_file in
+ - | *:- | *:-:* ) # input from stdin
+ cat >$tmp/stdin
+ ac_file_in=`echo "$ac_file" | sed 's,[^:]*:,,'`
+ ac_file=`echo "$ac_file" | sed 's,:.*,,'` ;;
+ *:* ) ac_file_in=`echo "$ac_file" | sed 's,[^:]*:,,'`
+ ac_file=`echo "$ac_file" | sed 's,:.*,,'` ;;
+ * ) ac_file_in=$ac_file.in ;;
+ esac
+
+ test x"$ac_file" != x- && { echo "$as_me:$LINENO: creating $ac_file" >&5
+echo "$as_me: creating $ac_file" >&6;}
+
+ # First look for the input files in the build tree, otherwise in the
+ # src tree.
+ ac_file_inputs=`IFS=:
+ for f in $ac_file_in; do
+ case $f in
+ -) echo $tmp/stdin ;;
+ [\\/$]*)
+ # Absolute (can't be DOS-style, as IFS=:)
+ test -f "$f" || { { echo "$as_me:$LINENO: error: cannot find input file: $f" >&5
+echo "$as_me: error: cannot find input file: $f" >&2;}
+ { (exit 1); exit 1; }; }
+ echo $f;;
+ *) # Relative
+ if test -f "$f"; then
+ # Build tree
+ echo $f
+ elif test -f "$srcdir/$f"; then
+ # Source tree
+ echo $srcdir/$f
+ else
+ # /dev/null tree
+ { { echo "$as_me:$LINENO: error: cannot find input file: $f" >&5
+echo "$as_me: error: cannot find input file: $f" >&2;}
+ { (exit 1); exit 1; }; }
+ fi;;
+ esac
+ done` || { (exit 1); exit 1; }
+ # Remove the trailing spaces.
+ sed 's/[ ]*$//' $ac_file_inputs >$tmp/in
+
+_ACEOF
+
+# Transform confdefs.h into two sed scripts, `conftest.defines' and
+# `conftest.undefs', that substitutes the proper values into
+# config.h.in to produce config.h. The first handles `#define'
+# templates, and the second `#undef' templates.
+# And first: Protect against being on the right side of a sed subst in
+# config.status. Protect against being in an unquoted here document
+# in config.status.
+rm -f conftest.defines conftest.undefs
+# Using a here document instead of a string reduces the quoting nightmare.
+# Putting comments in sed scripts is not portable.
+#
+# `end' is used to avoid that the second main sed command (meant for
+# 0-ary CPP macros) applies to n-ary macro definitions.
+# See the Autoconf documentation for `clear'.
+cat >confdef2sed.sed <<\_ACEOF
+s/[\\&,]/\\&/g
+s,[\\$`],\\&,g
+t clear
+: clear
+s,^[ ]*#[ ]*define[ ][ ]*\([^ (][^ (]*\)\(([^)]*)\)[ ]*\(.*\)$,${ac_dA}\1${ac_dB}\1\2${ac_dC}\3${ac_dD},gp
+t end
+s,^[ ]*#[ ]*define[ ][ ]*\([^ ][^ ]*\)[ ]*\(.*\)$,${ac_dA}\1${ac_dB}\1${ac_dC}\2${ac_dD},gp
+: end
+_ACEOF
+# If some macros were called several times there might be several times
+# the same #defines, which is useless. Nevertheless, we may not want to
+# sort them, since we want the *last* AC-DEFINE to be honored.
+uniq confdefs.h | sed -n -f confdef2sed.sed >conftest.defines
+sed 's/ac_d/ac_u/g' conftest.defines >conftest.undefs
+rm -f confdef2sed.sed
+
+# This sed command replaces #undef with comments. This is necessary, for
+# example, in the case of _POSIX_SOURCE, which is predefined and required
+# on some systems where configure will not decide to define it.
+cat >>conftest.undefs <<\_ACEOF
+s,^[ ]*#[ ]*undef[ ][ ]*[a-zA-Z_][a-zA-Z_0-9]*,/* & */,
+_ACEOF
+
+# Break up conftest.defines because some shells have a limit on the size
+# of here documents, and old seds have small limits too (100 cmds).
+echo ' # Handle all the #define templates only if necessary.' >>$CONFIG_STATUS
+echo ' if grep "^[ ]*#[ ]*define" $tmp/in >/dev/null; then' >>$CONFIG_STATUS
+echo ' # If there are no defines, we may have an empty if/fi' >>$CONFIG_STATUS
+echo ' :' >>$CONFIG_STATUS
+rm -f conftest.tail
+while grep . conftest.defines >/dev/null
+do
+ # Write a limited-size here document to $tmp/defines.sed.
+ echo ' cat >$tmp/defines.sed <<CEOF' >>$CONFIG_STATUS
+ # Speed up: don't consider the non `#define' lines.
+ echo '/^[ ]*#[ ]*define/!b' >>$CONFIG_STATUS
+ # Work around the forget-to-reset-the-flag bug.
+ echo 't clr' >>$CONFIG_STATUS
+ echo ': clr' >>$CONFIG_STATUS
+ sed ${ac_max_here_lines}q conftest.defines >>$CONFIG_STATUS
+ echo 'CEOF
+ sed -f $tmp/defines.sed $tmp/in >$tmp/out
+ rm -f $tmp/in
+ mv $tmp/out $tmp/in
+' >>$CONFIG_STATUS
+ sed 1,${ac_max_here_lines}d conftest.defines >conftest.tail
+ rm -f conftest.defines
+ mv conftest.tail conftest.defines
+done
+rm -f conftest.defines
+echo ' fi # grep' >>$CONFIG_STATUS
+echo >>$CONFIG_STATUS
+
+# Break up conftest.undefs because some shells have a limit on the size
+# of here documents, and old seds have small limits too (100 cmds).
+echo ' # Handle all the #undef templates' >>$CONFIG_STATUS
+rm -f conftest.tail
+while grep . conftest.undefs >/dev/null
+do
+ # Write a limited-size here document to $tmp/undefs.sed.
+ echo ' cat >$tmp/undefs.sed <<CEOF' >>$CONFIG_STATUS
+ # Speed up: don't consider the non `#undef'
+ echo '/^[ ]*#[ ]*undef/!b' >>$CONFIG_STATUS
+ # Work around the forget-to-reset-the-flag bug.
+ echo 't clr' >>$CONFIG_STATUS
+ echo ': clr' >>$CONFIG_STATUS
+ sed ${ac_max_here_lines}q conftest.undefs >>$CONFIG_STATUS
+ echo 'CEOF
+ sed -f $tmp/undefs.sed $tmp/in >$tmp/out
+ rm -f $tmp/in
+ mv $tmp/out $tmp/in
+' >>$CONFIG_STATUS
+ sed 1,${ac_max_here_lines}d conftest.undefs >conftest.tail
+ rm -f conftest.undefs
+ mv conftest.tail conftest.undefs
+done
+rm -f conftest.undefs
+
+cat >>$CONFIG_STATUS <<\_ACEOF
+ # Let's still pretend it is `configure' which instantiates (i.e., don't
+ # use $as_me), people would be surprised to read:
+ # /* config.h. Generated by config.status. */
+ if test x"$ac_file" = x-; then
+ echo "/* Generated by configure. */" >$tmp/config.h
+ else
+ echo "/* $ac_file. Generated by configure. */" >$tmp/config.h
+ fi
+ cat $tmp/in >>$tmp/config.h
+ rm -f $tmp/in
+ if test x"$ac_file" != x-; then
+ if diff $ac_file $tmp/config.h >/dev/null 2>&1; then
+ { echo "$as_me:$LINENO: $ac_file is unchanged" >&5
+echo "$as_me: $ac_file is unchanged" >&6;}
+ else
+ ac_dir=`(dirname "$ac_file") 2>/dev/null ||
+$as_expr X"$ac_file" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \
+ X"$ac_file" : 'X\(//\)[^/]' \| \
+ X"$ac_file" : 'X\(//\)$' \| \
+ X"$ac_file" : 'X\(/\)' \| \
+ . : '\(.\)' 2>/dev/null ||
+echo X"$ac_file" |
+ sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ s//\1/; q; }
+ /^X\(\/\/\)[^/].*/{ s//\1/; q; }
+ /^X\(\/\/\)$/{ s//\1/; q; }
+ /^X\(\/\).*/{ s//\1/; q; }
+ s/.*/./; q'`
+ { if $as_mkdir_p; then
+ mkdir -p "$ac_dir"
+ else
+ as_dir="$ac_dir"
+ as_dirs=
+ while test ! -d "$as_dir"; do
+ as_dirs="$as_dir $as_dirs"
+ as_dir=`(dirname "$as_dir") 2>/dev/null ||
+$as_expr X"$as_dir" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \
+ X"$as_dir" : 'X\(//\)[^/]' \| \
+ X"$as_dir" : 'X\(//\)$' \| \
+ X"$as_dir" : 'X\(/\)' \| \
+ . : '\(.\)' 2>/dev/null ||
+echo X"$as_dir" |
+ sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ s//\1/; q; }
+ /^X\(\/\/\)[^/].*/{ s//\1/; q; }
+ /^X\(\/\/\)$/{ s//\1/; q; }
+ /^X\(\/\).*/{ s//\1/; q; }
+ s/.*/./; q'`
+ done
+ test ! -n "$as_dirs" || mkdir $as_dirs
+ fi || { { echo "$as_me:$LINENO: error: cannot create directory \"$ac_dir\"" >&5
+echo "$as_me: error: cannot create directory \"$ac_dir\"" >&2;}
+ { (exit 1); exit 1; }; }; }
+
+ rm -f $ac_file
+ mv $tmp/config.h $ac_file
+ fi
+ else
+ cat $tmp/config.h
+ rm -f $tmp/config.h
+ fi
+done
+_ACEOF
+
+cat >>$CONFIG_STATUS <<\_ACEOF
+
+{ (exit 0); exit 0; }
+_ACEOF
+chmod +x $CONFIG_STATUS
+ac_clean_files=$ac_clean_files_save
+
+
+# configure is writing to config.log, and then calls config.status.
+# config.status does its own redirection, appending to config.log.
+# Unfortunately, on DOS this fails, as config.log is still kept open
+# by configure, so config.status won't be able to write to it; its
+# output is simply discarded. So we exec the FD to /dev/null,
+# effectively closing config.log, so it can be properly (re)opened and
+# appended to by config.status. When coming back to configure, we
+# need to make the FD available again.
+if test "$no_create" != yes; then
+ ac_cs_success=:
+ ac_config_status_args=
+ test "$silent" = yes &&
+ ac_config_status_args="$ac_config_status_args --quiet"
+ exec 5>/dev/null
+ $SHELL $CONFIG_STATUS $ac_config_status_args || ac_cs_success=false
+ exec 5>>config.log
+ # Use ||, not &&, to avoid exiting from the if with $? = 1, which
+ # would make configure fail if this is the last instruction.
+ $ac_cs_success || { (exit 1); exit 1; }
+fi
+
+
+rm -f Makedep
+ac_n="${ac_n:-$ECHO_N}"
+echo $ac_n "running make Makedep.force""... $ac_c" 1>&6
+echo "configure:7504: running make Makedep.force" >&5
+if >&5 2>&5 make Makedep.force; then :
+ echo "$as_me:$LINENO: result: ok" >&5
+echo "${ECHO_T}ok" >&6
+
+else
+ echo "$as_me:$LINENO: result: error" >&5
+echo "${ECHO_T}error" >&6
+ { { echo "$as_me:$LINENO: error: cannot compute depends" >&5
+echo "$as_me: error: cannot compute depends" >&2;}
+ { (exit 1); exit 1; }; }
+fi
+
+echo "configure:7517: all OK" >&5
+
+echo "configure done. Now you should run: make; make install"
+
diff --git a/graphics/sam2p/configure.in b/graphics/sam2p/configure.in
new file mode 100644
index 0000000000..08e0ec043d
--- /dev/null
+++ b/graphics/sam2p/configure.in
@@ -0,0 +1,223 @@
+dnl
+dnl configure.in -- for sam2p
+dnl by pts@fazekas.hu at Thu Nov 1 22:46:51 CET 2001
+dnl Mon Mar 4 08:56:35 CET 2002
+dnl
+dnl Dat: autoheader stops reading the file at the 1st error
+dnl Imp: concat (TCL, Ruby)
+dnl Imp: stringify
+dnl Imp: C and C++
+dnl Imp: warnings
+dnl OK : traditional C
+dnl Imp: ctype
+dnl Imp: check for socklen_t
+
+dnl Process this file with autoconf to produce a configure script.
+
+AC_INIT(gensi.cpp)
+AC_CONFIG_HEADER(config.h)
+AC_PTS_ENABLE_DEBUG
+
+AC_MSG_CHECKING([for --enable-lzw])
+AC_ARG_ENABLE(lzw,
+ [ --enable-lzw enable built-in LZW (de)compression (def: no)],
+ [], [])
+if test x1 = x"`perl -e 'print time>1056165811'`"; then
+ # After 19 June 2003: default: yes
+ if test x"$enable_lzw" = x"no"; then
+ AC_MSG_RESULT(no)
+ else
+ AC_MSG_RESULT(yes)
+ AC_DEFINE(USE_BUILTIN_LZW)
+ dnl AC_MSG_WARN(LZW was patented till 19 June 2003; ask permission from Unisys to use it!)
+ fi
+else
+ if test x"$enable_lzw" = x"yes"; then
+ AC_MSG_RESULT(yes)
+ AC_DEFINE(USE_BUILTIN_LZW)
+ AC_MSG_WARN(LZW is patented till 19 June 2003; ask permission from Unisys to use it!)
+ else
+ AC_MSG_RESULT(no)
+ fi
+fi
+
+dnl Sun Jul 7 23:58:11 CEST 2002
+AC_MSG_CHECKING([for --enable-zip])
+AC_ARG_ENABLE(zip,
+ [ --enable-zip enable built-in ZIP compression (def: yes)],
+ [], [])
+if test x"$enable_zip" = x"no"; then
+ AC_MSG_RESULT(no)
+else
+ AC_MSG_RESULT(yes)
+ AC_DEFINE(USE_BUILTIN_ZIP)
+fi
+
+dnl Sun Jul 7 23:58:11 CEST 2002
+AC_MSG_CHECKING([for --enable-fax])
+AC_ARG_ENABLE(fax,
+ [ --enable-fax enable built-in Fax compression (def: yes)],
+ [], [])
+if test x"$enable_fax" = x"no"; then
+ AC_MSG_RESULT(no)
+else
+ AC_MSG_RESULT(yes)
+ AC_DEFINE(USE_BUILTIN_FAXE)
+fi
+
+AC_MSG_CHECKING([for --enable-gif])
+AC_ARG_ENABLE(gif,
+ [ --enable-gif enable reading and writing GIF images (def: no)],
+ [], [])
+if test x"$enable_gif" = x"yes"; then
+ AC_MSG_RESULT(yes)
+ AC_DEFINE(USE_IN_GIF)
+ AC_DEFINE(USE_OUT_GIF)
+ AC_MSG_WARN(GIF is a resistered trademark of Compuserve; ask permission from them to use it!)
+else
+ AC_MSG_RESULT(no)
+fi
+
+dnl Checks for programs.
+dnl AC_PROG_CC
+AC_LANG_CPLUSPLUS
+CXXFLAGS=" "
+dnl ^^^ set it to non-empty, so AC_PROG_CXX won't include `-g'
+CCC="$CCC g++"
+dnl ^^^ check g++ before c++ (see acspecific.m4, grep AC_PROG_CXX)
+AC_PROG_CXX
+
+AC_SUBST(GFLAG)
+if test x"$ac_cv_prog_cxx_g" = xyes; then GFLAG=-g; else GFLAG=""; fi
+dnl ac_cv_prog_cc_g also
+
+AC_PTS_PROG_CXXFLAGS(fs, -fsigned-char)
+AC_PTS_PROG_CXXFLAGS(nrne, -fno-rtti -fno-exceptions)
+dnl ^^^ `g++ -fno-rtti': disables `typeinfo' (??) and run-time type identification
+dnl ^^^ `g++ -fno-exceptions': disables catch and throw
+AC_PTS_PROG_CXXFLAGSB(apwaw, -ansi -pedantic -Wall -W)
+AC_PTS_PROG_CXXFLAGSB(wextra, -Wextra)
+dnl vvv gcc-3.2 gives too many stupid warnings with -Wtraditional
+dnl AC_PTS_PROG_CXXFLAGSB(-Wtraditional)
+AC_PTS_PROG_CXXFLAGSB(ptscxxopts, -felide-constructors -Wstrict-prototypes dnl
+-Wpointer-arith -Wcast-align -Winline dnl
+-Wcast-qual -Wmissing-prototypes)
+AC_PTS_CHECK_IGNORING(nebfcmd,-W -Wall -Wnested-externs -Wbad-function-cast -Wmissing-declarations)
+if test x"$ac_cv_pts_ignoring_nebfcmd" = xyes
+then ac_cv_prog_cxx_nebfcmd=no
+fi
+AC_PTS_PROG_CXXFLAGSB(nebfcmd,-Wnested-externs -Wbad-function-cast -Wmissing-declarations)
+dnl vvv g++ version egcs-2.91.60 + gcc version 2.7.2.3 requires
+dnl `g++ -fno-rtti -fno-exceptions' for AC_PTS_GCC_LINKS_CXX to be `yes'
+AC_PTS_GCC_LINKS_CXX
+
+AC_PTS_WARN_PROG(cjpeg, [cjpeg is required for /Compression/IJG])
+AC_PTS_WARN_PROG(djpeg, [djpeg is required for loading JPEG files])
+AC_PTS_WARN_PROG(tif22pnm, [tif22pnm is required for loading TIFF files])
+AC_PTS_WARN_PROG(tifftopnm, [tifftopnm might become useful for loading TIFF files])
+AC_PTS_WARN_PROG(pngtopnm, [pngtopnm might become useful for loading PNG files])
+dnl AC_PTS_WARN_PROG(gs, [gs is required for /Compression/Fax, and might become recommended for /Compression/ZIP])
+AC_PTS_WARN_PROG(gs, [gs is recommended for viewing PS files[,] and might become recommended for /Compression/ZIP])
+AC_PTS_WARN_PROG(lzw_codec, [lzw_codec might become recommended for /Compression/LZW])
+AC_PTS_WARN_PROG(gzip, [gzip might become useful for /Compression/ZIP])
+AC_PTS_WARN_PROG(zip, [zip might become useful for /Compression/ZIP])
+AC_PTS_ERR_PROG(bash, [bash is required for compiling this program])
+AC_PTS_ERR_PROG(make, [make is required for compiling this program])
+AC_PTS_ERR_PROG(perl, [perl is required for compiling this program])
+dnl AC_PTS_ERR_PROG(touch, [touch is required for compiling this program])
+dnl ^^^ as of 0.37, touch is not required
+
+#AC_CHECK_PROG(ac_pts_cjpeg, cjpeg, yes)
+
+dnl Checks for C/C++ language features
+AC_PTS_HAVE_STDC
+AC_PTS_HAVE_SWITCH_ENUM_BUG
+AC_PTS_ENSURE_ASCII_SYSTEM
+AC_C_CONST
+AC_PTS_C_VOLATILE
+AC_PTS_HAVE_STATIC_CONST
+
+dnl Checks for libraries.
+
+dnl Checks for header files.
+dnl AC_CHECK_HEADERS(stdio.h); exit 42
+dnl AC_CHECK_HEADERS(stdio.h stdlib.h unistd.h string.h strings.h)
+
+dnl Dat: getc_in_stdio fails for uClibc-0.9.14 _and_ `i386-uclibc-gcc -ansi'
+CXXFLAGS_save="$CXXFLAGS"
+CXXFLAGS="$CXXFLAGS -ansi"
+AC_PTS_CHECK_HEADER(stdio.h, getc, getc_in_stdio, [return argc>42? getc(stdin)*0+1:0;])
+AC_PTS_CHECK_HEADER(stdio.h, fgetc, fgetc_in_stdio, [return argc>42?fgetc(stdin)*0+1:0;])
+AC_PTS_CHECK_HEADER(stdio.h, putc, putc_in_stdio, [return argc>42? putc(' ',stdout)*0+1:0;])
+AC_PTS_CHECK_HEADER(stdio.h, fputc, fputc_in_stdio, [return argc>42?fputc(' ',stdout)*0+1:0;])
+CXXFLAGS="$CXXFLAGS_save"
+
+AC_PTS_CHECK_HEADER(stdio.h, sprintf, sprintf_in_stdio, [char s[42]="X"; sprintf(s, "Hello, World!"); return *s!='H';] )
+AC_PTS_CHECK_HEADER(stdlib.h, atoi, atoi_in_stdlib, [return atoi("42")!=42;])
+AC_PTS_CHECK_HEADER(unistd.h, write, write_in_unistd, [return write(1,"what",0)!=0;])
+AC_PTS_CHECK_HEADER(stdlib.h, system, system_in_stdlib, [/*>255 OK*/return system("true")!=0;])
+AC_PTS_CHECK_HEADER(sys/stat.h, lstat, lstat_in_sys_stat,[struct stat st; return 0!=lstat("/",&st);])
+AC_PTS_CHECK_STRING
+AC_PTS_CHECK_MALLOC
+AC_FUNC_ALLOCA
+AC_PTS_CFG_PRINTFGLEN
+AC_PTS_CFG_P_TMPDIR
+AC_PTS_HAVE_POPEN_
+if test $ac_cv_pts_have_popen_ = yes; then
+ ac_cv_pts_have_popen_b=no
+fi
+AC_PTS_HAVE_POPEN_B
+AC_PTS_HAVE_VSNPRINTF
+AC_PTS_HAVE_SYSTEMF
+
+dnl Checks for integral/pointer sizes.
+
+dnl AC_C_CHAR_UNSIGNED
+
+AC_PTS_CHECK_POINTERS
+dnl AC_PTS_CHECK_INTEGRALS -- alread in AC_PTS_CHECK_POINTERS
+dnl AC_REQUIRE([AC_PTS_CHECK_POINTERS])
+dnl AC_REQUIRE([AC_PTS_CHECK_INTEGRALS])
+dnl Dat: POINTERS, INTEGRALS order would result in `(cached)' without AC_REQUIRE
+dnl DAT: newer autoconfs disallow AC_REQUIRE(...) outside macros
+
+dnl ac_cv_alma=korte # Dat: automagically inserted into config.cache
+dnl AC_DEFINE(PTS_INT128_T, 42) # Dat: includes to conftest.h, config.h
+
+dnl cat confdefs.h # Dat: contains already AC_DEFINE()d symbols
+
+dnl Checks for typedefs, structures, and compiler characteristics.
+dnl AC_TYPE_SIZE_T
+AC_PTS_CHECK_INTEGRAL_TYPE(size_t, unsigned)
+dnl AC_PTS_CHECK_INTEGRAL_TYPE(time_t, unsigned)
+dnl AC_PTS_CHECK_INTEGRAL_TYPE(mode_t, int)
+dnl AC_PTS_CHECK_INTEGRAL_TYPE(off_t, long)
+dnl AC_PTS_CHECK_INTEGRAL_TYPE(pid_t, int)
+dnl AC_PTS_CHECK_INTEGRAL_TYPE(dev_t, unsigned long)
+dnl dnl ^^^ Dat: unsigned PTS_INT64_T on Linux i386
+dnl AC_PTS_CHECK_INTEGRAL_TYPE(uid_t, unsigned)
+dnl AC_PTS_CHECK_INTEGRAL_TYPE(gid_t, unsigned)
+dnl AC_PTS_CHECK_INTEGRAL_TYPE(size_tt, signed)
+dnl Dat: AC_TYPE_SIGNAL is OK, there should be no AC_PTS_CHECK_* substitute
+dnl AC_PTS_TYPE_GETGROUPS
+dnl ^^^ doesn't work wth CPPFLAGS=-traditional
+AC_PTS_CHECK_SIZEOF(bool, -1)
+dnl ^^^ Dat: 0 #if (PC: 1, Digital Unix: 8, Solaris: 4)
+dnl ^^^ Dat: autoconf-2.54 AC_CHECK_SIZEOF checks sys/types.h sys/stat.h stdlib.h string.h memory.h strings.h inttypes.h stdint.h unistd.h
+
+dnl Checks for library functions.
+dnl (None!)
+
+dnl Finishing.
+
+dnl AC_OUTPUT(config.h) -- bad!!
+dnl skipping AC_OUTPUT -- bad!!
+AC_OUTPUT(Makehelp)
+
+dnl AC_PTS_RUN_OK([perl -x -S ./ccdep.pl $CXX], [], [AC_MSG_ERROR(cannot compute depends)])
+rm -f Makedep
+AC_PTS_RUN_OK([make Makedep.force], [], [AC_MSG_ERROR(cannot compute depends)])
+AC_PTS_OK
+echo "configure done. Now you should run: make; make install"
+
+dnl end of configure.in
diff --git a/graphics/sam2p/contrib/aprea.ps b/graphics/sam2p/contrib/aprea.ps
new file mode 100644
index 0000000000..6d8ab0b297
--- /dev/null
+++ b/graphics/sam2p/contrib/aprea.ps
@@ -0,0 +1,22 @@
+% anti-setpagedevice preamble by pts@inf.bme.hu in 2002.03.15
+userdict begin
+1 dict dup /ImagingBBox null put
+/setpagedevice where{
+ pop setpagedevice
+ /setpagedevice{% -dict:pagedevice- sp -
+ dup length dict copy
+ dup /PageSize undef dup /ImagingBBox undef
+ dup /HWResolution undef
+ 0}% changed to //setpagedevice in next line
+ dup dup length 1 sub 3 index load put bind 1 index
+ where{dup wcheck{3 1 roll put}{pop def}ifelse}{def}ifelse
+ % ^^^ instead of ef' -- redef at the appropriate place
+ }if
+[/11x17/a3/a4/a4small/b5/ledger/legal/letter/lettersmall/note
+/a0/a1/a2/a5/a6/a7/a8/a9/a10/b0/b1/b2/b3/b4/b5/c0/c1/c2/c3/c4
+/c5/c6/archE/archD/archC/archB/archA/flsa/flse/halfletter
+/tabloid/csheet/dsheet/esheet/executivepage/com10envelope
+/monarchenvelope/c5envelope/dlenvelope/folio/quarto]{
+dup where{dup wcheck{exch{}put}{pop{}def}ifelse}{pop}ifelse
+% ^^^ make these ops a no-op ({}) if they exist
+}forall end% userdict \ No newline at end of file
diff --git a/graphics/sam2p/contrib/sam2p.tk b/graphics/sam2p/contrib/sam2p.tk
new file mode 100644
index 0000000000..99350f9d68
--- /dev/null
+++ b/graphics/sam2p/contrib/sam2p.tk
@@ -0,0 +1,1450 @@
+#!/usr/bin/wish -f
+#
+# sam2p.tk
+# by pts@fazekas.hu at Sat Apr 6 13:14:37 CEST 2002
+#
+# OK: confirm quit
+# Imp: don't update widgets when error in job file
+# Imp: newline mangling when loading/saving files
+# Imp: /DCT, ability to type literal MiniPS code to an `entry'
+# Imp: Perl parser should signal error on <hex123> etc.
+# Imp: B2Press + Move + B2Release; inserts twice
+# Imp: initial `focus'
+# Imp: default values
+# Imp: tk-start with sh
+# Imp: to center of the resized window
+# Imp: tooltips (mouse button 2, 3)
+# Imp: less vertical padding
+# Imp: really detect what kind of -*-fixed fonts we have
+# Dat: TCL 8.0 doesn't have `string equal'
+# Dat: never do `.text mark set sel.first 1.5', beacuse this will override tag `sel'
+# Dat: `entry' widgets don't accept "insert + 1 chars" as a character index
+# Dat: tag-parser treats comments as legal tokens
+# Dat: <Insert> matches <Shift-Insert>, <Key-Insert> does not.
+# Dat: <Motion> is mouse motion event over the sub-window
+# Dat: <Enter> and <Leave> is an event sent when
+# SUXX: Tcl: 8.0 doesn't have [string map ...]
+# SUXX: Tk: radio and checkbuttons cannot be made smaller or larger
+# SUXX: Tk: color for -relief cannot be specified
+# SUXX: Tk: on UNIX, Tk converts "Times New Roman" to "times" unless specified as "-*-times new roman-*-*-*-*-*-*-*-*-*-*-iso8859-1"
+# SUXX: Tk: .text cursor width cannot be extended to the right only (not to the left)
+# SUXX: Tk: .text cannot show the last line on the top unless first==last
+# SUXX: Tk bug: echo `bind . <ButtonRelease-2> {put got}' | wish
+# Test: 1. press button2 2. move mouse 3. release button 4. move mouse
+# `got' is printed twice. Strange: works fine with button 1 and 3.
+# Even the following doesn't help:
+# echo `bind . <B2-ButtonRelease-2> {put got}' | wish
+# Even event parameters are useless to distinguish normal and duplicate
+# events. This is a bug even on all other X11 clients. May be a GPM bug
+# or an xlib bug??
+
+# puts [file type alma]
+
+proc pts_PATH_sep {} {
+ global tcl_platform
+ if {0==[string compare windows $tcl_platform(platform)]} {return ;}
+ return :
+ # Imp: `macintosh'
+}
+
+proc pts_read_ok {filename} {
+ if {0==[string length $filename]} {return 0}
+ if {[catch {set t [file type $filename]}]} {
+ if {[catch {set t [file type [file dirname $filename]]}]} {return !d}
+ return !e
+ }
+ if {0!=[string compare $t file]} {return !f}
+ if {![file readable $filename]} {return !r}
+ return OK
+}
+
+proc pts_write_ok {filename} {
+ if {0==[string length $filename]} {return 0}
+ if {[catch {set t [file type $filename]}]} {
+ if {[catch {set t [file type [set dir [file dirname $filename]]]}]} {return !d}
+ if {0==[string compare $t directory] && [file writable $dir]} {return ++}
+ return !dw
+ }
+ if {0!=[string compare $t file]} {return !f}
+ if {![file writable $filename]} {return !w}
+ return OK
+}
+
+proc pts_direct_bindtags {w} {
+ #** Moves all binds associated with widget $w to directly widget itself.
+ ## Half idea: bindtags $w "$w [bindtags $w]"
+ # Dat: this assumes [lindex [bindtags $w] 0] == $w
+ foreach tag [bindtags $w] {
+ if {0!=[string compare $tag $w]} {
+ foreach evtseq [bind $tag] {
+ bind $w $evtseq [bind $w $evtseq]\n[bind $tag $evtseq]
+ }
+ }
+ }
+ bindtags $w $w
+}
+
+proc pts_readonly {w} {
+ #** @param $w text or entry
+ #** Makes the specified widget read-only. [$w configure -state disabled]
+ #** is not OK, because it makes the insertion cursor invisible.
+ pts_direct_bindtags $w
+ # SUXX: cannot be avoided. Example: we must disable <Key> (typing letters),
+ # but allow <Key-Left>
+ bind $w <Meta-Key-d> break
+ bind $w <Meta-Key-f> break
+ bind $w <Meta-Key-Delete> break
+ bind $w <Meta-Key-BackSpace> break
+ bind $w <Control-Key-d> break
+ bind $w <Control-Key-i> break
+ bind $w <Control-Key-k> break
+ bind $w <Control-Key-h> break
+ bind $w <Control-Key-t> break
+ bind $w <Key-BackSpace> break
+ bind $w <Key-Delete> break
+ bind $w <Key-Return> break
+ bind $w <Key-KP_Enter> break
+ bind $w <Key> break
+ bind $w <<PasteSelection>> break
+ bind $w <<Paste>> break
+ bind $w <<Cut>> break
+ bind $w <<Clear>> break
+}
+
+proc pts_readonly_color {w} {
+ #** Calls [pts_readonly $w], and sets widget colors etc. to make the user
+ #** see that it's a read-only widget.
+ pts_readonly $w
+ $w configure -background [[winfo toplevel $w] cget -background] -relief sunken
+}
+
+proc pts_listrev {list} {
+ # by pts@fazekas.hu at Sun Apr 21 21:08:20 CEST 2002
+ set i [llength $list]
+ set ret {}
+ while {$i>0} {incr i -1; lappend ret [lindex $list $i]}
+ return $ret
+}
+
+proc pts_listrev1 {list} {
+ #** Chops the 1st element of list, and returns the reverse of the rest.
+ # by pts@fazekas.hu at Sun Apr 21 21:08:20 CEST 2002
+ set i [llength $list]
+ set ret {}
+ while {$i>1} {incr i -1; lappend ret [lindex $list $i]}
+ return $ret
+}
+
+## puts [pts_listrev {1 2 {3 4}}]; exit
+
+set pts_unknown_font [font actual ..unknown..]
+proc pts_has_font {f} {
+ # by pts@fazekas.hu at Sat Apr 6 16:26:24 CEST 2002
+ # This is rather dirty, because there is no clean way to test whether a font
+ # exists in Tk.
+ #** return 1 or 0
+ global pts_unknown_font
+ if {0==[string compare fixed $f]} {return 1}
+ if {[string match -*-fixed-* $f]} {return 1} ;# Imp: first `*' shouldn't contain `-'
+ # Dat: pts_unknown_font is `fixed' on UNIX systems...
+ if {0==[string compare $pts_unknown_font [font actual $f]]} {return 0}
+ return 1
+}
+
+proc pts_last_font {first args} {
+ #** @param first,args list of font names (suitable arg for `-font' of widgets)
+ #** @return the last font name that is available
+ for {set i [llength $args]} {$i>0} {} {
+ incr i -1
+ if {[pts_has_font [set f [lindex $args $i]]]} {return $f}
+ }
+ return $first
+}
+
+proc pts_fix_shift_tab {} {
+ # by pts@fazekas.hu at Sat Apr 6 15:22:58 CEST 2002
+ set tmp [bind all <Shift-Key-Tab>]
+ ## puts $tmp
+ if {[string length $tmp]==0} {set tmp {tkTabToWindow [tk_focusPrev %]}}
+ bind all <Shift-Key-Tab> $tmp
+ catch {bind all <Key-ISO_Left_Tab> $tmp}
+ # ^^^ Dat: catch is here because some systems don't have ISO_Left_Tab
+}
+
+proc pts_fix_one_tab {wPath} {
+ # by pts@fazekas.hu at Sat Apr 6 15:38:43 CEST 2002
+ # pts_fix_shift_tab() should be called.
+ bind $wPath <Key-Tab> "[bind all <Key-Tab>]; break"
+ bind $wPath <Shift-Key-Tab> "[bind all <Shift-Key-Tab>]; break"
+ bind $wPath <Key-ISO_Left_Tab> "[bind all <Shift-Key-Tab>]; break"
+}
+
+proc pts_tag_set_first {w tagName index} {
+ if {[$w tag nextrange $tagName 1.0 end] != ""} {
+ if {[$w compare $index < $tagName.last]} {
+ if {[$w compare $index < $tagName.first]} \
+ {$w tag add $tagName $index $tagName.first} \
+ {$w tag remove $tagName $tagName.first $index}
+ } {
+ set tmp [$w index $tagName.last]
+ $w tag remove $tagName 1.0 end
+ $w tag add $tagName $tmp $index
+ }
+ }
+}
+proc pts_tag_set_last {w tagName index} {
+ if {[$w tag nextrange $tagName 1.0 end] != ""} {
+ if {[$w compare $index > $tagName.first]} {
+ if {[$w compare $index > $tagName.last]} \
+ {$w tag add $tagName $tagName.last $index} \
+ {$w tag remove $tagName $index $tagName.last}
+ } {
+ set tmp [$w index $tagName.first]
+ $w tag remove $tagName 1.0 end
+ $w tag add $tagName $index $tmp
+ }
+ }
+}
+
+proc pts_paste {w} {catch {
+ set tmp [$w index insert]
+ $w insert insert [selection get -displayof $w -selection CLIPBOARD]
+ $w tag remove sel 0.1 end
+ $w tag add sel $tmp insert
+}}
+
+proc pts_text_insert_newline {w autoindent} {
+ #** Doesn't respect overstrike mode (neither does Turbo Pascal).
+ #** Does auto-indenting of spaces and tabs.
+ if {[$w cget -state] == "disabled"} {return}
+ if $autoindent {
+ if {![string length [set tmp [$w search -regexp "\[^ \t]" {insert linestart} {insert lineend}]]]} {set tmp "insert lineend"}
+ $w insert insert \n[$w get {insert linestart} $tmp]
+ } {$w insert insert \n}
+ $w see insert
+}
+proc pts_text_autoindent {w bool} {
+ if $bool {} ;# early error message if bool is malformed
+ bind $w <Return> "pts_text_insert_newline %W $bool; break"
+}
+
+# vvv Overriding text.tcl, so we won't clobber the visible selection.
+proc tkTextInsert {w s} {
+ if {($s == "") || ([$w cget -state] == "disabled")} {return}
+ if {[string match "* 1" [bind $w <Insert>]]} {
+ # vvv in overstrike mode, overstrike only in the middle of the line
+ if {[$w compare insert != "insert lineend"]} {$w delete insert}
+ }
+ $w insert insert $s; $w see insert
+}
+
+#proc pts_text_insert {w s overstrike} {
+# if {($s == "") || ([$w cget -state] == "disabled")} {return}
+# set tmp [$w index insert]
+# # vvv in overstrike mode, overstrike only in the middle of the line
+# if {$overstrike && [$w compare insert != "insert lineend"]} {$w delete insert}
+# $w insert insert $s; $w see insert
+#}
+proc pts_text_overstrike {w bool} {
+ #puts [$w configure -insertontime]
+ #puts [$w configure -insertofftime]
+ if {$bool} {$w configure -insertofftime 0} \
+ {$w configure -insertofftime [lindex [$w configure -insertofftime] 3]}
+ # Dat: we cannot override the widget's <KeyPress> method here, because then
+ # we won't be able to receive cursor movement etc. events, see docs in
+ # bindtags(n) and bind(n). So support must be built into tkTextInsert,
+ # since `bind Text <KeyPress> {tkTextInsert %W %A}' is the default.
+ # bind Text <KeyPress> "pts_text_insert %W %A $bool; break ;#alma"
+ focus .; focus $w ;# trick to avoid non-reblinking bug in Tk8.0 Linux.
+}
+proc pts_text_toggle_overstrike {w bool} {
+ if {$bool} {set bool 0} {set bool 1}
+ pts_text_overstrike $w $bool
+ bind $w <Insert> "pts_text_toggle_overstrike %W $bool"
+}
+proc pts_text_auto_overstrike {w bool} {
+ #** Sets overstrike mode, and binds Insert to do the switching. A
+ #** non-blinking cursor indicates overstrike mode. (Tk is too stupid to draw
+ #** a block cursor.)
+ #** @param w a text widget
+ pts_text_overstrike $w $bool
+ bind $w <Key-Insert> "pts_text_toggle_overstrike %W $bool"
+}
+
+# redefine tkScrollButtonDown, so it won't `sunken' the slider
+# (se tcl8.2/scrlbar.tcl)
+proc tkScrollButtonDown {w x y} {
+ global tkPriv
+ set tkPriv(relief) [$w cget -activerelief]
+ if {0==[string compare slider [set element [$w identify $x $y]]]} {
+ tkScrollStartDrag $w $x $y
+ } else {
+ $w configure -activerelief sunken
+ tkScrollSelect $w $element initial
+ }
+}
+proc tkScrollButton2Down {w x y} {
+ global tkPriv
+ set element [$w identify $x $y]
+ if {0==[string compare $element arrow1]||0==[string compare $element arrow2]} {
+ tkScrollButtonDown $w $x $y
+ return
+ }
+ tkScrollToPos $w [$w fraction $x $y]
+ set tkPriv(relief) [$w cget -activerelief]
+ update idletasks
+ # $w configure -activerelief sunken
+ $w activate slider
+ tkScrollStartDrag $w $x $y
+}
+
+option add *Dialog.msg.wrapLength 3i widgetDefault
+proc pts_message_box {args} {
+ global sa_normfont
+ #** similar to tkMessageBox; ignores platform's native MessageBox support.
+ global tkPriv tcl_platform
+
+ set w tkPrivMsgBox
+ upvar #0 $w data
+
+ #
+ # The default value of the title is space (" ") not the empty string
+ # because for some window managers, a
+ # wm title .foo ""
+ # causes the window title to be "foo" instead of the empty string.
+ #
+ set specs {
+ {-default "" "" ""}
+ {-icon "" "" "info"}
+ {-message "" "" ""}
+ {-parent "" "" .}
+ {-title "" "" " "}
+ {-type "" "" "ok"}
+ }
+
+ tclParseConfigSpec $w $specs "" $args
+
+ if {[lsearch {info warning error question} $data(-icon)] == -1} {
+ error "invalid icon \"$data(-icon)\", must be error, info, question or warning"
+ }
+ if {$tcl_platform(platform) == "macintosh"} {
+ if {$data(-icon) == "error"} {
+ set data(-icon) "stop"
+ } elseif {$data(-icon) == "warning"} {
+ set data(-icon) "caution"
+ } elseif {$data(-icon) == "info"} {
+ set data(-icon) "note"
+ }
+ }
+
+ if {![winfo exists $data(-parent)]} {
+ error "bad window path name \"$data(-parent)\""
+ }
+
+ switch -- $data(-type) {
+ abortretryignore {
+ set buttons {
+ {abort -width 6 -text Abort -under 0}
+ {retry -width 6 -text Retry -under 0}
+ {ignore -width 6 -text Ignore -under 0}
+ }
+ }
+ ok {
+ set buttons {
+ {ok -width 6 -text OK -under 0}
+ }
+ if {$data(-default) == ""} {
+ set data(-default) "ok"
+ }
+ }
+ okcancel {
+ set buttons {
+ {ok -width 6 -text OK -under 0}
+ {cancel -width 6 -text Cancel -under 0}
+ }
+ }
+ retrycancel {
+ set buttons {
+ {retry -width 6 -text Retry -under 0}
+ {cancel -width 6 -text Cancel -under 0}
+ }
+ }
+ yesno {
+ set buttons {
+ {yes -width 6 -text Yes -under 0}
+ {no -width 6 -text No -under 0}
+ }
+ }
+ yesnocancel {
+ set buttons {
+ {yes -width 6 -text Yes -under 0}
+ {no -width 6 -text No -under 0}
+ {cancel -width 6 -text Cancel -under 0}
+ }
+ }
+ default {
+ error "invalid message box type \"$data(-type)\", must be abortretryignore, ok, okcancel, retrycancel, yesno or yesnocancel"
+ }
+ }
+
+ if {[string compare $data(-default) ""]} {
+ set valid 0
+ foreach btn $buttons {
+ if {![string compare [lindex $btn 0] $data(-default)]} {
+ set valid 1
+ break
+ }
+ }
+ if {!$valid} {
+ error "invalid default button \"$data(-default)\""
+ }
+ }
+
+ # 2. Set the dialog to be a child window of $parent
+ #
+ #
+ if {[string compare $data(-parent) .]} {
+ set w $data(-parent).__tk__messagebox
+ } else {
+ set w .__tk__messagebox
+ }
+
+ # 3. Create the top-level window and divide it into top
+ # and bottom parts.
+
+ catch {destroy $w}
+ toplevel $w -class Dialog
+ wm title $w $data(-title)
+ wm iconname $w Dialog
+ wm protocol $w WM_DELETE_WINDOW { }
+ wm transient $w $data(-parent)
+ if {$tcl_platform(platform) == "macintosh"} {
+ unsupported1 style $w dBoxProc
+ }
+
+ frame $w.bot
+ pack $w.bot -side bottom -fill both
+ frame $w.top
+ pack $w.top -side top -fill both -expand 1
+ if {$tcl_platform(platform) != "macintosh"} {
+ $w.bot configure -relief raised -bd 1
+ $w.top configure -relief raised -bd 1
+ }
+
+ # 4. Fill the top part with bitmap and message (use the option
+ # database for -wraplength so that it can be overridden by
+ # the caller).
+
+ label $w.msg -justify left -text $data(-message)
+ #catch {$w.msg configure -font \
+ # -Adobe-Times-Medium-R-Normal--*-180-*-*-*-*-*-*
+ #}
+ pack $w.msg -in $w.top -side right -expand 1 -fill both -padx 3m -pady 3m
+ if {$data(-icon) != ""} {
+ label $w.bitmap -bitmap $data(-icon)
+ pack $w.bitmap -in $w.top -side left -padx 3m -pady 3m
+ }
+
+ # 5. Create a row of buttons at the bottom of the dialog.
+
+ set i 0
+ foreach but $buttons {
+ set name [lindex $but 0]
+ set opts [lrange $but 1 end]
+ if {![string compare $opts {}]} {
+ # Capitalize the first letter of $name
+ set capName \
+ [string toupper \
+ [string index $name 0]][string range $name 1 end]
+ set opts [list -text $capName]
+ }
+
+ eval button $w.$name $opts -font $sa_normfont -borderwidth 1 -pady 2 -underline 0 -command [list "set tkPriv(button) $name"]
+
+ if {![string compare $name $data(-default)]} {
+ $w.$name configure -default active
+ }
+ pack $w.$name -in $w.bot -side left -expand 1 \
+ -padx 3m -pady 2m
+
+ # create the binding for the key accelerator, based on the underline
+ #
+ set underIdx [$w.$name cget -under]
+ if {$underIdx >= 0} {
+ set key [string index [$w.$name cget -text] $underIdx]
+ bind $w <Alt-[string tolower $key]> "$w.$name invoke"
+ bind $w <Alt-[string toupper $key]> "$w.$name invoke"
+ }
+ incr i
+ }
+
+ # 6. Create a binding for <Return> on the dialog if there is a
+ # default button.
+
+ if {[string compare $data(-default) ""]} {
+ bind $w <Return> "tkButtonInvoke $w.$data(-default)"
+ }
+
+ # 7. Withdraw the window, then update all the geometry information
+ # so we know how big it wants to be, then center the window in the
+ # display and de-iconify it.
+
+ wm withdraw $w
+ update idletasks
+ set x [expr {[winfo screenwidth $w]/2 - [winfo reqwidth $w]/2 \
+ - [winfo vrootx [winfo parent $w]]}]
+ set y [expr {[winfo screenheight $w]/2 - [winfo reqheight $w]/2 \
+ - [winfo vrooty [winfo parent $w]]}]
+ wm geom $w +$x+$y
+ wm deiconify $w
+
+ # 8. Set a grab and claim the focus too.
+
+ set oldFocus [focus]
+ set oldGrab [grab current $w]
+ if {$oldGrab != ""} {
+ set grabStatus [grab status $oldGrab]
+ }
+ grab $w
+ if {[string compare $data(-default) ""]} {
+ focus $w.$data(-default)
+ } else {
+ focus $w
+ }
+
+ # 9. Wait for the user to respond, then restore the focus and
+ # return the index of the selected button. Restore the focus
+ # before deleting the window, since otherwise the window manager
+ # may take the focus away so we can't redirect it. Finally,
+ # restore any grab that was in effect.
+
+ tkwait variable tkPriv(button)
+ catch {focus $oldFocus}
+ destroy $w
+ if {$oldGrab != ""} {
+ if {$grabStatus == "global"} {
+ grab -global $oldGrab
+ } else {
+ grab $oldGrab
+ }
+ }
+ return $tkPriv(button)
+}
+
+
+# ---
+
+proc sa_radio {framePath variable value labelCaption args} {
+ global $variable sa_normfont
+ # Imp: use -text
+ set $variable ""
+ frame $framePath
+ lappend args -variable $variable -value $value -indicatoron true -borderwidth 1
+ # lappend args -value $value -indicatoron true -borderwidth 1
+ eval "radiobutton $framePath.r $args"
+
+ $framePath.r configure -activebackground [$framePath.r cget -background]
+ label $framePath.l -text $labelCaption -font $sa_normfont ;# Imp: Why doesn't -anchor work??
+ bind $framePath.l <ButtonRelease-1> "$framePath.r invoke"
+ pack $framePath.r $framePath.l -side left
+ # bind $framePath.r <Key-ISO_Left_Tab> {tkTabToWindow [tk_focusPrev %W]}
+}
+#proc sa_radio_pack {framePath} {}
+proc sa_check {wPath variable labelCaption args} {
+ global sa_boldfont
+ # Imp: clicking to the right from the caption shouldn't have effect
+ lappend args -font $sa_boldfont -text $labelCaption -anchor w -borderwidth 1 -variable $variable
+ eval "checkbutton $wPath $args"
+ $wPath configure -activebackground [$wPath cget -background]
+}
+
+proc sa_check_update {wPath variable labelCaption} {
+ sa_check $wPath $variable $labelCaption -command "update_check $variable $wPath"
+}
+
+proc sa_int {framePath variable labelCaption entryWidth args} {
+ # Imp: clicking to the right from the caption shouldn't have effect
+ # Imp: check for int...
+ global sa_normfont sa_boldfont
+ frame $framePath ;# may already exist??
+ label $framePath.l -text $labelCaption -font $sa_boldfont
+ lappend args -relief sunken -width $entryWidth -font $sa_normfont \
+ -borderwidth 1 -foreground black -background white \
+ -selectbackground yellow -selectforeground black -selectborderwidth 0
+ eval "entry $framePath.i $args"
+ pack $framePath.l $framePath.i -side left
+ # $framePath configure -activebackground [$framePath cget -background]
+}
+
+proc sa_w_text {args} {
+ lappend args -relief solid -highlightcolor gray30 \
+ -borderwidth 1 -foreground black -background white \
+ -selectbackground gray85 -selectforeground black -selectborderwidth 0
+ eval "text $args"
+}
+
+proc sa_w_entry {args} {
+ lappend args -relief sunken -borderwidth 1 -foreground black -background white \
+ -selectbackground yellow -selectforeground black -selectborderwidth 0
+ eval "entry $args"
+}
+
+set sa_frame 0
+proc sa_vframe {parentPath} {
+ #** Creates and packs vertical frame, which is 5 pixel high
+ global sa_frame
+ set w $parentPath.saf[incr sa_frame]
+ frame $w -height 5 -width 1
+ pack $w -fill x
+}
+
+# vvv The mouse must be used to insert visible selection (of other apps)
+bind Text <Insert> {}
+
+bind Text <B2-Motion> {}
+bind Text <Button-2> {}
+# puts T[bind Text]T
+
+
+# vvv allow the well-known (almost indrustry standard) Windows/Borland/GTK
+# cliboard key bindings on all platforms
+event add <<Cut>> <Control-Key-x> <Shift-Key-Delete>
+event add <<Copy>> <Control-Key-c> <Control-Key-Insert>
+event add <<Paste>> <Control-Key-v> <Shift-Key-Insert>
+# event add <<PasteSelection>> <ButtonRelease-2>
+# Dat: <<Paste>> is normal, <Control-Key-v> paste, which requires prior
+# <Control-Key-c>. Works across applications.
+# Dat: <<PasteSelection>> is xterm/netscape-like paste, which does not
+# require <Control-Key-c>. Also works across applications.
+
+# vvv this <<Paste>> deletes current selection even on UNIX; but we don't like that
+# bind Text <<Paste>> {catch {%W delete sel.first sel.last}; catch {%W insert insert [selection get -displayof %W -selection CLIPBOARD]}}
+# vvv this <<Paste>> leaves visible selection intact
+# bind Text <<Paste>> {catch {%W insert insert [selection get -displayof %W -selection CLIPBOARD]}}
+# vvv this <<Paste>> sets visible selection to the newly pasted data
+bind Text <<Paste>> {pts_paste %W}
+
+# vvv our <<PasteSelection>> doesn't move the cursor (like xterm, unlike Motif)
+bind Text <<PasteSelection>> {pts_text_paste_selection %W %x %y}
+
+bind Text <B2-Motion> {}
+bind Text <Button-2> {}
+
+# bind Text <ButtonRelease-2> {puts evt; pts_text_paste_selection %W %x %y}
+#catch {
+#event delete <<PasteSelection>> <ButtonRelease-2>
+#}
+#catch {
+#event add <<PasteSelection>> <B2-ButtonRelease-2>
+#event add <<PasteSelection>> <Button-2>
+#}
+
+# puts EI[event info <<PasteSelection>>]
+# puts A[event info <<PasteSelection>>]BN
+
+proc pts_text_paste_selection {w x y} {
+ #** If has focus, than pastes visible selection to the unchanged cursor
+ #** position; otherwise claims focus and sets cursor position to mouse.
+ if {0==[string compare $w [focus -displayof $w]]} {
+ catch {$w insert insert [selection get -displayof $w]}
+ if {0==[string compare normal [$w cget -state]]} {focus $w}
+ } {$w mark set insert [tkTextClosestGap $w $x $y]; focus $w}
+}
+
+
+# vvv overrides text.tcl, doesn't clobber the selection.
+bind Text <1> {tkTextButton1 %W %x %y}
+
+proc ptsTextDelLn W {
+ # puts [%W index {insert linestart}]..[%W index {insert lineend + 1 chars}]
+ if {[$W compare {insert lineend + 1 chars} == end]} {
+ # <Control-y> in the last line must not move the cursor
+ $W delete {insert linestart} {insert lineend}
+ } {
+ $W delete {insert linestart} {insert lineend + 1 chars}
+ }
+}
+
+# vvv Overriding text.tcl, so we won't clobber the visible selection when moving
+# the cursor or just inserting
+proc tkTextSetCursor {w pos} {
+ if {[$w compare $pos == end]} {set pos {end - 1 chars}}
+ $w mark set insert $pos
+ # $w tag remove sel 1.0 end
+ $w see insert
+}
+
+# vvv Overriding text.tcl, so PageUp and PageDown will jump within the page.
+proc tkTextScrollPages {w count} {
+ set tmp [expr {([$w cget -height]-1)*$count}]
+ $w yview scroll $tmp units
+ return "insert + $tmp lines"
+}
+
+# vvv Overrides text.tcl with Turbo Pascal-style Shift+Arrow selection:
+# Shift+Movement-key, when moved _from_ either end of the selection,
+# updates that end appropriately. Otherwise, it clobbers the selection,
+# and creates a new selection from the current `insert' position to the
+# position the cursor is moved to.
+proc tkTextKeySelect {w newIndex} {
+ # puts "[$w index insert] -> [$w index $newIndex] ([$w index end])"
+ if {[$w compare end == $newIndex]} {set newIndex "end - 1 char"}
+ $w mark set anchor insert
+ if {[$w tag nextrange sel 1.0 end] == ""} {
+ if {[$w compare $newIndex < insert]} {$w tag add sel $newIndex insert} {$w tag add sel insert $newIndex}
+ } { # already have a selection
+ # puts "a=[$w index sel.first]-[$w index sel.last] i=[$w index insert]"
+ if {[$w compare insert == sel.first]} {pts_tag_set_first $w sel $newIndex} \
+ elseif {[$w compare insert == sel.last]} {pts_tag_set_last $w sel $newIndex} \
+ { $w tag remove sel 1.0 end
+ if {[$w compare $newIndex < insert]} {$w tag add sel $newIndex insert} {$w tag add sel insert $newIndex}
+ }
+ }
+ $w mark set insert $newIndex; $w see insert
+ update idletasks
+ # puts "[$w tag ranges sel]"
+ # puts "b=[$w index sel.first]-[$w index sel.last] i=[$w index insert]"
+}
+
+# Imp: ^K B: Control-Space, ^K K: Control-Shift-Space
+
+bind Text <Control-Key-y> {ptsTextDelLn %W}
+bind Text <Control-Key-Y> [bind Text <Control-Key-y>]
+bind Text <Control-Key-d> {if {[%W compare {insert + 1 chars} != end]} {%W delete insert}}
+# ^^^ ensures that pressing `Delete' on the last empty line is a no-op
+bind Text <Key-Delete> [bind Text <Control-Key-d>]
+# ^^^ don't clobber visible selection
+bind Text <Key-BackSpace> {if {[%W compare insert != 1.0]} {%W delete insert-1c; %W see insert}}
+# ^^^ don't clobber visible selection
+
+proc pts_entry_Delete {w} {
+ set i 0
+ set j -1
+ set k -1
+ set i [$w index insert]
+ catch {set j [$w index sel.first]}
+ catch {set k [$w index sel.last]}
+ if {0==[string compare $i $j] || 0==[string compare $i $k]} \
+ {$w delete sel.first sel.last} \
+ {$w delete insert}
+}
+
+bind Entry <B2-Motion> {}
+bind Entry <Button-2> {}
+
+# vvv Overrides entry.tcl, so it won't clobber the selection.
+bind Entry <Key-Delete> {pts_entry_Delete %W}
+# vvv Overrides entry.tcl, so it won't clobber the selection.
+bind Entry <Control-Key-d> {pts_entry_Delete %W}
+bind Entry <Control-Key-i> {%W insert insert \t}
+
+# vvv Overrides entry.tcl, so it won't clobber the selection.
+proc tkEntrySetCursor {w pos} {$w icursor $pos; tkEntrySeeInsert $w}
+# vvv Overrides entry.tcl, so it won't clobber the selection.
+proc tkEntryInsert {w s} {if {[string length $s]} {
+ $w insert insert $s
+ tkEntrySeeInsert $w
+}}
+# vvv Overrides entry.tcl with Turbo Pascal look and feel.
+proc tkEntryKeySelect {w new} {
+ if {[$w selection present]} {
+ set i [$w index insert]
+ if {[$w index sel.first]==$i} {$w selection from sel.last} \
+ elseif {[$w index sel.last]==$i} {$w selection from sel.first} \
+ {$w selection from insert}
+ } {$w selection from insert}
+ $w selection to $new
+ $w icursor $new
+ # tkEntrySeeInsert will be called by our caller.
+}
+# vvv Overrides entry.tcl, so it won't clobber the selection.
+proc tkEntryBackspace w {
+ set x [expr {[$w index insert] - 1}]
+ if {$x >= 0} {$w delete $x}
+ if {[$w index @0] >= [$w index insert]} {
+ set range [$w xview]
+ set left [lindex $range 0]
+ set right [lindex $range 1]
+ $w xview moveto [expr {$left - ($right - $left)/2.0}]
+ }
+}
+
+proc pts_entry_paste_selection {w x y} {
+ #** If has focus, than pastes visible selection to the unchanged cursor
+ #** position; otherwise claims focus and sets cursor position to mouse.
+ if {0==[string compare $w [focus -displayof $w]]} {
+ catch {$w insert insert [selection get -displayof $w]}
+ if {0==[string compare normal [$w cget -state]]} {focus $w}
+ } {$w icursor [tkEntryClosestGap $w $x]; focus $w}
+}
+bind Entry <<PasteSelection>> {pts_entry_paste_selection %W %x %y}
+bind Entry <Insert> {} ;# <Shift-Insert> already OK.
+
+
+# vvv override tk.tcl, so it won't select the whole Entry when tab is pressed}
+proc tkTabToWindow w {focus $w}
+
+# ---
+
+# vvv Imp: improve this on Windows
+set sa_normfont [pts_last_font \
+ system variable helvetica \
+ arial {arial -12 normal} \
+ -adobe-helvetica-medium-r-normal--11-*-100-100-*-*-iso8859-* \
+ -adobe-helvetica-medium-r-normal--12-*-75-75-*-*-iso8859-* \
+ sansserif dialog}]
+set sa_boldfont [pts_last_font \
+ sansserif system variable helvetica \
+ arial {arial -12 bold} \
+ -adobe-helvetica-bold-r-normal--12-*-75-75-*-*-iso8859-1 \
+ -adobe-helvetica-bold-r-normal--11-80-100-100-p-60-iso8859-1 \
+ dialogb]
+set sa_fixfont [pts_last_font \
+ fixed systemfixed fixsedsys monospaced monospace \
+ -*-fixed-*-*-*--13-*-*-*-*-*-iso8859-1 \
+ -misc-fixed-medium-r-semicondensed--13-*-75-75-*-*-iso8859-1 \
+ 6x13]
+# puts sa_normfont=$sa_normfont; puts sa_boldfont=$sa_boldfont
+# Dat: 100 DPI, 14-point Helvetica is too large, 11-point is somewhat small
+
+option add *Dialog.msg.font $sa_normfont ;# respected
+option add *Dialog.Button*font $sa_boldfont ;# respected
+
+wm title . {sam2p Job Editor}
+set tk_StrictMotif 0
+pts_fix_shift_tab
+# . configure -bg red
+
+
+frame .gtop
+
+set g .gtop.g0
+frame $g
+
+label $g.lFileFormat -text FileFormat -anchor w -font $sa_boldfont
+sa_radio $g.fPSL1 FileFormat PSL1 "PS L1" -command {update_radio FileFormat PSL1}
+sa_radio $g.fPSLC FileFormat PSLC "PS LC" -command {update_radio FileFormat PSLC}
+sa_radio $g.fPSL2 FileFormat PSL2 "PS L2" -command {update_radio FileFormat PSL2}
+sa_radio $g.fPSL3 FileFormat PSL3 "PS L3" -command {update_radio FileFormat PSL3}
+sa_radio $g.fPDFB10 FileFormat PDFB1.0 "PDF B 1.0" -command {update_radio FileFormat PDFB1.0}
+sa_radio $g.fPDFB12 FileFormat PDFB1.2 "PDF B 1.2" -command {update_radio FileFormat PDFB1.2}
+sa_radio $g.fPDF10 FileFormat PDF1.0 "PDF 1.0" -command {update_radio FileFormat PDF1.0}
+sa_radio $g.fPDF12 FileFormat PDF1.2 "PDF 1.2" -command {update_radio FileFormat PDF1.2}
+sa_radio $g.fGIF89a FileFormat GIF89a "GIF 89a" -command {update_radio FileFormat GIF89a}
+sa_radio $g.fEmpty FileFormat Empty Empty -command {update_radio FileFormat Empty}
+sa_radio $g.fMeta FileFormat Meta Meta -command {update_radio FileFormat Meta}
+sa_radio $g.fPNM FileFormat PNM PNM -command {update_radio FileFormat PNM}
+sa_radio $g.fPAM FileFormat PAM PAM -command {update_radio FileFormat PAM}
+sa_radio $g.fPIP FileFormat PIP PIP -command {update_radio FileFormat PIP}
+sa_radio $g.fJPEG FileFormat JPEG JPEG -command {update_radio FileFormat JPEG}
+sa_radio $g.fTIFF FileFormat TIFF TIFF -command {update_radio FileFormat TIFF}
+sa_radio $g.fPNG FileFormat PNG PNG -command {update_radio FileFormat PNG}
+
+pack $g.lFileFormat -fill x
+pack $g.fPSL1 $g.fPSLC $g.fPSL2 $g.fPSL3 $g.fPDFB10 $g.fPDFB12 $g.fPDF10 $g.fPDF12 $g.fGIF89a \
+ $g.fEmpty $g.fMeta $g.fPNM $g.fPAM $g.fPIP $g.fJPEG $g.fTIFF $g.fPNG -fill x
+frame $g.pFileFormat -height 5 -width 1
+pack $g.pFileFormat -fill x
+
+
+set g .gtop.g1
+frame $g
+
+label $g.lSampleFormat -text SampleFormat -anchor w -font $sa_boldfont
+sa_radio $g.fOpaque SampleFormat Opaque Opaque -command {update_radio SampleFormat Opaque}
+sa_radio $g.fTransparent SampleFormat Transparent Transparent -command {update_radio SampleFormat Transparent}
+sa_radio $g.fGray1 SampleFormat Gray1 "Gray 1" -command {update_radio SampleFormat Gray1}
+sa_radio $g.fIndexed1 SampleFormat Indexed1 "Indexed 1" -command {update_radio SampleFormat Indexed1}
+sa_radio $g.fMask SampleFormat Mask Mask -command {update_radio SampleFormat Mask}
+sa_radio $g.fTransparent2 SampleFormat Transparent2 "Transparent 2" -command {update_radio SampleFormat Transparent2}
+sa_radio $g.fGray2 SampleFormat Gray2 "Gray 2" -command {update_radio SampleFormat Gray2}
+sa_radio $g.fIndexed2 SampleFormat Indexed2 "Indexed 2" -command {update_radio SampleFormat Indexed2}
+sa_radio $g.fTransparent4 SampleFormat Transparent4 "Transparent 4" -command {update_radio SampleFormat Transparent4}
+sa_radio $g.fRGB1 SampleFormat RGB1 "RGB 1" -command {update_radio SampleFormat Rgb1}
+sa_radio $g.fGray4 SampleFormat Gray4 "Gray 4" -command {update_radio SampleFormat Gray4}
+sa_radio $g.fIndexed4 SampleFormat Indexed4 "Indexed 4" -command {update_radio SampleFormat Indexed4}
+sa_radio $g.fTransparent8 SampleFormat Transparent8 "Transparent 8" -command {update_radio SampleFormat Transparent8}
+sa_radio $g.fRgb2 SampleFormat Rgb2 "RGB 2" -command {update_radio SampleFormat Rgb2}
+sa_radio $g.fGray8 SampleFormat Gray8 "Gray 8" -command {update_radio SampleFormat Gray8}
+sa_radio $g.fIndexed8 SampleFormat Indexed8 "Indexed 8" -command {update_radio SampleFormat Indexed8}
+sa_radio $g.fRgb4 SampleFormat Rgb4 "RGB 4" -command {update_radio SampleFormat Rgb4}
+sa_radio $g.fRgb8 SampleFormat Rgb8 "RGB 8" -command {update_radio SampleFormat Rgb8}
+pack $g.lSampleFormat -fill x
+pack $g.fOpaque $g.fTransparent $g.fGray1 $g.fIndexed1 $g.fMask $g.fTransparent2 $g.fGray2 $g.fIndexed2 $g.fTransparent4 \
+ $g.fRGB1 $g.fGray4 $g.fIndexed4 $g.fTransparent8 $g.fRgb2 $g.fGray8 \
+ $g.fIndexed8 $g.fRgb4 $g.fRgb8 -fill x
+frame $g.pSampleFormat -height 5 -width 1
+pack $g.pSampleFormat -fill x
+
+set g .gtop.g2
+frame $g
+
+proc find_val_range {key} {
+ #** @param key for example "/Compression", "/InputFile", of type tKey
+ #** @return "" or [beg end] abs.index of the value associated with that key
+ #** (may span multiple tokens)
+ global jtw ;# text widget containing the tagged job file
+ set end 1.0
+ while {[llength [set lst [$jtw tag nextrange tKey $end]]]} {
+ set beg [lindex $lst 0]
+ set end [lindex $lst 1]
+ ##puts "key=<[$jtw get $beg $end]>"
+ set ikey [$jtw get $beg $end]
+ if {0==[string compare $ikey $key]} {
+
+ ## puts prev=[$jtw tag prevrange tAny $end]
+ set lst [$jtw tag prevrange tAny $end]
+ if {0!=[llength $lst] && [$jtw compare [lindex $lst 0] < $end]
+ && [$jtw compare $end < [lindex $lst 1]]} {
+ set lst [list $end [lindex $lst 1]]
+ } {
+ if {![llength [set lst [$jtw tag nextrange tAny $end]]]} return ""
+ # ^^^ Imp: show error: found, but no value
+ }
+ ##puts "lst=$lst end=$end."
+ ##eval "puts \[$jtw get $lst\]"
+ if {2!=[llength [set tns [$jtw tag names [lindex $lst 0]]]]} return ""
+ # ^^^ Imp: show error: found, but untagged value
+ ##puts LT=[lindex $tns 1]:$tns:
+ if {![llength [set lst [$jtw tag nextrange [lindex $tns 1] $end]]]} return ""
+ # ^^^ This trick is used to find only a single tag. A single tag often
+ # means a single PostScript token, but -- for example `(a)(b)' and
+ # `[]' contain a single tag, but two tokens.
+ # Imp: show better error message
+ set white [$jtw get $end [lindex $lst 0]]
+ ##puts aaa($white)
+ if {[regexp "\[^\\000\011-\015 ]" $white]} return ""
+ # ^^^ Imp: show error: key and value separated by non-whitespace
+ ##puts bbb
+ set beg [lindex $lst 0]
+ set end [lindex $lst 1]
+ set val [$jtw get $beg $end]
+ set openc [expr {2*[string match <<* $val]+[string match \\\[* $val]}] ;# ]
+ ## puts "openc=$openc; val=<$val>"
+ if {$openc} {
+ set end "$beg + $openc chars"
+ set openc 1
+ while {1} {
+ if {![llength [set lst [$jtw tag nextrange tBrac $end]]]} return ""
+ # ^^^ Imp: show error: unclosed >>
+ set val [$jtw get [lindex $lst 0] [lindex $lst 1]]
+ if {[string match <<* $val]} {incr openc; set end 2} \
+ elseif {[string match \\\[* $val]} {incr openc; set end 1} \
+ elseif {[string match >>* $val]} {incr openc -1; set end 2} \
+ elseif {[string match \]* $val]} {incr openc -1; set end 1} \
+ {return ""}
+ # ^^^ Imp: show error: invalid tBrac
+ set end "[lindex $lst 0] + $end chars"
+ if {!$openc} {return "$beg [$jtw index $end]"}
+ }
+ }
+ # puts "val=<$val>"
+ # return [$jtw get $beg $end]
+ return $lst
+ }
+ }
+ return ""
+}
+
+proc update_psval {key newval} {
+ #** return oldval or ""
+ global jtw
+ if {![llength [set found [find_val_range $key]]]} {return ""}
+ set oldval [eval "$jtw get $found"]
+ eval "$jtw delete $found"
+ set found [lindex $found 0]
+ if {[string match /* $newval]} {$jtw insert $found $newval {tAny tNameval}} \
+ elseif {[string match (* $newval]} {$jtw insert $found $newval {tAny tString}} \
+ elseif {[string match \[-0-9\]* $newval]} {$jtw insert $found $newval {tAny tInt}} \
+ {$jtw insert $found $newval {tAny tSing}}
+ $jtw mark set insert "$found + 1 chars"; $jtw see insert
+ return $oldval
+}
+
+proc update_radio {key newval} {
+ global jtw
+ # puts "got=([find_val_range /Compression])"
+ #set found [find_val_range /Hints]
+ # set found [find_val_range /Profile]
+ #puts "found=$found."
+ #puts "is=([$jtw get [lindex $found 0] [lindex $found 1]])."
+ if {![string length [update_psval /$key /$newval]]} {
+ bell
+ pts_message_box -title Warning -message "Cannot find key /$key. Please verify that the .job file is correct."
+ }
+}
+
+proc update_check {key wPath} {
+ set varname [$wPath cget -variable]
+ global $varname
+ if {[set $varname]} {update_psval /$key true} {update_psval /$key false}
+}
+
+#set psstr_map ""
+#proc psstr_map_init {} {
+# for {set i 0} {$i<32} {incr i} {lappend psstr_map [format %c $i] [format \\%02o $i]}
+# for {set i 127} {$i<256} {incr i} {lappend psstr_map [format %c $i] [format \\%02o $i]}
+#}
+#(\\)'
+#psstr_map_init
+#regexp {^[] -'+-[^]+} str
+
+proc pts_psstr_q {str} {
+ #** This would be <60 chars in Perl. TCL is stupid, lame and sloow.
+ set ret ""
+ while {1} {
+ regexp {^[] -'+-[^-~]*} $str head
+ # ^^^ rejects low-unprintable, >=127, backslash, lparen and rparen
+ set ret $ret$head
+ if {[string length $str]==[set headlen [string length $head]]} break
+ scan [string index $str $headlen] %c charcode
+ set ret $ret[format \\%03o [expr {$charcode&255}]]
+ set str [string range $str [expr {1+$headlen}] end]
+ }
+ return $ret
+}
+
+proc update_str {key newval empty} {
+ # Imp: regsub...
+ # set newval [string map $psstr_map $newval]
+ if {[string length $newval]} {set newval ([pts_psstr_q $newval])} {set newval $empty}
+ if {![string length [update_psval /$key $newval]]} {
+ bell
+ pts_message_box -title Warning -message "Cannot find key /$key. Please verify that the .job file is correct."
+ }
+}
+
+proc update_int {key newval empty} {
+ if {[catch {set intval [expr {0+$newval}]}] || [string compare $intval $newval]} {set intval $empty}
+ if {![string length [update_psval /$key $intval]]} {
+ bell
+ pts_message_box -title Warning -message "Cannot find key /$key. Please verify that the .job file is correct."
+ }
+}
+
+proc but_save {} {
+ global jtw jfn
+ set f [open [$jfn get] w]
+ catch {fconfigure $f -encoding binary} ;# TCL 8.2
+ fconfigure $f -translation binary
+ puts -nonewline $f [$jtw get 1.0 end]
+ close $f
+ # bell
+}
+
+set tmpfnb "sam2p_tmp_[pid]"
+
+proc but_relight {} {
+ # Imp: error checks
+ # Imp: \n transl
+ # set f [open |[list tr a-z A-Z >tmp.tmp] w]
+ global jtw tmpfnb
+ set f [open "|perl -I. -Msam2ptol -e sam2ptol::highlight $jtw >$tmpfnb.tjb" w]
+ catch {fconfigure $f -encoding binary} ;# TCL 8.2
+ fconfigure $f -translation binary
+ puts -nonewline $f [$jtw get 1.0 end]
+ close $f
+ set f [open $tmpfnb.tjb r]
+ catch {fconfigure $f -encoding binary} ;# TCL 8.2
+ fconfigure $f -translation binary
+ # puts [read $f]
+ eval [read $f]
+ close $f
+ file delete -- $tmpfnb.tjb
+}
+
+proc but_load {} {
+ global jtw jfn tmpfnb
+ if {[catch {set f [open [$jfn get] r]} err]} {
+ pts_message_box -message "Load failed: $err"
+ } {
+ catch {fconfigure $f -encoding binary} ;# TCL 8.2
+ fconfigure $f -translation binary
+ $jtw delete 1.0 end
+ $jtw insert end [read $f]
+ close $f
+ but_relight
+ # bell
+
+ global InputFile InputFileOK
+ set InputFile ""
+ if {[llength [set found [find_val_range /InputFile]]]} {
+ set val [eval "$jtw get $found"]
+ if {[string match (*) $val]} {
+ # vvv Imp: real PS backslash interpolation, not TCL
+ set InputFile [subst -nocommands -novariables [string range $val 1 [expr {[string length $val]-2}]]]
+ }
+ }
+ set InputFileOK [pts_read_ok $InputFile]
+
+ global OutputFile OutputFileOK
+ set OutputFile ""
+ if {[llength [set found [find_val_range /OutputFile]]]} {
+ set val [eval "$jtw get $found"]
+ if {[string match (*) $val]} {
+ # vvv Imp: real PS backslash interpolation, not TCL
+ set OutputFile [subst -nocommands -novariables [string range $val 1 [expr {[string length $val]-2}]]]
+ }
+ }
+ set OutputFileOK [pts_write_ok $OutputFile]
+
+ global FileFormat
+ set FileFormat ""
+ if {[llength [set found [find_val_range /FileFormat]]]} {
+ set FileFormat [string range [eval "$jtw get $found"] 1 end]
+ }
+
+ global SampleFormat
+ set SampleFormat ""
+ if {[llength [set found [find_val_range /SampleFormat]]]} {
+ set SampleFormat [string range [eval "$jtw get $found"] 1 end]
+ }
+
+ global Compression
+ set Compression ""
+ if {[llength [set found [find_val_range /Compression]]]} {
+ set Compression [string range [eval "$jtw get $found"] 1 end]
+ }
+
+ global TransferEncoding
+ set TransferEncoding ""
+ if {[llength [set found [find_val_range /TransferEncoding]]]} {
+ set TransferEncoding [string range [eval "$jtw get $found"] 1 end]
+ }
+
+ global Predictor
+ set Predictor ""
+ if {[llength [set found [find_val_range /Predictor]]]} {
+ set Predictor [eval "$jtw get $found"]
+ }
+
+ global TransferCPL
+ set TransferCPL ""
+ if {[llength [set found [find_val_range /TransferCPL]]]} {
+ set TransferCPL [eval "$jtw get $found"]
+ }
+
+ global Effort
+ set Effort ""
+ if {[llength [set found [find_val_range /Effort]]]} {
+ set Effort [eval "$jtw get $found"]
+ }
+
+ global RecordSize
+ set RecordSize ""
+ if {[llength [set found [find_val_range /RecordSize]]]} {
+ set RecordSize [eval "$jtw get $found"]
+ }
+
+ global K
+ set K ""
+ if {[llength [set found [find_val_range /K]]]} {
+ set K [eval "$jtw get $found"]
+ }
+
+ global Quality
+ set Quality ""
+ if {[llength [set found [find_val_range /Quality]]]} {
+ set Quality [eval "$jtw get $found"]
+ }
+
+ global WarningOK
+ set WarningOK ""
+ if {[llength [set found [find_val_range /WarningOK]]]} {
+ if {[string compare true [eval "$jtw get $found"]]} {set WarningOK 1} {set WarningOK 1}
+ }
+
+ global TmpRemove
+ set TmpRemove ""
+ if {[llength [set found [find_val_range /TmpRemove]]]} {
+ if {[string compare true [eval "$jtw get $found"]]} {set TmpRemove 1} {set TmpRemove 1}
+ }
+
+ }
+}
+
+proc but_quit {} {
+ if {0==[string compare yes [pts_message_box -type yesno -title {Confirm quit} -message "Quit now, without saving?"]]} exit
+}
+
+proc but_run {} {
+ # by pts@fazekas.hu at Fri Apr 26 23:43:17 CEST 2002
+ global JobFile
+ sa_debug_append "exec sam2p $JobFile:\n"
+ # if {[catch {set ret [exec sam2p $JobFile 2>@ stdout]} ret]} {}
+ if {[catch {set ret [exec sh -c {exec sam2p $1 2>&1} sam2p. $JobFile]} ret]} {
+ set ret "Error running sam2p:\n$ret"
+ }
+ # puts ($ret)
+ sa_debug_append $ret\n\n
+}
+
+# option add *Dialog*Label*font fixed
+# option add *Label*Font times
+#option add *font times
+#option add *$g*font times
+#option add *Dialog.msg.background red
+
+label $g.lCompression -text Compression -anchor w -font $sa_boldfont
+sa_radio $g.fNone Compression None None -command {update_radio Compression None}
+sa_radio $g.fLZW Compression LZW LZW -command {update_radio Compression LZW}
+sa_radio $g.fZIP Compression ZIP ZIP -command {update_radio Compression ZIP}
+sa_int $g.fZIP.fEffort Effort Effort 2 -textvariable Effort
+bind $g.fZIP.fEffort.i <FocusOut> {update_int Effort [%W get] pop}
+pack $g.fZIP.fEffort -side left
+sa_radio $g.fRLE Compression RLE RLE -command {update_radio Compression RLE}
+sa_int $g.fRLE.fRecordSize RecordSize R.S 3 -textvariable RecordSize
+bind $g.fRLE.fRecordSize.i <FocusOut> {update_int RecordSize [%W get] pop}
+pack $g.fRLE.fRecordSize -side left
+sa_radio $g.fFax Compression Fax Fax -command {update_radio Compression Fax}
+sa_int $g.fFax.fK K K 5 -textvariable K
+bind $g.fFax.fK.i <FocusOut> {update_int K [%W get] pop}
+pack $g.fFax.fK -side left
+sa_radio $g.fDCT Compression DCT DCT -command {update_radio Compression DCT}
+sa_radio $g.fIJG Compression IJG IJG -command {update_radio Compression IJG}
+sa_int $g.fIJG.fQuality Quality Q'lty 3 -textvariable Quality
+bind $g.fIJG.fQuality.i <FocusOut> {update_int Quality [%W get] pop}
+pack $g.fIJG.fQuality -side left
+sa_radio $g.fJAI Compression JAI JAI -command {update_radio Compression JAI}
+#label $g.fJAI.haha -text haha
+#pack $g.fJAI.haha -side left
+pack $g.lCompression -fill x
+pack $g.fNone $g.fLZW $g.fZIP $g.fRLE $g.fFax $g.fDCT $g.fIJG $g.fJAI -fill x
+sa_vframe $g
+
+sa_int $g.lPredictor Predictor Predictor 3 -textvariable Predictor
+bind $g.lPredictor.i <FocusOut> {update_int Predictor [%W get] pop}
+pack $g.lPredictor -fill x
+sa_vframe $g
+
+sa_check_update $g.cWarningOK WarningOK WarningOK
+# -textvariable WarningOK
+pack $g.cWarningOK -fill x
+sa_vframe $g
+
+label $g.lTransferEncoding -text TransferEncoding -anchor w -font $sa_boldfont
+sa_radio $g.fBinary TransferEncoding Binary Binary -command {update_radio TransferEncoding Binary}
+sa_radio $g.fASCII TransferEncoding ASCII ASCII -command {update_radio TransferEncoding ASCII}
+sa_radio $g.fHex TransferEncoding Hex Hex -command {update_radio TransferEncoding Hex}
+sa_radio $g.fA85 TransferEncoding A85 A85 -command {update_radio TransferEncoding A85}
+pack $g.lTransferEncoding -fill x
+pack $g.fBinary $g.fASCII $g.fHex $g.fA85 -fill x
+frame $g.pTransferEncoding -height 5 -width 1
+pack $g.pTransferEncoding -fill x
+
+sa_int $g.fTransferCPL TransferCPL TransferCPL 3 -textvariable TransferCPL
+bind $g.fTransferCPL.i <FocusOut> {update_int TransferCPL [%W get] pop}
+
+pack $g.fTransferCPL -fill x
+sa_vframe $g
+
+sa_check_update $g.cTmpRemove TmpRemove {Tmp Remove}
+pack $g.cTmpRemove -fill x
+sa_vframe $g
+
+
+set g .gtop.g3
+frame $g
+
+sa_w_text $g.t -width 58 -height 18 -wrap none -font $sa_fixfont
+pts_fix_one_tab $g.t
+pts_text_autoindent $g.t 1
+pts_text_auto_overstrike $g.t 0
+# $g.t insert end "<<%sam2p job file\n /InputFile (alma)\n /OutputFile (korte)\n /Profile \[\n /Compression /LZW/Predictor 13\n /Hints<</DCT <</a true /b (>>)>> >>\n ]\n>>\n"
+# $g.t insert end [read [open template.job r]]
+# Imp: close file...
+$g.t mark set insert 1.0; $g.t see insert
+$g.t tag configure tAny; $g.t tag lower tAny sel
+$g.t tag configure tSing -foreground "#003f7f"; $g.t tag raise tSing sel
+$g.t tag configure tString -foreground "#007f7f"; $g.t tag raise tString sel
+$g.t tag configure tKey -foreground "#00007f"; $g.t tag raise tKey sel
+$g.t tag configure tNameval -foreground "#0000ff"; $g.t tag raise tNameval sel
+$g.t tag configure tBrac -foreground "#ff0000"; $g.t tag raise tBrac sel
+$g.t tag configure tComment -foreground "#007f00"; $g.t tag raise tComment sel
+$g.t tag configure tInt -foreground "#3f0000"; $g.t tag raise tInt sel
+$g.t tag configure tError -background "#ffdddd"; $g.t tag lower tError sel
+
+# puts X[bindtags $g.t]X
+# puts X[bind $g.t]X
+# puts XZ[bind all]X
+
+set jtw $g.t
+
+# Imp: delete tmp.tmp
+
+# -font sansserif
+# puts [$g.t tag ranges tSing]
+# reground blue
+
+# update idletasks; puts [winfo geometry $g.t] ;# not ready, has to be packed first
+
+frame $g.f
+sa_w_text $g.f.td -width 1 -height 13 -wrap char -font $sa_fixfont \
+ -yscrollcommand "$g.f.sd set" -spacing3 2
+$g.f.td configure -selectbackground yellow ;# override
+scrollbar $g.f.sd -command "$g.f.td yview" -width 11 -elementborderwidth 2 \
+ -relief flat -borderwidth 1 -takefocus 0 -troughcolor gray65
+$g.f.sd configure -activebackground [$g.f.sd cget -background]
+
+# OK: non-editable, but not disabled (we need the cursor!)
+# $g.f.td configure -background [lindex [$g.f.td configure -background] 3]
+pts_readonly_color $g.f.td
+# puts $g.f.td
+# puts TD:[bind .gtop.g3.f.td <Key-Return>]
+
+pts_fix_one_tab $g.f.td
+$g.f.td insert end "Debug messages, sam2p output:\n\n"
+# $g.f.td insert end "0\n1\n2\n3\n4\n5\n6\n7\n8\n9\n10\n11\n12\n13\n14\n15\n16\n17\n18\n19\n"
+# $g.f.td insert end "21\n22\n23\n24\n25\n26\n27\n28\n29\n30\n31\n32\n33\n34\n35\n36\n37\n38\n39\n"
+$g.f.td mark set insert 1.0; $g.f.td see insert
+set debugtext $g.f.td
+
+pack $g.t -expand 0 -fill x
+pack $g.f.td -expand 1 -fill both -side left
+pack $g.f.sd -fill both -side left
+pack $g.f -expand 1 -fill both
+
+pack .gtop.g0 .gtop.g1 .gtop.g2 -side left
+pack .gtop.g3 -expand 1 -fill both -side left
+
+frame .gbot
+frame .gbot.gbl
+
+set g .gbot.gbl.fCurdir
+frame $g
+label $g.l -text "Current dir" -font $sa_boldfont
+sa_w_entry $g.e -font $sa_normfont
+# bind $g.e <FocusOut> {update_str e [%W get] pop}
+pack $g.l -side left
+pack $g.e -expand 1 -fill x -side left
+$g.e insert 0 [pwd]
+
+# puts [bind .gbot.gbl.fCurdir.e]
+
+bind Text <B2-Motion> {}
+bind Text <Button-2> {}
+# puts T[bind Text]T
+# puts [bind Text <Button-2>]
+#puts ([bind Entry <Tab>])
+
+#foreach evtseq [bind Entry] {
+# if {[string match <Key-*> $evtseq]
+# || [string match <*-Key-*> $evtseq]
+# || [string match <*-Key> $evtseq]
+# } {
+# bind $g.e $evtseq {break}
+# puts +:$evtseq
+# } {
+# #puts -:$evtseq
+# }
+#}
+
+# Dat: this assumes [lindex [bindtags $g.e] 0] == $g.e
+#foreach tag [bindtags $g.e] {
+# foreach evtseq [bind $tag] {
+# # if {0==[string length [bind $g.e $evtseq]]} {bind $g.e $evtseq [bind $tag $evtseq]}
+# }
+#}
+
+pts_readonly_color $g.e
+
+
+# event info <<Clear>>
+#bind $g.e <Key-Tab> {# nothing}
+#bind $g.e <Key-ISO_Left_Tab> {# nothing}
+# puts /[bind $g.e]
+# puts :[bind $g.e <Key-Return>]
+
+set g .gbot.gbl.fJobFile
+frame $g
+label $g.l -text JobFile -font $sa_boldfont
+sa_w_entry $g.e -font $sa_normfont -textvariable JobFile
+label $g.r -text OK -font $sa_normfont -textvariable JobFileOK -width 2
+bind $g.e <FocusOut> {set JobFileOK [pts_write_ok $JobFile]}
+set jfn $g.e
+pack $g.l -side left
+pack $g.e -expand 1 -fill x -side left
+pack $g.r -side left
+
+
+set g .gbot.gbl.fInputFile
+frame $g
+label $g.l -text InputFile -font $sa_boldfont
+sa_w_entry $g.e -font $sa_normfont -textvariable InputFile
+label $g.r -text OK -font $sa_normfont -textvariable InputFileOK -width 2
+bind $g.e <FocusOut> {update_str InputFile [%W get] pop; set InputFileOK [pts_read_ok $InputFile]}
+pack $g.l -side left
+pack $g.e -expand 1 -fill x -side left
+pack $g.r -side left
+set InputFileOK [pts_read_ok $InputFile]
+
+set g .gbot.gbl.fOutputFile
+frame $g
+label $g.l -text OutputFile -font $sa_boldfont
+sa_w_entry $g.e -font $sa_normfont -textvariable OutputFile
+label $g.r -text OK -font $sa_normfont -textvariable OutputFileOK -width 2
+bind $g.e <FocusOut> {update_str OutputFile [%W get] pop; set OutputFileOK [pts_write_ok $OutputFile]}
+pack $g.l -side left
+pack $g.e -expand 1 -fill x -side left
+pack $g.r -side left
+
+pack .gbot.gbl.fCurdir .gbot.gbl.fJobFile .gbot.gbl.fInputFile .gbot.gbl.fOutputFile -expand 1 -fill x
+
+frame .gbot.ha
+button .gbot.ha.bLoad -text {Load Job} -font $sa_normfont -borderwidth 1 -pady 2 -underline 0 \
+ -command but_load
+bind . <Alt-Key-l> but_load
+button .gbot.ha.bSave -text {Save Job} -font $sa_normfont -borderwidth 1 -pady 2 -underline 0 \
+ -command but_save
+bind . <Alt-Key-s> but_save
+
+frame .gbot.hb
+button .gbot.hb.bRun -text {Run} -font $sa_normfont -borderwidth 1 -pady 2 -underline 0 \
+ -command but_run
+bind . <Alt-Key-r> but_run
+button .gbot.hb.bQuit -text {Quit} -font $sa_normfont -borderwidth 1 -pady 2 -underline 0 \
+ -command but_quit
+bind . <Alt-Key-q> but_quit
+pack .gbot.gbl -expand 1 -fill x -side left
+pack .gbot.ha.bLoad .gbot.ha.bSave
+pack .gbot.hb.bRun .gbot.hb.bQuit
+pack .gbot.ha .gbot.hb -side left
+
+pack .gtop -expand 1 -fill both
+pack .gbot -expand 0 -fill x
+update idletasks ;# a sima [update] helyett, hogy a "geometry" jó legyen
+scan [wm geometry .] "%dx%d%s" width height tmp
+wm minsize . $width $height
+
+
+set env(PATH) $env(PATH)[pts_PATH_sep].
+#if {[catch {set ret [exec sam2p --help 2>&1]} ret]} {}
+if {[catch {set ret [exec sh -c {exec sam2p --help 2>&1}]} ret]} {
+ set ret "Error:\n$ret"
+}
+
+proc sa_debug_append msg {
+ global debugtext
+ $debugtext insert end $msg
+ $debugtext mark set insert end
+ $debugtext see insert
+}
+
+sa_debug_append $ret\n\n
+# puts ($ret)
+
+
+$jfn delete 0 end
+if {[llength $argv]} {$jfn insert 0 [lindex $argv 0]; but_load} {
+ $jfn insert 0 template.job; but_load; $jfn delete 0 end
+ set InputFileOK 0
+ set OutputFileOK 0
+ set JobFileOK 0
+}
+# set InputFile hello
+# but_load
+# puts $argv
+# puts TD:[bind .gtop.g3.f.td <Key-Return>]
+
+
+#__END__
diff --git a/graphics/sam2p/contrib/sam2ptol.pm b/graphics/sam2p/contrib/sam2ptol.pm
new file mode 100644
index 0000000000..8c73da50fc
--- /dev/null
+++ b/graphics/sam2p/contrib/sam2ptol.pm
@@ -0,0 +1,77 @@
+# sam2ptol.pm by pts@math.bme.hu at Sun Apr 7 14:48:27 CEST 2002
+package sam2ptol;
+BEGIN{$^W=1}
+use integer;
+use strict;
+
+my %keys=qw{/InputFile 1 /OutputFile 1 /TmpRemove 1 /Profile 1
+ /FileFormat 1 /SampleFormat 1 /WarningOK 1 /TransferEncoding 1 /Compression 1
+ /Predictor 1 /Transparent 1 /Hints 1
+ /Effort 1 /RecordSize 1 /K 1 /Quality 1 /ColorTransform 1 /TransferCPL 1
+ /EncoderColumns 1 /EncoderRows 1 /EncoderColors 1
+ /PredictorColumns 1 /PredictorBPC 1 /PredictorColors 1
+ /Comment 1 /Title 1 /Subject 1 /Author 1 /Creator 1 /Producer 1
+ /Created 1 /Produced 1 /LoadHints 1 /Templates 1};
+# Dat: DCT is not key!
+my %values=qw{
+ /PSL1 1 /PSLC 1 /PSL2 1 /PSL3 1 /PDFB1.0 1 /PDFB1.2 1 /PDF1.0 1 /PDF1.2 1
+ /GIF89a 1 /Empty 1 /Meta 1 /PNM 1 /PAM 1 /PIP 1 /Opaque 1 /Transparent 1
+ /Transparent2 1 /Transparent4 1 /Transparent8 1 /Gray1 1 /Gray2 1 /Gray4 1
+ /Gray8 1 /Indexed1 1 /Indexed2 1 /Indexed4 1 /Indexed8 1 /Mask 1 /Rgb1 1
+ /Rgb2 1 /Rgb4 1 /Rgb8 1 /RGB1 1 /RGB2 1 /RGB4 1 /RGB8 1 /Asis 1 /Binary 1
+ /ASCII 1 /Hex 1 /AHx 1 /ASCIIHex 1 /A85 1 /ASCII85 1 /None 1 /LZW 1 /ZIP 1
+ /Flate 1 /Fl 1 /RLE 1 /RunLength 1 /RunLengthEncoded 1 /RL 1 /PackBits 1
+ /Fax 1 /CCITTFax 1 /CCF 1 /DCT 1 /JPEG 1 /JPG 1 /JFIF 1 /IJG 1 /JAI 1
+};
+
+sub highlight {
+ #** Example: perl -I. -Msam2ptol -e sam2ptol::highlight alma <examples/a_jpg.job
+ die "$0: 1arg, tclPath expected\n" if @ARGV!=1;
+ my $w=$ARGV[0]; # name of the widget
+ $_=join'',<STDIN>;
+ my($beg,$end,$c,$ta,$tb);
+ for (qw{tError tInt tComment tString tSing tKey tNameval tBrac}) { print "$w tag remove tString 1.0 end\n" }
+ while (m@(
+ \((\\.|[^\\()]+)*\) # String. Imp: nesting??
+ |/([^\000-\040/\%{}<>\[\]()\177-\377]*) # Sname
+ |[_A-Za-z_]([^\000-\040/\%{}<>\[\]()\177-\377]*) # Ename
+ |<<|>>|\[|\]
+ |true|false|pop|null
+ |%[^\r\n]*
+ |-?\d+
+ )@gsx) {
+ my $e=$1;
+ $beg=($end=pos())-length($e);
+ $c=substr($e,0,1);
+ $ta="$w tag add"; $tb=" {1.0 + $beg chars} {1.0 + $end chars}\n";
+ if ($c eq'/') {
+ if (exists $keys{$e}) {
+ print "$ta tKey$tb";
+ # print STDERR "($e)\n";
+ } elsif (exists $values{$e}) {
+ print "$ta tNameval$tb";
+ } else {
+ print "$ta tError$tb";
+ }
+ } elsif ($c eq'(') {
+ print "$ta tString$tb";
+ print "$w tag add tString {1.0 + $beg chars} {1.0 + $end chars}\n"
+ } elsif ($e eq'true' or $e eq'false' or $e eq'pop' or $e eq'null') {
+ print "$ta tSing$tb";
+ } elsif ($e=~/\A[_A-Za-z]/) {
+ # } elsif ($e=~/\A\w/) {
+ # print STDERR "($e)\n";
+ print "$ta tError$tb";
+ } elsif ($c eq'%') {
+ print "$ta tComment$tb";
+ } elsif ($c eq'-' or ord($c)>=ord('0') and ord($c)<=ord('9')) {
+ print "$ta tInt$tb";
+ } else {
+ print "$ta tBrac$tb";
+ }
+ print "$ta tAny$tb";
+ # print "[".pos()."]\n";
+ }
+}
+
+1;
diff --git a/graphics/sam2p/contrib/template.job b/graphics/sam2p/contrib/template.job
new file mode 100644
index 0000000000..751846d499
--- /dev/null
+++ b/graphics/sam2p/contrib/template.job
@@ -0,0 +1,33 @@
+<<%sam2p job file template (.cpp code is _not_ generated from this)
+ /InputFile pop
+ /OutputFile pop
+ /TmpRemove true /LoadHints pop /Templates pop
+ /Profile [<<
+ /FileFormat pop
+ /SampleFormat pop
+ /WarningOK true
+ /TransferEncoding pop
+ /Compression /None
+ /Predictor 1
+ /Transparent null
+ /Hints <<
+ /Effort -1
+ /RecordSize 0
+ /K 0
+ /Quality 75
+ /ColorTransform pop
+ /TransferCPL 78
+ /DCT <<>>
+ /EncoderColumns 0 /EncoderRows 0 /EncoderColors 0
+ /PredictorColumns 0 /PredictorBPC 0 /PredictorColors 0
+ /Comment pop
+ /Title pop
+ /Subject pop
+ /Author pop
+ /Creator pop
+ /Producer pop
+ /Created pop
+ /Produced pop
+ >>
+ >>]
+>>% __EOF__
diff --git a/graphics/sam2p/crc32.c b/graphics/sam2p/crc32.c
new file mode 100644
index 0000000000..c321656cc0
--- /dev/null
+++ b/graphics/sam2p/crc32.c
@@ -0,0 +1,144 @@
+/* crc32.c -- compute the CRC-32 of a data stream
+ * Ripped from the zip sources:
+ * Copyright (C) 1995 Mark Adler
+ * For conditions of distribution and use, see copyright notice in zlib.h
+ */
+
+/* $Id: crc32.c,v 1.2 2002/12/11 14:01:52 pts Exp $ */
+
+#ifdef __GNUC__
+#ifndef __clang__
+#pragma implementation
+#endif
+#endif
+#if OBJDEP
+# warning PROVIDES: crc32
+#endif
+
+/*#include "zip.h"*/
+/* #ifndef USE_ZLIB */
+#include "crc32.h"
+
+#define ZCONST PTS_const
+
+#ifdef CRC32
+# undef CRC32
+#endif
+#define CRC32(c, b) (crc_table[((int)(c) ^ (b)) & 0xff] ^ ((c) >> 8))
+#define DO1(buf) crc = CRC32(crc, *(unsigned char ZCONST*)buf++)
+#define DO2(buf) DO1(buf); DO1(buf)
+#define DO4(buf) DO2(buf); DO2(buf)
+#define DO8(buf) DO4(buf); DO4(buf)
+
+#undef NO_UNROLLED_LOOPS
+#define local static
+#define ulg unsigned PTS_INT32_T
+#define uch unsigned char
+#define extent slen_t
+#ifndef NULL
+#define NULL ((void*)0)
+#endif
+#ifndef near
+#define near
+#endif
+#ifndef ___
+/**** pts ****/
+#if defined(__STDC__) || defined(__cplusplus)
+# define _(args) args
+# define ___(arg2s,arg1s,argafter) arg2s /* Dat: no direct comma allowed in args :-( */
+#else
+# define _(args) ()
+# define ___(arg2s,arg1s,argafter) arg1s argafter /* Dat: no direct comma allowed in args :-( */
+#endif
+#endif
+
+/* ========================================================================
+ * Table of CRC-32's of all single-byte values (made by make_crc_table)
+ */
+local ZCONST ulg near crc_table[] = {
+ 0x00000000UL, 0x77073096UL, 0xee0e612cUL, 0x990951baUL, 0x076dc419UL,
+ 0x706af48fUL, 0xe963a535UL, 0x9e6495a3UL, 0x0edb8832UL, 0x79dcb8a4UL,
+ 0xe0d5e91eUL, 0x97d2d988UL, 0x09b64c2bUL, 0x7eb17cbdUL, 0xe7b82d07UL,
+ 0x90bf1d91UL, 0x1db71064UL, 0x6ab020f2UL, 0xf3b97148UL, 0x84be41deUL,
+ 0x1adad47dUL, 0x6ddde4ebUL, 0xf4d4b551UL, 0x83d385c7UL, 0x136c9856UL,
+ 0x646ba8c0UL, 0xfd62f97aUL, 0x8a65c9ecUL, 0x14015c4fUL, 0x63066cd9UL,
+ 0xfa0f3d63UL, 0x8d080df5UL, 0x3b6e20c8UL, 0x4c69105eUL, 0xd56041e4UL,
+ 0xa2677172UL, 0x3c03e4d1UL, 0x4b04d447UL, 0xd20d85fdUL, 0xa50ab56bUL,
+ 0x35b5a8faUL, 0x42b2986cUL, 0xdbbbc9d6UL, 0xacbcf940UL, 0x32d86ce3UL,
+ 0x45df5c75UL, 0xdcd60dcfUL, 0xabd13d59UL, 0x26d930acUL, 0x51de003aUL,
+ 0xc8d75180UL, 0xbfd06116UL, 0x21b4f4b5UL, 0x56b3c423UL, 0xcfba9599UL,
+ 0xb8bda50fUL, 0x2802b89eUL, 0x5f058808UL, 0xc60cd9b2UL, 0xb10be924UL,
+ 0x2f6f7c87UL, 0x58684c11UL, 0xc1611dabUL, 0xb6662d3dUL, 0x76dc4190UL,
+ 0x01db7106UL, 0x98d220bcUL, 0xefd5102aUL, 0x71b18589UL, 0x06b6b51fUL,
+ 0x9fbfe4a5UL, 0xe8b8d433UL, 0x7807c9a2UL, 0x0f00f934UL, 0x9609a88eUL,
+ 0xe10e9818UL, 0x7f6a0dbbUL, 0x086d3d2dUL, 0x91646c97UL, 0xe6635c01UL,
+ 0x6b6b51f4UL, 0x1c6c6162UL, 0x856530d8UL, 0xf262004eUL, 0x6c0695edUL,
+ 0x1b01a57bUL, 0x8208f4c1UL, 0xf50fc457UL, 0x65b0d9c6UL, 0x12b7e950UL,
+ 0x8bbeb8eaUL, 0xfcb9887cUL, 0x62dd1ddfUL, 0x15da2d49UL, 0x8cd37cf3UL,
+ 0xfbd44c65UL, 0x4db26158UL, 0x3ab551ceUL, 0xa3bc0074UL, 0xd4bb30e2UL,
+ 0x4adfa541UL, 0x3dd895d7UL, 0xa4d1c46dUL, 0xd3d6f4fbUL, 0x4369e96aUL,
+ 0x346ed9fcUL, 0xad678846UL, 0xda60b8d0UL, 0x44042d73UL, 0x33031de5UL,
+ 0xaa0a4c5fUL, 0xdd0d7cc9UL, 0x5005713cUL, 0x270241aaUL, 0xbe0b1010UL,
+ 0xc90c2086UL, 0x5768b525UL, 0x206f85b3UL, 0xb966d409UL, 0xce61e49fUL,
+ 0x5edef90eUL, 0x29d9c998UL, 0xb0d09822UL, 0xc7d7a8b4UL, 0x59b33d17UL,
+ 0x2eb40d81UL, 0xb7bd5c3bUL, 0xc0ba6cadUL, 0xedb88320UL, 0x9abfb3b6UL,
+ 0x03b6e20cUL, 0x74b1d29aUL, 0xead54739UL, 0x9dd277afUL, 0x04db2615UL,
+ 0x73dc1683UL, 0xe3630b12UL, 0x94643b84UL, 0x0d6d6a3eUL, 0x7a6a5aa8UL,
+ 0xe40ecf0bUL, 0x9309ff9dUL, 0x0a00ae27UL, 0x7d079eb1UL, 0xf00f9344UL,
+ 0x8708a3d2UL, 0x1e01f268UL, 0x6906c2feUL, 0xf762575dUL, 0x806567cbUL,
+ 0x196c3671UL, 0x6e6b06e7UL, 0xfed41b76UL, 0x89d32be0UL, 0x10da7a5aUL,
+ 0x67dd4accUL, 0xf9b9df6fUL, 0x8ebeeff9UL, 0x17b7be43UL, 0x60b08ed5UL,
+ 0xd6d6a3e8UL, 0xa1d1937eUL, 0x38d8c2c4UL, 0x4fdff252UL, 0xd1bb67f1UL,
+ 0xa6bc5767UL, 0x3fb506ddUL, 0x48b2364bUL, 0xd80d2bdaUL, 0xaf0a1b4cUL,
+ 0x36034af6UL, 0x41047a60UL, 0xdf60efc3UL, 0xa867df55UL, 0x316e8eefUL,
+ 0x4669be79UL, 0xcb61b38cUL, 0xbc66831aUL, 0x256fd2a0UL, 0x5268e236UL,
+ 0xcc0c7795UL, 0xbb0b4703UL, 0x220216b9UL, 0x5505262fUL, 0xc5ba3bbeUL,
+ 0xb2bd0b28UL, 0x2bb45a92UL, 0x5cb36a04UL, 0xc2d7ffa7UL, 0xb5d0cf31UL,
+ 0x2cd99e8bUL, 0x5bdeae1dUL, 0x9b64c2b0UL, 0xec63f226UL, 0x756aa39cUL,
+ 0x026d930aUL, 0x9c0906a9UL, 0xeb0e363fUL, 0x72076785UL, 0x05005713UL,
+ 0x95bf4a82UL, 0xe2b87a14UL, 0x7bb12baeUL, 0x0cb61b38UL, 0x92d28e9bUL,
+ 0xe5d5be0dUL, 0x7cdcefb7UL, 0x0bdbdf21UL, 0x86d3d2d4UL, 0xf1d4e242UL,
+ 0x68ddb3f8UL, 0x1fda836eUL, 0x81be16cdUL, 0xf6b9265bUL, 0x6fb077e1UL,
+ 0x18b74777UL, 0x88085ae6UL, 0xff0f6a70UL, 0x66063bcaUL, 0x11010b5cUL,
+ 0x8f659effUL, 0xf862ae69UL, 0x616bffd3UL, 0x166ccf45UL, 0xa00ae278UL,
+ 0xd70dd2eeUL, 0x4e048354UL, 0x3903b3c2UL, 0xa7672661UL, 0xd06016f7UL,
+ 0x4969474dUL, 0x3e6e77dbUL, 0xaed16a4aUL, 0xd9d65adcUL, 0x40df0b66UL,
+ 0x37d83bf0UL, 0xa9bcae53UL, 0xdebb9ec5UL, 0x47b2cf7fUL, 0x30b5ffe9UL,
+ 0xbdbdf21cUL, 0xcabac28aUL, 0x53b39330UL, 0x24b4a3a6UL, 0xbad03605UL,
+ 0xcdd70693UL, 0x54de5729UL, 0x23d967bfUL, 0xb3667a2eUL, 0xc4614ab8UL,
+ 0x5d681b02UL, 0x2a6f2b94UL, 0xb40bbe37UL, 0xc30c8ea1UL, 0x5a05df1bUL,
+ 0x2d02ef8dUL
+};
+
+
+/* ========================================================================= */
+ulg crc32 ___((register ulg crc, register ZCONST char *buf, extent len),(crc, buf, len),(
+ register ulg crc; /* crc shift register */
+ register ZCONST char *buf; /* pointer to bytes to pump through */
+ extent len; /* number of bytes in buf[] */
+/* Run a set of bytes through the crc shift register. If buf is a NULL
+ pointer, then initialize the crc shift register contents instead.
+ Return the current crc in either case. */
+)) {
+ /* register ulg near *crc_table; */
+
+ if (buf == NULLP) return crc /*0L*/;
+
+ /* crc_table = get_crc_table(); */
+
+ crc = crc ^ 0xffffffffUL;
+#ifndef NO_UNROLLED_LOOPS
+ while (len >= 8) {
+ DO8(buf);
+ len -= 8;
+ }
+#endif
+ if (len) do {
+ DO1(buf);
+ } while (--len);
+ return crc ^ 0xffffffffUL; /* (instead of ~c for 64-bit machines) */
+}
+
+/* #endif */ /* !USE_ZLIB */
+
+/* __EOF__ */
diff --git a/graphics/sam2p/crc32.h b/graphics/sam2p/crc32.h
new file mode 100644
index 0000000000..fe12eb73d9
--- /dev/null
+++ b/graphics/sam2p/crc32.h
@@ -0,0 +1,32 @@
+/* crc32.c -- Calculate CRC-32 for GZIP + PNG
+ */
+
+#ifndef CRC32_H
+#define CRC32_H 1
+
+#ifdef __GNUC__
+#ifndef __clang__
+#pragma interface
+#endif
+#endif
+
+#include "config2.h"
+
+#define CRC32_INITIAL ((unsigned PTS_INT32_T)0)
+/** Usage:
+ * unsigned PTS_INT32_T crc=CRC32_INITIAL;
+ * crc=crc32(crc, "alma", 4);
+ * crc=crc32(crc, "korte", 5);
+ * ...
+ * putchar( (char)(crc & 0xff) );
+ * putchar( (char)((crc >> 8) & 0xff) );
+ * putchar( (char)((crc >> 16) & 0xff) );
+ * putchar( (char)((crc >> 24) & 0xff) );
+ */
+extern
+#ifdef __cplusplus
+"C"
+#endif
+unsigned PTS_INT32_T crc32 _((unsigned PTS_INT32_T oldcrc, char PTS_const *s, slen_t slen));
+
+#endif /* CRC32_H */
diff --git a/graphics/sam2p/debian/README.debian b/graphics/sam2p/debian/README.debian
new file mode 100644
index 0000000000..99058a1507
--- /dev/null
+++ b/graphics/sam2p/debian/README.debian
@@ -0,0 +1,6 @@
+The Debian Package sam2p
+----------------------------
+
+Comments regarding the Package
+
+Szabó Péter <pts@winter>, Fri, 7 Feb 2003 12:16:40 +0100
diff --git a/graphics/sam2p/debian/changelog b/graphics/sam2p/debian/changelog
new file mode 100644
index 0000000000..3bee880942
--- /dev/null
+++ b/graphics/sam2p/debian/changelog
@@ -0,0 +1,281 @@
+sam2p (0.49.4) lucid; urgency=low
+
+ * fixed memory use bugs and vulnerabilities, e.g. these:
+ https://github.com/pts/sam2p/issues/14
+ * improved compatibility with new gcc, clang and perl
+ * improved Makefile automation
+
+ -- Peter Szabo <pts@fazekas.hu> Wed, 27 Sep 2017 17:39:12 +0200
+
+sam2p (0.49.3) lucid; urgency=low
+
+ * Added 36 changes in total.
+ * Fixed dozens of bugs.
+ * Improved GCC and Clang compatibility: fixed warnings, extended ccdep.pl .
+
+ -- Peter Szabo <pts@fazekas.hu> Fri, 10 Oct 2016 17:01:57 +0200
+
+sam2p (0.49.2) lucid; urgency=low
+
+ * Fixed GCC 4.8 incompatibilities in ccdep.pl (the dependency generator
+ of the build system) and elsewhere.
+ * Fixed GCC gcc 4.6 and 4.8 warnings.
+ * Fixed some harmless memory leaks.
+ * Fixed integer-pointer sign bug with `gcc -fPIC' (so it works with the
+ defaults of https://wiki.debian.org/Hardening, see
+ https://code.google.com/p/sam2p/issues/detail?id=11).
+
+ -- Peter Szabo <pts@fazekas.hu> Fri, 06 Sep 2013 15:06:32 +0200
+
+sam2p (0.49.1) lucid; urgency=low
+
+ * Fixed GCC 4.6 incompatibilities in ccdep.pl (the dependency generator
+ of the build system).
+
+ -- Peter Szabo <pts@fazekas.hu> Wed, 14 Dec 2011 17:44:47 +0100
+
+sam2p (0.49-2) karmic; urgency=low
+
+ * Fixed error reporting at cleanup time.
+ * Fixed file closing for temporary file removal on Windows.
+
+ -- Peter Szabo <pts@fazekas.hu> Thu, 30 Jun 2011 01:24:59 +0200
+
+sam2p (0.49-1) karmic; urgency=low
+
+ * Fixed version reporting in `sam2p --version'.
+
+ -- Peter Szabo <pts@fazekas.hu> Wed, 29 Jun 2011 19:17:45 +0200
+
+sam2p (0.48-1) karmic; urgency=low
+
+ * Added sam2p_pdf_scale.pl to the files list.
+ * Added examples/sam2p.spec for Fedora.
+
+ -- Peter Szabo <pts@fazekas.hu> Tue, 22 Mar 2011 19:23:07 +0100
+
+sam2p (0.47-1) unstable; urgency=low
+
+ * Fixed some bugs.
+ * Added some missing example files.
+ * Clarified the documentation a bit.
+
+ -- Szabó Péter <pts@fazekas.hu> Sun, 8 Aug 2009 01:50:53 +0200
+
+sam2p (0.46-2) unstable; urgency=low
+
+ * image.cpp: added sortPal(), so now sam2p converts source images to
+ canonical form.
+ * encoder.cpp, sam2p_main.cpp: Fixed predictor autodetection ultimately.
+ * Small compliation and documentation improvements.
+
+ -- Szabó Péter <pts@fazekas.hu> Sun, 5 Apr 2009 01:50:53 +0200
+
+sam2p (0.46-1) unstable; urgency=low
+
+ * Small bugfixes.
+ * encoder.cpp: Fixed ``/Predictor 15'' so it produces an efficient
+ predictor, similar to what libpng does.
+ * sam2p_main.cpp: Made ``/Predictor 15'' automatic for ZIP or LZW
+ compression if no `-c' command line flag was specified.
+
+ -- Szabó Péter <pts@fazekas.hu> Sun, 5 Apr 2009 01:50:53 +0200
+
+sam2p (0.45-3) unstable; urgency=low
+
+ * in_ps.c: improved PostScript EPS load support, forcing `showpage'.
+
+ -- Szabó Péter <pts@icy.seasons.hu> Thu, 10 Aug 2006 13:07:47 +0200
+
+sam2p (0.45-2) unstable; urgency=low
+
+ * cgif.c is indicated to be free software.
+
+ -- Szabó Péter <pts@math.bme.hu> Sun, 2 Jul 2006 23:04:21 +0200
+
+sam2p (0.45-1) unstable; urgency=low
+
+ * Small docs changes.
+ * Little bugfixes.
+
+ -- Szabó Péter <pts@math.bme.hu> Sun, 2 Jul 2006 17:19:29 +0200
+
+sam2p (0.44-14) unstable; urgency=low
+
+ * assertion BUGFIX in image.cpp:1480 Image::SampledInfo::setSampleFormat()
+
+ -- Szabo Peter <pts@math.bme.hu> Thu, 6 Apr 2006 15:13:11 +0200
+
+sam2p (0.44-13) unstable; urgency=low
+
+ * Added -j:quiet
+ * No >/dev/null on png22pnm and tif22pnm
+
+ -- Szabó Péter <pts@math.bme.hu> Fri, 26 Aug 2005 08:29:56 +0200
+
+sam2p (0.44-12) unstable; urgency=low
+
+ * Fixed non-(0,0)-based EPS loading by putting `translate' after
+ `setpagedevice' in in_ps.cpp
+
+ -- Szabó Péter <pts@math.bme.hu> Fri, 12 Aug 2005 23:13:38 +0200
+
+sam2p (0.44-11) unstable; urgency=low
+
+ * %%BeginData:; hack for GSView, as reported by Zoltán Petres
+
+ -- Szabó Péter <pts@math.bme.hu> Tue, 17 May 2005 14:39:20 +0200
+
+sam2p (0.44-10) unstable; urgency=low
+
+ * encoder.cpp slen_t -> int fixes for 64-bit. Thanks to Stefan Fritsch.
+
+ -- Szabó Péter <pts@math.bme.hu> Thu, 14 Apr 2005 09:23:01 +0200
+
+sam2p (0.44-9) unstable; urgency=low
+
+ * 64-bit fix (slen_t and slendiff_t), in reply to the
+ report by Stefan Fritsch.
+
+ -- Szabó Péter <pts@math.bme.hu> Tue, 12 Apr 2005 20:51:40 +0200
+
+sam2p (0.44-8) unstable; urgency=low
+
+ * Added /ImageDPI and -m:dpi:, see README.
+ * Fixed a couple of bugs.
+
+ -- Szabó Péter <pts@winter> Mon, 21 Feb 2005 23:53:51 +0100
+
+sam2p (0.44-7) unstable; urgency=low
+
+ * Updated copyright of pts_fax.c
+ * Updated copyright of cgif.c
+ * BUGFIX of JPEG -> EPS `delete tp' buf in appliers.cpp
+
+ -- Szabó Péter <pts@math.bme.hu> Thu, 20 Jan 2005 15:11:23 +0100
+
+sam2p (0.44-6) unstable; urgency=low
+
+ * Re-ripped pts_defl.c from linux-2.6.8.1 (ZLIB 1.1.3),
+ formerly it was Info-ZIP 2.2
+ * BUGFIX in image.cpp
+ * Documentation fixes
+
+ -- Szabó Péter <pts@winter> Tue, 18 Jan 2005 17:04:28 +0100
+
+sam2p (0.44-5) unstable; urgency=low
+
+ * Added -pdf:x (generate PDF with /XObject{}s).
+ * Changed PDF output so elements of /Kids are indirect references
+ (see the PDF Reference 1.5 for details).
+ * Added option: -transparent "#abcdef"
+
+ -- Szabó Péter <pts@winter> Sat, 8 Jan 2005 12:29:10 +0100
+
+sam2p (0.44-4) unstable; urgency=low
+
+ * Some glitches of g++-3.4 avoided. Now sam2p compiles fine.
+ * -l:gs=-r216 support for PDF.
+
+ -- Szabó Péter <pts@math.bme.hu> Thu, 6 Jan 2005 10:59:50 +0100
+
+sam2p (0.44-3) unstable; urgency=low
+
+ * minor fixes, documentation addons
+
+ -- Szabó Péter <pts@math.bme.hu> Tue, 1 Jun 2004 18:50:15 +0200
+
+sam2p (0.44-2) unstable; urgency=low
+
+ * Added answers to FAQ in README.
+
+ -- Szabó Péter <pts@math.bme.hu> Fri, 5 Mar 2004 19:54:44 +0100
+
+sam2p (0.44-1) unstable; urgency=low
+
+ * bugfixes
+ * PDF, PS and EPS import
+ * compressed bts2.ttt, so target sam2p is smaller (ps_tiny --copy)
+ * printf("%.16g") in configure
+
+ -- Szabó Péter <pts@math.bme.hu> Wed, 1 Oct 2003 19:49:32 +0200
+
+sam2p (0.43-4) unstable; urgency=low
+
+ * Allow to read stdin from a pipe
+ * Recognize SOF2 (progressive) JPEG and other non-baseline types
+ * Fixed SimBuffer::Flat::copyRange
+
+ -- Szabó Péter <pts@math.bme.hu> Tue, 11 Mar 2003 14:10:37 +0100
+
+sam2p (0.43-3) unstable; urgency=low
+
+ * Merged with CVS, created Debian source packages.
+
+ -- Szabó Péter <pts@math.bme.hu> Wed, 12 Feb 2003 20:51:58 +0100
+
+sam2p (0.43-2) unstable; urgency=low
+
+ * Added proper Description:, Depends: and Build-Depends: to
+ debian/changelog, modified the Makefile to respect $(DESTDIR) etc.
+
+ -- Szabó Péter <pts@winter> Fri, 7 Feb 2003 14:16:56 +0100
+
+sam2p (0.43-1) unstable; urgency=low
+
+ * Initial Debian release.
+ * PDF generation bugfixes
+ * PDF /MediaBox is output into a separate line near the beginning of file
+ (graphicP compatibility)
+
+sam2p (0.41) unstable; urgency=low
+
+ * vcsam2p.exe (graphic .exe with Visual Studio 6.0), merged
+ * added Below feature -m:lower:5
+ * png22pnm support
+ * Debian Slink pdfTeX integration
+
+ -- Szabó Péter <pts@winter> Wed, 5 Feb 2003 18:40:12 +0100
+
+sam2p (0.41) unstable; urgency=low
+
+ * All earlier versions listed here:
+ * 0.29 Apr 4 2002
+ sam2p_article.tex preliminary version
+ * 0.30 Sat Apr 6 09:19:23 CEST 2002
+ * 0.31 -- Fri Apr 12 23:54:57 CEST 2002
+ not working TCL/TK GUI, sam2p_article corrected
+ * 0.32 Sat Apr 13 12:55:09 CEST 2002 --
+ PCX input, class Encoder, class Decoder
+ * 0.33 JPEG, TIFF, PNG input. JPEG output.
+ * 0.34 PDF output, PNG output.
+ * 0.35 Fri Apr 26 08:28:41 CEST 2002
+ transparency, gui, sam2p_talk, EuroBachoTeX 2002
+ * 0.36 Sat May 26 14:06:09 CEST 2002
+ Blanca bugfixes
+ * 0.37 Sat Jun 1 14:06:43 CEST 2002
+ ccdep.pl, --enable-debug, XPM output, opaque TIFF output,
+ more PS output, BMP output, transparent PNM output, one-liner mode,
+ XWD output, PS output with margins, autoconf consts,
+ built-in CCITTFaxEncode
+ * 0.38 Tue Sep 3 20:16:59 CEST 2002
+ Many portability bugfixes. Now more versions of GNU C++ compilers and
+ more achitectures are tested and supported.
+ gcc-3.1 or gcc-3.2 compliance (AC_C_CONST working const; with autoconf
+ 2.53)
+ * 0.39 -j:warn, allow /OutputFile(-) (stdout) in one-liner mode,
+ one-liner mode with src == dst filename `--', EPS margins, PDF margins,
+ -m, scaling PS output command line, PSL1 Gray ZIP&LZW in all
+ TransferEncodings
+ * 0.40 Wed Dec 11 19:24:31 CET 2002
+ builds out-of-the box (./configure ...; make -> sam2p.exe) on Win32 with MinGW32 + Perl
+ * 0.41 GIF and XPM load bugfixes
+ synchronized to GIMP tif22pnm
+ transparent(+?) TIFF output, really
+ better tif22pnm support
+
+ -- Szabó Péter <pts@winter> Wed, 5 Feb 2003 11:40:12 +0100
+
+Local variables:
+mode: debian-changelog
+End:
diff --git a/graphics/sam2p/debian/control b/graphics/sam2p/debian/control
new file mode 100644
index 0000000000..0eb0ddd129
--- /dev/null
+++ b/graphics/sam2p/debian/control
@@ -0,0 +1,24 @@
+Source: sam2p
+Section: unknown
+Priority: optional
+Maintainer: Szabó Péter <pts@fazekas.hu>
+Standards-Version: 3.2.1
+Build-Depends: g++, perl
+
+Package: sam2p
+Architecture: any
+Depends: ${shlibs:Depends}
+Recommends: tif22pnm | netpbm, png22pnm | netpbm, libjpeg-progs
+Description: convert raster images to EPS and PDF and others
+ sam2p is a UNIX command line utility written in ANSI C++ that converts many
+ raster (bitmap) image formats into Adobe PostScript or PDF files. The images
+ are not vectorized. sam2p gives full control to the user to specify
+ standards-compliance, compression, and bit depths. In some cases sam2p can
+ compress an image 100 times smaller than the PostScript output of many other
+ common image converters. sam2p provides ZIP, RLE and LZW (de)compression
+ filters even on Level1 devices.
+ .
+ Recommendations: package netpbm provides the tifftopnm and pngtopnm utilities.
+ Please use tif22pnm and png22pnm (by the author of sam2p) instead of these,
+ because *22* provides a much richer functionality with less bugs. package
+ libjpeg-prog provides the excellent cjpeg and djpeg utilities.
diff --git a/graphics/sam2p/debian/copyright b/graphics/sam2p/debian/copyright
new file mode 100644
index 0000000000..28c5b7b6aa
--- /dev/null
+++ b/graphics/sam2p/debian/copyright
@@ -0,0 +1,4 @@
+This package was written by Szabó Péter pts@winter on Fri, 7 Feb 2003 12:16:40 +0100.
+
+Copyright: GPL (see /usr/share/common-licenses/GPL)
+
diff --git a/graphics/sam2p/debian/dirs b/graphics/sam2p/debian/dirs
new file mode 100644
index 0000000000..3c52b973ea
--- /dev/null
+++ b/graphics/sam2p/debian/dirs
@@ -0,0 +1,3 @@
+usr/bin
+usr/sbin
+usr/share/man/man1
diff --git a/graphics/sam2p/debian/rules b/graphics/sam2p/debian/rules
new file mode 100755
index 0000000000..1a36a82e8f
--- /dev/null
+++ b/graphics/sam2p/debian/rules
@@ -0,0 +1,69 @@
+#!/usr/bin/make -f
+# Made with the aid of debmake, by Christoph Lameter,
+# based on the sample debian/rules file for GNU hello by Ian Jackson.
+
+package=sam2p
+
+build:
+ $(checkdir)
+ ./configure --enable-gif --enable-lzw --prefix=/usr
+ $(MAKE)
+ touch build
+
+clean:
+ $(checkdir)
+ -rm -f build
+ -$(MAKE) MAKE_DIST=1 clean
+ -rm -f `find . -name "*~"`
+ -rm -rf debian/tmp debian/files* core debian/substvars
+# Dat: make distclean would remove the `configure' script
+
+binary-indep: checkroot build
+ $(checkdir)
+# There are no architecture-independent files to be uploaded
+# generated by this package. If there were any they would be
+# made here.
+
+binary-arch: checkroot build
+ $(checkdir)
+ -rm -rf debian/tmp
+ install -d debian/tmp
+ cd debian/tmp && install -d `cat ../dirs`
+ $(MAKE) install prefix=`pwd`/debian/tmp/usr DESTDIR=`pwd`/debian/tmp/usr
+# Must have debmake installed for this to work. Otherwise please copy
+# /usr/bin/debstd into the debian directory and change debstd to debian/debstd
+ debstd README README.1 README.2 README.3 README.4 README.5 README.6 README~
+ dpkg-gencontrol -isp
+ chown -R root.root debian/tmp
+ chmod -R go=rX debian/tmp
+ dpkg --build debian/tmp ..
+
+define checkdir
+ test -f debian/rules
+endef
+
+binary:
+ $(checkdir)
+ if test root = "`whoami`"; then $(MAKE) -f debian/rules binary-indep binary-arch; \
+ else fakeroot $(MAKE) -f debian/rules binary-indep binary-arch; fi
+
+checkroot:
+ $(checkdir)
+ test root = "`whoami`"
+
+.PHONY: binary binary-arch binary-indep clean checkroot
+
+.PHONY: source source-here
+source-here:
+ rm -rf debsrc
+ mkdir -p debsrc/debian
+ cp -a $(wildcard $(addprefix debian/,README.debian docs changelog control copyright dirs rules prerm postrm postinst preinst)) debsrc/debian
+ $(MAKEF) install-debsrc
+ DIR="`<debian/changelog perl -ne 'print if s@^(\S+) [(]([^)]+?)(?:-\d+)?[)].*@$$1-$$2@;last'`" && \
+ test ! -d "$$DIR" && \
+ mv debsrc "$$DIR" && \
+ (dpkg-source -b "$$DIR";true) && \
+ rm -rf "$$DIR"
+
+source: source-here
+ mv $(package)_*-*.tar.gz $(package)_*-*.dsc ..
diff --git a/graphics/sam2p/encoder.cpp b/graphics/sam2p/encoder.cpp
new file mode 100644
index 0000000000..4bb8c714ad
--- /dev/null
+++ b/graphics/sam2p/encoder.cpp
@@ -0,0 +1,1765 @@
+/* encoder.cpp -- various PostScript and PDF encoding filter implementations
+ * by pts@fazekas.hu at Sun Mar 3 14:16:00 CET 2002
+ * --- Mon Mar 4 00:00:20 CET 2002
+ */
+
+/* Imp: make built-in FlateEncode DYNALLOC */
+/* Imp: add lzw_codec */
+/* Imp: add gzip */
+/* Imp: add zlib */
+
+#ifdef __GNUC__
+#ifndef __clang__
+#pragma implementation
+#endif
+#endif
+
+
+#include "encoder.hpp"
+#include "error.hpp"
+#include "gensio.hpp"
+#include <stdlib.h> /* getenv() */
+#include <string.h>
+
+/* --- */
+
+/** Does output EOD (end-of-data) marker `>' */
+class ASCIIHexEncode: public PSEncoder {
+ public:
+ /** @param maxcpl_: maximum # hex digits per line, should be even */
+ ASCIIHexEncode(GenBuffer::Writable &out_, unsigned maxcpl_);
+ virtual void vi_write(char const*buf, slen_t len);
+ protected:
+ unsigned maxcpl;
+ /** Number of hex digits already printed. */
+ unsigned curcpl;
+ GenBuffer::Writable &out;
+};
+
+/** Does output EOD (end-of-data) marker `~>' */
+class ASCII85Encode: public PSEncoder {
+ public:
+ /** @param maxcpl_: maximum # hex digits per line, should be even */
+ ASCII85Encode(GenBuffer::Writable &out_, unsigned maxcpl_);
+ virtual void vi_write(char const*buf, slen_t len);
+
+ protected:
+ void wencoded(char const *encoded);
+ void wout(unsigned PTS_INT32_T buf_);
+ unsigned maxcpl;
+ /** Number of digits available in this line */
+ GenBuffer::Writable &out;
+ unsigned ascii85breaklen;
+ unsigned ascii85left;
+ unsigned PTS_INT32_T ascii85buf;
+ char *obuf, *obufend, *op;
+ char dscst; /* For converting `%%' to `% %' to avoid DSC parser errors */
+};
+
+/** Doesn't output EOD (end-of-data) marker `>' */
+class RunLengthEncode: public PSEncoder {
+ public:
+ /** @param maxcpl_: maximum # hex digits per line, should be even */
+ RunLengthEncode(GenBuffer::Writable &out_, slen_t RecordSize_);
+ virtual void vi_write(char const*buf, slen_t len);
+
+ protected:
+ slen_t recordsize;
+ GenBuffer::Writable &out;
+ // char *obuf, *obufend, *op;
+ slen_t record_left;
+ unsigned saved_c, saved_rep;
+ /** size == header+buffer+EOD */
+ char saved[130];
+};
+
+static int gen_write(char *block, unsigned len, void *zfile);
+
+#if USE_BUILTIN_ZIP
+#include "pts_defl.h" /* Imp: because pts_defl_interface :-( */
+#if OBJDEP
+# warning REQUIRES: pts_defl
+#endif
+class FlateEncode: public PSEncoder {
+#if PTS_DEFL_RIPPED_ZLIB /* Dat: defined in pts_defl.h */
+ public:
+ /** @param level: 1..9: 9==highest compression */
+ FlateEncode(GenBuffer::Writable &out_, unsigned level_);
+ virtual ~FlateEncode() { zlib_deflateEnd(&zs); } /* Dat: ==Z_OK check (for unflushed buffers) omitted */
+ virtual void vi_write(char const*buf, slen_t len);
+ protected:
+ /** Formerly only one instance of FlateEncode was allowed.
+ * It exists <=> loced==true
+ */
+ // static bool locked;
+ /** Writable that this filter writes to */
+ GenBuffer::Writable &out;
+ char workspace[ZLIB_DEFLATE_WORKSPACESIZE_MIN]; /* big, about 270k */
+ char obuf[4096];
+ /*struct*/ z_stream zs;
+#else /* old, ripped from Info-ZIP 2.2 */
+ public:
+ /** @param level: 1..9: 9==highest compression */
+ FlateEncode(GenBuffer::Writable &out_, unsigned level_);
+ virtual ~FlateEncode() { if (fs!=NULLP) fs->delete2(fs); }
+ virtual void vi_write(char const*buf, slen_t len);
+ static void *gen_malloc(unsigned n);
+ static void gen_free(void *p);
+ protected:
+ /** Formerly only one instance of FlateEncode was allowed.
+ * It exists <=> loced==true
+ */
+ // static bool locked;
+ /** Writable that this filter writes to */
+ GenBuffer::Writable &out;
+ #if SIZEOF_INT>2
+ typedef unsigned s_t;
+ #else
+ typedef unsigned short s_t;
+ #endif
+ /** Adler32 checksum */
+ s_t s1, s2;
+ bool had_header;
+ struct pts_defl_interface* fs;
+#endif /* else PTS_DEFL_RIPPED_ZLIB */
+};
+#endif
+
+/** Just store the data in Flate (ZLIB) format, no real compression. Adds
+ * about 3 bytes of overhead per 65535 bytes (compression ratio:
+ * 100.004578%)
+ */
+class FlateStoreEncode: public PSEncoder {
+ public:
+ /** @param level: 1..9: 9==highest compression */
+ FlateStoreEncode(GenBuffer::Writable &out_);
+ inline virtual ~FlateStoreEncode() {}
+ virtual void vi_write(char const*buf, slen_t len);
+ protected:
+ GenBuffer::Writable &out;
+ #if SIZEOF_INT>2
+ typedef unsigned s_t;
+ #else
+ typedef unsigned short s_t;
+ #endif
+ /** Adler32 checksum */
+ s_t s1, s2;
+ bool had_header;
+ /** Number of bytes already in buf */
+ unsigned abuflen;
+ /** Max: 65535 */
+ #if HAVE_STATIC_CONST
+ static const unsigned ABUFSIZE=65535;
+ #else
+ #define ABUFSIZE 65535
+ #endif
+ /** Should really not allocate a FlateStoreEncode on the stack. */
+ char abuf[ABUFSIZE+5];
+};
+
+#if USE_BUILTIN_FAXE
+
+#include "pts_fax.h"
+#if OBJDEP
+# warning REQUIRES: pts_faxe
+#endif
+class CCITTFaxEncode: public PSEncoder {
+ public:
+ CCITTFaxEncode(GenBuffer::Writable &out_, slendiff_t K, slen_t Columns, bool EndOfLine, bool BlackIs1);
+ virtual void vi_write(char const*buf, slen_t len);
+ protected:
+ GenBuffer::Writable &out;
+ stream_CFE_state sCFEs;
+ unsigned char rbuf[4096];
+ unsigned char wbuf[4096];
+ stream_cursor_read r;
+ stream_cursor_write w;
+ unsigned char *hard, *rlimit;
+
+ static void*gen_xalloc(unsigned n);
+ static void gen_free(void *ptr);
+ static void gen_memset(void *s, int c, unsigned n);
+ static void gen_memcpy(void *dest, const void *src, unsigned n);
+};
+#endif
+
+#if USE_BUILTIN_LZW
+#include "pts_lzw.h" /* Imp: because pts_lzw_state :-( */
+#if OBJDEP
+# warning REQUIRES: pts_lzw
+#endif
+class LZWEncode: public PSEncoder {
+ public:
+ LZWEncode(GenBuffer::Writable &out_);
+ virtual void vi_write(char const*buf, slen_t len);
+ protected:
+ GenBuffer::Writable &out;
+ struct pts_lzw_state fs;
+};
+#endif
+
+/**
+ * Reporting of GS errors is somewhat dump: the actual message isn't reported,
+ * only the fact that something went wrong.
+ * Imp: force a no-error trailer output by gs, and check that
+ */
+class GSEncode: public PSEncoder {
+ public:
+ /** @param filter_psname is a full-featured PostScript *Encode filter
+ * specification string, for example: "<</Effort 5>>/FlateEncode" or
+ * "0/RunLengthEncode" or "72 pop/ASCIIHexEncode"; will be surrounded as
+ * `currentfile ... filter'
+ */
+ GSEncode(GenBuffer::Writable &out_, char const*filter_psname);
+ inline virtual ~GSEncode() {}
+ /* vvv Imp: correct these */
+ virtual void vi_write(char const*buf, slen_t len);
+ protected:
+ class P: public Filter::PipeE {
+ protected: virtual void vi_check();
+ public: P(GenBuffer::Writable &out_, char const*filter_psname);
+ };
+ /** We need this delegator because `delete ...' won't work with multiple
+ * inheritance. (?? )
+ */
+ P p;
+};
+
+class CjpegEncode: public PSEncoder {
+ public:
+ /** @param filter_psname is a full-featured PostScript *Encode filter
+ * specification string, for example: "<</Effort 5>>/FlateEncode" or
+ * "0/RunLengthEncode" or "72 pop/ASCIIHexEncode"; will be surrounded as
+ * `currentfile ... filter'
+ */
+ CjpegEncode(GenBuffer::Writable &out_, char const*filter_psname, slen_t Columns, slen_t Rows, bool rgbp_, unsigned char quality);
+ inline virtual ~CjpegEncode() {}
+ virtual void vi_write(char const*buf, slen_t len);
+ protected:
+ class P: public Filter::PipeE { public:
+ // protected: virtual void vi_check();
+ P(GenBuffer::Writable &out_, slen_t Columns, slen_t Rows, bool rgbp_, unsigned char quality);
+ protected: /* Not needed: protected -> public: pacify VC6.0 */
+ virtual void vi_copy(FILE *f);
+ bool rgbp;
+ };
+ /** We need this delegator because `delete ...' won't work with multiple
+ * inheritance. (?? )
+ */
+ P p;
+};
+
+#if !USE_BUILTIN_LZW
+class Lzw_codecEncode: public PSEncoder {
+ public:
+ /** @param filter_psname is a full-featured PostScript *Encode filter
+ * specification string, for example: "<</Effort 5>>/FlateEncode" or
+ * "0/RunLengthEncode" or "72 pop/ASCIIHexEncode"; will be surrounded as
+ * `currentfile ... filter'
+ */
+ Lzw_codecEncode(GenBuffer::Writable &out_, char const*filter_psname);
+ inline virtual ~Lzw_codecEncode() {}
+ virtual void vi_write(char const*buf, slen_t len);
+ protected:
+ class P: public Filter::PipeE { public:
+ // protected: virtual void vi_check();
+ P(GenBuffer::Writable &out_);
+ protected:
+ // virtual void vi_copy(FILE *f);
+ };
+ /** We need this delegator because `delete ...' won't work with multiple
+ * inheritance. (?? )
+ */
+ P p;
+};
+#endif
+
+class TIFFPredictor2: public Encoder {
+ public:
+ /** @param maxcpl_: maximum # hex digits per line, should be even */
+ TIFFPredictor2(GenBuffer::Writable &out_, unsigned char bpc_, slen_t columns_, unsigned char cpp_);
+ virtual void vi_write(char const*buf, slen_t len);
+ protected:
+ unsigned PTS_INT32_T h;
+ unsigned char *obuf, *op, bpc, cpp;
+ slen_t rlen;
+ GenBuffer::Writable &out;
+};
+
+class PNGPredictorNone: public Encoder {
+ public:
+ /** @param maxcpl_: maximum # hex digits per line, should be even */
+ PNGPredictorNone(GenBuffer::Writable &out_, unsigned char bpc_, slen_t columns_, unsigned char cpp_);
+ virtual void vi_write(char const*buf, slen_t len);
+ protected:
+ slen_t rlen, opleft;
+ GenBuffer::Writable &out;
+};
+
+class PNGPredictorSub: public Encoder {
+ public:
+ /** @param maxcpl_: maximum # hex digits per line, should be even */
+ PNGPredictorSub(GenBuffer::Writable &out_, unsigned char bpc_, slen_t columns_, unsigned char cpp_);
+ virtual void vi_write(char const*buf, slen_t len);
+ protected:
+ unsigned PTS_INT32_T h;
+ unsigned char *obuf, *op;
+ slen_t rlen;
+ GenBuffer::Writable &out;
+ unsigned char bpccpp;
+};
+
+class PNGPredictorUp: public Encoder {
+ public:
+ /** @param maxcpl_: maximum # hex digits per line, should be even */
+ PNGPredictorUp(GenBuffer::Writable &out_, unsigned char bpc_, slen_t columns_, unsigned char cpp_);
+ virtual void vi_write(char const*buf, slen_t len);
+ protected:
+ unsigned char *obuf, *op, *oq;
+ slen_t rlen;
+ GenBuffer::Writable &out;
+};
+
+class PNGPredictorAverage: public Encoder {
+ public:
+ /** @param maxcpl_: maximum # hex digits per line, should be even */
+ PNGPredictorAverage(GenBuffer::Writable &out_, unsigned char bpc_, slen_t columns_, unsigned char cpp_);
+ virtual void vi_write(char const*buf, slen_t len);
+ protected:
+ unsigned PTS_INT32_T h/*, g*/;
+ unsigned char *obuf, *op, *oq;
+ slen_t rlen;
+ GenBuffer::Writable &out;
+ unsigned char bpccpp;
+};
+
+class PNGPredictorPaeth: public Encoder {
+ public:
+ /** @param maxcpl_: maximum # hex digits per line, should be even */
+ PNGPredictorPaeth(GenBuffer::Writable &out_, unsigned char bpc_, slen_t columns_, unsigned char cpp_);
+ virtual void vi_write(char const*buf, slen_t len);
+ protected:
+ unsigned PTS_INT32_T h, g;
+ unsigned char *obuf, *op, *oq;
+ slen_t rlen;
+ GenBuffer::Writable &out;
+ unsigned char bpccpp;
+};
+
+/** This class implements inferior predictor autoselection heuristics.
+ * Please use PNGPredictorAuto instead.
+ * Imp: code reuse with PNGPredictorAuto
+ */
+class PNGPredictorAutoBadSigned: public Encoder {
+ public:
+ /** @param maxcpl_: maximum # hex digits per line, should be even */
+ PNGPredictorAutoBadSigned(GenBuffer::Writable &out_, unsigned char bpc_, slen_t columns_, unsigned char cpp_);
+ virtual void vi_write(char const*buf, slen_t len);
+ protected:
+ unsigned PTS_INT32_T h, g;
+ unsigned char *obuf, *o_prior, *o_0, *o_1, *o_2, *o_3, *o_4, *oo[5];
+ slen_t rlen;
+ GenBuffer::Writable &out;
+ unsigned char bpccpp;
+ slen_t opleft;
+};
+
+/** This class implements inferior predictor autoselection heuristics.
+ * Please use PNGPredictorAuto instead.
+ * Imp: code reuse with PNGPredictorAuto
+ */
+class PNGPredictorAutoBadUnsigned: public Encoder {
+ public:
+ /** @param maxcpl_: maximum # hex digits per line, should be even */
+ PNGPredictorAutoBadUnsigned(GenBuffer::Writable &out_, unsigned char bpc_, slen_t columns_, unsigned char cpp_);
+ virtual void vi_write(char const*buf, slen_t len);
+ protected:
+ unsigned PTS_INT32_T h, g;
+ unsigned char *obuf, *o_prior, *o_0, *o_1, *o_2, *o_3, *o_4, *oo[5];
+ slen_t rlen;
+ GenBuffer::Writable &out;
+ unsigned char bpccpp;
+ slen_t opleft;
+};
+
+/** This class implements to so-called ``minimum sum of absolute differences''
+ * predictior autoselection heuristics, the same as what pngwutil.c
+ * contains in function png_write_find_filter() in libpng 1.2.20. (See that
+ * function for a discussion of other heuristics. A summary of this heuristics:
+ * we find which method provides the smallest value when summing the absolute
+ * values of the distances from zero, using anything >= 128 as negative
+ * numbers.
+ */
+class PNGPredictorAuto: public Encoder {
+ public:
+ /** @param maxcpl_: maximum # hex digits per line, should be even */
+ PNGPredictorAuto(GenBuffer::Writable &out_, unsigned char bpc_, slen_t columns_, unsigned char cpp_);
+ virtual void vi_write(char const*buf, slen_t len);
+ protected:
+ unsigned PTS_INT32_T h, g;
+ unsigned char *obuf, *o_prior, *o_0, *o_1, *o_2, *o_3, *o_4, *oo[5];
+ slen_t rlen;
+ GenBuffer::Writable &out;
+ unsigned char bpccpp;
+ slen_t opleft;
+};
+
+/* --- */
+
+FlateStoreEncode::FlateStoreEncode(GenBuffer::Writable &out_)
+ :out(out_)
+ ,s1(1)
+ ,s2(0)
+ ,had_header(false)
+ ,abuflen(0)
+ {}
+
+#if 0
+/** 0x7801: ZLIB header signaling fastest compression
+ * 0: 2 bits: DEFLATE block header signaling stored (uncompressed) block +
+ * 6 bits of padding.
+ */
+char FlateStoreEncode::header[3]= { 0x78, 1, 0 };
+#endif
+
+void FlateStoreEncode::vi_write(char const*buf, slen_t len) {
+ register s_t sold;
+ register char const*p=buf; char const*pend=p+len;
+ (void)sold;
+ if (len==0) { /* EOF: flush and send trailer */
+ /* Dat: Last block has to be written even if it's empty. */
+ if (!had_header) { out.vi_write("\x78\x01", 2); had_header=true; }
+ abuf[0]=(char)1; /* Last, stored block with padding */
+ abuf[1]=abuflen; abuf[2]=abuflen>>8;
+ abuf[3]=~(abuflen); abuf[4]=~(abuflen>>8);
+ out.vi_write(abuf, abuflen+5);
+ if (s1>=65521) s1-=65521;
+ if (s2>=65521) s2-=65521;
+ unsigned char trailer[4];
+ trailer[0]=s2>>8; trailer[1]=s2&255; trailer[2]=s1>>8; trailer[3]=s1&255;
+ out.vi_write((char const*)trailer,4);
+ out.vi_write(0,0); /* Signal EOF */
+ return;
+ }
+ /* From rfc1950.txt:
+ Adler-32 is composed of two sums accumulated per byte: s1 is
+ the sum of all bytes, s2 is the sum of all s1 values. Both sums
+ are done modulo 65521. s1 is initialized to 1, s2 to zero. The
+ Adler-32 checksum is stored as s2*65536 + s1 in most-
+ significant-byte first (network) order.
+ */
+ /* Update Adler-32 checksum */
+ while (p!=pend) {
+ #if SIZEOF_INT>2
+ if ((s1+=*(unsigned char const*)p)>=65521) s1-=65521;
+ if ((s2+=s1)>=65521) s2-=65521;
+ #elif SIZEOF_SHORT==2
+ sold=s1;
+ if ((s1+=*(unsigned char const*)p))<sold) s1+=15; /* 15==65536-21 */
+ sold=s2;
+ s2=(s2+s1)&0xffff;
+ if ((s2+=s1)<sold) s2+=15;
+ #else
+ /* vvv 0xffff is needed since unsigned short may be > 0..65535 */
+ sold=s1;
+ s1=(s1+*(unsigned char const*)p)&0xffff;
+ if (s1<sold) s1+=15; /* 15==65536-21 */
+ sold=s2;
+ s2=(s2+s1)&0xffff;
+ if (s2<sold) s2+=15;
+ #endif
+ p++;
+ }
+ // fprintf(stderr, "len=%u\n", len);
+ unsigned abufleft;
+ while ((abufleft=ABUFSIZE-abuflen)<len) {
+ // putchar('.');
+ // fprintf(stderr, "ABUFSIZE=%u abuflen=%u\n", ABUFSIZE, abuflen);
+ memcpy(abuf+abuflen+5, buf, abufleft);
+ abuf[0]=0; /* Stored block with padding */
+ abuf[1]=(char)ABUFSIZE; abuf[2]=(char)(ABUFSIZE>>8);
+ abuf[3]=(char)~(ABUFSIZE); abuf[4]=(char)~(ABUFSIZE>>8);
+ if (!had_header) { out.vi_write("\x78\x01", 2); had_header=true; }
+ /* fprintf(stderr,"%02x %02x", abuf[1], abuf[2]); */
+ out.vi_write(abuf, ABUFSIZE+5); /* emit next stored block with header */
+ abuflen=0;
+ len-=abufleft;
+ buf+=abufleft;
+ }
+ // putchar('X');
+ memcpy(abuf+abuflen+5, buf, len);
+ abuflen+=len;
+ /* Now abuf is possibly full. That is intentional, so we will be able to
+ * emit a full last block instead of an empty one.
+ */
+}
+
+/* --- */
+
+ASCIIHexEncode::ASCIIHexEncode(GenBuffer::Writable &out_, unsigned maxcpl_)
+ :maxcpl(maxcpl_)
+ ,curcpl(0)
+ ,out(out_) {}
+
+void ASCIIHexEncode::vi_write(char const*buf, slen_t len) {
+ /* Imp: buffering (1K etc.) */
+ static char const hextable []="0123456789abcdef";
+ char obuf[3];
+ obuf[0]='\n';
+ if (len==0) { out.vi_write(">",1); out.vi_write(0,0); }
+ else while (len--!=0) {
+ obuf[1]=hextable[(*(unsigned char const*)buf)>>4];
+ obuf[2]=hextable[(*(unsigned char const*)buf)&15];
+ if (curcpl>=maxcpl) { curcpl=2; out.vi_write(obuf, 3); }
+ else { curcpl+=2; out.vi_write(obuf+1, 2); }
+ buf++;
+ }
+}
+
+/* --- */
+
+ASCII85Encode::ASCII85Encode(GenBuffer::Writable &out_, unsigned maxcpl_)
+ :maxcpl(maxcpl_)
+ ,out(out_)
+ ,ascii85breaklen(maxcpl_)
+ ,ascii85left(4)
+ ,dscst(1) {
+ obufend=(op=obuf=new char[4096])+4096;
+}
+
+void ASCII85Encode::wencoded(char const *cp) {
+ for (; *cp!='\0'; ) {
+ if (op==obufend) out.vi_write(op=obuf, obufend-obuf);
+ // if (*cp<='!') { fprintf(stderr, "e=%d.\n", cp-encoded); }
+ assert(*cp>='!');
+ assert(*cp<='~');
+ if (dscst) {
+ if (dscst == 1) {
+ dscst = (*cp == '%') ? 2 : 0;
+ } else { /* if (dscst == 2) { */
+ if (*cp == '%') {
+ if (--ascii85breaklen == 0) {
+ *op++ = '\n';
+ ascii85breaklen = maxcpl;
+ } else {
+ /* Add space for `% %' instead of `%%' at BOL. */
+ *op++ = ' ';
+ }
+ if (op==obufend) out.vi_write(op=obuf, obufend-obuf);
+ }
+ dscst = 0;
+ }
+ }
+ *op++=*cp++;
+ if (--ascii85breaklen == 0) {
+ if (op==obufend) out.vi_write(op=obuf, obufend-obuf);
+ *op++='\n';
+ ascii85breaklen = maxcpl;
+ dscst = 1;
+ }
+ } /* NEXT */
+}
+
+void ASCII85Encode::vi_write(char const*buf, slen_t len) {
+ if (len==0) {
+ char encoded[6];
+ assert(ascii85left<=4);
+ if (ascii85left!=4) {
+ unsigned PTS_INT32_T buf_=ascii85buf<<8*ascii85left;
+ unsigned PTS_INT32_T q;
+ unsigned w1;
+
+ q = buf_ / ((unsigned PTS_INT32_T)85*85*85*85); /* actually only a byte */
+ assert(q<=85);
+ encoded[0] = q + '!';
+
+ buf_ -= q * ((unsigned PTS_INT32_T)85*85*85*85); q = buf_ / ((unsigned PTS_INT32_T)85*85*85);
+ encoded[1] = q + '!';
+
+ buf_ -= q * ((unsigned PTS_INT32_T)85*85*85); q = buf_ / (85*85);
+ encoded[2] = q + '!';
+
+ w1 = (unsigned) (buf_ - q*(unsigned PTS_INT32_T)(85*85));
+ assert(w1/85<85);
+ encoded[3] = (w1 / 85) + '!';
+ encoded[4] = (w1 % 85) + '!';
+ encoded[5-ascii85left] = '\0';
+ wencoded(encoded);
+ } /* IF */
+ if (op!=obuf) out.vi_write(obuf, op-obuf); /* flush buffer cache */
+ out.vi_write("~>",2); out.vi_write(0,0);
+ delete [] obuf;
+ obuf=(char*)NULLP;
+ } else {
+ assert(obuf!=NULLP);
+ register unsigned PTS_INT32_T abuf=ascii85buf;
+ register unsigned aleft=ascii85left;
+ assert(aleft>=1 && aleft<=4);
+ do {
+ while (len!=0 && aleft!=0) {
+ abuf=(abuf<<8)+*(unsigned char const*)buf++; len--; aleft--;
+ }
+ if (aleft!=0) break;
+ wout(abuf);
+ aleft=4;
+ } while (len!=0);
+ ascii85buf=abuf; ascii85left=aleft;
+ }
+}
+
+void ASCII85Encode::wout(unsigned PTS_INT32_T buf_) {
+ char encoded[6];
+ if (buf_ != (unsigned PTS_INT32_T)0) {
+ unsigned PTS_INT32_T q;
+ unsigned w1;
+
+ q = buf_ / ((unsigned PTS_INT32_T)85*85*85*85); /* actually only a byte */
+ encoded[0] = q + '!';
+
+ buf_ -= q * ((unsigned PTS_INT32_T)85*85*85*85); q = buf_ / ((unsigned PTS_INT32_T)85*85*85);
+ encoded[1] = q + '!';
+
+ buf_ -= q * ((unsigned PTS_INT32_T)85*85*85); q = buf_ / (85*85);
+ encoded[2] = q + '!';
+
+ w1 = (unsigned) (buf_ - q*(unsigned PTS_INT32_T)(85*85));
+ encoded[3] = (w1 / 85) + '!';
+ encoded[4] = (w1 % 85) + '!';
+ encoded[5] = '\0';
+ } else {
+ encoded[0] = 'z', encoded[1] = '\0';
+ }
+ wencoded(encoded);
+}
+
+/* --- */
+
+RunLengthEncode::RunLengthEncode(GenBuffer::Writable &out_, slen_t RecordSize_)
+ :recordsize(RecordSize_==0?(slen_t)-1:RecordSize_)
+ ,out(out_) {
+ record_left=recordsize;
+ // obufend=(op=obuf=new char[4096])+4096; /* Imp: implement write buffering */
+ saved_c=saved_rep=0;
+}
+
+void RunLengthEncode::vi_write(char const*buf, slen_t len) {
+ unsigned j, umax;
+ char b;
+ if (len==0) { /* handle EOF */
+ if (saved_rep!=0) {
+ assert(saved_rep>=2);
+ (saved+1)[-1]=257-saved_rep;
+ (saved+1)[1]=(char)128; /* EOD */
+ out.vi_write((saved+1)-1,3);
+ // fprintf(stderr,"rd=%u\n",saved_rep);
+ } else if (saved_c!=0) {
+ (saved+1)[-1]=saved_c-1;
+ (saved+1)[saved_c]=(char)128; /* EOD */
+ out.vi_write((saved+1)-1, saved_c+2);
+ // fprintf(stderr,"re=%u\n",saved_c);
+ } else {
+ (saved+1)[-1]=(char)128;
+ out.vi_write((saved+1)-1, 1);
+ }
+ out.vi_write(0,0); /* propagate EOF */
+ record_left=0; /* signal that no further data will be accepted */
+ return;
+ }
+ again:
+ assert(record_left>=1);
+ assert(len>=1);
+ /* Imp: locally cache vars saved* */
+ j=0;
+ if (saved_c==0) {
+ saved_rep=0; saved_c=1; b=(saved+1)[0]=*buf++; len--;
+ if (0==--record_left) goto put_norep;
+ if (0==len) return;
+ goto yes;
+ }
+ if (saved_c==1 && saved_rep==0) { yes:
+ if (*buf++==(saved+1)[0]) {
+ saved_rep=2; len--;
+ if (0==--record_left) goto put_rep;
+ } else {
+ (saved+1)[1]=buf[-1]; saved_c=2; len--;
+ if (0==--record_left) goto put_norep;
+ }
+ if (0==len) return;
+ }
+ assert(record_left>=1);
+ assert(len>=1);
+ assert((saved_rep==0 && saved_c>=2) || (saved_rep>=2 && saved_c==1));
+ if (saved_rep!=0) { /* Try to increase the repeating sequence */
+ assert(saved_rep>=2);
+ assert(saved_c==1);
+ assert(len>=1);
+ b=(saved+1)[0];
+ umax=len>128?128:len; if (umax>record_left) umax=record_left;
+ /* fprintf(stderr,"um1=%u\n", umax); */
+ if (umax>128-saved_rep) umax=128-saved_rep;
+ assert(umax>=1);
+ j=0; while (j!=umax && buf[j]==b) { j++; saved_rep++; }
+ if (j!=len || saved_rep==128) {
+ put_rep: /* Found a maximal repeat width */
+ (saved+1)[-1]=257-saved_rep;
+ out.vi_write((saved+1)-1,2);
+ /* fprintf(stderr,"ra=%u\n",saved_rep); */
+ if ((record_left-=j)==0) record_left=recordsize;
+ buf+=j;
+ saved_c=saved_rep=0;
+ if (0==(len-=j)) return;
+ goto again;
+ } /* Current repeat width can be further increased */
+ } else { /* Try to increase the non-repeating sequence */
+ assert(saved_c>=2);
+ if (buf[0]==(saved+1)[saved_c-1]) { /* this decision might be sub-optimal */
+ saved_c--;
+ /* Now: saved_c: non-repeat length, >=1 */
+ (saved+1)[-1]=saved_c-1;
+ out.vi_write((saved+1)-1, saved_c+1);
+ /* fprintf(stderr,"rb=%u\n",saved_c); */
+ // record_left++; /* because of saved_c--; but we would increase it later anyway */
+ // buf+=saved_c;
+ (saved+1)[0]=buf[0]; /* first matching char-pair data */
+ saved_c=1; saved_rep=2; /* make the new block a >=2 repeat */
+ record_left--; buf++;
+ if (0==--len) return;
+ goto again;
+ }
+ (saved+1)[saved_c++]=buf[0];
+ //record_left--;
+ //buf++;
+ //len--;
+ //if (saved_c==128) goto put_norep;
+ //if (0==len) return;
+ umax=len>128?128:len; if (umax>record_left) umax=record_left;
+ if (umax>128-saved_c) umax=128-saved_c;
+ /* fprintf(stderr,"um2=%u\n", umax); */
+ assert(umax>=1);
+ j=1; while (j!=umax && buf[j]!=buf[j-1]) (saved+1)[saved_c++]=buf[j++];
+ if (j!=len || saved_c==128) {
+ put_norep: /* Found a maximal non-repeat width */
+ (saved+1)[-1]=saved_c-1;
+ out.vi_write((saved+1)-1, saved_c+1);
+ /* fprintf(stderr,"rc=%u\n",saved_c); */
+ if ((record_left-=j)==0) record_left=recordsize;
+ buf+=j;
+ saved_c=saved_rep=0;
+ if (0==(len-=j)) return;
+ goto again;
+ } /* Current non-repeat width can be further increased */
+ }
+ assert(j==len);
+ record_left-=j;
+ assert(saved_rep<128);
+ assert(saved_c<128);
+}
+
+/* --- */
+
+#if USE_BUILTIN_ZIP
+// bool FlateEncode::locked=false;
+
+#if PTS_DEFL_RIPPED_ZLIB
+FlateEncode::FlateEncode(GenBuffer::Writable &out_, unsigned level_)
+ :out(out_) {
+ // assert(!locked); locked /* locking is not necessary anymore */
+ // pts_deflate_init(&fs); /* obsolete */
+ zs.total_in=0;
+ zs.total_out=0;
+ zs.workspace=workspace;
+ zs.msg=(char*)0;
+ zs.state=(struct zlib_internal_state*)0;
+ zs.data_type=Z_UNKNOWN; /* Imp: do we have to initialize it? */
+ assert(zlib_deflate_workspacesize()+(unsigned)0<sizeof(workspace) && "Flate workspace too small");
+ if (Z_OK!=zlib_deflateInit(&zs, level_))
+ Error::sev(Error::EERROR) << "Flate init error (out of memory?)" << (Error*)0;
+}
+
+void FlateEncode::vi_write(char const*buf, slen_t len) {
+ slen_t got, zgot;
+ /* fprintf(stderr,"wcall\n"); */
+ zs.next_in=(unsigned char*)const_cast<char*>(buf); zs.avail_in=len;
+ if (len==0) { /* flush all output */
+ do { /* SUXX: C compiler should emit a warning: while (1) { ... } while(...); */
+ zs.next_out=(unsigned char*)obuf; zs.avail_out=sizeof(obuf);
+ /* fprintf(stderr,"wdone zai=%d zao=%d\n", zs.avail_in, zs.avail_out); */
+ if (Z_STREAM_END!=(zgot=zlib_deflate(&zs, Z_FINISH)) && Z_OK!=zgot)
+ Error::sev(Error::EERROR) << "Flate close error: " << zs.msg << (Error*)0;
+ got=sizeof(obuf)-zs.avail_out;
+ /* fprintf(stderr, "got=%u zgot=%d Z_OK=%d\n", got, zgot, Z_OK); */
+ if (got>0) out.vi_write(obuf, got);
+ } while (zgot==Z_OK);
+ /* Dat: zlib_deflateEnd() will be called in the destructur */
+ out.vi_write(0,0); /* Signal EOF */
+ /* Dat: zlib_deflate() adds RFC 1950 header and adler32 checksum automatically */
+ } else {
+ do {
+ /* fprintf(stderr,"writ\n"); */
+ zs.next_out=(unsigned char*)obuf; zs.avail_out=sizeof(obuf);
+ if (Z_OK!=zlib_deflate(&zs, 0))
+ Error::sev(Error::EERROR) << "Flate write error: " << zs.msg << (Error*)0;
+ if (0<(got=sizeof(obuf)-zs.avail_out)) out.vi_write(obuf, got);
+ } while (0!=zs.avail_in);
+ }
+}
+#else
+FlateEncode::FlateEncode(GenBuffer::Writable &out_, unsigned level_)
+ :out(out_)
+ ,s1(1)
+ ,s2(0)
+ ,had_header(false) {
+ // assert(!locked); locked /* locking is not necessary anymore */
+ // pts_deflate_init(&fs); /* obsolete */
+ fs=pts_defl_new(
+ /*zpfwrite=*/ gen_write,
+ /*zpfmalloc=*/ gen_malloc,
+ /*zpffree=*/ gen_free,
+ /*pack_level=*/ level_,
+ /*zfile=*/ (void*)&out_
+ );
+ if (fs==NULL) Error::sev(Error::EERROR) << "Flate init error (out of memory?)" << (Error*)0;
+}
+void *FlateEncode::gen_malloc(unsigned n) {
+ return operator new(n);
+ // return new char[n];
+}
+void FlateEncode::gen_free(void *p) {
+ /*return*/ operator delete(p);
+ // delete [] (char*)p;
+}
+
+void FlateEncode::vi_write(char const*buf, slen_t len) {
+ register s_t sold;
+ register char const*p=buf; char const*pend=p+len;
+ (void)sold;
+ if (!had_header) {
+ out.vi_write("\x78\xda",2); /* ZLIB (RFC 1950): max compression header */
+ had_header=true;
+ }
+ if (len==0) { /* EOF: send trailer */
+ fs->deflate2(0,0,fs); /* Let the compressor flush its buffers. */
+ if (fs->err!=0) Error::sev(Error::EERROR) << "Flate compression error" << (Error*)0;
+ fs->delete2(fs);
+ fs=(struct pts_defl_interface*)NULL;
+ if (s1>=65521) s1-=65521;
+ if (s2>=65521) s2-=65521;
+ unsigned char trailer[4];
+ trailer[0]=s2>>8; trailer[1]=s2&255; trailer[2]=s1>>8; trailer[3]=s1&255;
+ out.vi_write((char const*)trailer,4);
+ out.vi_write(0,0); /* Signal EOF */
+ return;
+ }
+ assert(fs!=NULL);
+
+ /* From rfc1950.txt:
+ Adler-32 is composed of two sums accumulated per byte: s1 is
+ the sum of all bytes, s2 is the sum of all s1 values. Both sums
+ are done modulo 65521. s1 is initialized to 1, s2 to zero. The
+ Adler-32 checksum is stored as s2*65536 + s1 in most-
+ significant-byte first (network) order.
+ */
+ /* Update Adler-32 checksum */
+ while (p!=pend) {
+ #if SIZEOF_INT>2
+ if ((s1+=*(unsigned char const*)p)>=65521) s1-=65521;
+ if ((s2+=s1)>=65521) s2-=65521;
+ #elif SIZEOF_SHORT==2
+ sold=s1;
+ if ((s1+=*(unsigned char const*)p))<sold) s1+=15; /* 15==65536-21 */
+ sold=s2;
+ s2=(s2+s1)&0xffff;
+ if ((s2+=s1)<sold) s2+=15;
+ #else
+ /* vvv 0xffff is needed since unsigned short may be > 0..65535 */
+ sold=s1;
+ s1=(s1+*(unsigned char const*)p)&0xffff;
+ if (s1<sold) s1+=15; /* 15==65536-21 */
+ sold=s2;
+ s2=(s2+s1)&0xffff;
+ if (s2<sold) s2+=15;
+ #endif
+ p++;
+ }
+ while (len>=0x8000) { fs->deflate2(const_cast<char*>(buf),0x8000, fs); len-=0x8000; buf+=0x8000; }
+ if (len!=0) fs->deflate2(const_cast<char*>(buf),len, fs);
+}
+#endif /* PTS_DEFL_RIPPED_ZLIB */
+#endif /* USE_BUILTIN_ZIP */
+
+int /*FlateEncode::*/gen_write(char *block, unsigned len, void *zfile) {
+ static_cast<GenBuffer::Writable*>(zfile)->vi_write(block, len);
+ return 0;
+}
+
+
+/* --- */
+
+#if USE_BUILTIN_FAXE
+void* CCITTFaxEncode::gen_xalloc(unsigned n) {
+ return operator new(n);
+ // void *ret; if ((ret=malloc(n))==0) abort(); return ret;
+}
+void CCITTFaxEncode::gen_free(void *ptr) {
+ /*return*/ operator delete(ptr);
+ // free(ptr);
+}
+void CCITTFaxEncode::gen_memset(void *s, int c, unsigned n) {
+ /*return*/ memset(s,c,n);
+}
+void CCITTFaxEncode::gen_memcpy(void *dest, const void *src, unsigned n) {
+ /*return*/ memcpy(dest, src, n);
+}
+CCITTFaxEncode::CCITTFaxEncode(GenBuffer::Writable &out_, slendiff_t K, slen_t Columns, bool EndOfLine, bool BlackIs1): out(out_) {
+ sCFEs.memset_=gen_memset;
+ sCFEs.xalloc_=gen_xalloc;
+ sCFEs.free_=gen_free;
+ sCFEs.memcpy_=gen_memcpy;
+ s_CFE_template.set_defaults((stream_state*)&sCFEs);
+ sCFEs.K=K;
+ sCFEs.Columns=Columns;
+ sCFEs.EndOfLine=EndOfLine;
+ sCFEs.BlackIs1=BlackIs1;
+ const int cf_max_height=(unsigned)-1/2-100; /* Dat: was slen_t */
+ if (sCFEs.K < -cf_max_height || sCFEs.K > cf_max_height /* Dat: .K is an int */
+ || sCFEs.Columns < 0 || sCFEs.Columns > cfe_max_width /* Dat: .Columns is an int */
+ || sCFEs.Rows < 0 || sCFEs.Rows > cf_max_height /* Dat: .Rows is an int */
+ || sCFEs.DamagedRowsBeforeError < 0
+ || sCFEs.DamagedRowsBeforeError > cf_max_height /* Dat: .DamagedRowsBeforeError is an int */
+ || sCFEs.DecodedByteAlign < 1 || sCFEs.DecodedByteAlign > 16
+ || (sCFEs.DecodedByteAlign & (sCFEs.DecodedByteAlign - 1)) != 0
+ ) Error::sev(Error::EERROR) << "pts_fax: invalid params" << (Error*)0;
+ if (0!=s_CFE_template.init((stream_state*)&sCFEs))
+ Error::sev(Error::EERROR) << "pts_fax: init failed" << (Error*)0;
+ #if __CHECKER__
+ memset(&r, 0, sizeof(r));
+ memset(&w, 0, sizeof(w));
+ #endif
+ r.ptr=rlimit=rbuf-1;
+ hard=rbuf+sizeof(rbuf)-1;
+ assert(hard-r.ptr>=(int)s_CFE_template.min_in_size);
+}
+
+void CCITTFaxEncode::vi_write(char const*buf, slen_t len) {
+ int pog;
+ // unsigned char *save_wptr;
+ if (len==0) {
+ r.limit=rlimit;
+ do {
+ w.ptr=wbuf-1;
+ w.limit=wbuf+sizeof(wbuf)-1;
+ assert(w.limit-w.ptr>=(int)s_CFE_template.min_out_size);
+ pog=s_CFE_template.process((stream_state*)&sCFEs, &r, &w, /*last:*/ true);
+ // fprintf(stderr, "pog=%d write=%d last=%d\n", pog, w.ptr-(wbuf-1), true);
+ assert(pog!=PTSFAX_ERRC); /* /CCITTFaxEncode filter must accept any input */
+ assert(pog!=PTSFAX_EOFC); /* /CCITTFaxEncode filter doesn't have EOD markers */
+ if (w.ptr!=wbuf-1) out.vi_write((char const*)wbuf, w.ptr-(wbuf-1));
+ } while (pog==1);
+ s_CFE_template.release((stream_state*)&sCFEs);
+ out.vi_write(0,0); /* propagate EOF */
+ return;
+ }
+
+ while (len!=0) {
+ assert(r.ptr==rbuf-1);
+ assert(hard>rlimit);
+ unsigned clen=hard-rlimit;
+ if (clen>len) clen=len;
+ assert(clen>0);
+ // fprintf(stderr, "clen=%u\n", clen);
+ memcpy(rlimit+1, buf, clen);
+ rlimit+=clen;
+ buf+=clen;
+ len-=clen;
+ /* if (r.ptr==rlimit) break; */
+ r.limit=rlimit;
+ do {
+ w.ptr=wbuf-1;
+ w.limit=wbuf+sizeof(wbuf)-1;
+ assert(w.limit-w.ptr>=(int)s_CFE_template.min_out_size);
+ pog=s_CFE_template.process((stream_state*)&sCFEs, &r, &w, /*last:*/ false);
+ // fprintf(stderr, "len=%d pog=%d write=%d last=%d\n", len, pog, w.ptr-(wbuf-1), false);
+ assert(pog!=PTSFAX_ERRC); /* /CCITTFaxEncode filter must accept any input */
+ assert(pog!=PTSFAX_EOFC); /* /CCITTFaxEncode filter doesn't have EOD markers */
+ if (w.ptr!=wbuf-1) out.vi_write((char const*)wbuf, w.ptr-(wbuf-1));
+ } while (pog==1);
+ // assert(pog!=1); /* not true: output space is enough (sizeof(wbuf)>min_out_size) */
+ assert(pog==0); /* more input is needed */
+ if (r.ptr!=rbuf-1) {
+ // fprintf(stderr, "limit=%d\n", rlimit-r.ptr);
+ memmove(rbuf, r.ptr+1, rlimit-r.ptr);
+ rlimit=rbuf-1+(rlimit-r.ptr);
+ r.ptr=rbuf-1;
+ }
+ }
+ // fprintf(stderr, "done\n");
+}
+#endif /* USE_BUILTIN_FAXE */
+
+/* --- */
+
+#if USE_BUILTIN_LZW
+LZWEncode::LZWEncode(GenBuffer::Writable &out_): out(out_) {
+ fs.tif_writer=/*FlateEncode::*/gen_write;
+ fs.tif_sout=(void*)&out_;
+ if (0==pts_lzw_init(&fs)) Error::sev(Error::EERROR) << "LZW init error" << (Error*)0;
+}
+
+void LZWEncode::vi_write(char const*buf, slen_t len) {
+ /* Imp: report real error _reason_ (if appropriate?? ) */
+ if (len==0) {
+ if (0==fs.tif_feeder(0,0,&fs)) goto we;
+ out.vi_write(0,0); /* propagate EOF */
+ return;
+ }
+ while (len>=0x8000) {
+ if (0==fs.tif_feeder(const_cast<char*>(buf),0x8000,&fs)) we:
+ Error::sev(Error::EERROR) << "LZW write error" << (Error*)0;
+ len-=0x8000; buf+=0x8000;
+ }
+ if (len!=0 && 0==fs.tif_feeder(const_cast<char*>(buf),len,&fs)) goto we;
+}
+#endif /* USE_BUILTIN_LZW */
+
+/* --- */
+
+#if !USE_BUILTIN_LZW
+Lzw_codecEncode::Lzw_codecEncode(GenBuffer::Writable &out_, char const*filter_psname)
+ :p(out_) {
+ (void)filter_psname;
+}
+void Lzw_codecEncode::vi_write(char const*buf, slen_t len) { p.vi_write(buf,len); }
+
+/* Imp: figure out path-to-gs: gs or gswin32c */
+Lzw_codecEncode::P::P(GenBuffer::Writable &out_)
+ // :PipeEncoder(out_, ">/tmp/t cat - cjpeg quality %i", quality), rgbp(rgbp_) {
+ // :Filter::PipeE(out_, "cjpeg -quality %i >%D", quality), rgbp(rgbp_) {
+ :Filter::PipeE(out_, "lzw_codec encode >%D") {}
+#endif
+
+/* --- */
+
+CjpegEncode::CjpegEncode(GenBuffer::Writable &out_, char const*filter_psname, slen_t Columns, slen_t Rows, bool rgbp_, unsigned char quality)
+ :p(out_, Columns, Rows, rgbp_, quality) {
+ (void)filter_psname;
+}
+void CjpegEncode::vi_write(char const*buf, slen_t len) { p.vi_write(buf,len); }
+
+/* Imp: figure out path-to-gs: gs or gswin32c */
+CjpegEncode::P::P(GenBuffer::Writable &out_, slen_t Columns, slen_t Rows, bool rgbp_, unsigned char quality)
+ // :PipeEncoder(out_, ">/tmp/t cat - cjpeg quality %i", quality), rgbp(rgbp_) {
+ :Filter::PipeE(out_, "cjpeg -quality %i >%D", quality), rgbp(rgbp_) {
+ /* Dat: we're extremely lucky that cjpeg can read PGM or PPM files from stdin */
+ // operator<<("P5 width height 255\n"); /* RAWBITS PGM */
+ // operator<<("P6 width height 255\n"); /* RAWBITS PPM */
+ *this << (rgbp_?"P6 ":"P5 ") << Columns << ' ' << Rows << " 255\n";
+}
+void CjpegEncode::P::vi_copy(FILE *f) {
+ char r[10];
+ static char jfif[9]="\377\340\000\020JFIF";
+ static unsigned char adobe[16]= {
+ 0xff, /* marker */
+ 0xee, /* APP14 */
+ 0, /* length-hi */
+ 14, /* length-lo */
+ 'A', 'd', 'o', 'b', 'e', /* ID */
+ 1, /* version-hi */
+ 0, /* version-lo */
+ 0, 0, /* flags0 */
+ 0, 0, /* flags1 */
+ 0, /* ColorTransform */
+ };
+ if (MACRO_GETC(f)!=0xff || MACRO_GETC(f)!=0xd8 || fread(r, 1, 8, f)!=8) {
+ bad: Error::sev(Error::EERROR) << "CjpegEncode: cjpeg created bad JPEG" << (Error*)0;
+ }
+ out.vi_putcc((char)0xff);
+ out.vi_putcc((char)0xd8);
+ r[9]=r[3]; r[3]='\020';
+ if ((unsigned char)r[9]>=6 && 0==memcmp(r, jfif, 8)) { /* JFIF marker */
+ r[3]=r[9]; unsigned skip=r[9]-6;
+ out.vi_write(r, 8);
+ while (skip--!=0) out.vi_putcc(MACRO_GETC(f));
+ }
+ if (ferror(f) || feof(f)) goto bad;
+ /* Now we can emit the Adobe marker. */
+ adobe[sizeof(adobe)-1]=rgbp==true; /* ColorTransform value 0 for Gray, 1 for RGB->YCbCr */
+ out.vi_write((char*)adobe, sizeof(adobe));
+ /* vvv Dat: pacify VC6.0: Filter::PipeE::vi_copy(f); doesn't work */
+ PipeE::vi_copy(f);
+ /* ^^^ copy rest of file verbatim */
+ // ((Filter::PipeE)*this).vi_copy(f);
+}
+
+/* --- */
+
+GSEncode::GSEncode(GenBuffer::Writable &out_, char const*filter_psname)
+ :p(out_, filter_psname) {}
+void GSEncode::vi_write(char const*buf, slen_t len) { p.vi_write(buf,len); }
+
+/* Imp: figure out path-to-gs: gs or gswin32c */
+GSEncode::P::P(GenBuffer::Writable &out_, char const*filter_psname)
+ :Filter::PipeE(out_, "gs -s_OFN=%D -dNODISPLAY -q - >%E")
+ {
+ operator<<("{/o _OFN(w)file ");
+ operator<<(filter_psname);
+ operator<<(" filter def/s 4096 string def"
+ "{currentfile s readstring exch o exch writestring not{exit}if}loop "
+ "o closefile quit}bind exec\n");
+}
+void GSEncode::P::vi_check() {
+ /* If STDOUT of gs is not empty, then it is very probably an error message. */
+ // tmpename.term0(); /* already is */
+ assert(tmpename.end_()[0]=='\0');
+ if (0!=Files::statSize(tmpename())) Error::sev(Error::EERROR) << "GSEncode: GS runtime error" << (Error*)0;
+ /* Imp: display a meaningful error message */
+}
+
+/* --- */
+
+PSEncoder* PSEncoder::newASCIIHexEncode(GenBuffer::Writable &out_,unsigned maxcpl_) {
+ // SimBuffer::B fp; (fp << maxcpl_ << " pop/ASCIIHexEncode").term0();
+ // PSEncoder *ret=new GSEncode(out_, fp());
+ PSEncoder *ret=new ASCIIHexEncode(out_,maxcpl_);
+ // ret->shortname="AHx"; ret->longname="ASCIIHex";
+ // ret->filter_psname << fp;
+ return ret;
+}
+PSEncoder* PSEncoder::newASCII85Encode(GenBuffer::Writable &out_,unsigned maxcpl_) {
+ // SimBuffer::B fp; (fp << maxcpl_ << " pop/ASCII85Encode").term0();
+ PSEncoder *ret=new ASCII85Encode(out_,maxcpl_);
+ // PSEncoder *ret=new GSEncode(out_, fp());
+ // ret->shortname="A85"; ret->longname="ASCII85";
+ // ret->filter_psname << fp;
+ return ret;
+}
+PSEncoder* PSEncoder::newCCITTFaxEncode(GenBuffer::Writable &out_,slendiff_t K, slen_t Columns, bool EndOfLine, bool BlackIs1) {
+ #if USE_BUILTIN_FAXE
+ return new CCITTFaxEncode(out_, K, Columns, EndOfLine, BlackIs1);
+ #else
+ // (void)out_; (void)K; (void)Columns;
+ // assert(0 && "unimplemented");
+ SimBuffer::B fp("<< /K ");
+ fp << K << "/Columns " << Columns;
+ if (EndOfLine) fp << "/EndOfLine true"; /* PS default: false */
+ if (BlackIs1) fp << "/BlackIs1 true";
+ (fp << ">>/CCITTFaxEncode").term0();
+ // fprintf(stderr, "fp=(%s)\n", fp());
+ PSEncoder *ret=new GSEncode(out_, fp());
+ // ret->shortname="CCF"; ret->longname="CCITTFax";
+ // ret->filter_psname << fp; /* Dat: this could be made faster */
+ return ret;
+ #endif
+}
+PSEncoder* PSEncoder::newLZWEncode(GenBuffer::Writable &out_) {
+#if USE_BUILTIN_LZW
+ SimBuffer::B fp("/LZWEncode");
+ PSEncoder *ret=new LZWEncode(out_);
+ // PSEncoder *ret=new GSEncode(out_, fp());
+ // ret->shortname="LZW"; ret->longname="LZW";
+ // ret->filter_psname << fp;
+ return ret;
+#else
+ (void)out_;
+ #if 0
+ Error::sev(Error::EERROR) << "LZW not supported in this compilation of sam2p" << (Error*)0;
+ #endif
+ Error::sev(Error::WARNING) << "LZW: please `configure --enable-lzw' for builtin /Compression/LZW support" << (Error*)0;
+ #if 0
+ /* This is useless, because gs 5.50--7.04 have dummy LZW compressor:
+ * it emits a correct LZW stream, but does no real compression, and
+ * the file size is often increased.
+ */
+ PSEncoder *ret=new GSEncode(out_, "/LZWEncode");
+ // ret->shortname="LZW"; ret->longname="LZW";
+ // ret->filter_psname << "/LZWEncode";
+ return ret;
+ #endif
+ #if 1 /* ask lzw_codec from the author of sam2p */
+ return new Lzw_codecEncode(out_, "/LZWEncode");
+ #endif
+ return 0;
+#endif
+}
+PSEncoder* PSEncoder::newFlateEncode(GenBuffer::Writable &out_, signed Effort) {
+ // (void)out_; (void)K; (void)Columns;
+ // assert(0 && "unimplemented");
+ if (Effort==0) {
+ PSEncoder *ret=new FlateStoreEncode(out_);
+ // ret->shortname="Fla"; ret->longname="Flate";
+ // ret->filter_psname << fp;
+ return ret;
+ }
+ if (Effort<1 || Effort>9) Effort=5;
+ #if USE_BUILTIN_ZIP
+ PSEncoder *ret=new FlateEncode(out_, Effort);
+ #else
+ SimBuffer::B fp("<</Effort "); (fp << Effort << ">>/FlateEncode").term0();
+ PSEncoder *ret=new GSEncode(out_, fp());
+ #endif
+ // ret->shortname="Fla"; ret->longname="Flate";
+ // ret->filter_psname << fp;
+ return ret;
+}
+PSEncoder* PSEncoder::newRunLengthEncode(GenBuffer::Writable &out_, slen_t RecordSize) {
+ SimBuffer::B fp; (fp << RecordSize << "/RunLengthEncode").term0();
+ PSEncoder *ret=new RunLengthEncode(out_, RecordSize);
+ // PSEncoder *ret=new GSEncode(out_, fp());
+ // ret->shortname="RL"; ret->longname="RunLength";
+ // ret->filter_psname << fp;
+ return ret;
+}
+
+PSEncoder* PSEncoder::newDCTIJGEncode(GenBuffer::Writable &out_,
+ slen_t Columns,
+ slen_t Rows,
+ unsigned char Colors, /*1..4*/
+ unsigned char quality /*libJPEG quality: 0..100 */
+) {
+ /* Dat: this supports only the Gray and RGB color spaces of JPEG */
+ param_assert(Colors==1 || Colors==3);
+ param_assert(/* quality>=0 && */ quality <=100);
+ SimBuffer::B fp("<<IJG ");
+ (fp<< "/Columns " << Columns
+ << "/Rows " << Rows
+ << "/Colors " << (unsigned)Colors
+ << ">>/DCTEncode").term0();
+ /* Dat: the default of /ColorTransform (defined in DCTEncode in
+ subsubsection 3.13.3 in PLRM.pdf) is just perfect. */
+ PSEncoder *ret=new CjpegEncode(out_, fp(), Columns, Rows, Colors==3, quality);
+ // ret->longname=ret->shortname="DCT"; ret->filter_psname << fp;
+ return ret;
+}
+
+PSEncoder* PSEncoder::newDCTEncode(GenBuffer::Writable &out_,
+ slen_t Columns,
+ slen_t Rows,
+ unsigned char Colors, /*1..4*/
+ unsigned char quality, /*libJPEG quality: 0..100 */
+ unsigned char const*HSamples, /*all 1..4, NULLP OK*/
+ unsigned char const*VSamples, /*all 1..4, NULLP OK*/
+ unsigned char (*QuantTables)[64], /*NULLP OK*/
+ double QFactor, /*0..1000000*/
+ unsigned numHuffTables,
+ unsigned char **HuffTables, /*NULLP OK*/
+ unsigned char ColorTransform /*0,1,2 3=default*/
+) {
+ (void)quality;
+ (void)QuantTables;
+ (void)QFactor;
+ (void)numHuffTables;
+ (void)HuffTables;
+ SimBuffer::B tmp;
+ /* Imp: respect quality */
+ /* Imp: respect QFactor (double) */
+ /* Imp: respect QuantTables */
+ /* Imp: respect numHuffTables, HuffTables */
+
+ SimBuffer::B fp("<<");
+ fp << "/Columns " << Columns
+ << "/Rows " << Rows
+ << "/Colors " << (unsigned)Colors;
+ if (HSamples!=(unsigned char const*)NULLP) {
+ tmp.clear(); tmp.vi_write((char const*)HSamples, (unsigned)Colors);
+ fp << "/HSamples "; fp.appendDumpPS(tmp,true);
+ }
+ if (VSamples!=(unsigned char const*)NULLP) {
+ tmp.clear(); tmp.vi_write((char const*)VSamples, (unsigned)Colors);
+ fp << "/VSamples "; fp.appendDumpPS(tmp,true);
+ }
+ if (ColorTransform!=3) fp << "/ColorTransform " << (unsigned)ColorTransform;
+ (fp << ">>/DCTEncode").term0();
+
+ // PSEncoder *ret=new DCTEncode(out_,? ? ?);
+ PSEncoder *ret=new GSEncode(out_, fp());
+ // ret->shortname="DCT"; ret->longname="DCT";
+ // ret->filter_psname << fp;
+ return ret;
+}
+
+PSEncoder* PSEncoder::newDCTEncode(GenBuffer::Writable &out_,
+ slen_t Columns,
+ slen_t Rows,
+ unsigned char Colors, /*1..4*/
+ unsigned char ColorTransform, /*0,1,2 3=default*/
+ SimBuffer::Flat const& other_parameters
+) {
+ SimBuffer::B fp("<<");
+ fp << "/Columns " << Columns
+ << "/Rows " << Rows
+ << "/Colors " << (unsigned)Colors;
+ if (ColorTransform!=3) fp << "/ColorTransform " << (unsigned)ColorTransform;
+ (fp << other_parameters << ">>/DCTEncode").term0();
+ PSEncoder *ret=new GSEncode(out_, fp());
+ // ret->shortname="DCT"; ret->longname="DCT";
+ // ret->filter_psname << fp;
+ return ret;
+}
+
+/* --- */
+
+TIFFPredictor2::TIFFPredictor2(GenBuffer::Writable &out_, unsigned char bpc_, slen_t columns_, unsigned char cpp_)
+ : h(0), bpc(bpc_), cpp(cpp_), out(out_) {
+ param_assert(cpp_*bpc_<=32);
+ rlen=(columns_*cpp_*bpc_+7)>>3; /* BUGFIX at Tue Mar 12 12:09:51 CET 2002 */
+ op=obuf=new unsigned char[rlen];
+}
+
+void TIFFPredictor2::vi_write(char const*buf, slen_t len) {
+ unsigned char const *p=(unsigned char const*)buf, *pend0=p+len;
+ slen_t opleft=rlen-(op-obuf);
+ register unsigned int i, d, o, bpccpp;
+ if (len==0) {
+ assert(opleft==rlen); /* unflushed (half-ready) row disallowed */
+ assert(obuf!=NULLP);
+ delete [] obuf;
+ obuf=(unsigned char*)NULLP;
+ out.vi_write(0,0);
+ return;
+ }
+ bpccpp=(cpp-1)*bpc;
+ if (bpc==1) {
+ while (p!=pend0) {
+ i=*p++;
+ d=(i>>7); o =((d-((h>>bpccpp)))&1)<<7; h=(h<<1)|d;
+ d=(i>>6); o|=((d-((h>>bpccpp)))&1)<<6; h=(h<<1)|d;
+ d=(i>>5); o|=((d-((h>>bpccpp)))&1)<<5; h=(h<<1)|d;
+ d=(i>>4); o|=((d-((h>>bpccpp)))&1)<<4; h=(h<<1)|d;
+ d=(i>>3); o|=((d-((h>>bpccpp)))&1)<<3; h=(h<<1)|d;
+ d=(i>>2); o|=((d-((h>>bpccpp)))&1)<<2; h=(h<<1)|d;
+ d=(i>>1); o|=((d-((h>>bpccpp)))&1)<<1; h=(h<<1)|d;
+ d=(i ); o|=((d-((h>>bpccpp)))&1) ; h=(h<<1)|d;
+ *op++=o;
+ if (--opleft==0) { h=0; out.vi_write((char*)obuf,rlen); op=obuf; opleft=rlen; }
+ }
+ } else if (bpc==2) {
+ while (p!=pend0) {
+ i=*p++;
+ d=(i>>6); o =((d-((h>>bpccpp)))&3)<<6; h=(h<<2)|d; // fprintf(stderr,"d=%#x\n", d);
+ d=(i>>4); o|=((d-((h>>bpccpp)))&3)<<4; h=(h<<2)|d;
+ d=(i>>2); o|=((d-((h>>bpccpp)))&3)<<2; h=(h<<2)|d;
+ d=(i ); o|=((d-((h>>bpccpp)))&3) ; h=(h<<2)|d;
+ *op++=o;
+ if (--opleft==0) { h=0; out.vi_write((char*)obuf,rlen); op=obuf; opleft=rlen; }
+ }
+ } else if (bpc==4) {
+ while (p!=pend0) {
+ i=*p++;
+ d=(i>>4); o =((d-((h>>bpccpp)))&15)<<4; h=(h<<4)|d;
+ d=(i ); o|=((d-((h>>bpccpp)))&15) ; h=(h<<4)|d;
+ *op++=o;
+ if (--opleft==0) { h=0; out.vi_write((char*)obuf,rlen); op=obuf; opleft=rlen; }
+ }
+ } else if (bpc==8) {
+ while (p!=pend0) {
+ i=*p++; *op++=((i-((h>>bpccpp)))/*&255*/); h=(h<<8)|i;
+ if (--opleft==0) { h=0; out.vi_write((char*)obuf,rlen); op=obuf; opleft=rlen; }
+ }
+ } else assert(0);
+}
+
+/* --- */
+
+PNGPredictorNone::PNGPredictorNone(GenBuffer::Writable &out_, unsigned char bpc_, slen_t columns_, unsigned char cpp_)
+ : opleft(0), out(out_) {
+ rlen=(columns_*cpp_*bpc_+7)>>3;
+}
+
+void PNGPredictorNone::vi_write(char const*buf, slen_t len) {
+ if (len==0) {
+ assert(opleft==0); /* unflushed (half-ready) row disallowed */
+ out.vi_write(0,0);
+ return;
+ }
+ /* The following code just inserts a '\0' in front of each scanline */
+ /* Imp: make it faster by collapsing vi_writes */
+ if (opleft==0) { opleft=rlen; out.vi_write("\0",1); } /* Scanline (row) header: describes predictor used */
+ while (len>opleft) {
+ out.vi_write(buf,opleft);
+ buf+=opleft; len-=opleft;
+ opleft=rlen; out.vi_write("\0",1); /* Scanline (row) header: describes predictor used */
+ }
+ if (len!=0) out.vi_write(buf,len);
+ opleft-=len;
+}
+
+/* --- */
+
+PNGPredictorSub::PNGPredictorSub(GenBuffer::Writable &out_, unsigned char bpc_, slen_t columns_, unsigned char cpp_)
+ : h(0), out(out_) {
+ param_assert(cpp_*bpc_<=32);
+ rlen=(columns_*cpp_*bpc_+7)>>3;
+ op=obuf=1+new unsigned char[rlen+1];
+ obuf[-1]='\1'; /* Scanline (row) header: describes predictor used */
+ bpccpp=((cpp_*bpc_+7)&~7)-8;
+}
+
+void PNGPredictorSub::vi_write(char const*buf, slen_t len) {
+ unsigned char const *p=(unsigned char const*)buf, *pend0=p+len;
+ slen_t opleft=rlen-(op-obuf);
+ register unsigned int i;
+ if (len==0) {
+ assert(opleft==rlen); /* unflushed (half-ready) row disallowed */
+ assert(obuf!=NULLP);
+ delete [] (obuf-1);
+ obuf=(unsigned char*)NULLP;
+ out.vi_write(0,0);
+ return;
+ }
+ while (p!=pend0) {
+ i=*p++; *op++=((i-((h>>bpccpp)))/*&255*/); h=(h<<8)|i;
+ if (--opleft==0) { h=0;
+ out.vi_write((char*)obuf-1,rlen+1); op=obuf; opleft=rlen;
+ }
+ }
+}
+
+/* --- */
+
+PNGPredictorUp::PNGPredictorUp(GenBuffer::Writable &out_, unsigned char bpc_, slen_t columns_, unsigned char cpp_)
+ : out(out_) {
+ rlen=(columns_*cpp_*bpc_+7)>>3;
+ // fprintf(stderr, "rUp.rlen=%u cpp=%u bpc=%u\n", rlen, cpp_, bpc_);
+ op=obuf=1+new unsigned char[2*rlen+1];
+ oq=op+rlen; /* prev scanline */
+ memset(oq, '\0', rlen);
+ obuf[-1]='\2'; /* Scanline (row) header: describes predictor used */
+}
+
+void PNGPredictorUp::vi_write(char const*buf, slen_t len) {
+ unsigned char const *p=(unsigned char const*)buf, *pend0=p+len;
+ slen_t opleft=rlen-(op-obuf);
+ if (len==0) {
+ assert(opleft==rlen); /* unflushed (half-ready) row disallowed */
+ assert(obuf!=NULLP);
+ delete [] (obuf-1);
+ obuf=(unsigned char*)NULLP;
+ out.vi_write(0,0);
+ return;
+ }
+ while (p!=pend0) {
+ *op++=((*p-*oq)/*&255*/); *oq++=*p++;
+ if (--opleft==0) {
+ out.vi_write((char*)obuf-1,rlen+1); opleft=rlen;
+ op=obuf; oq=obuf+rlen;
+ }
+ }
+}
+
+/* --- */
+
+PNGPredictorAverage::PNGPredictorAverage(GenBuffer::Writable &out_, unsigned char bpc_, slen_t columns_, unsigned char cpp_)
+ : h(0), /*g(0),*/ out(out_) {
+ param_assert(cpp_*bpc_<=32);
+ rlen=(columns_*cpp_*bpc_+7)>>3;
+ op=obuf=1+new unsigned char[2*rlen+1];
+ oq=op+rlen; /* prev scanline */
+ memset(oq, '\0', rlen);
+ obuf[-1]='\3'; /* Scanline (row) header: describes predictor used */
+ bpccpp=((cpp_*bpc_+7)&~7)-8;
+}
+
+void PNGPredictorAverage::vi_write(char const*buf, slen_t len) {
+ unsigned char const *p=(unsigned char const*)buf, *pend0=p+len;
+ slen_t opleft=rlen-(op-obuf);
+ register unsigned int i;
+ if (len==0) {
+ assert(opleft==rlen); /* unflushed (half-ready) row disallowed */
+ assert(obuf!=NULLP);
+ delete [] (obuf-1);
+ obuf=(unsigned char*)NULLP;
+ out.vi_write(0,0);
+ return;
+ }
+ while (p!=pend0) {
+ /* vvv Data: *og+h can be 0..510 */
+ i=*p; *op++=i-((((h>>bpccpp)&255)+*oq)>>1); h=(h<<8)|i; *oq++=*p++;
+ // i=*p; *op++=(*p-((*oq+h)>>1)/*&255*/); h=i; *oq++=*p++;
+ if (--opleft==0) {
+ out.vi_write((char*)obuf-1,rlen+1); opleft=rlen;
+ op=obuf; oq=obuf+rlen; h=0;
+ }
+ }
+}
+
+/* --- */
+
+/* Dat: egcs-2.91.60 is buggy */
+// static inline unsigned abs_(unsigned i) { return ((signed)i)<0 ? -i : i; }
+static inline unsigned abs_(unsigned i) { return ((signed)i)<0 ? (i*-1) : i; }
+
+static inline unsigned paeth_predictor(unsigned a, unsigned b, unsigned c) {
+ /* Code ripped from RFC 2083 (PNG specification), which also says:
+ * The calculations within the PaethPredictor function must be
+ * performed exactly, without overflow. Arithmetic modulo 256 is to
+ * be used only for the final step of subtracting the function result
+ * from the target byte value.
+ */
+ /* a = left, b = above, c = upper left */
+ unsigned p = a + b - c; /* initial estimate */
+ unsigned pa = abs_(p - a); /* distances to a, b, c */
+ unsigned pb = abs_(p - b);
+ unsigned pc = abs_(p - c);
+ // assert(abs_(3*(-1))==3);
+ // fprintf(stderr, "b=%u c=%u %d %d\n", b, c, p-b, ((signed)(p-b))<0 ? (b-p) : (p-b) );
+ // fprintf(stderr, "pa=%u pb=%u pc=%u\n", pa, pb, pc);
+ assert(pa<=255);
+ assert(pb<=255);
+ assert(pc<=255*2);
+ /* return nearest of a,b,c, breaking ties in order a,b,c. */
+ return (pa <= pb && pa <= pc) ? a
+ : pb <= pc ? b
+ : c;
+}
+
+PNGPredictorPaeth::PNGPredictorPaeth(GenBuffer::Writable &out_, unsigned char bpc_, slen_t columns_, unsigned char cpp_)
+ : h(0), g(0), out(out_) {
+ param_assert(cpp_*bpc_<=32);
+ rlen=(columns_*cpp_*bpc_+7)>>3;
+ op=obuf=1+new unsigned char[2*rlen+2];
+ oq=obuf+rlen+1; /* prev scanline */
+ memset(obuf+rlen, '\0', rlen+1);
+ obuf[-1]='\4'; /* Scanline (row) header: describes predictor used */
+ bpccpp=((cpp_*bpc_+7)&~7)-8;
+}
+
+void PNGPredictorPaeth::vi_write(char const*buf, slen_t len) {
+ unsigned char const *p=(unsigned char const*)buf, *pend0=p+len;
+ slen_t opleft=rlen-(op-obuf);
+ register unsigned int i;
+ if (len==0) {
+ assert(opleft==rlen); /* unflushed (half-ready) row disallowed */
+ assert(obuf!=NULLP);
+ delete [] (obuf-1);
+ obuf=(unsigned char*)NULLP;
+ out.vi_write(0,0);
+ return;
+ }
+ while (p!=pend0) {
+ // assert(0==obuf[rlen] && 4==obuf[-1]);
+ i=*p; *op++=i-paeth_predictor((h>>bpccpp)&255, *oq, (g>>bpccpp)&255);
+ h=(h<<8)|i; g=(g<<8)|*oq; *oq++=*p++;
+ // i=*p; *op++=i-h; h=i; *oq++=*p++;
+ if (--opleft==0) {
+ out.vi_write((char*)obuf-1,rlen+1); opleft=rlen;
+ op=obuf; oq=obuf+rlen+1; h=0; g=0;
+ }
+ }
+}
+
+/* --- */
+
+#if SIZEOF_INT >= 4
+typedef int weight_t;
+#else
+typedef long weight_t;
+#endif
+
+PNGPredictorAutoBadSigned::PNGPredictorAutoBadSigned(GenBuffer::Writable &out_, unsigned char bpc_, slen_t columns_, unsigned char cpp_)
+ : h(0), g(0), out(out_) {
+ param_assert(cpp_*bpc_<=32);
+ opleft=rlen=(columns_*cpp_*bpc_+7)>>3;
+ obuf=new unsigned char[6*rlen+6];
+ o_prior=obuf+rlen+1; /* Prior(x): ooprior[-opleft] */
+ obuf[rlen*1+1]='\0'; o_0=obuf+2*rlen+2;
+ obuf[rlen*2+2]='\1'; o_1=obuf+3*rlen+3;
+ obuf[rlen*3+3]='\2'; o_2=obuf+4*rlen+4;
+ obuf[rlen*4+4]='\3'; o_3=obuf+5*rlen+5;
+ obuf[rlen*5+5]='\4'; o_4=obuf+6*rlen+6;
+ oo[0]=o_0; oo[1]=o_1; oo[2]=o_2; oo[3]=o_3; oo[4]=o_4;
+ memset(obuf, '\0', rlen+1);
+ bpccpp=((cpp_*bpc_+7)&~7)-8;
+}
+
+void PNGPredictorAutoBadSigned::vi_write(char const*buf, slen_t len) {
+ unsigned char const *p=(unsigned char const*)buf, *pend0=p+len;
+ register unsigned int i;
+ register unsigned raw_x_bpp, prior_x, prior_x_bpp;
+ if (len==0) {
+ assert(opleft==rlen); /* unflushed (half-ready) row disallowed */
+ assert(obuf!=NULLP);
+ delete [] obuf;
+ obuf=(unsigned char*)NULLP;
+ out.vi_write(0,0);
+ return;
+ }
+ while (p!=pend0) {
+ raw_x_bpp=(h>>bpccpp) &255;
+ prior_x=*(o_prior-opleft);
+ prior_x_bpp=(g>>bpccpp) &255;
+ i=*p;
+ *(o_0-opleft)=i;
+ *(o_1-opleft)=i-raw_x_bpp;
+ *(o_2-opleft)=i-prior_x;
+ *(o_3-opleft)=i-((raw_x_bpp+prior_x)>>1);
+ *(o_4-opleft)=i-paeth_predictor(raw_x_bpp, prior_x, prior_x_bpp);
+ h=(h<<8)|i; g=(g<<8)|*(o_prior-opleft); *(o_prior-opleft)=*p++;
+ if (--opleft==0) {
+ /* Select the predictor having the smallest signed sum of values. */
+ weight_t min_weight, cur_weight;
+ unsigned min_pred=0, cur_pred;
+ register signed char *beg, *end;
+ min_weight=0; beg=(end=(signed char*)o_0)-rlen; while (beg!=end) min_weight+=*beg++;
+ if (min_weight<0) min_weight*=-1;
+ for (cur_pred=1; cur_pred<=4; cur_pred++) {
+ cur_weight=0; beg=(end=(signed char*)oo[cur_pred])-rlen; while (beg!=end) cur_weight+=*beg++;
+ if (cur_weight<0) cur_weight*=-1;
+ if (cur_weight<min_weight) { min_weight=cur_weight; min_pred=cur_pred; }
+ }
+ // fprintf(stderr, "cp=%u\n", min_pred);
+
+ out.vi_write((char*)(oo[min_pred]-rlen-1),rlen+1);
+ opleft=rlen; h=0; g=0;
+ }
+ }
+}
+
+/* --- */
+
+PNGPredictorAutoBadUnsigned::PNGPredictorAutoBadUnsigned(GenBuffer::Writable &out_, unsigned char bpc_, slen_t columns_, unsigned char cpp_)
+ : h(0), g(0), out(out_) {
+ param_assert(cpp_*bpc_<=32);
+ opleft=rlen=(columns_*cpp_*bpc_+7)>>3;
+ obuf=new unsigned char[6*rlen+6];
+ o_prior=obuf+rlen+1; /* Prior(x): ooprior[-opleft] */
+ obuf[rlen*1+1]='\0'; o_0=obuf+2*rlen+2;
+ obuf[rlen*2+2]='\1'; o_1=obuf+3*rlen+3;
+ obuf[rlen*3+3]='\2'; o_2=obuf+4*rlen+4;
+ obuf[rlen*4+4]='\3'; o_3=obuf+5*rlen+5;
+ obuf[rlen*5+5]='\4'; o_4=obuf+6*rlen+6;
+ oo[0]=o_0; oo[1]=o_1; oo[2]=o_2; oo[3]=o_3; oo[4]=o_4;
+ memset(obuf, '\0', rlen+1);
+ bpccpp=((cpp_*bpc_+7)&~7)-8;
+}
+
+void PNGPredictorAutoBadUnsigned::vi_write(char const*buf, slen_t len) {
+ unsigned char const *p=(unsigned char const*)buf, *pend0=p+len;
+ register unsigned int i;
+ register unsigned raw_x_bpp, prior_x, prior_x_bpp;
+ // unsigned lines=0;
+ if (len==0) {
+ assert(opleft==rlen); /* unflushed (half-ready) row disallowed */
+ assert(obuf!=NULLP);
+ delete [] obuf;
+ obuf=(unsigned char*)NULLP;
+ out.vi_write(0,0);
+ return;
+ }
+ // fprintf(stderr, "rlen=%u len=%u opleft=%u\n", rlen, len, opleft);
+ while (p!=pend0) {
+ raw_x_bpp=(h>>bpccpp) &255;
+ prior_x=*(o_prior-opleft);
+ prior_x_bpp=(g>>bpccpp) &255;
+ i=*p;
+ *(o_0-opleft)=i;
+ *(o_1-opleft)=i-raw_x_bpp;
+ *(o_2-opleft)=i-prior_x;
+ *(o_3-opleft)=i-((raw_x_bpp+prior_x)>>1);
+ *(o_4-opleft)=i-paeth_predictor(raw_x_bpp, prior_x, prior_x_bpp);
+ h=(h<<8)|i; g=(g<<8)|*(o_prior-opleft); *(o_prior-opleft)=*p++;
+ if (--opleft==0) {
+ /* Select the predictor having the smallest unsigned sum of values. */
+ weight_t min_weight, cur_weight;
+ unsigned min_pred=0, cur_pred;
+ register unsigned char *beg, *end;
+ min_weight=0; beg=(end=(unsigned char*)o_0)-rlen; while (beg!=end) min_weight+=*beg++;
+ for (cur_pred=1; cur_pred<=4; cur_pred++) {
+ cur_weight=0; beg=(end=(unsigned char*)oo[cur_pred])-rlen; while (beg!=end) cur_weight+=*beg++;
+ if (cur_weight<min_weight) { min_weight=cur_weight; min_pred=cur_pred; }
+ }
+ // fprintf(stderr, "cp=%u\n", min_pred);
+
+ out.vi_write((char*)(oo[min_pred]-rlen-1),rlen+1);
+ opleft=rlen; h=0; g=0;
+ // lines++;
+ }
+ }
+ // fprintf(stderr, "oen=%u opleft=%u lines=%u\n", len, opleft, lines);
+}
+
+/* --- */
+
+PNGPredictorAuto::PNGPredictorAuto(GenBuffer::Writable &out_, unsigned char bpc_, slen_t columns_, unsigned char cpp_)
+ : h(0), g(0), out(out_) {
+ param_assert(cpp_*bpc_<=32);
+ opleft=rlen=(columns_*cpp_*bpc_+7)>>3;
+ obuf=new unsigned char[6*rlen+6];
+ o_prior=obuf+rlen+1; /* Prior(x): ooprior[-opleft] */
+ obuf[rlen*1+1]='\0'; o_0=obuf+2*rlen+2;
+ obuf[rlen*2+2]='\1'; o_1=obuf+3*rlen+3;
+ obuf[rlen*3+3]='\2'; o_2=obuf+4*rlen+4;
+ obuf[rlen*4+4]='\3'; o_3=obuf+5*rlen+5;
+ obuf[rlen*5+5]='\4'; o_4=obuf+6*rlen+6;
+ oo[0]=o_0; oo[1]=o_1; oo[2]=o_2; oo[3]=o_3; oo[4]=o_4;
+ memset(obuf, '\0', rlen+1);
+ bpccpp=((cpp_*bpc_+7)&~7)-8;
+}
+
+void PNGPredictorAuto::vi_write(char const*buf, slen_t len) {
+ unsigned char const *p=(unsigned char const*)buf, *pend0=p+len;
+ register unsigned int i;
+ register unsigned raw_x_bpp, prior_x, prior_x_bpp;
+ // unsigned lines=0;
+ if (len==0) {
+ assert(opleft==rlen); /* unflushed (half-ready) row disallowed */
+ assert(obuf!=NULLP);
+ delete [] obuf;
+ obuf=(unsigned char*)NULLP;
+ out.vi_write(0,0);
+ return;
+ }
+ // fprintf(stderr, "rlen=%u len=%u opleft=%u\n", rlen, len, opleft);
+ while (p!=pend0) {
+ raw_x_bpp=(h>>bpccpp) &255;
+ prior_x=*(o_prior-opleft);
+ prior_x_bpp=(g>>bpccpp) &255;
+ i=*p;
+ *(o_0-opleft)=i;
+ *(o_1-opleft)=i-raw_x_bpp;
+ *(o_2-opleft)=i-prior_x;
+ *(o_3-opleft)=i-((raw_x_bpp+prior_x)>>1);
+ *(o_4-opleft)=i-paeth_predictor(raw_x_bpp, prior_x, prior_x_bpp);
+ h=(h<<8)|i; g=(g<<8)|*(o_prior-opleft); *(o_prior-opleft)=*p++;
+ if (--opleft==0) {
+ /* Select the predictor having the smallest unsigned sum of values. */
+ weight_t min_weight, cur_weight;
+ unsigned min_pred=0, cur_pred;
+ register signed char *beg, *end;
+ /* abs_(...) here converts '\xFF' to 1. Good. */
+ min_weight=0; beg=(end=(signed char*)o_0)-rlen; while (beg!=end) min_weight+=abs_(*beg++);
+ for (cur_pred=1; cur_pred<=4; cur_pred++) {
+ cur_weight=0; beg=(end=(signed char*)oo[cur_pred])-rlen; while (beg!=end) cur_weight+=abs_(*beg++);
+ if (cur_weight<min_weight) { min_weight=cur_weight; min_pred=cur_pred; }
+ }
+ // fprintf(stderr, "cp=%u\n", min_pred);
+
+ out.vi_write((char*)(oo[min_pred]-rlen-1),rlen+1);
+ opleft=rlen; h=0; g=0;
+ // lines++;
+ }
+ }
+ // fprintf(stderr, "oen=%u opleft=%u lines=%u\n", len, opleft, lines);
+}
+
+/* --- */
+
+Encoder* PSEncoder::newPredictor(GenBuffer::Writable &out_, unsigned char type, unsigned char bpc_, slen_t columns_, unsigned char cpp_) {
+ switch ((unsigned)type) {
+ /* Imp: make these faster with `register int' etc. tricks */
+ /* See also better_predictor in rule.cpp for the list of predictor numbers */
+ case 1: return new Filter::VerbatimE(out_);
+ case 2: return new TIFFPredictor2(out_, bpc_, columns_, cpp_);
+ case 10: return new PNGPredictorNone(out_, bpc_, columns_, cpp_);
+ case 11: return new PNGPredictorSub(out_, bpc_, columns_, cpp_);
+ case 12: return new PNGPredictorUp(out_, bpc_, columns_, cpp_);
+ case 13: return new PNGPredictorAverage(out_, bpc_, columns_, cpp_);
+ case 14: return new PNGPredictorPaeth(out_, bpc_, columns_, cpp_);
+ case 15: return new PNGPredictorAuto(out_, bpc_, columns_, cpp_);
+ case 45: return new PNGPredictorAutoBadUnsigned(out_, bpc_, columns_, cpp_); /* pts' extension */
+ case 55: return new PNGPredictorAutoBadSigned(out_, bpc_, columns_, cpp_); /* pts' extension */
+ }
+ // fprintf(stderr, "pred=%d\n", type);
+ param_assert(0 && "invalid predictor requested");
+ return (Encoder*)0; /*notreached*/
+}
+
+/* __END__ */
diff --git a/graphics/sam2p/encoder.hpp b/graphics/sam2p/encoder.hpp
new file mode 100644
index 0000000000..f26368c5f4
--- /dev/null
+++ b/graphics/sam2p/encoder.hpp
@@ -0,0 +1,103 @@
+/* encoder.hpp -- specific encoding filters
+ * by pts@fazekas.hu at Tue Feb 26 13:30:02 CET 2002
+ */
+
+#ifdef __GNUC__
+#ifndef __clang__
+#pragma interface
+#endif
+#endif
+
+#ifndef ENCODER_HPP
+#define ENCODER_HPP 1
+
+#include "config2.h"
+#include "gensio.hpp"
+#include <stdio.h>
+
+class PSEncoder: public Encoder {
+ public:
+ /** @return "Flate", "LZW", "DCT", "RunLength", "CCITTFax", "ASCIIHex", "ASCII85" */
+ // inline char const* getLongname() const { return longname; }
+ /** @return "Fla", "LZW", "DCT", "RL", "CCF", "AHx", "A85" */
+ // inline char const* getShortname() const { return shortname; }
+ // inline SimBuffer::Flat const& getFPSname() const { return filter_psname; }
+ // virtual void vi_write(char const*buf, slen_t len) =0;
+ inline virtual ~PSEncoder() {}
+
+ /* The class methods below may return different implementations according to
+ * the command line and compile-time options.
+ */
+ static PSEncoder* newASCIIHexEncode(GenBuffer::Writable &out_,unsigned maxcpl_);
+ static PSEncoder* newASCII85Encode(GenBuffer::Writable &out_,unsigned maxcpl_);
+ /** Fax (PSL2 CCITTFaxEncode filter, Uncompressed=true! (parts of the data
+ * can be inserted uncompressed, when the decoder decides that this is
+ * advantageous), K=-1,0,positive,
+ * EndOfLine=false, EncodedByteAlign=false, Columns=..., Rows=0,
+ * EndOfBlock=true, BlackIs1=false, DamagedRowsBeforeError=0
+ * K must be -1, 0 or positive, see PLRM 3.13.3
+ * K==-1: Group 4 pure 2D encoding. TIFF COMPRESSION_CCITTFAX4,
+ * GROUP4OPT_UNCOMPRESSED.
+ * K==0: Group 3 pure 1D encoding. TIFF COMPRESSION_CCITTFAX3,
+ * GROUP3OPT_UNCOMPRESSED.
+ * K>=1: Group 3 2D (mixed 1D and 2D), a 1D-line can be followed by at most
+ * K-1 2D-line. TIFF COMPRESSION_CCITTFAX3, GROUP3OPT_UNCOMPRESSED,
+ * GROUP3OPT_2DENCODING (K is explicitly raised to image height).
+ * @param EndOfLine should be false for PS/PDF, but must be true for TIFF.
+ */
+ static PSEncoder* newCCITTFaxEncode(GenBuffer::Writable &out_,slendiff_t K, slen_t Columns, bool EndOfLine=false, bool BlackIs1=false);
+ /** PSL2 LZWEncode filter EarlyChange=true, UnitLength=8 LowBitFirst=false */
+ static PSEncoder* newLZWEncode(GenBuffer::Writable &out_);
+ /** PSL3 FlateEncode (ZIP) filter Effort=...: 1..9: 9==highest compression. -1==5 */
+ static PSEncoder* newFlateEncode(GenBuffer::Writable &out_, signed Effort=-1);
+ /** PSL2 RunLengthEncode filter, similar to TIFF PackBits, recordsize=... */
+ static PSEncoder* newRunLengthEncode(GenBuffer::Writable &out_, slen_t RecordSize=0);
+ /** PSL2 DCTEncode. Calls the cjpeg utility (in the debian package
+ * libjpeg-progs) to do the task. The input must be RGB or Gray with
+ * BitsPerComponent==8.
+ */
+ static PSEncoder* newDCTIJGEncode(GenBuffer::Writable &out_,
+ slen_t Columns,
+ slen_t Rows,
+ unsigned char Colors, /*1..4*/
+ unsigned char quality /*libJPEG quality: 0..100 */
+ );
+ /** @param other_parameters "" or something
+ * like: "/HSamples [1 2 1]/ColorTransform 2"
+ */
+ static PSEncoder* newDCTEncode(GenBuffer::Writable &out_,
+ slen_t Columns,
+ slen_t Rows,
+ unsigned char Colors, /*1..4*/
+ unsigned char ColorTransform, /*0,1,2 3=default*/
+ SimBuffer::Flat const& other_parameters
+ );
+ /** PSL2 DCTEncode. Not supported yet. Imp: build support */
+ static PSEncoder* newDCTEncode(GenBuffer::Writable &out_,
+ slen_t Columns,
+ slen_t Rows,
+ unsigned char Colors, /*1..4*/
+ unsigned char quality=75, /*libJPEG quality: 0..100 */
+ unsigned char const*HSamples=(unsigned char*)NULLP, /*all 1..4, NULLP OK*/
+ unsigned char const*VSamples=(unsigned char*)NULLP, /*all 1..4, NULLP OK*/
+ /* vvv pacify VC6.0; no unsigned char (*QuantTables)[64]=(unsigned char(*)[64])NULLP, */
+ unsigned char (*QuantTables)[64]=0, /*NULLP OK*/
+ double QFactor=1.0, /*0..1000000*/
+ unsigned numHuffTables=0,
+ unsigned char **HuffTables=(unsigned char**)NULLP, /*NULLP OK*/
+ unsigned char ColorTransform=2 /*0,1,2 3=default*/
+ );
+ // static Encoder* newTIFFPredictor2(GenBuffer::Writable &out_, unsigned char bpc_, slen_t columns_, unsigned char cpp_);
+ // static Encoder* newPNGPredictor11(GenBuffer::Writable &out_, unsigned char bpc_, slen_t columns_, unsigned char cpp_);
+ /** @param type: 1: no predictor, 2: TIFFPredictor2, 10: PNGPredictorNone (None)
+ * 11: PNGPredictorSub (Sub), 12: PNGPredictorUp (Up),
+ * 13: PNGPredictorAverage (Average), 14: PNGPredictorPaeth (Paeth),
+ * 15: PNGPredictorAuto (optimum).
+ */
+ static Encoder* newPredictor(GenBuffer::Writable &out_, unsigned char type, unsigned char bpc_, slen_t columns_, unsigned char cpp_);
+ protected:
+ // char const *longname, *shortname;
+ // SimBuffer::B filter_psname;
+};
+
+#endif /* encoder.hpp */
diff --git a/graphics/sam2p/error.cpp b/graphics/sam2p/error.cpp
new file mode 100644
index 0000000000..c5da52d517
--- /dev/null
+++ b/graphics/sam2p/error.cpp
@@ -0,0 +1,198 @@
+/*
+ * error.cpp
+ * by pts@fazekas.hu at Fri Mar 1 11:46:27 CET 2002
+ * added policies at Sat Sep 7 18:28:30 CEST 2002
+ */
+
+#ifdef __GNUC__
+#ifndef __clang__
+#pragma implementation
+#endif
+#endif
+
+#include "error.hpp"
+#include "gensio.hpp"
+#include <stdio.h>
+#include <stdlib.h> /* exit() */
+#include <string.h> /* strlen() */
+#if _MSC_VER > 1000
+# include "windows.h" /* ExitThread() */
+#endif
+
+char const* Error::argv0=(char const*)NULLP;
+char const* Error::long_argv0=(char const*)NULLP;
+char const* Error::banner0=(char const*)NULLP;
+char const* Error::tmpargv0=(char const*)"pRg_tMp";
+
+static Filter::NullE devNull;
+Files::FILEW serr_default(stderr);
+GenBuffer::Writable * Error::serr = &serr_default;
+static Error::Policy defaultPolicy={
+ (SimBuffer::B*)NULLP, /* record */
+ (Error::level_t)-9999, /* topSecret */
+ (Error::level_t)-9999, /* topRecorded */
+ (Error::level_t)0, /* killer (level>=0) */
+ (Error::level_t)-99, /* printed */
+ (Error::level_t)-199, /* recorded */
+ Error::serr, /* err */
+ (Error::Policy*)NULLP, /* prev */
+ (Error::Policy*)NULLP, /* next */
+ (Error::level_t)-9999, /* curlev */
+};
+Error::Policy *Error::policy_top=&defaultPolicy, *Error::policy_bottom=&defaultPolicy;
+
+char const*Error::level2str(level_t level) {
+ return level==ASSERT ? "failed_assertion" : /* Imp: make assert() produce this */
+ level==FATAL ? "Fatal Error" :
+ level==ERROR_CONT ? "Error" :
+ level==EERROR ? "Error" :
+ level==WARNING_DEFER ? "Warning" :
+ level==WARNING ? "Warning" :
+ level==NOTICE ? "Notice" :
+ level==NOTICE_DEFER ? "Notice" :
+ level==INFO ? "Info" :
+ level==DEBUG ? "DEBUG" :
+ "??level" ;
+}
+
+GenBuffer::Writable& Error::sev(level_t level) {
+ /* So they are trying to make an error? Let's see whether they can. */
+ GenBuffer::Writable *err=policy_top->err;
+ // printf("curlev=%d\n", policy_top->curlev);
+ assert(policy_top->curlev==-9999 && "nested error/ unfinished prev err");
+ policy_top->curlev=level;
+ /* printf("level=%d\n", level); */
+ if (level>=policy_top->printed) { /* printed or killer */
+ #if 0 /* Disables printing of "using template: " */
+ /* vvv Delay printing this message after all recorded messages */
+ if (policy_top->record!=NULLP) err=policy_top->record;
+ #endif
+ } else if (level>=policy_top->recorded) { /* recorded */
+ if (NULLP==(err=policy_top->record)) err=policy_top->record=new SimBuffer::B();
+ if (level>policy_top->topRecorded) policy_top->topRecorded=level;
+ } else { /* secret */
+ if (level>policy_top->topSecret) policy_top->topSecret=level;
+ return devNull;
+ }
+ return *err << (argv0==(char const*)NULLP?"??argv0":argv0) << ": " << level2str(level) << ": ";
+ /* Processing will continue soon by GenBuffer::Writable& operator <<(GenBuffer::Writable& gb,Error*) */
+}
+
+GenBuffer::Writable& operator <<(GenBuffer::Writable& err,Error*) {
+ err << '\n';
+ Error::level_t level=Error::policy_top->curlev;
+ if (level>=Error::policy_top->killer) { /* killer */
+ /* Also print recorded messages throughout the the policy stack */
+ Error::Policy *p=Error::policy_bottom;
+ while (p!=NULLP) {
+ if (NULLP!=p->record) Error::policy_top->err->vi_write(p->record->begin_(), p->record->getLength());
+ p=p->next;
+ }
+ // if (level>=Error::policy_top->killer)
+ Error::cexit(level);
+ }
+ /* Note that the order of error messages might be scrambled, i.e `printed'
+ * is printed before `recorded'.
+ */
+ Error::policy_top->curlev=(Error::level_t)-9999; /* pedantic but useless because of nesting */
+ return err;
+}
+
+void Error::pushPolicy(level_t killer_, level_t printed_, level_t recorded_, GenBuffer::Writable *err) {
+ Policy *p=new Policy();
+ p->record=(SimBuffer::B*)NULLP;
+ p->topSecret=p->topRecorded=(Error::level_t)-9999;
+ p->killer=killer_;
+ p->printed=printed_;
+ p->recorded=recorded_;
+ p->err=(err==NULLP) ? policy_top->err : err;
+ p->prev=policy_top;
+ p->next=(Policy*)NULLP;
+ policy_top=p->prev->next=p;
+ p->curlev=(Error::level_t)-9999; /* pedantic but useless because of nesting */
+}
+
+SimBuffer::B *Error::getRecorded() {
+ SimBuffer::B *ret=policy_top->record;
+ policy_top->record=(SimBuffer::B*)NULLP;
+ return ret;
+}
+
+void Error::setTopPrinted(level_t printed_) {
+ policy_top->printed=printed_;
+}
+
+Error::level_t Error::getTopPrinted() { return policy_top->printed; }
+
+void Error::popPolicy() {
+ if (policy_top==policy_bottom) {
+ Error::sev(Error::ASSERT) << "popPolicy: underflow" << (Error*)0;
+ } else {
+ if (NULLP!=policy_top->record) {
+ (*Error::policy_top->err) << "-- recorded messages:\n";
+ Error::policy_top->err->vi_write(policy_top->record->begin_(), policy_top->record->getLength());
+ delete policy_top->record;
+ }
+ policy_top=policy_top->prev;
+ delete policy_top->next;
+ policy_top->next=(Policy*)NULLP;
+ }
+}
+
+/* --- */
+
+Error::Cleanup *Error::first_cleanup=(Error::Cleanup*)NULLP;
+
+int Error::runCleanups(int exitCode) {
+ /* Flush buffered messages and revert to the default policy so subsequent
+ * errors can be logged.
+ */
+ while (policy_top != policy_bottom)
+ popPolicy();
+
+ Cleanup *next;
+ int exit2;
+ while (first_cleanup!=NULLP) {
+ // fprintf(stderr, "hand %p\n", first_cleanup);
+ if (exitCode<(exit2=first_cleanup->handler(first_cleanup))) exitCode=exit2;
+ next=first_cleanup->next;
+ /* Allocated from as an array of char (to make space for
+ * first_cleanup->getBuf()), but has no destructors.
+ */
+ delete [] (char*)first_cleanup;
+ first_cleanup=next;
+ }
+ return exitCode;
+}
+
+void Error::cexit(int exitCode) {
+ #if _MSC_VER > 1000
+ ExitThread(exitCode);
+ #else
+ exit(exitCode); /* <stdlib.h> */
+ #endif
+}
+
+Error::Cleanup* Error::newCleanup(Error::Cleanup::handler_t handler, void *data, slen_t bufSize) {
+ param_assert(handler!=0);
+ // slen_t num_packets=(bufSize+sizeof(Cleanup)-1)/sizeof(Cleanup);
+ Cleanup *new_=(Cleanup*)new char[bufSize+sizeof(Cleanup)]; /* new Cleanup[1+num_packets]; */
+ /* ^^^ should be a new Cleanup + new char[bufSize]; now we can avoid alignment
+ * problems
+ */
+ new_->handler=handler;
+ new_->bufSize=bufSize;
+ new_->data=data;
+ new_->next=first_cleanup;
+ first_cleanup=new_;
+ return new_;
+}
+
+Error::Cleanup* Error::newCleanup(Error::Cleanup::handler_t handler, void *data, char const*bufCstr) {
+ const slen_t bufSize=strlen(bufCstr)+1;
+ Cleanup *new_=newCleanup(handler, data, bufSize);
+ memcpy(new_->getBuf(), bufCstr, bufSize);
+ return new_;
+}
+
+/* __END__ */
diff --git a/graphics/sam2p/error.hpp b/graphics/sam2p/error.hpp
new file mode 100644
index 0000000000..af9a58ed20
--- /dev/null
+++ b/graphics/sam2p/error.hpp
@@ -0,0 +1,170 @@
+/* error.hpp -- handling errors/warnings etc.
+ * by pts@fazekas.hu at Fri Mar 1 11:32:36 CET 2002
+ */
+
+#ifdef __GNUC__
+#ifndef __clang__
+#pragma interface
+#endif
+#endif
+
+#ifndef ERROR_HPP
+#define ERROR_HPP 1
+
+#include "config2.h"
+#include "gensi.hpp"
+
+/** This may be usafe if an error happens inside an error. Usage:
+ * Error::sev(Error::WARNING) << "Zero-length image." << (Error*)0;
+ */
+class Error {
+ public:
+ static char const* banner0;
+ static char const* argv0;
+ static char const* tmpargv0;
+ static char const* long_argv0;
+ /** Error types. */
+ BEGIN_STATIC_ENUM(int,level_t)
+ ASSERT=4, FATAL=3,
+ EERROR=2, /* ERROR conflicts with the Win32 API :-( */
+ ERROR_CONT=-2, /* error, but continue running program */
+ WARNING=-3,
+ WARNING_DEFER=-4, /* warning, but defer (and later possibly omit) displaying it */
+ NOTICE=-5,
+ NOTICE_DEFER=-6, INFO=-111, DEBUG=-222
+ END_STATIC_ENUM()
+ /** Standard error stream (stderr) of the current process. */
+ static GenBuffer::Writable * serr;
+ /** Returns address to statically allocated buffer. */
+ static char const*level2str(level_t level);
+ /** This is the (carefully hidden :-)) method of raising errors (i.e
+ * displaying error messages and terminating the program).
+ * Example usage:
+ * Error::sev(Error::WARNING_DEFER) << "check_rule: /BMP requires "
+ * "/Predictor " << 1 << (Error*)0;
+ * The error is interpreted according to the current policy. The policy
+ * divides errors into three categories:
+ *
+ * -- secret: nothing happens (even the error message is _not_ printed)
+ * -- recorded: nothing happens (even the error message is _not_ printed),
+ * but the message is remembered for further processing.
+ * -- printed: the error message is printed, and program execution continues
+ * Before printing this message, all recorded errors on the policy stack
+ * are also printed (deepest first).
+ * -- killer: like `printed', but runs cleanup handlers and terminates the
+ * program immediately.
+ *
+ * @param level is one of the constants mentioned above (FATAL, EERROR,
+ * WARNING, NOTICE etc). Can be positive, zero or negative. The larger
+ * the `level', the more severe the error is. The default policy is:
+ * level>=0 errors are killer, -99<=level<=-1 errors are printed,
+ * -199<=level<=-100 are recorded and level<=-200 errors are secret.
+ */
+ static GenBuffer::Writable& sev(level_t level);
+
+ public:
+ /** The field order is important in this struct, because of the initializers. */
+ struct Policy {
+ /** All recorded messages. Default: NULL. This means empty. */
+ SimBuffer::B *record;
+ /** The highest level of Secret category encountered so far. Default: -9999 */
+ level_t topSecret;
+ /** The highest level of Recorded category encountered so far. Default: -9999 */
+ level_t topRecorded;
+ /** Lower bound of these categories in this policy. */
+ level_t killer, printed, recorded;
+ /** Error stream to print printed and killer messages. */
+ GenBuffer::Writable *err;
+ /** NULL for top policy */
+ Policy *prev, *next;
+ /** Level of the current error being raised. */
+ level_t curlev;
+ };
+ protected:
+ /** Boundaries of the policy stack. */
+ static Policy *policy_top, *policy_bottom;
+ public:
+ friend GenBuffer::Writable& operator <<(GenBuffer::Writable&,Error*);
+ /** Creates a new policy and makes it active by pushing it onto the top of
+ * the policy stack.
+ */
+ static void pushPolicy(level_t killer_, level_t printed_, level_t recorded_, GenBuffer::Writable *err=(GenBuffer::Writable*)NULLP);
+ /** @return the messages already recorded, and clears the `record' entry
+ * of the current policy. The caller is responsible for deleting the
+ * pointer returned. May return NULLP for empty records. Typical example:
+ * delete Error::getRecorded();
+ */
+ static SimBuffer::B *getRecorded();
+ /** Prints all recorded error messages, and removes the topmost element of
+ * the policy stack. Typical example:
+ * delete Error::getRecorded(); popPolicy();
+ */
+ static void popPolicy();
+
+ /** @example Error::setTopPrinted(Error::ERROR_CONT); suppress anything
+ * below error, such as warnings.
+ */
+ static void setTopPrinted(level_t printed_);
+
+ static level_t getTopPrinted();
+
+ /** The Cleanup mechanism is similar to atexit(3) and on_exit(3). This is
+ * just a simple struct with no destructors, virtual methods or inheritance.
+ *
+ * Additional data (char[] buffer) can be allocated and stored right
+ * after the object (this+1), it can be retrieved with getBuf(), and it will
+ * be deleted when the object is deleted by runCleanups().
+ */
+ struct Cleanup {
+ /** Must _not_ cause any Errors.
+ * @return an exit code. If larger than the current one, replaces it
+ */
+ typedef int (*handler_t)(Cleanup*);
+ /** Owned externally. */
+ handler_t handler;
+ /** size of extra data allocated at getBuf(). */
+ slen_t bufSize;
+ /** Arbitrary data, owned by `handler': handler' must delete `data'
+ * when called.
+ */
+ void *data;
+ /** NULLP: no next, end of chain */
+ Cleanup *next;
+ inline char *getBuf() { return (char*)(this+1); }
+ inline slen_t getSize() { return bufSize; }
+ };
+ /** Creates and returns a new Cleanup, and registers it in front of the
+ * existing ones. Copies `handler' and `data' to it. Also allocates `bufSize' bytes
+ * of char[] buffer (at result->getBuf()) owned by the cleanup, but doesn't
+ * initialize the buffer.
+ *
+ * Doesn't take ownership of `handler', takes ownership of `data'.
+ * `handler' must delete `data' or pass on ownership when called,
+ * typically by runCleanups().
+ */
+ static Cleanup* newCleanup(Cleanup::handler_t handler, void *data, slen_t bufSize);
+ /** Creates and returns a new Cleanup, and registers it in front of the
+ * existing ones. Copies `handler' and `data' to it. Also allocates
+ * strlen(bufCstr)+1 bytes of char[] buffer (at result->getBuf()) owned by
+ * the cleanup, and initializes it from bufCstr.
+ *
+ * Doesn't take ownership of `handler', takes ownership of `data'.
+ * `handler' must delete `data' or pass on ownership when called,
+ * typically by runCleanups().
+ */
+ static Cleanup* newCleanup(Cleanup::handler_t handler, void *data, char const*bufCstr);
+ /** Reverts to the default logging policy,
+ * executes the cleanup handlers (in reverse-registration order),
+ * unregisters and deletes all the cleanups, and returns the
+ * new exit code, which is at least exitCode.
+ */
+ static int runCleanups(int exitCode);
+ /* Exits from the process with the specified exit code. */
+ static void cexit(int exitCode);
+ protected:
+ static Cleanup *first_cleanup;
+};
+
+GenBuffer::Writable& operator <<(GenBuffer::Writable&,Error*);
+
+#endif
diff --git a/graphics/sam2p/examples/a_jpg.job b/graphics/sam2p/examples/a_jpg.job
new file mode 100644
index 0000000000..b579462730
--- /dev/null
+++ b/graphics/sam2p/examples/a_jpg.job
@@ -0,0 +1,8 @@
+<<%sam2p-job; by Sun Mar 17 21:59:30 CET 2002
+/InputFile (examples/a.jpg)
+/OutputFile (test.eps)
+/Profile [
+ << /FileFormat/PSL3 /SampleFormat/Asis /TransferEncoding/Binary
+ /Compression/JAI >>
+ ]
+>>
diff --git a/graphics/sam2p/examples/a_jpg2.job b/graphics/sam2p/examples/a_jpg2.job
new file mode 100644
index 0000000000..14da8c383e
--- /dev/null
+++ b/graphics/sam2p/examples/a_jpg2.job
@@ -0,0 +1,8 @@
+<<%sam2p-job; by Sun Mar 17 21:59:30 CET 2002
+/InputFile (examples/a.jpg)
+/OutputFile (test.eps)
+/Profile [
+ << /FileFormat/PSL3 /SampleFormat/Rgb8 /TransferEncoding/Binary
+ /Compression/JAI >>
+ ]
+>>
diff --git a/graphics/sam2p/examples/a_l1r8r_eps.job b/graphics/sam2p/examples/a_l1r8r_eps.job
new file mode 100644
index 0000000000..4b531f711b
--- /dev/null
+++ b/graphics/sam2p/examples/a_l1r8r_eps.job
@@ -0,0 +1,9 @@
+<<%sam2p-job; by pts@fazekas.hu at Sun Jun 2 16:57:49 CEST 2002
+/InputFile (examples/a.jpg)
+/OutputFile (test.eps)
+/Profile [
+ << /FileFormat/PSLC /SampleFormat/RGB8
+ /TransferEncoding/A85
+ /Compression/RLE >>
+ ]
+>>
diff --git a/graphics/sam2p/examples/at-logo_none_xpm.job b/graphics/sam2p/examples/at-logo_none_xpm.job
new file mode 100644
index 0000000000..b94b0bb154
--- /dev/null
+++ b/graphics/sam2p/examples/at-logo_none_xpm.job
@@ -0,0 +1,10 @@
+<<%sam2p-job; by pts@fazekas.hu at Tue Jun 4 20:16:14 CEST 2002
+/InputFile (examples/at-logo.gif)
+/OutputFile (test.xpm)
+/Profile [
+ << /FileFormat/XPM
+ /SampleFormat/Transparent4
+ /TransferEncoding/ASCII
+ /Compression/None
+ >> ]
+>>
diff --git a/graphics/sam2p/examples/fishg_lzw12_pdf.job b/graphics/sam2p/examples/fishg_lzw12_pdf.job
new file mode 100644
index 0000000000..714a070c93
--- /dev/null
+++ b/graphics/sam2p/examples/fishg_lzw12_pdf.job
@@ -0,0 +1,8 @@
+<<%sam2p-job; by pts@fazekas.hu at Tue Jun 4 22:07:29 CEST 2002
+/InputFile (examples/fishg.gif)
+/OutputFile (test.pdf)
+/Profile [
+ << /FileFormat/PDFB1.0 /SampleFormat/Indexed2 /TransferEncoding/Binary
+ /Compression/LZW /Predictor 12 >>
+ ]
+>>
diff --git a/graphics/sam2p/examples/fishg_lzw2_pdf.job b/graphics/sam2p/examples/fishg_lzw2_pdf.job
new file mode 100644
index 0000000000..aefc76ece5
--- /dev/null
+++ b/graphics/sam2p/examples/fishg_lzw2_pdf.job
@@ -0,0 +1,8 @@
+<<%sam2p-job; by pts@fazekas.hu at Tue Jun 4 22:07:29 CEST 2002
+/InputFile (examples/fishg.gif)
+/OutputFile (test.pdf)
+/Profile [
+ << /FileFormat/PDFB1.0 /SampleFormat/Indexed2 /TransferEncoding/Binary
+ /Compression/LZW /Predictor 2 >>
+ ]
+>>
diff --git a/graphics/sam2p/examples/fishwbb_l128n_eps.job b/graphics/sam2p/examples/fishwbb_l128n_eps.job
new file mode 100644
index 0000000000..3b98692ad9
--- /dev/null
+++ b/graphics/sam2p/examples/fishwbb_l128n_eps.job
@@ -0,0 +1,10 @@
+<<%sam2p-job; by pts@fazekas.hu at Sun Jun 2 12:11:08 CEST 2002
+/InputFile (examples/fishwbb.gif)
+/OutputFile (test.eps)
+/Profile [
+ << /FileFormat/PSLC
+ /SampleFormat/Indexed2
+ /TransferEncoding/A85
+ /Compression/None >>
+ ]
+>>
diff --git a/graphics/sam2p/examples/fishwbb_l128r_eps.job b/graphics/sam2p/examples/fishwbb_l128r_eps.job
new file mode 100644
index 0000000000..3581ba7a41
--- /dev/null
+++ b/graphics/sam2p/examples/fishwbb_l128r_eps.job
@@ -0,0 +1,10 @@
+<<%sam2p-job; by pts@fazekas.hu at Sat Jun 1 21:56:11 CEST 2002
+/InputFile (examples/fishwbb.gif)
+/OutputFile (test.eps)
+/Profile [
+ << /FileFormat/PSLC
+ /SampleFormat/Indexed2
+ /TransferEncoding/A85
+ /Compression/RLE >>
+ ]
+>>
diff --git a/graphics/sam2p/examples/fishwbb_l12bn_eps.job b/graphics/sam2p/examples/fishwbb_l12bn_eps.job
new file mode 100644
index 0000000000..52773e81ca
--- /dev/null
+++ b/graphics/sam2p/examples/fishwbb_l12bn_eps.job
@@ -0,0 +1,10 @@
+<<%sam2p-job; by pts@fazekas.hu at Sun Jun 2 14:38:24 CEST 2002
+/InputFile (examples/fishwbb.gif)
+/OutputFile (test.eps)
+/Profile [
+ << /FileFormat/PSLC
+ /SampleFormat/Indexed2
+ /TransferEncoding/Binary
+ /Compression/None >>
+ ]
+>>
diff --git a/graphics/sam2p/examples/fishwbb_l12br_eps.job b/graphics/sam2p/examples/fishwbb_l12br_eps.job
new file mode 100644
index 0000000000..9e8107a733
--- /dev/null
+++ b/graphics/sam2p/examples/fishwbb_l12br_eps.job
@@ -0,0 +1,10 @@
+<<%sam2p-job; by pts@fazekas.hu at Sun Jun 2 14:24:53 CEST 2002
+/InputFile (examples/fishwbb.gif)
+/OutputFile (test.eps)
+/Profile [
+ << /FileFormat/PSLC
+ /SampleFormat/Indexed2
+ /TransferEncoding/Binary
+ /Compression/RLE >>
+ ]
+>>
diff --git a/graphics/sam2p/examples/fishwbb_l12hn_eps.job b/graphics/sam2p/examples/fishwbb_l12hn_eps.job
new file mode 100644
index 0000000000..aeaa9d4aac
--- /dev/null
+++ b/graphics/sam2p/examples/fishwbb_l12hn_eps.job
@@ -0,0 +1,10 @@
+<<%sam2p-job; by pts@fazekas.hu at Sun Jun 2 14:38:24 CEST 2002
+/InputFile (examples/fishwbb.gif)
+/OutputFile (test.eps)
+/Profile [
+ << /FileFormat/PSLC
+ /SampleFormat/Indexed2
+ /TransferEncoding/Hex
+ /Compression/None >>
+ ]
+>>
diff --git a/graphics/sam2p/examples/fishwbb_l12hr_eps.job b/graphics/sam2p/examples/fishwbb_l12hr_eps.job
new file mode 100644
index 0000000000..4dcd293e1f
--- /dev/null
+++ b/graphics/sam2p/examples/fishwbb_l12hr_eps.job
@@ -0,0 +1,10 @@
+<<%sam2p-job; by pts@fazekas.hu at Sun Jun 2 14:24:53 CEST 2002
+/InputFile (examples/fishwbb.gif)
+/OutputFile (test.eps)
+/Profile [
+ << /FileFormat/PSLC
+ /SampleFormat/Indexed2
+ /TransferEncoding/Hex
+ /Compression/RLE >>
+ ]
+>>
diff --git a/graphics/sam2p/examples/fishwbb_l148n_eps.job b/graphics/sam2p/examples/fishwbb_l148n_eps.job
new file mode 100644
index 0000000000..940b4f67d7
--- /dev/null
+++ b/graphics/sam2p/examples/fishwbb_l148n_eps.job
@@ -0,0 +1,10 @@
+<<%sam2p-job; by pts@fazekas.hu at Sun Jun 2 12:11:08 CEST 2002
+/InputFile (examples/fishwbb.gif)
+/OutputFile (test.eps)
+/Profile [
+ << /FileFormat/PSLC
+ /SampleFormat/Indexed4
+ /TransferEncoding/A85
+ /Compression/None >>
+ ]
+>>
diff --git a/graphics/sam2p/examples/fishwbb_l148r_eps.job b/graphics/sam2p/examples/fishwbb_l148r_eps.job
new file mode 100644
index 0000000000..f6d81a0d8c
--- /dev/null
+++ b/graphics/sam2p/examples/fishwbb_l148r_eps.job
@@ -0,0 +1,10 @@
+<<%sam2p-job; by pts@fazekas.hu at Sat Jun 1 21:56:11 CEST 2002
+/InputFile (examples/fishwbb.gif)
+/OutputFile (test.eps)
+/Profile [
+ << /FileFormat/PSLC
+ /SampleFormat/Indexed4
+ /TransferEncoding/A85
+ /Compression/RLE >>
+ ]
+>>
diff --git a/graphics/sam2p/examples/fishwbb_l14bn_eps.job b/graphics/sam2p/examples/fishwbb_l14bn_eps.job
new file mode 100644
index 0000000000..e7adc31e93
--- /dev/null
+++ b/graphics/sam2p/examples/fishwbb_l14bn_eps.job
@@ -0,0 +1,10 @@
+<<%sam2p-job; by pts@fazekas.hu at Sun Jun 2 14:38:28 CEST 2002
+/InputFile (examples/fishwbb.gif)
+/OutputFile (test.eps)
+/Profile [
+ << /FileFormat/PSLC
+ /SampleFormat/Indexed4
+ /TransferEncoding/Binary
+ /Compression/None >>
+ ]
+>>
diff --git a/graphics/sam2p/examples/fishwbb_l14br_eps.job b/graphics/sam2p/examples/fishwbb_l14br_eps.job
new file mode 100644
index 0000000000..83d93346b5
--- /dev/null
+++ b/graphics/sam2p/examples/fishwbb_l14br_eps.job
@@ -0,0 +1,10 @@
+<<%sam2p-job; by pts@fazekas.hu at Sun Jun 2 14:29:41 CEST 2002
+/InputFile (examples/fishwbb.gif)
+/OutputFile (test.eps)
+/Profile [
+ << /FileFormat/PSLC
+ /SampleFormat/Indexed4
+ /TransferEncoding/Binary
+ /Compression/RLE >>
+ ]
+>>
diff --git a/graphics/sam2p/examples/fishwbb_l14hn_eps.job b/graphics/sam2p/examples/fishwbb_l14hn_eps.job
new file mode 100644
index 0000000000..6a5d596a44
--- /dev/null
+++ b/graphics/sam2p/examples/fishwbb_l14hn_eps.job
@@ -0,0 +1,10 @@
+<<%sam2p-job; by pts@fazekas.hu at Sun Jun 2 14:38:28 CEST 2002
+/InputFile (examples/fishwbb.gif)
+/OutputFile (test.eps)
+/Profile [
+ << /FileFormat/PSLC
+ /SampleFormat/Indexed4
+ /TransferEncoding/Hex
+ /Compression/None >>
+ ]
+>>
diff --git a/graphics/sam2p/examples/fishwbb_l14hr_eps.job b/graphics/sam2p/examples/fishwbb_l14hr_eps.job
new file mode 100644
index 0000000000..83e62e733c
--- /dev/null
+++ b/graphics/sam2p/examples/fishwbb_l14hr_eps.job
@@ -0,0 +1,10 @@
+<<%sam2p-job; by pts@fazekas.hu at Sun Jun 2 14:29:41 CEST 2002
+/InputFile (examples/fishwbb.gif)
+/OutputFile (test.eps)
+/Profile [
+ << /FileFormat/PSLC
+ /SampleFormat/Indexed4
+ /TransferEncoding/Hex
+ /Compression/RLE >>
+ ]
+>>
diff --git a/graphics/sam2p/examples/fishwbb_l188n_eps.job b/graphics/sam2p/examples/fishwbb_l188n_eps.job
new file mode 100644
index 0000000000..2b82aacb01
--- /dev/null
+++ b/graphics/sam2p/examples/fishwbb_l188n_eps.job
@@ -0,0 +1,10 @@
+<<%sam2p-job; by pts@fazekas.hu at Sun Jun 2 12:11:08 CEST 2002
+/InputFile (examples/fishwbb.gif)
+/OutputFile (test.eps)
+/Profile [
+ << /FileFormat/PSLC
+ /SampleFormat/Indexed8
+ /TransferEncoding/A85
+ /Compression/None >>
+ ]
+>>
diff --git a/graphics/sam2p/examples/fishwbb_l188r_eps.job b/graphics/sam2p/examples/fishwbb_l188r_eps.job
new file mode 100644
index 0000000000..ecec33281c
--- /dev/null
+++ b/graphics/sam2p/examples/fishwbb_l188r_eps.job
@@ -0,0 +1,10 @@
+<<%sam2p-job; by pts@fazekas.hu at Sat Jun 1 21:56:11 CEST 2002
+/InputFile (examples/fishwbb.gif)
+/OutputFile (test.eps)
+/Profile [
+ << /FileFormat/PSLC
+ /SampleFormat/Indexed8
+ /TransferEncoding/A85
+ /Compression/RLE >>
+ ]
+>>
diff --git a/graphics/sam2p/examples/fishwbb_l18bn_eps.job b/graphics/sam2p/examples/fishwbb_l18bn_eps.job
new file mode 100644
index 0000000000..0f928c39c1
--- /dev/null
+++ b/graphics/sam2p/examples/fishwbb_l18bn_eps.job
@@ -0,0 +1,10 @@
+<<%sam2p-job; by pts@fazekas.hu at Sun Jun 2 12:11:08 CEST 2002
+/InputFile (examples/fishwbb.gif)
+/OutputFile (test.eps)
+/Profile [
+ << /FileFormat/PSLC
+ /SampleFormat/Indexed8
+ /TransferEncoding/Binary
+ /Compression/None >>
+ ]
+>>
diff --git a/graphics/sam2p/examples/fishwbb_l18br_eps.job b/graphics/sam2p/examples/fishwbb_l18br_eps.job
new file mode 100644
index 0000000000..ab59d4d28b
--- /dev/null
+++ b/graphics/sam2p/examples/fishwbb_l18br_eps.job
@@ -0,0 +1,10 @@
+<<%sam2p-job; by pts@fazekas.hu at Sun Jun 2 13:23:31 CEST 2002
+/InputFile (examples/fishwbb.gif)
+/OutputFile (test.eps)
+/Profile [
+ << /FileFormat/PSLC
+ /SampleFormat/Indexed8
+ /TransferEncoding/Binary
+ /Compression/RLE >>
+ ]
+>>
diff --git a/graphics/sam2p/examples/fishwbb_l18hn_eps.job b/graphics/sam2p/examples/fishwbb_l18hn_eps.job
new file mode 100644
index 0000000000..8e83e0b057
--- /dev/null
+++ b/graphics/sam2p/examples/fishwbb_l18hn_eps.job
@@ -0,0 +1,10 @@
+<<%sam2p-job; by pts@fazekas.hu at Sun Jun 2 12:11:08 CEST 2002
+/InputFile (examples/fishwbb.gif)
+/OutputFile (test.eps)
+/Profile [
+ << /FileFormat/PSLC
+ /SampleFormat/Indexed8
+ /TransferEncoding/Hex
+ /Compression/None >>
+ ]
+>>
diff --git a/graphics/sam2p/examples/fishwbb_l18hr_eps.job b/graphics/sam2p/examples/fishwbb_l18hr_eps.job
new file mode 100644
index 0000000000..d53dd9b2b8
--- /dev/null
+++ b/graphics/sam2p/examples/fishwbb_l18hr_eps.job
@@ -0,0 +1,10 @@
+<<%sam2p-job; by pts@fazekas.hu at Sun Jun 2 13:23:31 CEST 2002
+/InputFile (examples/fishwbb.gif)
+/OutputFile (test.eps)
+/Profile [
+ << /FileFormat/PSLC
+ /SampleFormat/Indexed8
+ /TransferEncoding/Hex
+ /Compression/RLE >>
+ ]
+>>
diff --git a/graphics/sam2p/examples/fusi2_png.job b/graphics/sam2p/examples/fusi2_png.job
new file mode 100644
index 0000000000..33fddbf46d
--- /dev/null
+++ b/graphics/sam2p/examples/fusi2_png.job
@@ -0,0 +1,10 @@
+<<%sam2p-job; by pts@fazekas.hu at Sat Apr 20 16:49:24 CEST 2002
+/InputFile (examples/fusi2.pnm)
+%/InputFile (examples/fusiblack.ppm)
+/OutputFile (test.png)
+/Profile [
+ << /FileFormat/PNG /SampleFormat/Transparent4 /TransferEncoding/Binary
+ /Compression/ZIP /Predictor 15
+ >>
+ ]
+>>
diff --git a/graphics/sam2p/examples/fusi_gif.job b/graphics/sam2p/examples/fusi_gif.job
new file mode 100644
index 0000000000..e6fca1fc2c
--- /dev/null
+++ b/graphics/sam2p/examples/fusi_gif.job
@@ -0,0 +1,11 @@
+<<%sam2p-job; by pts@fazekas.hu at Sat Apr 20 16:49:24 CEST 2002
+/InputFile (examples/fusi.tiff)
+/OutputFile (test.gif)
+/Profile [
+ << /FileFormat/GIF89a
+ /SampleFormat/Transparent4
+ %/SampleFormat/Indexed4 % doesn't work, contains transparent pixels
+ /TransferEncoding/Binary
+ /Compression/None >>
+ ]
+>>
diff --git a/graphics/sam2p/examples/fusi_l1t8r_eps.job b/graphics/sam2p/examples/fusi_l1t8r_eps.job
new file mode 100644
index 0000000000..b35eb48019
--- /dev/null
+++ b/graphics/sam2p/examples/fusi_l1t8r_eps.job
@@ -0,0 +1,10 @@
+<<%sam2p-job; by pts@fazekas.hu at Sun Jun 2 16:15:00 CEST 2002
+/InputFile (examples/fusi.tiff)
+/OutputFile (test.eps)
+/Profile [
+ << /FileFormat/PSL1
+ /SampleFormat/Transparent8
+ /TransferEncoding/A85
+ /Compression/RLE >>
+ ]
+>>
diff --git a/graphics/sam2p/examples/fusi_l1tbr_eps.job b/graphics/sam2p/examples/fusi_l1tbr_eps.job
new file mode 100644
index 0000000000..25cf1050c9
--- /dev/null
+++ b/graphics/sam2p/examples/fusi_l1tbr_eps.job
@@ -0,0 +1,10 @@
+<<%sam2p-job; by pts@fazekas.hu at Sun Jun 2 15:59:13 CEST 2002
+/InputFile (examples/fusi.tiff)
+/OutputFile (test.eps)
+/Profile [
+ << /FileFormat/PSL1
+ /SampleFormat/Transparent4
+ /TransferEncoding/Binary
+ /Compression/RLE >>
+ ]
+>>
diff --git a/graphics/sam2p/examples/fusi_l1thn_eps.job b/graphics/sam2p/examples/fusi_l1thn_eps.job
new file mode 100644
index 0000000000..1dc1003277
--- /dev/null
+++ b/graphics/sam2p/examples/fusi_l1thn_eps.job
@@ -0,0 +1,11 @@
+<<%sam2p-job; by pts@fazekas.hu at Sun Jun 2 15:58:00 CEST 2002
+% original fusi_tral1_eps.job by pts@fazekas.hu at Sat Jun 1 19:00:48 CEST 2002
+/InputFile (examples/fusi.tiff)
+/OutputFile (test.eps)
+/Profile [
+ << /FileFormat/PSL1
+ /SampleFormat/Transparent4
+ /TransferEncoding/Hex
+ /Compression/None >>
+ ]
+>>
diff --git a/graphics/sam2p/examples/fusi_l1thr_eps.job b/graphics/sam2p/examples/fusi_l1thr_eps.job
new file mode 100644
index 0000000000..cb1ce0fbce
--- /dev/null
+++ b/graphics/sam2p/examples/fusi_l1thr_eps.job
@@ -0,0 +1,10 @@
+<<%sam2p-job; by pts@fazekas.hu at Sun Jun 2 16:14:01 CEST 2002
+/InputFile (examples/fusi.tiff)
+/OutputFile (test.eps)
+/Profile [
+ << /FileFormat/PSL1
+ /SampleFormat/Transparent4
+ /TransferEncoding/Hex
+ /Compression/RLE >>
+ ]
+>>
diff --git a/graphics/sam2p/examples/fusi_png.job b/graphics/sam2p/examples/fusi_png.job
new file mode 100644
index 0000000000..0c12cdc9be
--- /dev/null
+++ b/graphics/sam2p/examples/fusi_png.job
@@ -0,0 +1,9 @@
+<<%sam2p-job; by pts@fazekas.hu at Sat Apr 20 16:49:24 CEST 2002
+/InputFile (examples/fusi.tiff)
+%/InputFile (examples/fusiblack.ppm)
+/OutputFile (test.png)
+/Profile [
+ << /FileFormat/PNG /SampleFormat/Transparent4 /TransferEncoding/Binary
+ /Compression/ZIP /Predictor 15 >>
+ ]
+>>
diff --git a/graphics/sam2p/examples/fusi_pnm.job b/graphics/sam2p/examples/fusi_pnm.job
new file mode 100644
index 0000000000..4d37ac1297
--- /dev/null
+++ b/graphics/sam2p/examples/fusi_pnm.job
@@ -0,0 +1,9 @@
+<<%sam2p-job; by pts@fazekas.hu at Tue Jun 4 21:42:08 CEST 2002
+/InputFile (examples/fusi.gif)
+/OutputFile (test.pnm)
+/unknown pop
+/Profile [
+ << /FileFormat/PNM /SampleFormat/Transparent4 /TransferEncoding/Binary
+ /Compression/None >>
+]
+>>
diff --git a/graphics/sam2p/examples/fusi_pnm_ascii.job b/graphics/sam2p/examples/fusi_pnm_ascii.job
new file mode 100644
index 0000000000..b5cda4e76c
--- /dev/null
+++ b/graphics/sam2p/examples/fusi_pnm_ascii.job
@@ -0,0 +1,9 @@
+<<%sam2p-job; by pts@fazekas.hu at Sat Jun 15 15:03:47 CEST 2002
+/InputFile (examples/fusi.gif)
+/OutputFile (test.pnm)
+/unknown pop
+/Profile [
+ << /FileFormat/PNM /SampleFormat/Transparent4 /TransferEncoding/ASCII
+ /Compression/None >>
+]
+>>
diff --git a/graphics/sam2p/examples/fusi_tiff_bad_pdf.job b/graphics/sam2p/examples/fusi_tiff_bad_pdf.job
new file mode 100644
index 0000000000..4bd35bbb51
--- /dev/null
+++ b/graphics/sam2p/examples/fusi_tiff_bad_pdf.job
@@ -0,0 +1,8 @@
+<<%sam2p-job; by pts@fazekas.hu at Sun Apr 14 15:14:32 CEST 2002
+/InputFile (examples/fusi.tiff)
+/OutputFile (test.eps)
+/Profile [
+ << /FileFormat/PDFB1.0 /SampleFormat/Gray8 /TransferEncoding/Binary
+ /Compression/ZIP >>
+ ]
+>>
diff --git a/graphics/sam2p/examples/fusi_tiff_eps.job b/graphics/sam2p/examples/fusi_tiff_eps.job
new file mode 100644
index 0000000000..83663896f3
--- /dev/null
+++ b/graphics/sam2p/examples/fusi_tiff_eps.job
@@ -0,0 +1,8 @@
+<<%sam2p-job; by pts@fazekas.hu at Sun Apr 14 15:14:32 CEST 2002
+/InputFile (examples/fusi.tiff)
+/OutputFile (test.eps)
+/Profile [
+ << /FileFormat/PSL3 /SampleFormat/Gray8 /TransferEncoding/Binary
+ /Compression/ZIP >>
+ ]
+>>
diff --git a/graphics/sam2p/examples/fusi_tra_eps.job b/graphics/sam2p/examples/fusi_tra_eps.job
new file mode 100644
index 0000000000..6098f3f5ca
--- /dev/null
+++ b/graphics/sam2p/examples/fusi_tra_eps.job
@@ -0,0 +1,12 @@
+<<%sam2p-job; by pts@fazekas.hu at Wed Apr 24 13:32:12 CEST 2002
+/InputFile (examples/fusi.tiff)
+/OutputFile (test.eps)
+/Profile [
+ << /FileFormat/PSL3
+ /SampleFormat/Transparent4
+ %/SampleFormat/Indexed4 % doesn't work, contains transparent pixels
+ /TransferEncoding/A85
+ /Predictor 45
+ /Compression/ZIP >>
+ ]
+>>
diff --git a/graphics/sam2p/examples/fusi_trabin_eps.job b/graphics/sam2p/examples/fusi_trabin_eps.job
new file mode 100644
index 0000000000..ba14ef8198
--- /dev/null
+++ b/graphics/sam2p/examples/fusi_trabin_eps.job
@@ -0,0 +1,11 @@
+<<%sam2p-job; by pts@fazekas.hu at Wed Apr 24 13:32:12 CEST 2002
+/InputFile (examples/fusi.tiff)
+/OutputFile (test.eps)
+/Profile [
+ << /FileFormat/PSL3
+ /SampleFormat/Transparent4
+ %/SampleFormat/Indexed4 % doesn't work, contains transparent pixels
+ /TransferEncoding/Binary
+ /Compression/None >>
+ ]
+>>
diff --git a/graphics/sam2p/examples/fusi_tradct_eps.job b/graphics/sam2p/examples/fusi_tradct_eps.job
new file mode 100644
index 0000000000..fa9af95e66
--- /dev/null
+++ b/graphics/sam2p/examples/fusi_tradct_eps.job
@@ -0,0 +1,11 @@
+<<%sam2p-job; by pts@fazekas.hu at Tue Jun 11 18:18:51 CEST 2002
+/InputFile (examples/fusi.tiff)
+/OutputFile (test.eps)
+/Profile [
+ << /FileFormat/PSL2
+ /SampleFormat/Gray8
+ %/SampleFormat/Indexed4 % doesn't work, contains transparent pixels
+ /TransferEncoding/A85
+ /Compression/DCT >>
+ ]
+>>
diff --git a/graphics/sam2p/examples/fusi_tradct_jpeg.job b/graphics/sam2p/examples/fusi_tradct_jpeg.job
new file mode 100644
index 0000000000..59148cec14
--- /dev/null
+++ b/graphics/sam2p/examples/fusi_tradct_jpeg.job
@@ -0,0 +1,11 @@
+<<%sam2p-job; by pts@fazekas.hu at Tue Jun 11 18:18:51 CEST 2002
+/InputFile (examples/fusi.tiff)
+/OutputFile (test.jpg)
+/Profile [
+ << /FileFormat/JPEG
+ /SampleFormat/Gray8
+ %/SampleFormat/Indexed4 % doesn't work, contains transparent pixels
+ /TransferEncoding/Binary
+ /Compression/DCT >>
+ ]
+>>
diff --git a/graphics/sam2p/examples/fusi_trafax_eps.job b/graphics/sam2p/examples/fusi_trafax_eps.job
new file mode 100644
index 0000000000..805a4c50b4
--- /dev/null
+++ b/graphics/sam2p/examples/fusi_trafax_eps.job
@@ -0,0 +1,11 @@
+<<%sam2p-job; by pts@fazekas.hu at Wed Apr 24 13:32:12 CEST 2002
+/InputFile (examples/fusi.tiff)
+/OutputFile (test.eps)
+/Profile [
+ << /FileFormat/PSL2
+ /SampleFormat/Transparent4
+ %/SampleFormat/Indexed4 % doesn't work, contains transparent pixels
+ /TransferEncoding/A85
+ /Compression/Fax >>
+ ]
+>>
diff --git a/graphics/sam2p/examples/fusi_traijg_eps.job b/graphics/sam2p/examples/fusi_traijg_eps.job
new file mode 100644
index 0000000000..1be2320af6
--- /dev/null
+++ b/graphics/sam2p/examples/fusi_traijg_eps.job
@@ -0,0 +1,13 @@
+<<%sam2p-job; by pts@fazekas.hu at Wed Apr 24 13:32:12 CEST 2002
+% Doesn't work (of course), because JPEG compression requires a bit depth of
+% 8, but /Transparent* provides a bit depth of 1.
+/InputFile (examples/fusi.tiff)
+/OutputFile (test.eps)
+/Profile [
+ << /FileFormat/PSL2
+ /SampleFormat/Transparent4
+ %/SampleFormat/Indexed4 % doesn't work, contains transparent pixels
+ /TransferEncoding/A85
+ /Compression/IJG >>
+ ]
+>>
diff --git a/graphics/sam2p/examples/fusi_tral1a85_eps.job b/graphics/sam2p/examples/fusi_tral1a85_eps.job
new file mode 100644
index 0000000000..b6b7a60606
--- /dev/null
+++ b/graphics/sam2p/examples/fusi_tral1a85_eps.job
@@ -0,0 +1,10 @@
+<<%sam2p-job; by pts@fazekas.hu at Sat Jun 1 19:54:45 CEST 2002
+/InputFile (examples/fusi.tiff)
+/OutputFile (test.eps)
+/Profile [
+ << /FileFormat/PSL1
+ /SampleFormat/Transparent4
+ /TransferEncoding/A85
+ /Compression/None >>
+ ]
+>>
diff --git a/graphics/sam2p/examples/fusiblack_png.job b/graphics/sam2p/examples/fusiblack_png.job
new file mode 100644
index 0000000000..e664d0b1a6
--- /dev/null
+++ b/graphics/sam2p/examples/fusiblack_png.job
@@ -0,0 +1,9 @@
+<<%sam2p-job; by pts@fazekas.hu at Sat Apr 20 16:49:24 CEST 2002
+%/InputFile (examples/fusi.tiff)
+/InputFile (examples/fusiblack.ppm)
+/OutputFile (test.png)
+/Profile [
+ << /FileFormat/PNG /SampleFormat/Indexed4 /TransferEncoding/Binary
+ /Compression/ZIP /Predictor 15 >>
+ ]
+>>
diff --git a/graphics/sam2p/examples/fusiwhite_a85none.job b/graphics/sam2p/examples/fusiwhite_a85none.job
new file mode 100644
index 0000000000..f5920d0527
--- /dev/null
+++ b/graphics/sam2p/examples/fusiwhite_a85none.job
@@ -0,0 +1,8 @@
+<<%sam2p-job; by pts@fazekas.hu at Sat Jun 1 19:30:08 CEST 2002
+/InputFile (examples/fusiwhite.gif)
+/OutputFile (test.eps)
+/Profile [
+ << /FileFormat/PSL1 /SampleFormat/Gray4 /TransferEncoding/A85
+ /Compression/None >>
+]
+>>
diff --git a/graphics/sam2p/examples/fusiwhite_binnone.job b/graphics/sam2p/examples/fusiwhite_binnone.job
new file mode 100644
index 0000000000..f4c8bd68dd
--- /dev/null
+++ b/graphics/sam2p/examples/fusiwhite_binnone.job
@@ -0,0 +1,8 @@
+<<%sam2p-job; by pts@fazekas.hu at Sat Jun 1 16:46:25 CEST 2002
+/InputFile (examples/fusiwhite.gif)
+/OutputFile (test.eps)
+/Profile [
+ << /FileFormat/PSL1 /SampleFormat/Gray4 /TransferEncoding/Binary
+ /Compression/None >>
+]
+>>
diff --git a/graphics/sam2p/examples/fusiwhite_xwd.job b/graphics/sam2p/examples/fusiwhite_xwd.job
new file mode 100644
index 0000000000..bda3506967
--- /dev/null
+++ b/graphics/sam2p/examples/fusiwhite_xwd.job
@@ -0,0 +1,8 @@
+<<%sam2p-job; by pts@fazekas.hu at Sat Aug 10 23:30:08 CEST 2002
+/InputFile (examples/fusiwhite.gif)
+/OutputFile (test.xwd)
+/Profile [
+ << /FileFormat/XWD /SampleFormat/Gray8 /TransferEncoding/Binary
+ /Compression/None /Predictor 1 >>
+ ]
+>>
diff --git a/graphics/sam2p/examples/j_taska_lzw_eps.job b/graphics/sam2p/examples/j_taska_lzw_eps.job
new file mode 100644
index 0000000000..21ea2d5718
--- /dev/null
+++ b/graphics/sam2p/examples/j_taska_lzw_eps.job
@@ -0,0 +1,12 @@
+<<%sam2p-job; by pts@fazekas.hu at Tue Jun 11 20:09:17 CEST 2002
+%/InputFile (/tmp/j_taska.png)
+/InputFile (/tmp/j_taska.gif)
+/OutputFile (test.eps)
+%/LoadHints (asis)
+/Profile [
+ << /FileFormat/PSL2 /SampleFormat/Gray8 /TransferEncoding/A85
+ /Compression/LZW
+ % /Predictor 15
+ >>
+ ]
+>>
diff --git a/graphics/sam2p/examples/j_taska_rle_bmp.job b/graphics/sam2p/examples/j_taska_rle_bmp.job
new file mode 100644
index 0000000000..1530a96efb
--- /dev/null
+++ b/graphics/sam2p/examples/j_taska_rle_bmp.job
@@ -0,0 +1,11 @@
+<<%sam2p-job; by pts@fazekas.hu at Sun Jun 23 21:20:59 CEST 2002
+/InputFile (/tmp/j_taska.png)
+/OutputFile (test.bmp)
+%/LoadHints (asis)
+/Profile [
+ << /FileFormat/BMP /SampleFormat/Indexed8 /TransferEncoding/Binary
+ /Compression/RLE
+ % /Compression/None
+ >>
+ ]
+>>
diff --git a/graphics/sam2p/examples/mixing_ijg.job b/graphics/sam2p/examples/mixing_ijg.job
new file mode 100644
index 0000000000..7417f739df
--- /dev/null
+++ b/graphics/sam2p/examples/mixing_ijg.job
@@ -0,0 +1,9 @@
+<<%sam2p-job; by Fri Mar 22 13:10:53 CET 2002
+/InputFile (examples/mixing1.xpm)
+/OutputFile (test.eps)
+/Profile [
+ << /FileFormat/PSL2 /SampleFormat/RGB8 /TransferEncoding/A85
+ /Compression/IJG
+>>
+ ]
+>>
diff --git a/graphics/sam2p/examples/mixing_pcx_zip.job b/graphics/sam2p/examples/mixing_pcx_zip.job
new file mode 100644
index 0000000000..aac2047fce
--- /dev/null
+++ b/graphics/sam2p/examples/mixing_pcx_zip.job
@@ -0,0 +1,8 @@
+<<%sam2p-job; by Fri Mar 22 13:10:53 CET 2002
+/InputFile (examples/mixing1.pcx)
+/OutputFile (test.eps)
+/Profile [
+ << /FileFormat/PSL3 /SampleFormat/Indexed2 /TransferEncoding/A85
+ /Compression/ZIP /Predictor 2>>
+ ]
+>>
diff --git a/graphics/sam2p/examples/mixing_zip.job b/graphics/sam2p/examples/mixing_zip.job
new file mode 100644
index 0000000000..fd1233bb34
--- /dev/null
+++ b/graphics/sam2p/examples/mixing_zip.job
@@ -0,0 +1,8 @@
+<<%sam2p-job; by Fri Mar 22 13:10:53 CET 2002
+/InputFile (examples/mixing0.xpm)
+/OutputFile (test.eps)
+/Profile [
+ << /FileFormat/PSL3 /SampleFormat/Indexed2 /TransferEncoding/A85
+ /Compression/ZIP /Predictor 2>>
+ ]
+>>
diff --git a/graphics/sam2p/examples/pts2.pbm b/graphics/sam2p/examples/pts2.pbm
new file mode 100644
index 0000000000..006b4e3861
--- /dev/null
+++ b/graphics/sam2p/examples/pts2.pbm
Binary files differ
diff --git a/graphics/sam2p/examples/pts2_l1g8n_eps.job b/graphics/sam2p/examples/pts2_l1g8n_eps.job
new file mode 100644
index 0000000000..8e737d890c
--- /dev/null
+++ b/graphics/sam2p/examples/pts2_l1g8n_eps.job
@@ -0,0 +1,9 @@
+<<%sam2p-job; by pts@fazekas.hu at Sun Jun 2 16:25:06 CEST 2002
+/InputFile (examples/pts2.pbm)
+/OutputFile (test.eps)
+/Profile [
+ << /FileFormat/PSL1 /SampleFormat/Gray4
+ /TransferEncoding/A85
+ /Compression/None >>
+ ]
+>>
diff --git a/graphics/sam2p/examples/pts2_l1g8r_eps.job b/graphics/sam2p/examples/pts2_l1g8r_eps.job
new file mode 100644
index 0000000000..e4800cd9a3
--- /dev/null
+++ b/graphics/sam2p/examples/pts2_l1g8r_eps.job
@@ -0,0 +1,9 @@
+<<%sam2p-job; by pts@fazekas.hu at Sun Jun 2 15:31:48 CEST 2002
+/InputFile (examples/pts2.pbm)
+/OutputFile (test.eps)
+/Profile [
+ << /FileFormat/PSL1 /SampleFormat/Gray2
+ /TransferEncoding/Binary
+ /Compression/RLE >>
+ ]
+>>
diff --git a/graphics/sam2p/examples/pts2_l1gbr_eps.job b/graphics/sam2p/examples/pts2_l1gbr_eps.job
new file mode 100644
index 0000000000..efb9d623c5
--- /dev/null
+++ b/graphics/sam2p/examples/pts2_l1gbr_eps.job
@@ -0,0 +1,9 @@
+<<%sam2p-job; by pts@fazekas.hu at Sun Jun 2 15:30:22 CEST 2002
+/InputFile (examples/pts2.pbm)
+/OutputFile (test.eps)
+/Profile [
+ << /FileFormat/PSL1 /SampleFormat/Gray1
+ /TransferEncoding/Binary
+ /Compression/RLE >>
+ ]
+>>
diff --git a/graphics/sam2p/examples/pts2_pbm.job b/graphics/sam2p/examples/pts2_pbm.job
new file mode 100644
index 0000000000..949d7d54d6
--- /dev/null
+++ b/graphics/sam2p/examples/pts2_pbm.job
@@ -0,0 +1,10 @@
+<<%sam2p-job; by pts@fazekas.hu at Sun Mar 17 16:21:44 CET 2002
+% This is file (named test0.job).
+/InputFile (examples/pts2.pbm)
+/OutputFile (test.eps)
+/unknown pop
+/Profile [
+ << /FileFormat/PSL1 /SampleFormat/Gray8 /TransferEncoding/A85
+ /Compression/ZIP /Hints<</Effort 6>> /Predictor 1 >>
+]
+>>
diff --git a/graphics/sam2p/examples/pts2_pbm_pnm.job b/graphics/sam2p/examples/pts2_pbm_pnm.job
new file mode 100644
index 0000000000..731bbc0345
--- /dev/null
+++ b/graphics/sam2p/examples/pts2_pbm_pnm.job
@@ -0,0 +1,9 @@
+<<%sam2p-job; by pts@fazekas.hu at Tue Jun 4 21:42:08 CEST 2002
+/InputFile (examples/pts2.pbm)
+/OutputFile (test.pnm)
+/unknown pop
+/Profile [
+ << /FileFormat/PNM /SampleFormat/Indexed8 /TransferEncoding/Binary
+ /Compression/None >>
+]
+>>
diff --git a/graphics/sam2p/examples/pts2_pbm_zip0.job b/graphics/sam2p/examples/pts2_pbm_zip0.job
new file mode 100644
index 0000000000..2a94da8acd
--- /dev/null
+++ b/graphics/sam2p/examples/pts2_pbm_zip0.job
@@ -0,0 +1,10 @@
+<<%sam2p-job; by pts@fazekas.hu at Sun Mar 17 16:21:44 CET 2002
+% This is file (named test0.job).
+/InputFile (examples/pts2.pbm)
+/OutputFile (test.eps)
+/unknown pop
+/Profile [
+ << /FileFormat/PSL3 /SampleFormat/Gray8 /TransferEncoding/Binary
+ /Compression/ZIP /Hints<</Effort 0>> /Predictor 1 >>
+]
+>>
diff --git a/graphics/sam2p/examples/ptsbanner.gif b/graphics/sam2p/examples/ptsbanner.gif
new file mode 100644
index 0000000000..8cccb071bb
--- /dev/null
+++ b/graphics/sam2p/examples/ptsbanner.gif
Binary files differ
diff --git a/graphics/sam2p/examples/ptsbanner2_ijg_tiff.job b/graphics/sam2p/examples/ptsbanner2_ijg_tiff.job
new file mode 100644
index 0000000000..f0e644f35c
--- /dev/null
+++ b/graphics/sam2p/examples/ptsbanner2_ijg_tiff.job
@@ -0,0 +1,9 @@
+<<%sam2p-job; by pts@fazekas.hu at Tue Jun 11 19:49:26 CEST 2002
+/InputFile (examples/ptsbanner2a.jpg)
+/OutputFile (test.tiff)
+%/LoadHints (asis)
+/Profile [
+ << /FileFormat/TIFF /SampleFormat/Rgb8 /TransferEncoding/Binary
+ /Compression/IJG >>
+ ]
+>>
diff --git a/graphics/sam2p/examples/ptsbanner2_jai.job b/graphics/sam2p/examples/ptsbanner2_jai.job
new file mode 100644
index 0000000000..90ff2607cf
--- /dev/null
+++ b/graphics/sam2p/examples/ptsbanner2_jai.job
@@ -0,0 +1,9 @@
+<<%sam2p-job; by Sun Mar 17 21:59:30 CET 2002
+/InputFile (examples/ptsbanner2.jpg)
+/OutputFile (test.eps)
+%/LoadHints (asis)
+/Profile [
+ << /FileFormat/PSL3 /SampleFormat/Asis /TransferEncoding/Hex
+ /Compression/JAI >>
+ ]
+>>
diff --git a/graphics/sam2p/examples/ptsbanner2_jai_jpeg.job b/graphics/sam2p/examples/ptsbanner2_jai_jpeg.job
new file mode 100644
index 0000000000..5057b82ef4
--- /dev/null
+++ b/graphics/sam2p/examples/ptsbanner2_jai_jpeg.job
@@ -0,0 +1,9 @@
+<<%sam2p-job; by pts@fazekas.hu at Wed Apr 17 13:49:02 CEST 2002
+/InputFile (examples/ptsbanner2.jpg)
+/OutputFile (test.jpg)
+%/LoadHints (asis)
+/Profile [
+ << /FileFormat/JPEG /SampleFormat/Asis /TransferEncoding/Binary
+ /Compression/JAI >>
+ ]
+>>
diff --git a/graphics/sam2p/examples/ptsbanner2_jai_pdf.job b/graphics/sam2p/examples/ptsbanner2_jai_pdf.job
new file mode 100644
index 0000000000..6f514072c6
--- /dev/null
+++ b/graphics/sam2p/examples/ptsbanner2_jai_pdf.job
@@ -0,0 +1,8 @@
+<<%sam2p-job; by pts@fazekas.hu at Wed Apr 17 12:26:49 CEST 2002
+/InputFile (examples/ptsbanner2.jpg)
+/OutputFile (test.pdf)
+/Profile [
+ << /FileFormat/PDF1.2 /SampleFormat/Asis /TransferEncoding/A85
+ /Compression/JAI >>
+ ]
+>>
diff --git a/graphics/sam2p/examples/ptsbanner2_jai_tiff.job b/graphics/sam2p/examples/ptsbanner2_jai_tiff.job
new file mode 100644
index 0000000000..d1ed8ada60
--- /dev/null
+++ b/graphics/sam2p/examples/ptsbanner2_jai_tiff.job
@@ -0,0 +1,9 @@
+<<%sam2p-job; by pts@fazekas.hu at Sun Jun 2 22:28:37 CEST 2002
+/InputFile (examples/ptsbanner2a.jpg)
+/OutputFile (test.tiff)
+%/LoadHints (asis)
+/Profile [
+ << /FileFormat/TIFF /SampleFormat/Asis /TransferEncoding/Binary
+ /Compression/JAI >>
+ ]
+>>
diff --git a/graphics/sam2p/examples/ptsbanner2_jpeg_tiff.job b/graphics/sam2p/examples/ptsbanner2_jpeg_tiff.job
new file mode 100644
index 0000000000..ac8a94892b
--- /dev/null
+++ b/graphics/sam2p/examples/ptsbanner2_jpeg_tiff.job
@@ -0,0 +1,9 @@
+<<%sam2p-job; by pts@fazekas.hu at Tue Jun 11 19:49:26 CEST 2002
+/InputFile (examples/ptsbanner2a.jpg)
+/OutputFile (test.tiff)
+%/LoadHints (asis)
+/Profile [
+ << /FileFormat/TIFF /SampleFormat/Rgb8 /TransferEncoding/Binary
+ /Compression/DCT >>
+ ]
+>>
diff --git a/graphics/sam2p/examples/ptsbanner__jpeg.job b/graphics/sam2p/examples/ptsbanner__jpeg.job
new file mode 100644
index 0000000000..bfce6c0190
--- /dev/null
+++ b/graphics/sam2p/examples/ptsbanner__jpeg.job
@@ -0,0 +1,9 @@
+<<%sam2p-job; by Sun Mar 17 21:59:30 CET 2002
+/InputFile (examples/ptsbanner.gif)
+/OutputFile (test.jpg)
+%/LoadHints (asis)
+/Profile [
+ << /FileFormat/JPEG /SampleFormat/Rgb8 /TransferEncoding/Binary
+ /Compression/IJG >>
+ ]
+>>
diff --git a/graphics/sam2p/examples/ptsbanner_bbox_pdf.job b/graphics/sam2p/examples/ptsbanner_bbox_pdf.job
new file mode 100644
index 0000000000..2e83c1ef19
--- /dev/null
+++ b/graphics/sam2p/examples/ptsbanner_bbox_pdf.job
@@ -0,0 +1,12 @@
+<<%sam2p-job; by pts@fazekas.hu at Sat Jun 15 16:47:10 CEST 2002
+/InputFile (examples/ptsbanner.gif)
+/OutputFile (test.pdf)
+/Profile [
+ << /FileFormat/PDF1.0 /SampleFormat/Bbox /TransferEncoding/Hex
+ % /Compression/LZW /Predictor 15
+ /Compression/RLE
+ % /Compression/LZW /Predictor 2
+ % /Compression/LZW
+ >>
+ ]
+>>
diff --git a/graphics/sam2p/examples/ptsbanner_gif_xwd.job b/graphics/sam2p/examples/ptsbanner_gif_xwd.job
new file mode 100644
index 0000000000..528a3d97d8
--- /dev/null
+++ b/graphics/sam2p/examples/ptsbanner_gif_xwd.job
@@ -0,0 +1,8 @@
+<<%sam2p-job; by pts@fazekas.hu at Sat Aug 10 23:30:08 CEST 2002
+/InputFile (examples/ptsbanner.gif)
+/OutputFile (test.xwd)
+/Profile [
+ << /FileFormat/XWD /SampleFormat/Indexed8 /TransferEncoding/Binary
+ /Compression/None /Predictor 1 >>
+ ]
+>>
diff --git a/graphics/sam2p/examples/ptsbanner_jpeg.job b/graphics/sam2p/examples/ptsbanner_jpeg.job
new file mode 100644
index 0000000000..5a836e0d8b
--- /dev/null
+++ b/graphics/sam2p/examples/ptsbanner_jpeg.job
@@ -0,0 +1,8 @@
+<<%sam2p-job; by Sun Mar 17 22:34:14 CET 2002
+/InputFile (examples/ptsbanner2.jpg)
+/OutputFile (test.eps)
+/Profile [
+ << /FileFormat/PSLC /SampleFormat/Rgb8 /TransferEncoding/Hex
+ /Compression/None >>
+ ]
+>>
diff --git a/graphics/sam2p/examples/ptsbanner_jpg_xwd.job b/graphics/sam2p/examples/ptsbanner_jpg_xwd.job
new file mode 100644
index 0000000000..690a7429c5
--- /dev/null
+++ b/graphics/sam2p/examples/ptsbanner_jpg_xwd.job
@@ -0,0 +1,8 @@
+<<%sam2p-job; by pts@fazekas.hu at Sat Aug 10 23:30:08 CEST 2002
+/InputFile (examples/ptsbanner2.jpg)
+/OutputFile (test.xwd)
+/Profile [
+ << /FileFormat/XWD /SampleFormat/Rgb8 /TransferEncoding/Binary
+ /Compression/None /Predictor 1 >>
+ ]
+>>
diff --git a/graphics/sam2p/examples/ptsbanner_lzw.job b/graphics/sam2p/examples/ptsbanner_lzw.job
new file mode 100644
index 0000000000..f90230e4fc
--- /dev/null
+++ b/graphics/sam2p/examples/ptsbanner_lzw.job
@@ -0,0 +1,8 @@
+<<%sam2p-job; by Fri Mar 22 13:10:53 CET 2002
+/InputFile (examples/ptsbanner.gif)
+/OutputFile (test.eps)
+/Profile [
+ << /FileFormat/PSL2 /SampleFormat/Indexed8 /TransferEncoding/Hex
+ /Compression/LZW /Predictor 15 >>
+ ]
+>>
diff --git a/graphics/sam2p/examples/ptsbanner_lzw_framed.job b/graphics/sam2p/examples/ptsbanner_lzw_framed.job
new file mode 100644
index 0000000000..2b01660447
--- /dev/null
+++ b/graphics/sam2p/examples/ptsbanner_lzw_framed.job
@@ -0,0 +1,13 @@
+<<%sam2p-job; by pts@fazekas.hu at Sat Sep 7 15:48:57 CEST 2002
+/InputFile (examples/ptsbanner.gif)
+/OutputFile (test.eps)
+/Profile [
+ << /FileFormat/PSL2 /SampleFormat/Indexed8 /TransferEncoding/Hex
+ /Compression/LZW /Predictor 15
+ /Hints <<
+ /LeftMargin 20 /TopMargin 15
+ /RightMargin 10 /BottomMargin 25
+ >>
+ >>
+ ]
+>>
diff --git a/graphics/sam2p/examples/ptsbanner_lzw_margin.job b/graphics/sam2p/examples/ptsbanner_lzw_margin.job
new file mode 100644
index 0000000000..f1b6094b62
--- /dev/null
+++ b/graphics/sam2p/examples/ptsbanner_lzw_margin.job
@@ -0,0 +1,13 @@
+<<%sam2p-job; by pts@fazekas.hu at Sat Sep 7 15:26:41 CEST 2002
+/InputFile (examples/ptsbanner.gif)
+/OutputFile (test.eps)
+/Profile [
+ << /FileFormat/PSL2 /SampleFormat/Indexed8 /TransferEncoding/Hex
+ /Compression/LZW /Predictor 15
+ /Hints <<
+ /LeftMargin 10.5 pt /TopMargin -360dd
+ /RightMargin 3 bp /BottomMargin 5.0in
+ >>
+ >>
+ ]
+>>
diff --git a/graphics/sam2p/examples/ptsbanner_lzw_margin_pdf.job b/graphics/sam2p/examples/ptsbanner_lzw_margin_pdf.job
new file mode 100644
index 0000000000..649c35ad1b
--- /dev/null
+++ b/graphics/sam2p/examples/ptsbanner_lzw_margin_pdf.job
@@ -0,0 +1,13 @@
+<<%sam2p-job; by pts@fazekas.hu at Sat Sep 7 22:48:18 CEST 2002
+/InputFile (examples/ptsbanner.gif)
+/OutputFile (test.pdf)
+/Profile [
+ << /FileFormat/PDFB1.0 /SampleFormat/Indexed8 /TransferEncoding/Hex
+ /Compression/LZW /Predictor 15
+ /Hints <<
+ /LeftMargin 20 /TopMargin 15
+ /RightMargin 10 /BottomMargin 25
+ >>
+ >>
+ ]
+>>
diff --git a/graphics/sam2p/examples/ptsbanner_lzw_pdf.job b/graphics/sam2p/examples/ptsbanner_lzw_pdf.job
new file mode 100644
index 0000000000..e6954a0cab
--- /dev/null
+++ b/graphics/sam2p/examples/ptsbanner_lzw_pdf.job
@@ -0,0 +1,12 @@
+<<%sam2p-job; by pts@fazekas.hu at Sat Apr 20 19:03:10 CEST 2002
+/InputFile (examples/ptsbanner.gif)
+/OutputFile (test.pdf)
+/Profile [
+ << /FileFormat/PDF1.0 /SampleFormat/Indexed8 /TransferEncoding/Hex
+ % /Compression/LZW /Predictor 15
+ % /Compression/RLE
+ /Compression/LZW /Predictor 2
+ % /Compression/LZW
+ >>
+ ]
+>>
diff --git a/graphics/sam2p/examples/ptsbanner_lzw_pdfb.job b/graphics/sam2p/examples/ptsbanner_lzw_pdfb.job
new file mode 100644
index 0000000000..00fbfe51f3
--- /dev/null
+++ b/graphics/sam2p/examples/ptsbanner_lzw_pdfb.job
@@ -0,0 +1,10 @@
+<<%sam2p-job; by pts@fazekas.hu at Sat Apr 20 19:03:39 CEST 2002
+/InputFile (examples/ptsbanner.gif)
+/OutputFile (test.pdf)
+/Profile [
+ << /FileFormat/PDFB1.0 /SampleFormat/Indexed8 /TransferEncoding/Hex
+ % /Compression/LZW /Predictor 2 % OK in pdftops 0.92
+ /Compression/LZW /Predictor 10 % triggers bug in pdftops 0.92
+ >>
+ ]
+>>
diff --git a/graphics/sam2p/examples/ptsbanner_lzw_ps.job b/graphics/sam2p/examples/ptsbanner_lzw_ps.job
new file mode 100644
index 0000000000..9668e26bb6
--- /dev/null
+++ b/graphics/sam2p/examples/ptsbanner_lzw_ps.job
@@ -0,0 +1,12 @@
+<<%sam2p-job; by pts@fazekas.hu at Fri Aug 16 17:22:27 CEST 2002
+/InputFile (examples/ptsbanner.gif)
+/OutputFile (test.ps)
+/Profile [
+ << /FileFormat/PSL2 /SampleFormat/Indexed8 /TransferEncoding/Hex
+ /Compression/LZW /Predictor 15
+ /Hints << /Scale/OK /LeftMargin 10.5 pt /RightMargin 21dd
+ /TopMargin 0 bp
+ >>
+ >>
+ ]
+>>
diff --git a/graphics/sam2p/examples/ptsbanner_lzw_rot_ps.job b/graphics/sam2p/examples/ptsbanner_lzw_rot_ps.job
new file mode 100644
index 0000000000..57624a4901
--- /dev/null
+++ b/graphics/sam2p/examples/ptsbanner_lzw_rot_ps.job
@@ -0,0 +1,10 @@
+<<%sam2p-job; by Fri Mar 22 13:10:53 CET 2002
+/InputFile (examples/ptsbanner.gif)
+/OutputFile (test.ps)
+/Profile [
+ << /FileFormat/PSL2 /SampleFormat/Indexed8 /TransferEncoding/Hex
+ /Compression/LZW /Predictor 15
+ /Hints << /Scale/RotateOK /LeftMargin 10.5 /RightMargin 21 >>
+ >>
+ ]
+>>
diff --git a/graphics/sam2p/examples/ptsbanner_lzw_tiff.job b/graphics/sam2p/examples/ptsbanner_lzw_tiff.job
new file mode 100644
index 0000000000..a3a11e68ce
--- /dev/null
+++ b/graphics/sam2p/examples/ptsbanner_lzw_tiff.job
@@ -0,0 +1,12 @@
+<<%sam2p-job; by Tue Jun 4 18:28:53 CEST 2002
+/InputFile (examples/ptsbanner.gif)
+/OutputFile (test.tiff)
+/Profile [
+ << /FileFormat/TIFF
+ /SampleFormat/Indexed8
+ % /SampleFormat/Rgb8
+ /TransferEncoding/LSBfirst
+ /Compression/LZW /Predictor 2
+ % /Compression/None
+ >> ]
+>>
diff --git a/graphics/sam2p/examples/ptsbanner_none_tiff.job b/graphics/sam2p/examples/ptsbanner_none_tiff.job
new file mode 100644
index 0000000000..a9e7f78d0c
--- /dev/null
+++ b/graphics/sam2p/examples/ptsbanner_none_tiff.job
@@ -0,0 +1,8 @@
+<<%sam2p-job; by Tue Jun 4 18:28:53 CEST 2002
+/InputFile (examples/ptsbanner.gif)
+/OutputFile (test.tiff)
+/Profile [
+ << /FileFormat/TIFF /SampleFormat/Indexed8 /TransferEncoding/LSBfirst
+ /Compression/None
+ >> ]
+>>
diff --git a/graphics/sam2p/examples/ptsbanner_png.job b/graphics/sam2p/examples/ptsbanner_png.job
new file mode 100644
index 0000000000..8f65f2aa8b
--- /dev/null
+++ b/graphics/sam2p/examples/ptsbanner_png.job
@@ -0,0 +1,8 @@
+<<%sam2p-job; by Fri Mar 22 13:10:53 CET 2002
+/InputFile (examples/ptsbanner.gif)
+/OutputFile (test.png)
+/Profile [
+ << /FileFormat/PNG /SampleFormat/RGB8 /TransferEncoding/Binary
+ /Compression/ZIP /Predictor 12>>
+ ]
+>>
diff --git a/graphics/sam2p/examples/ptsbanner_rle_pdf.job b/graphics/sam2p/examples/ptsbanner_rle_pdf.job
new file mode 100644
index 0000000000..ce9c89cc5b
--- /dev/null
+++ b/graphics/sam2p/examples/ptsbanner_rle_pdf.job
@@ -0,0 +1,12 @@
+<<%sam2p-job; by pts@fazekas.hu at Tue Jun 4 18:46:53 CEST 2002
+/InputFile (examples/ptsbanner.gif)
+/OutputFile (test.pdf)
+/Profile [
+ << /FileFormat/PDF1.0 /SampleFormat/Indexed8 /TransferEncoding/Hex
+ % /Compression/LZW /Predictor 15
+ /Compression/RLE
+ % /Compression/LZW /Predictor 2
+ % /Compression/LZW
+ >>
+ ]
+>>
diff --git a/graphics/sam2p/examples/ptsbanner_rle_tiff.job b/graphics/sam2p/examples/ptsbanner_rle_tiff.job
new file mode 100644
index 0000000000..42e2fa23be
--- /dev/null
+++ b/graphics/sam2p/examples/ptsbanner_rle_tiff.job
@@ -0,0 +1,11 @@
+<<%sam2p-job; by Tue Jun 4 18:28:53 CEST 2002
+/InputFile (examples/ptsbanner.gif)
+/OutputFile (test.tiff)
+/Profile [
+ << /FileFormat/TIFF
+ /SampleFormat/Indexed8
+ % /SampleFormat/Rgb8
+ /TransferEncoding/LSBfirst
+ /Compression/RLE
+ >> ]
+>>
diff --git a/graphics/sam2p/examples/ptsbanner_tralzw.job b/graphics/sam2p/examples/ptsbanner_tralzw.job
new file mode 100644
index 0000000000..23df805301
--- /dev/null
+++ b/graphics/sam2p/examples/ptsbanner_tralzw.job
@@ -0,0 +1,18 @@
+<<%sam2p-job; by Fri Mar 22 13:10:53 CET 2002
+/InputFile (examples/ptsbanner.gif)
+/OutputFile(test.eps)
+/Profile [
+% sasdasdasd /Korte [
+ << /FileFormat /PSL2 /SampleFormat/Transparent8
+ /TransferEncoding/Binary
+ /WarningOK true
+ % /TransferEncoding/Hex
+ % /Compression/LZW
+ /Predictor 1
+ /Compression /RLE
+ /Hints << /K 42 >>
+ >>
+ ]
+>>
+
+
diff --git a/graphics/sam2p/examples/ptsbanner_xpm_zip.job b/graphics/sam2p/examples/ptsbanner_xpm_zip.job
new file mode 100644
index 0000000000..d95c938420
--- /dev/null
+++ b/graphics/sam2p/examples/ptsbanner_xpm_zip.job
@@ -0,0 +1,8 @@
+<<%sam2p-job; by Fri Mar 22 13:10:53 CET 2002
+/InputFile (examples/ptsbanner.xpm)
+/OutputFile (test.eps)
+/Profile [
+ << /FileFormat/PSL3 /SampleFormat/Rgb4 /TransferEncoding/A85
+ /Compression/ZIP /Predictor 2>>
+ ] % /a 4
+>>
diff --git a/graphics/sam2p/examples/ptsbanner_zip.job b/graphics/sam2p/examples/ptsbanner_zip.job
new file mode 100644
index 0000000000..afb7edd048
--- /dev/null
+++ b/graphics/sam2p/examples/ptsbanner_zip.job
@@ -0,0 +1,8 @@
+<<%sam2p-job; by Fri Mar 22 13:10:53 CET 2002
+/InputFile (examples/ptsbanner.gif)
+/OutputFile (test.eps)
+/Profile [
+ << /FileFormat/PSL3 /SampleFormat/RGB4 /TransferEncoding/A85
+ /Compression/ZIP /Predictor 2>>
+ ]
+>>
diff --git a/graphics/sam2p/examples/ptsbanner_ziprgb4_tiff.job b/graphics/sam2p/examples/ptsbanner_ziprgb4_tiff.job
new file mode 100644
index 0000000000..ece5e0c1d3
--- /dev/null
+++ b/graphics/sam2p/examples/ptsbanner_ziprgb4_tiff.job
@@ -0,0 +1,13 @@
+<<%sam2p-job; by Tue Jun 4 19:41:52 CEST 2002
+% Note: this doesn't work with libtiff, because they haven't implemented
+% the predictor...
+/InputFile (examples/ptsbanner.gif)
+/OutputFile (test.tiff)
+/Profile [
+ << /FileFormat/TIFF
+ % /SampleFormat/Indexed8
+ /SampleFormat/Rgb4
+ /TransferEncoding/LSBfirst
+ /Compression/ZIP /Predictor 2
+ >> ]
+>>
diff --git a/graphics/sam2p/examples/ptsbanner_ziprgb8_tiff.job b/graphics/sam2p/examples/ptsbanner_ziprgb8_tiff.job
new file mode 100644
index 0000000000..fca693d190
--- /dev/null
+++ b/graphics/sam2p/examples/ptsbanner_ziprgb8_tiff.job
@@ -0,0 +1,11 @@
+<<%sam2p-job; by pts@fazekas.hu at Tue Jun 4 19:42:29 CEST 2002
+/InputFile (examples/ptsbanner.gif)
+/OutputFile (test.tiff)
+/Profile [
+ << /FileFormat/TIFF
+ % /SampleFormat/Indexed8
+ /SampleFormat/Rgb8
+ /TransferEncoding/LSBfirst
+ /Compression/ZIP /Predictor 2
+ >> ]
+>>
diff --git a/graphics/sam2p/examples/ptsbannerg_jai.job b/graphics/sam2p/examples/ptsbannerg_jai.job
new file mode 100644
index 0000000000..ce71fe7825
--- /dev/null
+++ b/graphics/sam2p/examples/ptsbannerg_jai.job
@@ -0,0 +1,9 @@
+<<%sam2p-job; by Sun Mar 17 21:59:30 CET 2002
+/InputFile (examples/ptsbannerg.jpg)
+/OutputFile (test.eps)
+%/LoadHints (asis)
+/Profile [
+ << /FileFormat/PSL3 /SampleFormat/Asis /TransferEncoding/Hex
+ /Compression/JAI >>
+ ]
+>>
diff --git a/graphics/sam2p/examples/ptsbannerg_jai_pdf.job b/graphics/sam2p/examples/ptsbannerg_jai_pdf.job
new file mode 100644
index 0000000000..eb93a6eb23
--- /dev/null
+++ b/graphics/sam2p/examples/ptsbannerg_jai_pdf.job
@@ -0,0 +1,8 @@
+<<%sam2p-job; by pts@fazekas.hu at Wed Apr 17 12:26:49 CEST 2002
+/InputFile (examples/ptsbannerg.jpg)
+/OutputFile (test.pdf)
+/Profile [
+ << /FileFormat/PDFB1.0 /SampleFormat/Asis /TransferEncoding/A85
+ /Compression/JAI >>
+ ]
+>>
diff --git a/graphics/sam2p/examples/ptsbannerg_jai_tiff.job b/graphics/sam2p/examples/ptsbannerg_jai_tiff.job
new file mode 100644
index 0000000000..292e5a2444
--- /dev/null
+++ b/graphics/sam2p/examples/ptsbannerg_jai_tiff.job
@@ -0,0 +1,9 @@
+<<%sam2p-job; by pts@fazekas.hu at Tue Jun 4 15:15:20 CEST 2002
+/InputFile (examples/ptsbannerg.jpg)
+/OutputFile (test.tiff)
+%/LoadHints (asis)
+/Profile [
+ << /FileFormat/TIFF /SampleFormat/Asis /TransferEncoding/Binary
+ /Compression/JAI >>
+ ]
+>>
diff --git a/graphics/sam2p/examples/ptsbannerg_lzw_tiff.job b/graphics/sam2p/examples/ptsbannerg_lzw_tiff.job
new file mode 100644
index 0000000000..e4eb830b60
--- /dev/null
+++ b/graphics/sam2p/examples/ptsbannerg_lzw_tiff.job
@@ -0,0 +1,12 @@
+<<%sam2p-job; by Tue Jun 4 18:28:53 CEST 2002
+/InputFile (examples/ptsbannerg.jpg)
+/OutputFile (test.tiff)
+/Profile [
+ << /FileFormat/TIFF
+ % /SampleFormat/Indexed8
+ /SampleFormat/Gray8
+ /TransferEncoding/LSBfirst
+ /Compression/LZW /Predictor 2
+ % /Compression/None
+ >> ]
+>>
diff --git a/graphics/sam2p/examples/sam2p_fishg.job b/graphics/sam2p/examples/sam2p_fishg.job
new file mode 100644
index 0000000000..8713cedb7a
--- /dev/null
+++ b/graphics/sam2p/examples/sam2p_fishg.job
@@ -0,0 +1,8 @@
+<<%sam2p-job; by pts@fazekas.hu at Fri Apr 26 09:33:29 CEST 2002
+/InputFile (talk/fishg.gif)
+/OutputFile (talk/fishg.pdf)
+/Profile [
+ << /FileFormat/PDFB1.0 /SampleFormat/Indexed2 /TransferEncoding/Binary
+ /Compression/LZW /Predictor 2 >>
+ ]
+>>
diff --git a/graphics/sam2p/examples/sam2p_fisht.job b/graphics/sam2p/examples/sam2p_fisht.job
new file mode 100644
index 0000000000..8713cedb7a
--- /dev/null
+++ b/graphics/sam2p/examples/sam2p_fisht.job
@@ -0,0 +1,8 @@
+<<%sam2p-job; by pts@fazekas.hu at Fri Apr 26 09:33:29 CEST 2002
+/InputFile (talk/fishg.gif)
+/OutputFile (talk/fishg.pdf)
+/Profile [
+ << /FileFormat/PDFB1.0 /SampleFormat/Indexed2 /TransferEncoding/Binary
+ /Compression/LZW /Predictor 2 >>
+ ]
+>>
diff --git a/graphics/sam2p/examples/sam2p_fishwbb.job b/graphics/sam2p/examples/sam2p_fishwbb.job
new file mode 100644
index 0000000000..b93a105e1b
--- /dev/null
+++ b/graphics/sam2p/examples/sam2p_fishwbb.job
@@ -0,0 +1,8 @@
+<<%sam2p-job; by pts@fazekas.hu at Fri Apr 26 09:33:29 CEST 2002
+/InputFile (talk/fishwbb.gif)
+/OutputFile (talk/fishwbb.pdf)
+/Profile [
+ << /FileFormat/PDFB1.0 /SampleFormat/Indexed2 /TransferEncoding/Binary
+ /Compression/LZW /Predictor 2 >>
+ ]
+>>
diff --git a/graphics/sam2p/examples/sam2p_fishwbg.job b/graphics/sam2p/examples/sam2p_fishwbg.job
new file mode 100644
index 0000000000..7719ef92ef
--- /dev/null
+++ b/graphics/sam2p/examples/sam2p_fishwbg.job
@@ -0,0 +1,8 @@
+<<%sam2p-job; by pts@fazekas.hu at Fri Apr 26 09:33:29 CEST 2002
+/InputFile (talk/fishwbg.gif)
+/OutputFile (talk/fishwbg.pdf)
+/Profile [
+ << /FileFormat/PDFB1.0 /SampleFormat/Indexed4 /TransferEncoding/Binary
+ /Compression/LZW /Predictor 10>>
+ ]
+>>
diff --git a/graphics/sam2p/examples/sam2p_fishwbg_bug.job b/graphics/sam2p/examples/sam2p_fishwbg_bug.job
new file mode 100644
index 0000000000..a12b84870c
--- /dev/null
+++ b/graphics/sam2p/examples/sam2p_fishwbg_bug.job
@@ -0,0 +1,9 @@
+<<%sam2p-job; by pts@fazekas.hu at Fri Apr 26 09:33:29 CEST 2002
+% Shows acroread4 bug (Predictor 2 with indexed images)
+/InputFile (talk/fishwbg.gif)
+/OutputFile (talk/fishwbg.pdf)
+/Profile [
+ << /FileFormat/PDFB1.0 /SampleFormat/Indexed4 /TransferEncoding/Binary
+ /Compression/LZW /Predictor 2 >>
+ ]
+>>
diff --git a/graphics/sam2p/examples/sam2p_fishwww.job b/graphics/sam2p/examples/sam2p_fishwww.job
new file mode 100644
index 0000000000..d8704f832f
--- /dev/null
+++ b/graphics/sam2p/examples/sam2p_fishwww.job
@@ -0,0 +1,8 @@
+<<%sam2p-job; by pts@fazekas.hu at Fri Apr 26 09:33:29 CEST 2002
+/InputFile (talk/fishwww.gif)
+/OutputFile (talk/fishwww.pdf)
+/Profile [
+ << /FileFormat/PDFB1.0 /SampleFormat/Opaque /TransferEncoding/Binary
+ /Compression/LZW /Predictor 2 >>
+ ]
+>>
diff --git a/graphics/sam2p/examples/sam2psho.job b/graphics/sam2p/examples/sam2psho.job
new file mode 100644
index 0000000000..8262a3664f
--- /dev/null
+++ b/graphics/sam2p/examples/sam2psho.job
@@ -0,0 +1,8 @@
+<<%sam2p-job; by pts@fazekas.hu at Thu Apr 25 09:09:51 CEST 2002
+/InputFile (talk/sam2psho.png)
+/OutputFile (talk/sam2psho.pdf)
+/Profile [
+ << /FileFormat/PDFB1.0 /SampleFormat/Indexed8 /TransferEncoding/Binary
+ /Compression/LZW /Predictor 2 >>
+ ]
+>>
diff --git a/graphics/sam2p/examples/shot_fax31d_tiff.job b/graphics/sam2p/examples/shot_fax31d_tiff.job
new file mode 100644
index 0000000000..83e8978f0d
--- /dev/null
+++ b/graphics/sam2p/examples/shot_fax31d_tiff.job
@@ -0,0 +1,12 @@
+<<%sam2p-job; by pts@fazekas.hu at Tue Jun 4 22:13:03 CEST 2002
+/InputFile (examples/shot.gif)
+/OutputFile (test.tiff)
+/Profile [
+ << /FileFormat/TIFF
+ % /SampleFormat/Indexed8
+ /SampleFormat/Indexed1
+ /TransferEncoding/MSBfirst
+ /Compression/CCITTFax
+ % default: /Hints << /K 0 >>
+ >> ]
+>>
diff --git a/graphics/sam2p/examples/shot_fax32d_tiff.job b/graphics/sam2p/examples/shot_fax32d_tiff.job
new file mode 100644
index 0000000000..37c5bbaa2b
--- /dev/null
+++ b/graphics/sam2p/examples/shot_fax32d_tiff.job
@@ -0,0 +1,13 @@
+<<%sam2p-job; by pts@fazekas.hu at Tue Jun 4 22:13:03 CEST 2002
+/InputFile (examples/shot.gif)
+/OutputFile (test.tiff)
+/Profile [
+ << /FileFormat/TIFF
+ % /SampleFormat/Indexed8
+ /SampleFormat/Indexed1
+ /TransferEncoding/MSBfirst
+ /Compression/CCITTFax
+ %/Compression/RLE
+ /Hints << /K 5 >> % Group3 2D
+ >> ]
+>>
diff --git a/graphics/sam2p/examples/shot_fax4_tiff.job b/graphics/sam2p/examples/shot_fax4_tiff.job
new file mode 100644
index 0000000000..970de4418f
--- /dev/null
+++ b/graphics/sam2p/examples/shot_fax4_tiff.job
@@ -0,0 +1,12 @@
+<<%sam2p-job; by pts@fazekas.hu at Tue Jun 4 22:13:03 CEST 2002
+/InputFile (examples/shot.gif)
+/OutputFile (test.tiff)
+/Profile [
+ << /FileFormat/TIFF
+ % /SampleFormat/Indexed8
+ /SampleFormat/Indexed1
+ /TransferEncoding/MSBfirst
+ /Compression/CCITTFax
+ /Hints << /K -1 >> % Group4
+ >> ]
+>>
diff --git a/graphics/sam2p/examples/shot_gif.job b/graphics/sam2p/examples/shot_gif.job
new file mode 100644
index 0000000000..544c321378
--- /dev/null
+++ b/graphics/sam2p/examples/shot_gif.job
@@ -0,0 +1,8 @@
+<<%sam2p-job; by Fri Mar 22 17:36:41 CET 2002
+/InputFile (examples/shot_large.gif)
+%/OutputFile (examples/shot.gif)
+/OutputFile (test.gif)
+/Profile [
+ << /FileFormat/GIF89a /SampleFormat/Indexed1 /TransferEncoding/Binary /Compression/None >>
+ ]
+>>
diff --git a/graphics/sam2p/examples/shot_i1.job b/graphics/sam2p/examples/shot_i1.job
new file mode 100644
index 0000000000..b32e18948d
--- /dev/null
+++ b/graphics/sam2p/examples/shot_i1.job
@@ -0,0 +1,7 @@
+<<%sam2p-job; by Fri Mar 22 17:36:41 CET 2002
+/InputFile (examples/shot.gif)
+/OutputFile (test.eps)
+/Profile [
+ << /FileFormat/PSL2 /SampleFormat/Indexed1 /TransferEncoding/Binary /Compression/RLE >>
+ ]
+>>
diff --git a/graphics/sam2p/examples/shot_l118r_eps.job b/graphics/sam2p/examples/shot_l118r_eps.job
new file mode 100644
index 0000000000..d4a45e6fc1
--- /dev/null
+++ b/graphics/sam2p/examples/shot_l118r_eps.job
@@ -0,0 +1,10 @@
+<<%sam2p-job; by pts@fazekas.hu at Sat Jun 1 21:56:11 CEST 2002
+/InputFile (examples/shot.gif)
+/OutputFile (test.eps)
+/Profile [
+ << /FileFormat/PSL1
+ /SampleFormat/Indexed1
+ /TransferEncoding/A85
+ /Compression/RLE >>
+ ]
+>>
diff --git a/graphics/sam2p/examples/shot_l11bn_eps.job b/graphics/sam2p/examples/shot_l11bn_eps.job
new file mode 100644
index 0000000000..ce01b50bbc
--- /dev/null
+++ b/graphics/sam2p/examples/shot_l11bn_eps.job
@@ -0,0 +1,10 @@
+<<%sam2p-job; by pts@fazekas.hu at Sat Jun 1 21:56:11 CEST 2002
+/InputFile (examples/shot.gif)
+/OutputFile (test.eps)
+/Profile [
+ << /FileFormat/PSL1
+ /SampleFormat/Indexed1
+ /TransferEncoding/Binary
+ /Compression/None >>
+ ]
+>>
diff --git a/graphics/sam2p/examples/shot_l11br_eps.job b/graphics/sam2p/examples/shot_l11br_eps.job
new file mode 100644
index 0000000000..49aed717c8
--- /dev/null
+++ b/graphics/sam2p/examples/shot_l11br_eps.job
@@ -0,0 +1,10 @@
+<<%sam2p-job; by pts@fazekas.hu at Sat Jun 1 21:56:11 CEST 2002
+/InputFile (examples/shot.gif)
+/OutputFile (test.eps)
+/Profile [
+ << /FileFormat/PSL1
+ /SampleFormat/Indexed1
+ /TransferEncoding/Binary
+ /Compression/RLE >>
+ ]
+>>
diff --git a/graphics/sam2p/examples/shot_l11hr_eps.job b/graphics/sam2p/examples/shot_l11hr_eps.job
new file mode 100644
index 0000000000..695ae1e84f
--- /dev/null
+++ b/graphics/sam2p/examples/shot_l11hr_eps.job
@@ -0,0 +1,10 @@
+<<%sam2p-job; by pts@fazekas.hu at Sat Jun 1 21:56:11 CEST 2002
+/InputFile (examples/shot.gif)
+/OutputFile (test.eps)
+/Profile [
+ << /FileFormat/PSL1
+ /SampleFormat/Indexed1
+ /TransferEncoding/Hex
+ /Compression/RLE >>
+ ]
+>>
diff --git a/graphics/sam2p/examples/shot_l1m8r_eps.job b/graphics/sam2p/examples/shot_l1m8r_eps.job
new file mode 100644
index 0000000000..cc69d3fee3
--- /dev/null
+++ b/graphics/sam2p/examples/shot_l1m8r_eps.job
@@ -0,0 +1,11 @@
+<<%sam2p-job; by pts@fazekas.hu at Sun Jun 2 15:17:55 CEST 2002
+% original (shot_mask.eps) by pts@fazekas.hu at Sat Mar 23 14:32:58 CET 2002
+/InputFile (examples/shot.gif)
+/OutputFile (test.eps)
+/Profile [
+ << /FileFormat/PSL1 /SampleFormat/Mask
+ /TransferEncoding/A85
+ /Transparent <fF008> % Means RGB color triplet #ff0080
+ /Compression/RLE >>
+ ]
+>>
diff --git a/graphics/sam2p/examples/shot_l1mbn_eps.job b/graphics/sam2p/examples/shot_l1mbn_eps.job
new file mode 100644
index 0000000000..9d456864bb
--- /dev/null
+++ b/graphics/sam2p/examples/shot_l1mbn_eps.job
@@ -0,0 +1,11 @@
+<<%sam2p-job; by pts@fazekas.hu at Sun Jun 2 15:16:11 CEST 2002
+% original (shot_mask.eps) by pts@fazekas.hu at Sat Mar 23 14:32:58 CET 2002
+/InputFile (examples/shot.gif)
+/OutputFile (test.eps)
+/Profile [
+ << /FileFormat/PSL1 /SampleFormat/Mask
+ /TransferEncoding/Binary
+ /Transparent <fF008> % Means RGB color triplet #ff0080
+ /Compression/None >>
+ ]
+>>
diff --git a/graphics/sam2p/examples/shot_l1mbr_eps.job b/graphics/sam2p/examples/shot_l1mbr_eps.job
new file mode 100644
index 0000000000..cd233d29c5
--- /dev/null
+++ b/graphics/sam2p/examples/shot_l1mbr_eps.job
@@ -0,0 +1,11 @@
+<<%sam2p-job; by pts@fazekas.hu at Sun Jun 2 15:16:11 CEST 2002
+% original (shot_mask.eps) by pts@fazekas.hu at Sat Mar 23 14:32:58 CET 2002
+/InputFile (examples/shot.gif)
+/OutputFile (test.eps)
+/Profile [
+ << /FileFormat/PSL1 /SampleFormat/Mask
+ /TransferEncoding/Binary
+ /Transparent <fF008> % Means RGB color triplet #ff0080
+ /Compression/RLE >>
+ ]
+>>
diff --git a/graphics/sam2p/examples/shot_l1mhr_eps.job b/graphics/sam2p/examples/shot_l1mhr_eps.job
new file mode 100644
index 0000000000..dbc550e35b
--- /dev/null
+++ b/graphics/sam2p/examples/shot_l1mhr_eps.job
@@ -0,0 +1,11 @@
+<<%sam2p-job; by Sun Jun 2 15:17:43 CEST 2002
+% original (shot_mask.eps) by pts@fazekas.hu at Sat Mar 23 14:32:58 CET 2002
+/InputFile (examples/shot.gif)
+/OutputFile (test.eps)
+/Profile [
+ << /FileFormat/PSL1 /SampleFormat/Mask
+ /TransferEncoding/Hex
+ /Transparent <fF008> % Means RGB color triplet #ff0080
+ /Compression/RLE >>
+ ]
+>>
diff --git a/graphics/sam2p/examples/shot_pdfb.job b/graphics/sam2p/examples/shot_pdfb.job
new file mode 100644
index 0000000000..0b84da5771
--- /dev/null
+++ b/graphics/sam2p/examples/shot_pdfb.job
@@ -0,0 +1,9 @@
+<<%sam2p-job; by pts@fazekas.hu at Sat Apr 20 20:55:37 CEST 2002
+/InputFile (examples/shot.gif)
+/OutputFile (test.pdf)
+% triggers Ghostscript 5.50 lowest-bit rendering bug
+/Profile [
+ << /FileFormat/PDFB1.2 /SampleFormat/Indexed1 /TransferEncoding/Binary
+ /Compression/ZIP /Predictor 45 >>
+ ]
+>>
diff --git a/graphics/sam2p/examples/shot_pdfb_hex.job b/graphics/sam2p/examples/shot_pdfb_hex.job
new file mode 100644
index 0000000000..defaf10fcb
--- /dev/null
+++ b/graphics/sam2p/examples/shot_pdfb_hex.job
@@ -0,0 +1,9 @@
+<<%sam2p-job; by pts@fazekas.hu at Sun Jun 23 19:18:10 CEST 2002
+/InputFile (examples/shot.gif)
+/OutputFile (test.pdf)
+% triggers Ghostscript 5.50 lowest-bit rendering bug
+/Profile [
+ << /FileFormat/PDFB1.2 /SampleFormat/Indexed1 /TransferEncoding/Hex
+ /Compression/ZIP /Predictor 45 >>
+ ]
+>>
diff --git a/graphics/sam2p/examples/shot_png.job b/graphics/sam2p/examples/shot_png.job
new file mode 100644
index 0000000000..fd783f7bbd
--- /dev/null
+++ b/graphics/sam2p/examples/shot_png.job
@@ -0,0 +1,7 @@
+<<%sam2p-job; by Fri Mar 22 17:36:41 CET 2002
+/InputFile (examples/shot_large.gif)
+/OutputFile (test.png)
+/Profile [
+ << /FileFormat/PNG /SampleFormat/Indexed1 /TransferEncoding/Binary /Compression/ZIP /Predictor 45 >>
+ ]
+>>
diff --git a/graphics/sam2p/examples/shot_ppm.job b/graphics/sam2p/examples/shot_ppm.job
new file mode 100644
index 0000000000..2990b7f414
--- /dev/null
+++ b/graphics/sam2p/examples/shot_ppm.job
@@ -0,0 +1,10 @@
+<<%sam2p-job; by pts@fazekas.hu at Sat Mar 23 14:32:58 CET 2002
+/InputFile (examples/shot.gif)
+/OutputFile (test.ppm)
+/Profile [
+ << /FileFormat/PNM /SampleFormat/Rgb8
+ /TransferEncoding/ASCII
+ % /TransferEncoding/Binary
+ /Compression/None >>
+ ]
+>>
diff --git a/graphics/sam2p/examples/sziget_al.job b/graphics/sam2p/examples/sziget_al.job
new file mode 100644
index 0000000000..0f3febfb4a
--- /dev/null
+++ b/graphics/sam2p/examples/sziget_al.job
@@ -0,0 +1,12 @@
+<<%sam2p-job; by Fri Mar 22 17:36:41 CET 2002
+/InputFile (examples/sziget_al.ppm)
+%/InputFile (examples/sziget.gif)
+/OutputFile (test.eps)
+/Profile [
+ << /FileFormat/PSL2 /SampleFormat/Mask /TransferEncoding/Binary
+% /Compression/RLE
+ /Compression/LZW
+% /Compression/None
+ >>
+ ]
+>>
diff --git a/graphics/sam2p/examples/sziget_al_pdf.job b/graphics/sam2p/examples/sziget_al_pdf.job
new file mode 100644
index 0000000000..897853d3a5
--- /dev/null
+++ b/graphics/sam2p/examples/sziget_al_pdf.job
@@ -0,0 +1,9 @@
+<<%sam2p-job; by pts@fazekas.hu at Sat Apr 20 20:49:05 CEST 2002
+/InputFile (examples/sziget_al.ppm)
+/OutputFile (test.pdf)
+/Profile [
+ << /FileFormat/PDF1.0 /SampleFormat/Mask /TransferEncoding/Binary
+ /Compression/RLE
+ >>
+ ]
+>>
diff --git a/graphics/sam2p/examples/sziget_ma.job b/graphics/sam2p/examples/sziget_ma.job
new file mode 100644
index 0000000000..731d40b92b
--- /dev/null
+++ b/graphics/sam2p/examples/sziget_ma.job
@@ -0,0 +1,8 @@
+<<%sam2p-job; by Fri Mar 22 17:36:41 CET 2002
+/InputFile (examples/sziget.gif)
+/OutputFile (test.eps)
+/Profile [
+ << /FileFormat/PSL2 /SampleFormat/Mask /TransferEncoding/Binary
+ /Compression/Fax >>
+ ]
+>>
diff --git a/graphics/sam2p/examples/transparent_tr.job b/graphics/sam2p/examples/transparent_tr.job
new file mode 100644
index 0000000000..adbaf72682
--- /dev/null
+++ b/graphics/sam2p/examples/transparent_tr.job
@@ -0,0 +1,7 @@
+<<%sam2p-job; by Fri Mar 22 17:54:01 CET 2002
+/InputFile (examples/transparent.gif)
+/OutputFile (test.eps)
+/Profile [
+ << /FileFormat/PSL1 /SampleFormat/Transparent /TransferEncoding/Binary /Compression/RLE >>
+ ]
+>>
diff --git a/graphics/sam2p/examples/transparent_tr_pdf.job b/graphics/sam2p/examples/transparent_tr_pdf.job
new file mode 100644
index 0000000000..c9e50bde11
--- /dev/null
+++ b/graphics/sam2p/examples/transparent_tr_pdf.job
@@ -0,0 +1,7 @@
+<<%sam2p-job; by pts@fazekas.hu at Wed Apr 17 13:26:00 CEST 2002
+/InputFile (examples/transparent.gif)
+/OutputFile (test.pdf)
+/Profile [
+ << /FileFormat/PDFB1.2 /SampleFormat/Transparent /TransferEncoding/Binary /Compression/ZIP >>
+ ]
+>>
diff --git a/graphics/sam2p/examples/xv_cant_display_eps.job b/graphics/sam2p/examples/xv_cant_display_eps.job
new file mode 100644
index 0000000000..7dfb50af60
--- /dev/null
+++ b/graphics/sam2p/examples/xv_cant_display_eps.job
@@ -0,0 +1,14 @@
+<<%sam2p-job; by pts@fazekas.hu at Sat Jun 15 11:38:37 CEST 2002
+/InputFile (examples/xv_cant_display.gif)
+/OutputFile (test.eps)
+/Profile [
+ << /FileFormat/PSL2
+ % /SampleFormat/Rgb8
+ % /SampleFormat/Indexed8
+ % /SampleFormat/Gray1
+ /SampleFormat/Transparent2
+ /TransferEncoding/Binary
+ /Compression/RLE
+ % /Transparent null
+ >> ]
+>>
diff --git a/graphics/sam2p/examples/xv_cant_display_eps_gray.job b/graphics/sam2p/examples/xv_cant_display_eps_gray.job
new file mode 100644
index 0000000000..db2448999e
--- /dev/null
+++ b/graphics/sam2p/examples/xv_cant_display_eps_gray.job
@@ -0,0 +1,14 @@
+<<%sam2p-job; by pts@fazekas.hu at Sat Jun 15 15:16:11 CEST 2002
+/InputFile (examples/xv_cant_display.gif)
+/OutputFile (test.eps)
+/Profile [
+ << /FileFormat/PSL2
+ /SampleFormat/Gray1
+ % /SampleFormat/Indexed8
+ % /SampleFormat/Gray1
+ % /SampleFormat/Transparent2
+ /TransferEncoding/Binary
+ /Compression/RLE
+ % /Transparent null
+ >> ]
+>>
diff --git a/graphics/sam2p/examples/xv_cant_display_eps_rgb.job b/graphics/sam2p/examples/xv_cant_display_eps_rgb.job
new file mode 100644
index 0000000000..9ce1c73a5a
--- /dev/null
+++ b/graphics/sam2p/examples/xv_cant_display_eps_rgb.job
@@ -0,0 +1,14 @@
+<<%sam2p-job; by pts@fazekas.hu at Sat Jun 15 11:38:37 CEST 2002
+/InputFile (examples/xv_cant_display.gif)
+/OutputFile (test.eps)
+/Profile [
+ << /FileFormat/PSL2
+ /SampleFormat/Rgb8
+ % /SampleFormat/Indexed8
+ % /SampleFormat/Gray1
+ % /SampleFormat/Transparent2
+ /TransferEncoding/Binary
+ /Compression/RLE
+ % /Transparent null
+ >> ]
+>>
diff --git a/graphics/sam2p/examples/xv_cant_display_gif.job b/graphics/sam2p/examples/xv_cant_display_gif.job
new file mode 100644
index 0000000000..25425484b3
--- /dev/null
+++ b/graphics/sam2p/examples/xv_cant_display_gif.job
@@ -0,0 +1,14 @@
+<<%sam2p-job; by pts@fazekas.hu at Sat Jun 15 12:18:10 CEST 2002
+/InputFile (examples/xv_cant_display.gif)
+/OutputFile (test.gif)
+/Profile [
+ << /FileFormat/GIF89a
+ % /SampleFormat/Rgb8
+ % /SampleFormat/Indexed8
+ % /SampleFormat/Gray1
+ /SampleFormat/Transparent2
+ /TransferEncoding/Binary
+ /Compression/LZW
+ % /Transparent null
+ >> ]
+>>
diff --git a/graphics/sam2p/examples/yellow_gif.job b/graphics/sam2p/examples/yellow_gif.job
new file mode 100644
index 0000000000..ad7a7fa4a6
--- /dev/null
+++ b/graphics/sam2p/examples/yellow_gif.job
@@ -0,0 +1,7 @@
+<<%sam2p-job; by Fri Mar 22 17:36:41 CET 2002
+/InputFile (examples/yellow_large.gif)
+/OutputFile (examples/yellow.gif)
+/Profile [
+ << /FileFormat/GIF89a /SampleFormat/Indexed1 /TransferEncoding/Binary /Compression/LZW >>
+ ]
+>>
diff --git a/graphics/sam2p/examples/yellow_op.job b/graphics/sam2p/examples/yellow_op.job
new file mode 100644
index 0000000000..043860ff14
--- /dev/null
+++ b/graphics/sam2p/examples/yellow_op.job
@@ -0,0 +1,9 @@
+<<%sam2p-job; by Fri Mar 22 17:36:41 CET 2002
+/InputFile (examples/yellow.gif)
+/OutputFile (test.eps)
+/Profile [
+ << /FileFormat/PSL1 /SampleFormat/Opaque /TransferEncoding/Binary /Compression/RLE >>
+ % << /FileFormat/PSL1 /SampleFormat/Transparent /TransferEncoding/Binary /Compression/RLE >>
+ % << /FileFormat/PSL2 /SampleFormat/Indexed2 /TransferEncoding/Binary /Compression/RLE >>
+ ]
+>>
diff --git a/graphics/sam2p/examples/yellow_op_pdf.job b/graphics/sam2p/examples/yellow_op_pdf.job
new file mode 100644
index 0000000000..c127f8fd6d
--- /dev/null
+++ b/graphics/sam2p/examples/yellow_op_pdf.job
@@ -0,0 +1,7 @@
+<<%sam2p-job; by pts@fazekas.hu at Wed Apr 17 13:15:22 CEST 2002
+/InputFile (examples/yellow.gif)
+/OutputFile (test.pdf)
+/Profile [
+ << /FileFormat/PDF1.0 /SampleFormat/Opaque /TransferEncoding/AHx /Compression/RLE >>
+ ]
+>>
diff --git a/graphics/sam2p/examples/yellow_rle_tiff.job b/graphics/sam2p/examples/yellow_rle_tiff.job
new file mode 100644
index 0000000000..24f0fed98d
--- /dev/null
+++ b/graphics/sam2p/examples/yellow_rle_tiff.job
@@ -0,0 +1,11 @@
+<<%sam2p-job; by pts@fazekas.hu at Tue Jun 11 20:36:42 CEST 2002
+/InputFile (examples/yellow.gif)
+/OutputFile (test.tiff)
+/Profile [
+ << /FileFormat/TIFF
+ /SampleFormat/Indexed8
+ % /SampleFormat/Rgb8
+ /TransferEncoding/LSBfirst
+ /Compression/RLE
+ >> ]
+>>
diff --git a/graphics/sam2p/files b/graphics/sam2p/files
new file mode 100644
index 0000000000..8fcafba834
--- /dev/null
+++ b/graphics/sam2p/files
@@ -0,0 +1,235 @@
+main.hpp
+config-vc6.h
+sam2p16.ico
+sam2p32.ico
+vcsam2p.ico
+vcsam2p.cpp
+vcsam2p.dsp
+vcsam2p.h
+vcsam2p.ico
+vcsam2p.rc
+resource.h
+StdAfx.cpp
+StdAfx.h
+hq.pl
+c_lgcc.cpp
+c_lgcc3.cpp
+in_jai.hpp
+jpegdump_main.cpp
+sam2p_main.cpp
+test_main.cpp
+testfax_main.c
+snprintf.h
+snprintf.c
+pts_fax.c
+pts_fax.h
+examples/pts2.pbm
+examples/ptsbanner.gif
+ccdep.pl
+helpere.hpp
+encoder.hpp
+error.hpp
+gensi.hpp
+gensio.hpp
+image.hpp
+gensi.cpp
+Makefile
+rule.hpp
+gensio.cpp
+minips.hpp
+cgif.c
+encoder.cpp
+error.cpp
+image.cpp
+in_bmp.cpp
+in_gif.cpp
+in_jai.cpp
+in_jpeg.cpp
+in_lbm.cpp
+in_pcx.cpp
+in_png.cpp
+in_pnm.cpp
+in_ps.cpp
+pts_defl.c
+pts_defl.h
+in_tga.cpp
+in_tiff.cpp
+in_xpm.cpp
+out_gif.cpp
+crc32.c
+crc32.h
+cgif.h
+cols2.pl
+in_pnm.cpp
+xpmc.h
+in_xpm.cpp
+in_tga.cpp
+minips.cpp
+rule.cpp
+sam2p_main.cpp
+Makehelp.in
+pts_lzw.c
+mkdist.sh
+input-bmp.ci
+input-pnm.ci
+input-tga.ci
+at_bitmap.h
+pts_lzw.h
+files
+pts_defl.c
+pts_defl.h
+aclocal.m4
+configure.in
+config2.h
+config.h.in
+configure
+COPYING
+README
+appliers.cpp
+in_jai.cpp
+out_gif.cpp
+mapping.hpp
+mapping.cpp
+contrib/aprea.ps
+contrib/sam2p.tk
+contrib/sam2ptol.pm
+contrib/template.job
+examples/a_jpg.job
+examples/a_jpg2.job
+examples/a_l1r8r_eps.job
+examples/at-logo_none_xpm.job
+examples/fishg_lzw12_pdf.job
+examples/fishg_lzw2_pdf.job
+examples/fishwbb_l128n_eps.job
+examples/fishwbb_l128r_eps.job
+examples/fishwbb_l12bn_eps.job
+examples/fishwbb_l12br_eps.job
+examples/fishwbb_l12hn_eps.job
+examples/fishwbb_l12hr_eps.job
+examples/fishwbb_l148n_eps.job
+examples/fishwbb_l148r_eps.job
+examples/fishwbb_l14bn_eps.job
+examples/fishwbb_l14br_eps.job
+examples/fishwbb_l14hn_eps.job
+examples/fishwbb_l14hr_eps.job
+examples/fishwbb_l188n_eps.job
+examples/fishwbb_l188r_eps.job
+examples/fishwbb_l18bn_eps.job
+examples/fishwbb_l18br_eps.job
+examples/fishwbb_l18hn_eps.job
+examples/fishwbb_l18hr_eps.job
+examples/fusi2_png.job
+examples/fusi_gif.job
+examples/fusi_l1t8r_eps.job
+examples/fusi_l1tbr_eps.job
+examples/fusi_l1thn_eps.job
+examples/fusi_l1thr_eps.job
+examples/fusi_png.job
+examples/fusi_pnm.job
+examples/fusi_pnm_ascii.job
+examples/fusi_tiff_bad_pdf.job
+examples/fusi_tiff_eps.job
+examples/fusi_tra_eps.job
+examples/fusi_trabin_eps.job
+examples/fusi_tradct_eps.job
+examples/fusi_tradct_jpeg.job
+examples/fusi_trafax_eps.job
+examples/fusi_traijg_eps.job
+examples/fusi_tral1a85_eps.job
+examples/fusiblack_png.job
+examples/fusiwhite_a85none.job
+examples/fusiwhite_binnone.job
+examples/fusiwhite_xwd.job
+examples/j_taska_lzw_eps.job
+examples/j_taska_rle_bmp.job
+examples/mixing_ijg.job
+examples/mixing_pcx_zip.job
+examples/mixing_zip.job
+examples/pts2_l1g8n_eps.job
+examples/pts2_l1g8r_eps.job
+examples/pts2_l1gbr_eps.job
+examples/pts2_pbm.job
+examples/pts2_pbm_pnm.job
+examples/pts2_pbm_zip0.job
+examples/ptsbanner2_ijg_tiff.job
+examples/ptsbanner2_jai.job
+examples/ptsbanner2_jai_jpeg.job
+examples/ptsbanner2_jai_pdf.job
+examples/ptsbanner2_jai_tiff.job
+examples/ptsbanner2_jpeg_tiff.job
+examples/ptsbanner__jpeg.job
+examples/ptsbanner_bbox_pdf.job
+examples/ptsbanner_gif_xwd.job
+examples/ptsbanner_jpeg.job
+examples/ptsbanner_jpg_xwd.job
+examples/ptsbanner_lzw.job
+examples/ptsbanner_lzw_framed.job
+examples/ptsbanner_lzw_margin.job
+examples/ptsbanner_lzw_margin_pdf.job
+examples/ptsbanner_lzw_pdf.job
+examples/ptsbanner_lzw_pdfb.job
+examples/ptsbanner_lzw_ps.job
+examples/ptsbanner_lzw_rot_ps.job
+examples/ptsbanner_lzw_tiff.job
+examples/ptsbanner_none_tiff.job
+examples/ptsbanner_png.job
+examples/ptsbanner_rle_pdf.job
+examples/ptsbanner_rle_tiff.job
+examples/ptsbanner_tralzw.job
+examples/ptsbanner_xpm_zip.job
+examples/ptsbanner_zip.job
+examples/ptsbanner_ziprgb4_tiff.job
+examples/ptsbanner_ziprgb8_tiff.job
+examples/ptsbannerg_jai.job
+examples/ptsbannerg_jai_pdf.job
+examples/ptsbannerg_jai_tiff.job
+examples/ptsbannerg_lzw_tiff.job
+examples/sam2p_fishg.job
+examples/sam2p_fisht.job
+examples/sam2p_fishwbb.job
+examples/sam2p_fishwbg.job
+examples/sam2p_fishwbg_bug.job
+examples/sam2p_fishwww.job
+examples/sam2psho.job
+examples/shot_fax31d_tiff.job
+examples/shot_fax32d_tiff.job
+examples/shot_fax4_tiff.job
+examples/shot_gif.job
+examples/shot_i1.job
+examples/shot_l118r_eps.job
+examples/shot_l11bn_eps.job
+examples/shot_l11br_eps.job
+examples/shot_l11hr_eps.job
+examples/shot_l1m8r_eps.job
+examples/shot_l1mbn_eps.job
+examples/shot_l1mbr_eps.job
+examples/shot_l1mhr_eps.job
+examples/shot_pdfb.job
+examples/shot_pdfb_hex.job
+examples/shot_png.job
+examples/shot_ppm.job
+examples/sziget_al.job
+examples/sziget_al_pdf.job
+examples/sziget_ma.job
+examples/transparent_tr.job
+examples/transparent_tr_pdf.job
+examples/xv_cant_display_eps.job
+examples/xv_cant_display_eps_gray.job
+examples/xv_cant_display_eps_rgb.job
+examples/xv_cant_display_gif.job
+examples/yellow_gif.job
+examples/yellow_op.job
+examples/yellow_op_pdf.job
+examples/yellow_rle_tiff.job
+bts.ttt
+l1zip.psm
+l1lzw.psm
+psmlib.psm
+ps_tiny.c
+debian/README.debian
+debian/changelog
+debian/control
+debian/copyright
+debian/dirs
+debian/rules
+sam2p_pdf_scale.pl
diff --git a/graphics/sam2p/gensi.cpp b/graphics/sam2p/gensi.cpp
new file mode 100644
index 0000000000..b280d9d01c
--- /dev/null
+++ b/graphics/sam2p/gensi.cpp
@@ -0,0 +1,1222 @@
+/*
+ * gensi.cpp
+ * by pts@fazekas.hu at Tue Feb 26 13:28:12 CET 2002
+ */
+
+#ifdef __GNUC__
+#ifndef __clang__
+#pragma implementation
+#endif
+#endif
+
+#include "gensi.hpp"
+#include <string.h> /* strlen() */
+// #include <stdarg.h> /* va_list */
+
+void GenBuffer::iter_char_sub(char const*beg, slen_t len, void *data) {
+ while (len--!=0) (1[(block_char_t**)data][0])(*beg++, 0[(void**)data]);
+}
+
+struct copydata_t {
+ char *to;
+ slen_t cfrom;
+ slen_t clen;
+ slen_t sumlen;
+};
+#define CD static_cast<copydata_t*>(data)
+static void iter_copy_sub(char const*beg, slen_t len, void *data) {
+ slen_t i;
+ CD->sumlen+=len;
+ if (CD->clen==0) return;
+ i=CD->cfrom;
+ if (i>=len) { CD->cfrom-=len; return; }
+ if (i>0) { CD->cfrom=0; beg+=i; len-=i; }
+ if (len>=CD->clen) { memcpy(CD->to, beg, CD->clen); CD->clen=0; return; }
+ memcpy(CD->to, beg, len);
+ CD->to+=len; CD->clen-=len;
+}
+// #include <stdio.h>
+slen_t GenBuffer::copyRange(char *to, slen_t cfrom, slen_t clen) const {
+ if (clen==0) return getLength();
+ copydata_t cd= { to, cfrom, clen, 0 };
+ each_sub(iter_copy_sub, &cd);
+#if 1
+ while (cd.clen--!=0) *cd.to++='\0'; /* padding */
+#else
+ fprintf(stderr,"cd.clen=%d\n", cd.clen);
+ while (cd.clen--!=0) {
+ fprintf(stderr,"padded.\n");
+ *cd.to++='\0'; /* padding */
+ }
+#endif
+ return cd.sumlen;
+}
+
+#if HAVE_LONG_LONG && NEED_LONG_LONG
+# define LONGEXT PTS_CFG_LONGEST
+#else
+# define LONGEXT long
+#endif
+
+/* Imp: ensure reentrace. Maybe vi_write wants to output a number which would
+ * overwrite ours...
+ */
+static char numtmp[sizeof(LONGEXT)*3+2];
+
+bool GenBuffer::toBool(bool &dst) {
+ /* on 1 true yes ja igen igaz be oui vrai: 1tyjibov */
+ /* off 0 false no nein nem hamis ki non -- : 0fnhk */
+ slen_t len=copyRange(numtmp, 0, 3);
+ numtmp[0]|=32; numtmp[1]|=32; numtmp[2]|=32; /* poor man's uppercase */
+ dst=true;
+ if (len==0) return true;
+ if ((numtmp[0]=='o' && numtmp[1]=='f' && numtmp[2]=='f')
+ || numtmp[0]=='0' || numtmp[0]=='f' || numtmp[0]=='n' || numtmp[0]=='h'
+ || numtmp[0]=='k') dst=false;
+ else if ((numtmp[0]<'0' || numtmp[0]>'9') && (numtmp[0]<'a' || numtmp[0]>'z')) return true;
+ return false;
+}
+
+// #include <stdio.h>
+
+bool GenBuffer::toInteger(unsigned long &dst) {
+ /* Imp: several bases (2, 8, 10 and 16), ignore _too_long_ */
+ /* Imp: check for overflow! */
+ slen_t len=copyRange(numtmp, 0, sizeof(numtmp));
+ // fprintf(stderr,"len=%d\n", len);
+ if (len>=sizeof(numtmp)) return true; /* too long */
+ /* ASSERT(numtmp null-terminated) */
+ char *p=numtmp;
+ if (*p=='+') p++;
+ unsigned long i=0;
+ while (1) {
+ // fprintf(stderr,"toInteger'%c'\n", *p);
+ if (*p<'0' || *p>'9') break;
+ i=10*i+(*p-'0');
+ p++;
+ }
+ dst=i;
+ return *p!='\0'; /* a non-digit arrived */
+}
+bool GenBuffer::toInteger(signed long &dst) {
+ /* Imp: several bases (2, 8, 10 and 16), ignore _too_long_ */
+ slen_t len=copyRange(numtmp, 0, sizeof(numtmp));
+ if (len>=sizeof(numtmp)) return true; /* too long */
+ /* ASSERT(numtmp null-terminated) */
+ char *p=numtmp;
+ bool neg=false;
+ if (*p=='+') p++;
+ else if (*p=='-') { neg=true; p++; }
+ unsigned long i=0;
+ while (1) {
+ if (*p<'0' || *p>'9') break;
+ i=10*i+(*p-'0');
+ p++;
+ }
+ dst=neg?-(long)i:i;
+ return *p!='\0'; /* a non-digit arrived */
+}
+#if HAVE_LONG_LONG && NEED_LONG_LONG
+bool GenBuffer::toInteger(unsigned PTS_CFG_LONGEST &dst) {
+ /* Imp: several bases (2, 8, 10 and 16), ignore _too_long_ */
+ slen_t len=copyRange(numtmp, 0, sizeof(numtmp));
+ if (len>=sizeof(numtmp)) return true; /* too long */
+ /* ASSERT(numtmp null-terminated) */
+ char *p=numtmp;
+ if (*p=='+') p++;
+ unsigned PTS_CFG_LONGEST i=0;
+ while (1) {
+ if (*p<'0' || *p>'9') break;
+ i=10*i+(*p-'0');
+ p++;
+ }
+ dst=i;
+ return *p!='\0'; /* a non-digit arrived */
+}
+bool GenBuffer::toInteger(signed PTS_CFG_LONGEST &dst) {
+ /* Imp: several bases (2, 8, 10 and 16), ignore _too_long_ */
+ slen_t len=copyRange(numtmp, 0, sizeof(numtmp));
+ if (len>=sizeof(numtmp)) return true; /* too long */
+ /* ASSERT(numtmp null-terminated) */
+ char *p=numtmp;
+ bool neg=false;
+ if (*p=='+') p++;
+ else if (*p=='-') { neg=true; p++; }
+ unsigned PTS_CFG_LONGEST i=0;
+ while (1) {
+ if (*p<'0' || *p>'9') break;
+ i=10*i+(*p-'0');
+ p++;
+ }
+ dst=neg?-i:i;
+ return *p!='\0'; /* a non-digit arrived */
+}
+#endif
+bool GenBuffer::toCString(char *&dst) {
+ slen_t len=getLength();
+ dst=new char[len+1];
+ copyRange(dst, 0, len+1); /* copies the terminating '\0' automatically. */
+ return false;
+}
+
+int GenBuffer::cmp(GenBuffer const& s2) const {
+ Sub u1, u2;
+ slen_t m;
+ int i;
+ first_sub(u1);
+ s2.first_sub(u2);
+ while (1) {
+ if (u1.len==0 && u2.len==0) return 0; /* (*this) == s2 */
+ else if (u1.len==0) return -1; /* (*this) < s2 */
+ else if (u2.len==0) return 1; /* (*this) > s2 */
+ m=(u1.len<u2.len)?u1.len:u2.len;
+ if (0!=(i=memcmp(u1.beg,u2.beg,m))) return i;
+ if (0==(u1.len-=m)) next_sub(u1); else u1.beg+=m;
+ if (0==(u2.len-=m)) s2.next_sub(u2); else u2.beg+=m;
+ }
+}
+
+int GenBuffer::cmp(char const* u2beg, slen_t u2len) const {
+ Sub u1;
+ slen_t m;
+ int i;
+ first_sub(u1);
+ while (1) {
+ if (u1.len==0 && u2len==0) return 0; /* (*this) == s2 */
+ else if (u1.len==0) return -1; /* (*this) < s2 */
+ else if (u2len ==0) return 1; /* (*this) > s2 */
+ m=(u1.len<u2len)?u1.len:u2len;
+ if (0!=(i=memcmp(u1.beg,u2beg,m))) return i;
+ if (0==(u1.len-=m)) next_sub(u1); else u1.beg+=m;
+ u2len-=m; u2beg+=m;
+ }
+}
+
+int GenBuffer::cmp(char const* u2beg) const {
+ return cmp(u2beg, strlen(u2beg));
+}
+
+/* --- */
+
+bool GenBuffer::Readable::equal_content(GenBuffer::Readable &other) {
+ int i1, i2;
+ while (((i1=vi_getcc())&255) == ((i2=other.vi_getcc())&255) && i1!=-1) ;
+ return i1==i2;
+}
+
+slen_t GenBuffer::Readable::vi_read(char *to_buf, slen_t max) {
+ register char *p=to_buf;
+ char *end=to_buf+max;
+ int c;
+ while (p!=end && 0<=(c=vi_getcc())) *p++=c;
+ return p-to_buf;
+}
+
+int GenBuffer::Readable::readFill(char *to_buf, slen_t max) {
+ slen_t got, sum=0;
+ while (max>0 && 0<(got=vi_read(to_buf, max))) { to_buf+=got; sum+=got; max-=got; }
+ return sum;
+}
+
+/* --- */
+
+void GenBuffer::Writable::iter_write_sub(char const*beg, slen_t len, void *data) {
+ if (len!=0) static_cast<GenBuffer::Writable*>(data)->vi_write(beg, len);
+}
+
+GenBuffer::Writable& GenBuffer::Writable::operator <<(char const*cstr) {
+ assert(cstr!=0);
+ vi_write(cstr, strlen(cstr));
+ return*this;
+}
+
+GenBuffer::Writable& GenBuffer::Writable::operator <<(void const*ptr) {
+ if (ptr==0) vi_write("(null)", 6);
+ else {
+ vi_write("(0d", 3);
+ /* Imp: hexadecimal pointer output */
+ *this << (PTS_INTP_T)ptr;
+ vi_putcc(')');
+ }
+ return*this;
+}
+
+void GenBuffer::Writable::write_num(unsigned long n, unsigned zdigits) {
+ if (zdigits>=sizeof(numtmp)) {
+ memset(numtmp,'0',sizeof(numtmp));
+ while (zdigits>2*sizeof(numtmp)) {
+ vi_write(numtmp, sizeof(numtmp));
+ zdigits-=sizeof(numtmp);
+ }
+ vi_write(numtmp, zdigits-sizeof(numtmp));
+ zdigits=sizeof(numtmp);
+ }
+ char *j=numtmp+sizeof(numtmp), *jend=j-zdigits;
+ while (j!=jend) { *--j='0'+n%10; n/=10; }
+ vi_write(j, zdigits);
+}
+#if HAVE_LONG_LONG && NEED_LONG_LONG
+void GenBuffer::Writable::write_num(unsigned PTS_CFG_LONGEST n, unsigned zdigits) {
+ if (zdigits>=sizeof(numtmp)) {
+ memset(numtmp,'0',sizeof(numtmp));
+ while (zdigits>2*sizeof(numtmp)) {
+ vi_write(numtmp, sizeof(numtmp));
+ zdigits-=sizeof(numtmp);
+ }
+ vi_write(numtmp, zdigits-sizeof(numtmp));
+ zdigits=sizeof(numtmp);
+ }
+ char *j=numtmp+sizeof(numtmp), *jend=j-zdigits;
+ while (j!=jend) { *--j='0'+n%10; n/=10; }
+ vi_write(j, zdigits);
+}
+#endif
+
+void GenBuffer::Writable::write_num(unsigned long n) {
+ char *j=numtmp+sizeof(numtmp);
+ do *--j='0'+n%10; while ((n/=10)!=0);
+ vi_write(j, numtmp+sizeof(numtmp)-j);
+}
+void GenBuffer::Writable::write_num(signed long nn) {
+ register unsigned long n;
+ char *j=numtmp+sizeof(numtmp);
+ if (nn<0) {
+ n=-nn; do *--j='0'+n%10; while ((n/=10)!=0);
+ *--j='-';
+ } else {
+ n=nn; do *--j='0'+n%10; while ((n/=10)!=0);
+ }
+ vi_write(j, numtmp+sizeof(numtmp)-j);
+}
+#if HAVE_LONG_LONG && NEED_LONG_LONG
+void GenBuffer::Writable::write_num(unsigned PTS_CFG_LONGEST n) {
+ char *j=numtmp+sizeof(numtmp);
+ do *--j='0'+n%10; while ((n/=10)!=0);
+ vi_write(j, numtmp+sizeof(numtmp)-j);
+}
+void GenBuffer::Writable::write_num(signed PTS_CFG_LONGEST nn) {
+ register unsigned PTS_CFG_LONGEST n;
+ char *j=numtmp+sizeof(numtmp);
+ if (nn<0) {
+ n=-nn; do *--j='0'+n%10; while ((n/=10)!=0);
+ *--j='-';
+ } else {
+ n=nn;
+ do *--j='0'+n%10; while ((n/=10)!=0);
+ }
+ vi_write(j, numtmp+sizeof(numtmp)-j);
+}
+#endif
+
+GenBuffer::Writable& GenBuffer::Writable::vformat(slen_t n, char const *fmt, va_list ap) {
+ SimBuffer::B buf;
+ buf.vformat(n, fmt, ap);
+ vi_write(buf(), buf.getLength());
+ return*this;
+}
+GenBuffer::Writable& GenBuffer::Writable::vformat(char const *fmt, va_list ap) {
+ SimBuffer::B buf;
+ buf.vformat(fmt, ap);
+ vi_write(buf(), buf.getLength());
+ return*this;
+}
+GenBuffer::Writable& GenBuffer::Writable::format(slen_t n, char const *fmt, ...) {
+ va_list ap;
+ PTS_va_start(ap, fmt);
+ vformat(n, fmt, ap);
+ va_end(ap);
+ return *this;
+}
+GenBuffer::Writable& GenBuffer::Writable::format(char const *fmt, ...) {
+ va_list ap;
+ PTS_va_start(ap, fmt);
+ vformat(fmt, ap);
+ va_end(ap);
+ return *this;
+}
+
+/* --- */
+
+slen_t SimBuffer::Flat::copyRange(char *to, slen_t cfrom, slen_t clen) const {
+ if (cfrom<len) { /* added padding BUGFIX at Fri Mar 7 20:30:07 CET 2003 */
+ slen_t dlen;
+ memcpy(to, beg+cfrom, dlen=cfrom+clen>len ? len-cfrom : clen);
+ to+=dlen;
+ }
+ while (clen--!=0) *to++='\0'; /* padding */
+ return len;
+}
+
+slen_t SimBuffer::Flat::findLast(char const c) const {
+ char const*p;
+ for (p=beg+len;p>=beg;p--) if (*p==c) return p-beg;
+ return len;
+}
+
+slen_t SimBuffer::Flat::findFirst(char const c) const {
+ char const*p, *end=beg+len;
+ for (p=beg;p!=end;p++) if (*p==c) return p-beg;
+ return len;
+}
+
+slen_t SimBuffer::Flat::findFirst(char const* s, slen_t slen) const {
+ if (slen==0) return 0; /* found */
+ if (slen>len) return len; /* not found */
+ char const c=*s;
+ char const*p=beg, *end=beg+len-slen+1;
+ if (slen==1) {
+ for (;p!=end;p++) if (*p==c) return p-beg;
+ } else {
+ for (;p!=end;p++) if (*p==c && 0==memcmp(p,s,slen)) return p-beg;
+ }
+ return len;
+}
+
+int SimBuffer::Flat::cmpFlat(SimBuffer::Flat const& s2) const {
+ return memcmp(beg, s2.beg, len<s2.len?len:s2.len) || (len>s2.len)-(len<s2.len);
+}
+
+int SimBuffer::Flat::cmp(char const* s2beg, slen_t s2len) const {
+ return memcmp(beg, s2beg, len<s2len?len:s2len) || (len>s2len)-(len<s2len);
+}
+
+/* --- */
+
+SimBuffer::Static::Static(char const*cstr) { beg=cstr; len=strlen(cstr); }
+
+/* --- */
+
+void SimBuffer::Appendable::vi_write(char const*str, slen_t slen) {
+ if (slen>0) {
+ char *p=vi_mkend(slen);
+ memcpy(p, str, slen);
+ }
+}
+void SimBuffer::Appendable::prepend(char const*str, slen_t slen) {
+ if (slen>0) {
+ char *p=vi_mkbeg(slen);
+ memcpy(p, str, slen);
+ }
+}
+
+/* inlined.
+void SimBuffer::Appendable::vi_putcc(char c) {
+ vi_mkend(1)[0]=c;
+}*/
+
+/* --- */
+
+SimBuffer::Linked::~Linked() {
+ Node *n;
+ while (first!=0) {
+ if (first->beg!=(char*)(first+1)) delete [] first->beg;
+ n=first->next; delete [] first; first=n;
+ }
+}
+
+slen_t SimBuffer::Linked::getLength() const {
+ slen_t len=0;
+ Node *n=first;
+ while (n!=0) { len+=n->len; n=n->next; }
+ return len;
+}
+
+SimBuffer::Linked::Linked(GenBuffer const& other) {
+ slen_t len=other.getLength();
+ Node *n=static_cast<Node*>(static_cast<void*>(new char[sizeof(Node)+len]));
+ n->beg=(char*)(n+1);
+ other.copyRange(n->beg, 0, len);
+ n->len=len;
+ n->next=0;
+ first=last=n;
+}
+SimBuffer::Linked::Linked(char const*str) {
+ slen_t len=strlen(str);
+ Node *n=static_cast<Node*>(static_cast<void*>(new char[sizeof(Node)+len]));
+ n->beg=(char*)(n+1);
+ memcpy(n->beg, str, len);
+ n->len=len;
+ n->next=0;
+ first=last=n;
+}
+SimBuffer::Linked& SimBuffer::Linked::operator=(GenBuffer const& other) {
+ slen_t len=other.getLength();
+ Node *n=static_cast<Node*>(static_cast<void*>(new char[sizeof(Node)+len]));
+ n->beg=(char*)(n+1);
+ other.copyRange(n->beg, 0, len);
+ n->len=len;
+ n->next=0;
+ first=last=n;
+ return *this;
+}
+SimBuffer::Linked& SimBuffer::Linked::operator=(SimBuffer::Linked const& other) {
+ /* Imp: avoid code repeat */
+ slen_t len=other.getLength();
+ Node *n=static_cast<Node*>(static_cast<void*>(new char[sizeof(Node)+len]));
+ n->beg=(char*)(n+1);
+ other.copyRange(n->beg, 0, len);
+ n->len=len;
+ n->next=0;
+ first=last=n;
+ return *this;
+}
+
+void SimBuffer::Linked::each_sub(GenBuffer::block_sub_t block, void *data) const {
+ Node *n=first;
+ while (n!=0) { block(n->beg, n->len, data); n=n->next; }
+}
+void SimBuffer::Linked::first_sub(Sub &sub) const {
+ if (first!=0) {
+ sub.data=first->next;
+ sub.beg=first->beg;
+ sub.len=first->len;
+ } else sub.len=0;
+}
+void SimBuffer::Linked::next_sub(Sub &sub) const {
+ if (sub.data!=0) {
+ sub.beg=static_cast<Node*>(sub.data)->beg;
+ sub.len=static_cast<Node*>(sub.data)->len;
+ sub.data=static_cast<Node*>(sub.data)->next;
+ } else sub.len=0;
+}
+char *SimBuffer::Linked::vi_mkend(slen_t len) {
+ Node *n=static_cast<Node*>(static_cast<void*>(new char[sizeof(Node)+len]));
+ n->beg=(char*)(n+1);
+ n->len=len;
+ n->next=0;
+ if (last==0) first=last=n;
+ else { last->next=n; last=n; }
+ return n->beg;
+}
+char *SimBuffer::Linked::vi_mkbeg(slen_t len) {
+ Node *n=static_cast<Node*>(static_cast<void*>(new char[sizeof(Node)+len]));
+ n->beg=(char*)(n+1);
+ n->len=len;
+ n->next=first;
+ first=n;
+ if (last==0) last=n;
+ return n->beg;
+}
+
+/* --- */
+
+SimBuffer::Resizable& SimBuffer::Resizable::operator=(GenBuffer const& s2) {
+ vi_grow2(0, s2.getLength()-getLength(), 0, 0);
+ assert(getLength()==s2.getLength());
+
+ Sub u1, u2;
+ slen_t m;
+ first_sub(u1);
+ s2.first_sub(u2);
+ assert(!((u1.len==0) ^ (u2.len==0))); /* s1 and s2 end in the same time */
+ while (u1.len!=0) {
+ m=(u1.len<u2.len)?u1.len:u2.len;
+ memcpy(const_cast<char*>(u1.beg), u2.beg, m);
+ if (0==(u1.len-=m)) next_sub(u1); else u1.beg+=m;
+ if (0==(u2.len-=m)) s2.next_sub(u2); else u2.beg+=m;
+ assert(!((u1.len==0) ^ (u2.len==0))); /* s1 and s2 end in the same time */
+ }
+ return*this;
+}
+
+//void SimBuffer::Resizable::clear() { /* Inlined. */
+// vi_grow2(0, -getLength(), 0, 0);
+//}
+
+void SimBuffer::Resizable::keepLeft(slen_t howmuch) {
+ slen_t len=getLength();
+ vi_grow2(0, len>howmuch?0-len+howmuch:-(slendiff_t)len, 0, 0);
+ /* ^^^ BUGFIX at Tue Jun 11 19:57:03 CEST 2002 */
+}
+void SimBuffer::Resizable::keepRight(slen_t howmuch) {
+ slen_t len=getLength();
+ vi_grow2(len>howmuch?0-len+howmuch:-(slendiff_t)len, 0, 0, 0);
+ /* ^^^ BUGFIX at Tue Jun 11 19:57:03 CEST 2002 */
+}
+void SimBuffer::Resizable::keepSubstr(slen_t from_offset, slen_t slen) {
+ slen_t len=getLength();
+ if (from_offset>=len) vi_grow2(0, -(slendiff_t)len, 0, 0);
+ else if (from_offset+slen>=len) vi_grow2(-(slendiff_t)from_offset, 0, 0, 0);
+ else vi_grow2(-(slendiff_t)from_offset, len-from_offset-slen, 0, 0);
+}
+
+/* --- */
+
+void SimBuffer::B::vi_grow2(slendiff_t left, slendiff_t right, char **lbeg, char **rbeg) {
+ assert(alloced>=len);
+ char *origbeg=const_cast<char*>(beg);
+ if (left<0) { if (len<=(slen_t)-left) len=0; else beg-=left; left=0; } /* ! */
+ if (right<0) { if (len<=(slen_t)-right)len=0; else len+=right;right=0; }
+ /* ^^^ BUGFIX at Tue Jun 11 16:07:56 CEST 2002 */
+ assert(left>=0);
+ assert(right>=0);
+ slen_t newlen=left+right+len;
+ assert(newlen>=len);
+ char *newbeg;
+ assert(alloced>=sizeof(small)/1);
+ if (beg==small) {
+ assert(alloced==sizeof(small));
+ if (newlen>sizeof(small)) {
+ assert(newlen>len);
+ newbeg=new char[alloced=2*newlen];
+ memcpy(newbeg+left, beg, len);
+ beg=newbeg;
+ }
+ } else { /* beg!=small */
+ // assert(len>=alloced/2); /* -- may not always be true, especially not after appending a `long' */
+ if (newlen<alloced/2) { /* shrink */
+ // assert(newlen<=len); /* filled-expectations are true _after_ vi_grow2, not before */
+ if (newlen>sizeof(small)) {
+ newbeg=new char[alloced=newlen];
+ memcpy(newbeg+left, beg, len);
+ } else {
+ memcpy((newbeg=small)+left, beg, len);
+ delete [] origbeg;
+ alloced=sizeof(small);
+ }
+ beg=newbeg;
+ } else if (newlen>alloced) { /* grow */
+ assert(newlen>sizeof(small));
+ assert(newlen>len);
+ newbeg=new char[alloced=2*newlen];
+ memcpy(newbeg+left, beg, len);
+ delete [] origbeg;
+ beg=newbeg;
+ } else if (beg!=origbeg) { /* called with negative `left' @param */
+ assert(left==0);
+ memmove(origbeg, beg, len); /* Slow, may move the whole buffer. */
+ }
+ }
+ // fprintf(stderr, "newlen=%u\n", newlen);
+ len=newlen;
+ if (lbeg) *lbeg=const_cast<char*>(beg);
+ if (rbeg) *rbeg=const_cast<char*>(beg+newlen-right);
+ assert(alloced==sizeof(small) || (alloced>sizeof(small) && len>=alloced/2));
+ assert(alloced>=len);
+}
+
+SimBuffer::B::B(char const* cstr): alloced(sizeof(small)) {
+ beg=small;
+ slen_t len_=strlen(cstr);
+ if (len_>sizeof(small)) { len=0; vi_grow2(0, len_, 0, 0); }
+ else len=len_;
+ assert(len==len_);
+ memcpy(const_cast<char*>(beg), cstr, len);
+}
+
+SimBuffer::B::B(char const* str, slen_t len_): alloced(sizeof(small)) {
+ beg=small;
+ if (len_>sizeof(small)) { len=0; vi_grow2(0, len_, 0, 0); }
+ else len=len_;
+ assert(len==len_);
+ memcpy(const_cast<char*>(beg), str, len);
+}
+
+SimBuffer::B::B(SimBuffer::B const& other): GenBuffer(), SimBuffer::Resizable(), SimBuffer::Flat(), alloced(sizeof(small)) {
+ beg=small;
+ if (other.len>sizeof(small)) { len=0; vi_grow2(0, other.len, 0, 0); }
+ else len=other.len;
+ assert(len==other.len);
+ memcpy(const_cast<char*>(beg), other.beg, len);
+}
+
+SimBuffer::B::B(SimBuffer::Flat const& other): alloced(sizeof(small)) {
+ beg=small;
+ if (other.len>sizeof(small)) { len=0; vi_grow2(0, other.len, 0, 0); }
+ else len=other.len;
+ assert(len==other.len);
+ memcpy(const_cast<char*>(beg), other.beg, len);
+}
+
+SimBuffer::B::B(SimBuffer::Flat const& other,int): alloced(sizeof(small)) {
+ beg=small;
+ if (other.len>=sizeof(small)) { len=0; vi_grow2(0, other.len+1, 0, 0); len--; }
+ else len=other.len;
+ assert(len==other.len);
+ memcpy(const_cast<char*>(beg), other.beg, len);
+ const_cast<char*>(beg)[len]='\0';
+}
+
+SimBuffer::B::B(SimBuffer::Flat const& other, slen_t from_offset, slen_t len_): alloced(sizeof(small)) {
+ /* substr */
+ beg=small;
+ if (from_offset<other.len) {
+ if (from_offset+len_>other.len) len_=other.len-from_offset;
+ if (len_>sizeof(small)) { len=0; vi_grow2(0, len_, 0, 0); }
+ else len=len_;
+ assert(len==len_);
+ memcpy(const_cast<char*>(beg), other.beg+from_offset, len);
+ } else len=0;
+}
+
+SimBuffer::B::B(GenBuffer const& other): alloced(sizeof(small)) {
+ slen_t len_=other.getLength();
+ beg=small;
+ if (len_>sizeof(small)) { len=0; vi_grow2(0, len_, 0, 0); }
+ else len=len_;
+ assert(len==len_);
+ other.copyRange(const_cast<char*>(beg), 0, len_);
+}
+
+/** Constructor: copy (consume) data from a readable stream. */
+SimBuffer::B::B(GenBuffer::Readable &other): alloced(sizeof(small)) {
+ beg=small;
+ len=0;
+#if 000
+ operator <<(other);
+#else
+ B_append(other);
+#endif
+}
+
+SimBuffer::B::B(char const* as,slen_t al, char const* bs,slen_t bl): alloced(sizeof(small)) {
+ slen_t len_=al+bl;
+ beg=small;
+ if (len_>sizeof(small)) { len=0; vi_grow2(0, len_, 0, 0); }
+ else len=len_;
+ assert(len==len_);
+ memcpy(const_cast<char*>(beg), as, al);
+ memcpy(const_cast<char*>(beg)+al, bs, bl);
+}
+
+SimBuffer::B::B(char const* as,slen_t al, char const* bs,slen_t bl,int): alloced(sizeof(small)) {
+ slen_t len_=al+bl;
+ beg=small;
+ if (len_>=sizeof(small)) { len=0; vi_grow2(0, len_+1, 0, 0); len--; }
+ else len=len_;
+ assert(len==len_);
+ memcpy(const_cast<char*>(beg), as, al);
+ memcpy(const_cast<char*>(beg)+al, bs, bl);
+ const_cast<char*>(beg)[al+bl]='\0';
+}
+
+SimBuffer::B::B(GenBuffer const& a, GenBuffer const& b): alloced(sizeof(small)) {
+ slen_t al=a.getLength();
+ slen_t bl=b.getLength();
+ slen_t len_=al+bl;
+ beg=small;
+ if (len_>sizeof(small)) { len=0; vi_grow2(0, len_, 0, 0); }
+ else len=len_;
+ assert(len==len_);
+ a.copyRange(const_cast<char*>(beg), 0, al);
+ b.copyRange(const_cast<char*>(beg)+al, 0, bl);
+}
+
+SimBuffer::B::B(GenBuffer const& a, GenBuffer const& b, GenBuffer const& c): alloced(sizeof(small)) {
+ slen_t al=a.getLength();
+ slen_t bl=b.getLength();
+ slen_t cl=c.getLength();
+ slen_t len_=al+bl;
+ beg=small;
+ if (len_>sizeof(small)) { len=0; vi_grow2(0, len_, 0, 0); }
+ else len=len_;
+ assert(len==len_);
+ a.copyRange(const_cast<char*>(beg), 0, al);
+ b.copyRange(const_cast<char*>(beg)+al, 0, bl);
+ c.copyRange(const_cast<char*>(beg)+al+bl, 0, cl);
+}
+
+SimBuffer::B::B(char const* as,slen_t al, char const* bs,slen_t bl, char const* cs,slen_t cl): alloced(sizeof(small)) {
+ slen_t len_=al+bl+cl;
+ beg=small;
+ if (len_>sizeof(small)) { len=0; vi_grow2(0, len_, 0, 0); }
+ else len=len_;
+ assert(len==len_);
+ memcpy(const_cast<char*>(beg), as, al);
+ memcpy(const_cast<char*>(beg)+al, bs, bl);
+ memcpy(const_cast<char*>(beg)+al+bl, cs, cl);
+}
+
+SimBuffer::B::B(Flat const&b, char const*cs): alloced(sizeof(small)) {
+ slen_t cl=strlen(cs);
+ slen_t len_=b.len+cl;
+ beg=small;
+ if (len_>sizeof(small)) { len=0; vi_grow2(0, len_, 0, 0); }
+ else len=len_;
+ assert(len==len_);
+ memcpy(const_cast<char*>(beg), b.beg, b.len);
+ memcpy(const_cast<char*>(beg)+b.len, cs, cl);
+}
+
+SimBuffer::B::B(char const*as, Flat const&b, char const*cs): alloced(sizeof(small)) {
+ slen_t al=strlen(as);
+ slen_t cl=strlen(cs);
+ slen_t len_=al+b.len+cl;
+ beg=small;
+ if (len_>sizeof(small)) { len=0; vi_grow2(0, len_, 0, 0); }
+ else len=len_;
+ assert(len==len_);
+ memcpy(const_cast<char*>(beg), as, al);
+ memcpy(const_cast<char*>(beg)+al, b.beg, b.len);
+ memcpy(const_cast<char*>(beg)+al+b.len, cs, cl);
+}
+
+/* SimBuffer::B& operator<<(SimBuffer::B& self, GenBuffer::Readable &stream); */
+SimBuffer::B& SimBuffer::B::B_append(GenBuffer::Readable &stream) {
+ assert(alloced>=len);
+ slen_t oldlen, ask;
+ ask=stream.vi_availh();
+ if (ask>0) { oldlen=len; vi_grow2(0, ask+1, 0, 0); len=oldlen; }
+ if (alloced!=len) len+=stream.readFill(const_cast<char*>(beg+len), alloced-len);
+ while (alloced==len) { /* more data to be read */
+ oldlen=len; vi_grow2(0, alloced, 0, 0); len=oldlen;
+ stream.readFill(const_cast<char*>(beg+len), alloced-len);
+ }
+ return *this;
+}
+
+SimBuffer::B& SimBuffer::B::term0() {
+ if (len==alloced) { vi_grow2(0,1,0,0); len--; }
+ const_cast<char*>(beg)[len]='\0';
+ return *this;
+}
+
+void SimBuffer::B::grow_set0_by(slendiff_t lendiff) {
+ char *rbeg;
+ vi_grow2(0, lendiff, 0, &rbeg);
+ if (lendiff>0) memset(rbeg, '\0', lendiff);
+}
+
+char SimBuffer::B::getAt(slen_t idx) {
+ if (idx<len) return beg[idx];
+ /* grow_set0_by(idx+1-len); */
+ char *rbeg;
+ vi_grow2(0, idx-len+1, 0, &rbeg);
+ memset(rbeg, '\0', idx-len+1);
+ return '\0';
+}
+
+SimBuffer::B& SimBuffer::B::operator=(SimBuffer::Flat const& other) {
+ if (&other!=this) {
+ len=0;
+ vi_grow2(0, other.len, 0, 0);
+ memcpy(const_cast<char*>(beg), other.beg, len);
+ }
+ return*this;
+}
+
+SimBuffer::B& SimBuffer::B::operator=(SimBuffer::B const& other) {
+ if (&other!=this) {
+ len=0;
+ vi_grow2(0, other.len, 0, 0);
+ memcpy(const_cast<char*>(beg), other.beg, len);
+ }
+ return*this;
+}
+
+SimBuffer::B& SimBuffer::B::operator=(char const* cstr) {
+ slen_t slen=strlen(cstr);
+ len=0;
+ vi_grow2(0, slen, 0, 0);
+ memcpy(const_cast<char*>(beg), cstr, slen);
+ return*this;
+}
+
+SimBuffer::B SimBuffer::B::substr(slen_t first, slen_t howmuch) const {
+ return SimBuffer::B(*this, first, howmuch);
+}
+SimBuffer::B SimBuffer::B::substr(slen_t first) const {
+ /* Actually, this will probably be shorter than end-begin */
+ return SimBuffer::B(*this, first, len);
+}
+SimBuffer::B SimBuffer::B::right(slen_t howmuch) const {
+ return SimBuffer::B(*this, len<=howmuch?0:len-howmuch, howmuch);
+}
+SimBuffer::B SimBuffer::B::left(slen_t howmuch) const {
+ return SimBuffer::B(*this, 0, howmuch);
+}
+
+#if 0
+void SimBuffer::B::append(char const*s, const slen_t len_) {
+ char *rbeg;
+ vi_grow2(0, len_, 0, &rbeg);
+ memcpy(rbeg, s, len_);
+}
+#endif
+
+SimBuffer::B operator+(const SimBuffer::Flat& s1, const SimBuffer::Flat& s2) {
+ return SimBuffer::B(s1.beg, s1.len, s2.beg, s2.len);
+}
+SimBuffer::B operator+(const char *s1, const SimBuffer::Flat& s2) {
+ return SimBuffer::B(s1, strlen(s1), s2.beg, s2.len);
+}
+SimBuffer::B operator+(const SimBuffer::Flat& s1, const char *s2) {
+ return SimBuffer::B(s1.beg, s1.len, s2, strlen(s2));
+}
+
+SimBuffer::B& SimBuffer::B::operator<<(SimBuffer::Flat const& other) {
+ char *d;
+ vi_grow2(0, other.len, 0, &d);
+ memcpy(d,other.beg,other.len);
+ return*this;
+}
+
+SimBuffer::B& SimBuffer::B::operator<<(char c) {
+ if (len==alloced) { vi_grow2(0, 1, 0, 0); const_cast<char*>(beg)[len-1]=c; }
+ else const_cast<char*>(beg)[len++]=c;
+ return*this;
+}
+SimBuffer::B& SimBuffer::B::operator<<(char const *s) {
+ char *d;
+ slen_t slen=strlen(s);
+ vi_grow2(0, slen, 0, &d);
+ memcpy(d,s,slen);
+ return*this;
+}
+void SimBuffer::B::vi_write(char const*str, slen_t slen) {
+ if (slen>0) {
+ char *p; vi_grow2(0, slen, 0, &p);
+ memcpy(p, str, slen);
+ }
+}
+
+#define USGE(a,b) ((unsigned char)(a))>=((unsigned char)(b))
+static inline bool is_path(char const c) {
+ return c=='-' || c=='.' || c=='_' || c=='/'
+ || USGE('z'-'a',c-'a')
+ || USGE('Z'-'A',c-'A')
+ || USGE('9'-'0',c-'0');
+}
+static inline bool is_safe_c(char const c) {
+ return c!='\\' && c!='\'' && c!='\"' && USGE('~'-' ',c-' ');
+}
+static inline bool is_safe_ps(char const c) {
+ return c!='\\' && c!='(' && c!=')' && USGE('~'-' ',c-' ');
+}
+
+SimBuffer::B& SimBuffer::B::appendDump(const char c, bool dq) {
+ char t[7]; register char *p=t;
+ if (dq) *p++='\'';
+ if (is_path(c)) {
+ *p++=c;
+ } else {
+ *p++='\\';
+ *p++=('0'+((c>>6)&3));
+ *p++=('0'+((c>>3)&7));
+ *p++=('0'+(c&7));
+ }
+ if (dq) *p++='\'';
+ vi_write(t, p-t);
+ return*this;
+}
+
+
+SimBuffer::B& SimBuffer::B::appendDump(const SimBuffer::Flat &other, bool dq) {
+ slen_t rlen=dq?2:0;
+ register char c; register char const*p;
+ char const *pend; char *dst;
+ for (p=other.beg,pend=p+other.len; p!=pend; p++) rlen+=is_path(*p)?1:4;
+ vi_grow2(0, rlen, 0, &dst);
+ if (dq) *dst++='"';
+ for (p=other.beg,pend=p+other.len; p!=pend; p++) {
+ if (is_path(c=*p)) {
+ *dst++=c;
+ } else {
+ *dst++='\\';
+ *dst++=('0'+((c>>6)&3));
+ *dst++=('0'+((c>>3)&7));
+ *dst++=('0'+(c&7));
+ }
+ }
+ if (dq) *dst++='"';
+ assert(dst==end_());
+ return*this;
+}
+
+SimBuffer::B& SimBuffer::B::appendNpmq(const SimBuffer::Flat &other, bool dq) {
+ slen_t rlen=dq?2:0;
+ register char c; register char const*p;
+ char const *pend; char *dst;
+ for (p=other.beg,pend=p+other.len; p!=pend; p++) rlen+=is_path(*p)?1:2;
+ vi_grow2(0, rlen, 0, &dst);
+ if (dq) *dst++='"';
+ for (p=other.beg,pend=p+other.len; p!=pend; p++) {
+ if (is_path(c=*p)) {
+ *dst++=c;
+ } else {
+ *dst++='\\';
+ *dst++=c;
+ }
+ }
+ if (dq) *dst++='"';
+ assert(dst==end_());
+ return*this;
+}
+
+SimBuffer::B& SimBuffer::B::appendDumpC (const SimBuffer::Flat &other, bool dq) {
+ slen_t rlen=dq?2:0;
+ register char c; register char const*p;
+ char const *pend; char *dst;
+ for (p=other.beg,pend=p+other.len; p!=pend; p++) rlen+=is_safe_c(*p)?1:4;
+ vi_grow2(0, rlen, 0, &dst);
+ if (dq) *dst++='"';
+ for (p=other.beg,pend=p+other.len; p!=pend; p++) {
+ if (is_safe_c(c=*p)) {
+ *dst++=c;
+ } else {
+ *dst++='\\';
+ *dst++=('0'+((c>>6)&3));
+ *dst++=('0'+((c>>3)&7));
+ *dst++=('0'+(c&7));
+ }
+ }
+ if (dq) *dst++='"';
+ assert(dst==end_());
+ return*this;
+}
+
+SimBuffer::B& SimBuffer::B::appendFnq(const SimBuffer::Flat &other, bool preminus) {
+ slen_t rlen=0;
+ register char c; register char const*p;
+ char const *pend; char *dst;
+ if (OS_COTY==COTY_WINNT || OS_COTY==COTY_WIN9X) {
+ for (p=other.beg,pend=p+other.len; p!=pend; p++) {
+ if ('\0'==(c=*p) || c=='"') break;
+ rlen++;
+ }
+ if (preminus && rlen!=0 && other.beg[0]=='-') rlen+=2; /* .\ */
+ vi_grow2(0, rlen+2, 0, &dst);
+ *dst++='"'; /* Dat: "ab"c" ""def" is perfectly legal and parses to: `abc def' */
+ p=other.beg;
+ if (preminus && other.beg[0]=='-') { *dst++='.'; *dst++='\\'; }
+ for (p=other.beg,pend=p+other.len; p!=pend; p++) {
+ if ('\0'==(c=*p) || c=='"') break;
+ *dst++=c;
+ }
+ *dst++='"';
+ } else { /* Everything else is treated as UNIX */
+ for (p=other.beg,pend=p+other.len; p!=pend; p++) {
+ if ('\0'==(c=*p)) break;
+ rlen+=is_path(c)?1: c=='\n'?3:2;
+ }
+ if (preminus && rlen!=0 && other.beg[0]=='-') rlen+=2; /* ./ */
+ vi_grow2(0, rlen, 0, &dst);
+ if (preminus && other.beg[0]=='-') { *dst++='.'; *dst++='/'; }
+ for (p=other.beg,pend=p+other.len; p!=pend; p++) {
+ if ('\0'==(c=*p)) break;
+ if (is_path(c)) *dst++=c;
+ else if (c=='\n') { *dst++='"'; *dst++='\n'; *dst++='"'; }
+ else { *dst++='\\'; *dst++=c; }
+ }
+ } /* IF OS_COTY... */
+ assert(dst==end_());
+ return*this;
+}
+
+SimBuffer::B& SimBuffer::B::appendDumpPS (const SimBuffer::Flat &other, bool dq) {
+ slen_t rlen=dq?2:0;
+ register char c; register char const*p;
+ char const *pend;
+ for (p=other.beg,pend=p+other.len; p!=pend; p++) rlen+=is_safe_ps(*p)?1:4;
+ char *dst; vi_grow2(0, rlen, 0, &dst);
+ if (dq) *dst++='(';
+ for (p=other.beg,pend=p+other.len; p!=pend; p++) {
+ if (is_safe_ps(c=*p)) {
+ *dst++=c;
+ } else {
+ *dst++='\\';
+ *dst++=('0'+((c>>6)&3));
+ *dst++=('0'+((c>>3)&7));
+ *dst++=('0'+(c&7));
+ }
+ }
+ if (dq) *dst++=')';
+ assert(dst==end_());
+ return*this;
+}
+
+SimBuffer::B& SimBuffer::B::appendHppq(const SimBuffer::Flat &other) {
+ vi_grow2(0, other.len, 0, 0);
+ char *pend=const_cast<char*>(beg)+len;
+ register char c, *p=pend-other.len;
+ memcpy(p, other.beg, other.len);
+ for (;p!=pend;pend++) {
+ c=*p;
+ *p++=(
+ (c>='a' && c<='z') ? (char)(c-'a'+'A') :
+ (c>='A' && c<='Z') ? c :
+ '_'
+ );
+ }
+ return *this;
+}
+
+SimBuffer::B& SimBuffer::B::appendUnslash(const SimBuffer::Flat &other, int iniq) {
+ slen_t rlen=0;
+ slen_t left=other.len;
+ register char c; register char const*p=other.beg;
+ if (iniq<=256) {
+ if (left<2 || *p!=iniq || p[left-1]!=iniq) return*this;
+ /* ^^^ return empty string */
+ p++; left-=2;
+ }
+ while (0!=left) { /* Calculate lengths */
+ c=*p++;
+ if (c!='\\' || left==1) { rlen++; left--; continue; }
+ c=*p++;
+ if (c>='0' && c<='7') {
+ rlen++;
+ if (left>=3 && p[0]>='0' && p[0]<='7') {
+ if (left>=4 && p[1]>='0' && p[1]<='7') { p+=2; left-=4; }
+ else { p+=1; left-=3; }
+ } else left-=2;
+ } else if ((c=='x' || c=='X') && left>=3 && 16!=(hexc2n(p[0]))) {
+ rlen++;
+ if (left>=4 && 16!=(hexc2n(p[1]))) { p+=2; left-=4; }
+ else { p+=1; left-=2; }
+ } else if ((c=='c' || c=='C') && left>=4 && (p[0]=='-' || p[0]=='[')) {
+ rlen++; left-=4; p+=2;
+ } else if (c=='l' && left>=3) {
+ rlen++; left-=3; p++;
+ } else if (c=='u' && left>=3) {
+ rlen++; left-=3; p++;
+ } else if (c=='\n') {
+ left-=2;
+ } else { /* backslash is used for escaping a single char */
+ rlen++; left-=2;
+ }
+ }
+
+ char *dst; vi_grow2(0, rlen, 0, &dst);
+ unsigned tmp1, tmp2;
+ left=other.len; p=other.beg;
+ if (iniq<=256) {
+ assert(!(left<2 || *p!=iniq || p[left-1]!=iniq));
+ p++; left-=2;
+ }
+ while (0!=left) {
+ c=*p++;
+ if (c!='\\' || left==1) { *dst++=(c); left--; continue; }
+ c=*p++;
+ if (c>='0' && c<='7') {
+ if (left>=3 && p[0]>='0' && p[0]<='7') {
+ if (left>=4 && p[1]>='0' && p[1]<='7') {
+ *dst++=((char)((c<<6)+(p[0]<<3)+p[1]-'0'*73));
+ p+=2; left-=4;
+ } else {
+ *dst++=((char)((c<<3)+p[0]-'0'*9));
+ p+=1; left-=3;
+ }
+ } else {
+ *dst++=((char)(c-'0'));
+ left-=2;
+ }
+ } else if ((c=='x' || c=='X') && left>=3 && 16!=(tmp1=hexc2n(p[0]))) {
+ if (left>=4 && 16!=(tmp2=hexc2n(p[1]))) {
+ *dst++=((char)((tmp1<<4)+tmp2));
+ p+=2; left-=4;
+ } else {
+ *dst++=((char)tmp1);
+ p+=1; left-=2;
+ }
+ } else if ((c=='c' || c=='C') && left>=4 && (p[0]=='-' || p[0]=='[')) {
+ *dst++=((char)(p[1]>='a' && p[1]<='z' ? (p[1]+'A'-'a')^64 : p[1]^64));
+ left-=4; p+=2;
+ } else if (c=='l' && left>=3) {
+ *dst++=((char)(p[0]>='A' && p[0]<='Z' ? p[0]+'a'-'A' : p[0]));
+ left-=3; p++;
+ } else if (c=='u' && left>=3) {
+ *dst++=((char)(p[0]>='a' && p[0]<='z' ? p[0]+'A'-'a' : p[0]));
+ left-=3; p++;
+ } else if (c=='\n') {
+ left-=2;
+ } else { /* backslash is used for escaping a single char */
+ if (c=='a') c=007; // \x07 (alarm bell)
+ else if (c=='b') c=010; // \x08 (backspace) (_not_ alarm bell)
+ else if (c=='e') c=033; // \x1B (escape)
+ else if (c=='f') c=014; // \x0C (form feed)
+ else if (c=='n') c=012; // \x0A (newline, line feed)
+ else if (c=='r') c=015; // \x0D (carriage return)
+ else if (c=='t') c=011; // \x09 (horizontal tab)
+ else if (c=='v') c=013; // \x0B (vertical tab)
+ *dst++=(c); left-=2;
+ // if (0!=left--) { *dst++=(*p++); left--; } /* already escaped 1 */
+ }
+ }
+ return*this;
+}
+
+void SimBuffer::B::space_pad_cpy(char *dst, char const*src, slen_t pad) {
+ while (pad!=0 && src[0]!='\0') { *dst++=*src++; pad--; }
+ while (pad--!=0) *dst++=' ';
+}
+
+// #include <stdio.h>
+
+char *SimBuffer::B::substr_grow(slen_t first, slen_t oldmuch, slen_t newmuch) {
+ slen_t idx=first;
+ if (first<len) {
+ if (first+oldmuch>len) oldmuch=len-first;
+ if (newmuch<oldmuch) { first+=newmuch; oldmuch-=newmuch; newmuch=0; }
+ else if (newmuch>oldmuch) { first+=oldmuch; newmuch-=oldmuch; oldmuch=0; }
+ else return const_cast<char*>(beg)+first;
+ } else {
+ len=first=idx=oldmuch=0;
+ if (newmuch==0) { vi_grow2(0,0,0,0); return const_cast<char*>(beg); }
+ }
+ // fprintf(stderr, "newmuch=%u oldmuch=%u len=%u\n", newmuch, oldmuch, len);
+ if (newmuch>0) {
+ vi_grow2(0,newmuch,0,0);
+ char *p=const_cast<char*>(beg)+first; /* after vi_grow2() */
+ memmove(p+newmuch, p, len-first-newmuch);
+ } else if (oldmuch>0) {
+ char *p=const_cast<char*>(beg)+first; /* before vi_grow2() */
+ memmove(p, p+oldmuch, len-first-oldmuch);
+ vi_grow2(0,-(slendiff_t)oldmuch,0,0);
+ } else assert(0);
+ // fprintf(stderr, "len=%u oldmuch=%u\n", len, oldmuch);
+ return const_cast<char*>(beg)+idx;
+}
+
+/* --- Tue Jul 2 10:47:14 CEST 2002 */
+
+void GenBuffer::tolower_memcpy(char *dst, char const*s, slen_t slen) {
+ while (slen--!=0) *dst++=USGE('Z'-'A',*s-'A') ? *s+++'a'-'A' : *s++;
+}
+void GenBuffer::toupper_memcpy(char *dst, char const*s, slen_t slen) {
+ while (slen--!=0) *dst++=USGE('z'-'a',*s-'a') ? *s+++'A'-'a' : *s++;
+}
+
+int GenBuffer::nocase_memcmp(char const*a, char const *s, slen_t slen) {
+ int i;
+ while (slen--!=0) {
+ i=(USGE('Z'-'A',*a-'A') ? *a+++'a'-'A' : *a++)
+ -(USGE('Z'-'A',*s-'A') ? *s+++'a'-'A' : *s++);
+ if (i>0) return 1;
+ if (i<0) return -1;
+ }
+ return 0;
+}
+int GenBuffer::nocase_strcmp(char const*a, char const*b) {
+ slen_t alen=strlen(a), blen=strlen(b), min=alen<blen?alen:blen;
+ int ret=nocase_memcmp(a, b, min);
+ return ret!=0 || alen==blen ? ret : alen<blen ? -1 : 1;
+}
+
+bool GenBuffer::parseBool(char const *s, slen_t slen) {
+ if (slen==0) return true;
+ char c=s[0];
+ if ((slen==2 && (c=='o' || c=='O') && (s[1]=='n' || s[1]=='N'))
+ || (slen==3 && (c=='o' || c=='O') && (s[1]=='u' || s[1]=='U'))
+ ) return true;
+ /* on true yes ja igen oui enable 1 true vrai? right sure allowed
+ * off false no nein nem non disable 0 false faux? wrong nope disallowed
+ */
+ return c!='f' && c!='n' && c!='d' && c!='w' && c!='0'
+ && c!='F' && c!='N' && c!='D' && c!='W';
+}
+
+bool GenBuffer::strbegins(char const*a, char const *with) {
+ while (*with!='\0') if (*a++!=*with++) return false;
+ return true;
+}
+
+bool GenBuffer::nocase_strbegins(char const*a, char const *with) {
+ while (*with!='\0')
+ if ((USGE('Z'-'A',*a-'A') ? *a+++'a'-'A' : *a++)
+ !=(USGE('Z'-'A',*with-'A') ? *with+++'a'-'A' : *with++)
+ ) return false;
+ return true;
+}
+
+/* __END__ */
diff --git a/graphics/sam2p/gensi.hpp b/graphics/sam2p/gensi.hpp
new file mode 100644
index 0000000000..d4751cbdbe
--- /dev/null
+++ b/graphics/sam2p/gensi.hpp
@@ -0,0 +1,726 @@
+/* gensi.hpp -- generic char buffer and I/O facilities
+ * by pts@fazekas.hu at Sun Feb 24 15:56:02 CET 2002
+ */
+/* Imp: get rid of gensio.o (Buffer::Writable::printf requires B...) */
+
+#ifdef __GNUC__
+#ifndef __clang__
+#pragma interface
+#endif
+#endif
+
+#ifndef GENSI_HPP
+#define GENSI_HPP 1
+
+#include "config2.h"
+#include <stdarg.h> /* va_list */
+
+#if 'a'!=97 || '!'!=33
+#error You need an ASCII system to compile this.
+#endif
+
+/** A very generic, abstract char (pure 8-bit octet) buffer class. This class
+ * doesn't have any attributes.
+ */
+class GenBuffer {
+ public:
+ virtual inline ~GenBuffer() {}
+ static inline unsigned hexc2n(char c) {
+ return ((unsigned char)(c-'0')<=(unsigned char)('9'-'0')) ? c-'0'
+ : ((unsigned char)(c-'A')<=(unsigned char)('F'-'A')) ? c-'A'+10
+ : ((unsigned char)(c-'a')<=(unsigned char)('f'-'a')) ? c-'a'+10
+ : 16;
+ }
+ /** English ASCII letters [a-zA-Z] */
+ static void tolower_memcpy(char *dst, char const*s, slen_t slen);
+ /** English ASCII letters [a-zA-Z] */
+ static void toupper_memcpy(char *dst, char const*s, slen_t slen);
+ /** All letters treated as lower case. @return -1, 0 or 1 */
+ static int nocase_memcmp(char const*a, char const *s, slen_t slen);
+ static int nocase_strcmp(char const*a, char const *b);
+ /** All letters treated as lower case. @return -1, 0 or 1 */
+ static bool nocase_strbegins(char const*a, char const *with);
+ static bool strbegins(char const*a, char const *with);
+ static bool parseBool(char const *s, slen_t slen);
+
+ /* Imp: convert usage of each_sub to first_sub+next_sub */
+ typedef void (*block_sub_t)(char const*beg, slen_t len, void *data);
+ typedef void (*block_char_t)(char c, void *data);
+ struct Sub {
+ char const*beg;
+ slen_t len;
+ void *data, *data2;
+ };
+ /** Writable. */
+ struct SubW {
+ char *beg;
+ slen_t len;
+ void *data, *data2;
+ };
+ virtual slen_t getLength() const =0;
+ /** Iterates through each subrange of (this), and calls param `block'
+ * for each range. Must call block with positive `len's, and -- as a final
+ * call -- with len==0.
+ * @param data arbitrary data, to be passed to param `block'
+ */
+ virtual void each_sub(block_sub_t block, void *data) const =0;
+ /** Iterates through each character of (this), and calls param `block'
+ * for each char. Implemented by calling (this).each_sub
+ */
+ /** Produces sub.len==0 if empty. */
+ virtual void first_sub(Sub &sub) const =0;
+ /** Produces sub.len==0 if no more subs.
+ * @param sub fields `beg' and `len' are assumed to contain garbage (!)
+ * before invocation. Only `data' and `data2' can be relied upon.
+ */
+ virtual void next_sub(Sub &sub) const =0;
+ inline void each_char(block_char_t block, void *data) const {
+ void *t[2]= { data, (void*)(long)block };
+ each_sub(iter_char_sub, (void*)t);
+ }
+ inline bool isEmpty() const { return getLength()==0; }
+ /** @return true iff not empty */
+ inline virtual operator void*() const { return (void*)(getLength()!=0); }
+ /** @return true iff not empty; pacify VC6.0 */
+ // inline virtual operator bool() const { return (void*)(getLength()!=0); }
+ // inline virtual operator bool() const { return getLength()!=0; }
+ /** @return true iff empty */
+ inline virtual bool operator!() const { return getLength()==0; }
+ /** @return getLength() */
+ virtual slen_t copyRange(char *to, slen_t cfrom, slen_t clen) const;
+ /** @return true on conversion error */
+ bool toBool(bool &dst);
+ /** @return true on conversion error (overflow etc.) */
+ bool toInteger(unsigned long &dst);
+ /** @return true on conversion error (overflow etc.) */
+ bool toInteger(signed long &dst);
+ #if HAVE_LONG_LONG && NEED_LONG_LONG
+ /** @return true on conversion error (overflow etc.) */
+ bool toInteger(unsigned PTS_CFG_LONGEST &dst);
+ /** @return true on conversion error (overflow etc.) */
+ bool toInteger(signed PTS_CFG_LONGEST &dst);
+ #endif
+ /* Zero-initialize to pacify gcc-4.2.1 by giving initial value */
+ inline bool toInteger(unsigned short &i) { unsigned long l = 0; bool b=toInteger(l); i=l; return b; }
+ inline bool toInteger( signed short &i) { signed long l = 0; bool b=toInteger(l); i=l; return b; }
+ inline bool toInteger(unsigned int &i) { unsigned long l = 0; bool b=toInteger(l); i=l; return b; }
+ inline bool toInteger( signed int &i) { signed long l = 0; bool b=toInteger(l); i=l; return b; }
+ /** Allocates a fresh new, null-terminated string. @return true */
+ bool toCString(char *&dst);
+ /** @return negative iff (this)<s2, positive iff (this)>s2 */
+ virtual int cmp(GenBuffer const& s2) const;
+ /** @return negative iff (this)<s2, positive iff (this)>s2 */
+ virtual int cmp(char const* s2, slen_t len) const;
+ /** Null-terminated, calls cmp(char const* s2, slen_t len). */
+ int cmp(char const* s2) const;
+ friend bool operator==(const GenBuffer& s1, const GenBuffer& s2);
+ friend bool operator==(const char *s1, const GenBuffer& s2);
+ friend bool operator==(const GenBuffer& s1, const char *s2);
+ /* vvv G++ 2.91 doesn't autodetect these 15 operators :-( */
+ friend bool operator!=(const GenBuffer& s1, const GenBuffer& s2);
+ friend bool operator!=(const char *s1, const GenBuffer& s2);
+ friend bool operator!=(const GenBuffer& s1, const char *s2);
+ friend bool operator<=(const GenBuffer& s1, const GenBuffer& s2);
+ friend bool operator<=(const char *s1, const GenBuffer& s2);
+ friend bool operator<=(const GenBuffer& s1, const char *s2);
+ friend bool operator<(const GenBuffer& s1, const GenBuffer& s2);
+ friend bool operator<(const char *s1, const GenBuffer& s2);
+ friend bool operator<(const GenBuffer& s1, const char *s2);
+ friend bool operator>=(const GenBuffer& s1, const GenBuffer& s2);
+ friend bool operator>=(const char *s1, const GenBuffer& s2);
+ friend bool operator>=(const GenBuffer& s1, const char *s2);
+ friend bool operator>(const GenBuffer& s1, const GenBuffer& s2);
+ friend bool operator>(const char *s1, const GenBuffer& s2);
+ friend bool operator>(const GenBuffer& s1, const char *s2);
+
+ /** A very generic, abstract char (pure 8-bit octet) output (encoding
+ * stream, filter) class. Writing always succeeds, all data gets written.
+ * No attributes.
+ */
+ class Writable {
+ public:
+ virtual void vi_write(char const*, slen_t) =0;
+ virtual void vi_putcc(char) =0;
+ inline Writable &operator <<(GenBuffer const& b) {
+ b.each_sub(iter_write_sub, this);
+ return*this;
+ }
+ inline Writable &operator <<(char c) { vi_putcc(c); return*this; }
+ /** Outputs a null-terminated, C string. Not `inline' because the use
+ * of strlen().
+ */
+ virtual inline ~Writable() {}
+ Writable& operator <<(char const*);
+ Writable& operator <<(void const*);
+ inline Writable& operator <<( signed short n) { write_num((signed long)n); return*this; }
+ inline Writable& operator <<( signed int n) { write_num((signed long)n); return*this; }
+ inline Writable& operator <<( signed long n) { write_num(n); return*this; }
+ inline Writable& operator <<(unsigned short n) { write_num((unsigned long)n); return*this; }
+ inline Writable& operator <<(unsigned int n) { write_num((unsigned long)n); return*this; }
+ inline Writable& operator <<(unsigned long n) { write_num(n); return*this; }
+ #if HAVE_LONG_LONG && NEED_LONG_LONG
+ inline Writable &operator <<(signed long long n) { write_num(n); return*this; }
+ inline Writable &operator <<(unsigned long long n) { write_num(n); return*this; }
+ #endif
+ inline Writable& operator <<(bool b) {
+ if (b) vi_write("true", 4);
+ else vi_write("false", 5);
+ return*this;
+ }
+
+ /** appends at most `n' chars; uses SimBuffer::B::vformat as temp */
+ virtual Writable& vformat(slen_t n, char const *fmt, va_list ap);
+ /** appends; uses SimBuffer::B::vformat as temp */
+ virtual Writable& vformat(char const *fmt, va_list ap);
+ /** appends; calls vformat */
+ Writable& format(slen_t n, char const *fmt, ...);
+ /** appends; calls vformat */
+ Writable& format(char const *fmt, ...);
+
+ void write_num(signed long n);
+ void write_num(unsigned long n);
+ #if HAVE_LONG_LONG && NEED_LONG_LONG
+ void write_num(signed PTS_CFG_LONGEST n);
+ void write_num(unsigned PTS_CFG_LONGEST n);
+ #endif
+ /** @param zdigits specifies the exact number of digits to be appended.
+ * Zeroes are prepended if necessary.
+ */
+ void write_num(unsigned long n, unsigned zdigits);
+ #if HAVE_LONG_LONG && NEED_LONG_LONG
+ void write_num(unsigned PTS_CFG_LONGEST n, unsigned zdigits);
+ #endif
+ protected:
+ static void iter_write_sub(char const*beg, slen_t len, void *data);
+ };
+
+ /** Interface for a stream of characters. Similar to ISimplyiChar in
+ * CHsplit. No attributes.
+ */
+ class Readable {
+ public:
+ /** @return -1 on EOF/error, a char (0..255) otherwise.
+ */
+ virtual int vi_getcc() =0;
+ /** Does a single blocking read. Default functionality: calls vi_getcc()
+ * repeatedly.
+ * @return 0 on EOF/error, positive otherwise: number of characters
+ * successfully read.
+ */
+ virtual slen_t vi_read(char *to_buf, slen_t max);
+ /** Does multiple blocking reads, tries to fill `to_buf'. Calls vi_read()
+ * repeatedly.
+ */
+ int readFill(char *to_buf, slen_t max);
+ /** Returns a number not larger than the bytes available _altogether_
+ * from this stream. The default implementation returns 0, which is
+ * always safe. For regular files, the method should return the size
+ * of the file (unless the size is too large to be represented as an
+ * slen_t), for pipes and sockets, the method should return 0.
+ */
+ inline virtual slen_t vi_availh() { return 0; }
+ inline bool equal_content(Readable &other);
+ /** Does nothing or rewinds the stream to the beginning, so it can be
+ * read again. The default implementation does nothing.
+ */
+ inline virtual void vi_rewind() {}
+ virtual inline ~Readable() {}
+ };
+
+ protected:
+ static void iter_char_sub(char const*beg, slen_t len, void *data);
+};
+
+// vvv Doesn't work in gcc 2.95 since we have abstract methods :-(. Must be
+// declared inside class { ... };
+///GenBuffer::Writable &operator <<(GenBuffer::Writable a, GenBuffer b);
+
+/** Collection of some simplistic GenBuffer implementations. */
+class SimBuffer {
+ public:
+ class B;
+ /** A flat buffer, i.e occupying consecutive bytes in memory. This class is
+ * useless by itself since memory management (allocation and deletion of the
+ * memory area) isn't implemented. Example of virtual inheritance: needed
+ * because of SimBuffer::B.
+ */
+ class Flat: virtual public GenBuffer {
+ protected:
+ friend class /*SimBuffer::*/B; /* can read `beg' and `len' */
+ const char *beg;
+ slen_t len;
+ public:
+ inline virtual slen_t getLength() const { return len; }
+ virtual void each_sub(block_sub_t block, void *data) const {
+ if (len!=0) block(beg,len,data);
+ block(0,0,data);
+ }
+ inline virtual void first_sub(Sub &sub) const { sub.beg=beg; sub.len=len; };
+ inline virtual void next_sub(Sub &sub) const { sub.len=0; }
+ inline char const*getCString() const { return beg; }
+ inline char const*operator()() const { return beg; }
+ inline char const*begin_() const { return beg; }
+ inline char const*end_() const { return beg+len; }
+ // inline operator char const*() const { return beg; } /* would kill void* */
+ /** @param idx would cause overload conflict if declared len_t. No range check */
+ inline char const&operator[](slendiff_t idx) const { return beg[idx]; }
+ /** @return true iff not empty */
+ inline virtual operator void*() const { return (void*)(len!=0); }
+ // inline operator bool() const { return len!=0; }
+ /** @return true iff empty */
+ inline virtual bool operator!() const { return len==0; }
+ /**
+ * This is deliberatly not an `operator char'
+ * to avoid the ambiguity of implicit auto-conversion.
+ * @return 1st char or 0.
+ */
+ inline void toChar(char &ret) const {
+ ret= len==0 ? 0 : *beg;
+ }
+ /** Overridden. */
+ virtual slen_t copyRange(char *to, slen_t cfrom, slen_t clen) const;
+ /** @return getLength() if not found, offset otherwise */
+ slen_t findLast(char const c) const;
+ /** @return getLength() if not found, offset otherwise */
+ slen_t findFirst(char const c) const;
+ /** @return getLength() if not found, offset otherwise */
+ slen_t findFirst(char const* s, slen_t slen) const;
+ int cmpFlat(Flat const& s2) const;
+ virtual int cmp(char const* s2, slen_t len) const;
+ /** @param fallback default: '\0'
+ * @return if idx is too large: `fallback', otherwise: the asked char
+ */
+ virtual inline char getAt0(slen_t idx, char fallback='\0') {
+ return idx>=len ? fallback : beg[idx];
+ }
+ /* Dat: pacify VC6.0: use of undefined type 'SimBuffer' */
+ friend /*SimBuffer::*/B operator+(const /*SimBuffer::*/Flat& s1, const /*SimBuffer::*/Flat& s2);
+ friend /*SimBuffer::*/B operator+(const char *s1, const /*SimBuffer::*/Flat& s2);
+ friend /*SimBuffer::*/B operator+(const /*SimBuffer::*/Flat& s1, const char *s2);
+ };
+
+ /** A statically allocated, read-only char buffer, probably inside the TEXT
+ * section (program code). Needs no delete()ing. `Does' memory management by
+ * not doing anything: statically allocated memory belongs to whole lifetime
+ * of the process, so it doesn't have to be freed.
+ */
+ class Static: public Flat {
+ public:
+ Static(char const*);
+ Static(char const*beg_,slen_t len_) { beg=beg_; len=len_; }
+ };
+
+ /** A flat buffer of fixed length. Not particularly useful, try
+ * SimBuffer::B instead.
+ */
+ class Fixed: public Flat {
+ public:
+ inline Fixed(slen_t len_) { beg=new char[len_]; len=len_; }
+ virtual inline ~Fixed() {
+ delete [] const_cast<char*>(beg); /* Dat: const_cast: pacify VC6.0 */
+ }
+ private:
+ /** Disable this. */
+ inline Fixed& operator=(Fixed const&) {return*this;}
+ };
+
+#if 0
+ /** Fixed-length, writable */
+ class FixWrite: public GenBuffer {
+ public:
+ };
+#endif
+
+ /** Abstract class. Example of virtual inheritance, needed because of
+ * SimBuffer::B.
+ */
+ class Appendable: virtual public GenBuffer, public GenBuffer::Writable {
+ public:
+ /** Makes room for `len' more chars at the end of the string, and returns
+ * a pointer to the beginning of that location. Should be efficient.
+ */
+ virtual char *vi_mkend(slen_t) =0;
+ /** Makes room for `len' more chars at the end of the string, and returns
+ * a pointer to the beginning of that location. May be inefficient.
+ */
+ virtual char *vi_mkbeg(slen_t) =0;
+ /** Use this instead of append(...). */
+ virtual void vi_write(char const*, slen_t);
+ inline virtual void vi_putcc(char c) { vi_mkend(1)[0]=c; }
+ /** There is no append(...) method. Use vi_write() instead. */
+ void prepend(char const*, slen_t);
+ };
+
+ /** A one-way linked list of flat strings. Quickest for long memory appends.
+ * Does memory management.
+ */
+ class Linked: public Appendable {
+ public:
+ struct Node {
+ char *beg;
+ slen_t len;
+ /** May be NULL. */
+ Node *next;
+ };
+ Node *first, *last;
+ inline Linked(): first(0), last(0) {}
+ virtual ~Linked();
+ Linked(GenBuffer const& other);
+ Linked(char const*);
+ Linked& operator=(GenBuffer const& other);
+ Linked& operator=(Linked const& other);
+ virtual slen_t getLength() const;
+ virtual void each_sub(block_sub_t block, void *data) const;
+ virtual void first_sub(Sub &sub) const;
+ virtual void next_sub(Sub &sub) const;
+ virtual char *vi_mkend(slen_t len);
+ virtual char *vi_mkbeg(slen_t len);
+ };
+
+ /* Abstract class. */
+ class Resizable: public Appendable { public:
+ /** Grows the string by the specified `left' and `right' amount on the
+ * sides. The amounts may be positive, zero or negative. For a negative
+ * amount, the `?beg' will be rendered invalid. For a nonnegative amount,
+ * `?beg' will point to the beginning of the new, uninitialized part of the
+ * buffer.
+ */
+ virtual void vi_grow2(slendiff_t left, slendiff_t right, char **lbeg, char **rbeg) =0;
+ Resizable& operator=(GenBuffer const& other);
+ inline void clearFree() { vi_grow2(0, -(slendiff_t)getLength(), 0, 0); }
+ inline void forgetAll() { vi_grow2(0, -(slendiff_t)getLength(), 0, 0); }
+ /** If howmuch>getLength(), then clears the string. */
+ inline void forgetLast(slen_t howmuch) { vi_grow2(0, -(slendiff_t)howmuch, 0, 0); }
+ inline void forgetFirst(slen_t howmuch) { vi_grow2(-(slendiff_t)howmuch, 0, 0, 0); }
+ void keepLeft(slen_t howmuch);
+ void keepRight(slen_t howmuch);
+ void keepSubstr(slen_t from_offset, slen_t slen);
+ inline virtual char *vi_mkend(slen_t howmuch) { char *s; vi_grow2(0, howmuch, 0, &s); return s; }
+ inline virtual char *vi_mkbeg(slen_t howmuch) { char *s; vi_grow2(howmuch, 0, &s, 0); return s; }
+ };
+
+ /** A simple, non-shared, writable, flat memory buffer of bytes. Supports
+ * fast appends (with rare memory-rallocations) by pre-allocating at most
+ * twice as much memory. Prepends are
+ * slow, because they always include memory allocation and copying.
+ * Does memory management.
+ * Imp: check when `len' overflows (i.e 2*alloced etc.)
+ */
+ class B: public Resizable, public Flat {
+ /* BUGFIX at Tue Sep 3 18:04:34 CEST 2002:
+ * original order was: public Flat, public Resizable, but I got the
+ * error message from gcc-3.2: gensi.hpp:398: sorry, not implemented: adjusting pointers for covariant returns
+ */
+ protected:
+ /** Number of bytes preallocated. */
+ slen_t alloced;
+ char small[8];
+ public:
+ /** Overridden. */
+ virtual void vi_grow2(slendiff_t left, slendiff_t right, char **lbeg, char **rbeg);
+
+ /** Destructor: must be virtual since we have virtual methods. */
+ virtual ~B() {
+ if (beg!=small) delete [] const_cast<char*>(beg);
+ /* ^^^ Dat: const_cast: pacify VC6.0 */
+ }
+ /** Constructor: the empty buffer. */
+ inline B(): alloced(sizeof(small)) { beg=small; len=0; }
+ /** Constructor: copy data from a null-terminated C string. */
+ B(char const*);
+ /** Constructor: copy data from a memory buffer. */
+ B(char const*,slen_t);
+ /** Constructor: copy-constructor */
+ B(B const&);
+ /** Constructor: copy data from a Flat buffer. */
+ B(Flat const&);
+ /** Constructor: copy data from a Flat buffer, term0(). */
+ B(Flat const&,int);
+ /** Constructor: copy data from a GenBuffer. */
+ B(GenBuffer const&);
+ /** Constructor: copy (consume) data from a readable stream. */
+ B(GenBuffer::Readable &);
+ /** Constructor: concatenate two (2) memory buffers. */
+ B(char const*,slen_t, char const*,slen_t);
+ /** Constructor: concatenate two (2) memory buffers, term0(). */
+ B(char const*,slen_t, char const*,slen_t,int);
+ /** Constructor: concatenate two GenBuffers. */
+ B(GenBuffer const&, GenBuffer const&);
+ /** Constructor: concatenate three (3) memory buffers. */
+ B(char const*,slen_t, char const*,slen_t, char const*,slen_t);
+ /** Constructor: concatenate three (3) GenBuffers. */
+ B(GenBuffer const&, GenBuffer const&, GenBuffer const&);
+ /** Constructor: concatenate a flat buffer and a C string */
+ B(Flat const&, char const*);
+ /** Constructor: concatenate three ... */
+ B(char const*, Flat const&, char const*);
+ /** Constructor: a substring of a Flat buffer */
+ B(Flat const&, slen_t from_offset, slen_t slen);
+
+ /** Works even when other==&(this). @return (this) */
+ B& operator=(/*SimBuffer::*/Flat const& other);
+ /** C++ SUXX: type conversion (Flat& -> B&) doesn't work as expected.
+ * Works even when other==&(this). @return (this)
+ */
+ B& operator=(/*SimBuffer::*/B const& other);
+ /** @return (this) */
+ B& operator=(char const*);
+ /** Reads (consumes) the whole `stream', and appends the bytes to (this).
+ * @return (this) declaring `operator<<' inside would ruin inherited `operator<<'s
+ */
+ /* GenBuffer::Writable& operator<<(GenBuffer::Readable &stream); */
+
+ /** Pacify VC6.0 multiple inheritance*/
+ inline virtual operator void*() const { return (void*)(len!=0); }
+ /** Pacify VC6.0 multiple inheritance */
+ inline virtual bool operator!() const { return len==0; }
+
+ friend /*SimBuffer::*/B& operator<<(/*SimBuffer::*/B& self, GenBuffer::Readable &stream);
+ /** Specific operators for faster implementation */
+ B& operator<<(char c);
+ B& operator<<(char const* s);
+ /** Works even when other==&(this). @return (this) */
+ B& operator<<(Flat const&);
+ /* C++ inheritance SUXXXX: now I have to re-define _every_ operator<< in GenBuffer::Writable... */
+ B& operator <<(void const*);
+ inline B& operator <<( signed short n) { write_num((signed long)n); return*this; }
+ inline B& operator <<( signed int n) { write_num((signed long)n); return*this; }
+ inline B& operator <<( signed long n) { write_num(n); return*this; }
+ inline B& operator <<(unsigned short n) { write_num((unsigned long)n); return*this; }
+ inline B& operator <<(unsigned int n) { write_num((unsigned long)n); return*this; }
+ inline B& operator <<(unsigned long n) { write_num(n); return*this; }
+ #if HAVE_LONG_LONG && NEED_LONG_LONG
+ inline B &operator <<(signed long long n) { write_num(n); return*this; }
+ inline B &operator <<(unsigned long long n) { write_num(n); return*this; }
+ #endif
+ inline B& operator <<(bool b) { GenBuffer::Writable::operator<<(b); return*this; }
+
+#if 0
+ friend SimBuffer::B& operator<<(SimBuffer::B& self, char const*s);
+ friend SimBuffer::B& operator<<(SimBuffer::B& self, char c);
+#endif
+
+ inline char *begin_() const { return const_cast<char*>(beg); }
+ inline char *end_ () const { return const_cast<char*>(beg)+len; }
+ inline bool isFull() const { return len==alloced; }
+ /** Ensures beg[len]=='\0'. @return (this) */
+ B& term0();
+ /** @param idx would cause overload conflict if declared len_t. No range check */
+ inline char &operator[](slendiff_t idx) const { return const_cast<char*>(beg)[idx]; }
+ /** @param lendiff if negative, then makes the buffer shorter */
+ void grow_set0_by(slendiff_t lendiff);
+ /** Grows the buffer if necessary, fills with '\0' */
+ char getAt(slen_t idx);
+ /** Doesn't free unnecessary memory. */
+ inline void clear() { len=0; }
+ /** Removes oldmuch chars from index first, and makes place for newmuch
+ * chars there. Returns the beginning of the new place. Calls memmove().
+ * Tue Jun 11 15:33:33 CEST 2002
+ */
+ char *substr_grow(slen_t first, slen_t oldmuch, slen_t newmuch);
+ B substr(slen_t first, slen_t howmuch) const;
+ B substr(slen_t first) const;
+ B right(slen_t howmuch) const;
+ B left(slen_t howmuch) const;
+ static void space_pad_cpy(char *dst, char const*src, slen_t pad);
+
+ /* vi_write() doesn't work if s is inside (this).
+ * There is no append(...) method. Use vi_write() instead.
+ */
+ // void append(char const*s, const slen_t len_);
+ virtual void vi_write(char const*, slen_t);
+
+ /* Original: B& vformat(slen_t n, char const *fmt, va_list ap);
+ * Pacify VC6.0: error C2555: 'SimBuffer::B::vformat' : overriding virtual function differs from 'GenBuffer::Writable::vformat' only by return type or calling convention
+ */
+ /** appends at most `n' chars, no trailing '\0'. This is different from
+ * ANSI (old and C99) stdio.h, because those insert at most `n-1' chars
+ * (not counting the '\0'), _and_ a trailing '\0'. Truncates the output
+ * to `n' chars if it would be longer. (Truncation semantics changed at
+ * Tue Jun 11 14:27:12 CEST 2002. Old: truncate to no chars if longer)
+ */
+ GenBuffer::Writable& vformat(slen_t n, char const *fmt, va_list ap);
+ /** appends as many chars as requrested */
+ GenBuffer::Writable& vformat(char const *fmt, va_list ap);
+ /** appends; calls vformat(n); mandatorly non-inline because of ... */
+ GenBuffer::Writable& format(slen_t n, char const *fmt, ...);
+ /** appends; calls vformat(); mandatorly non-inline because of ... */
+ GenBuffer::Writable& format(char const *fmt, ...);
+
+ /*
+ * Name: NonPathMeta
+ * Input: any binary
+ * Output: non-path characters pre-backslashed
+ * Description: Places backslashes in front of non-path characters:
+ * [^-_./a-zA-Z0-9].
+ * Compatibility: UNIX shells: sh (Bourne Shell), bash, ksh, zsh. Use this in
+ * a shell script to protect a string from word splitting, variable
+ * substitution and everything else. Note that there will be problems
+ * only with \0 (depends on the shell) and \n (will be simply removed by
+ * the shell!). See also Quote::QShell for full shell compatility.
+ * Valid input type: binary
+ * Valid input: any binary
+ * On invalid input: impossible
+ * Inverse of valid: lossy: Quote::UnMeta
+ * Validity indicator: implemented
+ * Output type: some binary
+ * Direction: encode
+ * Method: each_byte
+ * Dependencies: -
+ */
+ B& appendNpmq(const Flat &other, bool dq=false);
+ /** Quotes a filename (actually a pathname since it may include
+ * (sub)directories) specified in param `other' to be passed to the
+ * most common shell of the host operating system (/bin/sh, COMMAND.COM,
+ * CMD.EXE etc.) as a separate command line argument for a command
+ * invoked from the shell.
+ *
+ * Under UNIX, this differs from appendNpmq only when treating [\n\0].
+ * Under Win32, the filename is surrounded by double quotes. Double quotes
+ * inside the filename are skipped. Other systems than Win32 are treated
+ * like UNIX.
+ * @param preminus prefix filenames starting with `-' with `./' ?
+ */
+ B& appendFnq(const Flat &other, bool preminus=false);
+ /**
+ * Name: Quote::NonPathOctal; from quote.rb
+ * Input: any binary
+ * Output: non-path characters converted to octal
+ * Description: Converts non-path characters ([^-_./a-zA-Z0-9]) in
+ * a string to their prebackslashed, 3-digit octal representation (i.e
+ * \123).
+ * Compatibility: Ruby, ANSI C, K&R C, C++, Java (without \u....),
+ * TCL double quotes (without \u....), TCL unquoted strings (without
+ * \u....), Perl5, Pike, AWK, PostScript Level 1, bc. See also
+ * Quote::*Octal.
+ * Valid input type: binary
+ * Valid input: any binary
+ * On invalid input: impossible
+ * Inverse of valid: lossy: Quote::UnSlash
+ * Validity indicator: implemented
+ * Output type: \A[-\\._/a-zA-Z0-9]*\z
+ * Direction: encode
+ * Method: each_byte
+ * Dependencies: -
+ */
+ B& appendDump(const Flat &other, bool dq=false);
+ B& appendDump(const char c, bool dq=false);
+ /**
+ * Name: Quote::Unslash
+ * Input: a double-quoted (backslashed) version of a string without
+ * the double quotes themselves
+ * Output: the original, unquoted (possibly binary) string
+ * Description: Converts a string expressed inside double quotes of some
+ * programming language (e.g Ruby, C, Java, Perl, Ruby) to its original,
+ * unquoted state. Transformation is done only after backslashes. The
+ * following `common' transformations are supported: \0, \00, \000
+ * (octal), \a (alarm bell), \b (backslash), \e (escape), \f (form feed),
+ * \n (newline), \r (carriage return), \t (horizontal tab), \v (verical
+ * tab) \x61, \c[, \l (lowercase), \u (upper case), \NL (skip this),
+ * \", \\, \... .
+ * Compatibility: Ruby, ANSI C, C++, Java (without \u....), TCL double
+ * quotes (without \u....), TCL unquoted strings, Perl5, Pike, AWK,
+ * PostScript Level 1, bc, PHP.
+ * See also Quote::UnSlashPHPC for full PHP:StripCSlashes() compatibility.
+ * See also Quote::UnSlashKnr. Compatible with PHP stripcslashes().
+ * See also Quote::UnSlashKnr. Differs from Quote::UnslashMiddle by not
+ * removing the double quotes from string edges.
+ * Valid input type: binary
+ * Valid input: any binary
+ * On invalid input: impossible
+ * Inverse of valid: lossy: Quote::NonPathOctal
+ * Validity indicator: implemented
+ * Output type: any binary
+ * Direction: decode
+ * Method: gsub
+ * Dependencies: -
+ *
+ * @param iniq the char that surrounds the quoted param `other'
+ * @param other a quoted string
+ * @return an empty string if iniq<256 and param `other' not delimited by iniq
+ */
+ B& appendUnslash(const Flat &other, int iniq);
+ /** Appends as a C (double-quoted) string. */
+ B& appendDumpC (const Flat &other, bool dq=false);
+ /** Appends as a PostScript (paren-quoted) string. */
+ B& appendDumpPS (const Flat &other, bool dq=false);
+ /** Make `other' upper case (English), plus change all non-alpha chars
+ * to underscore.
+ */
+ B& appendHppq(const Flat &other);
+
+ protected:
+ inline char *grow_by(slen_t howmuch) { char *s; vi_grow2(0, howmuch, 0, &s); return s; }
+ /*SimBuffer::*/B& B_append(GenBuffer::Readable &stream);
+#if 0
+ SimBuffer::B& B_append(char c);
+ SimBuffer::B& B_append(char const*s);
+#endif
+ };
+};
+
+inline SimBuffer::B& operator<<(SimBuffer::B& self, GenBuffer::Readable &stream) { return self.B_append(stream); }
+#if 0
+inline SimBuffer::B& operator<<(SimBuffer::B& self, char const*s) { return self.B_append(s); }
+inline SimBuffer::B& operator<<(SimBuffer::B& self, char c) { return self.B_append(c); }
+#endif
+
+/** Shorthand synonym */
+typedef SimBuffer::B Buffer;
+
+inline bool operator ==(const GenBuffer& s1, const GenBuffer& s2) {
+ return 0==s1.cmp(s2);
+}
+inline bool operator ==(const char *s1, const GenBuffer& s2) {
+ return 0==s2.cmp(s1);
+}
+inline bool operator ==(const GenBuffer& s1, const char *s2) {
+ return 0==s1.cmp(s2);
+}
+inline bool operator <(const GenBuffer& s1, const GenBuffer& s2) {
+ return 0>s1.cmp(s2);
+}
+inline bool operator <(const char *s1, const GenBuffer& s2) {
+ return 0<s2.cmp(s1);
+}
+inline bool operator <(const GenBuffer& s1, const char *s2) {
+ return 0>s1.cmp(s2);
+}
+inline bool operator >(const GenBuffer& s1, const GenBuffer& s2) {
+ return 0<s1.cmp(s2);
+}
+inline bool operator >(const char *s1, const GenBuffer& s2) {
+ return 0>s2.cmp(s1);
+}
+inline bool operator >(const GenBuffer& s1, const char *s2) {
+ return 0<s1.cmp(s2);
+}
+inline bool operator <=(const GenBuffer& s1, const GenBuffer& s2) {
+ return 0>=s1.cmp(s2);
+}
+inline bool operator <=(const char *s1, const GenBuffer& s2) {
+ return 0<=s2.cmp(s1);
+}
+inline bool operator <=(const GenBuffer& s1, const char *s2) {
+ return 0>=s1.cmp(s2);
+}
+inline bool operator >=(const GenBuffer& s1, const GenBuffer& s2) {
+ return 0<=s1.cmp(s2);
+}
+inline bool operator >=(const char *s1, const GenBuffer& s2) {
+ return 0>=s2.cmp(s1);
+}
+inline bool operator >=(const GenBuffer& s1, const char *s2) {
+ return 0<=s1.cmp(s2);
+}
+inline bool operator !=(const GenBuffer& s1, const GenBuffer& s2) {
+ return 0!=s1.cmp(s2);
+}
+inline bool operator !=(const char *s1, const GenBuffer& s2) {
+ return 0!=s2.cmp(s1);
+}
+inline bool operator !=(const GenBuffer& s1, const char *s2) {
+ return 0!=s1.cmp(s2);
+}
+
+#endif
diff --git a/graphics/sam2p/gensio.cpp b/graphics/sam2p/gensio.cpp
new file mode 100644
index 0000000000..2d53748a72
--- /dev/null
+++ b/graphics/sam2p/gensio.cpp
@@ -0,0 +1,912 @@
+/*
+ * gensio.cpp -- IO-specific methods
+ * by pts@fazekas.hu at Tue Feb 26 13:28:12 CET 2002
+ */
+
+#ifdef __GNUC__
+#ifndef __clang__
+#pragma implementation
+#endif
+#endif
+
+#if 0
+extern "C" int errno;
+/* OK: autodetect with autoconf */
+extern "C" int _l_stat(const char *file_name, struct stat *buf);
+/* OK: Imp: not in ANSI C, but we cannot emulate it! */
+extern "C" int _v_s_n_printf ( char *str, size_t n, const char *format, va_list ap );
+#else
+#undef __STRICT_ANSI__ /* for __MINGW32__ */
+#define _BSD_SOURCE 1 /* vsnprintf(); may be emulated with fixup_vsnprintf() */
+#ifndef __APPLE__ /* SUXX: Max OS X has #ifndef _POSIX_SOURCE around lstat() :-( */
+#define _POSIX_SOURCE 1 /* also popen() */
+#endif
+#ifdef USE_GNU_SOURCE_INSTEAD_OF_POSIX_SOURCE
+#define _GNU_SOURCE 1 /* Implies _POSIX_C_SOURCE >= 2. */
+#else
+#define _POSIX_C_SOURCE 2 /* also popen() */
+#endif
+#define _XOPEN_SOURCE_EXTENDED 1 /* Digital UNIX lstat */
+#ifndef _XPG4_2
+#define _XPG4_2 1 /* SunOS 5.7 lstat() */
+#endif
+#undef _XOPEN_SOURCE /* pacify gcc-3.1 */
+#define _XOPEN_SOURCE 1 /* popen() on Digital UNIX */
+#endif
+
+#include "gensio.hpp"
+#include "error.hpp"
+#include <string.h> /* strlen() */
+#include <stdarg.h> /* va_list */
+#if _MSC_VER > 1000
+// extern "C" int getpid(void);
+# include <process.h>
+#else
+# include <unistd.h> /* getpid() */
+#endif
+#include <sys/stat.h> /* struct stat */
+#include <stdlib.h> /* getenv() */
+#include <errno.h>
+#include <signal.h> /* signal() */ /* Imp: use sigaction */
+#if HAVE_DOS_BINARY
+#undef __STRICT_ANSI__
+#include <fcntl.h> /* O_BINARY */
+#include <io.h> /* setmode() */
+#endif
+
+#define USGE(a,b) ((unsigned char)(a))>=((unsigned char)(b))
+
+#if HAVE_PTS_VSNPRINTF /* Both old and c99 work OK */
+# define VSNPRINTF vsnprintf
+#else
+# if OBJDEP
+# warning REQUIRES: snprintf.o
+# endif
+# include "snprintf.h"
+# define VSNPRINTF fixup_vsnprintf /* Tested, C99. */
+#endif
+
+static void cleanup(int) {
+ Error::cexit(Error::runCleanups(126));
+}
+
+void Files::doSignalCleanup() {
+ signal(SIGINT, cleanup);
+ signal(SIGTERM, cleanup);
+#ifdef SIGHUP
+ signal(SIGHUP, SIG_IGN);
+#endif
+ /* Dat: don't do cleanup for SIGQUIT */
+}
+
+GenBuffer::Writable& SimBuffer::B::vformat(slen_t n, char const *fmt, va_list ap) {
+ /* Imp: test this code in various systems and architectures. */
+ /* Dat: vsnprintf semantics are verified in configure AC_PTS_HAVE_VSNPRINTF,
+ * and a replacement vsnprintf is provided in case of problems. We don't
+ * depend on HAVE_PTS_VSNPRINTF_C99, because C99-vsnprintf is a run-time
+ * property.
+ *
+ * C99 vsnprintf semantics: vsnprintf() always returns a non-negative value:
+ * the number of characters (trailing \0 not included) that would have been
+ * printed if there were enough space. Only the first maxlen (@param)
+ * characters may be modified. The output is terminated by \0 iff maxlen!=0.
+ * NULL @param dststr is OK iff maxlen==0. Since glibc 2.1.
+ * old vsnprintf semantics: vsnprintf() returns a non-negative value or -1:
+ * 0 if maxlen==0, otherwise: -1 if maxlen is shorter than all the characters
+ * plus the trailing \0, otherwise: the number of characters (trailing \0 not
+ * included) that were printed. Only the first maxlen (@param)
+ * characters may be modified. The output is terminated by \0 iff maxlen!=0.
+ * NULL @param dststr is OK iff maxlen==0.
+ */
+ if (n>0) { /* avoid problems with old-style vsnprintf */
+ char *s; vi_grow2(0, n+1, 0, &s); len-=n+1; /* +1: sprintf appends '\0' */
+ const_cast<char*>(beg)[len]='\0'; /* failsafe sentinel */
+ slen_t did=VSNPRINTF(s, n+1, fmt, ap);
+ if (did>n) did=n;
+ /* ^^^ Dat: always true: (unsigned)-1>n, so this works with both old and c99 */
+ /* Now: did contains the # chars to append, without trailing '\0' */
+ /* Dat: we cannot check for -1, because `did' is unsigned */
+ /* Dat: trailer '\0' doesn't count into `did' */
+ len+=did;
+ }
+ return *this;
+}
+GenBuffer::Writable& SimBuffer::B::vformat(char const *fmt, va_list ap) {
+ char dummy, *s;
+ slen_t did=VSNPRINTF(&dummy, 1, fmt, ap), n;
+ if (did>0) { /* skip if nothing to be appended */
+ /* vvv Dat: we cannot check for -1, because `did' is unsigned */
+ if ((did+1)!=(slen_t)0) { /* C99 semantics; quick shortcut */
+ vi_grow2(0, (n=did)+1, 0, &s); len-=n+1;
+ ASSERT_SIDE2(VSNPRINTF(s, n+1, fmt, ap), * 1U==did);
+ } else { /* old semantics: grow the buffer incrementally */
+ if ((n=strlen(fmt))<16) n=16; /* initial guess */
+ while (1) {
+ vi_grow2(0, n+1, 0, &s); len-=n+1; /* +1: sprintf appends '\0' */
+ const_cast<char*>(beg)[len]='\0'; /* failsafe sentinel */
+ did=VSNPRINTF(s, n+1, fmt, ap);
+ if ((did+1)!=(slen_t)0) {
+ assert(did!=0); /* 0 is caught early in this function */
+ assert(did<=n); /* non-C99 semantics */
+ break;
+ }
+ n<<=1;
+ }
+ }
+ len+=did;
+ }
+ return *this;
+}
+
+GenBuffer::Writable& SimBuffer::B::format(slen_t n, char const *fmt, ...) {
+ va_list ap;
+ PTS_va_start(ap, fmt);
+ vformat(n, fmt, ap);
+ va_end(ap);
+ return *this;
+}
+GenBuffer::Writable& SimBuffer::B::format(char const *fmt, ...) {
+ va_list ap;
+ PTS_va_start(ap, fmt);
+ vformat(fmt, ap);
+ va_end(ap);
+ return *this;
+}
+
+/* --- */
+
+GenBuffer::Writable& Files::FILEW::vformat(slen_t n, char const *fmt, va_list ap) {
+ /* Dat: no vfnprintf :-( */
+ SimBuffer::B buf;
+ buf.vformat(n, fmt, ap);
+ fwrite(buf(), 1, buf.getLength(), f);
+ return*this;
+}
+GenBuffer::Writable& Files::FILEW::vformat(char const *fmt, va_list ap) {
+ vfprintf(f, fmt, ap);
+ return*this;
+}
+
+/* --- */
+
+/** Must be <=32767. Should be a power of two. */
+static const slen_t GENSIO_BUFLEN=4096;
+
+void Encoder::vi_putcc(char c) { vi_write(&c, 1); }
+int Decoder::vi_getcc() { char ret; return vi_read(&ret, 1)==1 ? (unsigned char)ret : -1; }
+void Encoder::writeFrom(GenBuffer::Writable& out, FILE *f) {
+ char *buf=new char[GENSIO_BUFLEN];
+ int wr;
+ while (1) {
+ if ((wr=fread(buf, 1, GENSIO_BUFLEN, f))<1) break;
+ out.vi_write(buf, wr);
+ }
+ delete [] buf;
+}
+void Encoder::writeFrom(GenBuffer::Writable& out, GenBuffer::Readable& in) {
+ char *buf=new char[GENSIO_BUFLEN];
+ int wr;
+ while (1) {
+ if ((wr=in.vi_read(buf, GENSIO_BUFLEN))<1) break;
+ out.vi_write(buf, wr);
+ }
+ delete [] buf;
+}
+
+/* --- */
+
+Filter::FILEE::FILEE(char const* filename) {
+ if (NULLP==(f=fopen(filename,"wb"))) Error::sev(Error::EERROR) << "Filter::FILEE: error open4write: " << FNQ2(filename,strlen(filename)) << (Error*)0;
+ closep=true;
+}
+void Filter::FILEE::vi_write(char const*buf, slen_t len) {
+ if (len==0) close(); else fwrite(buf, 1, len, f);
+}
+void Filter::FILEE::close() {
+ if (closep) { fclose(f); f=(FILE*)NULLP; closep=false; }
+}
+
+/* --- */
+
+static FILE* fopenErr(char const* filename, char const* errhead) {
+ FILE *f;
+ if (NULLP==(f=fopen(filename,"rb")))
+ Error::sev(Error::EERROR) << errhead << ": error open4read: " << FNQ2(filename,strlen(filename)) << (Error*)0;
+ return f;
+}
+
+Filter::FILED::FILED(char const* filename) {
+ f=fopenErr(filename, "Filter::FileD");
+ closep=true;
+}
+slen_t Filter::FILED::vi_read(char *buf, slen_t len) {
+ if (len==0) { close(); return 0; }
+ return fread(buf, 1, len, f);
+}
+void Filter::FILED::close() {
+ if (closep) { fclose(f); f=(FILE*)NULLP; closep=false; }
+}
+
+/* --- */
+
+Filter::UngetFILED::UngetFILED(char const* filename_, FILE *stdin_f, closeMode_t closeMode_) {
+ if (stdin_f!=NULLP && (filename_==NULLP || (filename_[0]=='-' && filename_[1]=='\0'))) {
+ f=stdin_f;
+ Files::set_binary_mode(fileno(f), true);
+ closeMode_&=~CM_unlinkp;
+ if (0!=(closeMode_&CM_keep_stdinp)) closeMode_&=~CM_closep;
+ filename_=(char const*)NULLP; /* BUGFIX at Tue Jan 4 23:45:31 CET 2005 */
+ } else {
+ f=fopenErr(filename_, "Filter::UngetFileD");
+ }
+ if (filename_!=NULLP) strcpy(const_cast<char*>(filename=new char[strlen(filename_)+1]), filename_);
+ else filename=(char*)NULLP;
+ /* fprintf(stderr,"filename:%s\n",filename); */
+ closeMode=closeMode_;
+ ftell_at=0;
+ ofs=0;
+}
+// Filter::UngetFILED::checkFILE() { }
+slen_t Filter::UngetFILED::vi_read(char *buf, slen_t len) {
+ slen_t delta;
+ if (len==0) {
+ close(); return 0;
+ } else if (unget.getLength()==0) { delta=0; do_read_f:
+ delta+=(f==NULLP ? 0 : fread(buf, 1, len, f));
+ ftell_at+=delta;
+ return delta;
+ // delta+=fread(buf, 1, len, f); // write(1, buf, delta); // return delta;
+ } else if (ofs+len<=unget.getLength()) {
+ // printf("\nul=%d ft=%ld\n", unget.getLength(), ftell(f)); fflush(stdout);
+ memcpy(buf, unget()+ofs, len); /* Dat: don't remove from unget yet */
+ ftell_at+=len;
+ // write(1, buf, len);
+ if ((ofs+=len)==unget.getLength()) { unget.forgetAll(); ofs=0; }
+ return len;
+ } else {
+ // printf("\num=%d ft=%d\n", unget.getLength(), ftell(f)); fflush(stdout);
+ delta=unget.getLength()-ofs; /* BUGFIX at Sat Apr 19 17:15:50 CEST 2003 */
+ memcpy(buf, unget()+ofs, delta);
+ // write(1, buf, delta);
+ unget.forgetAll(); ofs=0;
+ buf+=delta;
+ len-=delta;
+ goto do_read_f;
+ }
+}
+void Filter::UngetFILED::close() {
+ /* Since close() may be closed twice (e.g. once manually, and once from the
+ * the destructor), everything below must be idempotent.
+ */
+
+ if (0!=(closeMode&CM_closep)) {
+ fclose(f); f=(FILE*)NULLP;
+ closeMode&=~CM_closep; /* Make it idempotent. */
+ }
+ unget.forgetAll(); /* Idempotent. */
+ ofs=0; /* Idempotent. */
+ if (filename!=NULLP) {
+ if (0!=(closeMode&CM_unlinkp)) { remove(filename); }
+ delete [] filename;
+ filename=(const char*)NULLP; /* Make it idempotent. */
+ }
+}
+
+int Filter::UngetFILED::vi_getcc() {
+ if (unget.getLength()==0) { do_getc:
+ int i=-1;
+ if (f!=NULLP && (i=MACRO_GETC(f))!=-1) ftell_at++;
+ return i;
+ }
+ if (ofs==unget.getLength()) { ofs=0; unget.forgetAll(); goto do_getc; }
+ ftell_at++;
+ return unget[ofs++];
+}
+int Filter::UngetFILED::getc_seekable() {
+ /* Glibc stdio doesn't allow fseek() even if the seek would go into the
+ * read buffer, and fseek(f, 0, SEEK_CUR) fails for unseekable files. Fine.
+ */
+ int c=MACRO_GETC(f);
+ return 0==fseek(f, -1L, SEEK_CUR) ? -2 : c;
+}
+bool Filter::UngetFILED::isSeekable() {
+ long pos, posend;
+ if (f==NULLP || 0!=(closeMode&CM_seekablep)) return true;
+ // return false;
+ clearerr(f); /* clears both the EOF and error indicators */
+ if (-1L==(pos=ftell(f)) /* sanity checks on ftell() and fseek() */
+ || 0!=fseek(f, 0L, SEEK_CUR)
+ || pos!=ftell(f)
+ || 0!=fseek(f, 0L, SEEK_END)
+ || (posend=ftell(f))==0 || posend<pos
+ || 0!=fseek(f, 0L, SEEK_SET)
+ || 0!=ftell(f)
+ || 0!=fseek(f, pos, SEEK_SET)
+ || pos!=ftell(f)
+ ) return false;
+ int c;
+ if ((c=getc_seekable())==-2 && pos==ftell(f)) {
+ // if (0!=fseek(f, -1L, SEEK_CUR) || pos!=ftell(f))
+ // Error::sev(Error::EERROR) << "Filter::UngetFILED: cannot seek back" << (Error*)0;
+ return true;
+ }
+ unget << (char)c; /* not seekable, must unget the test character just read */
+ return false;
+}
+FILE* Filter::UngetFILED::getFILE(bool seekable_p) {
+ FILE *tf;
+ if (!unget.isEmpty() || (seekable_p && !isSeekable())) { do_temp:
+ /* must create a temporary file */
+ SimBuffer::B tmpnam;
+ if (filename==NULLP) Error::sev(Error::NOTICE) << "Filter::UngetFILED" << ": using temp for" << " `-' (stdin)" << (Error*)0;
+ else Error::sev(Error::NOTICE) << "Filter::UngetFILED" << ": using temp for" << ": " << FNQ2(filename,strlen(filename)) << (Error*)0;
+ if (NULLP==(tf=Files::open_tmpnam(tmpnam, "wb+"))) {
+ if (filename==NULLP) Error::sev(Error::EERROR) << "Filter::UngetFILED" << ": cannot open temp file for" << " `-' (stdin)" << (Error*)0;
+ else Error::sev(Error::EERROR) << "Filter::UngetFILED" << ": cannot open temp file for" << ": " << FNQ2(filename,strlen(filename)) << (Error*)0;
+ }
+ tmpnam.term0();
+ /* vvv change filename, so CM_unlinkp can work */
+ if (filename!=NULLP) {
+ if (0!=(closeMode&CM_unlinkp)) { remove(filename); }
+ delete [] filename;
+ }
+ /* This is the object data member char const* filename' in
+ * Filter::UngetFILED, owned by `this', deleted in the close() method
+ * called from the Filter::UngetFILED destructor.
+ */
+ strcpy(const_cast<char*>(filename=new char[tmpnam.getLength()+1]), tmpnam());
+ /* Also makes a copy of the filename array, good */
+ Files::tmpRemoveCleanup(filename);
+ if (unget.getLength()-ofs==fwrite(unget()+ofs, 1, unget.getLength()-ofs, tf)) {
+ static const slen_t BUFSIZE=4096; /* BUGFIX at Sat Apr 19 15:43:59 CEST 2003 */
+ char *buf=new char[BUFSIZE];
+ unsigned got;
+ // fprintf(stderr, "ftf=%ld ofs=%d\n", ftell(f), ofs);
+ while ((0<(got=fread(buf, 1, BUFSIZE, f)))
+ && got==fwrite(buf, 1, got, tf)) {}
+ // fprintf(stderr,"got=%d ftell=%d\n", got, ftell(tf));
+ delete [] buf;
+ }
+ unget.forgetAll(); ofs=0;
+ fflush(tf); rewind(tf);
+ if (ferror(tf) || ferror(f))
+ Error::sev(Error::EERROR) << "Filter::UngetFILED" << ": cannot write temp file" << (Error*)0;
+ if (0!=(closeMode&CM_closep)) fclose(f);
+ closeMode|=CM_closep|CM_unlinkp; /* close and unlink the temporary file */
+ /* ^^^ Imp: verify VC++ compilation, +others */
+ f=tf;
+ } else if (f==NULLP) { /* no real file open */
+ #if OS_COTY==COTY_UNIX
+ tf=fopen("/dev/null","rb");
+ #else
+ #if OS_COPTY==COTY_WIN9X || OS_COTY==COTY_WINNT
+ tf=fopen("nul","rb");
+ #else
+ tf=(FILE*)NULLP;
+ #endif
+ #endif
+ if (tf==NULLP) goto do_temp; /* perhaps inside chroot() */
+ close();
+ closeMode|=CM_closep|CM_unlinkp; /* close and unlink the temporary file */
+ f=tf;
+ }
+ closeMode|=CM_seekablep;
+ return f;
+}
+void Filter::UngetFILED::seek(long abs_ofs) {
+ if (abs_ofs==vi_tell()) return;
+ (void) getFILE(true); /* ensure seekability */
+ if (0!=fseek(f, abs_ofs, SEEK_SET))
+ Error::sev(Error::EERROR) << "Filter::UngetFILED" << ": cannot seek" << (Error*)0;
+ assert(unget.isEmpty());
+ assert(ofs==0);
+ ftell_at=abs_ofs;
+}
+void Filter::UngetFILED::unread(char const *s, slen_t slen) {
+ ftell_at-=slen;
+ if (slen==0) {
+ } else if (slen<=ofs) {
+ memcpy(const_cast<char*>(unget()+(ofs-=slen)), s, slen);
+ } else {
+ slen-=ofs;
+ ofs=0;
+ if (!unget.isEmpty() || 0!=fseek(f, -slen, SEEK_CUR)) {
+ assert(unget.isEmpty()); // !!
+ unget.vi_write(s, slen); /* complete garbage unless unget was empty */
+ assert(unget.getLength());
+ }
+ }
+ // fprintf(stderr, "%d..\n", unget.getLength());
+}
+void Filter::UngetFILED::appendLine(GenBuffer::Writable &buf, int delimiter) {
+ // fprintf(stderr, "this=%p %d (%p)\n", this, unget.getLength(), unget());
+ unget.term0();
+ if (delimiter<0) {
+ char rbuf[4096];
+ slen_t got;
+ /* vvv Imp: less memory copying, less stack usage? */
+ while (0!=(got=vi_read(rbuf, sizeof(rbuf)))) buf.vi_write(rbuf, got);
+ } else if (unget.getLength()==0) { do_getc:
+ int i;
+ if (f!=NULLP) {
+ while ((i=MACRO_GETC(f))>=0 && i!=delimiter) { buf.vi_putcc(i); ftell_at++; }
+ if (i>=0) buf.vi_putcc(i);
+ }
+ } else {
+ char const *p=unget()+ofs, *p0=p, *pend=unget.end_();
+ assert(ofs<=unget.getLength());
+ while (p!=pend && *p!=delimiter) p++;
+ ftell_at+=p-p0;
+ if (p==pend) { buf.vi_write(p0, p-p0); ofs=0; unget.forgetAll(); goto do_getc; }
+ ftell_at++; p++; /* found delimiter in `unget' */
+ buf.vi_write(p0, p-p0);
+ ofs+=p-p0;
+ }
+}
+
+/* --- */
+
+Filter::PipeE::PipeE(GenBuffer::Writable &out_, char const*pipe_tmpl, slendiff_t i): tmpname(), out(out_), tmpename() {
+ /* <code similarity: Filter::PipeE::PipeE and Filter::PipeD::PipeD> */
+ param_assert(pipe_tmpl!=(char const*)NULLP);
+ SimBuffer::B *pp;
+ char const*s=pipe_tmpl;
+ lex: while (s[0]!='\0') { /* Interate throuh the template, substitute temporary filenames */
+ if (*s++=='%') switch (*s++) {
+ case '\0': case '%':
+ redir_cmd << '%';
+ break;
+ case 'i': /* the optional integer passed in param `i' */
+ redir_cmd << i;
+ break;
+ case '*': /* the optional unsafe string passed in param `i' */
+ redir_cmd << (char const*)i;
+ break;
+ case 'd': case 'D': /* temporary file for encoded data output */
+ pp=&tmpname;
+ put:
+ // if (*pp) Error::sev(Error::EERROR) << "Filter::PipeE" << ": multiple %escape" << (Error*)0;
+ /* ^^^ multiple %escape is now a supported feature */
+ // fprintf(stderr, "tmpl=(%s) s=(%s)\n", pipe_tmpl, s);
+ if (!*pp && !Files::find_tmpnam(*pp)) Error::sev(Error::EERROR) << "Filter::PipeE" << ": tmpnam() failed" << (Error*)0;
+ assert(! !*pp); /* pacify VC6.0 */
+ // *pp << ext;
+ pp->term0();
+ if ((unsigned char)(s[-1]-'A')<(unsigned char)('Z'-'A'))
+ redir_cmd.appendFnq(*pp, /*preminus:*/ true); /* Capital letter: quote from the shell */
+ else redir_cmd << *pp;
+ break;
+ case 'e': case 'E': /* temporary file for error messages */
+ pp=&tmpename;
+ goto put;
+ case 's': case 'S': /* temporary source file */
+ /* !! if the input is a regular, seekable file, don't copy to a temporary file */
+ pp=&tmpsname;
+ goto put;
+ default:
+ Error::sev(Error::EERROR) << "Filter::PipeE" << ": invalid %escape in pipe_tmpl" << (Error*)0;
+ } else redir_cmd << s[-1];
+ }
+ #if 0
+ if (!tmpname) Error::sev(Error::EERROR) << "Filter::PipeE" << ": no outname (%D) in cmd: " << (SimBuffer::B().appendDumpC(redir_cmd)) << (Error*)0;
+ #else
+ /* Append quoted file redirect to command, if missing */
+ if (!tmpname) { s=" >%D"; goto lex; }
+ #endif
+ #if !HAVE_PTS_POPEN
+ if (!tmpsname) { s=" <%S"; goto lex; }
+ #endif
+ // tmpname="tmp.name";
+ redir_cmd.term0();
+ if (tmpname) { Files::tmpRemoveCleanup(tmpname()); remove(tmpname()); } /* already term0() */
+ /* ^^^ Dat: remove() here introduces a race condition, but helps early error detection */
+ if (tmpename) Files::tmpRemoveCleanup(tmpename()); /* already term0() */
+ if (tmpsname) Files::tmpRemoveCleanup(tmpsname()); /* already term0() */
+ /* </code similarity: Filter::PipeE::PipeE and Filter::PipeD::PipeD> */
+
+ // fprintf(stderr, "rc: (%s)\n", redir_cmd());
+
+ #if HAVE_PTS_POPEN
+ if (!tmpsname) {
+ if (NULLP==(p=popen(redir_cmd(), "w" CFG_PTS_POPEN_B))) Error::sev(Error::EERROR) << "Filter::PipeE" << ": popen() failed: " << (SimBuffer::B().appendDumpC(redir_cmd)) << (Error*)0;
+ signal(SIGPIPE, SIG_IGN); /* Don't abort process with SIGPIPE signals if child cannot read our data */
+ } else {
+ #else
+ if (1) {
+ #endif
+ #if !HAVE_system_in_stdlib
+ Error::sev(Error::EERROR) << "Filter::PipeE" << ": no system() on this system" << (Error*)0;
+ #else
+ if (NULLP==(p=fopen(tmpsname(), "wb"))) Error::sev(Error::EERROR) << "Filter::PipeD" << ": fopen(w) failed: " << (SimBuffer::B().appendDumpC(redir_cmd)) << (Error*)0;
+ #endif
+ }
+}
+void Filter::PipeE::vi_copy(FILE *f) {
+ writeFrom(out, f);
+ if (ferror(f)) Error::sev(Error::EERROR) << "Filter::PipeE: vi_copy() failed" << (Error*)0;
+ fclose(f);
+}
+void Filter::PipeE::vi_write(char const*buf, slen_t len) {
+ assert(p!=NULLP);
+ int wr;
+ if (len==0) { /* EOF */
+ if (tmpsname) {
+ #if HAVE_system_in_stdlib
+ fclose(p);
+ if (0!=(Files::system3(redir_cmd()))) Error::sev(Error::EERROR) << "Filter::PipeE" << ": system() failed: " << (SimBuffer::B().appendDumpC(redir_cmd)) << (Error*)0;
+ remove(tmpsname());
+ #endif /* Dat: else is not required; would be unreachable code. */
+ } else {
+ #if HAVE_PTS_POPEN
+ if (0!=pclose(p)) Error::sev(Error::EERROR) << "Filter::PipeE" << ": pclose() failed; error in external prg" << (Error*)0;
+ #endif
+ }
+ vi_check();
+ p=(FILE*)NULLP;
+ FILE *f=fopen(tmpname(),"rb");
+ if (NULLP==f) Error::sev(Error::EERROR) << "Filter::PipeE" <<": fopen() after pclose() failed: "
+ << redir_cmd << ": " << tmpname << (Error*)0;
+ vi_copy(f);
+ // if (ferror(f)) Error::sev(Error::EERROR) << "Filter::Pipe: fread() tmpfile failed" << (Error*)0;
+ // fclose(f);
+ /* ^^^ interacts badly when Image::load() is called inside vi_copy(),
+ * Image::load() calls fclose()
+ */
+ if (tmpname ) remove(tmpname ());
+ if (tmpename) remove(tmpename());
+ if (tmpsname) remove(tmpsname());
+ out.vi_write(0,0); /* Signal EOF to subsequent filters. */
+ } else {
+ while (len!=0) {
+ wr=fwrite(buf, 1, len>0x4000?0x4000:len, p);
+// assert(!ferror(p));
+ if (ferror(p)) {
+ vi_check(); /* Give a chance to report a better error message when Broken File. */
+ Error::sev(Error::EERROR) << "Filter::PipeE" << ": pipe write failed" << (Error*)0;
+ }
+ buf+=wr; len-=wr;
+ }
+ }
+}
+Filter::PipeE::~PipeE() {}
+void Filter::PipeE::vi_check() {}
+
+/* --- */
+
+Filter::PipeD::PipeD(GenBuffer::Readable &in_, char const*pipe_tmpl, slendiff_t i): state(0), in(in_) {
+ /* <code similarity: Filter::PipeE::PipeE and Filter::PipeD::PipeD> */
+ param_assert(pipe_tmpl!=(char const*)NULLP);
+ SimBuffer::B *pp=(SimBuffer::B*)NULLP;
+ char const*s=pipe_tmpl;
+ lex: while (s[0]!='\0') { /* Interate throuh the template, substitute temporary filenames */
+ if (*s++=='%') switch (*s++) {
+ case '\0': case '%':
+ redir_cmd << '%';
+ break;
+ case 'i': /* the optional integer passed in param `i' */
+ redir_cmd << i;
+ break;
+ case '*': /* the optional unsafe string passed in param `i' */
+ redir_cmd << (char const*)i;
+ break;
+ case 'd': case 'D': /* temporary file for encoded data output */
+ pp=&tmpname;
+ put:
+ // if (*pp) Error::sev(Error::EERROR) << "Filter::PipeD: multiple %escape" << (Error*)0;
+ /* ^^^ multiple %escape is now a supported feature */
+ if (!*pp && !Files::find_tmpnam(*pp)) Error::sev(Error::EERROR) << "Filter::PipeD" << ": tmpnam() failed" << (Error*)0;
+ assert(*pp);
+ pp->term0();
+ if ((unsigned char)(s[-1]-'A')<(unsigned char)('Z'-'A'))
+ redir_cmd.appendFnq(*pp); /* Capital letter: quote from the shell */
+ else redir_cmd << *pp;
+ break;
+ case 'e': case 'E': /* temporary file for error messages */
+ pp=&tmpename;
+ goto put;
+ case 's': case 'S': /* temporary source file */
+ pp=&tmpsname;
+ goto put;
+ /* OK: implement temporary file for input, option to suppress popen() */
+ default:
+ Error::sev(Error::EERROR) << "Filter::PipeD: invalid %escape in pipe_tmpl" << (Error*)0;
+ } else redir_cmd << s[-1];
+ }
+ #if 0
+ if (!tmpname) Error::sev(Error::EERROR) << "Filter::PipeD" << ": no outname (%D) in cmd: " << (SimBuffer::B().appendDumpC(redir_cmd)) << (Error*)0;
+ #else
+ /* Append quoted file redirect to command, if missing */
+ if (!tmpname) { s=" >%D"; goto lex; }
+ #endif
+ #if !HAVE_PTS_POPEN
+ if (!tmpsname) { s=" <%S"; goto lex; }
+ #endif
+ // tmpname="tmp.name";
+ redir_cmd.term0();
+ if (tmpname) Files::tmpRemoveCleanup(tmpname ()); /* already term0() */
+ if (tmpename) Files::tmpRemoveCleanup(tmpename()); /* already term0() */
+ if (tmpsname) { Files::tmpRemoveCleanup(tmpsname()); remove(tmpsname()); } /* already term0() */
+ /* ^^^ Dat: remove() here introduces a race condition, but helps early error detection */
+ /* </code similarity: Filter::PipeE::PipeE and Filter::PipeD::PipeD> */
+}
+slen_t Filter::PipeD::vi_read(char *tobuf, slen_t tolen) {
+ assert(!(tolen!=0 && state==2));
+ if (state==2) return 0; /* Should really never happen. */
+ /* Normal read operation with tolen>0; OR tolen==0 */
+ if (state==0) { /* Read the whole stream from `in', write it to `tmpsname' */
+ #if HAVE_PTS_POPEN
+ if (!tmpsname) {
+ if (NULLP==(p=popen(redir_cmd(), "w" CFG_PTS_POPEN_B))) Error::sev(Error::EERROR) << "Filter::PipeD" << ": popen() failed: " << (SimBuffer::B().appendDumpC(redir_cmd)) << (Error*)0;
+ signal(SIGPIPE, SIG_IGN); /* Don't abort process with SIGPIPE signals if child cannot read our data */
+ vi_precopy();
+ in.vi_read(0,0);
+ if (0!=pclose(p)) Error::sev(Error::EERROR) << "Filter::PipeD" << ": pclose() failed; error in external prg" << (Error*)0;
+ } else {
+ #else
+ if (1) {
+ #endif
+ #if !HAVE_system_in_stdlib
+ Error::sev(Error::EERROR) << "Filter::PipeD" << ": no system() on this system" << (Error*)0;
+ #else
+ if (NULLP==(p=fopen(tmpsname(), "wb"))) Error::sev(Error::EERROR) << "Filter::PipeD" << ": fopen(w) failed: " << (SimBuffer::B().appendDumpC(redir_cmd)) << (Error*)0;
+ vi_precopy();
+ in.vi_read(0,0);
+ fclose(p);
+ if (0!=(Files::system3(redir_cmd()))) Error::sev(Error::EERROR) << "Filter::PipeD" << ": system() failed: " << (SimBuffer::B().appendDumpC(redir_cmd)) << (Error*)0;
+ remove(tmpsname());
+ #endif
+ }
+ vi_check();
+ if (NULLP==(p=fopen(tmpname(),"rb"))) Error::sev(Error::EERROR) << "Filter::PipeD" << ": fopen() after pclose() failed: " << tmpname << (Error*)0;
+ state=1;
+ } /* IF state==0 */
+ assert(state==1);
+ if (tolen==0 || 0==(tolen=fread(tobuf, 1, tolen, p))) do_close();
+ // putchar('{'); fwrite(tobuf, 1, tolen, stdout); putchar('}');
+ return tolen;
+}
+void Filter::PipeD::do_close() {
+ fclose(p); p=(FILE*)NULLP;
+ if (tmpname ) remove(tmpname ());
+ if (tmpename) remove(tmpename());
+ if (tmpsname) remove(tmpsname());
+ state=2;
+}
+void Filter::PipeD::vi_precopy() {
+ char *buf0=new char[GENSIO_BUFLEN], *buf;
+ slen_t len, wr;
+ while (0!=(len=in.vi_read(buf0, GENSIO_BUFLEN))) {
+ // printf("[%s]\n", buf0);
+ for (buf=buf0; len!=0; buf+=wr, len-=wr) {
+ wr=fwrite(buf, 1, len>0x4000?0x4000:len, p);
+ if (ferror(p)) {
+ vi_check(); /* Give a chance to report a better error message when Broken File. */
+ Error::sev(Error::EERROR) << "Filter::PipeD" << ": pipe write failed" << (Error*)0;
+ }
+ }
+ }
+ delete [] buf0;
+}
+int Filter::PipeD::vi_getcc() {
+ char ret; int i;
+ // fprintf(stderr,"state=%u\n", state);
+ switch (state) {
+ case 0: return vi_read(&ret, 1)==1 ? (unsigned char)ret : -1;
+ case 1: if (-1==(i=MACRO_GETC(p))) do_close(); return i;
+ /* case: 2: fall-through */
+ }
+ return -1;
+}
+void Filter::PipeD::vi_check() {}
+Filter::PipeD::~PipeD() { if (state!=2) vi_read(0,0); }
+
+Filter::BufR::BufR(GenBuffer const& buf_): bufp(&buf_) {
+ buf_.first_sub(sub);
+}
+int Filter::BufR::vi_getcc() {
+ if (bufp==(GenBuffer const*)NULLP) return -1; /* cast: pacify VC6.0 */
+ if (sub.len==0) {
+ bufp->next_sub(sub);
+ if (sub.len==0) { bufp=(GenBuffer const*)NULLP; return -1; }
+ }
+ sub.len--; return *sub.beg++;
+}
+slen_t Filter::BufR::vi_read(char *to_buf, slen_t max) {
+ if (max==0 || bufp==(GenBuffer const*)NULLP) return 0;
+ if (sub.len==0) {
+ bufp->next_sub(sub);
+ if (sub.len==0) { bufp=(GenBuffer const*)NULLP; return 0; }
+ }
+ if (max<sub.len) {
+ memcpy(to_buf, sub.beg, max);
+ sub.len-=max; sub.beg+=max;
+ return max;
+ }
+ max=sub.len; sub.len=0;
+ memcpy(to_buf, sub.beg, max);
+ return max;
+}
+void Filter::BufR::vi_rewind() { bufp->first_sub(sub); }
+
+Filter::FlatD::FlatD(char const* s_, slen_t slen_): s(s_), sbeg(s_), slen(slen_) {}
+Filter::FlatD::FlatD(char const* s_): s(s_), sbeg(s_), slen(strlen(s_)) {}
+void Filter::FlatD::vi_rewind() { s=sbeg; }
+int Filter::FlatD::vi_getcc() {
+ if (slen==0) return -1;
+ slen--; return *(unsigned char const*)s++;
+}
+slen_t Filter::FlatD::vi_read(char *to_buf, slen_t max) {
+ if (max>slen) max=slen;
+ memcpy(to_buf, s, max);
+ s+=max; slen-=max;
+ return max;
+}
+
+/* --- */
+
+
+#if HAVE_lstat_in_sys_stat
+# define PTS_lstat lstat
+#else
+# define PTS_lstat stat
+#endif
+
+/** @param fname must start with '/' (dir separator)
+ * @return true if file successfully created
+ */
+FILE *Files::try_dir(SimBuffer::B &dir, SimBuffer::B const&fname, char const*s1, char const*s2, char const*open_mode) {
+ if (dir.isEmpty() && s1==(char const*)NULLP) return (FILE*)NULLP;
+ SimBuffer::B full(s1!=(char const*)NULLP?s1:dir(),
+ s1!=(char const*)NULLP?strlen(s1):dir.getLength(),
+ s2!=(char const*)NULLP?s2:"",
+ s2!=(char const*)NULLP?strlen(s2):0, fname(), fname.getLength());
+ full.term0();
+ struct stat st;
+ FILE *f;
+ /* Imp: avoid race conditions with other processes pretending to be us... */
+ if (-1!=PTS_lstat(full(), &st)
+ || (0==(f=fopen(full(), open_mode)))
+ || ferror(f)
+ ) return (FILE*)NULLP;
+ dir=full;
+ return f;
+}
+
+#if OS_COTY==COTY_WIN9X || OS_COTY==COTY_WINNT
+# define DIR_SEP "\\"
+#else
+# define DIR_SEP "/"
+#endif
+
+FILE *Files::open_tmpnam(SimBuffer::B &dir, char const*open_mode, char const*extension) {
+ /* Imp: verify / on Win32... */
+ /* Imp: ensure uniqueness on NFS */
+ /* Imp: short file names */
+ static unsigned PTS_INT32_T counter=0;
+ assert(Error::tmpargv0!=(char const*)NULLP);
+ SimBuffer::B fname(DIR_SEP "tmp_", 5, Error::tmpargv0,strlen(Error::tmpargv0));
+ /* ^^^ Dat: we need DIR_SEP here, because the name of the tmp file may be
+ * passed to Win32 COMMAND.COM, which interprets "/" as a switch
+ */
+ long pid=getpid();
+ if (pid<0 && pid>-(1<<24)) pid=-pid;
+ fname << '_' << pid << '_' << counter++;
+ if (extension) fname << extension;
+ fname.term0();
+ FILE *f=(FILE*)NULLP;
+ // char const* open_mode=binary_p ? "wb" : "w"; /* Dat: "bw" is bad */
+ (void)( ((FILE*)NULLP!=(f=try_dir(dir, fname, 0, 0, open_mode))) ||
+ ((FILE*)NULLP!=(f=try_dir(dir, fname, getenv("TMPDIR"), 0, open_mode))) ||
+ ((FILE*)NULLP!=(f=try_dir(dir, fname, getenv("TMP"), 0, open_mode))) ||
+ ((FILE*)NULLP!=(f=try_dir(dir, fname, getenv("TEMP"), 0, open_mode))) ||
+ ((FILE*)NULLP!=(f=try_dir(dir, fname, PTS_CFG_P_TMPDIR, 0, open_mode))) ||
+ ((FILE*)NULLP!=(f=try_dir(dir, fname, "/tmp", 0, open_mode))) ||
+ ((FILE*)NULLP!=(f=try_dir(dir, fname, getenv("WINBOOTDIR"), "//temp", open_mode))) ||
+ ((FILE*)NULLP!=(f=try_dir(dir, fname, getenv("WINDIR"), "//temp", open_mode))) ||
+ ((FILE*)NULLP!=(f=try_dir(dir, fname, "c:/temp", 0, open_mode))) ||
+ ((FILE*)NULLP!=(f=try_dir(dir, fname, "c:/windows/temp", 0, open_mode))) ||
+ ((FILE*)NULLP!=(f=try_dir(dir, fname, "c:/winnt/temp", 0, open_mode))) ||
+ ((FILE*)NULLP!=(f=try_dir(dir, fname, "c:/tmp", 0, open_mode))) ||
+ ((FILE*)NULLP!=(f=try_dir(dir, fname, ".", 0, open_mode))) ||
+ ((FILE*)NULLP!=(f=try_dir(dir, fname, "..", 0, open_mode))) ||
+ ((FILE*)NULLP!=(f=try_dir(dir, fname, "../..", 0, open_mode))) );
+ return f;
+}
+
+bool Files::find_tmpnam(SimBuffer::B &dir) {
+ FILE *f=open_tmpnam(dir);
+ if (f!=NULL) { fclose(f); return true; }
+ return false;
+}
+
+bool Files::tmpRemove=true;
+
+static int cleanup_remove(Error::Cleanup *cleanup) {
+ if (Files::tmpRemove) {
+ int err = Files::removeIf(cleanup->getBuf());
+ if (err)
+ Error::sev(Error::ERROR_CONT) << "could not remove tmp file: " << cleanup->getBuf() << (Error*)0;
+ return err;
+ }
+ Error::sev(Error::WARNING) << "keeping tmp file: " << cleanup->getBuf() << (Error*)0;
+ return 0;
+}
+
+void Files::tmpRemoveCleanup(char const* filename) {
+ /* Copies the filename array. */
+ Error::newCleanup(cleanup_remove, 0, filename);
+}
+
+static int cleanup_remove_cond(Error::Cleanup *cleanup) {
+ if (*(FILE**)cleanup->data!=NULLP) {
+ fclose(*(FILE**)cleanup->data);
+ return cleanup_remove(cleanup);
+ }
+ return 0;
+}
+
+void Files::tmpRemoveCleanup(char const* filename, FILE**p) {
+ param_assert(p!=NULLP);
+ Error::newCleanup(cleanup_remove_cond, (void*)p, filename);
+}
+
+int Files::removeIf(char const* filename) {
+ if (0==remove(filename) || errno==ENOENT) return 0;
+ return 1;
+}
+
+slen_t Files::statSize(char const* filename) {
+ struct stat st;
+ if (-1==PTS_lstat(filename, &st)) return (slen_t)-1;
+ return st.st_size;
+}
+
+/* Tue Jul 2 10:57:21 CEST 2002 */
+char const* Files::only_fext(char const*filename) {
+ char const *ret;
+ if (OS_COTY==COTY_WINNT || OS_COTY==COTY_WIN9X) {
+ if ((USGE('z'-'a',filename[0]-'a') || USGE('Z'-'A',filename[0]-'A'))
+ && filename[1]==':'
+ ) filename+=2; /* strip drive letter */
+ ret=filename;
+ while (*filename!='\0') {
+ if (*filename=='/' || *filename=='\\') ret=++filename;
+ else filename++;
+ }
+ } else { /* Everything else is treated as UNIX */
+ ret=filename;
+ while (filename[0]!='\0') if (*filename++=='/') ret=filename;
+ }
+ return ret;
+}
+
+#if HAVE_DOS_BINARY
+void Files::set_binary_mode(int fd, bool binary) {
+ /* Wed Dec 11 18:17:30 CET 2002 */
+ setmode(fd, binary ? O_BINARY : O_TEXT);
+}
+#endif
+
+int Files::system3(char const *commands) {
+ #if OS_COTY==COTY_WIN9X || OS_COTY==COTY_WINNT
+ char const *p;
+ p=commands; while (*p!='\0' && *p!='\n') p++;
+ if (*p=='\0') return system(commands); /* no newline -- simple run */
+ SimBuffer::B tmpnam;
+ FILE *f=Files::open_tmpnam(tmpnam, "w", ".bat");
+ tmpnam.term0();
+ Files::tmpRemoveCleanup(tmpnam());
+ fprintf(f, "@echo off\n%s\n", commands);
+ if (ferror(f)) Error::sev(Error::EERROR) << "system3: write to tmp .bat file: " << tmpnam << (Error*)NULLP;
+ fclose(f);
+ // printf("(%s)\n", tmpnam()); system("bash");
+ // int ret=system(("sh "+tmpnam)());
+ int ret=system(tmpnam());
+ remove(tmpnam());
+ return ret;
+ #else
+ return system(commands);
+ #endif
+}
+
+/* __END__ */
diff --git a/graphics/sam2p/gensio.hpp b/graphics/sam2p/gensio.hpp
new file mode 100644
index 0000000000..ee0185c8d5
--- /dev/null
+++ b/graphics/sam2p/gensio.hpp
@@ -0,0 +1,403 @@
+/* gensio.hpp -- generic char buffer and I/O facilities
+ * by pts@fazekas.hu at Tue Feb 26 13:30:02 CET 2002
+ */
+
+#ifdef __GNUC__
+#ifndef __clang__
+#pragma interface
+#endif
+#endif
+
+#ifndef GENSIO_HPP
+#define GENSIO_HPP 1
+
+#include "config2.h"
+#include <stdarg.h> /* va_list */
+#include "gensi.hpp"
+#include <stdio.h>
+
+/* Naming conventions: *Encode is a specific, well-known PostScript or PDF
+ * encoding filter documented by Adobe, *Encoder is something more general.
+ */
+
+/** Writing 0 bytes for vi_write is interpreted as a close() operation.
+ * Constructor must not write anything to the underlying (lower-level)
+ * Encoder. Implementors must redefine vi_write(). Encoders may be stacked
+ * atop of each other.
+ */
+class Encoder: public GenBuffer::Writable { public:
+ /** Default: calls vi_write. */
+ virtual void vi_putcc(char c);
+ /** vi_write() must be called with positive slen_t for normal writing, and
+ * vi_write(?,0); must be called to signal EOF. After that, it is prohibited
+ * to call vi_write() either way.
+ */
+ virtual void vi_write(char const*buf, slen_t len) =0;
+ /** Copies all data (till EOF) from stream `f' to (this). */
+ static void writeFrom(GenBuffer::Writable& out, FILE *f);
+ /** Copies all data (till EOF) from stream `f' to (this). */
+ static void writeFrom(GenBuffer::Writable& out, GenBuffer::Readable &in);
+}; /* class Encoder */
+
+/** Implementors must redefine vi_read(), and they may redefine vi_getcc().
+ * A .vi_read(?,0) has special meaning in a Decoder (but not in a normal
+ * Readable).
+ */
+class Decoder: public GenBuffer::Readable { public:
+ /** Calls vi_read(&ret,1). Note that this is the inverse of
+ * GenBuffer::Readable, because there vi_read() calls vi_getcc(). Decoders
+ * may be stacked atop of each other.
+ */
+ virtual int vi_getcc();
+ /** vi_read() must be called with positive slen_t for normal reading, and
+ * vi_read(?,0); must be called to signal that the caller would not read from
+ * the Decoder again, so the decoder is allowed to release the resources
+ * used. After that, it is prohibited to call vi_read() either way.
+ */
+ virtual slen_t vi_read(char *to_buf, slen_t max) =0;
+}; /* class Decoder */
+
+class DecoderTeller: public Decoder { public:
+ /** Equivalent of ftell() */
+ virtual long vi_tell() const=0;
+};
+
+class Filter { public:
+ /** Starts a child process (with popen(pipe_tmpl,"wb")), pipes data to it,
+ * writes output to a temporary file. After _everything_ is written, the
+ * temporary file is read and fed to out_.
+ */
+ class PipeE: public Encoder {
+ public:
+ PipeE(GenBuffer::Writable &out_, char const*pipe_tmpl, slendiff_t i=0);
+ virtual ~PipeE();
+ virtual void vi_write(char const*buf, slen_t len);
+ protected:
+ FILE *p;
+ SimBuffer::B tmpname;
+ GenBuffer::Writable &out;
+ SimBuffer::B tmpename, redir_cmd;
+ /** Temporary source file name `%S', forces system() instead of popen() */
+ SimBuffer::B tmpsname;
+ /** vi_check() is called by this->vi_write(...) (and also when Broken Pipe)
+ * to check whether the encoding succeeded. vi_check() should raise an Error
+ * if it detects failure or simply return if it detects success. Default
+ * implementation: empty body which simly returns.
+ */
+ virtual void vi_check();
+ protected:
+ /** Copies the rest of (seekable) file `f' to `out' (subsequent filters).
+ * `f' is initially positioned at the beginning. Must call fclose(f).
+ * vi_copy() should raise Error::...s. The default implementation
+ * just copies the data bytes verbatim. `out.vi_write(0,0);' will be called
+ * by vi_write().
+ */
+ virtual void vi_copy(FILE *f);
+ };
+
+ /** Gobbles all data written to it, just like /dev/null */
+ class NullE: public Encoder {
+ public:
+ inline NullE() {}
+ inline virtual ~NullE() {}
+ inline virtual void vi_putcc(char) {}
+ inline virtual void vi_write(char const*, slen_t) {}
+ };
+
+ class VerbatimE: public Encoder {
+ public:
+ inline VerbatimE(GenBuffer::Writable& out_): out(&out_) {}
+ inline virtual void vi_write(char const*buf, slen_t len) { out->vi_write(buf,len); }
+ inline void setOut(GenBuffer::Writable& out_) { out=&out_; }
+ inline GenBuffer::Writable& getOut() const { return *out; }
+ protected:
+ GenBuffer::Writable* out;
+ };
+
+ class VerbatimCountE: public Encoder {
+ public:
+ inline VerbatimCountE(GenBuffer::Writable& out_): out(&out_), count(0) {}
+ inline virtual void vi_write(char const*buf, slen_t len) { out->vi_write(buf,len); count+=len; }
+ inline void setOut(GenBuffer::Writable& out_) { out=&out_; }
+ inline GenBuffer::Writable& getOut() const { return *out; }
+ inline slen_t getCount() const { return count; }
+ protected:
+ GenBuffer::Writable* out;
+ /** Number of bytes already written */
+ slen_t count;
+ };
+
+ class FILEE: public Encoder {
+ public:
+ inline FILEE(FILE *f_,bool closep_): f(f_), closep(closep_) {}
+ FILEE(char const* filename);
+ inline virtual void vi_putcc(char c) { MACRO_PUTC(c,f); }
+ virtual void vi_write(char const*buf, slen_t len);
+ void close();
+ protected:
+ FILE *f;
+ bool closep;
+ };
+
+ class PipeD: public Decoder { public:
+ PipeD(GenBuffer::Readable &in_, char const*pipe_tmpl, slendiff_t i=0);
+ virtual ~PipeD();
+ /** Equivalent to vi_read(&ret,1). */
+ virtual int vi_getcc();
+ /** Upon the first non-zero call, opens `p', calls vi_precopy() and
+ * closes `in'. Upon all non-zero calls,
+ * reads the temporary file with fread(). Upon vi_read(?,0), removes the
+ * the temporary files.
+ */
+ virtual slen_t vi_read(char *to_buf, slen_t max);
+ protected:
+ /** 0: never-read (initial state), 1: vi_precopy() already called, 2: EOF reached, `in' closed */
+ int state;
+ /** opened with popen(?,"w") in state:0->1, then with fopen(?,"rb") in state==1 */
+ FILE *p;
+ /** Temporary destination file name `%D' */
+ SimBuffer::B tmpname;
+ GenBuffer::Readable &in;
+ SimBuffer::B tmpename, redir_cmd;
+ /** Temporary source file name `%S', forces system() instead of popen() */
+ SimBuffer::B tmpsname;
+
+ /** Copies the whole `in' to writable pipe `p'. `p' will be closed by the
+ * caller; in.read(0,0) will be called by the caller.
+ * vi_precopy() should raise Error::...s. The default implementation
+ * just copies the data bytes verbatim.
+ */
+ virtual void vi_precopy();
+ /** vi_check() is called by this->vi_write(...) (and also when Broken Pipe)
+ * to check whether the encoding succeeded. vi_check() should raise an Error
+ * if it detects failure or simply return if it detects success. Default
+ * implementation: empty body which simly returns.
+ */
+ virtual void vi_check();
+ private:
+ void do_close();
+ };
+
+ class VerbatimD: public Decoder {
+ public:
+ inline VerbatimD(GenBuffer::Readable& in_): in(in_) {}
+ /** Works fine even if len==0. */
+ inline virtual slen_t vi_read(char *buf, slen_t len) { return in.vi_read(buf,len); }
+ protected:
+ GenBuffer::Readable& in;
+ };
+
+ class FILED: public DecoderTeller {
+ public:
+ inline FILED(FILE *f_,bool closep_): f(f_), closep(closep_) {}
+ FILED(char const* filename);
+ inline virtual ~FILED() { close(); }
+ inline virtual int vi_getcc() { return MACRO_GETC(f); }
+ virtual slen_t vi_read(char *buf, slen_t len);
+ void close();
+ inline virtual long vi_tell() const { return ftell(f); }
+ protected:
+ FILE *f;
+ bool closep;
+ };
+
+ /**
+ * Sat Apr 19 12:05:49 CEST 2003
+ * Always opens the file in binary mode.
+ * First reads from the unget buffer, then reads from a FILE*. A typical
+ * usage is:
+ * { Filter::UngetFILED f("in.txt"); // fopen("in.txt","rb"), true);
+ * f.getUnget() << "Prepend this in front of first line.\n";
+ * int c;
+ * while ((c=f.vi_getcc()!=-1)) putchar(c);
+ * }
+ */
+ class UngetFILED: public DecoderTeller {
+ public:
+ GenBuffer::Writable& getUnget() { return unget; }
+ BEGIN_STATIC_ENUM(unsigned char, closeMode_t)
+ CM_closep=1,
+ CM_unlinkp=2,
+ CM_keep_stdinp=4, /* CM_unlinkp, but keep STDIN open */
+ CM_seekablep=8, /* it is sure that this->f is seekable */
+ CM_MAX=4
+ END_STATIC_ENUM()
+ inline UngetFILED(FILE *f_, closeMode_t closep_): f(f_), closeMode(closep_), ftell_at(0), ofs(0) {}
+ UngetFILED(char const* filename_, FILE* stdin_f=(FILE*)NULLP, closeMode_t closeMode_=CM_closep);
+ inline virtual ~UngetFILED() { close(); }
+ virtual int vi_getcc();
+ virtual slen_t vi_read(char *buf, slen_t len);
+ /** Appends a line to buf, including delimiter unless EOF.
+ * @param delimiter: a char or negative to read to EOF
+ */
+ void appendLine(GenBuffer::Writable &buf, int delimiter='\n');
+ void close();
+ // void checkFILE();
+ inline virtual long vi_tell() const { return ftell_at; } // return ftell_add+ofs+(f!=NULLP ? ftell(f) : 0); }
+ /**
+ * @return equivalent to getc(f) if this->f is not seekable, but returns
+ * -2 if this->f is seekable.
+ */
+ int getc_seekable();
+ /**
+ * Actively tests whether FILE* is seekable. Doesn't work for regular files
+ * of 0 bytes.
+ */
+ bool isSeekable();
+ /** Reading (this) and reading the returned FILE* will be equivalent
+ * (unless this->getUnget() is used later).
+ * Creates a temporary file if this->unget is not empty.
+ * @param seekable_p if true, the returned FILE* must be seekable. Possibly
+ * creates a temporary file.
+ */
+ FILE* getFILE(bool seekable_p);
+ /** Implies a getFILE() */
+ void seek(long abs_ofs);
+ /** Tries to do an fseek(f, -slen, SEEK_CUR). On failure, appends to unget.
+ * The user should only unread() data obtained from vi_read().
+ */
+ void unread(char const *s, slen_t slen);
+ inline char const* getFilename() const { return filename; }
+ inline char const* getFilenameDefault(char const *def) const { return filename==NULLP ? def : filename; }
+ inline bool hadError() const { return f!=NULLP && ferror(f); }
+ protected:
+ FILE *f;
+ unsigned char closeMode;
+ slen_t ftell_at;
+ slen_t ofs;
+ SimBuffer::B unget;
+ char const* filename;
+ };
+
+ /** Reads from a memory of a GenBuffer via first_sub and next_sub. The
+ * GenBuffer should not be changed during the read. The GenBuffer isn't
+ * delete()d by (this)
+ */
+ class BufR: public GenBuffer::Readable {
+ public:
+ BufR(GenBuffer const& buf_);
+ virtual int vi_getcc();
+ virtual slen_t vi_read(char *to_buf, slen_t max);
+ virtual void vi_rewind();
+ protected:
+ GenBuffer const* bufp;
+ GenBuffer::Sub sub;
+ };
+
+ /** Reads from a consecutive memory area, which won't be
+ * delete()d by (this)
+ */
+ class FlatD: public DecoderTeller /*GenBuffer::Readable*/ {
+ public:
+ FlatD(char const* s_, slen_t slen_);
+ FlatD(char const* s_);
+ virtual int vi_getcc();
+ virtual slen_t vi_read(char *to_buf, slen_t max);
+ virtual void vi_rewind();
+ inline int getcc() { return slen!=0 ? (slen--, *(unsigned char const*)s++) : -1; }
+ inline virtual long vi_tell() const { return s-sbeg; }
+ inline long tell() const { return s-sbeg; }
+ protected:
+ char const *s, *sbeg;
+ slen_t slen;
+ };
+}; /* class Filter */
+
+class Files {
+ public:
+ /** Formerly `class WritableFILE' */
+ class FILEW: public GenBuffer::Writable {
+ public:
+ inline FILEW(FILE *f_): f(f_) {}
+ inline virtual void vi_putcc(char c) { MACRO_PUTC(c,f); }
+ inline virtual void vi_write(char const*buf, slen_t len) { fwrite(buf, 1, len, f); }
+ virtual GenBuffer::Writable& vformat(slen_t n, char const *fmt, va_list ap);
+ /** appends; uses SimBuffer::B as temp */
+ virtual GenBuffer::Writable& vformat(char const *fmt, va_list ap);
+ inline void close() { fclose(f); }
+ inline void setF(FILE *f_) { f=f_; }
+ private:
+ FILE *f;
+ };
+
+ /** Formerly `class ReadableFILE'. Doesn't close the its FILE* automatically. */
+ class FILER: public GenBuffer::Readable {
+ public:
+ inline FILER(FILE *f_): f(f_) {}
+ inline virtual int vi_getcc() { return MACRO_GETC(f); }
+ inline virtual slen_t vi_read(char *to_buf, slen_t max) { return fread(to_buf, 1, max, f); }
+ inline void close() { fclose(f); }
+ inline virtual void vi_rewind() { rewind(f); }
+ private:
+ FILE *f;
+ };
+
+ /** @return the beginning of the last substring in param filename that does
+ * not contain '/' (dir separator)
+ */
+ static char const* only_fext(char const*filename);
+
+ /** true iff temporary files should be removed at program finish end */
+ static bool tmpRemove;
+ /** @param fname must start with '/' (dir separator)
+ * @return true if file successfully created
+ */
+ static FILE *try_dir(SimBuffer::B &dir, SimBuffer::B const&fname, char const*s1, char const*s2, char const*open_mode="wb");
+ /* The file will be opened for writing only. It won't be registered for
+ * for automatic removal.
+ * @param dir `dir' is empty: appends a unique filename for a temporary
+ * file. Otherwise: returns a unique filename in the specified directory.
+ * Creates the new file with 0 size.
+ * @param extension NULLP or a string specifying the extension of the file
+ * to create (should beginn with ".")
+ * @param open_mode "w", "wb" or "wb+"
+ * @return FILE* opened for writing for success, NULLP on failure
+ * --return true on success, false on failure
+ */
+ static FILE *open_tmpnam(SimBuffer::B &dir, char const*open_mode="wb", char const*extension=(char const*)NULLP);
+ // static FILE *open_tmpnam(SimBuffer::B &dir, bool binary_p=true, char const*extension=(char const*)NULLP);
+ static bool find_tmpnam(SimBuffer::B &dir);
+ /** Calls lstat().
+ * @return (slen_t)-1 on error, the size otherwise
+ */
+ static slen_t statSize(char const* filename);
+ /** Ensures that file will be removed (if possible...) when the process
+ * terminates. Makes a copy of the filename array, it won't use filename
+ * after returning.
+ */
+ static void tmpRemoveCleanup(char const* filename);
+ /** Ensures that file will be removed (if possible...) when the process
+ * terminates. Copies the string filename. The file will be removed iff
+ * (*p!=NULLP) when the cleanup handler runs. The cleanup handler fclose()s
+ * the file before removing it.
+ */
+ static void tmpRemoveCleanup(char const* filename, FILE**p);
+ /** Removes the file/entity if exists.
+ * @return 0 on success (file hadn't existed, a directory component
+ * hadn't existed, or the file has been successfully removed),
+ * 1 otherwise
+ */
+ static int removeIf(char const *filename);
+
+ /** Sat Sep 7 20:58:54 CEST 2002 */
+ static void doSignalCleanup();
+
+ /** Set the specified file descriptor to binary mode. Useful for stdin (0),
+ * stdout (1), stderr (2) on Win32 and DOS systems. On these systems, this
+ * call has the effect of `fopen(..., "rb");' On UNIX, file
+ * descriptors are always binary.
+ */
+ #if HAVE_DOS_BINARY
+ static void set_binary_mode(int fd, bool binary);
+ #else
+ static inline void set_binary_mode(int,bool) {}
+ #endif
+
+ /** Like the system(3) call, but it is able to run a string containing
+ * multiple lines of commands. On Win32, it creates a batch file if
+ * necessary.
+ */
+ static int system3(char const *commands);
+};
+
+#endif
diff --git a/graphics/sam2p/helpere.hpp b/graphics/sam2p/helpere.hpp
new file mode 100644
index 0000000000..17c36c044a
--- /dev/null
+++ b/graphics/sam2p/helpere.hpp
@@ -0,0 +1,43 @@
+/*
+ * helpere.hpp -- help encoding images
+ * by pts@fazekas.hu at Tue Dec 9 10:53:21 CET 2003
+ */
+
+/* Don't use this here, because we don't have helpere.cpp
+#ifdef __GNUC__
+#ifndef __clang__
+#pragma interface
+#endif
+#endif
+*/
+
+#ifndef HELPERE_HPP
+#define HELPERE_HPP 1
+
+#include "image.hpp"
+#include "error.hpp"
+#include "gensio.hpp"
+
+/** Ugly multiple inheritance. !! unify with PNG, TIFF etc. */
+class HelperE: public Filter::NullE, public Filter::PipeE {
+ public:
+ inline HelperE(char const*filter_cmd, char const*mainfn=NULL): Filter::NullE(), Filter::PipeE(*(Filter::NullE*)this, filter_cmd, (slendiff_t)mainfn) {
+ /* ^^^ (slendiff_t) is unsafe cast */
+ // GenBuffer::Writable &out_, char *pipe_tmpl, slendiff_t i=0)
+ }
+ inline virtual void vi_copy(FILE *f) {
+ // img=Image::load("-", SimBuffer::B(), (Image::filep_t)f, (char const*)"PNM");
+ Filter::UngetFILED ufd((char const*)NULLP, f, Filter::UngetFILED::CM_closep|Filter::UngetFILED::CM_keep_stdinp);
+ img=Image::load((Image::Loader::UFD*)(long)&ufd, SimBuffer::B(), (char const*)"PNM");
+ /* We must close f, this is part of the vi_copy contract. If we fail to
+ * close it, cleanup_remove won't be able to remove the tmp files at
+ * Error::runCleanups() time.
+ */
+ fclose(f);
+ }
+ inline Image::Sampled *getImg() const { return img; }
+ protected:
+ Image::Sampled *img;
+};
+
+#endif
diff --git a/graphics/sam2p/hq.pl b/graphics/sam2p/hq.pl
new file mode 100755
index 0000000000..61728ed0bb
--- /dev/null
+++ b/graphics/sam2p/hq.pl
@@ -0,0 +1,33 @@
+#! /bin/sh --
+eval '(exit $?0)' && eval 'PERL_BADLANG=x;export PERL_BADLANG;: \
+;exec perl -x -S -- "$0" ${1+"$@"};#'if 0;
+eval 'setenv PERL_BADLANG x;exec perl -x -S -- "$0" $argv:q;#'.q
+#!perl -w
++($0=~/(.*)/s);do$1;die$@if$@;__END__+if 0;
+# Don't touch/remove lines 1--7: http://www.inf.bme.hu/~pts/Magic.Perl.Header
+
+#
+# hq.pl -- convert binary STDIN to C language "quoted\\-string"
+# by pts@fazekas.hu at Tue Dec 3 17:46:52 CET 2002
+#
+# VC6.0 imposes the following restrictions:
+# -- the number of (destination) characters inside a single "..." block may
+# not exceed 2048
+# -- the number of "..." blocks may not exceed 999 if the /Zm999 compiler
+# option is specified; this number should be minimized
+# -- "\12319" causes a stupid warning, should be emitted as: "\123\51\61"
+# -- output lines should not be too long (I limit them to 79 chars)
+#
+
+my @numenc=('\60','\61','\62','\63','\64','\65','\66','\67','\70','\71');
+my @enc;
+for (my $I=0;$I<256;$I++) { $enc[$I]=sprintf"\\%03o",$I }
+
+binmode STDIN if @ARGV;
+binmode STDOUT; # UNIX NL in output
+while (0<read STDIN, $_, 2040) {
+ s/([^\w\.\/\- ])(\d*)/$enc[ord$1].join("",@numenc[split"",$2])/ge;
+ s/(.{74}[^\\]{0,3})/$1\\\n/gs;
+ # ^^^ Dat: [^\\]{0,3} is for ensuring not breaking a \\
+ print "\"$_\"\n";
+}
diff --git a/graphics/sam2p/image.cpp b/graphics/sam2p/image.cpp
new file mode 100644
index 0000000000..2e3a3c00c7
--- /dev/null
+++ b/graphics/sam2p/image.cpp
@@ -0,0 +1,1922 @@
+/*
+ * image.cpp (formerly sampled.cpp)
+ * by pts@fazekas.hu at Wed Feb 27 09:26:05 CET 2002
+ */
+
+#ifdef __GNUC__
+#ifndef __clang__
+#pragma implementation
+#endif
+#endif
+
+#include "image.hpp"
+#include "error.hpp"
+#include <string.h> /* strlen() */
+#include "gensio.hpp"
+
+/* --- 4-byte hashing */
+
+#if SIZEOF_INT>=4
+typedef unsigned int u32_t;
+typedef signed int s32_t;
+#else
+typedef unsigned long u32_t;
+typedef signed long s32_t;
+#endif
+
+/* vvv Dat: moved these out of Hash46 to pacify VC6.0 */
+ const unsigned M=1409;
+ /** Number of _value_ data bytes (they are not hashed) */
+ const unsigned D=2;
+ /** Size of each tuple in the array `t' */
+ const unsigned HD=4+D;
+ /** A tuple is considered free iff its first byte equals FREE */
+ const unsigned char FREE=255;
+
+
+/**
+ * M=1409
+ * h(K)=K%1409
+ * h(i,K)=-i*(1+(K%1408)) (i in 0..1408)
+ * K=[a,r,g,b]=(a<<24)+(r<<16)+(g<<8)+b (4 bytes)
+ * h(K)=(253*a+722*r+(g<<8)+b)%1409
+ * h(i,K)=-i*(1+(896*a+768*r+(g<<8)+b)%1408)
+ *
+ * -- No dynamic growing or re-hashing. Useful for hashing colormap palettes
+ * with a maximum size of 256.
+ * -- Deleting not supported.
+ *
+ * Implementation: Use 32 bit integers for calculation.
+ *
+ * Imp: remove unused attr `size'
+ */
+class Hash46 {
+ public:
+ /** Creates an empty hash. */
+ Hash46();
+ inline unsigned getSize() const { return size; }
+ inline unsigned getLength() const { return size; }
+ inline unsigned getMaxSize() const { return M; }
+ inline bool isFull() const { return size==M; }
+ /** @return NULLP or the pointer to a tuple */
+ inline unsigned char* lookup(unsigned char k[4]) {
+ unsigned char *ret=walk(k);
+ return ret==NULLP || *ret==FREE ? (unsigned char*)NULLP : ret;
+ }
+ /** Can be called only if !isFull()
+ * @return NULL if isFull() and not found; otherwise: pointer to the tuple
+ * found or the place to which the insert can take place.
+ */
+ unsigned char* walk(unsigned char k[4]);
+ protected:
+ /** Number of non-free tuples in the hash. */
+ unsigned size;
+ unsigned char t[M*HD];
+};
+
+Hash46::Hash46(): size(0) {
+ memset(t, FREE, sizeof(t));
+}
+
+unsigned char *Hash46::walk(unsigned char k[4]) {
+ u32_t hk, hik;
+ hk=HD*(((((u32_t)1<<24)%M)*k[0]+(((u32_t)1<<16)%M)*k[1]+
+ (((u32_t)1<< 8)%M)*k[2]+k[3])%M);
+ hik=HD*(1+((((u32_t)1<<24)%(M-1))*k[0]+(((u32_t)1<<16)%(M-1))*k[1]+
+ (((u32_t)1<< 8)%(M-1))*k[2]+k[3])%(M-1));
+ /* fprintf(stderr, "hk=%u hik=%u\n", hk, hik); */
+ register unsigned char *p=t+hk;
+ unsigned i=M;
+ /* fprintf(stderr, "?? %02x %02x %02x %02x\n", k[0], k[1], k[2], k[3]); */
+ do {
+ /* fprintf(stderr, "examining %02x %02x %02x %02x %d\n", p[0], p[1], p[2], p[3], (k[0]=p[0] && k[1]==p[1] && k[2]==p[2])); */
+ if (*p==FREE || (k[0]==p[0] && k[1]==p[1] && k[2]==p[2] && k[3]==p[3])) return p;
+ /* ^^^ huge == BUGFIX at Sun Apr 14 00:16:59 CEST 2002 */
+ if (hk>=hik) { hk-=hik; p-=hik; }
+ else { hk+=M*HD-hik; p+=M*HD-hik; }
+ } while (--i!=0);
+ /* fprintf(stderr, "full\n"); */
+ return (unsigned char*)NULLP;
+}
+
+/* --- */
+
+const unsigned char Image::Sampled::cs2cpp[6]= { 0, 1, 3, 3, 4, 4 };
+char const *Image::Sampled::cs2devcs(unsigned char cs) {
+ static const char *names[]={ (char*)NULLP, "Gray", "RGB", "RGB", "CMYK", "CMYK" };
+ return cs>=1 && cs<=5 ? names[cs] : (char*)NULLP;
+}
+
+static void fatal_image_too_large() {
+ Error::sev(Error::EERROR) << "Image: Image too large." << (Error*)0;
+}
+
+static slen_t multiply_check(slen_t a, slen_t b) {
+ const slen_t result = a * b;
+ /* Check for overflow. Works only if everything is unsigned. */
+ if (result / a != b) fatal_image_too_large();
+ return result;
+}
+
+static slen_t multiply_check(slen_t a, slen_t b, slen_t c) {
+ return multiply_check(multiply_check(a, b), c);
+}
+
+static slen_t add_check(slen_t a, slen_t b) {
+ /* Check for overflow. Works only if everything is unsigned. */
+ if (b > (slen_t)-1 - a) fatal_image_too_large();
+ return a + b;
+}
+
+#if 0
+static slen_t add_check(slen_t a, slen_t b, slen_t c) {
+ return add_check(add_check(a, b), c);
+}
+#endif
+
+static slen_t add_check(slen_t a, slen_t b, slen_t c, slen_t d) {
+ return add_check(add_check(a, b), add_check(c, d));
+}
+
+void Image::Sampled::init(slen_t l_comment, slen_t l_header, dimen_t wd_, dimen_t ht_,
+ /* ^^^ 24 is required for /Transparent in out_tiff_work */
+ unsigned char bpc_, unsigned char ty_, unsigned char cpp_) {
+ /* Even if we continue from here, most probably we'll reach
+ * ``sam2p.yes: Error: applyProfile: invalid combination, no applicable OutputRule''.
+ * So more work is needed to support output images of size 0.
+ */
+ if (wd_ <= 0 || ht_ <= 0) Error::sev(Error::EERROR) << "Image: Image of size 0." << (Error*)0;
+ bpc=bpc_;
+ ty=ty_;
+ wd=wd_;
+ ht=ht_;
+ cpp=cpp_;
+ // pred=1;
+ transpc=0x1000000UL; /* Dat: this means: no transparent color */
+ const slen_t rlens = add_check(multiply_check(bpc_, cpp_, wd_), 7) >> 3;
+ rlen = rlens;
+ if (rlen != rlens) fatal_image_too_large();
+ beg=new char[len=add_check(l_comment, l_header, multiply_check(rlen, ht_), bpc)];
+ rowbeg=(headp=const_cast<char*>(beg)+l_comment)+l_header;
+ trail=const_cast<char*>(beg)+len-bpc;
+ memset(trail, 0, bpc);
+}
+
+Image::Gray* Image::Sampled::toGray0(unsigned char bpc_) {
+ unsigned char *crow=new unsigned char[wd*3+7*3], *p, *pend;
+ Image::Gray *img=new Image::Gray(wd, ht, bpc_);
+ unsigned char *outp=(unsigned char*)img->getRowbeg();
+ dimen_t htc;
+ memset(crow+wd*3, '\0', 7*3); /* *3 BUGFIX at Tue Jan 18 17:04:15 CET 2005 */
+ unsigned i;
+ /* Dat: not optimising for minimal rounding error since caller should ensure
+ * that there is no such error at all.
+ */
+ if (bpc_==1) {
+ assert(img->getBpc()==1);
+ for (htc=0;htc<ht;htc++) {
+ copyRGBRow((char*)crow, htc);
+ for (p=crow-3,pend=p+wd*3; p<pend; ) {
+ i =(*(p+=3)!=0)<<7; i|=(*(p+=3)!=0)<<6; i|=(*(p+=3)!=0)<<5; i|=(*(p+=3)!=0)<<4;
+ i|=(*(p+=3)!=0)<<3; i|=(*(p+=3)!=0)<<2; i|=(*(p+=3)!=0)<<1; i|=(*(p+=3)!=0);
+ *outp++=i;
+ }
+ }
+ } else if (bpc_==2) {
+ for (htc=0;htc<ht;htc++) {
+ copyRGBRow((char*)crow, htc);
+ for (p=crow-3,pend=p+wd*3; p<pend; ) {
+ i =(*(p+=3)/85)<<6; i|=(*(p+=3)/85)<<4; i|=(*(p+=3)/85)<<2; i|=(*(p+=3)/85);
+ *outp++=i;
+ }
+ }
+ } else if (bpc_==4) {
+ for (htc=0;htc<ht;htc++) {
+ copyRGBRow((char*)crow, htc);
+ for (p=crow-3,pend=p+wd*3; p<pend; ) {
+ i =(*(p+=3)/17)<<4; i|=(*(p+=3)/17);
+ *outp++=i;
+ }
+ }
+ } else if (bpc_==8) {
+ for (htc=0;htc<ht;htc++) {
+ copyRGBRow((char*)crow, htc);
+ for (p=crow-3,pend=p+wd*3; p!=pend; ) {
+ *outp++=*(p+=3);
+ }
+ }
+ } else assert(0);
+ delete [] crow;
+ return img;
+}
+Image::RGB* Image::Sampled::toRGB0(unsigned char bpc_) {
+ unsigned char *crow=new unsigned char[wd*3+7], *p, *pend;
+ Image::RGB *img=new Image::RGB(wd, ht, bpc_);
+ unsigned char *outp=(unsigned char*)img->getRowbeg();
+ dimen_t htc;
+ memset(crow+wd*3, '\0', 7);
+ unsigned i;
+ /* Dat: not optimising for minimal rounding error since caller should ensure
+ * that there is no such error at all.
+ */
+ if (bpc_==1) {
+ for (htc=0;htc<ht;htc++) {
+ copyRGBRow((char*)crow, htc);
+ for (p=crow,pend=crow+wd*3; p<pend; ) {
+ i =(*p++!=0)<<7; i|=(*p++!=0)<<6; i|=(*p++!=0)<<5; i|=(*p++!=0)<<4;
+ i|=(*p++!=0)<<3; i|=(*p++!=0)<<2; i|=(*p++!=0)<<1; i|=(*p++!=0);
+ *outp++=i;
+ }
+ }
+ } else if (bpc_==2) {
+ for (htc=0;htc<ht;htc++) {
+ copyRGBRow((char*)crow, htc);
+ for (p=crow,pend=crow+wd*3; p<pend; ) {
+ i =(*p++/85)<<6; i|=(*p++/85)<<4; i|=(*p++/85)<<2; i|=(*p++/85);
+ *outp++=i;
+ }
+ }
+ } else if (bpc_==4) {
+ for (htc=0;htc<ht;htc++) {
+ copyRGBRow((char*)crow, htc);
+ for (p=crow,pend=crow+wd*3; p<pend; ) {
+ i =(*p++/17)<<4; i|=(*p++/17);
+ *outp++=i;
+ }
+ }
+ } else if (bpc_==8) {
+ for (htc=0;htc<ht;htc++) {
+ copyRGBRow((char*)outp, htc);
+ outp+=wd*3;
+ }
+ } else assert(0);
+ delete [] crow;
+ return img;
+}
+
+Image::Indexed* Image::Sampled::toIndexed0()/* const*/ {
+ unsigned char *crow=new unsigned char[wd*3], k[6], *p, *pend, *w;
+ Image::Indexed *img=new Image::Indexed(wd, ht, 256, 8);
+ dimen_t htc;
+ unsigned char *pal=(unsigned char*)img->getHeadp(), *outp=(unsigned char*)img->getRowbeg();
+ unsigned ncols=0;
+ Hash46 h;
+ k[0]=0;
+ for (htc=0;htc<ht;htc++) {
+ copyRGBRow((char*)crow, htc);
+ for (p=crow,pend=crow+wd*3; p!=pend; p+=3) {
+ memcpy(k+1, p, 3);
+ w=h.walk(k);
+ assert(w!=NULL); /* Hash cannot be full since h.M>=256. */
+ /* fprintf(stderr, "w=%p\n", w); */
+ if (*w==/*h.*/FREE) {
+ if (ncols==256) { delete img; delete [] crow; return (Image::Indexed*)NULLP; }
+ /* ^^^ too many colors; cannot convert image to indexed */
+ memcpy(w,k,4);
+ memcpy(pal,k+1,3);
+ /* fprintf(stderr,"newcol=%02x #%02x%02x%02x\n", k[0], k[1], k[2], k[3]); */
+ /* fprintf(stderr,"newcol=pal #%02x%02x%02x\n", pal[0], pal[1], pal[2]); */
+ pal+=3;
+ *outp++=w[4]=ncols++;
+ } else { /* a color that we have already seen */
+ *outp++=w[4];
+ }
+ }
+ }
+ img->setNcolsMove(ncols);
+ delete [] crow;
+
+ /* Now img is ready. The user should call packPal() to make it even tighter. */
+ return img;
+}
+
+void Image::Sampled::to8mul() {
+ if (bpc==8) return;
+ if (wd==0 || ht==0) { bpc=8; return; }
+
+ unsigned oldBpc=bpc;
+ slen_t wdcpp=wd*cpp;
+ const char *oldBeg=beg;
+ unsigned char *p=(unsigned char*)rowbeg;
+
+ bpc=8;
+ rlen=wd;
+ beg=new char[len=rowbeg-oldBeg+rlen*ht+bpc];
+ headp= const_cast<char*>(beg)+(headp-oldBeg);
+ rowbeg=const_cast<char*>(beg)+(rowbeg-oldBeg);
+ trail= const_cast<char*>(beg)+len-bpc;
+ memcpy(const_cast<char*>(beg), oldBeg, rowbeg-beg);
+
+ unsigned char *to=(unsigned char*)rowbeg, *toend;
+ unsigned int i, j;
+ Image::Sampled::dimen_t htc;
+ if (oldBpc==1) {
+ htc=ht; while (htc--!=0) {
+ toend=to+((wdcpp)&~7);
+ while (to!=toend) {
+ i=*p++;
+ *to++=(i>>7)*255;
+ *to++=((i>>6)&1)*255;
+ *to++=((i>>5)&1)*255;
+ *to++=((i>>4)&1)*255;
+ *to++=((i>>3)&1)*255;
+ *to++=((i>>2)&1)*255;
+ *to++=((i>>1)&1)*255;
+ *to++=( i&1)*255;
+ }
+ if (0!=(j=(wdcpp)&7)) {
+ i=*p; /* No mem overrun, even if (wd&7)==0 */
+ while (j--!=0) { *to++=(i>>7)*255; i<<=1; }
+ }
+ }
+ } else if (oldBpc==2) {
+ htc=ht; while (htc--!=0) {
+ toend=to+((wdcpp)&~3);
+ while (to!=toend) {
+ i=*p++;
+ *to++=(i>>6)*85;
+ *to++=((i>>4)&3)*85;
+ *to++=((i>>2)&3)*85;
+ *to++=( i&3)*85;
+ }
+ if (0!=(j=(wdcpp)&3)) {
+ i=*p; /* No mem overrun, even if (wd&7)==0 */
+ while (j--!=0) { *to++=(i>>6)*85; i<<=2; }
+ }
+ }
+ } else if (oldBpc==4) {
+ htc=ht; while (htc--!=0) {
+ toend=to+((wdcpp)&~1);
+ while (to!=toend) {
+ i=*p++;
+ *to++=(i>>4)*17;
+ *to++=( i&15)*17;
+ }
+ if (0!=((wdcpp)&1)) *to++=(*p++>>4)*17;
+ }
+ } else assert(0 && "invalid bpc");
+
+ delete [] const_cast<char*>(oldBeg);
+}
+
+void Image::Sampled::to8nomul() {
+ if (bpc==8) return;
+ if (wd==0 || ht==0) { bpc=8; return; }
+
+ unsigned oldBpc=bpc;
+ slen_t wdcpp=wd*cpp;
+ const char *oldBeg=beg;
+ unsigned char *p=(unsigned char*)rowbeg;
+
+ bpc=8;
+ rlen=wd;
+ beg=new char[len=rowbeg-oldBeg+rlen*ht+bpc];
+ headp= const_cast<char*>(beg)+(headp-oldBeg);
+ rowbeg=const_cast<char*>(beg)+(rowbeg-oldBeg);
+ trail= const_cast<char*>(beg)+len-bpc;
+ memcpy(const_cast<char*>(beg), oldBeg, rowbeg-beg);
+
+ unsigned char *to=(unsigned char*)rowbeg, *toend;
+ unsigned int i, j;
+ Image::Sampled::dimen_t htc;
+ if (oldBpc==1) {
+ htc=ht; while (htc--!=0) {
+ toend=to+((wdcpp)&~7);
+ while (to!=toend) {
+ i=*p++;
+ *to++=(i>>7);
+ *to++=((i>>6)&1);
+ *to++=((i>>5)&1);
+ *to++=((i>>4)&1);
+ *to++=((i>>3)&1);
+ *to++=((i>>2)&1);
+ *to++=((i>>1)&1);
+ *to++=( i&1);
+ }
+ if (0!=(j=(wdcpp)&7)) {
+ i=*p++; /* No mem overrun, even if (wd&7)==0 */
+ while (j--!=0) { *to++=(i>>7); i<<=1; }
+ }
+ }
+ } else if (oldBpc==2) {
+ // assert(0);
+ htc=ht; while (htc--!=0) {
+ toend=to+((wdcpp)&~3);
+ while (to!=toend) {
+ i=*p++;
+ *to++=(i>>6);
+ *to++=((i>>4)&3);
+ *to++=((i>>2)&3);
+ *to++=( i&3);
+ }
+ if (0!=(j=(wdcpp)&3)) {
+ i=*p++;
+ // fprintf(stderr,"j=%d\n",j);
+ while (j--!=0) { *to++=(i>>6); i<<=2; }
+ }
+ }
+ assert((slen_t)((char*)to-rowbeg)==(slen_t)wd*cpp*ht);
+ } else if (oldBpc==4) {
+ htc=ht; while (htc--!=0) {
+ toend=to+((wdcpp)&~1);
+ while (to!=toend) {
+ i=*p++;
+ *to++=(i>>4);
+ *to++=( i&15);
+ }
+ if (0!=((wdcpp)&1)) *to++=(*p++>>4);
+ }
+ } else assert(0 && "invalid bpc");
+
+ delete [] const_cast<char*>(oldBeg);
+}
+
+unsigned char Image::Sampled::minRGBBpc() const {
+ unsigned char *crow=new unsigned char[wd*3], *p, *pend=crow+wd*3;
+ register unsigned minbpb=0;
+ dimen_t htc;
+ for (htc=0;htc<ht;htc++) {
+ copyRGBRow((char*)crow, htc);
+ for (p=crow; p!=pend; p++) {
+ if ((*p&15)*17!=*p) { delete [] crow; return 8; } /* 4 bits are not enough */
+ else if ((*p&3)*85!=*p) minbpb=3; /* 2 bits are not enough */
+ else if ((*p&1)*255!=*p) minbpb|=1; /* 1 bit is not enough */
+ }
+ }
+ delete [] crow;
+ return 1+minbpb;
+}
+
+bool Image::Sampled::hasPixelRGB(Image::Sampled::rgb_t rgb) const {
+ /* by pts@fazekas.hu at Sat Jan 8 13:24:19 CET 2005 */
+ /* Dat: this dumb implementation will be overridden */
+ if (rgb>0xffffffUL) return false;
+ unsigned char *crow=new unsigned char[wd*3], *p, *pend=crow+wd*3, t[3];
+ dimen_t htc;
+ t[0]=(rgb>>16)&255; t[1]=(rgb>>8)&255; t[2]=rgb&255;
+ for (htc=0;htc<ht;htc++) {
+ copyRGBRow((char*)crow, htc);
+ for (p=crow; p!=pend; p+=3) {
+ if (t[0]==p[0] && t[1]==p[1] && t[2]==p[2]) { delete [] crow; return true; }
+ }
+ }
+ delete [] crow;
+ return false;
+}
+
+bool Image::Gray::hasPixelRGB(Image::Sampled::rgb_t rgb) const {
+ /* by pts@fazekas.hu at Sat Jan 8 13:24:19 CET 2005 */
+ /* Dat: faster than Image::Sampled::hasPixelRGB */
+ if (rgb>0xffffffUL) return false;
+ unsigned char t[3];
+ t[0]=(rgb>>16)&255; t[1]=(rgb>>8)&255; t[2]=rgb&255;
+ if (t[0]!=t[1] || t[0]!=t[2]) return false;
+ if (bpc==8) {
+ unsigned char *p=(unsigned char*)rowbeg, *pend=p+wd*ht;
+ /* Imp: use memchr() if available */
+ while (p!=pend && t[0]!=p[0]) p++;
+ return p!=pend;
+ }
+ unsigned char *crow=new unsigned char[wd*3], *p, *pend=crow+wd*3;
+ dimen_t htc;
+ for (htc=0;htc<ht;htc++) {
+ copyRGBRow((char*)crow, htc); /* Imp: avoid this if bpp==8 */
+ p=crow; while (p!=pend && t[0]!=p[0]) p+=3;
+ if (p!=pend) { delete [] crow; return true; }
+ }
+ delete [] crow;
+ return false;
+}
+
+Image::Indexed* Image::Sampled::addAlpha0(Image::Indexed *iimg, Image::Gray *al) {
+ if (iimg==NULLP) Error::sev(Error::EERROR) << "addAlpha: too many colors, transparency impossible" << (Error*)0;
+ iimg->to8();
+ unsigned ncols;
+ if ((ncols=iimg->getNcols()) == 256) {
+ iimg->packPal(); // TODO: Do a more lightweight palette packing if there are only 2 colors (such as PNG import through PNM).
+ if ((ncols=iimg->getNcols())==256) Error::sev(Error::EERROR) << "addAlpha: too many colors, transparency impossible" << (Error*)0;
+ }
+ iimg->setNcolsMove(ncols+1);
+ /* fprintf(stderr,"old ncols=%u\n", ncols); */
+ iimg->setPal(ncols,0); /* black */
+ iimg->setTransp(ncols);
+ assert(iimg->getRlen()==iimg->getWd());
+ assert(iimg->getWd()==al->getWd());
+ char *p=iimg->getRowbeg(), *pend=p+iimg->getRlen()*iimg->getHt(), *alq=al->getRowbeg();
+ while (p!=pend) {
+ if ((unsigned char)*alq++!=255) *p=ncols; /* make it transparent */
+ p++;
+ }
+ return iimg;
+}
+
+/* --- */
+
+Image::Indexed::Indexed(Image::Sampled::dimen_t wd_, Image::Sampled::dimen_t ht_, unsigned short ncols_, unsigned char bpc_) {
+ param_assert(ncols_<=256);
+ /* vvv Dat: `3' is here for an extra palette entry */
+ init(3,3*ncols_,wd_,ht_,bpc_,TY_INDEXED,1);
+ transp=-1;
+ cs=CS_Indexed_RGB;
+}
+void Image::Indexed::setNcols(unsigned short ncols_) {
+ headp=rowbeg-ncols_*3;
+}
+void Image::Indexed::setNcolsMove(unsigned short ncols_) {
+ param_assert(ncols_<=256);
+ unsigned ncols=getNcols();
+ if (ncols_==ncols) return;
+ if (ncols_<ncols || (slen_t)(headp-beg)>=(ncols_-ncols)*3) {
+ memmove(rowbeg-ncols_*3, headp, (ncols_<ncols ? ncols_ : ncols)*3);
+ /* ^^^ *3 BUGFIX at Sun Apr 14 00:50:34 CEST 2002 */
+ } else { /* Imp: test this routine */
+ /* Tue Jun 11 16:22:52 CEST 2002 */
+ assert(ncols_>ncols);
+ const char *oldBeg=beg, *oldHeadp=headp, *oldRowbeg=rowbeg, *oldEnd=beg+len;
+ slen_t delta=(ncols_-ncols)*3;
+ // substr_grow(headp-oldBeg, ncols*3, ncols_*3); /* no such method */
+ beg=new char[len+delta];
+ headp= const_cast<char*>(beg)+(headp-oldBeg);
+ rowbeg=const_cast<char*>(beg)+(rowbeg-oldBeg)+delta;
+ trail= const_cast<char*>(beg)+(trail-oldBeg)+delta;
+ assert(beg+(headp-oldBeg)==rowbeg-ncols_*3);
+ /* Dat: this->xoffs is left unchanged */
+ memcpy(headp, oldHeadp, oldRowbeg-oldHeadp);
+ memcpy(rowbeg, oldRowbeg, oldEnd-oldRowbeg);
+ delete [] const_cast<char*>(oldBeg);
+ }
+ headp=rowbeg-ncols_*3;
+}
+void Image::Indexed::setPal(unsigned char color, Image::Sampled::rgb_t rgb) {
+ assert(color<(rowbeg-headp)/3);
+ unsigned char *p=(unsigned char*)headp+3*color;
+ *p++=rgb>>16;
+ *p++=rgb>>8;
+ *p=rgb;
+}
+void Image::Indexed::setTransp(unsigned char color) {
+ // param_assert(color>=0); /* always */
+ assert(transp==-1);
+ transp=color;
+ unsigned char *p=(unsigned char*)headp+3*color;
+ transpc=((Image::Sampled::rgb_t)p[0]<<16)+(p[1]<<8)+p[2];
+}
+
+bool Image::Indexed::setTranspc(rgb_t color) {
+ if (color!=0x1000000UL && color!=transpc) {
+ char t[3];
+ t[0]=color>>16; t[1]=color>>8; t[2]=color;
+ char *p=headp, *pend=rowbeg;
+ while (p!=pend) { /* Examine the palette. */
+ if (p[0]==t[0] && p[1]==t[1] && p[2]==t[2]) {
+ transpc=color;
+ transp=(p-headp)/3; /* destroy old transparency */
+ }
+ p+=3;
+ }
+ }
+ return transp!=-1;
+}
+
+bool Image::Indexed::wouldSetTranspc(rgb_t color) const {
+ if (transp!=-1) return true;
+ if (color!=0x1000000UL && color!=transpc) {
+ char t[3];
+ t[0]=color>>16; t[1]=color>>8; t[2]=color;
+ char *p=headp, *pend=rowbeg;
+ while (p!=pend) { /* Examine the palette. */
+ if (p[0]==t[0] && p[1]==t[1] && p[2]==t[2]) return true;
+ p+=3;
+ }
+ }
+ return false;
+}
+
+void Image::Indexed::setTranspcAndRepack(rgb_t color) {
+ if (!(color!=0x1000000UL && color!=transpc)) return;
+ char t[3];
+ t[0]=color>>16; t[1]=color>>8; t[2]=color;
+ char *p=headp, *pend=rowbeg;
+ bool need_repack = false;
+ while (p!=pend) { /* Examine the palette. */
+ if (p[0]==t[0] && p[1]==t[1] && p[2]==t[2]) {
+ transpc=color;
+ transp=(p-headp)/3; /* destroy old transparency */
+ need_repack = true;
+ }
+ p+=3;
+ }
+ if (need_repack) {
+ const unsigned char old_bpc = bpc;
+ packPal(); /* May change bpc. */
+ setBpc(old_bpc);
+ }
+}
+
+void Image::Indexed::to8() { to8nomul(); }
+Image::Indexed* Image::Indexed::toIndexed()/* const*/ { return this; }
+Image::RGB* Image::Indexed::toRGB(unsigned char bpc_)/* const*/ { return toRGB0(bpc_); }
+Image::Gray* Image::Indexed::toGray(unsigned char bpc_)/* const*/ { return toGray0(bpc_); }
+bool Image::Indexed::canGray() const {
+ char *p=headp, *pend=rowbeg, *tp=p+transp*3;
+ /* ignore transparent color at Sat Jun 15 15:18:24 CEST 2002 */
+ if (transp!=-1 && tp!=pend-3) {
+ while (p!=pend) { /* Examine the palette. */
+ if (p!=tp && (p[0]!=p[1] || p[1]!=p[2])) return false; /* Found a non-gray color. */
+ p+=3;
+ }
+ } else {
+ if (transp!=-1 && tp==pend-3) pend-=3; /* both conditions are important */
+ while (p!=pend) { /* Examine the palette. */
+ if (p[0]!=p[1] || p[1]!=p[2]) return false; /* Found a non-gray color. */
+ p+=3;
+ }
+ }
+ return true;
+}
+unsigned char Image::Indexed::minRGBBpc() const {
+ unsigned char *p=(unsigned char*)headp, *pend=(unsigned char*)rowbeg;
+ unsigned char *tp=p+transp*3;
+ /* ignore transparent color at Sat Jun 15 15:18:24 CEST 2002 */
+ register unsigned minbpb=0;
+ while (p!=pend) { /* Examine the palette. */
+ if (p==tp) { p+=3; continue; } /* ignore transparent color */
+ if ((*p&15)*17!=*p) return 8; /* 4 bits are not enough */
+ else if ((*p&3)*85!=*p) minbpb=3; /* 2 bits are not enough */
+ else if ((*p&1)*255!=*p) minbpb|=1; /* 1 bit is not enough */
+ p++;
+ }
+ return 1+minbpb;
+}
+void Image::Indexed::copyRGBRow(char *to, Image::Sampled::dimen_t whichrow) const {
+ param_assert(whichrow<ht);
+ if (wd==0) return;
+ unsigned char *p=(unsigned char*)rowbeg+rlen*whichrow;
+ char *r, *toend=to+3*wd;
+ unsigned int i, j;
+
+ if (bpc==1) {
+ toend-=3*(wd&7);
+ while (to!=toend) {
+ i=*p++;
+ r=headp+3*(i>>7); *to++=*r++; *to++=*r++; *to++=*r++;
+ r=headp+3*((i>>6)&1); *to++=*r++; *to++=*r++; *to++=*r++;
+ r=headp+3*((i>>5)&1); *to++=*r++; *to++=*r++; *to++=*r++;
+ r=headp+3*((i>>4)&1); *to++=*r++; *to++=*r++; *to++=*r++;
+ r=headp+3*((i>>3)&1); *to++=*r++; *to++=*r++; *to++=*r++;
+ r=headp+3*((i>>2)&1); *to++=*r++; *to++=*r++; *to++=*r++;
+ r=headp+3*((i>>1)&1); *to++=*r++; *to++=*r++; *to++=*r++;
+ r=headp+3*( i&1); *to++=*r++; *to++=*r++; *to++=*r++;
+ }
+ i=*p; /* No mem overrun, even if (wd&7)==0 */
+ j=wd&7;
+ while (j--!=0) { r=headp+3*(i>>7); *to++=*r++; *to++=*r++; *to++=*r++; i<<=1; }
+ } else if (bpc==2) {
+ toend-=3*(wd&3);
+ while (to!=toend) {
+ i=*p++;
+ r=headp+3*(i>>6); *to++=*r++; *to++=*r++; *to++=*r++;
+ r=headp+3*((i>>4)&3); *to++=*r++; *to++=*r++; *to++=*r++;
+ r=headp+3*((i>>2)&3); *to++=*r++; *to++=*r++; *to++=*r++;
+ r=headp+3*( i&3); *to++=*r++; *to++=*r++; *to++=*r++;
+ }
+ i=*p; /* No mem overrun, even if (wd&7)==0 */
+ j=wd&3;
+ while (j--!=0) { r=headp+3*(i>>6); *to++=*r++; *to++=*r++; *to++=*r++; i<<=2; }
+ } else if (bpc==4) {
+ toend-=3*(wd&1);
+ while (to!=toend) {
+ i=*p++;
+ r=headp+3*(i>>4); *to++=*r++; *to++=*r++; *to++=*r++;
+ r=headp+3*( i&15); *to++=*r++; *to++=*r++; *to++=*r++;
+ }
+ if (0!=(wd&1)) { r=headp+3*(*p>>4); *to++=*r++; *to++=*r++; *to++=*r++; }
+ } else if (bpc==8) {
+ // fprintf(stderr, "p=%u pp=%u ppp=%u\n", p[0], p[1], p[2]);
+ while (to!=toend) {
+ r=headp+3**p++; *to++=*r++; *to++=*r++; *to++=*r++;
+ }
+ } else assert(0 && "invalid bpc");
+}
+void Image::Indexed::packPal() {
+ /* Convert samples, make bpc=8. */
+ to8();
+
+ unsigned oldNcols=getNcols();
+ unsigned char *p, *pend;
+ assert((rowbeg-headp)%3==0);
+ assert(transp>=-1);
+ assert(transp<(int)oldNcols);
+ if (oldNcols<=1) return; /* Cannot optimize further. */
+
+ /* Find unused colors. old2new[c]=(is c used at least once)?1:0 */
+ unsigned char old2new[256], newpal[768];
+ memset(old2new, 0, sizeof(old2new));
+ for (p=(unsigned char*)rowbeg, pend=p+wd*ht; p!=pend; p++) old2new[*p]=1;
+
+ /* Find and eliminate duplicate colors. Build the new palette in the
+ * beginning of newpal. Use a Hash46 for a quick lookup of colors already
+ * seen. Use the previously computed old2new, but also overwrite it.
+ */
+ Hash46 h;
+ int newTransp=-1;
+ unsigned char *op=old2new, *opend=op+oldNcols, *w, k[6],
+ *ptransp=(unsigned char*)headp+3*transp; /* ==p-3 if no transparent color */
+ /* ^^^ headp BUGFIX at Fri Mar 22 18:02:18 CET 2002 */
+ p=(unsigned char*)headp;
+ // fprintf(stderr, "oldNcols=%d\n", (int)oldNcols);
+ unsigned newNcols=0;
+ while (op!=opend) {
+ // fprintf(stderr, "color=%d %d\n", (int)(op-old2new), p-ptransp);
+ if (0!=*op) { /* Map the color only if it is used in the image. */
+ // fprintf(stderr, "used=%d\n", (int)(op-old2new));
+ if (p==ptransp) { k[0]=1; k[1]=k[2]=k[3]=0; newTransp=newNcols; }
+ else { k[0]=0; memcpy(k+1,p,3); }
+ w=h.walk(k);
+ assert(w!=NULL); /* Hash cannot be full since h.M>=256. */
+ if (*w==/*h.*/FREE) {
+ memcpy(newpal+3*newNcols, p /* k+1 */, 3);
+ /* ^^^ side effect: make the transparent color black */
+ memcpy(w,k,4); w[4]=newNcols; *op=newNcols++;
+ } else *op=w[4];
+ }
+ p+=3; op++;
+ }
+ // fprintf(stderr,"newTransp=%d transp=%d\n", newTransp, transp);
+
+ // assert((newTransp==-1) == (transp==-1));
+ assert(newTransp==-1 || transp!=-1);
+ /* ^^^ BUGFIX: == not true, because image may have transparency, but no
+ * transparent pixels.
+ */
+ assert((char*)p==headp+oldNcols*3);
+ if (newNcols==oldNcols && transp==newTransp) {
+ /* Could not change # colors. */
+ if (transp==-1) goto done;
+ if ((unsigned)transp==oldNcols-1) { setPal(transp, 0); goto done; }
+ }
+
+ /* Make the transparent color last. */
+ if (newTransp!=-1 && newTransp!=(int)newNcols-1) {
+ assert(transp!=-1);
+ unsigned newLast=newNcols-1;
+ memcpy(newpal+3*newTransp, newpal+3*newLast, 3);
+ memset(newpal+3*newLast, 0, 3); transpc=0; /* make it black */
+ for (op=old2new; op!=opend; op++) if (*op==newLast) *op=newTransp;
+ old2new[transp]=newLast;
+ transp=newTransp=newLast;
+ p=newpal+newTransp*3;
+ }
+
+ /* Update the image. */
+ for (p=(unsigned char*)rowbeg, pend=p+wd*ht; p!=pend; p++) {
+ assert(*p<oldNcols);
+ *p=old2new[*p];
+ }
+
+ /* Update the palette. */
+ headp=rowbeg-3*newNcols; /* public method getNcols() uses rowbeg-headp */
+ memcpy(headp, newpal, 3*newNcols);
+ transp=newTransp;
+ /* vvv BUGFIX at Tue May 21 13:10:30 CEST 2002 */
+ if (newTransp==-1) transpc=0x1000000UL; /* Dat: this means: no transparent color */
+ else { transp=-1; setTransp(newTransp); }
+
+ done:
+ sortPal();
+}
+void Image::Indexed::sortPal() {
+ /* Run packPal() first (but it's recursive!) if transp is in the middle. */
+ unsigned ncols = getNcols(), i;
+ assert(transp == -1 || transp + 0U == ncols - 1);
+ assert(ncols <= 256);
+ if (ncols == 0) return; /* Safe if ncols == 0 and transp == -1. */
+ if (transp + 0U == ncols - 1) --ncols;
+ if (ncols <= 1) return;
+ #if SIZEOF_SHORT>=4
+ typedef unsigned short d_t;
+ #elif SIZEOF_INT>=4
+ typedef unsigned d_t;
+ #else
+ typedef unsigned long d_t;
+ #endif
+ d_t d[256];
+ unsigned char *p, *pend;
+ for (i = 0, p = (unsigned char*)headp; i < ncols; ++i, p += 3) {
+ d[i] = (d_t)p[0] << 24 | (d_t)p[1] << 16 | (d_t)p[2] << 8 | i;
+ /*printf("c[%d]=0x%08x\n", i, d[i]);*/
+ }
+ for (i = 1; i < ncols; ++i) {
+ if (d[i] < d[i - 1]) break;
+ }
+ if (i >= ncols) return; /* Palette already sorted. */
+
+ /* Heap sort (unstable). Based on Knuth's TAOCP 5.2.3.H .
+ * Although heap sort is unstable, sortPal implements a stable sort, because
+ * the color index (i) is included in the sorted number (d[i]).
+ */
+ { unsigned k;
+ d_t tmp, *i, *j, *l=d+(ncols>>1), *r=d+ncols-1;
+ while (1) { /* h2: */
+ k=l-d;
+ if (k!=0) {
+ tmp=*--l;
+ } else {
+ tmp=*r; *r=d[0];
+ if (--r==d) { d[0]=tmp; break; }
+ k++;
+ }
+ i=j=l;
+ while ((j+=k)<=r) { /* h4: */
+ k<<=1;
+ if (j<r && j[0]<j[1]) {
+ if (!(tmp<*++j)) break;
+ k++;
+ } else if (!(tmp<*j)) break;
+ *i=*j; i=j;
+ }
+ /* h8: */
+ *i=tmp;
+ }
+ }
+
+ unsigned char old2new[256];
+ for (i = 0, p = (unsigned char*)headp; i < ncols; ++i) {
+ d_t di = d[i];
+ /*printf("d[%d]=0x%08x\n", i, di);*/
+ assert((i == 0 || di >= d[i - 1]) && "bug in sorting palette");
+ old2new[di & 255] = i;
+ *p++ = di >> 24; *p++ = di >> 16; *p++ = di >> 8;
+ }
+
+ /* Update the image. */
+ for (p=(unsigned char*)rowbeg, pend=p+wd*ht; p!=pend; p++) {
+ *p=old2new[*p];
+ }
+}
+
+void Image::Indexed::delete_separated(register Indexed **p) {
+ while (*p!=NULLP) delete *p++;
+}
+Image::Indexed **Image::Indexed::separate() {
+ assert(getNcols()>=1);
+ unsigned char ncols1=getNcols()-1;
+ signed nncols=getNcols()-(transp==-1 ? 0 : 1);
+ register unsigned char curcol;
+ Indexed **ret=new Indexed*[nncols+1], **curimg=ret;
+ Image::Sampled::dimen_t htc;
+ assert(cpp==1);
+ slen_t wdcpp=wd/* *cpp*/;
+ register unsigned char *p;
+ char *to, *toend;
+ register unsigned int i;
+
+ ret[nncols]=(Indexed*)NULLP;
+ to8();
+ for (curcol=0; curcol<=ncols1; curcol++) {
+ if (transp==(signed int)curcol) continue;
+ curimg[0]=new Indexed(wd, ht, /*ncols:*/2, /*bpc:*/1);
+ memcpy(curimg[0]->headp, headp+3*curcol, 3); /* copy the color value */
+ curimg[0]->setTransp(1);
+ to=curimg[0]->rowbeg; p=(unsigned char*)rowbeg;
+ htc=ht; while (htc--!=0) {
+ toend=to+((wdcpp+7)>>3);
+ while (to!=toend) {
+ i =(*p++!=curcol)<<7; i|=(*p++!=curcol)<<6;
+ i|=(*p++!=curcol)<<5; i|=(*p++!=curcol)<<4;
+ i|=(*p++!=curcol)<<3; i|=(*p++!=curcol)<<2;
+ i|=(*p++!=curcol)<<1; i|=(*p++!=curcol);
+ *to++=i;
+ }
+ if (0!=(wdcpp&7)) p+=(wdcpp&7)-8; /* negative */
+ }
+ curimg++;
+ }
+ assert(curimg==ret+nncols);
+ return ret;
+}
+
+Image::Indexed *Image::Indexed::calcAlpha() {
+ /* by pts@fazekas.hu at Tue Jun 4 21:27:29 CEST 2002 */
+ assert(getNcols()>=1);
+ packPal(); /* removes transparency if no transparent pixel */
+ if (transp==-1) return (Image::Indexed*)NULLP;
+ to8();
+ Indexed *ret=new Indexed(wd, ht, /*ncols:*/2, /*bpc:*/1);
+ Image::Sampled::dimen_t htc;
+ assert(cpp==1);
+ slen_t wdcpp=wd/* *cpp*/;
+ register unsigned char *p;
+ char *to, *toend;
+ register unsigned int i, i8, i7;
+ unsigned char transpx=transp;
+
+ ret->headp[0]=ret->headp[1]=ret->headp[2]='\xFF'; /* white */
+ ret->headp[3]=ret->headp[4]=ret->headp[5]='\x00'; /* black, transparent */
+ ret->setTransp(1);
+ to=ret->rowbeg; p=(unsigned char*)rowbeg;
+ assert(transpx!=0);
+ #if 0
+ printf("tx=%u\n", transpx);
+ printf("%u %u %u\n", headp[0], headp[1], headp[2]);
+ #endif
+ htc=ht; while (htc--!=0) {
+ // putchar('.'); printf("mod=%d\n",(to-ret->rowbeg)%ret->rlen);
+ // assert((to-ret->rowbeg)%ret->rlen==0);
+ toend=to+(wdcpp>>3); /* ((wdcpp+7)>>3)-1; */
+ /* ^^^ BUGFIX at Tue Sep 17 11:08:46 CEST 2002 */
+ assert(toend>=to);
+ while (to!=toend) {
+ #if 1 /* add ->pal[0] funcitonality at Sat Jun 15 14:24:25 CEST 2002 */
+ i=0; i8=256;
+ /* vvv p[-1]=0 BUGFIX at Sun Dec 8 23:21:47 CET 2002 */
+ while ((i8>>=1)!=0) if (*p++==transpx) { p[-1]=0; i|=i8; }
+ #else
+ i =(*p++==transpx)<<7; i|=(*p++==transpx)<<6;
+ i|=(*p++==transpx)<<5; i|=(*p++==transpx)<<4;
+ i|=(*p++==transpx)<<3; i|=(*p++==transpx)<<2;
+ i|=(*p++==transpx)<<1; i|=(*p++==transpx);
+ #endif
+ *to++=i;
+ }
+ #if 1 /* This works even when p gets modified; this puts fixed 0 pads at EOLs */
+ if ((wdcpp&7)!=0) {
+ i7=1<<(7-(wdcpp&7)); i8=256; i=0;
+ /* vvv p[-1]=0 BUGFIX at Sun Dec 8 23:21:47 CET 2002 */
+ while ((i8>>=1)!=i7) if (*p++==transpx) { p[-1]=0; i|=i8; }
+ *to++=i;
+ }
+ #else
+ if (0!=(wdcpp&7)) p+=(wdcpp&7)-8; /* negative */
+ #endif
+ }
+ assert(ret->rlen==((wd+7)>>3));
+ /* printf("rlen=%d %d\n", ret->rlen, to-ret->rowbeg); */
+ assert(to==ret->rowbeg+ht*ret->rlen);
+ return ret;
+}
+
+void Image::Indexed::setBpc(unsigned char bpc_) {
+ unsigned ncols=getNcols();
+ if (bpc_==0) {
+ if (ncols<=2) bpc_=1;
+ else if (ncols<=4) bpc_=2;
+ else if (ncols<=16) bpc_=4;
+ else bpc_=8;
+ } else {
+ if (bpc_==1) assert(ncols<=2);
+ else if (bpc_==2) assert(ncols<=4);
+ else if (bpc_==4) assert(ncols<=16);
+ else if (bpc_!=8) param_assert(0 && "invalid bpc_");
+ }
+ // fprintf(stderr, "bpc: %u -> %u\n", bpc, bpc_);
+ if (bpc==bpc_) return;
+ to8(); /* Imp: make the transition without the intermediate 8-bits... */
+ if (bpc_==8) return;
+ if (ht==0 || wd==0) { bpc=bpc_; return; }
+
+ const char *oldBeg=beg;
+ unsigned char *p=(unsigned char*)rowbeg;
+ assert(cpp==1);
+ slen_t wdcpp=wd/* *cpp*/;
+ bpc=bpc_;
+ rlen=(((rlen_t)bpc_)*wd+7)>>3;
+ beg=new char[len=rowbeg-oldBeg+rlen*ht+bpc];
+ headp= const_cast<char*>(beg)+(headp-oldBeg);
+ rowbeg=const_cast<char*>(beg)+(rowbeg-oldBeg);
+ trail= const_cast<char*>(beg)+len-bpc;
+ memcpy(const_cast<char*>(beg), oldBeg, rowbeg-beg);
+
+ unsigned char *to=(unsigned char*)rowbeg, *toend;
+ unsigned int i;
+ Image::Sampled::dimen_t htc;
+ if (bpc_==1) {
+ // This reads bytes from trail.
+ htc=ht; while (htc--!=0) {
+ toend=to+((wdcpp+7)>>3);
+ while (to!=toend) {
+ i =*p++<<7; i|=*p++<<6; i|=*p++<<5; i|=*p++<<4;
+ i|=*p++<<3; i|=*p++<<2; i|=*p++<<1; i|=*p++;
+ *to++=i;
+ }
+ if (0!=(wdcpp&7)) p+=(wdcpp&7)-8; /* negative */
+ }
+ } else if (bpc_==2) {
+ // This reads bytes from trail.
+ htc=ht; while (htc--!=0) {
+ toend=to+((wdcpp+3)>>2);
+ while (to!=toend) {
+ i =*p++<<6; i|=*p++<<4; i|=*p++<<2; i|=*p++;
+ *to++=i;
+ }
+ if (0!=(wdcpp&3)) p+=(wdcpp&3)-4;
+ }
+ } else if (bpc_==4) {
+ // This reads bytes from trail.
+ htc=ht; while (htc--!=0) {
+ toend=to+((wdcpp+1)>>1);
+ while (to!=toend) {
+ i =*p++<<4; i|=*p++;
+ *to++=i;
+ }
+ if (0!=(wdcpp&1)) p--;
+ }
+ } else assert(0 && "invalid bpc");
+ delete [] const_cast<char*>(oldBeg);
+}
+Image::Sampled::rgb_t Image::Indexed::getPal(unsigned char color) const {
+ unsigned char *p=(unsigned char*)headp+3*color;
+ return ((Image::Sampled::rgb_t)p[0]<<16)+(p[1]<<8)+p[2];
+}
+
+void Image::Indexed::dumpDebug(GenBuffer::Writable& gw) {
+ gw <<"% ncols=" << getNcols()
+ << " rlen=" << rlen
+ << " ht=" << ht
+ << " wd=" << wd
+ << " cpp=" << (unsigned)cpp
+ << " bpc=" << (unsigned)bpc
+ << " transp=" << transp
+ << " transpc=" << (transp==-1?"none":rgb2webhash(getPal(transp)))
+ << " ty=" << (unsigned)ty
+ //<< " pred=" << (unsigned)pred
+ << '\n';
+ unsigned char *p=(unsigned char*)headp;
+ while (p!=(unsigned char*)rowbeg) {
+ gw << rgb2webhash(((Image::Sampled::rgb_t)p[0]<<16)+(p[1]<<8)+p[2]) << '\n';
+ p+=3;
+ }
+ gw << '\n';
+ gw.vi_write(rowbeg,rlen*ht);
+}
+
+Image::Sampled* Image::Indexed::addAlpha(Image::Gray *al) {
+ // Error::sev(Error::WARNING) << "Indexed: alpha channel ignored" << (Error*)0; return this;
+ if (al->getHt()!=ht || al->getWd()!=wd) Error::sev(Error::EERROR) << "addAlpha: image dimension mismatch" << (Error*)0;
+ bool ign_mid=false;
+ unsigned char lightest, darkest;
+ al->to8();
+ al->calcExtrema(lightest, darkest);
+ if (darkest==255) return this; /* no transparent pixels at all */
+ to8();
+ if (transp>=0) { /* Already have a transparent index. Join. */
+ register char *p=rowbeg;
+ register unsigned char transp_=transp;
+ char *pend=rowbeg+rlen*ht, *alq=al->getRowbeg();
+ /* Imp: choose an image color instead of black... */
+ /* Dat: 0..254: transparent, 255: opaque */
+ while (p!=pend) {
+ if ((unsigned char)(*alq+1)>1) ign_mid=true;
+ /* fprintf(stderr,"alq=%u\n", (unsigned char)*alq); */
+ if ((unsigned char)*alq++!=255) p[0]=transp_; /* black out transparent-wannabe pixels */
+ p++;
+ }
+ } else { /* No transparent color yet. */
+ packPal();
+ unsigned ncols=getNcols();
+ char *p=rowbeg, *pend=rowbeg+rlen*ht, *alq=al->getRowbeg();
+ /* Imp: choose an image color instead of black... */
+ /* Dat: 0..254: transparent, 255: opaque */
+ while (p!=pend) {
+ if ((unsigned char)(*alq+1)>1) ign_mid=true;
+ /* fprintf(stderr,"alq=%u\n", (unsigned char)*alq); */
+ if ((unsigned char)*alq++!=255) p[0]=ncols; /* may set to 0 if ncols==256 */
+ p++;
+ }
+ if (ncols==256) { /* Try again, probably now we have fewer colors */
+ packPal();
+ if ((ncols=getNcols())==256) Error::sev(Error::EERROR) << "Indexed::addAlpha: too many colors, transparency impossible" << (Error*)0;
+ for (p=rowbeg,alq=al->getRowbeg(); p!=pend; p++)
+ if ((unsigned char)*alq++!=255) *p=ncols;
+ }
+ setNcolsMove(ncols+1);
+ setPal(ncols,0); /* black */
+ setTransp(ncols);
+ }
+ if (ign_mid) Error::sev(Error::WARNING) << "addAlpha: half-transparent pixels made transparent" << (Error*)0;
+ return this;
+}
+void Image::Indexed::makeTranspZero() {
+ if (transp<1) return; /* no transparency or already 0 */
+ unsigned char oldBpc=bpc;
+ register unsigned char transpch=transp;
+ /* Imp: make this faster by not converting to 8 bits */
+ if (oldBpc!=8) to8();
+
+ /* Update the image. */
+ register unsigned char *p; unsigned char *pend;
+ for (p=(unsigned char*)rowbeg, pend=p+wd*ht; p!=pend; p++) {
+ if (*p==0) *p=transp;
+ else if (*p==transpch) *p=0;
+ }
+ rgb_t rzero=getPal(0), rtransp=getPal(transp);
+ setPal(transp, rzero); setPal(0, rtransp);
+ transp=0;
+ if (oldBpc!=8) setBpc(oldBpc);
+}
+
+/* --- */
+
+Image::Gray::Gray(Image::Sampled::dimen_t wd_, Image::Sampled::dimen_t ht_, unsigned char bpc_) {
+ init(0,0,wd_,ht_,bpc_,TY_GRAY,1);
+ cs=CS_GRAYSCALE;
+}
+void Image::Gray::to8() { to8mul(); }
+Image::RGB * Image::Gray::toRGB(unsigned char bpc_)/* const*/ { return toRGB0(bpc_); }
+Image::Gray* Image::Gray::toGray(unsigned char bpc_)/* const*/ { return bpc==bpc_ ? this : toGray0(bpc_); }
+Image::Indexed* Image::Gray::toIndexed()/* const*/ {
+ Image::Indexed *img=new Image::Indexed(wd, ht, (1<<bpc), bpc);
+ unsigned i;
+ rgb_t rgb;
+ if (bpc==1) {
+ img->setPal(0,0);
+ img->setPal(1,0xffffffL);
+ } else if (bpc==2) {
+ img->setPal(0,0);
+ img->setPal(1,0x555555L);
+ img->setPal(2,0xaaaaaaL);
+ img->setPal(3,0xffffffL);
+ } else if (bpc==4) {
+ for (i=0,rgb=0;i<16;i++,rgb+=(rgb_t)0x111111L) img->setPal(i,rgb);
+ } else if (bpc==8) {
+ for (i=0,rgb=0;i<256;i++,rgb+=(rgb_t)0x010101L) img->setPal(i,rgb);
+ }
+ memcpy(img->getRowbeg(), rowbeg, rlen*ht);
+ return img;
+}
+bool Image::Gray::canGray() const { return true; }
+void Image::Gray::copyRGBRow(char *to, Image::Sampled::dimen_t whichrow) const {
+ param_assert(whichrow<ht);
+ if (wd==0) return;
+ unsigned char *p=(unsigned char*)rowbeg+rlen*whichrow;
+ char *toend=to+3*wd;
+ unsigned int i, j, k;
+
+ if (bpc==1) {
+ toend-=3*(wd&7);
+ while (to!=toend) {
+ i=*p++;
+ k=(i>>7)*255; *to++=k; *to++=k; *to++=k;
+ k=((i>>6)&1)*255; *to++=k; *to++=k; *to++=k;
+ k=((i>>5)&1)*255; *to++=k; *to++=k; *to++=k;
+ k=((i>>4)&1)*255; *to++=k; *to++=k; *to++=k;
+ k=((i>>3)&1)*255; *to++=k; *to++=k; *to++=k;
+ k=((i>>2)&1)*255; *to++=k; *to++=k; *to++=k;
+ k=((i>>1)&1)*255; *to++=k; *to++=k; *to++=k;
+ k=( i&1)*255; *to++=k; *to++=k; *to++=k;
+ }
+ i=*p; /* No mem overrun, even if (wd&7)==0 */
+ j=wd&7;
+ while (j--!=0) { k=(i>>7)*255; *to++=k; *to++=k; *to++=k; i<<=1; }
+ } else if (bpc==2) {
+ toend-=3*(wd&3);
+ while (to!=toend) {
+ i=*p++;
+ k=(i>>6)*85; *to++=k; *to++=k; *to++=k;
+ k=((i>>4)&3)*85; *to++=k; *to++=k; *to++=k;
+ k=((i>>2)&3)*85; *to++=k; *to++=k; *to++=k;
+ k=( i&3)*85; *to++=k; *to++=k; *to++=k;
+ }
+ i=*p; /* No mem overrun, even if (wd&7)==0 */
+ j=wd&3;
+ while (j--!=0) { k=(i>>6)*85; *to++=k; *to++=k; *to++=k; i<<=2; }
+ } else if (bpc==4) {
+ toend-=3*(wd&1);
+ while (to!=toend) {
+ i=*p++;
+ k=(i>>4)*17; *to++=k; *to++=k; *to++=k;
+ k=( i&15)*17; *to++=k; *to++=k; *to++=k;
+ }
+ if (0!=(wd&1)) { k=(*p>>4)*17; *to++=k; *to++=k; *to++=k; }
+ } else if (bpc==8) {
+ while (to!=toend) { *to++=*p; *to++=*p; *to++=*p++; }
+ } else assert(0 && "invalid bpc");
+}
+#if 0
+void Image::Gray::setBpc(unsigned char bpc_) {
+ (void)bpc_;
+ assert(0 && "unimplemented"); /* unimplemented */
+}
+#endif
+
+Image::Sampled* Image::Gray::addAlpha(Image::Gray *al) {
+ // Error::sev(Error::WARNING) << "Gray: alpha channel ignored" << (Error*)0; return this;
+ if (al->getHt()!=ht || al->getWd()!=wd) Error::sev(Error::EERROR) << "addAlpha: image dimension mismatch" << (Error*)0;
+ bool ign_mid=false;
+ unsigned char lightest, darkest;
+ al->to8();
+ al->calcExtrema(lightest, darkest);
+ if (darkest==255) return this; /* no transparent pixels at all */
+ char *p=rowbeg, *pend=rowbeg+rlen*ht, *alq=al->getRowbeg();
+ /* Imp: choose an image color instead of black... */
+ /* Dat: 0..254: transparent, 255: opaque */
+ while (p!=pend) {
+ if ((unsigned char)(*alq+1)>1) ign_mid=true;
+ /* fprintf(stderr,"alq=%u\n", (unsigned char)*alq); */
+ if ((unsigned char)*alq++!=255) *p=0; /* black out transparent-wannabe pixels */
+ p++;
+ }
+ if (ign_mid) Error::sev(Error::WARNING) << "addAlpha: half-transparent pixels made transparent" << (Error*)0;
+ return addAlpha0(toIndexed(), al);
+}
+
+void Image::Gray::calcExtrema(unsigned char &lightest, unsigned char &darkest) {
+ to8();
+ unsigned l=0, d=255, val;
+ char *p=rowbeg, *pend=rowbeg+ht*wd;
+ while (p!=pend) {
+ val=*(unsigned char*)p++;
+ if (val>l) l=val;
+ if (val<d) d=val;
+ }
+ lightest=l; darkest=d;
+}
+
+
+/* --- */
+
+Image::RGB::RGB(Image::Sampled::dimen_t wd_, Image::Sampled::dimen_t ht_, unsigned char bpc_) {
+ init(0,0,wd_,ht_,bpc_,TY_RGB,3);
+ cs=CS_RGB;
+}
+void Image::RGB::to8() { to8mul(); }
+Image::Gray* Image::RGB::toGray(unsigned char bpc_)/* const*/ { return toGray0(bpc_); }
+Image::RGB* Image::RGB::toRGB(unsigned char bpc_)/* const*/ { return bpc==bpc_ ? this : toRGB0(bpc_); }
+Image::Indexed* Image::RGB::toIndexed()/* const*/ { return toIndexed0(); }
+bool Image::RGB::canGray() const { return false; }
+void Image::RGB::copyRGBRow(char *to, Image::Sampled::dimen_t whichrow) const {
+ param_assert(whichrow<ht);
+ if (wd==0) return;
+ unsigned char *p=(unsigned char*)rowbeg+rlen*whichrow;
+ char *toend=to+3*wd;
+ unsigned int i, j, k;
+
+ if (bpc==1) {
+ toend-=(wd*3)&7;
+ while (to!=toend) {
+ i=*p++;
+ k=(i>>7)*255; *to++=k;
+ k=((i>>6)&1)*255; *to++=k;
+ k=((i>>5)&1)*255; *to++=k;
+ k=((i>>4)&1)*255; *to++=k;
+ k=((i>>3)&1)*255; *to++=k;
+ k=((i>>2)&1)*255; *to++=k;
+ k=((i>>1)&1)*255; *to++=k;
+ k=( i&1)*255; *to++=k;
+ }
+ i=*p; /* No mem overrun, even if (wd&7)==0 */
+ j=(wd*3)&7;
+ while (j--!=0) { k=(i>>7)*255; *to++=k; i<<=1; }
+ } else if (bpc==2) {
+ toend-=(wd*3)&3;
+ while (to!=toend) {
+ i=*p++;
+ k=(i>>6)*85; *to++=k;
+ k=((i>>4)&3)*85; *to++=k;
+ k=((i>>2)&3)*85; *to++=k;
+ k=( i&3)*85; *to++=k;
+ }
+ i=*p; /* No mem overrun, even if (wd&7)==0 */
+ j=(wd*3)&3;
+ while (j--!=0) { k=(i>>6)*85; *to++=k; i<<=2; }
+ } else if (bpc==4) {
+ toend-=(wd*3)&7;
+ while (to!=toend) {
+ i=*p++;
+ k=(i>>4)*17; *to++=k;
+ k=( i&15)*17; *to++=k;
+ }
+ if (0!=((wd*3)&1)) *to++=(*p>>4)*17;
+ } else if (bpc==8) {
+ memcpy(to, p, 3*wd);
+ } else assert(0 && "invalid bpc");
+}
+#if 0
+void Image::RGB::setBpc(unsigned char bpc_) {
+ (void)bpc_;
+ assert(0 && "unimplemented"); /* unimplemented */
+}
+#endif
+
+Image::Sampled* Image::RGB::addAlpha(Image::Gray *al) {
+ if (al->getHt()!=ht || al->getWd()!=wd) Error::sev(Error::EERROR) << "addAlpha: image dimension mismatch" << (Error*)0;
+ bool ign_mid=false;
+ unsigned char lightest, darkest;
+ al->to8();
+ al->calcExtrema(lightest, darkest);
+ if (darkest==255) return this; /* no transparent pixels at all */
+ char *p=rowbeg, *pend=rowbeg+rlen*ht, *alq=al->getRowbeg();
+ /* Imp: choose an image color instead of black... */
+ /* Dat: 0..254: transparent, 255: opaque */
+ while (p!=pend) {
+ if ((unsigned char)(*alq+1)>1) ign_mid=true;
+ /* fprintf(stderr,"alq=%u\n", (unsigned char)*alq); */
+ if ((unsigned char)*alq++!=255) p[0]=p[1]=p[2]=0; /* black out transparent-wannabe pixels */
+ p+=3;
+ }
+ if (ign_mid) Error::sev(Error::WARNING) << "addAlpha: half-transparent pixels made transparent" << (Error*)0;
+ return addAlpha0(toIndexed(), al);
+}
+
+/* --- */
+
+char *Image::Sampled::rgb2webhash(rgb_t rgb) {
+ static char tmp[8];
+ char *p=tmp;
+ *p='#';
+ *++p='0'+(rgb>>20); if (*p>'9') *p+='a'-'0'-10;
+ *++p='0'+((rgb>>16)&15); if (*p>'9') *p+='a'-'0'-10;
+ *++p='0'+((rgb>>12)&15); if (*p>'9') *p+='a'-'0'-10;
+ *++p='0'+((rgb>>8)&15); if (*p>'9') *p+='a'-'0'-10;
+ *++p='0'+((rgb>>4)&15); if (*p>'9') *p+='a'-'0'-10;
+ *++p='0'+((rgb )&15); if (*p>'9') *p+='a'-'0'-10;
+ *++p='\0';
+ return tmp;
+}
+
+GenBuffer::Writable& operator<<(GenBuffer::Writable& gw, Image::Sampled const& img) {
+ slen_t buflen=img.getWd()*3;
+ char *buf=new char[buflen];
+ Image::Sampled::dimen_t y, ht=img.getHt();
+ /* vvv in the xv program: image file must be >=30 bytes long to be treated as image */
+ gw << "P6\n###############\n" << img.getWd() << ' ' << ht;
+ if (img.getTranspc()>=0x1000000UL) gw << "\n#Opaque";
+ else gw << "\n#T" << img.rgb2webhash(img.getTranspc());
+ gw << "\n255\n";
+ for (y=0; y<ht; y++) {
+ img.copyRGBRow(buf, y);
+ gw.vi_write(buf, buflen);
+ }
+ delete [] buf;
+ return gw;
+}
+
+static Image::Loader *first_image_loader=(Image::Loader*)NULLP;
+
+void Image::register0(Image::Loader *anew) {
+ param_assert(anew!=NULLP);
+ anew->next=first_image_loader;
+ first_image_loader=anew;
+}
+
+#if 0 /* removed by code refactoring */
+Image::Sampled* Image::load(char const* format, filep_t f_, SimBuffer::Flat const& loadHints) {} /* Removed. */
+#endif
+
+// #include <unistd.h> /* sleep() */
+
+#if 0
+Rule::Sampled *Rule::load(char const* filename) {
+ static char buf[2*Applier::MAGIC_LEN];
+ FILE *f=fopen(filename, "rb");
+ unsigned got=0;
+ if (f==NULLP) Error::sev(Error::EERROR) << "Cannot open/read image file: " << FNQ(filename) << (Error*)0;
+ slen_t ret=fread(buf, 1, Applier::MAGIC_LEN, f);
+ /* vvv Imp: clarify error message: may be a read error */
+ if (ret==0) Error::sev(Error::EERROR) << "Zero-length image file: " << FNQ(filename) << (Error*)0;
+ if (ret<Applier::MAGIC_LEN) memset(buf+ret, '\0', Applier::MAGIC_LEN-ret);
+#if 0
+ unsigned long pos=fseek(f, 0, SEEK_END);
+ pos=(pos<=Applier::MAGIC_LEN)?0:pos-Applier::MAGIC_LEN;
+ if (0!=fseek(f, pos, SEEK_SET)
+ || (got=fread(buf+Applier::MAGIC_LEN, 1, Applier::MAGIC_LEN, f))==0
+#else
+ if (0
+#endif
+ || (rewind(f), 0)
+ || ferror(f))
+ Error::sev(Error::EERROR) << "I/O error in image file: " << FNQ(filename) << (Error*)0;
+ if (got!=0 && got!=Applier::MAGIC_LEN) memmove(buf+2*Applier::MAGIC_LEN-got, buf+Applier::MAGIC_LEN, got);
+ Applier *p=first_image_loader;
+ Applier::reader_t reader;
+ while (p!=NULLP) {
+ if (NULLP!=(reader=p->checker(buf,buf+Applier::MAGIC_LEN))) { return reader(f); }
+ p=p->next;
+ }
+ Error::sev(Error::EERROR) << "Unknown image format: " << FNQ(filename) << (Error*)0;
+ // Error::sev(Error::WARNING) << "Zero-length image1." << (Error*)0;
+ // Error::sev(Error::WARNING) << "Zero-length image2." << (Error*)0;
+ return 0; /*notreached*/
+}
+#endif
+
+
+Image::Sampled *Image::load(Image::Loader::UFD* ufd0, SimBuffer::Flat const& loadHints, char const* format) {
+ Filter::UngetFILED &ufd=*(Filter::UngetFILED*)ufd0;
+ /* Dat: format arg used in in_pnm.cpp */
+ static char buf[Loader::MAGIC_LEN+1];
+ slen_t ret=ufd.vi_read(buf, Loader::MAGIC_LEN);
+ /* vvv Imp: clarify error message: may be a read error */
+ if (ufd.hadError()) Error::sev(Error::EERROR) << "I/O error pre in image file: " << FNQ(ufd.getFilenameDefault("-")) << (Error*)0;
+ if (ret==0) Error::sev(Error::EERROR) << "Zero-length image file: " << FNQ(ufd.getFilenameDefault("-")) << (Error*)0;
+ if (ret<Loader::MAGIC_LEN) memset(buf+ret, '\0', Loader::MAGIC_LEN-ret);
+ buf[Loader::MAGIC_LEN]='\0';
+ /* Dat: do not read the trailer onto buf+Loader::MAGIC_LEN, because no ->checker() uses it yet. */
+ Loader *p=first_image_loader;
+ Loader::reader_t reader;
+ ufd.unread(buf, ret); /* tries to seek back, on failure calls ufd.getUnget().vi_write() */
+ // ^^^ rewind(f); /* checker might have read */
+ /* ^^^ do this early for the checkers */
+ while (p!=NULLP) {
+ /* vvv each checker() must rewind ufd for itself */
+ if ((format==(char const*)NULLP || 0==strcmp(p->format, format))
+ && (Loader::checker_t)0!=p->checker
+ && (Loader::reader_t)0!=(reader=p->checker(buf,buf+Loader::MAGIC_LEN, loadHints, ufd0))
+ ) {
+ // fprintf(stderr, "%p %p\n", ufd0, &ufd);
+ return reader(ufd0, loadHints);
+ }
+ p=p->next;
+ }
+ // sleep(1000);
+ Error::sev(Error::EERROR) << "Unknown input image format: " << FNQ(ufd.getFilenameDefault("-")) << (Error*)0;
+ return 0; /*notreached*/
+}
+
+#if 0 /* not used anywhere, except in test_main. */
+Image::Sampled *Image::load(char const* filename, SimBuffer::Flat const& loadHints, filep_t stdin_f, char const* format) { /* Commented out. */
+ Filter::UngetFILED ufd(filename, stdin_f==NULLP ? stdin : (FILE*)stdin_f,
+ Filter::UngetFILED::CM_closep|Filter::UngetFILED::CM_keep_stdinp);
+ return load((Image::Loader::UFD*)&ufd, loadHints, format);
+ // Imp: better error message, something like: if (f==NULLP) Error::sev(Error::EERROR) << "Cannot open/read image file: " << FNQ(filename) << (Error*)0;
+}
+#endif
+
+#if 0 /* before Sat Apr 19 13:42:04 CEST 2003 */
+Image::Sampled *Image::load(char const* filename, SimBuffer::Flat const& loadHints, filep_t stdin_f, char const* format) {
+ /* Dat: format arg used in in_pnm.cpp */
+ static char buf[2*Loader::MAGIC_LEN];
+ bool stdin_p=filename[0]=='-' && filename[1]=='\0';
+ FILE *f=!stdin_p ? fopen(filename, "rb") : stdin_f!=NULLP ? (FILE*)stdin_f : stdin;
+ unsigned got=0;
+ if (f==NULLP) Error::sev(Error::EERROR) << "Cannot open/read image file: " << FNQ(filename) << (Error*)0;
+ slen_t ret=fread(buf, 1, Loader::MAGIC_LEN, f);
+ /* vvv Imp: clarify error message: may be a read error */
+ if (ret==0) Error::sev(Error::EERROR) << "Zero-length image file: " << FNQ(filename) << (Error*)0;
+ if (ret<Loader::MAGIC_LEN) memset(buf+ret, '\0', Loader::MAGIC_LEN-ret);
+#if 0
+ /* Dat: do not read the trailer, because no ->checker() uses it yet. */
+ unsigned long pos=fseek(f, 0, SEEK_END);
+ pos=(pos<=Loader::MAGIC_LEN)?0:pos-Loader::MAGIC_LEN;
+ if (0!=fseek(f, pos, SEEK_SET)
+ || (got=fread(buf+Loader::MAGIC_LEN, 1, Loader::MAGIC_LEN, f))==0
+#else
+ if (0
+#endif
+ || (rewind(f), 0)
+ || ferror(f))
+ Error::sev(Error::EERROR) << "I/O error pre in image file: " << FNQ(filename) << (Error*)0;
+ if (got!=0 && got!=Loader::MAGIC_LEN) memmove(buf+2*Loader::MAGIC_LEN-got, buf+Loader::MAGIC_LEN, got);
+ Loader *p=first_image_loader;
+ Loader::reader_t reader;
+ while (p!=NULLP) {
+ if ((format==(char const*)NULLP || 0==strcmp(p->format, format))
+ && (Loader::checker_t)NULLP!=p->checker
+ && (Loader::reader_t)NULLP!=(reader=p->checker(buf,buf+Loader::MAGIC_LEN, loadHints, f))
+ ) {
+ rewind(f); /* checker might have read */
+ Image::Sampled *ret=reader(f, loadHints);
+ if (ferror(f) || (!stdin_p && 0!=fclose(f))) /* don't close stdin */
+ Error::sev(Error::EERROR) << "I/O error post in image file: " << FNQ(filename) << (Error*)0;
+ return ret;
+ }
+ p=p->next;
+ }
+ Error::sev(Error::EERROR) << "Unknown input image format: " << FNQ(filename) << (Error*)0;
+ // Error::sev(Error::WARNING) << "Zero-length image1." << (Error*)0;
+ // Error::sev(Error::WARNING) << "Zero-length image2." << (Error*)0;
+ return 0; /*notreached*/
+}
+#endif
+
+unsigned Image::printLoaders(GenBuffer::Writable &out) {
+ unsigned num=0;
+ Loader *p=first_image_loader;
+ while (p!=NULLP) {
+ if (p->checker!=(Loader::checker_t)0 && p->format!=(char const*)NULLP) { num++; out << ' ' << p->format; }
+ p=p->next;
+ }
+ return num;
+}
+
+/* --- */
+
+Image::SampledInfo::SampledInfo(Sampled *img_)
+ :hasTransp(false)
+ ,nncols(257)
+ ,canGray(false)
+ ,minRGBBpc(8)
+ ,img(img_)
+ ,imgs((Indexed**)NULLP) {
+ param_assert(img_!=NULLP);
+ Sampled *bak=img;
+ if ((img=img->toIndexed())==NULLP) {
+ img=bak;
+ } else {
+ if (bak!=img) delete bak;
+ assert(img->getTy()==img->TY_INDEXED);
+ Indexed *iimg=PTS_dynamic_cast(Image::Indexed*,img);
+ /* This packPal() contains a call to sortPal(), which converts the indexed
+ * image to canonical form.
+ */
+ iimg->packPal();
+ nncols=iimg->getNcols();
+ if (true==(hasTransp=iimg->hasTransp())) nncols--;
+ }
+ minRGBBpc=img->minRGBBpc();
+ if ((canGray=img->canGray())==true && nncols==257) nncols=256;
+ sf=(sf_t)((img->getTy()==img->TY_BLACKBOX) ? 0+SF_Asis : 0+SF_None);
+ /* Dat: 0+: pacify gcc-3.1 */
+}
+
+Image::SampledInfo::~SampledInfo() {
+ delete img;
+ if (imgs!=NULLP) { Image::Indexed::delete_separated(imgs); delete imgs; }
+}
+
+void Image::SampledInfo::separate() {
+ // bool ok;
+ // ASSERT_SIDE(ok=(sf!=SF_Transparent2 && sf!=SF_Transparent4 && sf!=SF_Transparent8));
+ // if (!ok) return;
+ if (sf!=SF_Transparent2 && sf!=SF_Transparent4 && sf!=SF_Transparent8) return;
+ Indexed *iimg=PTS_dynamic_cast(Indexed*,img);
+ imgs=iimg->separate();
+}
+
+bool Image::SampledInfo::setSampleFormat(sf_t sf_, bool WarningOK, bool TryOnly, Sampled::rgb_t Transparent) {
+ /* at Sat Jun 15 11:48:51 CEST 2002: added transparency warnings */
+ /* fprintf(stderr, "sf=%u sf_=%u transparent=0x%lx\n", sf, sf_, Transparent+0UL); */
+ // assert(sf_==SF_Asis);
+ Indexed *iimg;
+ Sampled *bak=img;
+ param_assert(sf_!=SF_None);
+ param_assert(sf==SF_None || sf==SF_Asis || sf==sf_);
+ if (sf_==sf) return true; /* already converted */
+ bool zero=img->getWd()==0 || img->getHt()==0;
+ if (sf==SF_Asis && sf_!=SF_Asis && sf_!=SF_Bbox) {
+ Error::sev(Error::WARNING) << "SampleFormat: can't convert image loaded as Asis to other" << (Error*)0;
+ return false;
+ }
+ switch (sf_) {
+ case SF_Bbox:
+ sf=SF_Bbox; return true;
+ case SF_Opaque:
+ if (!hasTransp && nncols==1 && PTS_dynamic_cast(Indexed*,img)->wouldSetTranspc(Transparent)) return false;
+ if (hasTransp || nncols!=1) return false;
+ assert(img->getTy()==img->TY_INDEXED);
+ /* The color can be calculated: PTS_dynamic_cast(Indexed*>(img)->getPal(0); */
+ /* Conversion is not necessary. */
+ sf=SF_Opaque; return true;
+ case SF_Transparent:
+ if (!hasTransp && nncols==1 && PTS_dynamic_cast(Indexed*,img)->setTranspc(Transparent)) {
+ /* Must return true eventually, because setTranspc has modified the image. */
+ hasTransp=true; nncols=0;
+ } else if (!hasTransp || nncols!=0) {
+ return false;
+ }
+ assert(img->getTy()==img->TY_INDEXED);
+ /* Conversion is not necessary. */
+ sf=SF_Transparent; return true;
+ case SF_Gray1:
+ /* vvv strict hasTransp added at Mon Sep 9 22:53:24 CEST 2002 */
+ if (nncols>2 || !canGray || minRGBBpc>1 || zero || hasTransp || img->hasPixelRGB(Transparent)) return false;
+ /* ^^^ Imp: !! make the hasPixelRFB() check a lot faster (cache results) */
+ if (TryOnly) return WarningOK || (nncols>=2 && !hasTransp);
+ if (hasTransp) {
+ if (!WarningOK) return false;
+ /* Dat: nncols may be 1 or 2 ! (both transparent and opaque black) */
+ Error::sev(Error::WARNING) <<
+ (nncols<=1 ? "SampleFormat: Mask would be better than "
+ : "SampleFormat: Transparent2 would be better than ")
+ << "Gray1" << (Error*)0;
+ }
+ if (nncols<2) {
+ if (!WarningOK) return false;
+ Error::sev(Error::WARNING) << "SampleFormat: Opaque would be better than Gray1" << (Error*)0;
+ }
+ img=img->toGray(1); if (bak!=img) delete bak;
+ assert(img!=NULLP);
+ assert(img->getBpc()==1);
+ sf=SF_Gray1; return true;
+ case SF_Indexed1:
+ if (nncols>2 || zero || hasTransp || img->hasPixelRGB(Transparent)) return false;
+ if (TryOnly) return WarningOK || nncols>=2;
+ if (nncols<2) {
+ if (!WarningOK) return false;
+ Error::sev(Error::WARNING) << "SampleFormat: Opaque would be better than Indexed1" << (Error*)0;
+ }
+ if (canGray && minRGBBpc==1) {
+ Error::sev(Error::NOTICE) << "SampleFormat: Gray1 would be better than Indexed1" << (Error*)0;
+ }
+ assert(img->getTy()==img->TY_INDEXED);
+ // img=img->toIndexed(); /* should be a no-op */
+ // assert(img!=NULLP); if (bak!=img) delete bak;
+ { iimg=PTS_dynamic_cast(Indexed*,img);
+ iimg->setBpc(1);
+ if (iimg->wouldSetTranspc(Transparent)) return false; /* Dat: false if must be changed to become transparent. */
+ iimg->setTranspcAndRepack(Transparent);
+ }
+ sf=SF_Indexed1; return true;
+ case SF_Mask:
+ if (!hasTransp && nncols==2 && PTS_dynamic_cast(Indexed*,img)->wouldSetTranspc(Transparent)) { hasTransp=true; --nncols; }
+ if (nncols>1 || zero) return false;
+ if (TryOnly) return WarningOK || nncols+(hasTransp?1:0)==2;
+ if (nncols==1 && !hasTransp) {
+ if (!WarningOK) return false;
+ Error::sev(Error::WARNING) << "SampleFormat: Opaque would be better than Mask" << (Error*)0;
+ }
+ if (nncols==0) {
+ assert(hasTransp);
+ Error::sev(Error::WARNING) << "SampleFormat: Transparent would be better than Mask" << (Error*)0;
+ }
+ assert(img->getTy()==img->TY_INDEXED);
+ { iimg=PTS_dynamic_cast(Indexed*,img);
+ iimg->setBpc(1);
+ if (!iimg->wouldSetTranspc(Transparent)) return false;
+ iimg->setTranspcAndRepack(Transparent);
+ }
+ /* printf("gett=%d\n", PTS_dynamic_cast(Indexed*,img)->getTransp()); */
+ /* vvv BUGFIX: <1U -> <2U */
+ assert(PTS_dynamic_cast(Indexed*,img)->getTransp()==-1 || PTS_dynamic_cast(Indexed*,img)->getTransp()+0U<2U);
+ /* ^^^ color 0 is opaque, color 1 is transparent, thanks to
+ * img->packPal() called in SampleInfo() -- but setTranspc may have changed this
+ */
+ sf=SF_Mask; return true;
+ case SF_Transparent2:
+ if (!hasTransp && nncols==4 && PTS_dynamic_cast(Indexed*,img)->wouldSetTranspc(Transparent)) { hasTransp=true; --nncols; }
+ if (nncols>3 || zero) return false;
+ if (TryOnly) return WarningOK || (hasTransp && nncols>=2);
+ Error::sev(Error::NOTICE) << "SampleFormat: Transparent2 separates colors" << (Error*)0;
+ if (!hasTransp) {
+ if (!WarningOK) return false;
+ Error::sev(Error::WARNING) << "SampleFormat: Indexed2 would be better than Transparent2" << (Error*)0;
+ }
+ if (nncols<2) {
+ if (!WarningOK) return false;
+ Error::sev(Error::WARNING) << "SampleFormat: Mask would be better than Transparent2" << (Error*)0;
+ }
+ assert(img->getTy()==img->TY_INDEXED);
+ { iimg=PTS_dynamic_cast(Indexed*,img);
+ iimg->setBpc(2); /* BUGFIX at Sat Jun 15 13:55:25 CEST 2002 */
+ iimg->setTranspcAndRepack(Transparent);
+ // imgs=iimg->separate(); /* postponed because of GIF89a output */
+ }
+ sf=SF_Transparent2; return true;
+ case SF_Gray2:
+ if (nncols>4 || !canGray || minRGBBpc>2 || zero || hasTransp || img->hasPixelRGB(Transparent)) return false;
+ if (TryOnly) return WarningOK || (nncols>2 && !hasTransp);
+ if (hasTransp) {
+ if (!WarningOK) return false;
+ Error::sev(Error::WARNING) <<
+ (nncols<=3 ? "SampleFormat: Transparent2 would be better than "
+ : "SampleFormat: Transparent4 would be better than ")
+ << "Gray2" << (Error*)0;
+ }
+ if (nncols<=2) {
+ if (!WarningOK) return false;
+ Error::sev(Error::WARNING) << "SampleFormat: Gray1 would be better than Gray2" << (Error*)0;
+ }
+ img=img->toGray(2); if (bak!=img) delete bak;
+ assert(img!=NULLP);
+ sf=SF_Gray2; return true;
+ case SF_Indexed2:
+ if (nncols>4 || zero || hasTransp || img->hasPixelRGB(Transparent)) return false;
+ if (TryOnly) return WarningOK || nncols>2;
+ if (nncols<=2) {
+ if (!WarningOK) return false;
+ Error::sev(Error::WARNING) << "SampleFormat: Indexed1 would be better than Indexed2" << (Error*)0;
+ }
+ if (canGray && minRGBBpc<=2) {
+ Error::sev(Error::NOTICE) << "SampleFormat: Gray2 would be better than Indexed2" << (Error*)0;
+ }
+ assert(img->getTy()==img->TY_INDEXED);
+ { iimg=PTS_dynamic_cast(Indexed*,img);
+ iimg->setBpc(2);
+ if (iimg->wouldSetTranspc(Transparent)) return false;
+ iimg->setTranspcAndRepack(Transparent);
+ }
+ sf=SF_Indexed2; return true;
+ case SF_Transparent4:
+ if (!hasTransp && nncols==16 && PTS_dynamic_cast(Indexed*,img)->wouldSetTranspc(Transparent)) { hasTransp=true; --nncols; }
+ if (nncols>15 || zero) return false;
+ if (TryOnly) return WarningOK || (hasTransp && nncols>=4);
+ Error::sev(Error::NOTICE) << "SampleFormat: Transparent4 separates colors" << (Error*)0;
+ if (!hasTransp) {
+ if (!WarningOK) return false;
+ Error::sev(Error::WARNING) << "SampleFormat: Indexed4 would be better than Transparent4" << (Error*)0;
+ }
+ if (nncols<4) {
+ if (!WarningOK) return false;
+ Error::sev(Error::WARNING) << "SampleFormat: Transparent2 would be better than Transparent4" << (Error*)0;
+ }
+ assert(img->getTy()==img->TY_INDEXED);
+ { iimg=PTS_dynamic_cast(Indexed*,img);
+ iimg->setBpc(4);
+ iimg->setTranspcAndRepack(Transparent);
+ // imgs=iimg->separate(); /* postponed because of GIF89a output */
+ }
+ sf=SF_Transparent4; return true;
+ case SF_Rgb1:
+ if (nncols>8 || minRGBBpc>1 || zero || hasTransp || img->hasPixelRGB(Transparent)) return false;
+ if (TryOnly) return WarningOK || (nncols>4 && !canGray && !hasTransp);
+ if (hasTransp) {
+ if (!WarningOK) return false;
+ Error::sev(Error::WARNING) << "SampleFormat: Transparent4 would be better than " << "Rgb1" << (Error*)0;
+ }
+ if (canGray) {
+ if (!WarningOK) return false;
+ Error::sev(Error::WARNING) << "SampleFormat: Gray1 would be better than Rgb1" << (Error*)0;
+ }
+ if (nncols<=4) {
+ if (!WarningOK) return false;
+ Error::sev(Error::WARNING) << "SampleFormat: "
+ << (hasTransp ? "Transparent2 may" : "Indexed2 would")
+ << " be better than Rgb1" << (Error*)0;
+ }
+ img=img->toRGB(1); if (bak!=img) delete bak;
+ assert(img!=NULLP);
+ sf=SF_Rgb1; return true;
+ case SF_Gray4:
+ if (nncols>16 || !canGray || minRGBBpc>4 || zero || hasTransp || img->hasPixelRGB(Transparent)) return false;
+ /* ^^^ BUGFIX at Sat Jun 1 18:27:10 CEST 2002 */
+ if (TryOnly) return WarningOK || (nncols>4 && !hasTransp);
+ if (hasTransp) {
+ if (!WarningOK) return false;
+ Error::sev(Error::WARNING) <<
+ (nncols<=15 ? "SampleFormat: Transparent4 would be better than "
+ : "SampleFormat: Transparent8 may be better than ")
+ << "Gray4" << (Error*)0;
+ }
+ if (nncols<=4) {
+ if (!WarningOK) return false;
+ Error::sev(Error::WARNING) << "SampleFormat: Gray2 would be better than Gray4" << (Error*)0;
+ }
+ img=img->toGray(4); if (bak!=img) delete bak;
+ assert(img!=NULLP);
+ sf=SF_Gray4; return true;
+ case SF_Indexed4:
+ if (nncols>16 || zero || hasTransp || img->hasPixelRGB(Transparent)) return false;
+ if (TryOnly) return WarningOK || (nncols>4 && minRGBBpc>=4);
+ if (nncols<=4) {
+ if (!WarningOK) return false;
+ Error::sev(Error::WARNING) << "SampleFormat: Indexed2 would be better than Indexed4" << (Error*)0;
+ }
+ if (minRGBBpc<=1) {
+ if (!WarningOK) return false;
+ Error::sev(Error::WARNING) << "SampleFormat: RGB1 would be better than Indexed4" << (Error*)0;
+ }
+ if (canGray && minRGBBpc<=4) {
+ if (!WarningOK) return false;
+ Error::sev(Error::NOTICE) << "SampleFormat: Gray4 would be better than Indexed4" << (Error*)0;
+ }
+ assert(img->getTy()==img->TY_INDEXED);
+ { iimg=PTS_dynamic_cast(Indexed*,img);
+ iimg->setBpc(4);
+ if (iimg->wouldSetTranspc(Transparent)) return false;
+ iimg->setTranspcAndRepack(Transparent);
+ }
+ sf=SF_Indexed4; return true;
+ case SF_Transparent8:
+ if (!hasTransp && nncols==256 && PTS_dynamic_cast(Indexed*,img)->wouldSetTranspc(Transparent)) { hasTransp=true; --nncols; }
+ if (nncols>255 || zero) return false;
+ if (!WarningOK) return false;
+ if (TryOnly) return true;
+ Error::sev(Error::WARNING) << "SampleFormat: Transparent8 separates too many colors" << (Error*)0;
+ if (!hasTransp) {
+ Error::sev(Error::WARNING) << "SampleFormat: Indexed8 would be much better than Transparent8" << (Error*)0;
+ }
+ if (nncols<16) {
+ Error::sev(Error::WARNING) << "SampleFormat: Transparent4 would be better than Transparent8" << (Error*)0;
+ }
+ assert(img->getTy()==img->TY_INDEXED);
+ { iimg=PTS_dynamic_cast(Indexed*,img);
+ iimg->setBpc(8); /* should be a no-op */
+ iimg->setTranspcAndRepack(Transparent);
+ // imgs=iimg->separate(); /* postponed because of GIF89a output */
+ }
+ sf=SF_Transparent8; return true;
+ case SF_Rgb2:
+ if (nncols>64 || minRGBBpc>2 || zero || hasTransp || img->hasPixelRGB(Transparent)) return false;
+ if (TryOnly) return WarningOK || (nncols>16 && !canGray && !hasTransp);
+ if (hasTransp) {
+ if (!WarningOK) return false;
+ Error::sev(Error::WARNING) << "SampleFormat: Transparent8 would be better than " << "Rgb2" << (Error*)0;
+ }
+ if (canGray) {
+ if (!WarningOK) return false;
+ Error::sev(Error::WARNING) << "SampleFormat: Gray2 would be better than Rgb2" << (Error*)0;
+ }
+ if (nncols<=16) {
+ if (!WarningOK) return false;
+ Error::sev(Error::WARNING) << "SampleFormat: "
+ << (hasTransp ? "Transparent4 may" : "Indexed4 would")
+ << " be better than Rgb2" << (Error*)0;
+ }
+ img=img->toRGB(2); if (bak!=img) delete bak;
+ assert(img!=NULLP);
+ sf=SF_Rgb2; return true;
+ case SF_Gray8:
+ if (nncols>256 || !canGray || zero || hasTransp || img->hasPixelRGB(Transparent)) return false;
+ if (TryOnly) return WarningOK || (nncols>16 && !hasTransp);
+ if (hasTransp) {
+ if (!WarningOK) return false;
+ Error::sev(Error::WARNING) <<
+ (nncols<=255 ? "SampleFormat: Transparent8 may be better than "
+ : "SampleFormat: ignoring transparency for ")
+ << "Gray8" << (Error*)0;
+ }
+ if (minRGBBpc<=4) {
+ /* BUGFIX at Wed Jul 3 01:07:44 CEST 2002 */
+ if (!WarningOK) return false;
+ Error::sev(Error::WARNING) << "SampleFormat: Gray4 would be better than Gray8" << (Error*)0;
+ }
+ img=img->toGray(8); if (bak!=img) delete bak;
+ assert(img!=NULLP);
+ sf=SF_Gray8; return true;
+ case SF_Indexed8:
+ // fprintf(stderr, "nncols=%u hasTransp=%u zero=%u\n", nncols, hasTransp, zero);
+ if (nncols>256 || zero || hasTransp || img->hasPixelRGB(Transparent)) return false;
+ // assert(0);
+ if (TryOnly) return WarningOK || (nncols>16 && minRGBBpc>=8);
+ if (nncols<=16) {
+ if (!WarningOK) return false;
+ Error::sev(Error::WARNING) << "SampleFormat: Indexed4 would be better than Indexed8" << (Error*)0;
+ }
+ if (minRGBBpc<=2) {
+ if (!WarningOK) return false;
+ Error::sev(Error::WARNING) << "SampleFormat: RGB2 would be better than Indexed8" << (Error*)0;
+ }
+ if (canGray) {
+ if (!WarningOK) return false;
+ Error::sev(Error::NOTICE) << "SampleFormat: Gray8 would be better than Indexed8" << (Error*)0;
+ }
+ assert(img->getTy()==img->TY_INDEXED);
+ { iimg=PTS_dynamic_cast(Indexed*,img);
+ iimg->setBpc(8); /* should be a no-op */
+ if (iimg->wouldSetTranspc(Transparent)) return false;
+ iimg->setTranspcAndRepack(Transparent);
+ }
+ sf=SF_Indexed8; return true;
+ case SF_Rgb4:
+ // fprintf(stderr, "minrgbbpc=%d to=%d\n", minRGBBpc, TryOnly);
+ if (minRGBBpc>4 || zero || hasTransp || img->hasPixelRGB(Transparent)) return false;
+ if (TryOnly) return WarningOK || (nncols>256 && !canGray && !hasTransp);
+ if (hasTransp) {
+ if (!WarningOK) return false;
+ Error::sev(Error::WARNING) <<
+ (nncols<=255 ? "SampleFormat: Transparent8 may be better than "
+ : "SampleFormat: ignoring transparency for ")
+ << "Rgb4" << (Error*)0;
+ }
+ if (canGray) {
+ if (!WarningOK) return false;
+ Error::sev(Error::WARNING) << "SampleFormat: Gray4 would be better than Rgb4" << (Error*)0;
+ }
+ if (nncols<=256) {
+ if (!WarningOK) return false;
+ Error::sev(Error::WARNING) << "SampleFormat: "
+ << (hasTransp && nncols<=255 ? "Transparent8 may" : "Indexed8 would")
+ << " be better than Rgb4" << (Error*)0;
+ }
+ img=img->toRGB(4); if (bak!=img) delete bak;
+ assert(img!=NULLP);
+ sf=SF_Rgb4; return true;
+ case SF_Rgb8:
+ if (zero || hasTransp || img->hasPixelRGB(Transparent)) return false;
+ if (TryOnly) return WarningOK || (nncols>256 && !canGray && minRGBBpc>=8 && !hasTransp);
+ if (hasTransp) {
+ if (!WarningOK) return false;
+ Error::sev(Error::WARNING) <<
+ (nncols<=255 ? "SampleFormat: Transparent8 may be better than "
+ : "SampleFormat: ignoring transparency for ")
+ << "Rgb8" << (Error*)0;
+ }
+ if (canGray) {
+ if (!WarningOK) return false;
+ Error::sev(Error::WARNING) << "SampleFormat: Gray8 would be better than Rgb8" << (Error*)0;
+ }
+ if (minRGBBpc<=4) {
+ if (!WarningOK) return false;
+ Error::sev(Error::WARNING) << "SampleFormat: Rgb4 would be better than Rgb8" << (Error*)0;
+ }
+ if (nncols<=256) {
+ if (!WarningOK) return false;
+ Error::sev(Error::WARNING) << "SampleFormat: "
+ << (hasTransp && nncols<=255 ? "Transparent8 may" : "Indexed8 would")
+ << " be better than Rgb8" << (Error*)0;
+ }
+ img=img->toRGB(8); if (bak!=img) delete bak;
+ assert(img!=NULLP);
+ sf=SF_Rgb8; return true;
+ case SF_Asis:
+ if (img->getTy()!=img->TY_BLACKBOX) {
+ Error::sev(Error::WARNING) << "SampleFormat: cannot convert image to /Asis" << (Error*)0;
+ return false;
+ }
+ sf=SF_Asis; return true;
+ }
+ assert(0 && "unknown SampleFormat requested");
+ return false; /* NOTREACHED */
+}
+
+/* __END__ */
diff --git a/graphics/sam2p/image.hpp b/graphics/sam2p/image.hpp
new file mode 100644
index 0000000000..582cf50640
--- /dev/null
+++ b/graphics/sam2p/image.hpp
@@ -0,0 +1,405 @@
+/* image.hpp -- classes for sampled (indexed, gray and rgb) images
+ * by pts@fazekas.hu Wed Feb 27 09:24:47 CET 2002
+ */
+/* Imp: keep future transparency in toIndexed(...) */
+
+#ifdef __GNUC__
+#ifndef __clang__
+#pragma interface
+#endif
+#endif
+
+#ifndef SAMPLED_HPP
+#define SAMPLED_HPP 1
+
+#include "config2.h"
+#include "gensi.hpp"
+
+class Image {
+ public:
+ class RGB;
+ class Gray;
+ class Indexed;
+ /** Generic, sampled, rectangular image data. Abstract class.
+ * Each sample is 1, 2, 4 or 8 bits. Regions:
+ * beg..head-1: comment, ignored (e.g unused part of the indexed palette)
+ * headp..rowbeg-1: header: not predicted or compressed (e.g the indexed palette)
+ * rowbeg+0*rlen..rowbeg+0*rlen+rlen-1: sample data of the 0th row, compressed and predicted
+ * rowbeg+1*rlen..rowbeg+1*rlen+rlen-1: sample data of the 1st row
+ * rowbeg+2*rlen..rowbeg+2*rlen+rlen-1: sample data of the 1st row
+ * ...
+ * rowbeg+(h-1)*rlen..rowbeg+h*rlen-1: sample data of the last row
+ * trail..beg+len: trailer, ignored. Its length must be >=bpc.
+ * TODO: Remove trail, and see what breaks (e.g. setBpc).
+ */
+ class Sampled: public SimBuffer::Flat {
+ public:
+ /** Can hold 1 component of a sample of a single pixel. */
+ typedef unsigned char sample_t;
+ /** Can hold a height or depth of the image */
+ typedef unsigned int dimen_t;
+ /** Can hold a row length (in byte), which isn't greater than 3*(image width). */
+ typedef unsigned int rlen_t;
+ /** RGB = (red<<16)+(green<<8)+(blue). red, green and blue are 0..255 */
+ #if SIZEOF_LONG>4 && SIZEOF_INT>=4
+ typedef unsigned int rgb_t;
+ #else
+ typedef unsigned long rgb_t;
+ #endif
+ BEGIN_STATIC_ENUM1(unsigned char)
+ TY_INDEXED=1, TY_GRAY=2, TY_RGB=3, TY_OTHER=4, TY_BLACKBOX=5
+ END_STATIC_ENUM()
+ BEGIN_STATIC_ENUM1(unsigned char) // static const unsigned char
+ CS_UNKNOWN=0, /* error/unspecified */
+ CS_GRAYSCALE=1, /* monochrome */
+ CS_RGB=2, /* red/green/blue */
+ CS_YCbCr=3, /* Y/Cb/Cr (also known as YUV) */
+ CS_CMYK=4, /* C/M/Y/K */
+ CS_YCCK=5, /* Y/Cb/Cr/K */
+ CS_Indexed_RGB=12
+ END_STATIC_ENUM()
+ static const unsigned char cs2cpp[6];
+ /** @return NULLP on error */
+ static char const *cs2devcs(unsigned char cs);
+ protected:
+ char *headp;
+ char *rowbeg;
+ char *trail;
+ /** Extra offset */
+ slen_t xoffs;
+
+ /** Length of one row, in bytes. Each row must begin on a byte boundary, so
+ * extra bits are appended after the rightmost pixel. These bits are
+ * arbitrary, and are ignored by the PostScript interpreter.
+ */
+ rlen_t rlen;
+ /** Image height, in pixels. */
+ dimen_t ht;
+ /** Image width, in pixels. */
+ dimen_t wd;
+ /** Color space. */
+ unsigned char cs;
+ /** Components per pixel. (number of planes, image depth). 1 for indexed,
+ * 1 for gray, 3 for RGB
+ */
+ unsigned char cpp;
+ /** BitsPerComponent: 1, 2, 4 or 8. PostScript allows 12 too. */
+ unsigned char bpc;
+ /** Transparent color value. Imp: ... */
+ rgb_t transpc;
+ /** Image type, TY_... */
+ unsigned char ty;
+ /** Initializes various fields, allocates memory. Called from descendants'
+ * constructors.
+ */
+ void init(slen_t l_comment, slen_t l_header, dimen_t wd_, dimen_t ht_,
+ unsigned char bpc_, unsigned char ty_, unsigned char cpp_);
+ /** Convert samples, make bpc=8, multiplication. */
+ void to8mul();
+ /** Convert samples, make bpc=8, no multiplication. */
+ void to8nomul();
+ /** Calls copyRGBRow.
+ * @return an Image::Indexed version of (this) iff the number of
+ * colors<=256. Otherwise, returns NULLP.
+ */
+ Indexed* toIndexed0()/* const*/;
+ /** No averaging is done, only the red component is extracted */
+ Gray* toGray0(unsigned char bpc_);
+ RGB * toRGB0(unsigned char bpc_);
+ /** @return if any pixels are not gray: false. otherwise: true or false. */
+ public:
+ inline bool hasTransp() const { return transpc!=0x1000000UL; }
+ virtual bool canGray() const =0;
+ /** @return an RGB BitsPerComponent number (1,2,4 or 8) to which the image
+ * could be converted without any loss. The default implementation calls
+ * copyRGBRow().
+ */
+ virtual unsigned char minRGBBpc() const;
+ inline virtual ~Sampled() { delete [] const_cast<char*>(beg); }
+ /** Copies whichrow as wd*3 bytes (R0,G0,B0,R1,G1,B1...) to `to' */
+ virtual void copyRGBRow(char *to, dimen_t whichrow) const =0;
+ virtual bool hasPixelRGB(Image::Sampled::rgb_t rgb) const;
+ inline char *getRowbeg() const { return rowbeg; }
+ inline dimen_t getWd() const { return wd; }
+ inline dimen_t getHt() const { return ht; }
+ inline unsigned char getTy() const { return ty; }
+ inline unsigned char getBpc() const { return bpc; }
+ inline unsigned char getCpp() const { return cpp; }
+ inline unsigned char getCs() const { return cs; }
+ inline slen_t getXoffs() const { return xoffs; }
+ inline rlen_t getRlen() const { return rlen; }
+ inline rgb_t getTranspc() const { return transpc; }
+ inline char *getHeadp() const { return headp; }
+ /** Convert samples, make bpc=8. */
+ virtual void to8() =0;
+ /** @return NULLP if too many colors for indexed; otherwise a new Image::Indexed.
+ * The caller should `delete' (this) if toIndexed()==NULLP.
+ */
+ virtual /*Image::*/Indexed* toIndexed() =0;
+ virtual /*Image::*/RGB* toRGB(unsigned char bpc_) =0;
+ virtual /*Image::*/Gray* toGray(unsigned char bpc_) =0;
+ // virtual void setBpc(unsigned char bpc_) =0;
+ friend GenBuffer::Writable& operator<<(GenBuffer::Writable&, /*Image::*/Sampled const&);
+ /** @return address of static buffer: "#RRGGBB" */
+ static char *rgb2webhash(rgb_t);
+ /** @return (this) or an image containing (this) composed with alpha
+ * channel `al'
+ */
+ virtual Sampled* addAlpha(/*Image::*/Gray *al) =0;
+ /** assert(al.bpp=8) etc. Imp: document this */
+ static Indexed* addAlpha0(Indexed *iimg, Gray *al);
+ };
+
+ class Indexed: public Sampled {
+ public:
+ /** @param ncols_ must be >= the colors used */
+ Indexed(dimen_t wd_, dimen_t ht_, unsigned short ncols_, unsigned char bpc_);
+ /** This includes the transparent color as well. */
+ inline unsigned short getNcols() const { return (rowbeg-headp)/3; }
+ /** Destroys the color table, and creates one with ncols_ colors.
+ * @param ncols_ must be <= the ncols_ specified in the constructor
+ */
+ void setNcols(unsigned short ncols_);
+ /** Decreases the size of the palette (forgets last colors) to the
+ * specified amount.
+ */
+ void setNcolsMove(unsigned short ncols_);
+ void setPal(unsigned char coloridx, rgb_t rgb);
+ rgb_t getPal(unsigned char coloridx) const;
+ /** @param coloridx must be >=0, transp must be -1 */
+ void setTransp(unsigned char coloridx);
+ /** @return new hasTransp */
+ bool setTranspc(rgb_t color);
+ /** Returns like setTranspc, but doesn't change the image.
+ * @return new hasTransp
+ */
+ bool wouldSetTranspc(rgb_t color) const;
+ /** Like setTranspc, but if it makes any changes, then it calls
+ * packPal() and changes back bpc to its old value.
+ */
+ void setTranspcAndRepack(rgb_t color);
+ virtual void copyRGBRow(char *to, dimen_t whichrow) const;
+ /* virtual bool hasPixelRGB(Image::Sampled::rgb_t rgb) const; */
+ /** Packs (compresses) the palette so that it will be continuous in
+ * 0..ncols-1, and each color will be used exactly once. The
+ * transparent color (if present) will become black. As a side-effect,
+ * packPal() may set (this)->bpc=8.
+ */
+ void packPal();
+ virtual void to8();
+ virtual /*Image::*/Indexed* toIndexed();
+ virtual /*Image::*/RGB* toRGB(unsigned char bpc_);
+ virtual /*Image::*/Gray* toGray(unsigned char bpc_);
+ virtual bool canGray() const;
+ inline signed short getTransp() const { return transp; }
+ inline signed short getClearTransp() { signed short ret=transp; transp=-1; return ret; }
+ /** if (transp>0) transp=0;, converts image data. Does not change bpc. */
+ void makeTranspZero();
+ virtual unsigned char minRGBBpc() const;
+ /** Separates the current image into Indexed1 images. The caller is
+ * recommended to call packPal() first to reduce the number of required
+ * images.
+ * As a side-effect,
+ * separate() may set (this)->bpc=8.
+ * @return the array of images after full color separation: that is
+ * a dynamically allocated array of `getNcols()-(getTransp()!=-1)'
+ * Indexed images: each image is Indexed1, color 0 is opaque (with the
+ * color obtained from (this)), color 1 is transparent. The returned
+ * array is NULLP-terminated.
+ */
+ Indexed **separate();
+ /** Also calls packPal(). As a side effect, changes all transparent
+ * pixels to color index 0.
+ * @return NULLP if no transparent pixels.
+ */
+ Indexed *calcAlpha();
+ /** Deletes all elements of p, but not p itself.
+ * @param p a NULLP-terminated list of (Indexed*)s.
+ */
+ static void delete_separated(Indexed **p);
+ /** Reorganizes the image so it will have the specified bpc. Issues a
+ * runtime error if the specified bpc cannot be achieved.
+ * @param bpc_ the desired bpc, or 0: the best achievable.
+ */
+ virtual void setBpc(unsigned char bpc_);
+ void dumpDebug(GenBuffer::Writable& gw);
+ protected:
+ /* Index of the transparent color, or -1. */
+ signed short transp;
+ virtual /*Image::*/Sampled* addAlpha(/*Image::*/Gray *al);
+ /** Sorts the palette colors in lexicographic, stable order.
+ * Called from packPal() to get a consistent palette.
+ */
+ void sortPal();
+ };
+ class Gray: public Sampled {
+ public:
+ Gray(dimen_t wd_, dimen_t ht_, unsigned char bpc_);
+ virtual void copyRGBRow(char *to, dimen_t whichrow) const;
+ virtual bool hasPixelRGB(Image::Sampled::rgb_t rgb) const;
+ virtual void to8();
+ virtual /*Image::*/Indexed* toIndexed();
+ virtual bool canGray() const;
+ // virtual void setBpc(unsigned char bpc_);
+ virtual /*Image::*/RGB * toRGB(unsigned char bpc_);
+ virtual /*Image::*/Gray * toGray(unsigned char bpc_);
+ virtual /*Image::*/Sampled* addAlpha(/*Image::*/Gray *al);
+ /** Calls to8(). */
+ void calcExtrema(unsigned char &lightest, unsigned char &darkest);
+ };
+ class RGB: public Sampled {
+ public:
+ RGB(dimen_t wd_, dimen_t ht_, unsigned char bpc_);
+ virtual void copyRGBRow(char *to, dimen_t whichrow) const;
+ /* virtual bool hasPixelRGB(Image::Sampled::rgb_t rgb) const; */
+ virtual void to8();
+ virtual /*Image::*/Indexed* toIndexed();
+ virtual bool canGray() const;
+ // virtual void setBpc(unsigned char bpc_);
+ virtual /*Image::*/RGB * toRGB(unsigned char bpc_);
+ virtual /*Image::*/Gray * toGray(unsigned char bpc_);
+ virtual /*Image::*/Sampled* addAlpha(/*Image::*/Gray *al);
+ };
+
+ /** Avoid including <stdio.h> */
+ typedef void *filep_t;
+
+ /** Describes a driver that can load a specific image file format. */
+ struct Loader {
+ /** Filter::UngetFILED */
+ class UFD;
+ /** A function that can (allocate and) load a sampled image. Never
+ * returns NULL. On error, it calls Error::.... The filep_t argument
+ * should be really cast back to FILE*. The reader must fclose the FILE*.
+ */
+ // typedef Sampled*(*reader_t)(filep_t, SimBuffer::Flat const& loadHints);
+ typedef Sampled*(*reader_t)(UFD* ufd, SimBuffer::Flat const& loadHints);
+ BEGIN_STATIC_ENUM1(unsigned) MAGIC_LEN=64 END_STATIC_ENUM()
+ /** A function that checks the magic numbers at the beginning of a file
+ * (already read into buf), and returns NULL if it cannot load an image
+ * of that type, or a reader_t that will load the image. If (and only if!)
+ * file is shorter than 64 bytes, the buf is padded with '\000' bytes.
+ * @param f may read from freely if necessary (MAGIC_LEN is short), but
+ * has to call rewind(f) before reading
+ */
+ typedef reader_t(*checker_t)(char buf[MAGIC_LEN], char bufend[MAGIC_LEN], SimBuffer::Flat const& loadHints, UFD* ufd);
+ /** A null-terminated, compact string describing (not defining!) the image
+ * file format.
+ * Examples: "GIF", "XPM", "PNM"
+ */
+ char const*format;
+ checker_t checker;
+ /** Null or next loader. */
+ Loader *next;
+ };
+
+ /** Registers a new type of image Loader, i.e a new image file format. The
+ * new image format will be put in front of all others, and will be checked
+ * first
+ */
+ static void register0(Loader *);
+ /** Loads the image contained in te file `filename'.
+ * @param format NULLP is unknown (load any format)
+ * or an Image::Loader::format already registered
+ */
+ static Sampled* load(Loader::UFD* ufd, SimBuffer::Flat const& loadHints, char const* format);
+ static Sampled* load(char const *filename, SimBuffer::Flat const& loadHints, filep_t stdin_f=(filep_t*)NULLP, char const* format=(char const*)NULLP);
+ /* Prints the list of available Loaders (->format), separated by spaces.
+ * Returns the number of available Loaders. Prepends a space if >= loaders.
+ */
+ static unsigned printLoaders(GenBuffer::Writable &);
+
+ /** SampleFormat constants */
+ BEGIN_STATIC_ENUM(unsigned, sf_t)
+ SF_None=0, /* no specific sample format */
+ SF_Opaque=1,
+ SF_Transparent=2,
+ SF_Gray1=3,
+ SF_Indexed1=4,
+ SF_Mask=5,
+ SF_Transparent2=6,
+ SF_Gray2=7,
+ SF_Indexed2=8,
+ SF_Transparent4=9,
+ SF_Rgb1=10,
+ SF_Gray4=11,
+ SF_Indexed4=12,
+ SF_Transparent8=13,
+ SF_Rgb2=14,
+ SF_Gray8=15,
+ SF_Indexed8=16,
+ SF_Rgb4=17,
+ SF_Rgb8=18,
+ SF_Asis=19,
+ SF_Bbox=20,
+ SF_max=31
+ END_STATIC_ENUM()
+
+ /** Contains (and memory-manages) an image, and optimization information
+ * as a cache.
+ *
+ * A SampledInfo contains an image in a canonical format. That is, if two
+ * images have the same RGB8 (identical width, height and pixels) or
+ * blackbox (identical bytes) representation, and SampledInfo{} are
+ * created for both of them, it is guaranteed that the two SampledInfo{}s
+ * contain the same image data (width, height, canGray, minRGBBpc,
+ * SampleFormat (except for bpc), pixel data, palette (same size, colors
+ * and color order)).
+ */
+ class SampledInfo {
+ public:
+ /** This constructor call takes ownership of the `img_' pointer: it either
+ * reuses the original image (and will delete it in ~SampledInfo), or it
+ * immediately deletes the image, and uses another image.
+ */
+ SampledInfo(Sampled *img_);
+ ~SampledInfo();
+ inline Sampled* getImage() const { return img; }
+ /**
+ * Source image, may be modified even if TryOnly==false. If
+ * modified, the original will be freed.
+ * @param sf desired sample format, see Image::SF_* constants
+ * @param WarningOK if false: make the conversion fail if it would produces
+ * a Warning
+ * @param TryOnly if true: don't do the real conversion (but may do auxilary,
+ * idempontent, helper conversion), assume it has succeeded
+ * @param Transparent: as part of the conversion, try to make this RGB color
+ * transparent
+ * @return true iff the conversion succeeded. Note that img may be the same
+ * pointer even when true is returned. If false is returned, keeps
+ * the image unchanged.
+ */
+ bool setSampleFormat(sf_t sf, bool WarningOK, bool TryOnly, Sampled::rgb_t Transparent);
+ inline Indexed **getImgs() const { return imgs; }
+ inline Sampled *getImg() const { return img; }
+ inline unsigned getNncols() const { return nncols; }
+ void separate();
+ inline bool canGrayy() const { return canGray; }
+ inline unsigned char minRGBBpcc() const { return minRGBBpc; }
+ inline bool hasTranspp() const { return hasTransp; }
+ inline unsigned char minGrayBpcc() const { return canGray ? minRGBBpc : 0; }
+ inline void clearTransp() { hasTransp=false; }
+ protected:
+ bool hasTransp;
+ /** Number of non-transparent colors, or 257 if >=257. */
+ unsigned nncols;
+ /** Has only gray colors. */
+ bool canGray;
+ unsigned char minRGBBpc;
+ Sampled *img;
+ /** The array of images after full color separation. May be NULLP (default),
+ * or a dynamically allocated array of `nncols' Indexed images: each
+ * image is Indexed1, color 0 is opaque (with any value), color 1
+ * is transparent.
+ */
+ Indexed **imgs;
+ sf_t sf;
+ };
+};
+
+/** Dumps this Image as a rawbits PPM file (plus a comment indicating transparency)
+ * @return the Writable.
+ */
+GenBuffer::Writable& operator<<(GenBuffer::Writable&, Image::Sampled const&);
+
+#endif
diff --git a/graphics/sam2p/in_bmp.cpp b/graphics/sam2p/in_bmp.cpp
new file mode 100644
index 0000000000..6a683b23bc
--- /dev/null
+++ b/graphics/sam2p/in_bmp.cpp
@@ -0,0 +1,49 @@
+/*
+ * in_bmp.cpp -- read a Windows(?) BMP bitmap file
+ * by pts@fazekas.hu at Sat Mar 2 00:46:54 CET 2002
+ *
+ */
+
+#ifdef __GNUC__
+#ifndef __clang__
+#pragma implementation
+#endif
+#endif
+
+#include "image.hpp"
+#include "error.hpp"
+
+#if USE_IN_BMP
+
+#include "gensio.hpp"
+#include "input-bmp.ci"
+
+static Image::Sampled *in_bmp_reader(Image::Loader::UFD *ufd, SimBuffer::Flat const&) {
+ Image::Sampled *ret=0;
+ bitmap_type bitmap=bmp_load_image(((Filter::UngetFILED*)ufd)->getFILE(/*seekable:*/false));
+ /* Imp: Work without duplicated memory allocation */
+ if (BITMAP_PLANES(bitmap)==1) {
+ Image::Gray *img=new Image::Gray(BITMAP_WIDTH(bitmap), BITMAP_HEIGHT(bitmap), 8);
+ memcpy(img->getRowbeg(), BITMAP_BITS(bitmap), (slen_t)BITMAP_WIDTH(bitmap)*BITMAP_HEIGHT(bitmap));
+ ret=img;
+ } else if (BITMAP_PLANES(bitmap)==3) {
+ Image::RGB *img=new Image::RGB(BITMAP_WIDTH(bitmap), BITMAP_HEIGHT(bitmap), 8);
+ memcpy(img->getRowbeg(), BITMAP_BITS(bitmap), (slen_t)3*BITMAP_WIDTH(bitmap)*BITMAP_HEIGHT(bitmap));
+ ret=img;
+ } else assert(0 && "invalid BMP depth");
+ delete [] BITMAP_BITS(bitmap);
+ return ret;
+}
+
+static Image::Loader::reader_t in_bmp_checker(char buf[Image::Loader::MAGIC_LEN], char [Image::Loader::MAGIC_LEN], SimBuffer::Flat const&, Image::Loader::UFD*) {
+ return (buf[0]=='B' && buf[1]=='M'
+ && buf[6]==0 && buf[7]==0 && buf[8]==0 && buf[9]==0
+ && (unsigned char)(buf[14])<=64 && buf[15]==0 && buf[16]==0 && buf[17]==0)
+ ? in_bmp_reader : 0;
+}
+
+#else
+#define in_bmp_checker NULLP
+#endif /* USE_IN_BMP */
+
+Image::Loader in_bmp_loader = { "BMP", in_bmp_checker, 0 };
diff --git a/graphics/sam2p/in_gif.cpp b/graphics/sam2p/in_gif.cpp
new file mode 100644
index 0000000000..acd47d5224
--- /dev/null
+++ b/graphics/sam2p/in_gif.cpp
@@ -0,0 +1,91 @@
+/*
+ * in_gif.cpp -- read a Compuserve GIF file
+ * by pts@fazekas.hu at Fri Mar 1 22:28:46 CET 2002
+ *
+ */
+
+/*The creators of the GIF format require the following
+ acknowledgement:
+ The Graphics Interchange Format(c) is the Copyright property of
+ CompuServe Incorporated. GIF(sm) is a Service Mark property of
+ CompuServe Incorporated.
+*/
+
+#ifdef __GNUC__
+#ifndef __clang__
+#pragma implementation
+#endif
+#endif
+
+#ifdef USE_GNU_SOURCE_INSTEAD_OF_POSIX_SOURCE
+#define _GNU_SOURCE 1 /* Implies _POSIX_C_SOURCE and _POSIX_C_SOURCE >= 2. */
+#else
+#define _POSIX_SOURCE 1
+#define _POSIX_C_SOURCE 2
+#endif
+
+#include "config2.h" /* SUXX, ignores features.h */
+
+#if USE_IN_GIF
+
+#include "cgif.h"
+#include "cgif.c" /* _POSIX_SOURCE */
+#include "image.hpp"
+#include "error.hpp"
+#include "gensio.hpp"
+
+#undef CGIFFF
+#define CGIFFF CGIF::
+
+static Image::Sampled *in_gif_reader(Image::Loader::UFD *ufd, SimBuffer::Flat const&) {
+ Image::Indexed *img;
+ CGIFFF GifFileType *giff;
+ CGIFFF SavedImage *sp;
+ CGIFFF ColorMapObject *cm;
+ char const *err;
+
+ /* Dat: (CGIFFF GetGifError() || "unknown error") doesn't work like in Perl or Ruby */
+ if (0==(giff=CGIFFF DGifOpenFILE(((Filter::UngetFILED*)ufd)->getFILE(/*seekable:*/false))) || GIF_ERROR==CGIFFF DGifSlurp(giff))
+ Error::sev(Error::EERROR) << "GIF: " << ((err=CGIFFF GetGifError()) ? err : "unknown error") << (Error*)0;
+ if (giff->ImageCount<1)
+ Error::sev(Error::EERROR) << "GIF: no image in file" << (Error*)0;
+
+ sp=giff->SavedImages+0;
+ cm = (sp->ImageDesc.ColorMap ? sp->ImageDesc.ColorMap : giff->SColorMap);
+ img=new Image::Indexed(sp->ImageDesc.Width, sp->ImageDesc.Height, cm->ColorCount, 8);
+ CGIFFF GifColorType *co=cm->Colors, *ce=co+cm->ColorCount;
+ char *p=img->getHeadp();
+ while (co!=ce) { *p++=(char)co->Red; *p++=(char)co->Green; *p++=(char)co->Blue; co++; }
+ // fprintf(stderr, "transp=%d\n", sp->transp);
+ if (sp->transp!=-1) img->setTransp(sp->transp);
+ /* ^^^ comment out this line to ignore transparency of the GIF file */
+
+ assert(1L*sp->ImageDesc.Width*sp->ImageDesc.Height<=img->end_()-img->getRowbeg());
+ memcpy(img->getRowbeg(), sp->RasterBits, (slen_t)sp->ImageDesc.Width*sp->ImageDesc.Height);
+
+ CGIFFF DGifCloseFile(giff); /* also frees memory structure */
+
+ return img;
+}
+
+static Image::Loader::reader_t in_gif_checker(char buf[Image::Loader::MAGIC_LEN], char [Image::Loader::MAGIC_LEN], SimBuffer::Flat const&, Image::Loader::UFD*) {
+ return (0==memcmp(buf,"GIF87a",6) || 0==memcmp(buf,"GIF89a",6)) ? in_gif_reader : 0;
+}
+
+#define in_gif_name "GIF"
+
+#else
+#include <string.h>
+#include "image.hpp"
+#include "error.hpp"
+#define in_gif_name (char const*)NULLP
+/* #define in_gif_checker (Image::Loader::checker_t)NULLP */
+static Image::Loader::reader_t in_gif_checker(char buf[Image::Loader::MAGIC_LEN], char [Image::Loader::MAGIC_LEN], SimBuffer::Flat const&, Image::Loader::UFD*) {
+ if (0==memcmp(buf,"GIF87a",6) || 0==memcmp(buf,"GIF89a",6)) {
+ Error::sev(Error::WARNING) << "loader: please `configure --enable-gif' for loading GIF files" << (Error*)0;
+ }
+ return 0;
+}
+#endif /* USE_IN_GIF */
+
+Image::Loader in_gif_loader = { in_gif_name, in_gif_checker, 0 };
diff --git a/graphics/sam2p/in_jai.cpp b/graphics/sam2p/in_jai.cpp
new file mode 100644
index 0000000000..0479070813
--- /dev/null
+++ b/graphics/sam2p/in_jai.cpp
@@ -0,0 +1,394 @@
+/*
+ * in_jai.cpp -- read a JPEG file as-is
+ * by pts@math.bme.hu at Sun Mar 17 20:15:25 CET 2002
+ */
+/* Imp: test this code with various JPEG files! */
+
+#ifdef __GNUC__
+#ifndef __clang__
+#pragma implementation
+#endif
+#endif
+
+#include "image.hpp"
+#include "error.hpp"
+
+#if USE_IN_JAI
+
+#include "in_jai.hpp"
+#include <string.h> /* memchr() */
+#include <stdio.h>
+
+/* --- */
+
+class JAI: public Image::Sampled {
+ public:
+ /** (Horiz<<4+Vert) sampling factor for the first color component. Usually
+ * 0x11, but TIFF defaults to 0x22.
+ */
+ JAI(dimen_t wd_, dimen_t ht_, unsigned char bpc_, unsigned char cs_, slen_t flen_, slen_t SOF_offs_, unsigned char hvs_);
+ virtual void copyRGBRow(char *to, dimen_t whichrow) const;
+ virtual void to8();
+ virtual Image::Indexed* toIndexed();
+ virtual bool canGray() const;
+ // virtual void setBpc(unsigned char bpc_);
+ virtual Image::RGB * toRGB(unsigned char bpc_);
+ virtual Image::Gray * toGray(unsigned char bpc_);
+ virtual unsigned char minRGBBpc() const;
+ virtual Image::Sampled* addAlpha(Image::Gray *al);
+ void fixEOI();
+};
+
+JAI::JAI(dimen_t wd_, dimen_t ht_, unsigned char bpc_, unsigned char cs_, slen_t flen_, slen_t SOF_offs_, unsigned char hvs_) {
+ param_assert(cs_<=5);
+ // init(0,0,wd_,ht_,bpc_,TY_BLACKBOX,cs2cpp[cs_]);
+ cs=cs_;
+ bpc=8; (void)bpc_; // bpc=bpc_; /* /DCTDecode supports only BitsPerComponent==8 */
+ ty=TY_BLACKBOX;
+ wd=wd_;
+ ht=ht_;
+ cpp=cs2cpp[cs_];
+ // pred=1;
+ transpc=0x1000000UL; /* Dat: this means: no transparent color */
+ rlen=0;
+ beg=new char[len=0+flen_+0+bpc];
+ rowbeg=(headp=const_cast<char*>(beg))+flen_;
+ xoffs=SOF_offs_;
+ trail=const_cast<char*>(beg)+len-bpc;
+ const_cast<char*>(beg)[len-1]=hvs_; /* dirty place */
+}
+
+void JAI::fixEOI() {
+ /* by pts@fazekas.hu at Tue Jun 4 15:36:12 CEST 2002 */
+ if (rowbeg[-2]!='\xFF' || rowbeg[-1]!='\xD9') {
+ *rowbeg++='\xFF';
+ *rowbeg++='\xD9';
+ }
+}
+
+Image::Sampled* JAI::addAlpha(Image::Gray *) {
+ Error::sev(Error::WARNING) << "JAI: alpha channel ignored" << (Error*)0;
+ return this;
+}
+
+
+unsigned char JAI:: minRGBBpc() const { return bpc; }
+void JAI::copyRGBRow(char*, dimen_t) const { assert(0); }
+void JAI::to8() { assert(0); }
+Image::Indexed* JAI::toIndexed() { return (Image::Indexed*)NULLP; }
+bool JAI::canGray() const { return cs==CS_GRAYSCALE; }
+Image::RGB * JAI::toRGB(unsigned char) { assert(0); return 0; }
+Image::Gray * JAI::toGray(unsigned char) { assert(0); return 0; }
+
+/* --- The following code is based on standard/image.c from PHP4 */
+
+/* some defines for the different JPEG block types */
+#define M_SOF0 0xC0 /* Start Of Frame0: Baseline JPEG */
+#define M_SOF1 0xC1 /* N indicates which compression process */
+#define M_SOF2 0xC2 /* Only SOF0-SOF2 are now in common use */
+#define M_SOF3 0xC3
+#define M_SOF5 0xC5 /* NB: codes C4 and CC are NOT SOF markers */
+#define M_SOF6 0xC6
+#define M_SOF7 0xC7
+#define M_SOF9 0xC9
+#define M_SOF10 0xCA
+#define M_SOF11 0xCB
+#define M_SOF13 0xCD
+#define M_SOF14 0xCE
+#define M_SOF15 0xCF
+#define M_SOI 0xD8
+#define M_EOI 0xD9 /* End Of Image (end of datastream) */
+#define M_SOS 0xDA /* Start Of Scan (begins compressed data) */
+#define M_APP0 0xe0
+#define M_APP1 0xe1
+#define M_APP2 0xe2
+#define M_APP3 0xe3
+#define M_APP4 0xe4
+#define M_APP5 0xe5
+#define M_APP6 0xe6
+#define M_APP7 0xe7
+#define M_APP8 0xe8
+#define M_APP9 0xe9
+#define M_APP10 0xea
+#define M_APP11 0xeb
+#define M_APP12 0xec
+#define M_APP13 0xed
+#define M_APP14 0xee
+#define M_APP15 0xef
+
+
+#if 0
+static unsigned int jai_next_marker(FILE *fp)
+ /* get next marker byte from file */
+{
+ int c;
+
+#if 0 /**** pts ****/
+ /* skip unimportant stuff */
+ c = MACRO_GETC(fp);
+ while (c != 0xff) {
+ if ((c = MACRO_GETC(fp)) == EOF)
+ return M_EOI; /* we hit EOF */
+ }
+#else
+ if (0xff!=(c=MACRO_GETC(fp))) return M_EOI;
+#endif
+
+
+ /* get marker byte, swallowing possible padding */
+ do {
+ if ((c = MACRO_GETC(fp)) == EOF)
+ return M_EOI; /* we hit EOF */
+ } while (c == 0xff);
+
+ return (unsigned int) c;
+}
+#endif
+
+#if 0
+static inline int getc_(FILE *f) { return MACRO_GETC(f); }
+static inline long ftell_(FILE *f) { return ftell(f); }
+template <class T>
+static unsigned short jai_read2(T *fp);
+template <class T>
+static void jai_handle_jpeg(struct jai_gfxinfo *result, T *fp) {
+#endif
+/* Dat: removed templates at Tue Mar 11 19:59:16 CET 2003, because decoding
+ * JPEG headers isn't time-critical
+ */
+
+static inline unsigned short jai_read2(GenBuffer::Readable *fp) {
+#if 0
+ unsigned char a[ 2 ];
+ /* just return 0 if we hit the end-of-file */
+ if (fread(a,sizeof(a),1,fp) != 1) return 0;
+ return (((unsigned short) a[ 0 ]) << 8) + ((unsigned short) a[ 1 ]);
+#else
+ int a=fp->vi_getcc(), b=fp->vi_getcc();
+ /* just return 0 if we hit the end-of-file */
+ return a>=0 && b>=0 ? (a<<8)+b : 0;
+#endif
+}
+
+/** main loop to parse JPEG structure */
+void jai_parse_jpeg(struct jai_gfxinfo *result, DecoderTeller *fp, bool must_be_baseline) {
+ int c;
+ unsigned int length;
+ unsigned char had_adobe;
+
+ result->bad=9; /* signal invalid return value */
+ result->id_rgb=0;
+ result->had_jfif=0;
+ result->colortransform=127; /* no Adobe marker yet */
+ // fseek(fp, 0L, SEEK_SET); /* position file pointer on SOF */
+
+ /* Verify JPEG header */
+ /* Dat: maybe 0xFF != '\xFF' */
+ if ((c=fp->vi_getcc())!=0xFF) return;
+ while ((c=fp->vi_getcc())==0xFF) ;
+ if (c!=M_SOI) return;
+
+ result->bad=1;
+ // fprintf(stderr, "welcome ofs=%ld\n", fp->vi_tell());
+ while (1) {
+ if ((c=fp->vi_getcc())!=0xFF) { result->bad=8; return; }
+ while ((c=fp->vi_getcc())==0xFF) ;
+ if (c==-1) { result->bad=2; return; }
+ switch (c) {
+ case M_SOF0: do_SOF:
+ if (result->bad!=1) { result->bad=4; return; } /* only one M_SOF allowed */
+ result->SOF_type=c-M_SOF0;
+ result->SOF_offs=fp->vi_tell();
+ // fprintf(stderr, "SOF_offs=%d\n", result->SOF_offs);
+ /* handle SOFn block */
+ length=jai_read2(fp);
+ result->bpc = fp->vi_getcc();
+ result->height = jai_read2(fp);
+ result->width = jai_read2(fp);
+ result->cpp = fp->vi_getcc();
+ if ((length-=8)!=3U*result->cpp) return;
+ if (result->bpc!=8) { result->bad=6; return; }
+ if (result->cpp!=1 && result->cpp!=3 && result->cpp!=4) { result->bad=5; return; }
+ assert(length>=3);
+ if (result->cpp==3) {
+ result->id_rgb =fp->vi_getcc()=='R'; result->hvs=fp->vi_getcc(); fp->vi_getcc();
+ result->id_rgb&=fp->vi_getcc()=='G'; fp->vi_getcc(); fp->vi_getcc();
+ result->id_rgb&=fp->vi_getcc()=='B'; fp->vi_getcc(); fp->vi_getcc();
+ } else { length-=2; fp->vi_getcc(); result->hvs=fp->vi_getcc(); while (length--!=0) fp->vi_getcc(); }
+ result->bad=2;
+ break;
+ case M_SOF1:
+ case M_SOF2:
+ case M_SOF3:
+ case M_SOF5:
+ case M_SOF6:
+ case M_SOF7:
+ case M_SOF9:
+ case M_SOF10:
+ case M_SOF11:
+ case M_SOF13:
+ case M_SOF14:
+ case M_SOF15:
+ if (!must_be_baseline) goto do_SOF;
+ // fprintf(stderr, "SOF%u\n", marker-M_SOF0); assert(0);
+ result->bad=3;
+ return;
+ case M_SOS: /* we are about to hit image data. We're done. Success. */
+ if (result->bad==2 /* && !feof(fp)*/) { /* Dat: !feof() already guaranteed */
+ if (result->cpp==1) {
+ result->colorspace=Image::Sampled::CS_GRAYSCALE;
+ } else if (result->cpp==3) {
+ result->colorspace=Image::Sampled::CS_YCbCr;
+ if (result->had_jfif!=0) ;
+ else if (result->colortransform==0) result->colorspace=Image::Sampled::CS_RGB;
+ else if (result->colortransform==1) ;
+ else if (result->colortransform!=127) Error::sev(Error::EERROR) << "JAI: unknown ColorTransform: " << (unsigned)result->colortransform << (Error*)0;
+ else if (result->id_rgb!=0) result->colorspace=Image::Sampled::CS_RGB;
+ /* Imp: check for id_ycbcr */
+ else Error::sev(Error::WARNING) << "JAI: assuming YCbCr color space" << (Error*)0;
+ } else if (result->cpp==4) {
+ result->colorspace=Image::Sampled::CS_CMYK;
+ if (result->colortransform==0) ;
+ else if (result->colortransform==2) result->colorspace=Image::Sampled::CS_YCCK;
+ else if (result->colortransform!=127) Error::sev(Error::EERROR) << "JAI: unknown ColorTransform: " << (unsigned)result->colortransform << (Error*)0;
+ } else assert(0);
+ result->bad=0;
+ }
+ /* fall through */
+ case M_EOI: /* premature EOF */
+ return;
+ case M_APP0: /* JFIF application-specific marker */
+ length=jai_read2(fp);
+ if (length==2+4+1+2+1+2+2+1+1) {
+ result->had_jfif=fp->vi_getcc()=='J' && fp->vi_getcc()=='F' && fp->vi_getcc()=='I' &&
+ fp->vi_getcc()=='F' && fp->vi_getcc()==0;
+ length-=7;
+ } else length-=2;
+ while (length--!=0) fp->vi_getcc();
+ break;
+ case M_APP14: /* Adobe application-specific marker */
+ length=jai_read2(fp);
+ if ((length-=2)==5+2+2+2+1) {
+ had_adobe=fp->vi_getcc()=='A' && fp->vi_getcc()=='d' && fp->vi_getcc()=='o' &&
+ fp->vi_getcc()=='b' && fp->vi_getcc()=='e' && ((unsigned char)fp->vi_getcc())>=1;
+ fp->vi_getcc(); fp->vi_getcc(); fp->vi_getcc(); fp->vi_getcc(); fp->vi_getcc();
+ if (had_adobe) result->colortransform=fp->vi_getcc();
+ else fp->vi_getcc();
+ } else while (length--!=0) fp->vi_getcc();
+ break;
+ case M_APP1:
+ case M_APP2:
+ case M_APP3:
+ case M_APP4:
+ case M_APP5:
+ case M_APP6:
+ case M_APP7:
+ case M_APP8:
+ case M_APP9:
+ case M_APP10:
+ case M_APP11:
+ case M_APP12:
+ case M_APP13:
+ case M_APP15:
+ /* fall through */
+ default: { /* anything else isn't interesting */
+ /* skip over a variable-length block; assumes proper length marker */
+ unsigned short length;
+ length = jai_read2(fp);
+ length -= 2; /* length includes itself */
+ #if 0 /**** pts: fseek would disturb later ftell()s and feof()s */
+ fseek(fp, (long) length, SEEK_CUR); /* skip the header */
+ #else
+ while (length--!=0) fp->vi_getcc(); /* make feof(fp) correct */
+ #endif
+ }
+ }
+ }
+}
+
+char const*jai_errors[]={
+ (char const*)NULLP,
+ /*1*/ "missing SOF0 marker",
+ /*2*/ "premature EOF",
+ /*3*/ "not a Baseline JPEG (SOF must be SOF0)",
+ /*4*/ "more SOF0 markers",
+ /*5*/ "bad # components",
+ /*6*/ "bad bpc",
+ /*7*/ "?",
+ /*8*/ "0xFF expected",
+ /*9*/ "invalid JPEG header",
+ // /*10*/ "not ending with EOI", /* not output by jai_handle_jpeg! */
+};
+
+static Image::Sampled *in_jai_reader(Image::Loader::UFD* ufd, SimBuffer::Flat const&) {
+ // assert(0);
+ struct jai_gfxinfo gi;
+ Filter::UngetFILED* ufdd=(Filter::UngetFILED*)ufd;
+ FILE *file_=ufdd->getFILE(/*seekable:*/true);
+ jai_parse_jpeg(&gi, ufdd);
+ // jai_parse_jpeg(&gi, (FILE*)file_);
+ // long ftel=ftell((FILE*)file_);
+ if (gi.bad!=0) Error::sev(Error::EERROR) << "JAI: " << jai_errors[gi.bad] << (Error*)0;
+ // printf("ftell=%lu\n", ftell((FILE*)file_));
+ fseek((FILE*)file_, 0L, 2); /* EOF */
+ long flen=ftell((FILE*)file_); /* skip extra bytes after EOI. Imp: no need to do this */
+ // fprintf(stderr, "flen=%lu\n", flen);
+ assert(flen>2);
+ rewind((FILE*)file_);
+ JAI *ret=new JAI(gi.width,gi.height,gi.bpc,gi.colorspace,flen,gi.SOF_offs,gi.hvs);
+ if (fread(ret->getHeadp(), flen, 1, (FILE*)file_)!=1 || ferror((FILE*)file_)) {
+ ret->fixEOI();
+ /* fclose((FILE*)file_); */
+ Error::sev(Error::EERROR) << "JAI: IO error" << (Error*)0;
+ }
+ /* fclose((FILE*)file_); */
+ return ret;
+}
+
+static Image::Loader::reader_t in_jai_checker(char buf[Image::Loader::MAGIC_LEN], char [Image::Loader::MAGIC_LEN], SimBuffer::Flat const& loadHints, Image::Loader::UFD* ufd) {
+ if (0!=memcmp(buf, "\xff\xd8\xff", 3)
+ || !(loadHints.findFirst((char const*)",jpeg-asis,",6)!=loadHints.getLength() || loadHints.findFirst((char const*)",asis,",6)!=loadHints.getLength())
+ ) return 0;
+ Filter::UngetFILED* ufdd=(Filter::UngetFILED*)ufd;
+ ufdd->seek(0);
+ Image::Loader::reader_t ret=jai_is_baseline_jpeg(ufdd) ? in_jai_reader : 0;
+ ufdd->seek(0);
+ return ret;
+}
+
+#if 0 /* Filter::FlatR* used by JPEGSOF0Encode::vi_write() in appliers.cpp */
+static inline int getc_(Filter::FlatR *f) { return f->getcc(); }
+static inline long ftell_(Filter::FlatR *f) { return f->tell(); }
+void jai_parse_jpeg(struct jai_gfxinfo *result, Filter::FlatR *f) {
+ jai_handle_jpeg(result, f);
+}
+void jai_parse_jpeg(struct jai_gfxinfo *result, FILE *f) {
+ jai_handle_jpeg(result, f);
+}
+#endif
+
+#if 0 /* unused */
+int jai_is_baseline_jpeg(char const* filename) {
+ /* by pts@fazekas.hu at Tue Mar 11 20:27:56 CET 2003 */
+ FILE *f=fopen(filename, "rb");
+ if (!f) return -1;
+ Filter::FILED filed(f, /*closep:*/true);
+ return jai_is_baseline_jpeg(&filed);
+}
+#endif
+int jai_is_baseline_jpeg(/*DecoderTeller*/Filter::UngetFILED *fp) {
+ char buf[3];
+ struct jai_gfxinfo gi;
+ bool qfalse=(3!=fp->vi_read(buf, 3) || 0!=memcmp(buf, "\xff\xd8\xff", 3));
+ fp->unread(buf, 3);
+ if (qfalse) return false;
+ fp->getFILE(/*seekable*/true); /* make it seekable, so the caller can seek back */
+ jai_parse_jpeg(&gi, fp, /*must_be_baseline:*/false);
+ fp->seek(0);
+ return gi.bad!=0 ? -1 : gi.SOF_type==0;
+}
+#else
+#define in_jai_checker (Image::Loader::checker_t)NULLP
+#endif /* USE_IN_JAI */
+
+Image::Loader in_jai_loader = { "JAI", in_jai_checker, 0 };
diff --git a/graphics/sam2p/in_jai.hpp b/graphics/sam2p/in_jai.hpp
new file mode 100644
index 0000000000..4b35105688
--- /dev/null
+++ b/graphics/sam2p/in_jai.hpp
@@ -0,0 +1,48 @@
+/* in_jai.hpp -- Tue Jun 11 19:05:04 CEST 2002
+ */
+
+#ifdef __GNUC__
+#ifndef __clang__
+#pragma interface
+#endif
+#endif
+
+#ifndef IN_JAI_HPP
+#define IN_JAI_HPP 1
+
+#include "config2.h"
+
+#if USE_IN_JAI
+
+#include "gensio.hpp"
+
+struct jai_gfxinfo {
+ /** 0 for baseline JPEG, 1..15 for other JPEG compression */
+ unsigned char SOF_type;
+ unsigned char colorspace;
+ unsigned char bad, bpc, cpp, had_jfif, colortransform, id_rgb;
+ /** (Horiz<<4+Vert) sampling factor for the first color component. Usually
+ * 0x11, but TIFF defaults to 0x22.
+ */
+ unsigned char hvs;
+ /*Image::Sampled::dimen_t*/slen_t height, width;
+ /** Offset of byte just _after_ the first SOF marker (FF C0 or alike)
+ * from the beginning of the file.
+ */
+ slen_t SOF_offs;
+};
+
+extern char const*jai_errors[];
+#if 0
+ extern void jai_parse_jpeg(struct gfxinfo *result, Filter::FlatR *f);
+ extern void jai_parse_jpeg(struct gfxinfo *result, FILE *f);
+#else
+ extern void jai_parse_jpeg(struct jai_gfxinfo *result, DecoderTeller *fp, bool must_be_baseline=true);
+ /** Doesn't treat `-' as a special filename. @return 0, 1, or -1 on I/O error */
+ extern int jai_is_baseline_jpeg(char const* filename);
+ extern int jai_is_baseline_jpeg(/*DecoderTeller*/ Filter::UngetFILED *fp);
+#endif
+
+#endif
+
+#endif /* in_jai.hpp */
diff --git a/graphics/sam2p/in_jpeg.cpp b/graphics/sam2p/in_jpeg.cpp
new file mode 100644
index 0000000000..cceedf634e
--- /dev/null
+++ b/graphics/sam2p/in_jpeg.cpp
@@ -0,0 +1,39 @@
+/*
+ * in_jpeg.cpp -- read JPEG (JFIF and other) files with djpeg
+ * by pts@fazekas.hu at Sun Apr 14 14:50:30 CEST 2002
+ */
+
+#ifdef __GNUC__
+#ifndef __clang__
+#pragma implementation
+#endif
+#endif
+
+#include "image.hpp"
+
+#if USE_IN_JPEG
+
+#include "error.hpp"
+#include "gensio.hpp"
+#include "helpere.hpp"
+#include <string.h> /* memchr() */
+#include <stdio.h> /* printf() */
+
+static Image::Sampled *in_jpeg_reader(Image::Loader::UFD *ufd, SimBuffer::Flat const&) {
+ // Error::sev(Error::EERROR) << "Cannot load JPEG images yet." << (Error*)0;
+ HelperE helper("djpeg"); /* Run external process `djpeg' to convert JPEG -> PNM */
+ Encoder::writeFrom(*(Filter::PipeE*)&helper, *(Filter::UngetFILED*)ufd);
+ ((Filter::PipeE*)&helper)->vi_write(0,0); /* Signal EOF */
+ return helper.getImg();
+}
+
+static Image::Loader::reader_t in_jpeg_checker(char buf[Image::Loader::MAGIC_LEN], char [Image::Loader::MAGIC_LEN], SimBuffer::Flat const& loadHints, Image::Loader::UFD*) {
+ return (0==memcmp(buf, "\xff\xd8", 2)) && loadHints.findFirst((char const*)",asis,",6)==loadHints.getLength()
+ ? in_jpeg_reader : 0;
+}
+
+#else
+#define in_jpeg_checker (Image::Loader::checker_t)NULLP
+#endif /* USE_IN_XPM */
+
+Image::Loader in_jpeg_loader = { "JPEG", in_jpeg_checker, 0 };
diff --git a/graphics/sam2p/in_lbm.cpp b/graphics/sam2p/in_lbm.cpp
new file mode 100644
index 0000000000..cacd5d5a65
--- /dev/null
+++ b/graphics/sam2p/in_lbm.cpp
@@ -0,0 +1,279 @@
+/*
+ * in_lbm.cpp -- read a Deluxe Paint IFF/ILBM file
+ * by pts@fazekas.hu at Fri Mar 1 17:12:16 CET 2002
+ * -- Fri Mar 1 22:28:03 CET 2002
+ *
+ * I've ripped the reader code from xscavenger's source, and enhanced it
+ * a little bit (at Fri Mar 1 17:12:43 CET 2002), but I still think that
+ * this can read only the minority of the LBM files around.
+ */
+/* Imp: get docs about the LBM format, and rewrite this from scratch */
+
+#ifdef __GNUC__
+#ifndef __clang__
+#pragma implementation
+#endif
+#endif
+
+#include "image.hpp"
+#include "error.hpp"
+
+#if USE_IN_LBM
+
+#include <string.h> /* memchr() */
+#include "gensio.hpp"
+
+#define FORM 0x464f524dL
+#define ILBM 0x494c424dL
+#define PBM 0x50424d20L
+#define CMAP 0x434d4150L
+#define BODY 0x424f4459L
+#define BMHD 0x424d4844L
+/* typedef unsigned char uchar; */
+#define MAXBYTES 128 /* ?? */
+
+/* --- */
+
+#if SIZEOF_INT>=4
+typedef unsigned int u32_t;
+typedef signed int s32_t;
+#else
+typedef unsigned long u32_t;
+typedef signed long s32_t;
+#endif
+
+class LBMRead {
+ public:
+ inline LBMRead(FILE *f_): f(f_) {}
+ /* inline ~LBMRead() { fclose(f); } */
+ Image::Sampled *doit();
+ protected:
+ inline int getcn();
+ void errUnEOF();
+ void err(char const*s);
+ u32_t getUnpack(unsigned len, char *where);
+ u32_t getu32();
+ unsigned getu16();
+ FILE *f;
+};
+
+//static inline int fixbyte(char *take,int bit,int depth) {
+// int res=0,mask=1;
+// while (depth--) {
+// if (*take & bit) res|=mask;
+// mask<<=1;
+// take+=MAXBYTES;
+// }
+// return res;
+//}
+#if 0
+static void debit(char *picput, char *lines, unsigned wd, unsigned depth) {
+ unsigned depth2, bit=128, res, i, mask;
+ unsigned byteswide=((wd+15)>>4)<<1;
+ unsigned char *take;
+ for (i=0;i<wd;i++) {
+ mask=1; depth2=depth; take=(unsigned char*)lines; res=0; while (depth2--!=0) {
+ if (0!=(*take&bit)) res|=mask;
+ mask<<=1;
+ take+=byteswide;
+ }
+ *picput++=res;
+ if (bit==1) { bit=128; ++lines; } else bit>>=1;
+ }
+}
+#endif
+
+void LBMRead::errUnEOF() {
+ Error::sev(Error::EERROR) << "LBM: unexpected EOF" << (Error*)0;
+}
+void LBMRead::err(char const*s) {
+ Error::sev(Error::EERROR) << s << (Error*)0;
+}
+
+inline int LBMRead::getcn() {
+ int i=MACRO_GETC(f);
+ if (i==-1) errUnEOF();
+ return i;
+}
+
+u32_t LBMRead::getUnpack(unsigned len, char *where) {
+ /* RLE decompression */
+ int ch,ch2;
+ u32_t sofar=0;
+ while (len>0) {
+ ch=getcn();
+ if (ch<128) {
+ ch++;
+ assert(ch>=1);
+ if (len<(unsigned)ch) err("LBM: packet#1 too long");
+ len-=ch;
+ sofar+=1+ch;
+ while (ch--) *where++=getcn();
+ } else {
+ ch=1-(ch-256); /* 2..129 */
+ assert(ch>=1);
+ // fprintf(stderr, "len=%u ch=%u\n", len, ch);
+ if (len<(unsigned)ch) err("LBM: packet#2 too long");
+ len-=ch;
+ // fprintf(stderr, "xlen=%u ch=%u\n", len, ch);
+ ch2=getcn();
+ sofar+=2;
+ while (ch--) *where++=ch2;
+ }
+ }
+ return sofar;
+}
+
+u32_t LBMRead::getu32() {
+ u32_t val1=0;
+ val1=getcn()<<24L;
+ val1|=getcn()<<16L;
+ val1|=getcn()<<8;
+ val1|=getcn();
+ return val1;
+}
+unsigned LBMRead::getu16() {
+ u32_t val1=0;
+ val1|=getcn()<<8;
+ val1|=getcn();
+ return val1;
+}
+
+Image::Sampled *LBMRead::doit() {
+ char temparea[16];
+ u32_t type, size, i;
+ unsigned char comp=0;
+ unsigned j;
+ int ii;
+ Image::Sampled::dimen_t lbm_wd, lbm_ht, byteswide, depth=0; /* pts */
+ unsigned transp=256;
+ Image::Sampled *img=(Image::Sampled*)NULLP;
+ bool had_cmap=false, had_body=false, do_skip, had_transp=false;
+
+ /* sprintf(temparea,"%s/%s/%s",localname,localdirname,name); */
+ for (i=0;i<12;i++) temparea[i]=getcn();
+ if (0!=memcmp(temparea,"FORM",4) ||
+ 0!=memcmp(temparea+8,"ILBM",4)) err("LBM: magic says: this is not an LBM");
+ lbm_wd=lbm_ht=byteswide=0;
+ while ((ii=MACRO_GETC(f))!=-1 && ii!='\0') {
+ ungetc(ii,f);
+ if ((type=getu32())==0xffffffffL) break;
+ size=getu32();
+ do_skip=(size&1); /* pad to even size */
+ // fprintf(stderr,"size=%u\n", size);
+ if (type==BMHD) {
+ if (img!=NULLP) err("LBM: duplicate BMHD");
+ // if (size>sizeof(temparea)) {
+ // for (i=0;i<sizeof(temparea);i++) temparea[i]=getcn();
+ // for (;i<size;i++) getcn();
+ // } else for (i=0;i<size;i++) temparea[i]=getcn();
+ if (size<20) errUnEOF();
+ lbm_wd=getu16();
+ lbm_ht=getu16();
+ if (getu32()!=0) err("LBM: expected offsets==0");
+ depth=getcn();
+ if (depth!=24 && (depth<1 || depth>8)) err("LBM: invalid color depth");
+ if (getcn()!=0) err("LBM: expected masking==0");
+ if ((comp=getcn())>=2) err("LBM: expected comp==0 || comp==1");
+ getcn(); /* ignore padding */
+ transp=getu16(); /* index of transparent color */
+ // fprintf(stderr, "htt=%u transp=%u\n", lbm_ht, transp);
+ getu16(); /* Ignore aspect ratio. */
+ if (lbm_wd!=getu16() || lbm_ht!=getu16()) err("LBM: inconsistent dimens");
+ /* ^^^ Dat: pagex, pagey */
+ byteswide=((lbm_wd+15)>>4)<<1;
+ /*printf("(%d,%d) %d bpp\n",lbm_wd,lbm_ht,depth);*/
+ if (depth==24) {
+ had_cmap=true;
+ img=new Image::RGB(lbm_wd, lbm_ht, 8);
+ } else {
+ img=new Image::Indexed(lbm_wd, lbm_ht, 1<<depth, 8);
+ memset(img->getHeadp(), '\0', 3*(1<<depth)); /* clear palette */
+ }
+ } else if (type==BODY) {
+ if (!had_cmap) err("LBM: should be CMAP, BODY");
+ // fprintf(stderr, "wd=%u, %u exp=%u\n", lbm_wd, size, byteswide*depth*lbm_ht);
+ if (comp==0 && size!=byteswide*depth*lbm_ht) err("LBM: wrong BODY length");
+ char *buf=new char[byteswide*depth], *picput=img->getRowbeg(); // const_cast<char*>(img->getCString());
+ for (i=0;i<lbm_ht;i++) {
+ // fprintf(stderr, "i=%u ht=%u\n", i, lbm_ht);
+ if (comp) { for (j=0;j<depth;j++) size-=getUnpack(byteswide, buf+byteswide*j); }
+ else { for (j=0;j<depth*byteswide;j++) buf[j]=getcn(); }
+ /* ^^^ Imp: test !comp: find uncompressed LBM files */
+ if ((s32_t)size<0) goto dtl;
+
+ /* debit() */
+ /* LBM compression is quite stupid: it run-length-compresses
+ * individiual bits of the color depth as 8-bit bytes. Plus it requires
+ * each bit vector to be aligned to 16-bit boundary.
+ */
+ Image::Sampled::dimen_t depth2, bit=128, res, i, mask;
+ // unsigned byteswide=((lbm_wd+15)>>4)<<1;
+ unsigned char *take, *lines=(unsigned char*)buf;
+ if (depth!=24) {
+ for (i=0;i<lbm_wd;i++) {
+ mask=1; depth2=depth; take=lines; res=0; while (depth2--!=0) {
+ if (0!=(*take&bit)) res|=mask;
+ mask<<=1;
+ take+=byteswide;
+ }
+ if (res==transp) had_transp=true;
+ *picput++=res;
+ if (bit==1) { bit=128; ++lines; } else bit>>=1;
+ }
+ } else {
+ u32_t res;
+ for (i=0;i<lbm_wd;i++) {
+ mask=1; depth2=24; take=lines; res=0; while (depth2--!=0) {
+ if (0!=(*take&bit)) res|=mask;
+ mask<<=1;
+ take+=byteswide;
+ }
+ /* No transparency here. */
+ *picput++=res; /* Shift order verified. */
+ *picput++=res>>8;
+ *picput++=res>>16;
+ if (bit==1) { bit=128; ++lines; } else bit>>=1;
+ }
+ }
+ }
+ // fprintf(stderr,"size=%u\n", size);
+ if (size>1) { dtl: err("LBM: data too long"); }
+ if (size==1) getcn();
+ if (had_transp) { assert(depth!=24); static_cast<Image::Indexed*>(img)->setTransp(transp); }
+ // img->getRowbeg()[0]='\001'; img->getRowbeg()[1]='\002';
+ delete [] buf;
+ had_body=true;
+ } else if (type==CMAP) {
+ if (img==NULLP) err("LBM: should be: BMHD, CMAP");
+ if (had_cmap) err("LBM: duplicate CMAP");
+ if (size>3*(1U<<depth)) err("LBM: CMAP too large");
+ char *colormap=img->getHeadp();
+ // fprintf(stderr,"Si=%d size=%u\n", img->getRowbeg()-colormap, size);
+ for (i=0;i<size;i++) colormap[i]=getcn();
+ had_cmap=true;
+ } else {
+ Error::sev(Error::WARNING) << "LBM: unknown tag ignored: " << type << (Error*)0;
+ while (size--) MACRO_GETC(f);
+ }
+ if (do_skip) getcn();
+ // fprintf(stderr,"do_skip=%d t=%lu\n", do_skip, ftell(f));
+ }
+ if (!had_body) err("LBM: missing BODY");
+ return img;
+}
+
+static Image::Sampled *in_lbm_reader(Image::Loader::UFD *ufd, SimBuffer::Flat const&) {
+ return LBMRead(((Filter::UngetFILED*)ufd)->getFILE(/*seekable:*/false)).doit();
+ /* ^^^ Destructor: fclose((FILE*)file_); */
+}
+
+static Image::Loader::reader_t in_lbm_checker(char buf[Image::Loader::MAGIC_LEN], char [Image::Loader::MAGIC_LEN], SimBuffer::Flat const&, Image::Loader::UFD*) {
+ return (0==memcmp(buf,"FORM",4) && 0==memcmp(buf+8,"ILBM",4)) ? in_lbm_reader : 0;
+}
+
+#else
+#define in_lbm_checker NULLP
+#endif /* USE_IN_XPM */
+
+Image::Loader in_lbm_loader = { "LBM", in_lbm_checker, 0 };
diff --git a/graphics/sam2p/in_pcx.cpp b/graphics/sam2p/in_pcx.cpp
new file mode 100644
index 0000000000..fe48d1166e
--- /dev/null
+++ b/graphics/sam2p/in_pcx.cpp
@@ -0,0 +1,548 @@
+/*
+ * in_pcx.cpp: loads PCX images
+ * modified by pts@fazekas.hu at Fri Apr 12 22:16:08 CEST 2002
+ * -- Fri Apr 12 23:54:57 CEST 2002
+ *
+ * xvpcx.c - load routine for PCX format pictures
+ *
+ * LoadPCX(fname, pinfo) - loads a PCX file
+ */
+
+/**** pts ****/
+#include "config2.h"
+#include "image.hpp"
+
+#if USE_IN_PCX
+#include "error.hpp"
+#include "gensio.hpp"
+#include <string.h>
+
+
+/* Imp: palette handling etc. according to PCX_VER, see decode.c */
+#define dimen Image::Sampled::dimen_t
+#define pcxError(bname,conststr) Error::sev(Error::WARNING) << "PCX: " conststr << (Error*)0
+#define WaitCursor()
+#define xvbzero(p,len) memset(p, '\0', len)
+#define FatalError(conststr) Error::sev(Error::EERROR) << "PCX: " conststr << (Error*)0
+#define return_pcxError(bname, conststr) Error::sev(Error::EERROR) << "PCX: " conststr << (Error*)0
+#define byte unsigned char
+#define PCX_SIZE_T slen_t
+#define malloc_byte(n) new byte[n]
+#define PCX_FREE(p) delete [] (p)
+/* the following list give indicies into saveColors[] array in xvdir.c */
+#define F_FULLCOLOR 0
+#define F_GREYSCALE 1
+#define F_BWDITHER 2
+/* values 'picType' can take */
+#define PIC8 8
+#define PIC24 24
+#define xv_fopen(filename,read_mode) fopen(filename,"rb")
+#define BaseName(x) ((char*)0)
+#define PARM(parm) parm
+/* info structure filled in by the LoadXXX() image reading routines */
+#ifndef USE_PCX_DEBUG_MESSAGES
+#define USE_PCX_DEBUG_MESSAGES 0
+#endif
+
+typedef struct { byte *pic; /* image data */
+ dimen w, h; /* pic size */
+#if 0 /**** pts ****/
+ byte r[256],g[256],b[256];
+#else
+ /* byte pal[3*256]; */
+ byte *pal;
+# define PAL_R(pinfo,idx) (pinfo)->pal[3*(idx)]
+# define PAL_G(pinfo,idx) (pinfo)->pal[3*(idx)+1]
+# define PAL_B(pinfo,idx) (pinfo)->pal[3*(idx)+2]
+#endif /* colormap, if PIC8 */
+#if 0 /**** pts ****/
+ int colType; /* def. Color type to save in */
+ int type; /* PIC8 or PIC24 */
+ int normw, normh; /* 'normal size' of image file
+ (normally eq. w,h, except when
+ doing 'quick' load for icons */
+ int frmType; /* def. Format type to save in */
+ char fullInfo[128]; /* Format: field in info box */
+ char shrtInfo[128]; /* short format info */
+ char *comment; /* comment text */
+ int numpages; /* # of page files, if >1 */
+ char pagebname[64]; /* basename of page files */
+#endif
+ } PICINFO;
+
+
+/* #include "copyright.h" */
+
+/*
+ * the following code has been derived from code written by
+ * Eckhard Rueggeberg (Eckhard.Rueggeberg@ts.go.dlr.de)
+ */
+
+
+/* #include "xv.h" */
+
+/* offsets into PCX header */
+#define PCX_ID 0
+#define PCX_VER 1
+#define PCX_ENC 2
+#define PCX_BPP 3
+#define PCX_XMINL 4
+#define PCX_XMINH 5
+#define PCX_YMINL 6
+#define PCX_YMINH 7
+#define PCX_XMAXL 8
+#define PCX_XMAXH 9
+#define PCX_YMAXL 10
+#define PCX_YMAXH 11
+ /* hres (12,13) and vres (14,15) not used */
+#define PCX_CMAP 16 /* start of 16*3 colormap data */
+#define PCX_PLANES 65
+#define PCX_BPRL 66
+#define PCX_BPRH 67
+
+#define PCX_MAPSTART 0x0c /* Start of appended colormap */
+
+
+static int pcxLoadImage8 PARM((char *, FILE *, PICINFO *, byte *));
+static int pcxLoadImage24 PARM((char *, FILE *, PICINFO *, byte *));
+static void pcxLoadRaster PARM((FILE *, byte *, int, byte *, dimen, dimen));
+#if 0 /**** pts ****/
+static int pcxError PARM((char *, char *));
+#endif
+
+static PCX_SIZE_T multiply_check(PCX_SIZE_T a, PCX_SIZE_T b) {
+ const PCX_SIZE_T result = a * b;
+ /* Check for overflow. Works only if everything is unsigned. */
+ if (result / a != b) FatalError("Image too large.");
+ return result;
+}
+
+static PCX_SIZE_T multiply_check(PCX_SIZE_T a, PCX_SIZE_T b, PCX_SIZE_T c) {
+ return multiply_check(multiply_check(a, b), c);
+}
+
+/*******************************************/
+static Image::Sampled *LoadPCX
+#if 0 /**** pts ****/
+ ___((char *fname, PICINFO *pinfo), (fname, pinfo), (char *fname; PICINFO *pinfo;))
+#else
+ ___((FILE *fp, PICINFO *pinfo), (fname, pinfo), (char *fname; PICINFO *pinfo;))
+#endif
+/*******************************************/
+{
+ Image::Sampled *ret=(Image::Sampled*)NULLP;
+ byte hdr[128];
+#if 0 /**** pts ****/
+ long filesize;
+ char *bname;
+ FILE *fp;
+ char *errstr; byte *image;
+ int gray;
+#endif
+ int i, colors, fullcolor;
+
+ pinfo->pic = (byte *) NULL;
+ pinfo->pal = (byte *) NULL;
+#if 0 /**** pts ****/
+ pinfo->type = PIC8;
+ pinfo->comment = (char *) NULL;
+ bname = BaseName(fname);
+
+ /* open the stream */
+ fp = xv_fopen(fname,"r");
+ if (!fp) return_pcxError(bname, "unable to open file");
+#endif
+
+#if 0 /**** pts ****/
+ /* figure out the file size */
+ fseek(fp, 0L, 2);
+ filesize = ftell(fp);
+ fseek(fp, 0L, 0);
+#endif
+
+ /* read the PCX header */
+ if (fread(hdr, (PCX_SIZE_T) 128, (PCX_SIZE_T) 1, fp) != 1 ||
+ ferror(fp) || feof(fp)) {
+ /* fclose(fp); */
+ return_pcxError(bname, "EOF reached in PCX header.\n");
+ }
+
+ if (hdr[PCX_ID] != 0x0a || hdr[PCX_VER] > 5) {
+ /* fclose(fp); */
+ return_pcxError(bname,"unrecognized magic number");
+ }
+
+ pinfo->w = (hdr[PCX_XMAXL] + ((dimen) hdr[PCX_XMAXH]<<8))
+ - (hdr[PCX_XMINL] + ((dimen) hdr[PCX_XMINH]<<8));
+
+ pinfo->h = (hdr[PCX_YMAXL] + ((dimen) hdr[PCX_YMAXH]<<8))
+ - (hdr[PCX_YMINL] + ((dimen) hdr[PCX_YMINH]<<8));
+
+ pinfo->w++; pinfo->h++;
+
+ colors = 1 << (hdr[PCX_BPP] * hdr[PCX_PLANES]);
+ fullcolor = (hdr[PCX_BPP] == 8 && hdr[PCX_PLANES] == 3);
+
+#if USE_PCX_DEBUG_MESSAGES
+ fprintf(stderr,"PCX: %dx%d image, version=%d, encoding=%d\n",
+ pinfo->w, pinfo->h, hdr[PCX_VER], hdr[PCX_ENC]);
+ fprintf(stderr," BitsPerPixel=%d, planes=%d, BytePerRow=%d, colors=%d\n",
+ hdr[PCX_BPP], hdr[PCX_PLANES],
+ hdr[PCX_BPRL] + ((dimen) hdr[PCX_BPRH]<<8),
+ colors);
+#endif
+
+ if (colors>256 && !fullcolor) {
+ /* fclose(fp); */
+ return_pcxError(bname,"No more than 256 colors allowed in PCX file.");
+ }
+
+ if (hdr[PCX_ENC] != 1) {
+ /* fclose(fp); */
+ return_pcxError(bname,"Unsupported PCX encoding format.");
+ }
+
+ /* load the image, the image function fills in pinfo->pic */
+ if (!fullcolor) {
+ Image::Indexed *img=new Image::Indexed(pinfo->w, pinfo->h, colors, 8);
+ pinfo->pal=(byte*)img->getHeadp();
+ ASSERT_SIDE(pcxLoadImage8((char*)NULLP/*bname*/, fp, pinfo, hdr));
+ memcpy(img->getRowbeg(), pinfo->pic, multiply_check(pinfo->w, pinfo->h));
+ ret=img;
+ } else {
+ Image::RGB *img=new Image::RGB(pinfo->w, pinfo->h, 8);
+ ASSERT_SIDE(pcxLoadImage24((char*)NULLP/*bname*/, fp, pinfo, hdr));
+ memcpy(img->getRowbeg(), pinfo->pic, multiply_check(pinfo->w, pinfo->h, 3));
+ ret=img;
+ }
+ PCX_FREE(pinfo->pic);
+ pinfo->pic=(byte*)NULLP;
+
+
+ if (ferror(fp) | feof(fp)) /* just a warning */
+ pcxError(bname, "PCX file appears to be truncated.");
+
+ if (colors>16 && !fullcolor) { /* handle trailing colormap */
+ while (1) {
+ i=MACRO_GETC(fp);
+ if (i==PCX_MAPSTART || i==EOF) break;
+ }
+
+#if 0 /**** pts ****/
+ for (i=0; i<colors; i++) {
+ PAL_R(pinfo,i) = MACRO_GETC(fp);
+ PAL_G(pinfo,i) = MACRO_GETC(fp);
+ PAL_B(pinfo,i) = MACRO_GETC(fp);
+ }
+#endif
+ if (fread(pinfo->pal, 1, colors*3, fp) != colors * 3 + 0U ||
+ ferror(fp) || feof(fp)) {
+ pcxError(bname,"Error reading PCX colormap. Using grayscale.");
+ for (i=0; i<256; i++) PAL_R(pinfo,i) = PAL_G(pinfo,i) = PAL_B(pinfo,i) = i;
+ }
+ }
+ else if (colors<=16) { /* internal colormap */
+#if 0 /**** pts ****/
+ for (i=0; i<colors; i++) {
+ PAL_R(pinfo,i) = hdr[PCX_CMAP + i*3];
+ PAL_G(pinfo,i) = hdr[PCX_CMAP + i*3 + 1];
+ PAL_B(pinfo,i) = hdr[PCX_CMAP + i*3 + 2];
+ }
+#else
+ memcpy(pinfo->pal, hdr+PCX_CMAP, colors*3);
+#endif
+ }
+
+ if (colors == 2) { /* b&w */
+#if 0 /**** pts ****/
+ if (MONO(PAL_R(pinfo,0), PAL_G(pinfo,0), PAL_B(pinfo,0)) ==
+ MONO(PAL_R(pinfo,1), PAL_G(pinfo,1), PAL_B(pinfo,1))) {
+#else
+ if (PAL_R(pinfo,0)==PAL_R(pinfo,1) && PAL_G(pinfo,0)==PAL_G(pinfo,1) && PAL_B(pinfo,0)==PAL_B(pinfo,1)) {
+#endif
+ /* create cmap */
+ PAL_R(pinfo,0) = PAL_G(pinfo,0) = PAL_B(pinfo,0) = 255;
+ PAL_R(pinfo,1) = PAL_G(pinfo,1) = PAL_B(pinfo,1) = 0;
+#if USE_PCX_DEBUG_MESSAGES
+ fprintf(stderr,"PCX: no cmap: using 0=white,1=black\n");
+#endif
+ }
+ }
+ /* fclose(fp); */
+
+ /* finally, convert into XV internal format */
+#if 0 /**** pts ****/
+ pinfo->type = fullcolor ? PIC24 : PIC8;
+ pinfo->frmType = -1; /* no default format to save in */
+#endif
+
+#if 0 /**** pts ****/
+ /* check for grayscaleitude */
+ gray = 0;
+ if (!fullcolor) {
+ for (i=0; i<colors; i++) {
+ if ((PAL_R(pinfo,i) != PAL_G(pinfo,i)) || (PAL_R(pinfo,i) != PAL_B(pinfo,i))) break;
+ }
+ gray = (i==colors) ? 1 : 0;
+ }
+
+
+ if (colors > 2 || (colors==2 && !gray)) { /* grayscale or PseudoColor */
+ pinfo->colType = (gray) ? F_GREYSCALE : F_FULLCOLOR;
+#if 0 /**** pts ****/
+ sprintf(pinfo->fullInfo,
+ "%s PCX, %d plane%s, %d bit%s per pixel. (%ld bytes)",
+ (gray) ? "Greyscale" : "Color",
+ hdr[PCX_PLANES], (hdr[PCX_PLANES]==1) ? "" : "s",
+ hdr[PCX_BPP], (hdr[PCX_BPP]==1) ? "" : "s",
+ filesize);
+#endif
+ }
+ else {
+ pinfo->colType = F_BWDITHER;
+#if 0 /**** pts ****/
+ sprintf(pinfo->fullInfo, "B&W PCX. (%ld bytes)", filesize);
+#endif
+ }
+
+#if 0 /**** pts ****/
+ sprintf(pinfo->shrtInfo, "%dx%d PCX.", pinfo->w, pinfo->h);
+ pinfo->normw = pinfo->w; pinfo->normh = pinfo->h;
+#endif
+#endif
+
+ return ret;
+}
+
+/*****************************/
+static int pcxLoadImage8 ___((char *fname, FILE *fp, PICINFO *pinfo, byte *hdr), (fname, fp, pinfo, hdr),
+ (char *fname;
+ FILE *fp;
+ PICINFO *pinfo;
+ byte *hdr;))
+{
+ /* load an image with at most 8 bits per pixel */
+ (void)fname; /**** pts ****/
+
+ byte *image;
+
+ image = (byte *) malloc_byte(multiply_check(pinfo->h, pinfo->w));
+ if (!image) FatalError("Can't alloc 'image' in pcxLoadImage8()");
+
+ xvbzero((char *) image, multiply_check(pinfo->h, pinfo->w));
+
+ switch (hdr[PCX_BPP]) {
+ case 1: case 2: case 4: case 8: pcxLoadRaster(fp, image, hdr[PCX_BPP], hdr, pinfo->w, pinfo->h); break;
+ default:
+ PCX_FREE(image);
+ return_pcxError(fname, "Unsupported # of bits per plane.");
+ }
+
+ pinfo->pic = image;
+ return 1;
+}
+
+
+/*****************************/
+static int pcxLoadImage24 ___((char *fname, FILE *fp, PICINFO *pinfo, byte *hdr), (fname, fp, pinfo, hdr),
+ (char *fname;
+ FILE *fp;
+ PICINFO *pinfo;
+ byte *hdr;))
+{
+ byte *pix, *pic24;
+ int c;
+ unsigned i, j, w, h, cnt, planes, bperlin, nbytes;
+#if 0 /***** pts ****/
+ int maxv; /* ImageMagick does not have one */
+ byte scale[256];
+#endif
+
+ (void)fname; /**** pts ****/
+
+ w = pinfo->w; h = pinfo->h;
+
+ planes = (unsigned) hdr[PCX_PLANES];
+ bperlin = hdr[PCX_BPRL] + ((dimen) hdr[PCX_BPRH]<<8);
+
+ /* allocate 24-bit image */
+ const PCX_SIZE_T alloced = multiply_check(w, h, planes);
+ const PCX_SIZE_T w_planes = multiply_check(w, planes);
+ pic24 = (byte *) malloc_byte(alloced);
+ if (!pic24) FatalError("couldn't malloc 'pic24'");
+
+ /* This may still fail with a segfault for large values of alloced, even
+ * if malloc_byte has succeeded.
+ */
+ xvbzero((char *) pic24, alloced);
+ fprintf(stderr, "AAA3\n");
+
+#if 0 /**** pts ****/
+ maxv = 0;
+#endif
+ pix = pinfo->pic = pic24;
+ i = 0; /* planes, in this while loop */
+ j = 0; /* bytes per line, in this while loop */
+ nbytes = multiply_check(bperlin, h, planes);
+
+ while (nbytes > 0 && (c = MACRO_GETC(fp)) != EOF) {
+ if (c>=0xC0) { /* have a rep. count */
+ cnt = c & 0x3F;
+ c = MACRO_GETC(fp);
+ if (c == EOF) { MACRO_GETC(fp); break; }
+ }
+ else cnt = 1;
+ if (cnt > nbytes) FatalError("Repeat count too large.");
+
+#if 0 /**** pts ****/
+ if (c > maxv) maxv = c;
+#endif
+
+ while (cnt-- > 0) {
+ if (j < w) {
+ *pix = c;
+ pix += planes;
+ }
+ j++;
+ nbytes--;
+ if (j == bperlin) {
+ j = 0;
+ if (++i < planes) {
+ pix -= w_planes-1; /* next plane on this line */
+ }
+ else {
+ pix -= planes-1; /* start of next line, first plane */
+ i = 0;
+ }
+ }
+ }
+ }
+ if (nbytes != 0) pcxError(0, "Image data truncated.");
+
+
+#if 0 /**** pts ****/
+ /* scale all RGB to range 0-255, if they aren't */
+
+ if (maxv<255) {
+ for (i=0; i<=maxv; i++) scale[i] = (i * 255) / maxv;
+
+ for (i=0, pix=pic24; i<h; i++) {
+ if ((i&0x3f)==0) WaitCursor();
+ for (j=0; j<w_planes; j++, pix++) *pix = scale[*pix];
+ }
+ }
+#endif
+
+ return 1;
+}
+
+
+
+/*****************************/
+static void pcxLoadRaster ___((FILE *fp, byte *image, int depth, byte *hdr, dimen w, dimen h), (fp, image, depth, hdr, w, h),
+ (FILE *fp;
+ byte *image, *hdr;
+ int depth;
+ dimen w,h;))
+{
+ /* was supported: 8 bits per pixel, 1 plane, or 1 bit per pixel, 1-8 planes */
+
+ unsigned row, bcnt, bperlin, pad, cnt, pmask, i, pleft;
+ int b;
+ byte *oldimage;
+
+ bperlin = hdr[PCX_BPRL] + ((dimen) hdr[PCX_BPRH]<<8);
+ pad = (depth == 1) ? bperlin * 8 : bperlin;
+ if (pad < w) FatalError("pad too small");
+ pad -= w;
+
+ row = bcnt = 0;
+
+ pmask = 1; oldimage = image;
+ pleft=hdr[PCX_PLANES];
+
+ while ( (b=MACRO_GETC(fp)) != EOF) {
+ if (b>=0xC0) { /* have a rep. count */
+ cnt = b & 0x3F;
+ b = MACRO_GETC(fp);
+ if (b == EOF) { MACRO_GETC(fp); return; }
+ }
+ else cnt = 1;
+
+ for (i=0; i<cnt; i++) {
+ switch (depth) {
+ case 1:
+ *image++|=(b&0x80)?pmask:0;
+ *image++|=(b&0x40)?pmask:0;
+ *image++|=(b&0x20)?pmask:0;
+ *image++|=(b&0x10)?pmask:0;
+ *image++|=(b&0x8)?pmask:0;
+ *image++|=(b&0x4)?pmask:0;
+ *image++|=(b&0x2)?pmask:0;
+ *image++|=(b&0x1)?pmask:0;
+ break;
+ case 2: /**** pts ****/
+ *image++|=((b>>6)&3)*pmask;
+ *image++|=((b>>4)&3)*pmask;
+ *image++|=((b>>2)&3)*pmask;
+ *image++|=((b )&3)*pmask;
+ break;
+ case 4: /**** pts ****/
+ *image++|=((b>>4)&15)*pmask;
+ *image++|=((b )&15)*pmask;
+ break;
+ default:
+ *image++=(byte)b;
+ }
+
+ bcnt++;
+
+ if (bcnt == bperlin) { /* end of a line reached */
+ bcnt = 0;
+
+ if (--pleft==0) { /* moved to next row */
+ pleft=hdr[PCX_PLANES];
+ pmask=1;
+ image -= pad;
+ oldimage = image;
+ row++;
+ if (row >= h) return; /* done */
+ }
+ else { /* next plane, same row */
+ image = oldimage;
+ pmask<<=depth;
+ }
+ }
+ }
+ }
+}
+
+#if 0 /**** pts ****/
+/*******************************************/
+static int pcxError(fname,st)
+ char *fname, *st;
+{
+ SetISTR(ISTR_WARNING,"%s: %s", fname, st);
+ return 0;
+}
+#endif
+
+static Image::Sampled *in_pcx_reader(Image::Loader::UFD *ufd, SimBuffer::Flat const&) {
+ PICINFO pinfo_;
+ return LoadPCX(((Filter::UngetFILED*)ufd)->getFILE(/*seekable:*/false), &pinfo_);
+}
+static Image::Loader::reader_t in_pcx_checker(char buf[Image::Loader::MAGIC_LEN], char [Image::Loader::MAGIC_LEN], SimBuffer::Flat const&, Image::Loader::UFD*) {
+ return buf[PCX_ID]==0x0a
+ && (unsigned char)buf[PCX_VER]<=5
+ && buf[PCX_ENC]==1
+ && buf[PCX_BPP]<=8
+ ? in_pcx_reader : 0;
+}
+
+#else
+#define in_pcx_checker (Image::Loader::checker_t)NULLP
+#endif /* USE_IN_PCX */
+
+Image::Loader in_pcx_loader = { "PCX", in_pcx_checker, 0 };
+
+/* __END__ */
diff --git a/graphics/sam2p/in_png.cpp b/graphics/sam2p/in_png.cpp
new file mode 100644
index 0000000000..57342cea0f
--- /dev/null
+++ b/graphics/sam2p/in_png.cpp
@@ -0,0 +1,67 @@
+/*
+ * in_png.cpp -- read PNG (Portable Network Graphics, PNG is Not GIF) files with pngtopnm
+ * by pts@fazekas.hu at Sun Apr 14 14:50:30 CEST 2002
+ */
+
+#ifdef __GNUC__
+#ifndef __clang__
+#pragma implementation
+#endif
+#endif
+
+#include "image.hpp"
+
+#if USE_IN_PNG
+
+#include "error.hpp"
+#include "gensio.hpp"
+#include "helpere.hpp"
+#include <string.h> /* memchr() */
+#include <stdio.h> /* printf() */
+
+static Image::Sampled *in_png_reader(Image::Loader::UFD* ufd, SimBuffer::Flat const&) {
+ // Error::sev(Error::EERROR) << "Cannot load PNG images yet." << (Error*)0;
+ char const* cmd=
+#if 0
+ #if OS_COTY==COTY_WIN9X || OS_COTY==COTY_WINNT
+ "pngtopnm %S >%D\npngtopnm -alpha %S >>%D";
+ #else
+ #if OS_COTY==COTY_UNIX
+ "(pngtopnm <%S && pngtopnm -alpha <%S) >%D";
+ #else
+ "pngtopnm %S >%D\npngtopnm -alpha %S >>%D";
+ #endif
+ #endif
+#else /* Wed Feb 5 19:03:58 CET 2003 */
+ #if OS_COTY==COTY_WIN9X || OS_COTY==COTY_WINNT
+ "png22pnm -rgba %S >%D";
+ #else
+ #if OS_COTY==COTY_UNIX
+ #if 1
+ "(png22pnm -rgba %S || (pngtopnm <%S && pngtopnm -alpha <%S)) >%D";
+ #else
+ /* Dat: not using this to suppress `sh: png22pnm: command not found', because
+ * it would hide precious error messages printed by png22pnm.
+ */
+ "((png22pnm -rgba %S 2>/dev/null)|| (pngtopnm <%S && pngtopnm -alpha <%S)) >%D";
+ #endif
+ #else
+ "png22pnm -rgba %S >%D";
+ #endif
+ #endif
+#endif
+ HelperE helper(cmd); /* Run external process pngtopnm */
+ Encoder::writeFrom(*(Filter::PipeE*)&helper, *(Filter::UngetFILED*)ufd);
+ ((Filter::PipeE*)&helper)->vi_write(0,0); /* Signal EOF */
+ return helper.getImg();
+}
+
+static Image::Loader::reader_t in_png_checker(char buf[Image::Loader::MAGIC_LEN], char [Image::Loader::MAGIC_LEN], SimBuffer::Flat const&, Image::Loader::UFD*) {
+ return 0==memcmp(buf,"\211PNG\r\n\032\n",8) ? in_png_reader : 0;
+}
+
+#else
+#define in_png_checker (Image::Loader::checker_t)NULLP
+#endif /* USE_IN_PNG */
+
+Image::Loader in_png_loader = { "PNG", in_png_checker, 0 };
diff --git a/graphics/sam2p/in_pnm.cpp b/graphics/sam2p/in_pnm.cpp
new file mode 100644
index 0000000000..cd115a5237
--- /dev/null
+++ b/graphics/sam2p/in_pnm.cpp
@@ -0,0 +1,82 @@
+/*
+ * in_pnm.cpp -- read a NetPBM PNM bitmap file
+ * by pts@fazekas.hu at Sat Mar 2 00:46:54 CET 2002
+ *
+ */
+
+#ifdef __GNUC__
+#ifndef __clang__
+#pragma implementation
+#endif
+#endif
+
+#include "image.hpp"
+#include "error.hpp"
+
+#if USE_IN_PNM
+
+#include "gensio.hpp"
+#include "input-pnm.ci"
+#include <string.h>
+
+static Image::Sampled *in_pnm_reader(Image::Loader::UFD* ufd, SimBuffer::Flat const&) {
+ Image::Sampled *ret=0;
+ #if 0
+ FILE *f=((Filter::UngetFILED*)ufd)->getFILE(/*seekable:*/false);
+ bitmap_type bitmap=pnm_load_image(f);
+ #else
+ Filter::UngetFILED* ufdd=(Filter::UngetFILED*)ufd;
+ bitmap_type bitmap=pnm_load_image(ufdd);
+ #endif
+ /* Imp: Work without duplicated memory allocation */
+ if (BITMAP_PLANES(bitmap)==1) {
+ Image::Gray *img=new Image::Gray(BITMAP_WIDTH(bitmap), BITMAP_HEIGHT(bitmap), 8);
+ memcpy(img->getRowbeg(), BITMAP_BITS(bitmap), (slen_t)BITMAP_WIDTH(bitmap)*BITMAP_HEIGHT(bitmap));
+ ret=img;
+ } else if (BITMAP_PLANES(bitmap)==3) {
+ Image::RGB *img=new Image::RGB(BITMAP_WIDTH(bitmap), BITMAP_HEIGHT(bitmap), 8);
+ memcpy(img->getRowbeg(), BITMAP_BITS(bitmap), (slen_t)3*BITMAP_WIDTH(bitmap)*BITMAP_HEIGHT(bitmap));
+ /* fwrite(BITMAP_BITS(bitmap), 1, (slen_t)3*BITMAP_WIDTH(bitmap)*BITMAP_HEIGHT(bitmap), stdout); */
+ ret=img;
+ } else assert(0 && "invalid PNM depth");
+ delete [] BITMAP_BITS(bitmap);
+ if (ufdd->vi_getcc()=='P') {
+ ufdd->unread("P", 1);
+ // Error::sev(Error::NOTICE) << "PNM: loading alpha after PNM: "
+ // " ftell=" << ftell(f) <<
+ // " bytes=" << ((unsigned)bitmap.width*bitmap.height*bitmap.np) << (Error*)0;
+ bitmap=pnm_load_image(ufdd);
+ // fwrite(bitmap.bitmap,1,(unsigned)bitmap.width*bitmap.height*bitmap.np,stdout);
+ /* Dat: black pixel is transparent */
+ if (BITMAP_PLANES(bitmap)!=1) Error::sev(Error::EERROR) << "PNM: alpha must be PBM or PGM" << (Error*)0;
+ if (BITMAP_WIDTH(bitmap)!=ret->getWd() || BITMAP_HEIGHT(bitmap)!=ret->getHt()) {
+ Error::sev(Error::EERROR) << "PNM: inconsistent width or height in alpha" << (Error*)0;
+ }
+ Image::Gray *img=new Image::Gray(BITMAP_WIDTH(bitmap), BITMAP_HEIGHT(bitmap), 8);
+ memcpy(img->getRowbeg(), BITMAP_BITS(bitmap), (slen_t)BITMAP_WIDTH(bitmap)*BITMAP_HEIGHT(bitmap));
+ delete [] BITMAP_BITS(bitmap);
+ Image::Sampled *old=ret;
+ // old->packPal(); /* automatically called */
+ if ((ret=old->addAlpha(img))!=old) {
+ Error::sev(Error::NOTICE) << "PNM: loaded alpha after PNM" << (Error*)0;
+ delete old;
+ } else {
+ Error::sev(Error::NOTICE) << "PNM: loaded alpha, but no transparent pixels" << (Error*)0;
+ }
+ delete img;
+ }
+ /* fclose(f); */
+ return ret;
+}
+
+static Image::Loader::reader_t in_pnm_checker(char buf[Image::Loader::MAGIC_LEN], char [Image::Loader::MAGIC_LEN], SimBuffer::Flat const&, Image::Loader::UFD*) {
+ return (buf[0]=='P' && (buf[1]>='1' && buf[1]<='6') &&
+ (buf[2]=='\t' || buf[2]==' ' || buf[2]=='\r' || buf[2]=='\n' || buf[2]=='#'))
+ ? in_pnm_reader : 0;
+}
+
+#else
+#define in_pnm_checker NULLP
+#endif /* USE_IN_PNM */
+
+Image::Loader in_pnm_loader = { "PNM", in_pnm_checker, 0 };
diff --git a/graphics/sam2p/in_ps.cpp b/graphics/sam2p/in_ps.cpp
new file mode 100644
index 0000000000..369f7333f2
--- /dev/null
+++ b/graphics/sam2p/in_ps.cpp
@@ -0,0 +1,201 @@
+/*
+ * in_ps.cpp -- read PS and PDF files using GS
+ * by pts@fazekas.hu at Tue Sep 30 12:33:11 CEST 2003
+ */
+
+#ifdef __GNUC__
+#ifndef __clang__
+#pragma implementation
+#endif
+#endif
+
+#include "image.hpp"
+
+#if USE_IN_PS || USE_IN_PDF
+
+#include "error.hpp"
+#include "gensio.hpp"
+#include "helpere.hpp"
+#include <string.h> /* memchr() */
+#include <stdio.h> /* printf() */
+
+#if OS_COTY==COTY_WIN9X || OS_COTY==COTY_WINNT
+# define GS "gswin32c"
+#else
+# define GS "gs"
+#endif
+
+#endif /* USE_IN_PS || USE_IN_PDF */
+
+/** Adds a Ghostscript invocation command. Works for both PS and PDF. */
+static void add_gs_cmd(SimBuffer::B &cmd, SimBuffer::Flat const& hints) {
+ cmd << GS " -r72 -q -dTextAlphaBits=4 -dGraphicsAlphaBits=4 -dLastPage=1 -sDEVICE=pnmraw -dDELAYSAFER -dBATCH -dNOPAUSE -sOutputFile=%D ";
+ char const *p=hints(), *r;
+ /* Dat: hints ends by ',' '\0' */
+ // Files::FILEW(stdout) << hints << ";;\n";
+ while (*p!=',') p++; /* Dat: safe, because hints is assumed to start and end by ',' */
+ while (1) {
+ assert(*p==',');
+ if (*++p=='\0') break;
+ if (p[0]=='g' && p[1]=='s' && p[2]=='=') {
+ r=p+=3;
+ while (*p!=',') p++;
+ cmd.vi_write(r, p-r); /* Dat: -r... in here overrides -r72 above */
+ cmd << ' ';
+ } else {
+ while (*p!=',') p++;
+ }
+ }
+}
+
+#if USE_IN_PS
+
+/* !! -r144 and scale back..., also for PDF -- to enhance image quality */
+
+#undef DO_KEEP_TEMP
+#define DO_KEEP_TEMP 0
+
+static Image::Sampled *in_ps_reader_low(Image::Loader::UFD* ufd, char const*bboxline, SimBuffer::Flat const& hints) {
+ SimBuffer::B mainfn;
+ if (!Files::find_tmpnam(mainfn)) Error::sev(Error::EERROR) << "in_ps_reader" << ": tmpnam() failed" << (Error*)0;
+ mainfn.term0();
+ #if DO_KEEP_TEMP
+ printf("m: %s\n", mainfn());
+ #else
+ Files::tmpRemoveCleanup(mainfn());
+ #endif
+ FILE *f=fopen(mainfn(),"w");
+ fprintf(f, "%s", bboxline);
+ /* vvv Dat: ignore extra calls to `showpage' */
+ fprintf(f, "/showpage [ currentdict /showpage {} /put load /showpage load ] cvx def\n");
+ fprintf(f, "_IFN (r) file cvx exec\nshowpage\n"); /* Dat: doesn't rely on GS to
+ recognise EPSF-x.y comment, so works with both old and new gs */
+ // ^^^ !! DOS EPSF etc. instead of exec/run
+ fclose(f);
+ // Error::sev(Error::EERROR) << "Cannot load PS images yet." << (Error*)0;
+ /* Dat: -dLastPage=1 has no effect, but we keep it for PDF compatibility */
+ /* !! keep only 1st page, without setpagedevice for PS files */
+ /* Dat: -dSAFER won't let me open the file with `/' under ESP Ghostscript 7.05.6 (2003-02-05) */
+ /* Imp: win9X command line too long? */
+ SimBuffer::B cmd;
+ add_gs_cmd(cmd,hints);
+ cmd << " -s_IFN=%S -- %*";
+ /*fprintf(stderr,"cmd:%s\n",cmd.term0()()); */
+ HelperE helper(cmd.term0()(), mainfn()); /* Run external process GS */
+ Filter::UngetFILED* ufdd=(Filter::UngetFILED*)ufd;
+ int i=ufdd->vi_getcc();
+ if (i<0) Error::sev(Error::EERROR) << "in_ps_reader: Empty PostScript file." << (Error*)0; /* should never happen */
+ ((Filter::PipeE*)&helper)->vi_putcc(i);
+ Encoder::writeFrom(*(Filter::PipeE*)&helper, *ufdd);
+ ((Filter::PipeE*)&helper)->vi_write(0,0); /* Signal EOF */
+ #if !DO_KEEP_TEMP
+ remove(mainfn());
+ #endif
+ return helper.getImg();
+}
+
+static Image::Sampled *in_ps_reader(Image::Loader::UFD* ufd, SimBuffer::Flat const& hints) {
+ /* Use the paper size (<</PageSize[...]>> setpagedevice; a4; letter etc.)
+ * set up by the PostScript file, or the system default paper size.
+ */
+ return in_ps_reader_low(ufd, "", hints);
+}
+
+static Image::Sampled *in_eps_reader(Image::Loader::UFD* ufd, SimBuffer::Flat const& hints) {
+ /* Use the *BoundingBox if available, else use the paper size set up by
+ * the EPS file, or the system default paper size.
+ */
+ double llx=0.0, lly=0.0, urx=0.0, ury=0.0;
+ Filter::UngetFILED* ufdd=(Filter::UngetFILED*)ufd;
+ /* ^^^ SUXX: no warning for ufdd=ufdd */
+ /* SUXX: valgrind, checkergcc: no indication of segfault due to stack overflow inside fgetc() */
+ SimBuffer::B line; /* Imp: limit for max line length etc. */
+ #if 0
+ while ((line.clearFree(), ufdd->appendLine(line), line)) {
+ line.term0();
+ printf("line: %s", line());
+ }
+ #endif
+ slen_t line0ofs;
+ int had=0;
+ while ((line0ofs=line.getLength(), ufdd->appendLine(line), line0ofs!=line.getLength())) {
+ char const *thisline=line()+line0ofs;
+ line.term0();
+ // printf("line: %s", thisline);
+ if (thisline[0]=='\n' || thisline[0]=='\r') continue; /* empty line */
+ if (thisline[0]=='%' && thisline[1]=='!') continue; /* %!PS-... */
+ if (thisline[0]!='%' || thisline[1]!='%') break; /* non-ADSC comment */
+ if (had<3 && 4==sscanf(thisline+2, "ExactBoundingBox:%lg%lg%lg%lg", &llx, &lly, &urx, &ury)) had=3;
+ else if (had<2 && 4==sscanf(thisline+2, "HiResBoundingBox:%lg%lg%lg%lg", &llx, &lly, &urx, &ury)) had=2;
+ else if (had<1 && 4==sscanf(thisline+2, "BoundingBox:%lg%lg%lg%lg", &llx, &lly, &urx, &ury)) had=1;
+ /* Dat: finds MetaPost hiresbbox after %%EndComments */
+ // printf("line: %s", line()+line0ofs);
+ }
+ ufdd->unread(line(), line.getLength()); line.clearFree();
+ char bboxline[400];
+ if (had!=0) {
+ // fprintf(stderr, "bbox=[%"PTS_CFG_PRINTFGLEN"g %"PTS_CFG_PRINTFGLEN"g %"PTS_CFG_PRINTFGLEN"g %"PTS_CFG_PRINTFGLEN"g]\n", llx, lly, urx, ury);
+ /* Dat: we must call translate _after_ setpagedevice (so it will take effect), at least with ESP Ghostscript 7.05.6 (2003-02-05); BUGFIX at Fri Aug 12 22:49:07 CEST 2005 */
+ sprintf(bboxline,
+ "<</PageSize[%" PTS_CFG_PRINTFGLEN "g %" PTS_CFG_PRINTFGLEN "g]>>setpagedevice\n"
+ /* removing /PageSize also cancels /a4, /a5 etc. */
+ /* we need `currentmatrix ... setpagedevice setmatrix' because
+ * setpagedevice cancels the current transformation matrix so our
+ * `translate' below would be canceled if the EPS file contains
+ * `a5', `setpagedevice' etc.
+ */
+ "/setpagedevice{matrix currentmatrix exch "
+ "dup length dict copy dup /PageSize undef setpagedevice "
+ "setmatrix}bind def\n"
+ "%" PTS_CFG_PRINTFGLEN "g %" PTS_CFG_PRINTFGLEN "g translate\n"
+ , urx-llx, ury-lly, -llx, -lly);
+ } else {
+ Error::sev(Error::WARNING) << "in_eps_reader: missing EPS bbox" << (Error*)0;
+ bboxline[0]='\0';
+ }
+
+ return in_ps_reader_low(ufd, bboxline, hints);
+}
+
+static Image::Loader::reader_t in_ps_checker(char buf[Image::Loader::MAGIC_LEN], char [Image::Loader::MAGIC_LEN], SimBuffer::Flat const&, Image::Loader::UFD*) {
+ if (0!=memcmp(buf,"%!PS-Adobe-",11)) return 0;
+ char const *p=buf+11, *pend=buf+Image::Loader::MAGIC_LEN;
+ while (p!=pend && *p!=' ' && *p!='\t') p++;
+ while (p!=pend && (*p==' ' || *p=='\t')) p++;
+ /* Imp: option to accept BoundingBox for non-EPS PS */
+ return (0==strncmp(p,"EPSF-",5)) ? in_eps_reader : in_ps_reader;
+ /* ^^^ BUGFIX at Fri Nov 26 12:13:58 CET 2004 */
+ /* ^^^ BUGFIX again at Thu Jan 6 10:25:54 CET 2005 */
+}
+
+#else
+#define in_ps_checker (Image::Loader::checker_t)NULLP
+#endif /* USE_IN_PS */
+
+Image::Loader in_ps_loader = { "PS", in_ps_checker, 0 };
+
+#if USE_IN_PDF
+
+static Image::Sampled *in_pdf_reader(Image::Loader::UFD* ufd, SimBuffer::Flat const& hints) {
+ // Error::sev(Error::EERROR) << "Cannot load PDF images yet." << (Error*)0;
+ SimBuffer::B cmd;
+ add_gs_cmd(cmd,hints);
+ cmd << " -- %S";
+ /* Dat: -dSAFER won't let me open the file with `/' under ESP Ghostscript 7.05.6 (2003-02-05) */
+ /* Imp: win9X command line too long? */
+ fprintf(stderr, "gs_cmd=(%s)\n", cmd.term0()());
+ HelperE helper(cmd.term0()()); /* Run external process GS */
+ Encoder::writeFrom(*(Filter::PipeE*)&helper, *(Filter::UngetFILED*)ufd);
+ ((Filter::PipeE*)&helper)->vi_write(0,0); /* Signal EOF */
+ return helper.getImg();
+}
+
+static Image::Loader::reader_t in_pdf_checker(char buf[Image::Loader::MAGIC_LEN], char [Image::Loader::MAGIC_LEN], SimBuffer::Flat const&, Image::Loader::UFD*) {
+ return 0==memcmp(buf,"%PDF-",5) ? in_pdf_reader : 0;
+}
+
+#else
+#define in_pdf_checker (Image::Loader::checker_t)NULLP
+#endif /* USE_IN_PDF */
+
+Image::Loader in_pdf_loader = { "PDF", in_pdf_checker, 0 };
diff --git a/graphics/sam2p/in_tga.cpp b/graphics/sam2p/in_tga.cpp
new file mode 100644
index 0000000000..792afe5ab3
--- /dev/null
+++ b/graphics/sam2p/in_tga.cpp
@@ -0,0 +1,52 @@
+/*
+ * in_tga.cpp -- read a Truevision Targa TGA file
+ * by pts@fazekas.hu at Sat Mar 2 00:49:35 CET 2002
+ *
+ */
+
+#ifdef __GNUC__
+#ifndef __clang__
+#pragma implementation
+#endif
+#endif
+
+#include "image.hpp"
+#include "error.hpp"
+#include "gensio.hpp" /* Filter::UngetFILED */
+
+#if USE_IN_TGA
+
+#include "input-tga.ci" /* defines tga_load_image */
+
+static Image::Sampled *in_tga_reader(Image::Loader::UFD *ufd, SimBuffer::Flat const&) {
+ Image::Sampled *ret=0;
+ bitmap_type bitmap=tga_load_image(((Filter::UngetFILED*)ufd)->getFILE(/*seekable:*/false));
+ /* Imp: Work without duplicated memory allocation */
+ if (BITMAP_PLANES(bitmap)==1) {
+ Image::Gray *img=new Image::Gray(BITMAP_WIDTH(bitmap), BITMAP_HEIGHT(bitmap), 8);
+ memcpy(img->getRowbeg(), BITMAP_BITS(bitmap), (slen_t)BITMAP_WIDTH(bitmap)*BITMAP_HEIGHT(bitmap));
+ ret=img;
+ } else if (BITMAP_PLANES(bitmap)==3) {
+ Image::RGB *img=new Image::RGB(BITMAP_WIDTH(bitmap), BITMAP_HEIGHT(bitmap), 8);
+ memcpy(img->getRowbeg(), BITMAP_BITS(bitmap), (slen_t)3*BITMAP_WIDTH(bitmap)*BITMAP_HEIGHT(bitmap));
+ ret=img;
+ } else assert(0 && "invalid TGA depth");
+ delete [] BITMAP_BITS(bitmap);
+ return ret;
+}
+
+static Image::Loader::reader_t in_tga_checker(char buf[Image::Loader::MAGIC_LEN], char [Image::Loader::MAGIC_LEN], SimBuffer::Flat const&, Image::Loader::UFD*) {
+ /* vvv Unfortunately not all targa images have that footer */
+ /* return 0==memcmp(bufend+Image::Loader::MAGIC_LEN-18, "TRUEVISION-XFILE", 16) */
+ /* vvv 30..127: Aladdin Ghostscript adds 58 bytes of header */
+ return (unsigned char)buf[0]>=30 && (unsigned char)buf[0]<=63 &&
+ (unsigned char)buf[1]<=11 &&
+ ((unsigned char)buf[16]<=8 || (unsigned char)buf[16]==24)
+ ? in_tga_reader : 0;
+}
+
+#else
+#define in_tga_checker NULLP
+#endif /* USE_IN_XPM */
+
+Image::Loader in_tga_loader = { "TGA", in_tga_checker, 0 };
diff --git a/graphics/sam2p/in_tiff.cpp b/graphics/sam2p/in_tiff.cpp
new file mode 100644
index 0000000000..a4a94ec782
--- /dev/null
+++ b/graphics/sam2p/in_tiff.cpp
@@ -0,0 +1,68 @@
+/*
+ * in_tiff.cpp -- read TIFF (Tag Image File Format) files with tif22pnm
+ * by pts@fazekas.hu at Sun Apr 14 14:50:30 CEST 2002
+ */
+/* Imp: get docs about the TIFF format, and rewrite this from scratch */
+/* Imp: use xviff.c */
+
+#ifdef __GNUC__
+#ifndef __clang__
+#pragma implementation
+#endif
+#endif
+
+#include "image.hpp"
+
+#if USE_IN_TIFF
+
+#include "error.hpp"
+#include "gensio.hpp"
+#include "helpere.hpp"
+#include <string.h> /* memchr() */
+#include <stdio.h> /* printf() */
+
+static Image::Sampled *in_tiff_reader(Image::Loader::UFD *ufd, SimBuffer::Flat const&) {
+ // Error::sev(Error::EERROR) << "Cannot load TIFF images yet." << (Error*)0;
+ // HelperE helper("tifftopnm %S"); /* Cannot extract alpha channel */
+ // HelperE helper("tif22pnm -rgba %S"); /* tif22pnm <= 0.07 */
+ char const *cmd=
+ #if OS_COTY==COTY_WIN9X || OS_COTY==COTY_WINNT
+#if 0 /* unsafe if both tifftopnm and png22pnm exist */
+ "tifftopnm <%S >%D\ntif22pnm -rgba %S pnm: %D"; /* slow but safe */
+#else
+ "tif22pnm -rgba %S pnm:";
+#endif
+ #else
+ #if OS_COTY==COTY_UNIX
+ #if 1
+ "(tif22pnm -rgba %S pnm: || tifftopnm %S)";
+ #else
+ /* Dat: not using this to suppress `sh: tif22pnm: command not found', because
+ * it would hide precious error messages printed by tif22pnm.
+ */
+ "((tif22pnm -rgba %S pnm: 2>/dev/null)|| tifftopnm %S)";
+ #endif
+ #else
+ "tif22pnm -rgba %S pnm:"; /* Wants to seek in the file. */
+ #endif
+ #endif
+ HelperE helper(cmd);
+ Encoder::writeFrom(*(Filter::PipeE*)&helper, *(Filter::UngetFILED*)ufd);
+ ((Filter::PipeE*)&helper)->vi_write(0,0); /* Signal EOF */
+ return helper.getImg();
+}
+
+static Image::Loader::reader_t in_tiff_checker(char buf[Image::Loader::MAGIC_LEN], char [Image::Loader::MAGIC_LEN], SimBuffer::Flat const&, Image::Loader::UFD*) {
+ /* MM\x00\x2a: TIFF image data, big-endian
+ * II\x2a\x00: TIFF image data, little-endian
+ * The second word of TIFF files is the TIFF version number, 42, which has
+ * never changed. The TIFF specification recommends testing for it.
+ */
+ return (0==memcmp(buf,"MM\x00\x2a",4) || 0==memcmp(buf,"II\x2a\x00",4)) ? in_tiff_reader : 0;
+}
+
+#else
+#define in_tiff_checker (Image::Loader::checker_t)NULLP
+#endif /* USE_IN_XPM */
+
+Image::Loader in_tiff_loader = { "TIFF", in_tiff_checker, 0 };
diff --git a/graphics/sam2p/in_xpm.cpp b/graphics/sam2p/in_xpm.cpp
new file mode 100644
index 0000000000..f5af32e5b5
--- /dev/null
+++ b/graphics/sam2p/in_xpm.cpp
@@ -0,0 +1,411 @@
+/*
+ * in_xpm.cpp -- read an XPM file
+ * by pts@math.bme.hu at Fri Mar 1 09:56:54 CET 2002
+ */
+/* Imp: test this code with various xpm files! */
+
+#ifdef __GNUC__
+#ifndef __clang__
+#pragma implementation
+#endif
+#endif
+
+#include "image.hpp"
+
+#if USE_IN_XPM
+
+#if OBJDEP
+# warning REQUIRES: mapping.o
+#endif
+
+#ifndef USE_BIG_MEMORY
+#define USE_BIG_MEMORY 0
+#endif
+
+#include "mapping.hpp"
+#include "error.hpp"
+#include "xpmc.h"
+
+#include <string.h> /* memchr() */
+#include "gensio.hpp"
+
+#define USGE(a,b) ((unsigned char)(a))>=((unsigned char)(b))
+
+#if 0
+/** @return true iff params are different strings (not respecting case) */
+static int my_strcase_neq(char *s1, char *s2) {
+ while ((USGE(*s1,'A') && USGE('Z',*s1) ? *s1+'a'-'A' : *s1) ==
+ (USGE(*s2,'A') && USGE('Z',*s2) ? *s2+'a'-'A' : *s2)) {
+ if (*s1=='\0') return 0;
+ s1++; s2++;
+ }
+ return 1;
+}
+#endif
+
+#define my_strcase_neq(s1,s2) GenBuffer::nocase_strcmp(s1,s2)
+
+/** @ return RGB long */
+static Image::Sampled::rgb_t parse_rgb(char const*s) {
+ unsigned v=0, len;
+ Image::Sampled::rgb_t ret;
+ if (!s || !*s) return 0x2000000; /* not found */
+ // fprintf(stderr, "'%s'\n", s);
+ if (*s=='#') { /* an #RRGGBB web-style color spec; or #RRRRGGGGBBBB */
+ unsigned dif=0;
+ ++s;
+ while (dif<13 && (USGE(5,(s[dif]|32)-'a') || USGE(9,s[dif]-'0'))) dif++; /* find at most 13 hex digits */
+ if (s[dif]!='\0' || (dif!=12 && dif!=6)) return 0x2000000; /* not found, spec length error */
+ dif=(dif==12) ? 3 : 1;
+ // shr=24; while (shr!=0) {
+ ret= (Image::Sampled::rgb_t)( USGE(9,*s-'0') ? *s-'0' : 10+(*s|32)-'a' )<<20;
+ s++;
+ ret|=(Image::Sampled::rgb_t)( USGE(9,*s-'0') ? *s-'0' : 10+(*s|32)-'a' )<<16;
+ s+=dif; /* ignore lower two hex digits of 16-bit sample value */
+ ret|=(Image::Sampled::rgb_t)( USGE(9,*s-'0') ? *s-'0' : 10+(*s|32)-'a' )<<12;
+ s++;
+ ret|=(Image::Sampled::rgb_t)( USGE(9,*s-'0') ? *s-'0' : 10+(*s|32)-'a' )<<8;
+ s+=dif; /* ignore lower two hex digits of 16-bit sample value */
+ ret|=(Image::Sampled::rgb_t)( USGE(9,*s-'0') ? *s-'0' : 10+(*s|32)-'a' )<<4;
+ s++;
+ ret|=(Image::Sampled::rgb_t)( USGE(9,*s-'0') ? *s-'0' : 10+(*s|32)-'a' );
+ return ret;
+ }
+ /* vvv 223==255-32: ignore case when hashing */
+ char const *p=s;
+ while (*p!='\0') v=xpmColors_mul*v+(223&*(unsigned char const*)p++);
+ p=xpmColors_dat+xpmColors_ofs[(v&65535)%xpmColors_mod];
+ while (*p!='\0') {
+ len=strlen(p);
+ if (0==my_strcase_neq(p,s)) {
+ p+=len;
+ ret=(((Image::Sampled::rgb_t)((unsigned char const*)p)[1])<<16)+
+ (((Image::Sampled::rgb_t)((unsigned char const*)p)[2])<<8)+
+ (((Image::Sampled::rgb_t)((unsigned char const*)p)[3]));
+ return (ret==0x30201) ? 0x1000000 : ret; /* transparent color */
+ }
+ p+=len+4;
+ }
+ return 0x2000000; /* not found */
+}
+
+class XPMTok {
+ public:
+ /* Imp: report line numbers on errors */
+ BEGIN_STATIC_ENUM1(int)
+ T_NO_UNGOT=-1,
+ T_COMMA=257 /* The comma token, outside strings. */
+ END_STATIC_ENUM()
+ /* XPM states */
+ BEGIN_STATIC_ENUM1(char)
+ ST_OUT=0, /* outside s string */
+ ST_STR=1, /* inside a string */
+ ST_EOF=2 /* EOF */
+ END_STATIC_ENUM()
+ int getcc();
+ /** Reads an unsigned int. */
+ Image::Sampled::dimen_t getDimen();
+ Image::Sampled::rgb_t getColor();
+ void read(char *buf, unsigned len);
+ inline void readInStr(char *buf, unsigned len);
+ inline XPMTok(FILE *f_): f(f_), state(ST_OUT), ungot(T_NO_UNGOT) {}
+ inline void ungetcc(int c) { if (c>=0) ungot=c; }
+ void getComma();
+ protected:
+ FILE *f;
+ /** Current state. */
+ char state;
+ int ungot;
+};
+
+int XPMTok::getcc() {
+ int i;
+ if (ungot>=0 /*T_NO_UNGOT<0*/) { i=ungot; ungot=T_NO_UNGOT; return i; }
+ /* Imp: ignore C and C++ style comments (so we won't recognise strings inside comments) */
+ switch (state) {
+ case ST_OUT: st_out:
+ while (1) {
+ switch ((i=MACRO_GETC(f))) {
+ case -1: state=ST_EOF; return -1;
+ case ',': return T_COMMA;
+ case '"': state=ST_STR; goto st_str;
+ default: /* ignore outside strings */ break;
+ }
+ }
+ case ST_STR: st_str:
+ i=MACRO_GETC(f);
+ if (i==-1) { ue: Error::sev(Error::EERROR) << "XPM: unexpected EOF" << (Error*)0; }
+ else if (i=='"') { state=ST_OUT; goto st_out; }
+ else if (i=='\\') {
+ if ((i=MACRO_GETC(f))==-1) goto ue;
+ if (i=='\n') goto st_str;
+ /* Imp: handle octal, hexadecimal, \n etc. */
+ }
+ return i&255;
+ default: return -1;
+ }
+}
+Image::Sampled::dimen_t XPMTok::getDimen() {
+ Image::Sampled::dimen_t ret=0, bak;
+ int i;
+ while ((i=getcc())==' ' || i=='\t') ;
+ if (USGE(i,'0') && USGE('9',i)) {
+ ret=i-'0';
+ while (USGE((i=getcc()),'0') && USGE('9',i)) {
+ bak=ret;
+ ret=ret*10+(i-'0');
+ if (ret/10!=bak) Error::sev(Error::EERROR) << "XPM: dimen overflow" << (Error*)0;
+ }
+ ungetcc(i);
+ return ret;
+ } else Error::sev(Error::EERROR) << "XPM: dimen expected" << (Error*)0;
+ return 0; /*notreached*/
+}
+void XPMTok::getComma() {
+ if (getcc()!=T_COMMA) Error::sev(Error::EERROR) << "XPM: comma expected at " << ftell(f) << (Error*)0;
+}
+void XPMTok::read(char *buf, unsigned len) {
+ int i;
+ while (len--!=0) {
+ i=getcc();
+ // fprintf(stderr,"i=%d\n", i);
+ if (i>=0 && i<=255) *buf++=i; else Error::sev(Error::EERROR) << "XPM: data expected" << (Error*)0;
+ }
+}
+void XPMTok::readInStr(char *buf, unsigned len) {
+ /* Dat: this is OK noew */
+ // assert(state==ST_STR);
+ assert(ungot<0);
+ param_assert(len>=1);
+ if (state!=ST_STR) { len--; goto real; }
+ int i;
+ while (len--!=0) {
+ if ((i=MACRO_GETC(f))>=0 && i<=255 && i!='"' && i!='\\') *buf++=i;
+ else { assert(i>=0); ungetc(i,f); real:
+ i=getcc();
+ // fprintf(stderr,"i=%d\n", i);
+ if (i>=0 && i<=255) *buf++=i; else Error::sev(Error::EERROR) << "XPM: data expected" << (Error*)0;
+ }
+ }
+}
+Image::Sampled::rgb_t XPMTok::getColor() {
+ static char tmp[32];
+ int i;
+ while ((i=getcc())==' ' || i=='\t') ;
+ if (i=='g') { at_g:
+ i=getcc();
+ if (i!='4') ungetcc(i);
+ goto at_col;
+ } else if (i=='c' || i=='m' || i=='b' || i=='s') { at_col:
+ while ((i=getcc())==' ' || i=='\t') ;
+ char *p=tmp, *pend=tmp+sizeof(tmp)-1;
+ while (i>=33 && i<=126) {
+ if (p==pend) goto cexp; /* color name too long */
+ *p++=i;
+ i=getcc();
+ }
+ *p='\0';
+ if (i==' ' || i=='\t') { /* Maybe another color will come */
+ while ((i=getcc())==' ' || i=='\t') ;
+ if (i=='g') goto at_g;
+ else if (i=='c' || i=='m' || i=='b' || i=='s') goto at_col;
+ }
+ if (i!=T_COMMA) goto cexp;
+ Image::Sampled::rgb_t ret=parse_rgb(tmp);
+ if (ret==0x2000000) Error::sev(Error::EERROR) << "XPM: unknown color: " << tmp << (Error*)0;
+ return ret;
+ } else { cexp: Error::sev(Error::EERROR) << "XPM: color expected" << (Error*)0; }
+ return 0; /*notreached*/
+}
+
+static Image::Sampled *in_xpm_reader(Image::Loader::UFD *ufd, SimBuffer::Flat const&) {
+ // Error::sev(Error::EERROR) << "Cannot load XPM images yet." << (Error*)0;
+ XPMTok tok(((Filter::UngetFILED*)ufd)->getFILE(/*seekable:*/false));
+ Image::Sampled::dimen_t wd=tok.getDimen();
+ Image::Sampled::dimen_t ht=tok.getDimen();
+ Image::Sampled::dimen_t colors=tok.getDimen();
+ Image::Sampled::dimen_t cpp=tok.getDimen(); /* chars per pixel */
+
+ /* width height ncolors cpp [x_hot y_hot] */
+ int i; /* multiple purpose */
+ while ((i=tok.getcc())==' ' || i=='\t' || USGE(9,i-'0')) ;
+ tok.ungetcc(i); tok.getComma();
+
+ // Error::sev(Error::DEBUG) << "wd="<<wd<<" ht="<<ht<<" colors="<<colors<<" cpp="<<cpp << (Error*)0;
+ if (1UL*cpp*colors>65535) Error::sev(Error::EERROR) << "XPM: too many colors" << (Error*)0;
+ // if (cpp==1) {
+ // }
+ Image::Sampled::dimen_t transp=colors; /* No transparent colors yet. */
+ /* vvv Dat: last cpp bytes of tab are used for storing current pixel. */
+ char *tab=new char[cpp*(colors+1)], *p, *pend; /* BUGFIX: unsinged at Fri Nov 26 12:18:21 CET 2004 */
+ Image::Sampled::rgb_t *rgb=new Image::Sampled::rgb_t[colors], *rp;
+ for (rp=rgb,p=tab,pend=tab+cpp*colors; p!=pend; p+=cpp,rp++) {
+ tok.read(p,cpp);
+ *rp=tok.getColor();
+ if (*rp==0x1000000) {
+ if (transp!=colors) Error::sev(Error::WARNING) << "XPM: subsequent transparency might be blacked" << (Error*)0;
+ else transp=rp-rgb;
+ }
+ }
+ /* Now: transp: index of the last transparent color */
+ /* Dat: since (0x1000000&0xffffff)==0, transparent colors will have palette enrty black */
+
+ char *outbuf=0; /* avoid gcc warning */
+ Image::Sampled *ret;
+ Image::Indexed *iimg=(Image::Indexed*)NULLP;
+ tok.ungetcc(tok.T_COMMA);
+
+ if (colors<=256) {
+ ret=iimg=new Image::Indexed(wd,ht,colors,8);
+ if (transp!=colors) iimg->setTransp(transp);
+ } else {
+ ret=new Image::RGB(wd,ht,8);
+ if (transp!=colors) Error::sev(Error::WARNING) << "XPM: too many colors, transparency blacked" << (Error*)0;
+ }
+ outbuf=ret->getRowbeg();
+
+ if (cpp==1) { /* Easy job: make an Indexed image; defer .packPal() */
+ assert(colors<=256);
+ signed short bin[256], s;
+ memset(bin, 255, sizeof(bin)); /* Make bin[*]=-1 */
+ for (i=0;(unsigned)i<colors;i++) {
+ iimg->setPal(i, rgb[i]);
+ bin[(unsigned char)tab[i]]=i;
+ }
+ assert(p==pend);
+ while (ht--!=0) {
+ tok.getComma();
+ for (p=outbuf+ret->getRlen(); outbuf!=p; ) {
+ if ((i=tok.getcc())<0 || i>255) Error::sev(Error::EERROR) << "XPM: data expected" << (Error*)0;
+ if ((s=bin[i])<0) Error::sev(Error::EERROR) << "XPM: unpaletted color" << (Error*)0;
+ *outbuf++=s;
+ }
+ }
+ #if USE_BIG_MEMORY
+ } else if (cpp==2 && colors<=256) { /* Similarly easy job: make an Indexed image; defer .packPal() */
+ signed short *bin=new short[65536], s;
+ memset(bin, 255, sizeof(*bin) * 65536); /* Make bin[*]=-1 */
+ for (i=0,p=tab; (unsigned)i<colors; i++, p+=2) {
+ iimg->setPal(i, rgb[i]);
+ bin[(((unsigned char*)p)[0]<<8)+((unsigned char*)p)[1]]=i;
+ }
+ assert(p==pend);
+ while (ht--!=0) {
+ tok.getComma();
+ for (p=outbuf+ret->getRlen(); outbuf!=p; ) {
+ tok.readInStr(pend,2);
+ if ((s=bin[(((unsigned char*)pend)[0]<<8)+((unsigned char*)pend)[1]])<0) Error::sev(Error::EERROR) << "XPM: unpaletted color" << (Error*)0;
+ *outbuf++=s;
+ }
+ }
+ delete [] bin;
+ } else if (cpp==2 && colors<=65535) {
+ Image::Sampled::rgb_t rgb1;
+ unsigned short *bin=new unsigned short[65536], s;
+ memset(bin, 255, sizeof(*bin) * 65536); /* Make bin[*]=max */
+ for (i=0,p=tab; (unsigned)i<colors; i++, p+=2) bin[(((unsigned char*)p)[0]<<8)+((unsigned char*)p)[1]]=i;
+ while (ht--!=0) {
+ tok.getComma();
+ for (p=outbuf+ret->getRlen(); outbuf!=p; ) {
+ tok.readInStr(pend,2);
+ if ((s=bin[(((unsigned char*)pend)[0]<<8)+((unsigned char*)pend)[1]])==(unsigned short)-1) Error::sev(Error::EERROR) << "XPM: unpaletted color" << (Error*)0;
+ *outbuf++=(rgb1=rgb[s])>>16;
+ *outbuf++=rgb1>>8;
+ *outbuf++=rgb1;
+ }
+ }
+ delete [] bin;
+ #endif /* USE_BIG_MEMORY */
+ } else { /* Now comes the slow, but general solution */
+ #if USE_IN_XPM_MAPPING /* use Mapping */
+ if (colors<=256) {
+ Mapping::H h(1);
+ char c;
+ /* vvv `c' might become negative, but it is harmless */
+ for (p=tab,pend=tab+cpp*colors,c=0; p!=pend; p+=cpp,c++)
+ h.set(p, cpp, &c); /* every color-string should be unique; but no error message if it isn't */
+ while (ht--!=0) {
+ tok.getComma();
+ for (p=outbuf+ret->getRlen(); outbuf!=p; ) {
+ tok.readInStr(pend,cpp);
+ if (NULLP==(pend=h.get(pend, cpp))) Error::sev(Error::EERROR) << "XPM: unpaletted color" << (Error*)0;
+ *outbuf++=*pend;
+ }
+ }
+ } else { /* most general case with Mapping */
+ if (transp!=colors) Error::sev(Error::WARNING) << "XPM: too many colors, transparency blacked" << (Error*)0;
+ /* Dat: reading a JPEG downsampled to a 256-color XPM takes 3000 ms
+ * with Mapping, and 31000 ms without mapping. Nice speed increase.
+ */
+ Mapping::H h(3);
+ char tmpcol[3];
+ for (p=tab,pend=tab+cpp*colors,rp=rgb; p!=pend; p+=cpp,rp++) {
+ tmpcol[0]=rp[0]>>16;
+ tmpcol[1]=rp[0]>>8;
+ tmpcol[2]=rp[0];
+ h.set(p, cpp, tmpcol); /* every color-string should be unique; but no error message if it isn't */
+ }
+ while (ht--!=0) {
+ tok.getComma();
+ for (p=outbuf+ret->getRlen(); outbuf!=p; outbuf+=3) {
+ tok.readInStr(pend,cpp);
+ if (NULLP==(pend=h.get(pend, cpp))) Error::sev(Error::EERROR) << "XPM: unpaletted color" << (Error*)0;
+ memcpy(outbuf, pend, 3);
+ }
+ }
+ }
+ #else /* don't USE_IN_XPM_MAPPING */
+ Image::Sampled::dimen_t lastcol=0, x;
+ p=tab; /* cache pointer for the last color (lastcol) */
+ if (colors<=256) {
+ assert(cpp>1);
+ for (lastcol=0;lastcol<colors;lastcol++) iimg->setPal(lastcol, rgb[lastcol]);
+ lastcol=0;
+ while (ht--!=0) {
+ // putchar('.');
+ tok.getComma();
+ for (x=0;x<wd;x++) {
+ tok.read(pend,cpp);
+ if (0!=memcmp(p,pend,cpp)) {
+ p=tab; lastcol=0; while (p!=pend && 0!=memcmp(p,pend,cpp)) { p+=cpp; lastcol++; }
+ if (p==pend) Error::sev(Error::EERROR) << "XPM: unpaletted color" << (Error*)0;
+ if (rgb[lastcol]==0x1000000) p=tab+cpp*(lastcol=transp); /* fix single transp */
+ }
+ *outbuf++=lastcol;
+ }
+ }
+ } else { /* colors>256 */
+ while (ht--!=0) {
+ tok.getComma();
+ for (x=0;x<wd;x++) {
+ tok.read(pend,cpp);
+ if (0!=memcmp(p,pend,cpp)) {
+ p=tab; lastcol=0; while (p!=pend && 0!=memcmp(p,pend,cpp)) { p+=cpp; lastcol++; }
+ if (p==pend) Error::sev(Error::EERROR) << "XPM: unpaletted color" << (Error*)0;
+ }
+ *outbuf++=rgb[lastcol]>>16;
+ *outbuf++=rgb[lastcol]>>8;
+ *outbuf++=rgb[lastcol];
+ }
+ }
+ }
+ #endif
+ }
+ delete [] tab;
+ delete [] rgb;
+ /* Dat: we don't check for EOF. Imp: emit a warning? */
+ // Error::sev(Error::DEBUG) << "rp[-1]=" << rp[-1] << (Error*)0;
+ // while (-1!=(i=tok.getcc())) { putchar(i); }
+ /* fclose((FILE*)file_); */
+ return ret;
+}
+
+static Image::Loader::reader_t in_xpm_checker(char buf[Image::Loader::MAGIC_LEN], char [Image::Loader::MAGIC_LEN], SimBuffer::Flat const&, Image::Loader::UFD*) {
+ return (0==memcmp(buf, "/* XPM */", 9)) ? in_xpm_reader : 0;
+}
+
+#else
+# define in_xpm_checker NULLP
+#endif /* USE_IN_XPM */
+
+Image::Loader in_xpm_loader = { "XPM", in_xpm_checker, 0 };
diff --git a/graphics/sam2p/input-bmp.ci b/graphics/sam2p/input-bmp.ci
new file mode 100644
index 0000000000..234626d375
--- /dev/null
+++ b/graphics/sam2p/input-bmp.ci
@@ -0,0 +1,484 @@
+/* This code is ripped from Autotrace-0.29. Small modifications by pts. */
+
+/* input-bmp.ci: reads any bitmap I could get for testing */
+
+#ifdef __GNUC__
+#ifndef __clang__
+#pragma implementation
+#endif
+#endif
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+/* #include "types.h" */
+#include "at_bitmap.h"
+/* #include "message.h" */
+/* #include "xstd.h" */
+/* #include "input-bmp.h" */
+
+#define MAXCOLORS 256
+/* #define Image long */
+
+#define BitSet(byte, bit) (((byte) & (bit)) == (bit))
+
+#define ReadOK(file,buffer,len) (fread(buffer, len, 1, file) != 0)
+
+struct Bitmap_File_Head_Struct
+{
+ char zzMagic[2]; /* 00 "BM" */
+ unsigned long bfSize; /* 02 */
+ unsigned short zzHotX; /* 06 */
+ unsigned short zzHotY; /* 08 */
+ unsigned long bfOffs; /* 0A */
+ unsigned long biSize; /* 0E */
+} Bitmap_File_Head;
+
+struct Bitmap_Head_Struct
+{
+ unsigned long biWidth; /* 12 */
+ unsigned long biHeight; /* 16 */
+ unsigned short biPlanes; /* 1A */
+ unsigned short biBitCnt; /* 1C */
+ unsigned long biCompr; /* 1E */
+ unsigned long biSizeIm; /* 22 */
+ unsigned long biXPels; /* 26 */
+ unsigned long biYPels; /* 2A */
+ unsigned long biClrUsed; /* 2E */
+ unsigned long biClrImp; /* 32 */
+ /* 36 */
+} Bitmap_Head;
+
+static long ToL (unsigned char *);
+static short ToS (unsigned char *);
+static int ReadColorMap (FILE *,
+ unsigned char[256][3],
+ int,
+ int,
+ int *);
+static unsigned char *ReadImage (FILE *,
+ int,
+ int,
+ unsigned char[256][3],
+ int,
+ int,
+ int,
+ int);
+
+#if PTS_SAM2P
+bitmap_type bmp_load_image (FILE* filename)
+#else
+bitmap_type bmp_load_image (at_string filename)
+#endif
+{
+ FILE *fd;
+ unsigned char buffer[64];
+ int ColormapSize, rowbytes, Maps=0, Grey;
+ unsigned char ColorMap[256][3];
+ bitmap_type image;
+
+ #if PTS_SAM2P /**** pts ****/
+ fd=filename;
+ #else
+ fd = fopen (filename, "rb");
+
+ if (!fd)
+ FATAL1 ("Can't open \"%s\"\n", filename);
+ #endif
+
+ /* It is a File. Now is it a Bitmap? Read the shortest possible header.*/
+
+ if (!ReadOK(fd, buffer, 18) || (strncmp((const char *)buffer,"BM",2)))
+ #if PTS_SAM2P /**** pts ****/
+ FATALP ("BMP: Not a valid BMP file");
+ #else
+ FATAL ("Not a valid BMP file %s\n");
+ #endif
+
+ /* bring them to the right byteorder. Not too nice, but it should work */
+
+ Bitmap_File_Head.bfSize = ToL (&buffer[0x02]);
+ Bitmap_File_Head.zzHotX = ToS (&buffer[0x06]);
+ Bitmap_File_Head.zzHotY = ToS (&buffer[0x08]);
+ Bitmap_File_Head.bfOffs = ToL (&buffer[0x0a]);
+ Bitmap_File_Head.biSize = ToL (&buffer[0x0e]);
+
+ /* What kind of bitmap is it? */
+
+ if (Bitmap_File_Head.biSize == 12) /* OS/2 1.x ? */
+ {
+ if (!ReadOK (fd, buffer, 8))
+ FATALP ("BMP: Error reading BMP file header #1");
+
+ Bitmap_Head.biWidth = ToS (&buffer[0x00]); /* 12 */
+ Bitmap_Head.biHeight = ToS (&buffer[0x02]); /* 14 */
+ Bitmap_Head.biPlanes = ToS (&buffer[0x04]); /* 16 */
+ Bitmap_Head.biBitCnt = ToS (&buffer[0x06]); /* 18 */
+ Bitmap_Head.biCompr = 0;
+ Bitmap_Head.biSizeIm = 0;
+ Bitmap_Head.biXPels = Bitmap_Head.biYPels = 0;
+ Bitmap_Head.biClrUsed = 0;
+ Maps = 3;
+ }
+ else if (Bitmap_File_Head.biSize == 40) /* Windows 3.x */
+ {
+ if (!ReadOK (fd, buffer, Bitmap_File_Head.biSize - 4))
+ FATALP ("BMP: Error reading BMP file header #2");
+
+ Bitmap_Head.biWidth =ToL (&buffer[0x00]); /* 12 */
+ Bitmap_Head.biHeight =ToL (&buffer[0x04]); /* 16 */
+ Bitmap_Head.biPlanes =ToS (&buffer[0x08]); /* 1A */
+ Bitmap_Head.biBitCnt =ToS (&buffer[0x0A]); /* 1C */
+ Bitmap_Head.biCompr =ToL (&buffer[0x0C]); /* 1E */
+ Bitmap_Head.biSizeIm =ToL (&buffer[0x10]); /* 22 */
+ Bitmap_Head.biXPels =ToL (&buffer[0x14]); /* 26 */
+ Bitmap_Head.biYPels =ToL (&buffer[0x18]); /* 2A */
+ Bitmap_Head.biClrUsed =ToL (&buffer[0x1C]); /* 2E */
+ Bitmap_Head.biClrImp =ToL (&buffer[0x20]); /* 32 */
+ /* 36 */
+ Maps = 4;
+ }
+ else if (Bitmap_File_Head.biSize <= 64) /* Probably OS/2 2.x */
+ {
+ if (!ReadOK (fd, buffer, Bitmap_File_Head.biSize - 4))
+ FATALP ("BMP: Error reading BMP file header #3");
+
+ Bitmap_Head.biWidth =ToL (&buffer[0x00]); /* 12 */
+ Bitmap_Head.biHeight =ToL (&buffer[0x04]); /* 16 */
+ Bitmap_Head.biPlanes =ToS (&buffer[0x08]); /* 1A */
+ Bitmap_Head.biBitCnt =ToS (&buffer[0x0A]); /* 1C */
+ Bitmap_Head.biCompr =ToL (&buffer[0x0C]); /* 1E */
+ Bitmap_Head.biSizeIm =ToL (&buffer[0x10]); /* 22 */
+ Bitmap_Head.biXPels =ToL (&buffer[0x14]); /* 26 */
+ Bitmap_Head.biYPels =ToL (&buffer[0x18]); /* 2A */
+ Bitmap_Head.biClrUsed =ToL (&buffer[0x1C]); /* 2E */
+ Bitmap_Head.biClrImp =ToL (&buffer[0x20]); /* 32 */
+ /* 36 */
+ Maps = 3;
+ }
+ else
+ FATALP ("BMP: Error reading BMP file header #4");
+
+ /* Valid options 1, 4, 8, 16, 24, 32 */
+ /* 16 is awful, we should probably shoot whoever invented it */
+
+ /* There should be some colors used! */
+
+ ColormapSize = (Bitmap_File_Head.bfOffs - Bitmap_File_Head.biSize - 14) / Maps;
+
+ if ((Bitmap_Head.biClrUsed == 0) && (Bitmap_Head.biBitCnt <= 8))
+ Bitmap_Head.biClrUsed = ColormapSize;
+
+ /* Sanity checks */
+
+ if (Bitmap_Head.biHeight == 0 || Bitmap_Head.biWidth == 0)
+ FATALP ("BMP: Error reading BMP file header #5");
+
+ if (Bitmap_Head.biPlanes != 1)
+ FATALP ("BMP: Error reading BMP file header #6");
+
+ if (ColormapSize > 256 || Bitmap_Head.biClrUsed > 256)
+ FATALP ("BMP: Error reading BMP file header #7");
+
+ /* Windows and OS/2 declare filler so that rows are a multiple of
+ * word length (32 bits == 4 bytes)
+ */
+
+ rowbytes= ( (Bitmap_Head.biWidth * Bitmap_Head.biBitCnt - 1) / 32) * 4 + 4;
+
+#ifdef DEBUG
+ printf("\nSize: %u, Colors: %u, Bits: %u, Width: %u, Height: %u, Comp: %u, Zeile: %u\n",
+ Bitmap_File_Head.bfSize,Bitmap_Head.biClrUsed,Bitmap_Head.biBitCnt,Bitmap_Head.biWidth,
+ Bitmap_Head.biHeight, Bitmap_Head.biCompr, rowbytes);
+#endif
+
+ /* Get the Colormap */
+
+ if (ReadColorMap (fd, ColorMap, ColormapSize, Maps, &Grey) == -1)
+ FATALP ("BMP: Cannot read the colormap");
+
+#ifdef DEBUG
+ printf("Colormap read\n");
+#endif
+
+ /* Get the Image and return the ID or -1 on error*/
+ image.bitmap = ReadImage (fd,
+ Bitmap_Head.biWidth,
+ Bitmap_Head.biHeight,
+ ColorMap,
+ Bitmap_Head.biBitCnt,
+ Bitmap_Head.biCompr,
+ rowbytes,
+ Grey);
+ BITMAP_WIDTH (image) = (at_dimen_t) Bitmap_Head.biWidth;
+ BITMAP_HEIGHT (image) = (at_dimen_t) Bitmap_Head.biHeight;
+ BITMAP_PLANES (image) = Grey ? 1 : 3;
+
+ return (image);
+}
+
+static int
+ReadColorMap (FILE *fd,
+ unsigned char buffer[256][3],
+ int number,
+ int size,
+ int *grey)
+{
+ int i;
+ unsigned char rgb[4];
+
+ *grey=(number>2);
+ for (i = 0; i < number ; i++)
+ {
+ if (!ReadOK (fd, rgb, size))
+ FATALP ("BMP: Bad colormap");
+
+ /* Bitmap save the colors in another order! But change only once! */
+
+ buffer[i][0] = rgb[2];
+ buffer[i][1] = rgb[1];
+ buffer[i][2] = rgb[0];
+ *grey = ((*grey) && (rgb[0]==rgb[1]) && (rgb[1]==rgb[2]));
+ }
+ return 0;
+}
+
+static unsigned char*
+ReadImage (FILE *fd,
+ int width,
+ int height,
+ unsigned char cmap[256][3],
+ int bpp,
+ int compression,
+ int rowbytes,
+ int grey)
+{
+ unsigned char v,howmuch;
+ int xpos = 0, ypos = 0;
+ unsigned char *image;
+ unsigned char *temp, *buffer;
+ long rowstride, channels;
+ unsigned short rgb;
+ int i, j;
+
+ if (bpp >= 16) /* color image */
+ {
+ XMALLOCT (image, unsigned char*, width * height * 3 * sizeof (unsigned char));
+ channels = 3;
+ }
+ else if (grey) /* grey image */
+ {
+ XMALLOCT (image, unsigned char*, width * height * 1 * sizeof (unsigned char));
+ channels = 1;
+ }
+ else /* indexed image */
+ {
+ XMALLOCT (image, unsigned char*, width * height * 1 * sizeof (unsigned char));
+ channels = 1;
+ }
+
+ XMALLOCT (buffer, unsigned char*, rowbytes);
+ rowstride = width * channels;
+
+ ypos = height - 1; /* Bitmaps begin in the lower left corner */
+
+ switch (bpp) {
+
+ case 32:
+ {
+ while (ReadOK (fd, buffer, rowbytes))
+ {
+ temp = image + (ypos * rowstride);
+ for (xpos= 0; xpos < width; ++xpos)
+ {
+ *(temp++)= buffer[xpos * 4 + 2];
+ *(temp++)= buffer[xpos * 4 + 1];
+ *(temp++)= buffer[xpos * 4];
+ }
+ --ypos; /* next line */
+ }
+ }
+ break;
+
+ case 24:
+ {
+ while (ReadOK (fd, buffer, rowbytes))
+ {
+ temp = image + (ypos * rowstride);
+ for (xpos= 0; xpos < width; ++xpos)
+ {
+ *(temp++)= buffer[xpos * 3 + 2];
+ *(temp++)= buffer[xpos * 3 + 1];
+ *(temp++)= buffer[xpos * 3];
+ }
+ --ypos; /* next line */
+ }
+ }
+ break;
+
+ case 16:
+ {
+ while (ReadOK (fd, buffer, rowbytes))
+ {
+ temp = image + (ypos * rowstride);
+ for (xpos= 0; xpos < width; ++xpos)
+ {
+ rgb= ToS(&buffer[xpos * 2]);
+ *(temp++)= (unsigned char)(((rgb >> 10) & 0x1f) * 8);
+ *(temp++)= (unsigned char)(((rgb >> 5) & 0x1f) * 8);
+ *(temp++)= (unsigned char)(((rgb) & 0x1f) * 8);
+ }
+ --ypos; /* next line */
+ }
+ }
+ break;
+
+ case 8:
+ case 4:
+ case 1:
+ {
+ if (compression == 0)
+ {
+ while (ReadOK (fd, &v, 1))
+ {
+ for (i = 1; (i <= (8 / bpp)) && (xpos < width); i++, xpos++)
+ {
+ temp = (unsigned char*) (image + (ypos * rowstride) + (xpos * channels));
+ *temp= (unsigned char)(( v & ( ((1<<bpp)-1) << (8-(i*bpp)) ) ) >> (8-(i*bpp)));
+ }
+ if (xpos == width)
+ {
+ (void) ReadOK (fd, buffer, rowbytes - 1 -
+ (width * bpp - 1) / 8);
+ ypos--;
+ xpos = 0;
+
+ }
+ if (ypos < 0)
+ break;
+ }
+ break;
+ }
+ else
+ {
+ while (ypos >= 0 && xpos <= width)
+ {
+ (void) ReadOK (fd, buffer, 2);
+ if ((unsigned char) buffer[0] != 0)
+ /* Count + Color - record */
+ {
+ for (j = 0; ((unsigned char) j < (unsigned char) buffer[0]) && (xpos < width);)
+ {
+#ifdef DEBUG2
+ printf("%u %u | ",xpos,width);
+#endif
+ for (i = 1;
+ ((i <= (8 / bpp)) &&
+ (xpos < width) &&
+ ((unsigned char) j < (unsigned char) buffer[0]));
+ i++, xpos++, j++)
+ {
+ temp = image + (ypos * rowstride) + (xpos * channels);
+ *temp = (unsigned char) ((buffer[1] & (((1<<bpp)-1) << (8 - (i * bpp)))) >> (8 - (i * bpp)));
+ }
+ }
+ }
+ if (((unsigned char) buffer[0] == 0) && ((unsigned char) buffer[1] > 2))
+ /* uncompressed record */
+ {
+ howmuch = buffer[1];
+ for (j = 0; j < howmuch; j += (8 / bpp))
+ {
+ (void) ReadOK (fd, &v, 1);
+ i = 1;
+ while ((i <= (8 / bpp)) && (xpos < width))
+ {
+ temp = image + (ypos * rowstride) + (xpos * channels);
+ *temp = (unsigned char) ((v & (((1<<bpp)-1) << (8-(i*bpp)))) >> (8-(i*bpp)));
+ i++;
+ xpos++;
+ }
+ }
+
+ if ((howmuch % 2) && (bpp==4))
+ howmuch++;
+
+ if ((howmuch / (8 / bpp)) % 2)
+ (void) ReadOK (fd, &v, 1);
+ /*if odd(x div (8 div bpp )) then blockread(f,z^,1);*/
+ }
+ if (((unsigned char) buffer[0] == 0) && ((unsigned char) buffer[1]==0))
+ /* Line end */
+ {
+ ypos--;
+ xpos = 0;
+ }
+ if (((unsigned char) buffer[0]==0) && ((unsigned char) buffer[1]==1))
+ /* Bitmap end */
+ {
+ break;
+ }
+ if (((unsigned char) buffer[0]==0) && ((unsigned char) buffer[1]==2))
+ /* Deltarecord */
+ {
+ (void) ReadOK (fd, buffer, 2);
+ xpos += (unsigned char) buffer[0];
+ ypos -= (unsigned char) buffer[1];
+ }
+ }
+ break;
+ }
+ }
+ break;
+ default:
+ /* This is very bad, we should not be here */
+ ;
+ }
+
+ /* fclose (fd); */
+ if (bpp <= 8)
+ {
+ unsigned char *temp2, *temp3;
+ unsigned char index;
+ temp2 = temp = image;
+ XMALLOCT (image, unsigned char*, width * height * 3 * sizeof (unsigned char));
+ temp3 = image;
+ for (ypos = 0; ypos < height; ypos++)
+ {
+ for (xpos = 0; xpos < width; xpos++)
+ {
+ index = *temp2++;
+ *temp3++ = cmap[index][0];
+ if (!grey)
+ {
+ *temp3++ = cmap[index][1];
+ *temp3++ = cmap[index][2];
+ }
+ }
+ }
+ XFREE (temp);
+ }
+
+ XFREE (buffer);
+ return image;
+}
+
+#if 0 /**** pts ****/
+FILE *errorfile;
+char *prog_name = "bmp";
+char *filename;
+int interactive_bmp;
+#endif
+
+static long
+ToL (unsigned char *puffer)
+{
+ return (puffer[0] | puffer[1]<<8 | puffer[2]<<16 | puffer[3]<<24);
+}
+
+static short
+ToS (unsigned char *puffer)
+{
+ return ((short)(puffer[0] | puffer[1]<<8));
+}
diff --git a/graphics/sam2p/input-pnm.ci b/graphics/sam2p/input-pnm.ci
new file mode 100644
index 0000000000..6f7fff469c
--- /dev/null
+++ b/graphics/sam2p/input-pnm.ci
@@ -0,0 +1,495 @@
+/* This code is ripped from Autotrace-0.29. Small modifications by pts. */
+
+/* input-pnm.ci:
+ * The pnm reading and writing code was written from scratch by Erik Nygren
+ * (nygren@mit.edu) based on the specifications in the man pages and
+ * does not contain any code from the netpbm or pbmplus distributions.
+ */
+
+#ifdef __GNUC__
+#ifndef __clang__
+#pragma implementation
+#endif
+#endif
+
+/* #include "types.h" */
+#include "at_bitmap.h"
+/* #include "input-pnm.h" */
+/* #include "message.h" */
+/* #include "xstd.h" */
+
+/* #include <math.h> -- ceil(); emulated */
+#include <stdlib.h> /* atoi(...) */
+
+/**** pts ****/
+/* #include <ctype.h> */
+#define isspace(c) ((c)=='\0' || (c)==' ' || ((unsigned char)((c)-011)<=(unsigned char)(015-011)))
+/* ^^^ not strictly POSIX C locale */
+#define isdigit(c) ((unsigned char)(c-'0')<=(unsigned char)('9'-'0'))
+
+#if 0
+# define PNMFILE FILE
+# define fread_PNMFILE(s,slen,f) fread(s, 1, slen, f)
+#else
+# define PNMFILE /*Filter::UngetFILED*/GenBuffer::Readable
+# define fread_PNMFILE(s,slen,f) f->vi_read(s, slen)
+#endif
+
+/* Declare local data types
+ */
+
+typedef struct _PNMScanner
+{
+ PNMFILE *fd; /* The file descriptor of the file being read */
+ char cur; /* The current character in the input stream */
+ int eof; /* Have we reached end of file? */
+} PNMScanner;
+
+typedef struct _PNMInfo
+{
+ unsigned int xres, yres; /* The size of the image */
+ int maxval; /* For ascii image files, the max value
+ * which we need to normalize to */
+ int np; /* Number of image planes (0 for pbm) */
+ int asciibody; /* 1 if ascii body, 0 if raw body */
+ /* Routine to use to load the pnm body */
+ void (* loader) (PNMScanner *, struct _PNMInfo *, unsigned char *);
+} PNMInfo;
+
+/* Contains the information needed to write out PNM rows */
+typedef struct _PNMRowInfo
+{
+ PNMFILE *fd; /* File descriptor */
+ char *rowbuf; /* Buffer for writing out rows */
+ int xres; /* X resolution */
+ int np; /* Number of planes */
+ unsigned char *red; /* Colormap red */
+ unsigned char *grn; /* Colormap green */
+ unsigned char *blu; /* Colormap blue */
+} PNMRowInfo;
+
+/* Save info */
+typedef struct
+{
+ int raw; /* raw or ascii */
+} PNMSaveVals;
+
+typedef struct
+{
+ int run; /* run */
+} PNMSaveInterface;
+
+#define PNM_BUFLEN 512 /* The input buffer size for data returned
+ * from the scanner. Note that lines
+ * aren't allowed to be over 256 characters
+ * by the spec anyways so this shouldn't
+ * be an issue. */
+
+#define SAVE_COMMENT_STRING "# CREATOR: The GIMP's PNM Filter Version 1.0\n"
+
+/* Declare some local functions.
+ */
+
+static void pnm_load_ascii (PNMScanner *scan,
+ PNMInfo *info,
+ unsigned char *pixel_rgn);
+static void pnm_load_raw (PNMScanner *scan,
+ PNMInfo *info,
+ unsigned char *pixel_rgn);
+static void pnm_load_rawpbm (PNMScanner *scan,
+ PNMInfo *info,
+ unsigned char *pixel_rgn);
+
+static void pnmscanner_destroy (PNMScanner *s);
+#if 0
+static void pnmscanner_createbuffer (PNMScanner *s,
+ unsigned int bufsize);
+static void pnmscanner_getchar (PNMScanner *s);
+static void pnmscanner_getsmalltoken (PNMScanner *s, unsigned char *buf);
+#endif
+static void pnmscanner_eatwhitespace (PNMScanner *s);
+static void pnmscanner_gettoken (PNMScanner *s,
+ unsigned char *buf,
+ unsigned int bufsize);
+static unsigned pnmscanner_getint(PNMScanner *s);
+
+static PNMScanner * pnmscanner_create (PNMFILE *fd);
+
+
+#define pnmscanner_eof(s) ((s)->eof)
+#define pnmscanner_fd(s) ((s)->fd)
+
+#if 0
+/* pnmscanner_getchar ---
+ * Reads a character from the input stream
+ */
+static void
+pnmscanner_getchar (PNMScanner *s)
+{
+ if (s->inbuf)
+ {
+ s->cur = s->inbuf[s->inbufpos++];
+ if (s->inbufpos >= s->inbufvalidsize)
+ {
+ if (s->inbufsize > s->inbufvalidsize)
+ s->eof = 1;
+ else
+ s->inbufvalidsize = fread(s->inbuf, 1, s->inbufsize, s->fd);
+ s->inbufpos = 0;
+ }
+ }
+ else
+ s->eof = !fread(&(s->cur), 1, 1, s->fd);
+}
+#endif
+
+#define pnmscanner_getchar(s) do { s->eof = !fread_PNMFILE(&(s->cur), 1, s->fd); } while(0)
+
+/* pnmscanner_eatwhitespace ---
+ * Eats up whitespace from the input and returns when done or eof.
+ * Also deals with comments.
+ */
+static inline void pnmscanner_eatwhitespace(PNMScanner *s) { /**** pts ****/
+ while (1) {
+ if (s->cur=='#') {
+ do pnmscanner_getchar(s); while (s->cur!='\n');
+ } else if (!isspace(s->cur)) {
+ break;
+ }
+ pnmscanner_getchar(s);
+ }
+}
+
+
+static struct struct_pnm_types
+{
+ char name;
+ int np;
+ int asciibody;
+ int maxval;
+ void (* loader) (PNMScanner *, struct _PNMInfo *, unsigned char *pixel_rgn);
+} pnm_types[] =
+{
+ { '1', 0, 1, 1, pnm_load_ascii }, /* ASCII PBM */
+ { '2', 1, 1, 255, pnm_load_ascii }, /* ASCII PGM */
+ { '3', 3, 1, 255, pnm_load_ascii }, /* ASCII PPM */
+ { '4', 0, 0, 1, pnm_load_rawpbm }, /* RAW PBM */
+ { '5', 1, 0, 255, pnm_load_raw }, /* RAW PGM */
+ { '6', 3, 0, 255, pnm_load_raw }, /* RAW PPM */
+ { 0 , 0, 0, 0, NULL}
+};
+
+#if PTS_SAM2P
+bitmap_type pnm_load_image (PNMFILE* filename)
+#else
+bitmap_type pnm_load_image (at_string filename)
+#endif
+{
+ char buf[PNM_BUFLEN]; /* buffer for random things like scanning */
+ PNMInfo *pnminfo;
+ PNMScanner * volatile scan;
+ int ctr;
+ PNMFILE* fd;
+ bitmap_type bitmap;
+
+ #if PTS_SAM2P /**** pts ****/
+ fd=filename;
+ #else
+ /* open the file */
+ fd = xfopen (filename, "rb");
+ if (fd == NULL)
+ {
+ FATAL("PNM: can't open file\n");
+ BITMAP_BITS (bitmap) = NULL;
+ BITMAP_WIDTH (bitmap) = 0;
+ BITMAP_HEIGHT (bitmap) = 0;
+ BITMAP_PLANES (bitmap) = 0;
+ return (bitmap);
+ }
+ #endif
+
+
+ /* allocate the necessary structures */
+ /* pnminfo = (PNMInfo *) malloc (sizeof (PNMInfo)); */
+ XMALLOCT(pnminfo, PNMInfo*, sizeof(PNMInfo));
+
+ scan = NULL;
+ /* set error handling */
+
+ scan = pnmscanner_create(fd);
+
+ /* Get magic number */
+ pnmscanner_gettoken (scan, (unsigned char *)buf, PNM_BUFLEN);
+ if (pnmscanner_eof(scan))
+ FATALP ("PNM: premature end of file");
+ if (buf[0] != 'P' || buf[2])
+ FATALP ("PNM: is not a valid file");
+
+ /* Look up magic number to see what type of PNM this is */
+ for (ctr=0; pnm_types[ctr].name; ctr++)
+ if (buf[1] == pnm_types[ctr].name)
+ {
+ pnminfo->np = pnm_types[ctr].np;
+ pnminfo->asciibody = pnm_types[ctr].asciibody;
+ pnminfo->maxval = pnm_types[ctr].maxval;
+ pnminfo->loader = pnm_types[ctr].loader;
+ }
+ if (!pnminfo->loader)
+ FATALP ("PNM: file not in a supported format");
+
+ pnmscanner_gettoken(scan, (unsigned char *)buf, PNM_BUFLEN);
+ if (pnmscanner_eof(scan))
+ FATALP ("PNM: premature end of file");
+ pnminfo->xres = isdigit(*buf)?atoi(buf):0;
+ if (pnminfo->xres<=0)
+ FATALP ("PNM: invalid xres while loading");
+
+ pnmscanner_gettoken(scan, (unsigned char *)buf, PNM_BUFLEN);
+ if (pnmscanner_eof(scan))
+ FATALP ("PNM: premature end of file");
+ pnminfo->yres = isdigit(*buf)?atoi(buf):0;
+ if (pnminfo->yres<=0)
+ FATALP ("PNM: invalid yres while loading");
+
+ if (pnminfo->np != 0) /* pbm's don't have a maxval field */
+ {
+ pnmscanner_gettoken(scan, (unsigned char *)buf, PNM_BUFLEN);
+ if (pnmscanner_eof(scan))
+ FATALP ("PNM: premature end of file");
+
+ pnminfo->maxval = isdigit(*buf)?atoi(buf):0;
+ if ((pnminfo->maxval<=0)
+ || (pnminfo->maxval>255 && !pnminfo->asciibody))
+ FATALP ("PNM: invalid maxval while loading");
+ }
+
+ BITMAP_WIDTH (bitmap) = (at_dimen_t) pnminfo->xres;
+ BITMAP_HEIGHT (bitmap) = (at_dimen_t) pnminfo->yres;
+
+ BITMAP_PLANES (bitmap) = (pnminfo->np)?(pnminfo->np):1;
+ /* BITMAP_BITS (bitmap) = (unsigned char *) malloc (pnminfo->yres * pnminfo->xres * BITMAP_PLANES (bitmap)); */
+ XMALLOCT(BITMAP_BITS (bitmap), unsigned char *, pnminfo->yres * pnminfo->xres * BITMAP_PLANES (bitmap));
+ pnminfo->loader (scan, pnminfo, BITMAP_BITS (bitmap));
+ /* vvv Dat: We detect truncation late truncated files will just have garbage :-( */
+ if (pnmscanner_eof(scan))
+ FATALP ("PNM: truncated image data");
+
+ /* Destroy the scanner */
+ pnmscanner_destroy (scan);
+
+ /* free the structures */
+ /* free (pnminfo); */
+ XFREE(pnminfo);
+
+ /* close the file */
+ /* xfclose (fd, filename); */
+
+ return (bitmap);
+}
+
+static void
+pnm_load_ascii (PNMScanner *scan,
+ PNMInfo *info,
+ unsigned char *data)
+{
+ register unsigned char *d, *dend;
+ unsigned u, s;
+ #if 0 /**** pts ****/
+ /* Buffer reads to increase performance */
+ /* !! convert(1) is faster -- maybe buffering helps? */
+ pnmscanner_createbuffer(scan, 4096);
+ #endif
+ d = data;
+ if (info->np==0) { /* PBM */
+ dend=d+info->xres*info->yres;
+ while (d!=dend) {
+ /* pnmscanner_getsmalltoken(scan, (unsigned char *)buf); */
+ pnmscanner_eatwhitespace(scan);
+ *d++=-(scan->cur=='0');
+ pnmscanner_getchar(scan);
+ }
+ } else { /* PGM or PPM */ /**** pts ****/
+ dend=d+info->xres*info->yres*info->np;
+ switch (s=info->maxval) {
+ case 255:
+ while (d!=dend) {
+ *d++=pnmscanner_getint(scan); /* Dat: removed isdigit() */
+ }
+ break;
+ case 15:
+ while (d!=dend) {
+ *d++ = pnmscanner_getint(scan)*17;
+ }
+ break;
+ case 3:
+ while (d!=dend) {
+ *d++ = pnmscanner_getint(scan)*85;
+ }
+ break;
+ case 0: /* avoid division by 0 */
+ case 1:
+ while (d!=dend) {
+ *d++ = -(0==pnmscanner_getint(scan)); /* (*buf=='0')?0xff:0x00; */
+ }
+ default:
+ while (d!=dend) {
+ u=pnmscanner_getint(scan);
+ *d++ = (0UL+u*255UL+(s>>1))/s; /* always <= 255 */
+ }
+ }
+ }
+}
+
+static void
+pnm_load_raw (PNMScanner *scan,
+ PNMInfo *info,
+ unsigned char *data)
+{
+ unsigned char *d, *dend;
+ unsigned s=info->maxval;
+ slen_t delta, scanlines;
+ PNMFILE *fd=pnmscanner_fd(scan);
+
+ scanlines = info->yres;
+ d = data;
+ delta=info->xres * info->np;
+ dend=d+delta*scanlines;
+ while (d!=dend) {
+ if (info->xres*info->np != fread_PNMFILE((char*)d, delta, fd)) return;
+ d+=delta;
+ }
+ d=data;
+ switch (s=info->maxval) { /**** pts ****/
+ case 1: case 0:
+ for (; d!=dend; d++) if (*d!=0) *d=255;
+ break;
+ case 3:
+ while (d!=dend) *d++*=85;
+ break;
+ case 15:
+ while (d!=dend) *d++*=17;
+ break;
+ case 255:
+ break;
+ default:
+ for (; d!=dend; d++) *d=(0UL+*d*255UL+(s>>1))/s; /* always <= 255 */
+ break;
+ }
+}
+
+static void
+pnm_load_rawpbm (PNMScanner *scan,
+ PNMInfo *info,
+ unsigned char *data)
+{
+ unsigned char *buf;
+ unsigned char curbyte;
+ unsigned char *d;
+ unsigned int x, i;
+ unsigned int start, end, scanlines;
+ PNMFILE *fd;
+ unsigned int rowlen, bufpos;
+
+ fd = pnmscanner_fd(scan);
+ /****pts****/ /* rowlen = (unsigned int)ceil((double)(info->xres)/8.0);*/
+ rowlen=(info->xres+7)>>3;
+ /* buf = (unsigned char *)malloc(rowlen*sizeof(unsigned char)); */
+ XMALLOCT(buf, unsigned char*, rowlen*sizeof(unsigned char));
+
+ start = 0;
+ end = info->yres;
+ scanlines = end - start;
+ d = data;
+
+ for (i = 0; i < scanlines; i++)
+ {
+ if (rowlen != fread_PNMFILE((char*)buf, rowlen, fd))
+ FATALP ("PNM: error reading file");
+ bufpos = 0;
+ curbyte = buf[0];
+
+ for (x = 0; x < info->xres; x++)
+ {
+ if ((x % 8) == 0) {
+ curbyte = buf[bufpos++];
+ /* // if (curbyte!=0) printf("%d <%u>\n", x, curbyte); */
+ }
+ /* // if (curbyte!=0) printf("[%u]\n", curbyte); */
+ d[x] = (curbyte&0x80) ? 0x00 : 0xff;
+ curbyte <<= 1;
+ }
+
+ d += info->xres;
+ }
+
+ XFREE(buf);
+}
+
+/**************** FILE SCANNER UTILITIES **************/
+
+/* pnmscanner_create ---
+ * Creates a new scanner based on a file descriptor. The
+ * look ahead buffer is one character initially.
+ */
+static PNMScanner *
+pnmscanner_create (PNMFILE *fd)
+{
+ PNMScanner *s;
+
+ XMALLOCT (s, PNMScanner*, sizeof(PNMScanner));
+ s->fd = fd;
+ s->eof = !fread_PNMFILE(&(s->cur), 1, s->fd);
+ return s;
+}
+
+/* pnmscanner_destroy ---
+ * Destroys a scanner and its resources. Doesn't close the fd.
+ */
+static void
+pnmscanner_destroy (PNMScanner *s)
+{
+ XFREE(s);
+}
+
+#if 0 /**** pts ****/
+/* pnmscanner_createbuffer ---
+ * Creates a buffer so we can do buffered reads.
+ */
+static void
+pnmscanner_createbuffer (PNMScanner *s,
+ unsigned int bufsize)
+{
+ /* s->inbuf = (char *)malloc(sizeof(char)*bufsize); */
+ XMALLOCT(s->inbuf, char*, sizeof(char)*bufsize);
+ s->inbufsize = bufsize;
+ s->inbufpos = 0;
+ s->inbufvalidsize = fread(s->inbuf, 1, bufsize, s->fd);
+}
+#endif
+
+/* pnmscanner_gettoken ---
+ * Gets the next token, eating any leading whitespace.
+ */
+static void pnmscanner_gettoken (PNMScanner *s,
+ unsigned char *buf,
+ unsigned int bufsize)
+{
+ unsigned char *bufend=buf+bufsize-1;
+ pnmscanner_eatwhitespace(s);
+ while (!pnmscanner_eof(s) && !isspace(s->cur) && s->cur!='#') {
+ if (buf!=bufend) *buf++=s->cur;
+ pnmscanner_getchar(s);
+ }
+ *buf='\0';
+}
+
+static unsigned pnmscanner_getint(PNMScanner *s) {
+ unsigned ret=0;
+ pnmscanner_eatwhitespace(s);
+ while (!pnmscanner_eof(s)) {
+ if (isdigit(s->cur)) ret=10*ret+s->cur-'0';
+ else if (isspace(s->cur) || s->cur=='#') break;
+ pnmscanner_getchar(s);
+ }
+ return ret;
+}
diff --git a/graphics/sam2p/input-tga.ci b/graphics/sam2p/input-tga.ci
new file mode 100644
index 0000000000..6a936b9786
--- /dev/null
+++ b/graphics/sam2p/input-tga.ci
@@ -0,0 +1,591 @@
+/* This code is ripped from Autotrace-0.29. Small modifications by pts. */
+
+/* input-tga.ci reads tga files */
+
+#ifdef __GNUC__
+#ifndef __clang__
+#pragma implementation
+#endif
+#endif
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+/* #include <unistd.h> */
+
+#include "at_bitmap.h"
+/* #include "message.h" */
+/* #include "xstd.h" */
+/* #include "input-tga.h" */ /* BUGFIX by pts: bmp -> tga */
+
+/* TODO:
+ - Handle loading images that aren't 8 bits per channel.
+*/
+
+/* Round up a division to the nearest integer. */
+#define ROUNDUP_DIVIDE(n,d) (((n) + (d - 1)) / (d))
+
+#define MAX(a,b) ((a) > (b) ? (a) : (b))
+#define MIN(a,b) ((a) < (b) ? (a) : (b))
+
+#define INDEXED 1
+#define INDEXEDA 2
+#define GRAY 3
+#define TGA_RGB 5
+#define INDEXED_IMAGE 1
+#define INDEXEDA_IMAGE 2
+#define GRAY_IMAGE 3
+#define GRAYA_IMAGE 4
+#define TGA_RGB_IMAGE 5
+#define TGA_RGBA_IMAGE 6
+
+typedef struct _TgaSaveVals
+{
+ int rle;
+} TgaSaveVals;
+
+typedef struct _TgaSaveInterface
+{
+ int run;
+} TgaSaveInterface;
+
+struct tga_header
+{
+ unsigned char idLength;
+ unsigned char colorMapType;
+
+ /* The image type. */
+#define TGA_TYPE_MAPPED 1
+#define TGA_TYPE_COLOR 2
+#define TGA_TYPE_GRAY 3
+#define TGA_TYPE_MAPPED_RLE 9
+#define TGA_TYPE_COLOR_RLE 10
+#define TGA_TYPE_GRAY_RLE 11
+ unsigned char imageType;
+
+ /* Color Map Specification. */
+ /* We need to separately specify high and low bytes to avoid endianness
+ and alignment problems. */
+ unsigned char colorMapIndexLo, colorMapIndexHi;
+ unsigned char colorMapLengthLo, colorMapLengthHi;
+ unsigned char colorMapSize;
+
+ /* Image Specification. */
+ unsigned char xOriginLo, xOriginHi;
+ unsigned char yOriginLo, yOriginHi;
+
+ unsigned char widthLo, widthHi;
+ unsigned char heightLo, heightHi;
+
+ unsigned char bpp;
+
+ /* Image descriptor.
+ 3-0: attribute bpp
+ 4: left-to-right ordering
+ 5: top-to-bottom ordering
+ 7-6: zero
+ */
+#define TGA_DESC_ABITS 0x0f
+#define TGA_DESC_HORIZONTAL 0x10
+#define TGA_DESC_VERTICAL 0x20
+ unsigned char descriptor;
+};
+
+#if 0
+static struct
+{
+ unsigned int extensionAreaOffset;
+ unsigned int developerDirectoryOffset;
+#define TGA_SIGNATURE "TRUEVISION-XFILE"
+ char signature[16];
+ char dot;
+ char null;
+} tga_footer;
+#endif
+
+
+static bitmap_type ReadImage (FILE *fp,
+ struct tga_header *hdr);
+#if PTS_SAM2P /**** pts ****/
+bitmap_type tga_load_image (FILE* filename)
+#else
+bitmap_type tga_load_image (at_string filename)
+#endif
+{
+ FILE *fp;
+ struct tga_header hdr;
+
+ bitmap_type image;
+
+ image.bitmap = NULL;
+
+ #if PTS_SAM2P /**** pts ****/
+ fp=filename;
+ #else
+ fp = fopen (filename, "rb");
+ if (!fp)
+ FATAL1 ("TGA: can't open \"%s\"\n", filename);
+ #endif
+
+ memset(&hdr, '\0', sizeof(hdr));
+
+#if 0
+ /* Check the footer. */
+ if (fseek (fp, 0L - (sizeof (tga_footer)), SEEK_END)
+ || fread (&tga_footer, sizeof (tga_footer), 1, fp) != 1)
+#if PTS_SAM2P
+ FATALP("TGA: Cannot read footer");
+#else
+ FATAL1 ("TGA: Cannot read footer from \"%s\"\n", filename);
+#endif
+ /* Check the signature. */
+ if (fseek (fp, 0, SEEK_SET) ||
+#else
+ if (0 ||
+#endif
+ fread (&hdr, sizeof (hdr), 1, fp) != 1)
+#if PTS_SAM2P
+ FATALP("TGA: Cannot read header");
+#else
+ FATAL1 ("TGA: Cannot read header from \"%s\"\n", filename);
+#endif
+
+ /* Skip the image ID field. */
+ {
+#if 0
+ if (hdr.idLength && fseek (fp, hdr.idLength, SEEK_CUR))
+#else
+ char buf[256];
+ if (hdr.idLength!=fread(buf, 1, hdr.idLength, fp))
+#endif
+#if PTS_SAM2P
+ FATALP("TGA: Cannot skip ID field");
+#else
+ FATAL1 ("TGA: Cannot skip ID field in \"%s\"\n", filename);
+#endif
+ }
+
+ image = ReadImage (fp, &hdr);
+ /* fclose (fp); */
+ return image;
+}
+
+
+static int
+std_fread (unsigned char *buf,
+ int datasize,
+ int nelems,
+ FILE *fp)
+{
+
+ return fread (buf, datasize, nelems, fp);
+}
+
+#define RLE_PACKETSIZE 0x80
+
+/* Decode a bufferful of file. */
+static int
+rle_fread (unsigned char *buf,
+ int datasize,
+ int nelems,
+ FILE *fp)
+{
+ static unsigned char *statebuf = 0;
+ static int statelen = 0;
+ static int laststate = 0;
+
+ int j, k;
+ int buflen, count, bytes;
+ unsigned char *p;
+
+ /* Scale the buffer length. */
+ buflen = nelems * datasize;
+
+ j = 0;
+ while (j < buflen)
+ {
+ if (laststate < statelen)
+ {
+ /* Copy bytes from our previously decoded buffer. */
+ bytes = MIN (buflen - j, statelen - laststate);
+ memcpy (buf + j, statebuf + laststate, bytes);
+ j += bytes;
+ laststate += bytes;
+
+ /* If we used up all of our state bytes, then reset them. */
+ if (laststate >= statelen)
+ {
+ laststate = 0;
+ statelen = 0;
+ }
+
+ /* If we filled the buffer, then exit the loop. */
+ if (j >= buflen)
+ break;
+ }
+
+ /* Decode the next packet. */
+ count = fgetc (fp);
+ if (count == EOF)
+ {
+ return j / datasize;
+ }
+
+ /* Scale the byte length to the size of the data. */
+ bytes = ((count & ~RLE_PACKETSIZE) + 1) * datasize;
+
+ if (j + bytes <= buflen)
+ {
+ /* We can copy directly into the image buffer. */
+ p = buf + j;
+ }
+ else {
+ /* Allocate the state buffer if we haven't already. */
+ if (!statebuf)
+ statebuf = (unsigned char *) malloc (RLE_PACKETSIZE * datasize);
+ p = statebuf;
+ }
+
+ if (count & RLE_PACKETSIZE)
+ {
+ /* Fill the buffer with the next value. */
+ if (fread (p, datasize, 1, fp) != 1)
+ {
+ return j / datasize;
+ }
+
+ /* Optimized case for single-byte encoded data. */
+ if (datasize == 1)
+ memset (p + 1, *p, bytes - 1);
+ else
+ for (k = datasize; k < bytes; k += datasize)
+ memcpy (p + k, p, datasize);
+ }
+ else
+ {
+ /* Read in the buffer. */
+ if (fread (p, bytes, 1, fp) != 1)
+ {
+ return j / datasize;
+ }
+ }
+
+ /* We may need to copy bytes from the state buffer. */
+ if (p == statebuf)
+ statelen = bytes;
+ else
+ j += bytes;
+ }
+
+return nelems;
+}
+
+static bitmap_type
+ReadImage (FILE *fp,
+ struct tga_header *hdr)
+{
+ bitmap_type image;
+ unsigned char *buffer;
+ unsigned char *alphas;
+
+ int width, height, bpp, abpp, pbpp, nalphas;
+ int j, k;
+ int pelbytes, wbytes, bsize, npels, pels;
+ int rle, badread;
+ int itype=0;
+ unsigned char *cmap = NULL;
+ int (*myfread)(unsigned char *, int, int, FILE *);
+
+ /* Find out whether the image is horizontally or vertically reversed. */
+ char horzrev = (char) (hdr->descriptor & TGA_DESC_HORIZONTAL);
+ char vertrev = (char) (!(hdr->descriptor & TGA_DESC_VERTICAL));
+
+ image.bitmap = NULL;
+
+ /* Reassemble the multi-byte values correctly, regardless of
+ host endianness. */
+ width = (hdr->widthHi << 8) | hdr->widthLo;
+ height = (hdr->heightHi << 8) | hdr->heightLo;
+
+ bpp = hdr->bpp;
+ abpp = hdr->descriptor & TGA_DESC_ABITS;
+
+ if (hdr->imageType == TGA_TYPE_COLOR ||
+ hdr->imageType == TGA_TYPE_COLOR_RLE)
+ pbpp = MIN (bpp / 3, 8) * 3;
+ else if (abpp < bpp)
+ pbpp = bpp - abpp;
+ else
+ pbpp = bpp;
+
+ if (abpp + pbpp > bpp)
+ {
+ WARNINGP3 ("TGA: ",pbpp," bit image, ",abpp," bit alpha is greater than ",bpp," total bits per pixel");
+
+ /* Assume that alpha bits were set incorrectly. */
+ abpp = bpp - pbpp;
+ WARNINGP1 ("TGA: reducing to * bit alpha: ", abpp);
+ }
+ else if (abpp + pbpp < bpp)
+ {
+ WARNINGP3 ("TGA: ",pbpp," bit image, ",abpp," bit alpha is less than ",bpp," total bits per pixel");
+
+ /* Again, assume that alpha bits were set incorrectly. */
+ abpp = bpp - pbpp;
+ WARNINGP1 ("TGA: increasing to * bit alpha: ", abpp);
+ }
+
+ rle = 0;
+ switch (hdr->imageType)
+ {
+ case TGA_TYPE_MAPPED_RLE:
+ rle = 1;
+ case TGA_TYPE_MAPPED:
+ itype = INDEXED;
+
+ /* Find the size of palette elements. */
+ pbpp = MIN (hdr->colorMapSize / 3, 8) * 3;
+ if (pbpp < hdr->colorMapSize)
+ abpp = hdr->colorMapSize - pbpp;
+ else
+ abpp = 0;
+
+
+ if (bpp != 8)
+ /* We can only cope with 8-bit indices. */
+ FATALP ("TGA: index sizes other than 8 bits are unimplemented");
+ break;
+
+ case TGA_TYPE_GRAY_RLE:
+ rle = 1;
+ case TGA_TYPE_GRAY:
+ itype = GRAY;
+ break;
+
+ case TGA_TYPE_COLOR_RLE:
+ rle = 1;
+ case TGA_TYPE_COLOR:
+ itype = TGA_RGB;
+ break;
+
+ default:
+ FATALP1 ("TGA: unrecognized image type ", (unsigned)hdr->imageType);
+}
+
+ if ((abpp && abpp != 8) ||
+ ((itype == TGA_RGB || itype == INDEXED) && pbpp != 24) ||
+ (itype == GRAY && pbpp != 8))
+ /* FIXME: We haven't implemented bit-packed fields yet. */
+ FATALP ("TGA: channel sizes other than 8 bits are unimplemented");
+
+ /* Check that we have a color map only when we need it. */
+ if (itype == INDEXED)
+ {
+ if (hdr->colorMapType != 1)
+ FATALP1 ("TGA: indexed image has invalid color map type ",
+ (unsigned)hdr->colorMapType);
+ }
+ else if (hdr->colorMapType != 0)
+ FATALP1 ("TGA: non-indexed image has invalid color map type ",
+ (unsigned)hdr->colorMapType);
+
+ alphas = 0;
+ nalphas = 0;
+ if (hdr->colorMapType == 1)
+ {
+ /* We need to read in the colormap. */
+ int index, colors;
+ unsigned int length;
+
+ index = (hdr->colorMapIndexHi << 8) | hdr->colorMapIndexLo;
+ length = (hdr->colorMapLengthHi << 8) | hdr->colorMapLengthLo;
+
+ if (length == 0)
+ FATALP1 ("TGA: invalid color map length ", length);
+
+ pelbytes = ROUNDUP_DIVIDE (hdr->colorMapSize, 8);
+ colors = length + index;
+ cmap = (unsigned char *) malloc (colors * pelbytes);
+
+ /* Zero the entries up to the beginning of the map. */
+ memset (cmap, 0, index * pelbytes);
+
+ /* Read in the rest of the colormap. */
+ if (fread (cmap + (index * pelbytes), pelbytes, length, fp) != length)
+ FATALP1 ("TGA: error reading colormap; ftell == ", ftell (fp));
+
+ /* If we have an alpha channel, then create a mapping to the alpha
+ values. */
+ if (pelbytes > 3)
+ alphas = (unsigned char *) malloc (colors);
+
+ k = 0;
+ for (j = 0; j < colors * pelbytes; j += pelbytes)
+ {
+ /* Swap from BGR to TGA_RGB. */
+ unsigned char tmp = cmap[j];
+ cmap[k ++] = cmap[j + 2];
+ cmap[k ++] = cmap[j + 1];
+ cmap[k ++] = tmp;
+
+ /* Take the alpha values out of the colormap. */
+ if (alphas)
+ alphas[nalphas ++] = cmap[j + 3];
+ }
+
+ /* If the last color was transparent, then omit it from the
+ mapping. */
+ if (nalphas && alphas[nalphas - 1] == 0)
+ colors --;
+
+ /* Now pretend as if we only have 8 bpp. */
+ abpp = 0;
+ pbpp = 8;
+ pelbytes = 1;
+ }
+ else
+ pelbytes = 3;
+
+ image.bitmap = (unsigned char *) malloc (width * height * 3 * sizeof(unsigned char));
+ BITMAP_WIDTH (image) = (unsigned short) width;
+ BITMAP_HEIGHT (image) = (unsigned short) height;
+ BITMAP_PLANES (image) = (unsigned short) 3;
+
+ /* Calculate TGA bytes per pixel. */
+ bpp = ROUNDUP_DIVIDE (pbpp + abpp, 8);
+
+ /* Maybe we need to reverse the data. */
+ buffer = NULL;
+ if (horzrev || vertrev)
+ buffer = (unsigned char *) malloc (width * height * pelbytes * sizeof (unsigned char));
+ if (rle)
+ myfread = rle_fread;
+ else
+ myfread = std_fread;
+
+ wbytes = width * pelbytes;
+ badread = 0;
+
+ npels = width * height;
+ bsize = wbytes * height;
+
+ /* Suck in the data one height at a time. */
+ if (badread)
+ pels = 0;
+ else
+ pels = (*myfread) (image.bitmap, bpp, npels, fp);
+
+ if (pels != npels)
+ {
+ if (!badread)
+ {
+ /* Probably premature end of file. */
+ WARNINGP1 ("TGA: error reading; ftell == ", ftell (fp));
+ badread = 1;
+ }
+
+
+ /* Fill the rest of this tile with zeros. */
+ memset (image.bitmap + (pels * bpp), 0, ((npels - pels) * bpp));
+ }
+ /* If we have indexed alphas, then set them. */
+ if (nalphas)
+ {
+ /* Start at the end of the buffer, and work backwards. */
+ k = (npels - 1) * bpp;
+ for (j = bsize - pelbytes; j >= 0; j -= pelbytes)
+ {
+ /* Find the alpha for this index. */
+ image.bitmap[j + 1] = alphas[image.bitmap[k]];
+ image.bitmap[j] = image.bitmap[k --];
+ }
+ }
+
+ if (itype == GRAY)
+ for (j = bsize/3 - 1; j >= 0; j -= 1)
+ {
+ /* Find the alpha for this index. */
+ image.bitmap[3*j] = image.bitmap[j];
+ image.bitmap[3*j+1] = image.bitmap[j];
+ image.bitmap[3*j+2] = image.bitmap[j];
+ }
+
+
+ if (pelbytes >= 3)
+ {
+ /* Rearrange the colors from BGR to TGA_RGB. */
+ for (j = 0; j < bsize; j += pelbytes)
+ {
+ unsigned char tmp = image.bitmap[j];
+ image.bitmap[j] = image.bitmap[j + 2];
+ image.bitmap[j + 2] = tmp;
+ }
+ }
+
+
+
+ if (horzrev || vertrev)
+ {
+ unsigned char *tmp;
+ if (vertrev)
+ {
+ /* We need to mirror only vertically. */
+ for (j = 0; j < bsize; j += wbytes)
+ memcpy (buffer + j,
+ image.bitmap + bsize - (j + wbytes), wbytes);
+ }
+ else if (horzrev)
+ {
+ /* We need to mirror only horizontally. */
+ for (j = 0; j < bsize; j += wbytes)
+ for (k = 0; k < wbytes; k += pelbytes)
+ memcpy (buffer + k + j,
+ image.bitmap + (j + wbytes) - (k + pelbytes), pelbytes);
+ }
+ else
+ {
+ /* Completely reverse the pixels in the buffer. */
+ for (j = 0; j < bsize; j += pelbytes)
+ memcpy (buffer + j,
+ image.bitmap + bsize - (j + pelbytes), pelbytes);
+ }
+
+ /* Swap the buffers because we modified them. */
+ tmp = buffer;
+ buffer = image.bitmap;
+ image.bitmap = tmp;
+ }
+
+ if (fgetc (fp) != EOF)
+ WARNINGP ("TGA: too much input data, ignoring extra...");
+
+ free (buffer);
+
+ if (hdr->colorMapType == 1)
+ {
+ unsigned char *temp, *temp2, *temp3;
+ unsigned char index;
+ int xpos, ypos;
+
+ temp2 = temp = image.bitmap;
+ image.bitmap = temp3 = (unsigned char *) malloc (width * height * 3 * sizeof (unsigned char));
+
+ for (ypos = 0; ypos < height; ypos++)
+ {
+ for (xpos = 0; xpos < width; xpos++)
+ {
+ index = *temp2++;
+ *temp3++ = cmap[3*index+0];
+ *temp3++ = cmap[3*index+1];
+ *temp3++ = cmap[3*index+2];
+ }
+ }
+ free (temp);
+ free (cmap);
+ }
+
+ if (alphas)
+ free (alphas);
+
+ return image;
+} /* read_image */
diff --git a/graphics/sam2p/jpegdump_main.cpp b/graphics/sam2p/jpegdump_main.cpp
new file mode 100644
index 0000000000..804d89fbdd
--- /dev/null
+++ b/graphics/sam2p/jpegdump_main.cpp
@@ -0,0 +1,306 @@
+\/*
+ * jpegdump_main.cpp -- dump a JPEG stream
+ * by pts@math.bme.hu at Tue Jun 4 13:19:00 CEST 2002
+ */
+
+
+/* Structure of a typical JPEG file:
+(D8:SOI) (E0:APP0) (FE:COM)? (DB:DQT)*2 (C0:SOF0) (C4:DHT)*4 (DA:SOS)
+... (D9:EOI)
+*/
+
+#ifdef __GNUC__
+#ifndef __clang__
+#pragma implementation
+#endif
+#endif
+
+#include "config2.h"
+#include <stdio.h>
+
+#if OBJDEP
+#warning PROVIDES: jpegdump_main
+#endif
+
+typedef slen_t dimen_t;
+static const unsigned char
+ CS_UNKNOWN=0, /* error/unspecified */
+ CS_GRAYSCALE=1, /* monochrome */
+ CS_RGB=2, /* red/green/blue */
+ CS_YCbCr=3, /* Y/Cb/Cr (also known as YUV) */
+ CS_CMYK=4, /* C/M/Y/K */
+ CS_YCCK=5, /* Y/Cb/Cr/K */
+ CS_Indexed_RGB=12;
+
+
+/* --- The following code is based on standard/image.c from PHP4 */
+
+/* some defines for the different JPEG block types */
+#define M_SOF0 0xC0 /* Start Of Frame N */
+#define M_SOF1 0xC1 /* N indicates which compression process */
+#define M_SOF2 0xC2 /* Only SOF0-SOF2 are now in common use */
+#define M_SOF3 0xC3
+#define M_SOF5 0xC5 /* NB: codes C4 and CC are NOT SOF markers */
+#define M_SOF6 0xC6
+#define M_SOF7 0xC7
+#define M_SOF9 0xC9
+#define M_SOF10 0xCA
+#define M_SOF11 0xCB
+#define M_SOF13 0xCD
+#define M_SOF14 0xCE
+#define M_SOF15 0xCF
+#define M_SOI 0xD8
+#define M_EOI 0xD9 /* End Of Image (end of datastream) */
+#define M_SOS 0xDA /* Start Of Scan (begins compressed data) */
+#define M_COM 0xFE /* comment */
+#define M_DQT 0xDB /* QuantTables */
+#define M_DHT 0xC4 /* HuffTables */
+#define M_APP0 0xe0
+#define M_APP1 0xe1
+#define M_APP2 0xe2
+#define M_APP3 0xe3
+#define M_APP4 0xe4
+#define M_APP5 0xe5
+#define M_APP6 0xe6
+#define M_APP7 0xe7
+#define M_APP8 0xe8
+#define M_APP9 0xe9
+#define M_APP10 0xea
+#define M_APP11 0xeb
+#define M_APP12 0xec
+#define M_APP13 0xed
+#define M_APP14 0xee
+#define M_APP15 0xef
+
+
+static unsigned short jai_read2(FILE *fp) {
+ unsigned char a[ 2 ];
+
+ /* just return 0 if we hit the end-of-file */
+ if (fread(a,sizeof(a),1,fp) != 1) return 0;
+
+ return (((unsigned short) a[ 0 ]) << 8) + ((unsigned short) a[ 1 ]);
+}
+
+static unsigned int jai_next_marker(FILE *fp)
+ /* get next marker byte from file */
+{
+ int c;
+
+ /* skip unimportant stuff */
+
+ c = MACRO_GETC(fp);
+
+ while (c != 0xff) {
+ if ((c = MACRO_GETC(fp)) == EOF)
+ return M_EOI; /* we hit EOF */
+ }
+
+ /* get marker byte, swallowing possible padding */
+ do {
+ if ((c = MACRO_GETC(fp)) == EOF)
+ return M_EOI; /* we hit EOF */
+ } while (c == 0xff);
+
+ // printf("marker=%02X\n", c);
+ return (unsigned int) c;
+}
+
+static void jai_skip_variable(FILE *fp)
+ /* skip over a variable-length block; assumes proper length marker */
+{
+ unsigned short length;
+
+ printf("%lu: skip variable\n", ftell(fp));
+
+ length = jai_read2(fp);
+ length -= 2; /* length includes itself */
+ if (length>0) {
+ printf("... variable length=%u\n", length);
+ #if 0
+ fseek(fp, (long) length, SEEK_CUR); /* skip the header */
+ #endif
+ while (length--!=0) MACRO_GETC(fp); /* make feof(fp) correct */
+ printf("%lu: skipped variable; feof=%u\n", ftell(fp), feof(fp));
+ }
+}
+
+struct gfxinfo {
+ unsigned char bad, bpc, cpp, had_jfif, colortransform, id_rgb;
+ dimen_t height, width;
+ /** Offset of byte just _after_ the first SOF marker (FF C0 or alike)
+ * from the beginning of the file.
+ */
+ slen_t SOF_offs;
+};
+
+/** main loop to parse JPEG structure */
+static void jai_handle_jpeg(struct gfxinfo *result, FILE *fp) {
+ unsigned int length, marker;
+ unsigned char had_adobe, id, hvs, qtn;
+
+ result->bad=1; /* signal invalid return value */
+ result->id_rgb=0;
+ result->had_jfif=0;
+ result->colortransform=127; /* no Adobe marker yet */
+ // fseek(fp, 0L, SEEK_SET); /* position file pointer on SOF */
+
+ if (MACRO_GETC(fp) != 0xFF || MACRO_GETC(fp)!=M_SOI) return; /* JPEG header... */
+ printf("2: marker D8 (SOI)\n");
+
+ for (;;) {
+ assert(!feof(fp));
+ printf("... %lu\n", ftell(fp));
+ marker=jai_next_marker(fp);
+ printf("%lu: marker %02X\n", ftell(fp), marker);
+ switch (marker) {
+ case M_SOF0:
+ if (result->bad!=1) { result->bad=4; return; } /* only one M_SOF allowed */
+ result->SOF_offs=ftell(fp);
+ /* handle SOFn block */
+ length=jai_read2(fp);
+ result->bpc = MACRO_GETC(fp);
+ result->height = jai_read2(fp);
+ result->width = jai_read2(fp);
+ result->cpp = MACRO_GETC(fp);
+ if ((length-=8)!=3U*result->cpp) return;
+ if (result->cpp==3) {
+ result->id_rgb =(id=MACRO_GETC(fp)=='R'); hvs=MACRO_GETC(fp); qtn=MACRO_GETC(fp);
+ printf("Comp#1 id=0x%02X h_samp_fact=%u v_samp_fact=%u quant_tbl_no=%u\n",
+ id, hvs>>4, hvs&15, qtn);
+ result->id_rgb&=(id=MACRO_GETC(fp)=='G'); hvs=MACRO_GETC(fp); qtn=MACRO_GETC(fp);
+ printf("Comp#2 id=0x%02X h_samp_fact=%u v_samp_fact=%u quant_tbl_no=%u\n",
+ id, hvs>>4, hvs&15, qtn);
+ result->id_rgb&=(id=MACRO_GETC(fp)=='B'); hvs=MACRO_GETC(fp); qtn=MACRO_GETC(fp);
+ printf("Comp#3 id=0x%02X h_samp_fact=%u v_samp_fact=%u quant_tbl_no=%u\n",
+ id, hvs>>4, hvs&15, qtn);
+ } else while (length--!=0) MACRO_GETC(fp);
+ if (result->cpp!=1 && result->cpp!=3 && result->cpp!=4) {
+ result->bad=5; return;
+ }
+ if (feof(fp)) { result->bad=8; return; }
+ result->bad=2;
+ break;
+ case M_SOF1:
+ case M_SOF2:
+ case M_SOF3:
+ case M_SOF5:
+ case M_SOF6:
+ case M_SOF7:
+ case M_SOF9:
+ case M_SOF10:
+ case M_SOF11:
+ case M_SOF13:
+ case M_SOF14:
+ case M_SOF15:
+ // fprintf(stderr, "SOF%u\n", marker-M_SOF0); assert(0);
+ result->bad=3;
+ return;
+ case M_SOS: /* we are about to hit image data. We're done. */
+ jai_skip_variable(fp); /* anything else isn't interesting */
+ if (feof(fp)) { result->bad=8; return; }
+ if (result->bad==2 && !feof(fp)) result->bad=0;
+ /* Dat: we should really return() here, because the SOS marker is
+ * followed by binary data, not surrounded by markers.
+ */
+ break;
+ case M_EOI: /* end of image or EOF */
+ if (feof(fp)) result->bad=6;
+ else if (MACRO_GETC(fp)!=EOF) result->bad=7;
+ return;
+ case M_APP0: /* JFIF application-specific marker */
+ length=jai_read2(fp);
+ if (length==2+4+1+2+1+2+2+1+1) {
+ result->had_jfif=MACRO_GETC(fp)=='J' && MACRO_GETC(fp)=='F' && MACRO_GETC(fp)=='I' &&
+ MACRO_GETC(fp)=='F' && MACRO_GETC(fp)==0;
+ length-=7;
+ } else length-=2;
+ while (length--!=0) MACRO_GETC(fp);
+ if (feof(fp)) { result->bad=8; return; }
+ break;
+ case M_APP14: /* Adobe application-specific marker */
+ length=jai_read2(fp);
+ if ((length-=2)==5+2+2+2+1) {
+ had_adobe=MACRO_GETC(fp)=='A' && MACRO_GETC(fp)=='d' && MACRO_GETC(fp)=='o' &&
+ MACRO_GETC(fp)=='b' && MACRO_GETC(fp)=='e' && ((unsigned char)MACRO_GETC(fp))>=1;
+ MACRO_GETC(fp); MACRO_GETC(fp); MACRO_GETC(fp); MACRO_GETC(fp); MACRO_GETC(fp);
+ if (had_adobe) result->colortransform=MACRO_GETC(fp);
+ else MACRO_GETC(fp);
+ } else while (length--!=0) MACRO_GETC(fp);
+ if (feof(fp)) { result->bad=8; return; }
+ break;
+ case M_APP1:
+ case M_APP2:
+ case M_APP3:
+ case M_APP4:
+ case M_APP5:
+ case M_APP6:
+ case M_APP7:
+ case M_APP8:
+ case M_APP9:
+ case M_APP10:
+ case M_APP11:
+ case M_APP12:
+ case M_APP13:
+ case M_APP15:
+ /* fall through */
+ default:
+ jai_skip_variable(fp); /* anything else isn't interesting */
+ if (feof(fp)) { result->bad=8; return; }
+ break;
+ } }
+}
+
+static char *jai_errors[]={
+ (char*)NULLP,
+ /*1*/ "missing SOF0 marker",
+ /*2*/ "EOF|EOI before SOS", /* "premature EOF", */
+ /*3*/ "not a Baseline JPEG (SOF must be SOF0)",
+ /*4*/ "more SOF0 markers",
+ /*5*/ "bad # components",
+ /*6*/ "EOF before EOI",
+ /*7*/ "extra bytes after EOI",
+ /*8*/ "EOF before end of parametric marker",
+};
+
+int main(int argc, char **argv) {
+ struct gfxinfo gi;
+ FILE *f=argc>=2 ? fopen(argv[1], "rb"): stdin;
+ jai_handle_jpeg(&gi, f);
+ if (gi.bad==1) {
+ printf("JAI: Warning: %s.\n", jai_errors[gi.bad]);
+ gi.cpp=1;
+ gi.width=0;
+ gi.height=0;
+ gi.SOF_offs=0;
+ gi.bpc=0;
+ } else if (gi.bad!=0) { printf("JAI: %s.\n", jai_errors[gi.bad]); if (gi.bad!=1) return 1; }
+ unsigned char colorspace;
+ if (gi.cpp==1) {
+ colorspace=CS_GRAYSCALE;
+ } else if (gi.cpp==3) {
+ colorspace=CS_YCbCr;
+ if (gi.had_jfif!=0) ;
+ else if (gi.colortransform==0) colorspace=CS_RGB;
+ else if (gi.colortransform==1) ;
+ else if (gi.colortransform!=127) { printf("JAI: unknown ColorTransform: %u\n", (unsigned)gi.colortransform); return 2; }
+ else if (gi.id_rgb!=0) colorspace=CS_RGB;
+ /* Imp: check for id_ycbcr */
+ else printf("JAI: assuming YCbCr color space\n");
+ } else if (gi.cpp==4) {
+ colorspace=CS_CMYK;
+ if (gi.colortransform==0) ;
+ else if (gi.colortransform==2) colorspace=CS_YCCK;
+ else if (gi.colortransform!=127) { printf("JAI: unknown ColorTransform: %u\n", (unsigned)gi.colortransform); return 2; }
+ } else assert(0);
+ fseek(f, 0L, 2); /* EOF */
+ long flen=ftell(f); /* skip extra bytes after EOI */
+ fclose(f);
+ printf("%lu: flen\n", flen);
+ printf("bpc=%u cpp=%u had_jfif=%u colortransform=%u id_rgb=%u colorspace=%u\n",
+ gi.bpc, gi.cpp, gi.had_jfif, gi.colortransform, gi.id_rgb, colorspace);
+ printf("wd=%u ht=%u SOF_offs=%u\n", gi.width, gi.height, gi.SOF_offs);
+ return 0;
+}
+
+/* __EOF__ */
diff --git a/graphics/sam2p/l1lzw.psm b/graphics/sam2p/l1lzw.psm
new file mode 100644
index 0000000000..4825c52336
--- /dev/null
+++ b/graphics/sam2p/l1lzw.psm
@@ -0,0 +1,656 @@
+/* l1lzw.psm
+ * by pts@fazekas.hu at Sun Sep 22 01:23:57 CEST 2002
+ * formerly lzwdecode.psm -- a real, effective implementation of PostScript
+ * LanguageLevel2 and PDF /LZWDecode filters (same as the LZW
+ * compression used in TIFF raster image files), in PostScript Level1
+ * derived from lzwdecode.c by pts@fazekas.hu (at Wed Sep 4 11:11:45 CEST 2002)
+ * by pts@fazekas.hu at Wed Sep 4 11:30:18 CEST 2002
+ * first run at Wed Sep 4 14:18:43 CEST 2002
+ * linux-2.2.8 fine at Wed Sep 4 14:46:05 CEST 2002
+ * rets linux-2.2.8 fine at Wed Sep 4 15:58:24 CEST 2002
+ * works at Wed Sep 4 16:41:29 CEST 2002
+ * linux-2.2.8 58388480 uncompressed:
+ * lzwdecode.c: 17s user time (*1)
+ * lzw_codec.c: 6s user time (*0.353)
+ * lzwdecode.psm: 1080s user time (*63.53)
+ * stack-reorg works at Thu Sep 5 12:31:23 CEST 2002
+ * lzwdecode.psm: 980s user time (*57.65)
+ * lzwdecode.eps works at Thu Sep 5 14:31:23 CEST 2002
+ * last non-` at Sat Sep 21 23:40:03 CEST 2002
+ *
+ * Note that the LZW compression (but not uncompression) is patented by
+ * Unisys (patent number #4,558,302), so use this program at your own legal
+ * risk!
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You 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
+ */
+
+% OK: test with aaaaaaaaaaaa (stack overflow)
+
+#include "psmlib.psm"
+
+#if USE_A85D
+#else
+ #if USE_HEXD
+ #else
+ #define USE_BINARY 1
+ #endif
+#endif
+
+#if USE_NO_BIND
+ #define BIND_DEF def
+#else
+ #define BIND_DEF bind def
+#endif
+
+#if USE_PIN
+/* --- .pin begins */
+
+%<Head>
+%!PS-Adobe-3.0`E
+%%Inflater: pts@fazekas.hu l1lzw.psm
+%%Pages: 1
+`X%%DocumentData: `B
+%%LanguageLevel: 1
+`I%%EndComments
+%%Page: 1 1
+%</Head>
+
+%<Open>
+save`s `R
+%</Open>
+
+% vvv 50
+%<Abbr acount=26 xcount=30>
+begin
+%</Abbr>
+
+%<A x "load def"/> % best to make it first
+%<A E def/> % best to make it second
+% K: .toksubs.
+%<D T .stream./>
+%<D F .stream./>
+
+%<A + add/>
+%<A , and/>
+%<A - sub/>
+%<A . lt/>
+%<A : for/>
+%<A ; getinterval/>
+%<A * gt/>
+%<A = eq/>
+%<A @ loop/>
+%<A A currentfile/>
+%C!
+%D!
+%<A H index/>
+%<A J 4096/>
+%<A L length/>
+%<A O pop/>
+%S!
+%<A X exit/>
+%<A a packedarray/>
+%<A b bitshift/>
+%<A c exch/>
+%d!
+%<A g get/>
+%<A y copy/>
+%<A i ifelse/>
+%<A j if/>
+%<A r read/>
+%<A s string/>
+%<A t put/>
+%<A u dup/>
+% %<A | -1670420001/> -- not needed, long enough
+%<A ~ ne/>
+#if USE_SHORT_NAMES
+%<D e Flzwdecode_init/>
+%<D f Flzwdecode_do/>
+%<D I Fclear/>
+%<D k prefix/>
+%<D l suffix/>
+%<D m stack/>
+%<D n preread/>
+%<D o past/>
+%<D p nentry/>
+%<D q had_eof/>
+%<D v nentrybig/>
+%<D w nentryb/>
+%<D h stackslice/>
+%<D z gcode/>
+%<D B Fmain/>
+#endif
+#if USE_A85D
+%<D d a85_getc/>
+%<D S xS/>
+%<D D xD/>
+%<D C xC/>
+#endif
+#if USE_HEXD
+%<D d .hexd.un/>
+%<A S readhexstring/>
+%<D D .hexd.un/>
+%<D C .hexd./>
+#endif
+#if USE_BINARY
+%<D d .binary.un/>
+#if USE_PALETTE
+%<D S readstring/>
+#endif
+%<D D .binary.un/>
+%<D C .binary.un/>
+#endif
+
+%<TokSubs name=K inlining=0/>
+
+%<Test>
+#if USE_BINARY
+ /F /filter where {pop false}{true} ifelse def
+#else
+ #if USE_A85D
+ {mark currentfile/ASCII85Decode filter/T exch def}stopped
+ #endif
+ #if USE_HEXD
+ {mark currentfile/ASCIIHexDecode filter/T exch def}stopped
+ #endif
+ /F exch def cleartomark
+#endif
+`w `h `b[1 0 0 -1 0 `h]
+#if USE_TRUE
+true
+#else
+F
+#endif
+%</Test>
+
+%<S len=4096>
+4096 string
+%</S>
+
+#if USE_SHORT_NAMES_OLD
+ #define a85_getc d
+ #define Flzwdecode_init e
+ #define Flzwdecode_do f
+ #define Fclear I
+#endif
+
+#if USE_CURRENTFILE
+ #define STDIN currentfile
+#endif
+
+%<True>
+ % Fmain
+ % ^^^ must call it here, because _now_ `currentfile fileposition` is at the real image data
+ % vvv avoid Fmain here because of the substituted constant 4717 (and also size increase!)
+ Flzwdecode_init
+ % !! Imp: less code here, init as a macro
+ /Fmain 4096 string def
+ { Fmain Flzwdecode_do } `i
+ Fmain Flzwdecode_do pop % make sure that mEOD has been read
+ TE_read_eod
+%</True>
+
+%<False>
+#if USE_BINARY
+/F currentfile/LZWDecode filter def
+#else
+/F T/LZWDecode filter def
+#endif
+F `i
+F closefile
+#if !USE_BINARY
+T closefile
+#endif
+%</False>
+
+%<Defs>
+#else
+40 dict begin % LZWDict
+#endif
+
+#if 0
+% (a) () 0 1
+% DumpStack
+% TYPE_STACK(-str -int)
+% ZZZZZZZZZ
+% (a) 3
+% ASSERT_STACK(-str -int,(1))
+% pop pop
+#endif
+
+
+% Defaults: /EarlyChange 1 /UnitLength 8 /LowBitFirst false
+#if !USE_EARLYCHANGE_1
+/EarlyChange 1 def
+#endif
+#if !USE_UNITLENGTH_8
+/UnitLength 8 def
+#endif
+#if !USE_LOWBITFIRST_FALSE
+/LowBitFirst false def
+#endif
+
+/* OK: test with aaaaaaaaaaaa (stack overflow) */
+#define STACKSIZE 4096
+#define STACKSIZE_M1 4095
+
+#if USE_SHORT_NAMES_OLD
+#endif
+
+% Uninitialized const-vars
+/prefix 4096 array def % array[0..4095] of 0..4095
+/suffix 4096 string def
+/stack STACKSIZE string def
+#if USE_CURRENTFILE
+#else
+ /STDIN (%stdin) (r) file def
+ /STDOUT (%stdout) (w) file def % Fmain
+#endif
+#if USE_HEXD
+ /C(.)def
+#endif
+
+% Uninitialized vars
+#if USE_UNITLENGTH_8
+ #define mClear 256
+ #define mEOD 257
+#endif
+#if !USE_NO_NULLDEF
+ /preread null def
+ /past null def
+ /nentry null def
+ /had_eof null def % 0..2
+ #if !USE_UNITLENGTH_8
+ /mEOD null def
+ /mClear null def
+ #endif
+ /nentrybig null def
+ /nentryb null def
+ /gcode null def % Flzwdecode_do
+ /stackslice null def % Flzwdecode_do
+ #if USE_A85D
+ /S null def
+ /D null def
+ /C null def
+ #endif
+#endif
+
+#if USE_PIN
+{
+#endif
+
+#if USE_A85D
+ /a85_getc{ % Simple getchar() of ASCII85Decode filter :-)), formerly /d
+ PSM_A85_GETC
+ }BIND_DEF
+#endif
+
+%** - Fclear -
+/Fclear {
+ #if USE_UNITLENGTH_8
+ /nentry 258 def
+ /nentryb 9 def
+ #if USE_EARLYCHANGE_1
+ /nentrybig 512 def
+ #else
+ /nentrybig 513 EarlyChange sub def
+ #endif
+ #else
+ /nentry 1 UnitLength bitshift 2 add def
+ /nentryb UnitLength 1 add def
+ /nentrybig 1 nentryb bitshift
+ #if !USE_EARLYCHANGE_1
+ 1 EarlyChange sub add
+ #endif
+ def
+ #endif
+ 0 1 nentry 3 sub {
+ % Stack: code(0..255)
+ dup prefix exch dup
+ % Stack: code prefix code code
+ put
+ suffix exch dup put
+ } for
+} BIND_DEF
+
+%** - Flzwdecode_init -
+%** The caller should have modified /EarlyChange, /UnitLength and /LowBitFirst
+/Flzwdecode_init {
+ TE_init
+ /past 8 def
+ /preread 0 def
+ /had_eof 0 def
+ #if !USE_EARLYCHANGE_1
+ ASSERT_TRUE(EarlyChange 0 INT_EQ EarlyChange 1 INT_EQ BOOL_BIN(or,(ora1)), (lsp->EarlyChange==0 || lsp->EarlyChange==1))
+ #endif
+ #if USE_UNITLENGTH_8
+ Fclear
+ #else
+ ASSERT_TRUE(3 UnitLength INT_LE UnitLength 8 INT_LE and, (3<=lsp->UnitLength && lsp->UnitLength<=8))
+ Fclear
+ /mClear 1 UnitLength bitshift def
+ /mEOD 1 UnitLength bitshift 1 add def
+ #endif
+ /stackslice stack 0 0 getinterval def
+ /gcode {} def
+} BIND_DEF
+
+%** <str> Flzwdecode_do <str.pre>
+%** The caller should have called Flzwdecode_init. Flzwdecode_do fills the
+%** entire str.pre unless EOF on input prevents this. str.pre can have any
+%** length. Doesn`t depend of str.pre passed to it on the previous invocation.
+/Flzwdecode_do {
+ ASSERT_TRUE(10 nentry INT_LE,(lsp->nentry>=10))
+ dup % Silently leave on stack
+ stackslice had_eof
+ % Stack: reto rets==reto stackslice had_eof
+ { % W2:WHILE(1)
+ % Stack: len++ stackslice had_eof*
+ dup 0 INT_NE {
+ /had_eof exch def
+ pop
+ /stackslice stack 0 0 getinterval def
+ exit % exit(W2)
+ }if % return(len)
+ ASSERT_STACK(-str -str -str -int,(W2.in))
+ pop
+ % Stack: len++ stackslice
+ % Stack: reto rets stackslice
+ ASSERT_STACK(-str -str -str,(3))
+ /* Flush stack. */
+ 2 copy length exch length ge { % return from the stack (rets.length<=stackslice.length
+ % Stack: reto rets stackslice
+ dup 0 3 index length getinterval
+ % Stack: reto rets stackslice stackslice[0.. rets.length]
+ 2 index copy pop
+ % Stack: reto rets stackslice
+ /stackslice exch 2 index length dup
+ % Stack: reto rets /stackslice stackslice rets.length rets.length
+ 2 index length exch sub
+ % Stack: reto rets /stackslice stackslice rets.length stackslice.length-rets.length
+ getinterval def
+ 0 0 getinterval
+ % Stack: reto rets[0,0]
+ ASSERT_STACK(-str -str,(4))
+ exit % exit(W2)
+ }if
+ % vvv flush the whole stack into rets
+ 2 copy exch
+ copy pop % stackslice -> rets
+ length dup
+ % Stack: reto rets stackslice.length stackslice.length
+ 2 index length exch sub
+ % Stack: reto rets stackslice.length rets.length-stackslice.length
+ getinterval
+ % Stack: reto rets
+ ASSERT_STACK(-str -str,(5))
+ ASSERT_TRUE(dup length 1 exch INT_LE,(len>=1))
+ % Stack: len++
+
+ /* Read next code (0..4095) from input to `code` */
+ nentry nentrybig INT_EQ {
+ /nentryb nentryb 1 add def
+ /nentrybig 1 nentryb bitshift
+ #if !USE_EARLYCHANGE_1
+ 1 EarlyChange sub add
+ #endif
+ def
+ }if
+ ASSERT_TRUE(4 nentryb INT_LE nentryb 12 INT_LE and, (4<=nentryb && nentryb<=12))
+ ASSERT_STACK(-str -str,(6))
+
+ { % W1:WHILE(1)
+ ASSERT_STACK(-str -str,(7))
+ % Stack: len++
+ % assert(had_eof==0); -- cannot check this right here...
+ ASSERT_TRUE(1 past INT_LE past 8 INT_LE and,(1<=past && past<=8))
+ ASSERT_TRUE(1 nentryb INT_LE nentryb 13 INT_LE and,(1<=nentryb && nentryb<=13))
+ #if !USE_LOWBITFIRST_FALSE
+ LowBitFirst {
+ % Dat: this is untested, even the stack
+ /code 0 def
+ 0 1 netryb 1 sub {
+ % Stack: len++ i
+ past 8 INT_EQ {
+ /preread TE_read(def /past 0 def)
+ #if !USE_NO_EOF
+ {
+ TE_read_pop pop
+ /had_eof 2 def exit % exit from inner `for`
+ }ifelse
+ #endif
+ }if
+ preread 1 and 0 INT_NE {
+ 1 exch bitshift code INT_BIN(add,(ora2)) /code exch def
+ }{pop}ifelse
+ % Stack: len++
+ /preread preread -1 bitshift def
+ /past past 1 add def
+ }for
+ had_eof 0 INT_NE {0 had_eof exit}if % exit(W1)
+ code
+ }{ % else: !LowBitFirst
+ #endif
+ past nentryb add
+ % Stack: len++ past*
+ ASSERT_STACK(-str -str -int,(8))
+ dup 7 INT_GT {
+ dup 16 INT_GT {
+ 16 sub
+ preread 8 bitshift
+ % Stack: len++ past* code
+ /preread TE_read(def)
+ #if !USE_NO_EOF
+ {
+ TE_read_pop pop
+ % Stack: len++ past* code
+ pop
+ /past exch def
+ 0 2
+ % Stack: len++ garbage had_eof*
+ exit % exit(W1)
+ }ifelse
+ #endif
+ }{
+ 8 sub
+ 0 % /code
+ }ifelse
+ % Stack: len++ past* code
+ ASSERT_STACK(-str -str -int -int,(9))
+ ASSERT_TRUE(1 index 1 exch INT_LE 2 index 8 INT_LE and,(1<=lsp->past && lsp->past<=8))
+ preread INT_BIN(add,(or1))
+ % Stack: len++ past* code|preread
+ 1 index bitshift
+ % Stack: len++ past* code*==(code|preread)<<past*
+ /preread TE_read(def)
+ #if !USE_NO_EOF
+ {
+ TE_read_pop pop
+ % Stack: len++ past* code
+ pop
+ /past exch def
+ 0 2
+ % Stack: len++ garbage had_eof*
+ exit % exit(W1)
+ }ifelse
+ #endif
+ ASSERT_STACK(-str -str -int -int,(10))
+ }{
+ 0 % /code
+ }ifelse
+ exch
+ % Stack: len++ code past*
+ ASSERT_STACK(-str -str -int -int,(11))
+ preread exch 2 copy
+ % Stack: len++ code preread0 past* preread past*
+ { 255 127 63 31 15 7 3 1 0 } % cAnd
+ exch get and
+ % Stack: len++ code preread0 past* preread&cAnd[past*]
+ /preread exch def % lsp->preread&=(1<<(8-lsp->past))-1; /* do PCLEAR */
+ % Stack: len++ code preread0 past*
+ dup /past exch def
+ 8 sub bitshift INT_BIN(add,(or2))
+ % Stack: len++ code*==code|(preread>>(8-past))
+ ASSERT_STACK(-str -str -int,(12))
+ #if !USE_LOWBITFIRST_FALSE
+ }ifelse % if: /LowBitFirst
+ #endif
+ % Stack: len++ code
+ ASSERT_STACK(-str -str -int,(13))
+
+ dup mClear INT_LT{
+ /* Speed-up: process normal literal data code in `code` */
+ % Stack: len++ code
+ ASSERT_STACK(-str -str -int,(15b))
+ ASSERT_TRUE(dup 1 add mClear INT_LE,(code too high2)) /* /ioerror */
+ ASSERT_TRUE(nentry 4095 INT_LE,(table full2)) /* /ioerror */
+ prefix nentry 2 index put
+ suffix nentry 1 sub 2 index put
+ stack exch STACKSIZE_M1 exch put
+ % Stack: len++
+ ASSERT_STACK(-str -str,(15c))
+ /nentry nentry 1 add def
+ stack STACKSIZE_M1 1 getinterval
+ % Stack: len++ stackslice
+ 0 % /had_eof
+ ASSERT_STACK(-str -str -str -int,(20b))
+ exit % exit(W1)
+ }if
+
+ dup mEOD INT_GT{
+ /* Process normal data code (either literal or above-mEOD) in `code` */
+ % Stack: len++ code
+ ASSERT_STACK(-str -str -int,(15))
+ ASSERT_TRUE(dup 1 add nentry INT_LE,(code too high)) /* /ioerror */
+ ASSERT_TRUE(nentry 4095 INT_LE,(table full)) /* /ioerror */
+ prefix nentry 2 index put
+ % ASSERT_TRUE(0 stacklen INT_EQ,(lsp->stacklen==0))
+ % Stack: len++ code
+ stack exch dup STACKSIZE_M1 exch
+ nentry 1 sub
+ % Stack: len++ stack code STACKSIZE_M1 code nentry-1
+ ASSERT_STACK(-str -str -aryb -int -int -int -int,(16))
+ INT_EQ {
+ % the rightmost char of this entry will be equal to the leftmost
+ % side, as soon as we calculate the leftmost side
+ /gcode { stack STACKSIZE_M1 2 index put /gcode {} def } def
+ }if
+ %{
+ % ASSERT_TRUE(1 index nentry 2 sub INT_LE,(code<lsp->nentry-1))
+ % % /gcode { } def
+ %}ifelse
+ -1 0
+ % Stack: len++ -{...} stack code STACKSIZE-1|STACKSIZE-2 -1 0
+ {
+ % 1 index (code=) print ===
+ % Stack: len -{...} stack code putidx
+ ASSERT_STACK(-str -str -aryb -int -int,(17))
+ exch dup prefix exch get 2 copy
+ % Stack: len -{...} stack putidx code prefix[code] code prefix[code]
+ INT_EQ{pop exit}if % exit from inner for
+ % Stack: len -{...} stack putidx code prefix[code]
+ 4 copy pop suffix exch get
+ % Stack: len -{...} stack putidx code prefix[code] stack putidx suffix[code]
+ put
+ exch pop
+ exch pop
+ % Stack: len -{...} stack prefix[code]
+ }for
+ % Stack: len stack unused_putidx code
+ ASSERT_STACK(-str -str -aryb -int -int,(18))
+ dup suffix exch get
+ % dup (sufcode=) print ===
+ gcode
+ suffix nentry 1 sub 2 index put pop
+ % Stack: len stack unused_putidx suffix[code]
+ 3 copy put pop
+ % Stack: len stack unused_putidx
+ dup STACKSIZE exch sub
+ % Stack: len stack putidx STACKSIZE-putidx
+ ASSERT_STACK(-str -str -aryb -int -int,(19))
+ getinterval
+ ASSERT_TRUE(1 index length 0 INT_NE,(len!=0))
+ /nentry nentry 1 add def
+ % Stack: len++ stackslice
+ 0 % /had_eof
+ ASSERT_STACK(-str -str -str -int,(20))
+ exit % exit(W1)
+ }if
+
+ dup mEOD INT_EQ{
+ % Stack: len++ code==mEOD
+ pop 0 1
+ % Stack: len++ garbage had_eof*
+ ASSERT_STACK(-str -str -int -int,(14))
+ exit % exit(W1)
+ }if
+
+ ASSERT_TRUE(dup mClear INT_EQ,(code==mClear))
+ pop Fclear
+ % Stack: len++
+ ASSERT_STACK(-str -str,(21))
+ }loop % /W1:WHILE(1)
+ % Stack: len++ stackslice|garbage had_eof*
+ ASSERT_TRUE(TYPE_STACK(-str -str -str -int) TYPE_STACK(-str -str -int -int -bool) BOOL_BIN(or,(ora4)),(stack leaving W2))
+ } loop % /W2:WHILE(1)
+ % Stack: len++
+ % Stack: reto rets(buffer-not-read)
+ ASSERT_STACK(-str -str,(22))
+ length 1 index length exch sub
+ % Stack: reto reto.length-rets.length
+ 0 exch getinterval
+ % Stack: reto.pre(return-value)
+} BIND_DEF % Flzwdecode_do
+
+#if USE_PIN
+%/Fmain {
+%} BIND_DEF
+} % close the function defs section
+%</Defs>
+
+%<Data>
+%%BeginData:
+exec
+`S
+%%EndData
+end restore showpage
+%%Trailer
+%%EOF
+%</Data>
+#else
+
+#if !USE_CURRENTFILE
+% --- Main
+
+%** - Fmain -
+/Fmain {
+ /mys 8192 string def
+ Flzwdecode_init
+ { mys Flzwdecode_do
+ % Stack: mys.pre
+ dup length 0 INT_EQ{exit}if
+ STDOUT exch writestring
+ } loop
+ had_eof 1 INT_EQ {
+ { STDIN read {pop}{exit}ifelse }loop
+ }if
+} BIND_DEF
+Fmain
+#endif
+
+end % LZWDict
+#endif
+
+%%EOF
diff --git a/graphics/sam2p/l1zip.psm b/graphics/sam2p/l1zip.psm
new file mode 100644
index 0000000000..0c462a09ee
--- /dev/null
+++ b/graphics/sam2p/l1zip.psm
@@ -0,0 +1,1439 @@
+/*%
+% l1zip.psm -- /FlateDecode image data implementation for /PSL1
+% by pts@fazekas.hu at Sun Sep 22 01:01:00 CEST 2002
+% formerly flatedecode.psm -- please run faltedecode_eps_helper.sh...
+% by pts@fazekas.hu at Fri Sep 20 23:31:36 CEST 2002
+% -- Sat Sep 21 01:11:10 CEST 2002
+% doesn't work -- Sat Sep 21 02:52:36 CEST 2002
+% disallow preread==8, allow preread==0 WORKS -- Sat Sep 21 20:22:07 CEST 2002
+% derived from statecat.psm -- a stateful, faster minimalistic zcat (gzip -cd)
+% implementation, implemented in pure PostScript LanguageLevel1 (Run
+% through cpp (C preprocessor) to get the PostScript file
+% statecat.psm by pts@fazekas.hu
+% originally rcm.c
+% original author: Ron McFarland <rcm@one.net>, 1996
+% formally muzcat.c (at Tue Dec 25 11:07:47 CET 2001)
+% based on statecat.ps.3 by pts@fazekas.hu
+% rewritten, restructured and extended at Tue Dec 25 21:00:33 CET 2001
+% translated to PostScript except fvWork at Tue Dec 25 23:11:31 CET 2001
+% translated to PostScript altogether at Thu Dec 27 01:10:58 CET 2001
+% translation works with `cat random.file.gz random.file.gz'' at Thu Dec 27 14:19:36 CET 2001
+% Thu Dec 27 18:37:03 CET 2001:
+% statecat.ps: 1071960 ms user time (249.293 times slower than gunzip)
+% function inlining at Thu Dec 27 21:51:45 CET 2001
+% shorter keywords at Thu Dec 27 23:52:46 CET 2001
+% at Sat Feb 23 17:05:43 CET 2002:
+% statecat.ps originally: 5388 bytes
+% after eliminate-NULLs trick: 5349 bytes
+% after anti-32768... trick 5229 bytes
+% 5041
+%*/
+/*
+% Imp: more efficient optimize CFG_FMT_ZLIB_ONLY
+% Imp: do `F closefile', `T closefile' in %<True>
+% Not: don't inline TE_read for USE_HEXD (15*5 bytes for ACSO0g is not tolerable)
+% OK : verify a85_getc for really eating EOD (~>) chars
+% OK : find and catalogize `|' and other one-char abbrs
+% OK : shorter operator names (i.e `E' for `def', as in test_vm_eps.eps)
+% OK : shorter var names (such as `preread', `past')
+% Not: make global vars numbered, not named...
+% OK : make constU[]-3 a string, not an array
+% OK : make constW, constP, constL strings, not arrays
+% Imp: inline all except fvMktree (too long), fvFree (recursive) and fvWork (too long)
+% OK : verify, examine StateCatDict (45)
+% OK : find unused vars (such as `moo') in StateCatDict
+% OK : is constM or 1<< faster?? (decided 1<<)
+% OK : anti-`/z 42 eq', ensure `eq' compares numbers (INT_EQ)
+% OK : verify if/ifelse for ENDIF
+% OK : verify direction of `for's
+% OK : eliminate `stopped' context because it catches errors
+% OK : clear stack before `exit'
+% OK : verify `/name' against `name'; grep m@/@
+% OK : verify that `}' is followed by correct if|ifelse|def|bind|stopped|loop|for
+%
+% Typical error: syntax: /^#/
+% Typical error: syntax: m@/ +\w@
+% Typical error: mispelling
+% Typical error: missing `pop' at `dup ... eq{exit}if'
+% Typical error: missing `for|if|...' after '}'
+*/
+
+#include "psmlib.psm"
+
+#if USE_A85D
+#else
+ #if USE_HEXD
+ #else
+ #define USE_BINARY 1
+ #endif
+#endif
+
+#if USE_NO_BIND
+ #define BIND_DEF def
+#else
+ #define BIND_DEF bind def
+#endif
+
+/* --- .pin begins */
+
+%<Head>
+%!PS-Adobe-3.0`E
+%%Inflater: pts@fazekas.hu l1zip.psm
+%%Pages: 1
+`X%%DocumentData: `B
+%%LanguageLevel: 1
+`I%%EndComments
+%%Page: 1 1
+%</Head>
+
+%<Open>
+save`s `R
+%</Open>
+
+/* 88 dict dup /TokDict exch def begin */
+%<Abbr acount=26 xcount=62>
+begin
+%</Abbr>
+
+%<A x "load def"/> % best to make it first
+%<A E def/> % best to make it second
+
+%<A + add/>
+%<A , and/>
+%<A - sub/>
+%<A . lt/>
+%<A : for/>
+%<A ; getinterval/>
+%<A = eq/>
+%<A @ loop/>
+%<A A currentfile/>
+%<A H 32768/> /*!=LZW*/
+%<A J 32767/> /*!=LZW*/
+%<A O pop/>
+%<A X exit/>
+%<A a packedarray/>
+%<A b bitshift/>
+%<A c exch/>
+%<A g get/>
+%<A y copy/>
+%<A i ifelse/>
+%<A j if/>
+%<A t put/>
+%<A u dup/>
+%<A ~ ne/>
+#if 0 /* important in LZW, but not in Flate */
+ %<A * gt/>
+ %<A L length/>
+ %<A r read/>
+ %<A s string/>
+#endif
+#if USE_A85D
+%<D d a85_getc/>
+%<D S xS/>
+%<D D xD/>
+%<D C xC/>
+#endif
+#if USE_HEXD
+%<D d .hexd.un/>
+%<A S readhexstring/>
+%<D D .hexd.un/>
+%<D C .hexd./>
+#endif
+#if USE_BINARY
+%<D d .binary.un/>
+#if USE_PALETTE
+%<A S readstring/>
+#endif
+%<D D .binary.un/>
+%<D C .binary.un/>
+#endif
+
+#if USE_SHORT_NAMES
+% Free for short names: *?\^_`| BFGIKLMNPQRTUVWYZ efhklmnopqrsvwz
+% Numerical comments denote # calls or # accesses
+% : B: TokSubs
+%<D F Bary/> /* F must be overridden with array to avoid early TokSubs */
+% : G
+%<D I fxIgnore8/> % ? + 3
+%<D K Sbuf/>
+%<D L fvFree/> % 5
+%<D M fvMktree/> % 5
+%<D N .N./>
+%<D P preread/>
+%<D Q mQ/> % 6
+%<D R fxRead8/> % 6
+%<D T Gary/> /* T must be overridden with array to avoid early TokSubs */
+%<D U fvFree/> % 5
+%<D V fvMktree/> % 5
+%<D Y fxRead16/> % 7 /* formerly: C */
+%<D W oP/> % 4
+%<D Z .Z./>
+%<D e oO/> % 7
+%<D f .f./>
+%<D h .h./>
+%<D k fxSkip/> % 4
+%<D l constZ19/> % 3
+%<D m mode/>
+%<D n mF/> % 6
+%<D o .o./>
+%<D p .p./>
+%<D q .q./>
+%<D r fvRead/> % 10
+%<D s past/>
+%<D v .v./>
+%<D w tY/> % 6
+%<D z Tvar/>
+/* %<D z fxIgnore8z/> % 3 */ /* not a function anymore */
+%<D * fvWork/> % 1
+%<D _ fxRead8EOF/> % 1
+%<D ? Dvar/>
+%<D | fvMain/>
+#endif
+
+%<TokSubs name=B inlining=0/>
+
+#if USE_CURRENTFILE
+ #define STDIN currentfile
+#endif
+
+%<Test>
+#if USE_DEBUG2
+/FP /fileposition x
+#endif
+
+#if USE_BINARY
+ {mark /F currentfile/FlateDecode filter def}stopped
+#endif
+#if USE_A85D
+ {mark /T currentfile/ASCII85Decode filter def /F T/FlateDecode filter def}stopped
+#endif
+#if USE_HEXD
+ {mark /T currentfile/ASCIIHexDecode filter def /F T/FlateDecode filter def}stopped
+#endif
+/Z exch def cleartomark
+/G{`i}def % image, imagemask or `false 3 colorimage`
+`w `h `b[1 0 0 -1 0 `h]
+#if USE_TRUE
+true
+#else
+Z
+#endif
+%</Test>
+
+%<S len=32768>
+32768 string dup /Sbuf exch def
+%</S>
+
+%<True>
+ fvMain
+%</True>
+
+%<False>
+F G
+F closefile
+#if !USE_BINARY
+T closefile
+#endif
+%</False>
+
+#define ZZZ_ASET(aname,idx,b) aname idx b put
+#define ZZZ_AREF(aname,idx) aname idx get
+#define PASS
+#define GLOBAL_VAR0(t,name)
+#define SLOCAL_VAR0(t,name)
+#define GLOBAL_VAR(t,name) /name null def
+#define SLOCAL_VAR(t,name) /name null def
+#define GLOBAL_ARRAY(t,name,size) /name size t def
+#define LOCAL_VAR(a,b)
+
+#if 0 /* LINE_DEBUG */
+#define put (put:__LINE__) === put
+#define get (get:__LINE__) === get
+#endif
+
+%<Defs>
+% Imp: F closefile, T closefile
+/* We must define constants and global arrays first. */
+
+#define NULL 0
+#define NODESIZE 1998 /* NODESIZE%3==0 */
+/** Binary (Huffman) tree of nodes. */
+GLOBAL_ARRAY(array,N,NODESIZE)
+/**
+ * Contains the code word lengths used for Huffman code generation in
+ * fvMktree(). 320==288+32. 320 is large enough to hold both the code lengths
+ * of the literal--length (288) and the distance (32) Huffman trees -- and
+ * large enough to hold the auxilary Huffman tree (used for building the
+ * real tree) of length 19.
+ */
+GLOBAL_ARRAY(array,Z,320)
+GLOBAL_ARRAY(array,Bary,17)
+GLOBAL_ARRAY(array,Gary,17)
+#if CFG_NO_VAR_S
+#else
+GLOBAL_ARRAY(string,Sbuf,32768)
+#endif
+/constZ19 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 19 packedarray def
+#if USE_HEXD
+ /C(.)def
+#endif
+
+{ /* We start declaring functions inside the brace */
+
+#define constW { 16 17 18 0 8 7 9 6 10 5 11 4 12 3 13 2 14 1 15 } /* 19 packedarray def */
+#define constU { 3 4 5 6 7 8 9 10 11 13 15 17 19 23 27 31 35 43 51 59 67 83 99 115 131 163 195 227 258 } /* 29 packedarray def */
+#define constP { 0 0 0 0 0 0 0 0 1 1 1 1 2 2 2 2 3 3 3 3 4 4 4 4 5 5 5 5 0 } /* 29 packedarray def */
+#define constQ { 1 2 3 4 5 7 9 13 17 25 33 49 65 97 129 193 257 385 513 769 1025 1537 2049 3073 4097 6145 8193 12289 16385 24577 } /* 30 packedarray def */
+#define constL { 0 0 0 0 1 1 2 2 3 3 4 4 5 5 6 6 7 7 8 8 9 9 10 10 11 11 12 12 13 13 } /* 30 packedarray def */
+#if 0
+#define constM { 0 1 3 7 15 31 63 127 255 511 1023 2047 4095 8191 } /* 14 packedarray def */
+#endif
+
+#if USE_A85D
+ GLOBAL_VAR0(SINT32,xS) /* Variable `xS' was formerly called: `sx' */
+ GLOBAL_VAR0(SINT32,xD) /* Variable `xD' was formerly called: `dx' */
+ GLOBAL_VAR0(SINT32,xC) /* Variable `xC' was formerly called: `c0' */
+ /** - a85_getc <0..255|511>
+ * Reads a char from `currentfile' as /ASCII85Decode
+ */
+ /a85_getc{ % Simple getchar() of ASCII85Decode filter :-)), formerly /d
+ PSM_A85_GETC
+ }BIND_DEF
+#endif
+
+#if USE_NO_EOF
+ #define my_getchar() TE_read( )
+ #define my_ignorechar() TE_read(pop)
+#else
+ #define my_getchar() TE_read() {511}ifelse
+ #define my_ignorechar() TE_read(pop) if
+#endif
+
+
+/** Index of the first free node in <code>N</code>. */
+GLOBAL_VAR0(WORD,Dvar)
+
+GLOBAL_VAR0(WORD,Tvar) /* index (in S) of the first free position, [0..32767] */
+
+/* GLOBAL_VAR(NODEN,no) -- unused */
+/* GLOBAL_VAR(WORD,roo) -- unused */
+/* GLOBAL_VAR(WORD,rf) -- unused */
+/* GLOBAL_VAR(WORD,moo) -- unused */
+/* GLOBAL_VAR(WORD,mo) -- unused */
+/* GLOBAL_VAR(WORD,oooo) -- unused */
+/* GLOBAL_VAR(WORD,x) -- unused */
+GLOBAL_VAR0(WORD,mQ)
+GLOBAL_VAR0(WORD,mF)
+GLOBAL_VAR0(WORD,o)
+GLOBAL_VAR0(WORD,q)
+GLOBAL_VAR0(WORD,mode) /* MODE_* */
+GLOBAL_VAR0(WORD,tY) /* FMT_*; formerly ty */
+GLOBAL_VAR0(WORD,oO)
+GLOBAL_VAR0(WORD,oP)
+GLOBAL_VAR0(WORD,f)
+GLOBAL_VAR0(WORD,p)
+GLOBAL_VAR0(WORD,v)
+GLOBAL_VAR0(WORD,h)
+
+
+#define AREF_S(idx) AREF(Sbuf,idx)
+#define ASET_S(idx,val) ASET(Sbuf,idx,val)
+
+/* Reading Operations:
+
+-- fxRead8(): read a 8-bit byte at byte boundary
+-- fxRead16z(): read a 16-bit word at byte boundary, MSB first (ZIP)
+-- fxRead16(): read a 16-bit word at byte boundary, LSB first (normal)
+-- fxSkip(): skip to next byte boundary
+-- fxRead1(): read 1 bit (for Huffman)
+-- fvRead(): read any amount of bits (0..13), LSB first
+*/
+
+/* Dat: FlateDecode bit packing order is: (b7*128+...+b0)+(b15*128+...+b8)
+
+/** char, 0..255 */
+SLOCAL_VAR0(WORD,preread)
+/** -1..-8: bits of bufread[pos] already read */
+SLOCAL_VAR0(WORD,past)
+
+% static void fxInit(void) {
+% /fxInit {
+#define fxInit \
+ /preread 0 def \
+ /past -8 def
+% }BIND_DEF
+
+/* #define ASSERT_PREREAD_NOT_EOF() preread 255 gt ASSERT_FALSE_POP((unexpected eof)) */
+#define ASSERT_NOT_EOF(val) ASSERT_TRUE(val dup 255 and eq,(non-EOF expected))
+#define ASSERT_PREREAD_NOT_EOF() ASSERT_NOT_EOF(preread)
+
+/** reads 0..13 bits */
+% static WORD fvRead(WORD arg) {
+/fvRead {
+ DEBUG(dup (==> fvRead\() exch 42 string cvs concatstrings (\)\n) concatstrings)
+ DEBUG(( past=) past neg 42 string cvs concatstrings
+ ( preread=) preread 42 string cvs concatstrings
+ (\n) concatstrings concatstrings)
+ dup 0 INT_NE{
+ ASSERT_PREREAD_NOT_EOF()
+ past
+ % Stack: arg -opast
+ dup preread exch bitshift exch % SHR
+ % Stack: arg preread>>opast opast
+ dup 3 index sub
+ % Stack: arg ret==:preread>>-opast -opast -past==:-opast-arg
+ dup -8 ge{
+ /past exch def % BUG fixed at Thu Dec 27 14:53:53 CET 2001
+ pop
+ % Stack: arg ret
+ }{
+ ASSERT_TRUE(dup -9 le,(-past>=9))
+ /preread my_getchar() def
+ ASSERT_PREREAD_NOT_EOF()
+ dup -16 ge{ /* _GT_ */
+ 8 add /past exch def
+ 8 add
+ % Stack: arg ret==:preread>>opast 8-opast
+ preread exch bitshift % SHL
+ add
+ % Stack: arg ret''
+ }{
+ 16 add /past exch def
+ 8 add 2 copy
+ % Stack: arg retold 8-opast ret 8-opast
+ preread exch bitshift add % SHL
+ % Stack: arg retold 8-opast ret''
+ /preread my_getchar() def % BUG fixed at Thu Dec 27 15:40:53 CET 2001
+ ASSERT_TRUE(past -1 le,(-past>=1))
+ ASSERT_TRUE(past -4 ge,(-past<=4))
+ ASSERT_PREREAD_NOT_EOF()
+ exch 8 add preread exch bitshift add
+ % Stack: arg retold ret''
+ exch pop
+ % Stack: arg ret''
+ }ifelse
+ }ifelse
+ % Stack: arg ret
+ % exch constM exch get and % ret&=((1<<arg)-1);
+ % ^^^ BUG (re)-fixed at Thu Dec 27 14:50:49 CET 2001
+ exch 1 exch bitshift 1 sub and
+ }if
+ DEBUG(dup (<-- fvRead=) exch 42 string cvs concatstrings (\n) concatstrings)
+ % (%stderr) (w) file (<fvRead\n) writestring
+ % fvRead(0)==0 implicitly assumed
+}BIND_DEF
+
+% static WORD fxRead1(void) {
+% /fxRead1{
+#define fxRead1 \
+ ASSERT_PREREAD_NOT_EOF() \
+ past dup -8 INT_EQ{ \
+ pop \
+ /preread my_getchar() def \
+ /past -1 def \
+ preread 1 and \
+ /* Stack: ret */ \
+ }{ \
+ dup 1 sub /past exch def \
+ preread exch bitshift 1 and \
+ /* Stack: ret */ \
+ }ifelse
+% }BIND_DEF
+
+#if 0 /* old style past==0, inline only speed-critical functions */
+ % static void fxSkip(void) {
+ % /fxSkip{
+ #define fxSkip \
+ past 0 INT_NE{ \
+ ASSERT_PREREAD_NOT_EOF() \
+ /preread my_getchar() def \
+ /past 0 def \
+ }if
+ % }BIND_DEF
+
+ % static WORD fxRead16(void) {
+ % /fxRead16{
+ #define fxRead16 \
+ ASSERT_TRUE(past 0 INT_EQ,(past==0)) \
+ ASSERT_PREREAD_NOT_EOF() \
+ preread \
+ /* Stack: ret */ \
+ my_getchar() dup /preread exch def \
+ ASSERT_PREREAD_NOT_EOF() \
+ 8 bitshift \
+ add \
+ /preread my_getchar() def
+ % }BIND_DEF
+
+ % static WORD fxRead8(void) {
+ % /fxRead8{
+ #define fxRead8 \
+ ASSERT_TRUE(past 0 INT_EQ,(past==0)) \
+ ASSERT_PREREAD_NOT_EOF() \
+ preread \
+ /* Stack: ret */ \
+ /preread my_getchar() def
+ % }BIND_DEF
+
+ % static void fxIgnore8(WORD how_many_bytes) {
+ #define fxIgnore8 \
+ ASSERT_TRUE(dup 0 gt,(fxIgnore8arg>0)) \
+ ASSERT_TRUE(past 0 INT_EQ,(past==0)) \
+ ASSERT_PREREAD_NOT_EOF() \
+ -1 2 {pop my_ignorechar()}for \
+ /preread my_getchar() def
+
+ #define fxIgnore8z \
+ ASSERT_TRUE(past 0 INT_EQ,(past==0)) \
+ ASSERT_PREREAD_NOT_EOF() \
+ dup 0 INT_NE{ \
+ -1 2 {pop DEBUG2((fI8z)===) my_ignorechar()}for \
+ /preread my_getchar() def \
+ }{pop}ifelse
+
+ % static WORD fxRead8EOF(void) {
+ % /fxRead8EOF{
+ #define fxRead8EOF \
+ ASSERT_TRUE(past 0 INT_EQ,(past==0)) \
+ preread \
+ /* Stack: ret */ \
+ /preread my_getchar() def
+ % }BIND_DEF
+#else
+ #if 0
+ /* old-style: past==0 */
+ % static void fxSkip(void) {
+ /fxSkip{
+ past 0 INT_NE{
+ ASSERT_PREREAD_NOT_EOF()
+ /preread my_getchar() def
+ /past 0 def
+ }if
+ }BIND_DEF
+ % static WORD fxRead8(void) {
+ /fxRead8{
+ ASSERT_TRUE(past 0 INT_EQ,(past==0))
+ ASSERT_PREREAD_NOT_EOF()
+ preread
+ /* Stack: ret */
+ /preread my_getchar() def
+ }BIND_DEF
+ /fxIgnore8z{
+ % Same as void fxIgnore8(WORD how_many_bytes), but allow 0 as arg
+ ASSERT_TRUE(past 0 INT_EQ,(past==0))
+ ASSERT_PREREAD_NOT_EOF()
+ dup 0 INT_NE{
+ -1 2 {pop DEBUG2((fI8z)===) my_ignorechar()}for
+ /preread my_getchar() def
+ }{pop}ifelse
+ }BIND_DEF
+ /fxRead8EOF{
+ ASSERT_TRUE(past 0 INT_EQ,(past==0))
+ preread
+ /* Stack: ret */
+ /preread my_getchar() def
+ }BIND_DEF
+ #else
+ #define fxSkip /past -8 def
+ #define fxRead8 \
+ ASSERT_TRUE(past -8 INT_EQ,(past==-8)) \
+ my_getchar() ASSERT_NOT_EOF(dup)
+ % }BIND_DEF
+ #define fxRead8EOF \
+ ASSERT_TRUE(past -8 INT_EQ,(past==-8)) \
+ my_getchar()
+ % }BIND_DEF
+ #endif
+
+ % static WORD fxRead16(void) {
+ /fxRead16{
+ ASSERT_TRUE(past -8 INT_EQ,(past==-8))
+ my_getchar() ASSERT_NOT_EOF(dup)
+ my_getchar() ASSERT_NOT_EOF(dup)
+ 8 bitshift add
+ }BIND_DEF
+
+ % static void fxIgnore8(WORD how_many_bytes) {
+ /fxIgnore8{
+ ASSERT_TRUE(dup 0 gt,(fxIgnore8arg>0))
+ ASSERT_TRUE(past -8 INT_EQ,(past==-8))
+ ASSERT_PREREAD_NOT_EOF()
+ {my_getchar() ASSERT_NOT_EOF(dup) pop }repeat
+ }BIND_DEF
+ #define fxIgnore8z fxIgnore8
+#endif
+
+#define fvReadq fvRead
+/** Reads an uint16 from the ZIP file */
+#define fxRead16z fxRead16
+
+/**
+ * Allocates a new node and initializes it with empty content. This function
+ * lets us get rid of the global variable F (which was buggily uninitialized
+ * in the original scm.c).
+ * @return pointer to the newly allocated node
+ * @whichcode -1
+ */
+% DEFUN_0(NODEN,fvNalloc)
+% /fvNalloc{
+#define fvNalloc \
+ /* GLOBAL_REF(N) */ \
+ /* GLOBAL_REF(Dvar) */ \
+ /* LOCAL_VAR(NODEN,no) */ /* the first/next free node */ \
+ /* FUNCODE */ \
+ Dvar \
+ /* Stack: no */ \
+ ASSERT_TRUE(dup NODESIZE lt,(Dvar<NODESIZE)) \
+ dup N exch get /Dvar exch def /* SET(Dvar,AREF(N,no)); % not free anymore */ \
+ dup N exch NULL put /* ASET(N,no,NULL); */ /* clear; the other two fields are already cleared */ \
+ /* Stack: no */
+% }BIND_DEF
+
+/**
+ * Frees the Huffman tree originating from <code>root</code> recursively.
+ * Used <code>I</code> as input only.
+ * Moved <code>I</code> into a argeter.
+ * @param arg root node index in N
+ */
+% DEFUN_1_VOID(fvFree,NODEN)
+/fvFree{
+ % GLOBAL_REF(N)
+ % GLOBAL_REF(Dvar)
+ N exch dup NULL INT_NE{
+ 2 copy get fvFree
+ 2 copy 1 add get fvFree % fvFree(AREF(N,arg+1));
+ 2 copy 1 add NULL put % ASET(N,arg+1,NULL); /* clear */
+ 2 copy 2 add 0 put % ASET(N,arg+2,0); /* clear */
+ 2 copy Dvar put % ASET(N,arg,Dvar); /* link to the beginning of the free list */
+ /Dvar exch def pop % SET(Dvar,arg); /* set it free */
+ }{
+ % BUG fixed at Thu Dec 27 11:52:59 CET 2001
+ pop pop
+ }ifelse
+}BIND_DEF
+
+/**
+ * Goes down (descends) enough levels in the binary tree of (struct node)s.
+ * Reads numbers from input encoded as a Huffman tree represented by the
+ * (struct node)s.
+ * Called only from 2 places.
+ * Used <code>I</code> as both input and output, but the output is never used
+ * in the program. So I've put <code>I</code> to a argument.
+ * @param arg root is only for input
+ * @whichcode 3
+ */
+% DEFUN_1(WORD,fvDescend,NODEN)
+% /fvDescend{
+#define fvDescend \
+ /* GLOBAL_REF(N) */ \
+ /* FUNCODE */ \
+ DEBUG(dup (==> fvDescend\() exch 42 string cvs concatstrings (\)\n) concatstrings) \
+ N exch \
+ { /* Stack: N arg */ \
+ 2 copy get NULL INT_EQ{exit}if /* WHILE(NE(NULL,AREF(N,arg))) */ \
+ 2 copy fxRead1 add get exch pop /* SET(arg,AREF(N,arg+fxRead1())); */ \
+ }loop /* ENDWHILE */ \
+ /* Stack: N arg */ \
+ 2 add get \
+ DEBUG(dup (<-- fvDescend=) exch 42 string cvs concatstrings (\n) concatstrings) \
+ /* RETURN(fvDescend,AREF(N,arg+2)) */ /* arg->value; */
+% }BIND_DEF
+
+/**
+ * Allocates new (struct node)s. This is the Huffman tree
+ * builder. It reads the global array <code>Z</code>: the code lengths have
+ * been already stored there.
+ * Used <code>I</code> as output only, so I moved it to the return value.
+ * @param arg the number of entries (codes) of the Huffman tree to be built
+ * @return the root of the Huffman tree just built
+ * @whichcode 5
+ */
+% DEFUN_1(NODEN,fvMktree,WORD)
+/fvMktree{ % BUG fixed at Thu Dec 27 11:54:02 CET 2001
+ % GLOBAL_REF(B)
+ % GLOBAL_REF(G)
+ % GLOBAL_REF(N)
+ % GLOBAL_REF(Z)
+ % LOCAL_VAR(WORD,moo)
+ % LOCAL_VAR(WORD,mQ)
+ % LOCAL_VAR(WORD,mo)
+ % LOCAL_VAR(WORD,mF)
+ % FUNCODE
+ constZ19 0 17 getinterval Bary copy pop % OK to copy packedarray -> array
+ % Stack: arg
+ Bary Z 0 1 4 index 1 sub
+ % Stack: arg Bary Z 0 1 arg-1
+ { % Stack: arg Bary Z moo
+ 3 copy get
+ % Stack: arg Bary Z moo Bary Z[moo]
+ 2 copy get 1 add put
+ % Stack: arg Bary Z moo
+ pop
+ }for % WHILE(LT(moo,arg)) INCR(AREF(Bary,AREF(Z,moo))); INCR(moo); ENDWHILE
+ % Stack: arg Bary Z
+ pop 0 0 put % ASET(Bary,0,0);
+ Gary 0 0 put % ASET(Gary,0,0);
+ % Stack: arg
+ Gary Bary 0 1 15 % SET(moo,0); WHILE(LT(moo,16))
+ { % Stack: arg Gary Bary moo
+ 2 copy get
+ % Stack: arg Gary Bary moo Bary[moo]
+ 3 index 2 index get
+ % Stack: arg Gary Bary moo Bary[moo] Gary[moo]
+ add dup add % BUG fixed at Thu Dec 27 15:05:51 CET 2001
+ % Stack: arg Gary Bary moo 2*(Bary[moo]+Gary[moo])
+ 3 index exch 2 index 1 add exch
+ % Stack: arg Gary Bary moo Gary moo+1 2*(Bary[moo]+Gary[moo])
+ % ASET(Gary, moo+1,TWICE(AREF(Gary,moo)+AREF(Bary,moo)));
+ put pop
+ }for % BUG fixed at Thu Dec 27 14:59:52 CET 2001
+ % Stack: arg Gary Bary
+ pop pop
+ /* Dat: anode is the ->left pointer of the Sentinel node */
+ N 3 0 put % ASET(N,3,NULL); /* anode=NULL; */
+ % Stack: arg
+ 1 sub 0 exch 1 exch{ % SET(moo,0); WHILE(LT(moo,arg))
+ % Stack: moo
+ dup Z exch get dup 0 INT_NE{ % IF(NZ(AREF(Z,moo)))
+ % Stack: moo Z[moo]
+ % /* WORD o, f; */ /* struct node **f; */
+ dup Gary exch get /mQ exch def % SET(mQ,AREF(Gary,AREF(Z,moo)));
+ % Stack: moo Z[moo]
+ dup Gary exch 2 copy
+ % Stack: moo Z[moo] Gary Z[moo] Gary Z[moo]
+ get 1 add put % INCR(AREF(Gary,AREF(Z,moo)));
+ % Stack: moo Z[moo]
+ /mF 3 def % SET(mF,3); /* mF=&anode; */ % BUG fixed at Thu Dec 27 12:03:31 CET 2001
+ % SET(mo,AREF(Z,moo));
+ 1 sub -1 0
+ % Stack: moo Z[moo]-1 -1 0
+ { % WHILE(NZ(mo)); DECR(mo);
+ % Stack: moo mo
+ N mF get NULL INT_EQ{
+ N mF fvNalloc put
+ }if % IF(EQ(AREF(N,mF),NULL)); ASET(N,mF,fvNalloc NOARGS); ENDIF
+ 1 exch bitshift mQ and 0 INT_EQ{0}{1}ifelse
+ N mF get add
+ /mF exch def % SET(mF,AREF(N,mF)+TAND_P(mQ,SHL(1,mo)));
+ % Stack: moo
+ }for
+ N exch
+ % Stack: N moo
+ N mF 2 copy fvNalloc put % ASET(N,mF,fvNalloc NOARGS);
+ get 2 add
+ % Stack: N moo AREF(N,mF)+2
+ exch put % ASET(N,AREF(N,mF)+2,moo); /* (*f)->value=moo; */
+ % Stack: -
+ }{pop pop}ifelse % ENDIF
+ }for
+ % Stack: -
+ N 3 get
+}BIND_DEF
+
+
+#define FMT_ZLIB 120
+#define FMT_STOP 4 /* stop processing and flush STDIN */
+#if CFG_FMT_ZLIB_ONLYX
+#else
+#define FMT_ZIP_STORED 0 /* file is stored, not Deflated in ZIP file */
+#define FMT_GZIP 31
+#define FMT_NONE 3
+#define FMT_ZIP_DEFLATED 8
+#endif
+
+#define MODE_BOS 0 /* at beginning of (sub)file */
+#define MODE_MOB 1 /* at middle of a DEFLATE block */
+#define MODE_REP 2 /* printing a repeating string in a DEFLATE block */
+#define MODE_BOB 3 /* at the beginning of a block, just before BFINAL and BTYPE */
+#define MODE_COPY1 4 /* copying from input to output (a stored block) */
+#if CFG_FMT_ZLIB_ONLYX
+#else
+#define MODE_ZSTO 5 /* copying from input to output (FMT_ZIP_STORED) */
+#endif
+
+/**
+ * Root of the literal--length Huffman tree in <code>N</code>
+ * (see RFC 1951). Its length is at most 288 with values 0..287. Values
+ * 286 and 287 are invalid. A value in 0..255 means a literal byte, a
+ * value of 256 indicates end-of-block, and a
+ * value in 257..285 is a prefix (with 29 possible values) of a length
+ * in 3..258. See subsubsection 3.2.5 of RFC 1951.
+ */
+SLOCAL_VAR0(NODEN,v)
+/**
+ * Root of the distance Huffman tree in <code>N</code> (see RFC 1951).
+ * Its length is at most 32 with values 0..31. Values 30 and 31 are invalid.
+ * A value of 0..29 is a prefix (with 30 possible values) of a distance in
+ * 1..32768. See subsubsection 3.2.5 of RFC 1951.
+ */
+SLOCAL_VAR0(NODEN,h)
+
+
+#define SLIDEE dup 32767 INT_EQ{pop 0}{1 add}ifelse
+
+#if CFG_FMT_ZLIB_ONLY
+#define fvAFB \
+ DEBUG2((f0:__LINE__) ===only) DEBUG2(currentfile FP ===) \
+ /mode MODE_BOS def \
+ /tY FMT_STOP def /* force EOF */ \
+ fxSkip \
+ DEBUG2((f1:__LINE__) ===only) DEBUG2(currentfile FP ===) \
+ 4 fxIgnore8z \
+ DEBUG2((f2:__LINE__) ===only) DEBUG2(currentfile FP ===)
+#else
+% static void fvAFB(void) {
+% /fvAFB{ /* after final block (BFINAL) */
+#define fvAFB \
+ \
+ /mode MODE_BOS def /* SET(mode,MODE_BOS); */ \
+ fxSkip /* fxSkip(); */ \
+ /* ^^^ skip till we reach byte boundary. fvRead! 0..7 bits */ \
+ tY FMT_GZIP INT_EQ{ /* IF(EQ(tY,FMT_GZIP)) */ \
+ /* CRC32 and ISIZE remaining */ \
+ /* vvv IGNORE fxRead16(); IGNORE fxRead16(); IGNORE fxRead16(); IGNORE fxRead16(); */ \
+ 8 \
+ }{ \
+ tY FMT_ZLIB INT_EQ{ /* ELSE_IF(EQ(tY,FMT_ZLIB)) */ \
+ /* ADLER32 remaining */ \
+ 4 \
+ }{0}ifelse \
+ }ifelse \
+ fxIgnore8z
+% }BIND_DEF
+#endif /* CFG_FMT_ZLIB_ONLY */
+
+/** Reads data from input, uncompresses and saves it to Sbuf. Sbuf.length==32768.
+ * Saves 32768 bytes into Sbuf unless EOF prevents it. After return, the caller
+ * may read Sbuf, but it may not modify it.
+ * @return length to be saved to Sbuf
+ */
+% static WORD fvWork(void) {
+/fvWork{
+ % GLOBAL_REF(J)
+ % GLOBAL_REF(Y)
+ % GLOBAL_REF(Tvar)
+ % GLOBAL_REF(N)
+ % GLOBAL_REF(Dvar)
+ { % `{'': establish fake loop context for return
+ mode MODE_REP INT_EQ{ % IF(EQ(mode,MODE_REP))
+ ASSERT_TRUE(Tvar 0 INT_EQ,(Tvar==0))
+ ASSERT_TRUE(f 258 le,(f<=258))
+ % /* f==0 is OK now */
+ Tvar oO
+ 1 1 f{ % WHILE(NZ(f)) -- inverse for
+ pop
+ % Stack: Tvar oO
+ Sbuf 3 copy exch get
+ % Stack: Tvar oO Sbuf Tvar S[oO]
+ put % ASET_S(Tvar,AREF_S(oO));
+ SLIDEE % SLIDE(oO);
+ exch 1 add exch % INCR(Tvar);
+ % DECR(f);
+ }for % ENDWHILE
+ pop /Tvar exch def
+ /mode MODE_MOB def
+ }{
+ mode MODE_COPY1 INT_EQ{ % ELSE_IF(EQ(mode,MODE_COPY1))
+ % /* Now: f: copy count unsinged word16 */
+ ASSERT_TRUE(Tvar 0 INT_EQ,(Tvar==0))
+ % /* f==0 is OK now */
+ f 32767 gt{ /* _GT_ */ % IF((unsigned short)f>=32768)
+ ASSERT_TRUE(f 32768 sub f 32767 and eq,((f&32767)==f-32768))
+ /f f 32767 and def
+ 0 1 32767{ % WHILE(NE((unsigned short)Tvar,32768))
+ Sbuf exch fxRead8 put % ASET_S(Tvar,fxRead8());
+ % INCR(T);
+ % DECR(f);
+ }for % ENDWHILE
+ /Tvar 0 def % SET(Tvar,0);
+ % Stack: -
+ ASSERT_TRUE(mode MODE_COPY INT_EQ,(mode==MODE_COPY1))
+ % bbb111
+ 32768 exit % return (WORD)32768; outside loops
+ }{ % ELSE
+ Sbuf Tvar 1 1 f{ % WHILE(NZ(f)) -- inverse for
+ pop
+ % Stack: Sbuf Tvar
+ 2 copy fxRead8 put % ASET_S(Tvar,fxRead8());
+ 1 add % INCR(Tvar);
+ }for % ENDWHILE
+ /Tvar exch def pop
+ % /mode MODE_BOB def % SET(mode,MODE_BOB); % BUG fixed at Thu Dec 27 14:16:57 CET 2001
+ o 0 INT_NE{ % IF(NZ(o))
+ fvAFB % goto on_bos; SET(mode,MODE_BOS);
+ }{ % ELSE
+ /mode MODE_BOB def % SET(mode,MODE_BOB); % beginning of next block
+ }ifelse % ENDIF
+ }ifelse % ENDIF
+ }
+#if CFG_FMT_ZLIB_ONLY
+ if
+#else
+ {mode MODE_ZSTO INT_EQ{ % ELSE_IF(EQ(mode,MODE_ZSTO))
+ % /* Now: f: copy count low unsinged word16, oP: high unsigned word16 */
+ % /* Now: oo: 0..1 flag for decrementing oP */
+ ASSERT_TRUE(Tvar 0 INT_EQ,(Tvar==0))
+ % /* f==0 is OK now */
+ f 32767 gt{ /* _GT_ */ % IF((unsigned short)f>=32768)
+ ASSERT_TRUE(f 32768 sub f 32767 and eq,((f&32767)==f-32768))
+ /f f 32767 and def
+ 0 1 32767{ % WHILE(NE((unsigned short)Tvar,32768))
+ Sbuf exch fxRead8 put % ASET_S(Tvar,fxRead8());
+ % INCR(Tvar);
+ % DECR(f);
+ }for % ENDWHILE
+ /Tvar 0 def % SET(Tvar,0);
+ % Stack: -
+ ASSERT_TRUE(mode MODE_ZSTO INT_EQ,(mode==MODE_ZSTO))
+ % bbb222
+ 32768 exit % return (WORD)32768; outside loops
+ }{
+ oP 0 INT_NE{ % ELSE_IF(NZ(oP))
+ 0 1 32767{ % WHILE(NE((unsigned short)Tvar,32768))
+ Sbuf exch fxRead8 put % ASET_S(Tvar,fxRead8());
+ % INCR(Tvar);
+ % DECR(f);
+ }for % ENDWHILE
+ /Tvar 0 def % SET(Tvar,0);
+ % Stack: -
+ oO 0 INT_NE{ % IF(NZ(oO))
+ /oP oP 1 sub def % DECR(oP);
+ /oO 0 def % SET(oO,0);
+ }{ % ELSE
+ /oO 1 def % SET(oO,1);
+ }ifelse
+ ASSERT_TRUE(mode MODE_ZSTO INT_EQ,(mode==MODE_ZSTO))
+ % bbb333
+ 32768 exit % return (WORD)32768; outside loops
+ }{ % ELSE
+ Sbuf Tvar 1 1 f{ % WHILE(NZ(f)) -- inverse for
+ pop
+ % Stack: Sbuf Tvar
+ 2 copy fxRead8 put % ASET_S(Tvar,fxRead8());
+ 1 add % INCR(Tvar);
+ }for % ENDWHILE
+ /Tvar exch def pop
+ /mode MODE_BOS def % SET(mode,MODE_BOS);
+ }ifelse % oO!=0
+ }ifelse % f>=32768
+ }if % MODE==MODE_ZSTO
+ }ifelse % MODE==MODE_COPY1
+#endif /* CFG_FMT_ZLIB_ONLY */
+ }ifelse % MODE==MODE_REP
+ -1 exit % don''t return yet
+ }loop
+ % Stack: retval||-1
+
+ { % big-big MODE_MOB||MODE_BOB||MODE_BOS loop
+ #ifndef NDEBUG
+ % mode ===only ( big-big\n) print
+ #endif
+ ASSERT_TRUE(mode MODE_MOB INT_EQ mode MODE_BOB INT_EQ mode MODE_BOS INT_EQ or or,(MODE_MOB||MODE_BOB||MODE_BOS))
+
+ % Stack: retval||-1
+ dup -1 INT_NE{%ccc999
+ exit}if
+ mode MODE_MOB INT_EQ{ % IF(EQ(mode,MODE_MOB)); mode_mob:
+ ASSERT_TRUE(dup -1 INT_EQ,(was -1))
+ pop % -1
+ /**
+ * Uncompresses the data block with the Huffman codes set up.
+ *
+ * Reads at most 33 bits per entry. Unfortunately the block can be of
+ * arbitrary length (terminated by an entry of 256).
+ */
+ % /* vvv reads 0..15 bits, see subsubsection 3.2.7 of RFC 1951 */
+ {
+ % Dat: most of the time is spent inside fvDescend, fvRead and
+ % inside this loop
+ v fvDescend dup 256 INT_EQ{pop -1 exit}if % WHILE(NE(oo, 256))
+ dup 257 lt{ % IF(LT(oO,257))
+ % /* ^^^ BUG corrected */
+ Sbuf exch Tvar exch put % ASET_S(Tvar,oO);
+
+ % Stack: -
+ % vvv SLIDE(Tvar); /* Tvar++; Tvar&=32767; */
+ % vvv if (Tvar==0) return (WORD)32768; /* remain in MODE_MOB */
+ Tvar 32767 INT_EQ{
+ /Tvar 0 def
+ % bbb444
+ 32768 exit % return % in big-big-loop and MOB-loop
+ }if
+ /Tvar Tvar 1 add def
+ }{ % ELSE
+ 257 sub % SUB(oO,257);
+ % Stack: oO
+ dup constU exch get
+ exch constP exch get fvRead
+ add /f exch def % SET(f,AREF(constU,oO) + fvRead(AREF(constP,oO))); /* fvRead! 0..5 bits */
+ ASSERT_TRUE(3 f le f 258 le and,(3<=f && f<=258))
+ h fvDescend % SET(oO,fvDescend(h));
+ dup constQ exch get
+ exch constL exch get fvRead
+ add % SET(oO,AREF(constQ,oO) + fvRead(AREF(constL,oO))); /* fvRead! 0..13 bits */
+ Tvar exch sub 32767 and % /* oO = oO <= Tvar ? Tvar - oO : 32768 - oO + Tvar; */
+
+ f 32768 Tvar sub sub dup 0 lt{ % IF((unsigned short)f<32768-(unsigned short)Tvar)
+ pop
+ % Stack: oO
+ Tvar exch 1 1 f{ % WHILE(NZ(f)) -- inverse for
+ pop
+ % Stack: Tvar oO
+ Sbuf 3 copy exch get
+ % Stack: Tvar oO Sbuf Tvar S[oO]
+ put % ASET_S(Tvar,AREF_S(oO));
+ SLIDEE % SLIDE(oO);
+ exch 1 add exch % INCR(Tvar);
+ % DECR(f);
+ }for % ENDWHILE
+ % Dat: oO doesn''t have to be remembered here
+ pop /Tvar exch def
+ % Stack: -
+ ASSERT_TRUE(Tvar 32768 lt,(Tvar<32768))
+ }{ % ELSE
+ /f exch def % SUB(f,32768-Tvar);
+ % Stack: oO
+ Tvar 1 32767{ % WHILE(NE((unsigned short)Tvar,32768))
+ % Stack: oO Tvar
+ exch
+ % Stack: Tvar oO
+ Sbuf 3 copy exch get
+ % Stack: Tvar oO Sbuf Tvar S[oO]
+ put % ASET_S(Tvar,AREF_S(oO));
+ SLIDEE % SLIDE(oO);
+ exch pop % INCR(Tvar);
+ }for % ENDWHILE
+ /oO exch def
+ % Stack: -
+ /Tvar 0 def % SET(Tvar,0);
+ /mode MODE_REP def % SET(mode,MODE_REP);
+ % bbb555
+ 32768 exit % return (WORD)32768; % in big-big-loop and MOB-loop
+ }ifelse % ENDIF
+ }ifelse % ENDIF
+ }loop % ENDWHILE
+ % Stack: retval||-1
+ dup -1 INT_EQ{ % BUG fixed at Thu Dec 27 15:52:18 CET 2001
+ v fvFree % fvFree(v);
+ h fvFree % fvFree(h);
+ o 0 INT_NE{ % IF(NZ(o))
+ fvAFB % goto on_bos; SET(mode,MODE_BOS);
+ }{ % ELSE
+ /mode MODE_BOB def % SET(mode,MODE_BOB); % beginning of next block
+ }ifelse % ENDIF
+ }if
+ }if % ENDIF
+ % Stack: retval||-1
+ dup -1 INT_NE{%ccc888
+ exit}if pop
+
+ DEBUG2((;)===)
+
+ mode MODE_BOB INT_EQ{ % WHILE(EQ(mode,MODE_BOB)); mode_bob:
+ DEBUG(counttomark 42 string cvs)
+ DEBUG(( kope\n))
+ % assert(mode==MODE_BOB);
+ /o fxRead1 def % SET(o,fxRead1()); /* BFINAL: 1 iff this is the last data block */
+ /q 2 fvRead def % SET(q,fvRead(2)); /* BTYPE: block type; 0=stored, 1=fixed Huff, 2=dyn Huff */
+ % #if NDEBUG
+ % #else
+ % fprintf(stderr, "MODE_BOB o=%d q=%d %ld\n", o, q, ftell(stdin));
+ % #endif
+ DEBUG((MODE:BOB o=) o 42 string cvs
+ ( q=) q 42 string cvs
+ ( ) Stdin fileposition 42 string cvs
+ (\n) concatstrings concatstrings concatstrings
+ concatstrings concatstrings concatstrings)
+ ASSERT_TRUE(q 0 INT_EQ q 1 INT_EQ q 2 INT_EQ or or,(q==0 || q==1 || q==2))
+ q 0 INT_NE{ % IF(NZ(q))
+ /**
+ * Now: q==BTYPE, q==1 or q==2. (BTYPE==3 means error). Handles
+ * compressed data blocks, see subsubsection 3.2.5 of RFC 1951.
+ */
+ q 1 INT_EQ{ % IF(EQ(q,1))
+ /**
+ * Initializes the fixed Huffman codes for BTYPE==1.
+ */
+ % /* WORD oO; */
+ 287 -1 0{ % SET(oO,288); WHILE(NZ(oO)); DECR(oO);
+ Z exch dup 144 lt{8}{dup 256 lt{9}
+ {dup 280 lt{7}{8}ifelse}ifelse}ifelse put
+ /* ^^^ AREF(Z,oO) = oO < 144 ? 8
+ : oO < 256 ? 9
+ : oO < 280 ? 7
+ : 8; */
+ }for % ENDWHILE
+ /v 288 fvMktree def % SET(v,fvMktree(288));
+ 0 1 31{Z exch 5 put}for % SET(f,0); WHILE(LT(f,32)) ASET(Z,f,5); INCR(f); ENDWHILE
+ /h 32 fvMktree def % SET(h,fvMktree(32));
+ }{ % ELSE
+ /**
+ * Reads dynamic Huffman codes for BTYPE==2.
+ *
+ * Maximum read: 5+5+4+3*19+7*289 == 2094 bits
+ */
+ ASSERT_TRUE(q 2 INT_EQ,(q==2))
+ % /* WORD oO, oP, oPo, f, p, x, v; */
+ /p 5 fvRead 257 add def % SET(p, fvRead(5) + 257); /* HLIT: 257..286 (287--289 are unused) */
+ /oO 5 fvRead 1 add def % SET(oO, fvRead(5) + 1); /* HDIST: 1..32 */
+ /v 4 fvRead 4 add def % SET(v, fvRead(4) + 4); /* HCLEN: 4..19 */ /* small v */
+ constZ19 Z copy pop % WHILE(LT(oO,19)) ASET(Z,AREF(constW,oO), 0); INCR(oO); ENDWHILE
+ 0 1 v 1 sub{
+ Z exch constW exch get 3 fvRead put % WHILE(LT(oO,v)) ASET(Z,AREF(constW,oO), fvRead(3)); INCR(oO); ENDWHILE /* small v */
+ }for
+ % Stack: - (verified)
+ /v 19 fvMktree def % SET(v,fvMktree(19));
+ /oP 0 def % SET(oP,0);
+ % Stack: -
+ Z 0 { % SET(oO,0); WHILE(LT(oO,p + oO))
+ % Stack: Z oO
+ dup p oO add ge{exit}if
+ v fvDescend % SET(oPo,fvDescend(v));
+ % Stack: Z oO oPo
+ dup 16 INT_EQ{
+ pop oP /f 2 fvRead 3 add def % SET(oPo,oP); SET(f,3+fvRead(2));
+ }{
+ dup 17 INT_EQ{
+ pop 0 /f 3 fvRead 3 add def % SET(oPo,0); SET(f,3+fvRead(3));
+ }{
+ dup 18 INT_EQ{
+ pop 0 /f 7 fvRead 11 add def % SET(oPo,0); SET(f,11+fvRead(7));
+ }{
+ dup /oP exch def /f 1 def % SET(oP,oPo); SET(f,1);
+ }ifelse
+ }ifelse
+ }ifelse
+ % Stack: Z oO oPo
+ 1 1 f{ % SET(q,f); WHILE(NZ(q))
+ pop % BUG fixed at Thu Dec 27 12:17:58 CET 2001
+ 3 copy put % ASET(Z,oO,oPo);
+ exch 1 add exch % INCR(oO);
+ % DECR(q);
+ }for % ENDWHILE
+ pop % oPo, BUG fixed at Thu Dec 27 12:18:47 CET 2001
+ }loop % ENDWHILE
+ % Stack: Z oO''==p+oO
+ pop pop
+ v fvFree % fvFree(v);
+ /v p fvMktree def % SET(v,fvMktree(p));
+ % Stack: -
+ % /* vvv No need for array copy, just change/pass the pointer to Z... */
+ oO 1 sub -1 0{ % SET(oO'',oO); WHILE(NZ(oO'')) DECR(oO'');
+ Z exch dup
+ % Stack: Z oO'' oO''
+ p add Z exch get put % ASET(Z,oO'',AREF(Z,oO'' + p));
+ }for % ENDWHILE
+ /h oO fvMktree def % SET(h,fvMktree(x));
+ }ifelse % ENDIF
+ /mode MODE_MOB def % SET(mode,MODE_MOB);
+ % goto mode_mob;
+ }{ % ELSE /* inline: fv(..., 7); */
+
+ /**
+ * Copies a block of input to output (mostly) verbatim. This is for
+ * BTYPE==0, non-compressed block, subsubsection 3.2.4 of RFC 1951.
+ * (We need non-compressed because
+ * some blocks cannot be compressed effectively, so gzip inserts them
+ * as is.)
+ * @whichcode 7
+ */
+ fxSkip % fxSkip();
+ % /* ^^^ skip till we reach byte boundary. fvRead! 0..7 bits */
+ /f fxRead16 def % SET(f,fxRead16()); /* length of block: 0..65535 */
+ % #if NDEBUG
+ % #else
+ % fprintf(stderr, "COPY1_BLK=%d Tvar=%d\n", f, Tvar);
+ % #endif
+ 2 fxIgnore8 % IGNORE fxRead16(); /* one's complement of length; ignored */
+
+ f 32768 Tvar sub sub dup 0 lt{ % IF((unsigned short)f<32768-(unsigned short)Tvar)
+ pop
+ Sbuf Tvar 1 1 f{ % WHILE(NZ(f)) -- inverse for
+ pop
+ % Stack: Sbuf Tvar
+ 2 copy fxRead8 put % ASET_S(Tvar,fxRead8());
+ 1 add % INCR(Tvar);
+ }for % ENDWHILE
+ /Tvar exch def pop
+ ASSERT_TRUE(mode MODE_BOB INT_EQ,(mode==MODE_BOB))
+ ASSERT_TRUE(Tvar 32768 lt,(Tvar<32768))
+ }{ % ELSE
+ % /* Even if f>=32768 */
+ /f exch def % SUB(f,32768-Tvar);
+ Tvar 1 32767{ % WHILE(NE((unsigned short)Tvar,32768))
+ Sbuf exch fxRead8 put % ASET_S(Tvar,fxRead8());
+ % INCR(Tvar);
+ % DECR(f);
+ }for % ENDWHILE
+ /Tvar 0 def % SET(Tvar,0);
+ /mode MODE_COPY1 def % SET(mode,MODE_REP);
+ % bbb666
+ DEBUG(counttomark 42 string cvs)
+ DEBUG(( whata\n))
+ % trtr
+ ASSERT_TRUE(counttomark 0 eq,(seccounttomark==0))
+ DEBUG((whatb\n))
+ 32768 exit % return (WORD)32768; % exit from big-big loop
+ }ifelse % ENDIF
+ o 0 INT_NE{fvAFB}if % IF(NZ(o)); fvAFB(); ENDIF
+ DEBUG( counttomark 42 string cvs)
+ DEBUG((pikula\n))
+ }ifelse % ENDIF
+ }if % ENDWHILE /* MODE_BOB */
+ % Stack: -
+
+ mode MODE_BOS INT_EQ{
+ DEBUG(counttomark 42 string cvs)
+ DEBUG(( booski\n))
+ DEBUG2((boost)===only)
+ DEBUG2(currentfile FP ===)
+ {
+ DEBUG(counttomark 42 string cvs)
+ DEBUG(( boosbe\n))
+ tY FMT_STOP INT_EQ{ % WHILE(NE(tY,FMT_STOP))
+ Tvar 0 INT_NE{ % /* Flush unwritten buffer. */
+ Tvar% BUG fixed at Thu Dec 27 14:05:32 CET 2001
+ /Tvar 0 def
+ % Stack: Tvar_old
+ }{0}ifelse
+ % ccc777
+ exit % return % in big-big loop and BOS-loop
+ }if
+ % /* SET(oO,0); SET(oP,0); */ /* avoid GCC warnings */
+ % /* fxInit(); */ /* assert(Y==0); SET(J,0); SET(Y,0); */
+ /v NULL def /h NULL def % SET(v,NULL); SET(h,NULL);
+ % N 0 NULL put N 1 NULL put N 2 0 put % ASET(N,0,NULL); ASET(N,1,NULL); ASET(N,2,0); /* the NULL node is initially empty */
+ % N 3 NULL put N 4 NULL put N 5 0 put % ASET(N,3,NULL); ASET(N,4,NULL); ASET(N,5,0); /* the Sentinel node is initially empty */
+ constZ19 N copy pop % eliminate-NULLs trick: overwrites 1st >=6 elements of N
+ /Dvar 6 def % SET(Dvar,6); /* first free node is 6. `0' is NULL, `3' is Sentinel */
+ 6{ % SET(o,Dvar);
+ dup NODESIZE ge{pop exit}if % WHILE (LT(o,NODESIZE))
+ dup N exch dup 3 add put 1 add % ASET(N,o,o+3); INCR(o); /* next free node is next node */
+ dup N exch NULL put 1 add % ASET(N,o,NULL); INCR(o); /* empty RIGHT */
+ dup N exch 0 put 1 add % ASET(N,o,0); INCR(o); /* empty NVAL */
+ }loop % ENDWHILE
+ % Stack: -
+ fxRead8EOF dup /tY exch def % SET(tY,fxRead8EOF()); /* read first byte of the header */
+ % tY kkkkkkkkkk
+ dup 511 INT_EQ{ % IF(EQ(tY,511)) /* EOF */
+ /tY FMT_STOP def % SET(tY,FMT_STOP);
+ }{
+#if CFG_FMT_ZLIB_ONLY
+ 1 fxIgnore8 % IGNORE fxRead8(); /* skip second header byte: 0x01 or 0x5e or 0x9c or 0xda */
+#else
+ dup FMT_ZLIB INT_EQ{ % ELSE_IF(EQ(tY,120)) /* ZLIB format */
+ 1 fxIgnore8 % IGNORE fxRead8(); /* skip second header byte: 0x01 or 0x5e or 0x9c or 0xda */
+ % /* SET(tY,FMT_ZLIB); */
+ }{
+ dup 80 INT_EQ{ % ELSE_IF(EQ(tY,80)) /* ZIP format */
+ 1 fxIgnore8 % IGNORE fxRead8(); /* skip second header byte: 0x48 */
+ /tY FMT_NONE def % SET(tY,FMT_NONE);
+ fxRead8 % SET(o,fxRead8());
+ dup 3 INT_EQ{ % IF(EQ(o,3)) /* Local file header */
+ % fxRead8 pop % IGNORE fxRead8(); /* skip: 0x04 */
+ % fxRead16 pop % IGNORE fxRead16(); /* skip: version needed to extract file (0x0020) */
+ % fxRead16 pop % IGNORE fxRead16(); /* LOCFLG flags */
+ 5 fxIgnore8
+ /tY fxRead8 def % SET(tY,fxRead8()); /* lower half of compression method */
+ ASSERT_TRUE(tY FMT_ZIP_STORED INT_EQ tY FMT_ZIP_DEFLATED INT_EQ or,(ty==FMT_ZIP_STORED || ty==FMT_ZIP_DEFLATED))
+ % ^^^ BUG fixed at Thu Dec 27 20:55:52 CET 2001
+ % fxRead8 pop % IGNORE fxRead8(); /* upper half of compression method */
+ % fxRead16 pop fxRead16 pop % IGNORE fxRead16(); IGNORE fxRead16(); /* file modification time in MS-DOS format */
+ % fxRead16 pop fxRead16 pop % IGNORE fxRead16(); IGNORE fxRead16(); /* some kind of CRC-32 */
+ 9 fxIgnore8
+ /f fxRead16z def % SET(f, fxRead16z()); /* lower compressed file size */
+ /oP fxRead16z def % SET(oP,fxRead16z()); /* higher compressed file size */
+ 4 fxIgnore8 % fxRead16 pop fxRead16 pop % IGNORE fxRead16(); IGNORE fxRead16(); /* uncompressed file size */
+ fxRead16z % SET(oO,fxRead16z()); /* length of filename */
+ fxRead16z add % SET(q,fxRead16z()); /* length of extra field */
+ % WHILE(NZ(oO)) IGNORE fxRead8(); DECR(oO); ENDWHILE /* file name */
+ % WHILE(NZ(q)) IGNORE fxRead8(); DECR(q); ENDWHILE /* extra field */
+ % -1 1{fxRead8 pop}for
+ fxIgnore8z
+ }{
+ dup 7 INT_EQ{ % ELSE_IF(EQ(o,7)) /* Extended local header of previous file in ZIP */
+ % 1 1 13{fxRead8 pop}for % SET(o,0); WHILE(LT(o,13)) IGNORE fxRead8(); INCR(o); ENDWHILE /* BUGFIX: was 15 */
+ 13 fxIgnore8
+ }{
+ dup 5 INT_EQ{ % ELSE_IF(EQ(o,5)) /* End of Central Directory Structure in ZIP */
+ /* fprintf(stderr,"EOCDS\n"); */
+ % 1 1 17{fxRead8 pop}for % SET(o,0); WHILE(LT(o,17)) IGNORE fxRead8(); INCR(o); ENDWHILE
+ 17 fxIgnore8
+ fxRead16z % SET(o,fxRead16z()); /* CML: archive comment length */
+ % -1 1{fxRead8 pop}for % WHILE (NZ(o)) IGNORE fxRead8(); DECR(o); ENDWHILE
+ fxIgnore8z
+ }{
+ dup 1 INT_EQ{ % ELSE_IF(EQ(o,1)) /* Central Directory Structure */
+ /* fprintf(stderr,"CDS\n"); */
+ % 1 1 25{fxRead8 pop}for % SET(oO,0); WHILE(LT(oO,25)) IGNORE fxRead8(); INCR(oO); ENDWHILE
+ 25 fxIgnore8
+ fxRead16z % SET(f,fxRead16z()); /* LEN: length of file name */
+ fxRead16z add % SET(o,fxRead16z()); /* XLN: length of extra field */
+ fxRead16z add % SET(q,fxRead16z()); /* CML: length of file comment */
+ % fxRead16 pop fxRead16 pop fxRead16 pop
+ % fxRead16 pop fxRead16 pop fxRead16 pop
+ % ^^^ SET(oO,0); WHILE(LT(oO,12)) IGNORE fxRead8(); INCR(oO); ENDWHILE
+ 12 fxIgnore8
+ fxIgnore8z
+ % ^^^ WHILE(NZ(f)) IGNORE fxRead8(); DECR(f); ENDWHILE /* file name */
+ % WHILE(NZ(o)) IGNORE fxRead8(); DECR(o); ENDWHILE /* extra field */
+ % WHILE(NZ(q)) IGNORE fxRead8(); DECR(q); ENDWHILE /* file comment */
+ }if % o==1
+ }ifelse % o==5
+ }ifelse % o==7
+ }ifelse % o==3 % ENDIF /* IF ZIP structure sub-type */
+ % Stack: tY_old o
+ pop
+ }{
+ dup 31 INT_EQ{ % ELSE_IF(EQ(tY,31)) /* gzip/RFC 1952 format */
+ /* fprintf(stderr,"gzip!\n"); */
+ /* SET(tY,FMT_GZIP); */
+ /* The most simple gzip header (10 bytes):
+ * ID1 hex 0x1f == dec 31 == FMT_GZIP
+ * ID2 hex 0x8b
+ * CM hex 0x08
+ * FLG hex 0x00
+ * MTIME hex 0x00, 0x00, 0x00, 0x00 (1 Jan 1970, UNIX epoch)
+ * XFL hex 0x00
+ * OS hex 0xff
+ * After that comes the compressed data stream.
+ * After that comes the CRC32 and ISIZE (byte aligned? ?)
+ */
+ 2 fxIgnore8 % fxRead16 pop % IGNORE fxRead16(); /* ignore ID2 and CM */
+ % kkkkkkkkkl
+ fxRead8 % SET(o,fxRead8()); /* FLG */
+ % fxRead16 pop fxRead16 pop % IGNORE fxRead16(); IGNORE fxRead16(); /* ignore MTIME */
+ % fxRead16 pop % IGNORE fxRead16(); /* ignore XFL, OS */
+ 6 fxIgnore8
+ % Stack: o==FLG
+ dup 2 and 0 INT_NE{ % IF(TAND_P(o,2)) /* GCONT: skip part number of continuation */
+ %fxRead16 pop % IGNORE fxRead16();
+ 2 fxIgnore8
+ }if % ENDIF
+ dup 4 and 0 INT_NE{ % IF(TAND_P(o,4)) /* ignore FEXTRA */
+ fxRead16 fxIgnore8
+ % 1 1 fxRead16{fxRead8 pop}for
+ % SET(q,fxRead16());
+ % WHILE(NZ(q)) IGNORE fxRead8(); DECR(q); ENDWHILE
+ }if % ENDIF
+ dup 8 and 0 INT_NE{ % IF(TAND_P(o,8))
+ {fxRead8 0 INT_EQ{exit}if}loop % WHILE(NZ(fxRead8())); PASS; ENDWHILE
+ }if % ENDIF /* ignore FNAME */
+ dup 17 and 0 INT_NE{ % IF(TAND_P(o,16))
+ {fxRead8 0 INT_EQ{exit}if}loop % WHILE(NZ(fxRead8())); PASS; ENDWHILE
+ }if % ENDIF /* ignore FCOMMENT */
+ dup 32 and 0 INT_NE{ % IF(TAND_P(o,32)) /* skip encryption header */
+ % fxRead16 pop fxRead16 pop fxRead16 pop
+ % fxRead16 pop fxRead16 pop fxRead16 pop
+ % SET(f,0); WHILE(LT(f,12)) IGNORE fxRead8(); INCR(f); ENDWHILE
+ 12 fxIgnore8
+ }if % ENDIF
+ % Stack: tY o
+ pop
+ }if % tY==31 (gzip/RFC 1952 format)
+ }ifelse % tY==80 (ZIP format)
+ }ifelse % tY==FMT_ZLIB
+#endif /* CFG_FMT_ZLIB_ONLY */
+ }ifelse % tY==511 % ENDIF /* IF file format */
+ % Stack: tY_old
+ pop
+ % /* fprintf(stderr,"tY=%d\n", tY); */
+ % tY bbbbbc
+#if CFG_FMT_ZLIB_ONLYX
+ /* FMT_ZIP_STORED can become alive somehow... */
+ tY FMT_STOP INT_NE tY 3 INT_NE and{
+ /mode MODE_BOB def % SET(mode,MODE_BOB);
+ -1 exit % goto mode_bob;
+ }if
+#else
+ tY FMT_ZIP_STORED INT_EQ{ % IF(EQ(tY,FMT_ZIP_STORED))
+ % /* fprintf(stderr,"ZIP_STORED oO=%d oP=%d\n", oO, oP); */
+ /oO 0 def % SET(oO,0);
+ f 32768 Tvar sub sub dup 0 lt{ % IF((unsigned short)f<32768-(unsigned short)Tvar)
+ pop
+ Sbuf Tvar 1 1 f{ % WHILE(NZ(f)) -- inverse for
+ pop
+ % Stack: Sbuf Tvar
+ 2 copy fxRead8 put % ASET_S(Tvar,fxRead8());
+ 1 add % INCR(Tvar);
+ }for % ENDWHILE
+ /Tvar exch def pop
+ ASSERT_TRUE(Tvar 32768 lt,(Tvar<32768))
+ oP 0 INT_NE{
+ /mode MODE_ZSTO def
+ % ccc555
+ Tvar exit % in big-big loop and BOS-loop
+ }if
+ % ^^^ IF(NZ(oP)); mode=MODE_ZSTO; return Tvar; ENDIF
+ ASSERT_TRUE(mode MODE_BOS INT_EQ,(mode==MODE_BOS))
+ }{ % ELSE
+ % /* Even if f>=32768 */
+ /f exch def % SUB(f,32768-Tvar);
+ Tvar 1 32767{ % WHILE(NE((unsigned short)Tvar,32768))
+ Sbuf exch fxRead8 put % ASET_S(Tvar,fxRead8());
+ % INCR(Tvar);
+ % DECR(f);
+ }for % ENDWHILE
+ /Tvar 0 def % SET(Tvar,0);
+ /mode MODE_ZSTO def % SET(mode,MODE_REP);
+ % bbb777
+ 32768 exit % return (WORD)32768; % in big-big loop and BOS-loop
+ }ifelse % ENDIF
+ }{
+ tY FMT_STOP INT_NE tY FMT_NONE INT_NE and{
+ /mode MODE_BOB def % SET(mode,MODE_BOB);
+ -1 exit % goto mode_bob;
+ }if
+ }ifelse % ENDIF
+#endif /* CFG_FMT_ZLIB_ONLY */
+ }loop % ENDWHILE /* outermost WHILE(NE(tY,FMT_STOP)) */
+ % Stack: retval
+ }{-1}ifelse % mode==MODE_BOS
+ % Stack: retval
+ }loop % big-big MODE_MOB||MODE_BOB||MODE_BOS loop
+ % Stack: retval
+}BIND_DEF % ENDFUN
+
+% Stdin already set
+#if 0
+% /fvInitAll{
+#define fvInitAll \
+ fxInit \
+ /tY FMT_NONE def \
+ /mode MODE_BOS def \
+ /Tvar 0 def /* make the round buffer empty */ \
+ TE_init
+% }BIND_DEF
+#else
+/fvMain{
+ % /XXX
+ % STDIN read
+ % STDIN C readhexstring
+ % pop 0 get true_action
+ % TE_read(===)
+
+ TE_init % must be called _before_ fxInit
+ fxInit
+ /tY FMT_NONE def
+ /mode MODE_BOS def
+ /Tvar 0 def
+ % /Tvar 0 def Tvar === quit
+ { Sbuf 0 fvWork getinterval } /G load exec
+ TE_read_eod % make sure that mEOD has been read
+}BIND_DEF
+#endif
+
+} /* We close the brace of declared functions */
+%</Defs>
+
+%<Data>
+%%BeginData:
+exec
+`S
+%%EndData
+end restore showpage
+%%Trailer
+%%EOF
+%</Data>
+
+%%EOF
diff --git a/graphics/sam2p/main.hpp b/graphics/sam2p/main.hpp
new file mode 100644
index 0000000000..fdb47f306f
--- /dev/null
+++ b/graphics/sam2p/main.hpp
@@ -0,0 +1,20 @@
+/* main.hpp -- provide functions for the GUI
+ * by pts@fazekas.hu at 2002.12.28
+ */
+
+#ifdef __GNUC__
+#ifndef __clang__
+#pragma interface
+#endif
+#endif
+
+#ifndef MAIN_HPP
+#define MAIN_HPP 1
+
+#include "gensi.hpp"
+
+extern void init_applier();
+extern void init_loader();
+extern void init_sam2p_engine(char const*argv0);
+
+#endif
diff --git a/graphics/sam2p/mapping.cpp b/graphics/sam2p/mapping.cpp
new file mode 100644
index 0000000000..4c3844ec77
--- /dev/null
+++ b/graphics/sam2p/mapping.cpp
@@ -0,0 +1,309 @@
+/*
+ * mapping.cpp -- associative array implementations
+ * by pts@fazekas.hu at Fri Mar 15 21:13:47 CET 2002
+ */
+
+#ifdef __GNUC__
+#ifndef __clang__
+#pragma implementation
+#endif
+#endif
+
+#include "mapping.hpp"
+#include "error.hpp"
+#include <string.h>
+#include <stdlib.h> /* abort() */
+
+/* --- */
+
+bool Mapping::Gen::update(char const*key, slen_t keylen, char const*data) {
+ char *found_data=get(key, keylen);
+ if (found_data==NULLP) return true;
+ memcpy(found_data, data, datalen);
+ return false;
+}
+
+/* --- */
+
+bool Mapping::DoubleHash::obj_assert() {
+ assert(len <= used);
+ assert(minlen <= len);
+ assert(used <= maxused);
+ assert(maxused < alloced);
+ assert(alloced < (slen_t)-2);
+ /* Imp: re-count used and len */
+ return true;
+}
+
+bool Mapping::DoubleHash::set (char const* key, slen_t keylen, char const*data) {
+ assert(obj_assert());
+ slen_t h1=vi_h1(key,keylen);
+ assert(h1<alloced);
+ Ary *p=ary+h1;
+ if (p->keylen==NEVER_USED) { added:
+ /* Dat: we shouldn't stop on p->keylen==DELETED */
+ /* This will be deleted by `delete [] (pp->keydata-datalen);' called from
+ * Mapping::DoubleHash::clear() called from the destructor of
+ * Mapping::DoubleHash15, also known as Mapping::H.
+ */
+ memcpy(p->keydata=new char[keylen+datalen], data, datalen);
+ memcpy(p->keydata+=datalen, key, p->keylen=keylen); len++;
+ //if (p->keylen==NEVER_USED && used++==maxused) { p->keylen=keylen; rehash(); }
+ // else { p->keylen=keylen; }
+ if (used++==maxused) rehash();
+ assert(obj_assert());
+ return true; /* new value added */
+ }
+ if (p->keylen==keylen && 0==memcmp(p->keydata, key, keylen)) { updated:
+ memcpy(p->keydata-datalen, data, datalen);
+ return false; /* value updated */
+ }
+ /* Not found for the 1st try. We have to walk. */
+ slen_t h2=vi_h2(key,keylen);
+ assert(1<=h2 && h1<alloced);
+ while (1) { /* Dat: maxlen < alloced, so this can safely be an infinite loop. */
+ if (h1>=h2) { h1-=h2; p-=h2; }
+ else { h1+=alloced-h2; p+=alloced-h2; }
+ if (p->keylen==NEVER_USED) goto added;
+ if (p->keylen==keylen && 0==memcmp(p->keydata, key, keylen)) goto updated;
+ }
+}
+char*Mapping::DoubleHash::get (char const* key, slen_t keylen) {
+ assert(obj_assert());
+ slen_t h1=vi_h1(key,keylen);
+ assert(h1<alloced);
+ Ary *p=ary+h1;
+ if (p->keylen==NEVER_USED) return (char*)NULLP;
+ if (p->keylen==keylen && 0==memcmp(p->keydata, key, keylen)) return p->keydata-datalen;
+ /* Not found for the 1st try. We have to walk. */
+ slen_t h2=vi_h2(key,keylen);
+ assert(1<=h2 && h1<alloced);
+ /* Dat: assert(lnko(...)) better in vi_h2 */
+ while (1) { /* Dat: maxlen < alloced, so this can safely be an infinite loop. */
+ if (h1>=h2) { h1-=h2; p-=h2; }
+ else { h1+=alloced-h2; p+=alloced-h2; }
+ if (p->keylen==NEVER_USED) return (char*)NULLP;
+ if (p->keylen==keylen && 0==memcmp(p->keydata, key, keylen)) return p->keydata-datalen;
+ }
+}
+bool Mapping::DoubleHash::deletee (char const* key, slen_t keylen) {
+ /* We must not set `p->keylen=NEVER_USED' in this method because this would
+ * ruin searches jumping on `p', but not coming from `p+h2'. So we just set
+ * `p->keylen=DELETED'.
+ */
+ assert(obj_assert());
+ slen_t h1=vi_h1(key,keylen);
+ assert(h1<alloced);
+ Ary *p=ary+h1;
+ if (p->keylen==NEVER_USED) return true; /* key to be deleted does not exist */
+ if (p->keylen==keylen && 0==memcmp(p->keydata, key, keylen)) { found:
+ vi_dtor(p->keydata-datalen);
+ delete [] (p->keydata-datalen);
+ p->keylen=(slen_t)DELETED;
+ // p->keydata=(char*)NULLP;
+ if (len--==minlen) rehash();
+ assert(obj_assert());
+ return false; /* key-value pair deleted */
+ }
+ /* Not found for the 1st try. We have to walk. */
+ slen_t h2=vi_h2(key,keylen);
+ assert(1<=h2 && h1<alloced);
+ while (1) { /* Dat: maxlen < alloced, so this can safely be an infinite loop. */
+ if (h1>=h2) { h1-=h2; p-=h2; }
+ else { h1+=alloced-h2; p+=alloced-h2; }
+ if (p->keylen==(slen_t)NEVER_USED) return true; /* key to be deleted does not exist */
+ if (p->keylen==keylen && 0==memcmp(p->keydata, key, keylen)) goto found;
+ }
+}
+void Mapping::DoubleHash::getFirst(char const*const*& key, slen_t &keylen, char *& data) {
+ assert(obj_assert());
+ Ary *p=ary, *pend=p+alloced;
+ while (p!=pend && p->keylen>=(slen_t)-2) p++;
+ if (p==pend) { key=(char const*const*)NULLP; }
+ else { key=&p->keydata; data=p->keydata-datalen; keylen=p->keylen; }
+}
+void Mapping::DoubleHash::getNext (char const*const*& key, slen_t &keylen, char *& data) {
+ assert(obj_assert());
+ /* vvv Dat: this operation is safe despite of the fact that it increases
+ * signedness off pointer target type ((char*) -> (Ary*)).
+ */
+ Ary *p=PTS_align_cast(Ary*,
+ ( (char*)const_cast<char**>(key)
+ - ((char*)&((Ary*)0)->keydata-(char*)0) )), *pend=ary+alloced;
+ p++;
+ while (p!=pend && p->keylen>=(slen_t)-2) p++;
+ if (p==pend) { key=(char const*const*)NULLP; }
+ else { key=&p->keydata; data=p->keydata-datalen; keylen=p->keylen; }
+}
+void Mapping::DoubleHash::rehash() {
+ unsigned old_scale=scale;
+ slen_t old_alloced=alloced;
+#ifndef NDEBUG
+ slen_t old_len=len;
+ slen_t old_used=used;
+#endif
+ Ary *old_ary=ary;
+ // printf("rehash minlen=%u len=%u used=%u maxused=%u alloced=%u\n", minlen, len, used, maxused, alloced);
+ vi_scale();
+ // printf("scaled minlen=%u len=%u used=%u maxused=%u alloced=%u\n", minlen, len, used, maxused, alloced);
+ // assert( minlen <= len);
+ if (scale==old_scale && used<=maxused) { assert(obj_assert()); return; }
+ Ary *pp=old_ary, *ppend=pp+old_alloced;
+ slen_t calclen=0, calcused=0;
+ ary=new Ary[alloced];
+ // printf("alloced=%u\n", alloced);
+ memset(ary, '\377', sizeof(Ary)*alloced); /* fill with NEVER_USED */
+ /* insert the old values to the new hash */
+ for (; pp!=ppend; pp++) {
+ if (pp->keylen!=NEVER_USED) calcused++;
+ if (pp->keylen<(slen_t)-2) {
+ // printf("%u %u\n", (unsigned char)pp->keydata[0], (unsigned char)pp->keydata[1]);
+ calclen++;
+ slen_t h1=vi_h1(pp->keydata,pp->keylen);
+ assert(h1<alloced);
+ Ary *p=ary+h1;
+ assert(p->keylen!=DELETED);
+ if (p->keylen==NEVER_USED) { found:
+ p->keylen=pp->keylen;
+ p->keydata=pp->keydata;
+ continue;
+ }
+ assert(!(p->keylen==pp->keylen && 0==memcmp(p->keydata, pp->keydata, pp->keylen)) && "dupicate key");
+ /* Not found for the 1st try. We have to walk. */
+ slen_t h2=vi_h2(pp->keydata,pp->keylen);
+ assert(1<=h2 && h1<alloced);
+ while (1) { /* Dat: maxlen < alloced, so this can safely be an infinite loop. */
+ if (h1>=h2) { h1-=h2; p-=h2; }
+ else { h1+=alloced-h2; p+=alloced-h2; }
+ assert(p->keylen!=DELETED);
+ if (p->keylen==NEVER_USED) goto found;
+ assert(!(p->keylen==pp->keylen && 0==memcmp(p->keydata, pp->keydata, pp->keylen)) && "dupicate key");
+ } /* WHILE */
+ }
+ } /* NEXT */
+ used=len=calclen;
+ assert(calclen==old_len);
+ assert(calcused==old_used);
+ assert(old_len==len);
+ assert(old_len==used);
+ assert(obj_assert());
+ delete [] old_ary;
+}
+void Mapping::DoubleHash::clear() {
+ assert(obj_assert());
+ Ary *pp=ary, *ppend=pp+alloced;
+ for (; pp!=ppend; pp++) if (pp->keylen<(slen_t)-2) {
+ vi_dtor(pp->keydata-datalen); /* this is quite fast */
+ delete [] (pp->keydata-datalen); /* this is really slow for millions of values */
+ pp->keylen=(slen_t)DELETED;
+ len--;
+ }
+ assert(len==0);
+ if (minlen!=0) rehash();
+}
+
+/* --- */
+
+static slen_t const d15_primes[]= {
+ 0, 10, 13, 23, 37, 59, 89, 137, 211, 317, 479, 719, 1087, 1637, 2459, 3691,
+ 5557, 8353, 12539, 18839, 28277, 42433, 63659,
+ 95507UL, 143261UL, 214913UL, 322397UL, 483611UL, 725423UL, 1088159UL, 1632259UL, 2448389UL,
+ 3672593UL, 5508913UL, 8263373UL, 12395069UL, 18592631UL, 27888947UL, 41833427UL,
+ 62750147UL, 94125247UL, 141187901UL, 211781873UL, 317672813UL, 476509223UL,
+ 714763843UL, 1072145771UL, 1608218669UL, 2412328031UL, 3618492049UL,
+#if SIZEOF_SLEN_T>=8
+ 5427738097UL, 8141607167UL, 12212410753UL, 18318616157UL, 27477924239UL,
+ 41216886467UL, 61825329719UL, 92737994593UL, 139106991917UL, 208660487887UL,
+ 312990731839UL, 469486097807UL, 704229146717UL, 1056343720093UL,
+ 1584515580187UL, 2376773370313UL, 3565160055487UL, 5347740083243UL,
+ 8021610124867UL, 12032415187319UL, 18048622780987UL, 27072934171487UL,
+ 40609401257291UL, 60914101885951UL, 91371152828947UL, 137056729243439UL,
+ 205585093865189UL, 308377640797829UL, 462566461196803UL,
+ 693849691795229UL, 1040774537692907UL, 1561161806539393UL,
+ 2341742709809177UL, 3512614064713777UL, 5268921097070759UL,
+ 7903381645606193UL, 11855072468409349UL, 17782608702614033UL,
+ 26673913053921061UL, 40010869580881603UL, 60016304371322423UL,
+ 90024456556983643UL, 135036684835475519UL, 202555027253213279UL,
+ 303832540879819943UL, 455748811319729951UL, 683623216979594929UL,
+ 1025434825469392417UL, 1538152238204088631UL, 2307228357306132983UL,
+ 3460842535959199481UL, 5191263803938799269UL,
+#endif
+ 0
+};
+
+void Mapping::DoubleHash15::vi_scale() {
+#if 0
+ // <lloced=63659 used=59671 maxused=59670
+ // alloced=1637 used=59671 maxused=1534
+
+ // <lloced=1637 used=1535 maxused=1534
+ // |lloced=2459 used=1535 maxused=1534
+ // |lloced=1637 used=1535 maxused=1534
+ // alloced=1637 used=1535 maxused=1534
+
+
+ printf("<lloced=%u used=%u maxused=%u\n", alloced, used, maxused);
+ if (len<minlen) { again:
+ /* assert(used==minlen-1); */
+ assert(scale>=1);
+ alloced=(d15_primes+2)[--scale];
+ if (scale>1) minlen=(d15_primes+2)[scale-2];
+ else if (scale==1) minlen=10;
+ else minlen=0;
+ if (len<minlen) goto again;
+ } else if (used>maxused) {
+ assert(used==maxused+1);
+ if ((alloced=(d15_primes+2)[++scale])==0) abort(); /* Imp: better overflow reporting */
+ if (scale>1) minlen=(d15_primes+2)[scale-2];
+ else if (scale==1) minlen=10;
+ else minlen=0;
+ // if (len<minlen) minlen=len;
+ } else assert(0);
+ printf("|lloced=%u used=%u maxused=%u\n", alloced, used, maxused);
+ if (alloced<=4000U) maxused=(alloced*15)>>4;
+ else maxused=(alloced>>4)*15;
+ if (used>maxused) printf("alloced=%u used=%u maxused=%u\n", alloced, used, maxused);
+#endif
+
+ /* Dat: we respect only `len', not used. */
+ /* Imp: make calculation of scale relative to previous one */
+
+ scale=0; while (1) {
+ // printf("xscale=%u\n", scale);
+ if (0==(alloced=(d15_primes+2)[scale])) { assert(0); abort(); } /* Imp: better overflow reporting */
+ if (alloced<=4000U) maxused=(alloced*15)>>4;
+ else maxused=(alloced>>4)*15; /* avoid overflows */
+ if (len<=maxused) break; /* _not_ used<=maxused, because of rehash() */
+ scale++;
+ }
+ minlen=(d15_primes)[scale];
+ // printf("ret alloced=%u used=%u maxused=%u\n", alloced, used, maxused);
+}
+slen_t Mapping::DoubleHash15::vi_h1(register char const*key, register slen_t keylen) {
+ register slen_t hval=0, m=alloced;
+ while (keylen--!=0) hval=((hval<<8)+*key++)%m;
+ /* Imp: make this accurate and faster (the `%' operation is rather slow) */
+ return hval;
+}
+slen_t Mapping::DoubleHash15::vi_h2(char const*key, slen_t keylen) {
+ register slen_t hval=0, m=alloced-1;
+ while (keylen--!=0) hval=((hval<<8)+*key++)%m;
+ /* Imp: make this accurate and faster (the `%' operation is rather slow) */
+ return hval+1;
+}
+void Mapping::DoubleHash15::vi_dtor(char *) {}
+
+Mapping::DoubleHash15::DoubleHash15(slen_t datalen_) {
+ ary=new Ary[alloced=(d15_primes+2)[scale=0]];
+ memset(ary, '\377', sizeof(Ary)*alloced); /* fill with NEVER_USED */
+ datalen=datalen_;
+ len=used=minlen=0;
+ maxused=(alloced>>4)*15;
+}
+Mapping::DoubleHash15::~DoubleHash15() {
+ minlen=0;
+ clear();
+ delete [] ary;
+}
+
+/* __END__ */
diff --git a/graphics/sam2p/mapping.hpp b/graphics/sam2p/mapping.hpp
new file mode 100644
index 0000000000..e7c798b0ac
--- /dev/null
+++ b/graphics/sam2p/mapping.hpp
@@ -0,0 +1,157 @@
+/* mapping.hpp -- an associative array that maps strings into arbitrary fixed-length values
+ * by pts@fazekas.hu at Sat Mar 23 16:01:55 CET 2002
+ */
+
+#ifdef __GNUC__
+#ifndef __clang__
+#pragma interface
+#endif
+#endif
+
+#ifndef MAPPING_HPP
+#define MAPPING_HPP 1
+
+#include "config2.h"
+#include "gensi.hpp"
+
+class Mapping {
+ /** A mapping is an assicative array whose keys are arbitrary binary strings
+ * and its values are arbirary fixed-length data. The Mapping class is
+ * abstract. The longest key which can be stored in a Mapping::Gen has
+ * length `(slen_t)-3'. The caller must verify that she doesn't try to
+ * call us with a longer string.
+ */
+ class Gen {
+ public:
+ inline virtual ~Gen() {}
+ /** Returns the length of one data value (same for all values, determined
+ * at construction of Gen).
+ */
+ inline slen_t getDataLen() const { return datalen; }
+ /** Returns the number of keys currently in this Mapping. */
+ inline slen_t getLength() const { return len; }
+ /** Returns the number of key positions allocated for this Mapping. This
+ * number may or may not have meaning, depending on the implementation.
+ */
+ inline slen_t getAlloced() const { return len; }
+ /**
+ * Updates or extends the mapping with the specified key/value pair.
+ * @param data must point to an area of length getDataLen(). That
+ * area will be copied (memcpy()) by set().
+ * @return true if key previously hasn't existed
+ */
+ virtual bool set(char const*key, slen_t keylen, char const*data) =0;
+ /** @return the address of the data that corresponds to param
+ * `key', or NULLP if `key' was not found. The returned value is valid
+ * until the next modification (.set(), deletee() methods).
+ */
+ virtual char* get(char const*key, slen_t keylen) =0;
+ /**
+ * Updates mapping with the specified key/value pair. Leaves it unchanged
+ * if the specified key doesn't exist. Calls get() and memcpy() to do the
+ * job.
+ * @param data must point to an area of length getDataLen(). That
+ * area will be copied by set().
+ * @return true if key previously hasn't existed
+ */
+ bool update(char const*key, slen_t keylen, char const*data);
+
+ /** Calls get to do the job. */
+ inline bool exists(char const*key, slen_t keylen) { return NULLP!=get(key, keylen); }
+
+ /**
+ * Deletes the specified `key' from the mapping.
+ * @param data must point to an area of length getDataLen(). That
+ * area will be copied by set().
+ * @return true if key previously hasn't existed
+ */
+ virtual bool deletee(char const*key, slen_t keylen) =0;
+
+ /** The user must ensure that she isn't updating the mapping while walking.
+ * @param key (out) is set to NULLP on empty mapping.
+ */
+ virtual void getFirst(char const*const*& key, slen_t &keylen, char *& data) =0;
+ /** The user must ensure that she isn't updating the mapping while walking.
+ * @param key (out) is set to NULLP if there are no more elements
+ */
+ virtual void getNext (char const*const*& key, slen_t &keylen, char *& data) =0;
+
+ protected:
+ slen_t datalen, len, alloced;
+ };
+
+ /** Double hashing. Still abstract. */
+ class DoubleHash: public Gen {
+ public:
+ inline virtual ~DoubleHash() {}
+ /** If it modifies `scale', then it must modify alloced, may modify minlen
+ * and maxused, and must not modify anything else. If it does not modify
+ * `scale', it must not modify anything else. After it returns,
+ * obj_assert() must hold. Must not copy or (re)allocate memory,
+ * rehashing is not done by vi_scale(). rehash() calls vi_scale(), and
+ * rehash() does the real reallocation.
+ */
+ virtual void vi_scale() =0;
+ /** First hash function. Must return a value in 0..alloced-1 */
+ virtual slen_t vi_h1(char const*key, slen_t keylen) =0;
+ /** Second hash function. Must return a value in 1..alloced-1, which is
+ * realatively prime to the value returned by vi_h2().
+ */
+ virtual slen_t vi_h2(char const*key, slen_t keylen) =0;
+ /** Destruct and free resources used by data. Called by deletee(). */
+ virtual void vi_dtor(char *data) =0;
+
+ /** Called by set() and deletee() ?? */
+ virtual bool set (char const* key, slen_t keylen, char const*data);
+ virtual char*get (char const* key, slen_t keylen);
+ virtual bool deletee (char const* key, slen_t keylen);
+ virtual void getFirst(char const*const*&key, slen_t &keylen, char *& data);
+ virtual void getNext (char const*const*&key, slen_t &keylen, char *& data);
+ /** Delete everything. */
+ void clear();
+ protected:
+ void rehash();
+ /** @return true */
+ bool obj_assert();
+ /** `keylen==(slen_t)-1' indicates a place never used,
+ * `keylen==(slen_t)-2' indicates a deleted place
+ * Before changing the value of NEVER_USED, please update the memset(...)
+ * in rehash().
+ */
+ BEGIN_STATIC_ENUM1(slen_t) NEVER_USED=(slen_t)-1, DELETED=(slen_t)-2 END_STATIC_ENUM()
+ // static const slen_t NEVER_USED=(slen_t)-1, DELETED=(slen_t)-2;
+ struct Ary {
+ slen_t keylen;
+ /** data is located at keydata, key is located keydata-datalen */
+ char *keydata;
+ } *ary;
+ /* The minimum number of keys before rehashing. */
+ slen_t minlen;
+ /* The maximum number of keys before rehashing. */
+ slen_t maxused;
+ /* The number of used places. A place is used unless it is NEVER_USED */
+ slen_t used;
+ /** Used by the implementor of vi_scale. */
+ unsigned scale;
+ };
+
+ /** Simple prime modulus double hashing with a factor of around 1.5
+ * between `alloced' scales. This class is not abstract anymore.
+ */
+ class DoubleHash15: public DoubleHash {
+ public:
+ DoubleHash15(slen_t datalen_);
+ virtual ~DoubleHash15();
+ virtual void vi_scale();
+ /** @return key % Prime */
+ virtual slen_t vi_h1(char const*key, slen_t keylen);
+ /** @return (key % (Prime-1))+1 */
+ virtual slen_t vi_h2(char const*key, slen_t keylen);
+ /** No-op. */
+ virtual void vi_dtor(char *data);
+ };
+ public:
+ typedef DoubleHash15 H;
+};
+
+#endif
diff --git a/graphics/sam2p/minips.cpp b/graphics/sam2p/minips.cpp
new file mode 100644
index 0000000000..d7a6b298aa
--- /dev/null
+++ b/graphics/sam2p/minips.cpp
@@ -0,0 +1,1104 @@
+/*
+ * minips.cpp
+ * by pts@fazekas.hu at Sat Mar 9 21:33:35 CET 2002
+ */
+
+#ifdef __GNUC__
+#ifndef __clang__
+#pragma implementation
+#endif
+#endif
+
+#include "minips.hpp"
+#include "error.hpp"
+#include "gensio.hpp"
+#if USE_DICT_MAPPING
+#if OBJDEP
+# warning REQUIRES: mapping.o
+#endif
+#include "mapping.hpp"
+#endif
+#include <stdio.h> /* sscanf() */
+#include <string.h> /* memset() */
+
+static inline bool is_ps_white(char c) {
+ return c=='\n' || c=='\r' || c=='\t' || c==' ' || c=='\f' || c=='\0';
+}
+
+static inline bool is_ps_name(char c) {
+ /* Dat: we differ from PDF since we do not treat the hashmark (`#') special
+ * in names.
+ * Dat: we differ from PostScript since we accept names =~ /[!-~]/
+ */
+ return c>='!' && c<='~'
+ && c!='/' && c!='%' && c!='{' && c!='}' && c!='<' && c!='>'
+ && c!='[' && c!=']' && c!='(' && c!=')';
+ /* Dat: PS avoids: /{}<>()[]% \n\r\t\000\f\040 */
+}
+
+/** @param b: assume null-terminated @return true on erro
+ * @return false on error
+ */
+static inline bool toInteger(SimBuffer::Flat const&b, signed long &ret) {
+ int n=0; /* BUGFIX?? found by __CHECKER__ */
+ // b.term0();
+ return sscanf(b(), "%li%n", &ret, &n)<1 || b[n]!='\0';
+}
+
+static inline bool toHex(char const*s, unsigned long &ret) {
+ int n=0;
+ return sscanf(s, "%lx%n", &ret, &n)<1 || s[n]!='\0';
+}
+
+static inline bool toHex3(char const*s, char ret[3]) {
+ unsigned long l;
+ if (toHex(s, l)) return true;
+ ret[0]=((l>>8)&15)*17; ret[1]=((l>>4)&15)*17; ret[2]=(l&15)*17;
+ return false;
+}
+
+static inline bool toHex6(char const*s, char ret[3]) {
+ unsigned long l;
+ if (toHex(s, l)) return true;
+ ret[0]=(l>>16)&255; ret[1]=(l>>8)&255; ret[2]=l&255;
+ return false;
+}
+
+/** @param b: assume null-terminated @return true on error */
+static inline bool toReal(SimBuffer::Flat const&b, double &ret) {
+ int n;
+ char c;
+ // b.term0();
+ /* Dat: glibc accepts "12e", "12E", "12e+" and "12E-" */
+ return sscanf(b(), "%lf%n", &ret, &n)<1
+ || (c=b[n-1])=='e' || c=='E' || c=='+' || c=='-' || b[n]!='\0';
+}
+
+/** This is not correct if blen cuts the real number into two strings.
+ * @param b: assume null-terminated @return true on error
+ */
+static inline bool toReal(char const *b, slen_t blen, double &ret) {
+ int n;
+ char c;
+ // b.term0();
+ /* Dat: glibc accepts "12e", "12E", "12e+" and "12E-" */
+ return sscanf(b, "%lf%n", &ret, &n)<1
+ || (c=b[n-1])=='e' || c=='E' || c=='+' || c=='-' || (slen_t)n!=blen;
+}
+
+MiniPS::Tokenizer::Tokenizer(GenBuffer::Readable& in_): in(in_), ungot(NO_UNGOT) {
+}
+int MiniPS::Tokenizer::yylex() {
+ int c=0; /* dummy initialization */
+ bool hi;
+ unsigned hv;
+ slen_t nest, len;
+ signed long l;
+ double d;
+ Real::metric_t metric;
+ char saved;
+
+ if (ungot==EOFF) return EOFF;
+ if (ungot!=NO_UNGOT) { c=ungot; ungot=NO_UNGOT; goto again; }
+ again_getcc:
+ c=in.vi_getcc();
+ again:
+ switch (c) {
+ case -1: eof:
+ return ungot=EOFF;
+ case '\n': case '\r': case '\t': case ' ': case '\f': case '\0':
+ goto again_getcc;
+ case '%': /* one-line comment */
+ while ((c=in.vi_getcc())!='\n' && c!='\r' && c!=-1) ;
+ if (c==-1) goto eof;
+ goto again_getcc;
+ case '{': case '[':
+ return '[';
+ case '}': case ']':
+ return ']';
+ case ')': goto err;
+ case '>':
+ if (in.vi_getcc()!='>') goto err;
+ return '>';
+ case '<':
+ if ((c=in.vi_getcc())==-1) { uf_hex: Error::sev(Error::EERROR) << "miniPS: unfinished hexstr" << (Error*)0; }
+ if (c=='<') return '<';
+ if (c=='~') Error::sev(Error::EERROR) << "miniPS: a85str unsupported" << (Error*)0;
+ tv.bb=&b; b.clear();
+ hi=true;
+ while (c!='>') {
+ if ((hv=b.hexc2n(c))!=16) {
+ if (hi) { b << (char)(hv<<4); hi=false; }
+ else { b.end_()[-1]|=hv; hi=true; }
+ } else if (!is_ps_white(c)) Error::sev(Error::EERROR) << "miniPS: syntax error in hexstr" << (Error*)0;
+ if ((c=in.vi_getcc())==-1) goto uf_hex;
+ }
+ /* This is correct even if an odd number of hex digits have arrived */
+ return '(';
+ case '(':
+ tv.bb=&b; b.clear();
+ nest=1;
+ while ((c=in.vi_getcc())!=-1) { redo:
+ if (c==')' && --nest==0) return '(';
+ if (c!='\\') { if (c=='(') nest++; b << (char)c; continue; }
+ /* read a backslash */
+ switch (c=in.vi_getcc()) {
+ case -1: goto uf_str;
+ case 'n': b << '\n'; break;
+ case 'r': b << '\r'; break;
+ case 't': b << '\t'; break;
+ case 'b': b << '\010'; break; /* \b and \a conflict between -ansi and -traditional */
+ case 'f': b << '\f'; break;
+ default:
+ if (c<'0' || c>'7') { b << (char)c; break; }
+ hv=c-'0'; /* read at most 3 octal chars */
+ if ((c=in.vi_getcc())==-1) goto uf_str;
+ if (c<'0' || c>'7') { b << (char)hv; goto redo; }
+ hv=8*hv+(c-'0');
+ if ((c=in.vi_getcc())==-1) goto uf_str;
+ if (c<'0' || c>'7') { b << (char)hv; goto redo; }
+ b << (char)(8*hv+(c-'0'));
+ } /* SWITCH */
+ } /* WHILE */
+ uf_str: Error::sev(Error::EERROR) << "miniPS: unfinished str" << (Error*)0;
+ case '/':
+ /* fall-through, b will begin with '/' */
+ default: /* /nametype, /integertype or /realtype */
+ tv.bb=&b; b.clear();
+ b.clear(); b << (char)c;
+ while ((c=in.vi_getcc())!=-1 && is_ps_name(c)) b << (char)c;
+ ungot=c==-1?EOFF:c;
+ if (b[0]=='/') return '/';
+ b.term0();
+ /* Dat: we don't support base-n number such as `16#100' == 256 in PostScript */
+ if (!toInteger(b, l)) { tv.i=l; return '1'; }
+ /* Dat: call toInteger _before_ toReal */
+ // if (!toReal(b, tv.d)) { fprintf(stderr,"%f;\n", tv.d); }
+ /* assert(tv.bb!=NULLP); */
+ len=b.getLength();
+ if (!toReal(b, d)) { /* tv.bb is also valid */
+ tv.r=new Real(d, b(), len);
+ return '.';
+ }
+ if (len>2 && (metric=Real::str2metric(b()+len-2))!=Real::ME_COUNT) {
+ saved=b[len-2];
+ b[len-2]='\0';
+ if (!toReal(b, d)) {
+ tv.r=new Real(d, b(), len-2);
+ tv.r->setMetric(metric);
+ return ':'; /* Real with metric */
+ }
+ b[len-2]=saved;
+ }
+ return 'E'; /* /nametype */
+ }
+ err:
+ Error::sev(Error::EERROR) << "miniPS: syntax error" << (Error*)0;
+ goto again_getcc; /* notreached */
+}
+
+/* --- */
+
+#if 0
+inline static unsigned typerr() { assert(0); return 0; }
+#endif
+
+unsigned MiniPS::getType(VALUE v) {
+ return (v&1)!=0 ? T_INTEGER
+ : v+0U>Qmax_+0U ? RVALUE(v)->getType()
+ : v==Qnull ? T_NULL+0/*avoid gcc-3.0 ld bug*/
+ : T_BOOLEAN;
+}
+char const* MiniPS::getTypeStr(unsigned u) {
+ static char const* strs[]= { (char const*)NULLP, "null", "boolean", "integer", "real", "string", "array", "dict", "name", "Ename", "void" };
+ // return strs[getType(v)];
+ return strs[u];
+}
+void MiniPS::delete0(VALUE v) {
+ if (isDirect(v)) return;
+ Value *vp=RVALUE(v);
+ unsigned ty=vp->getType();
+ if (ty==T_DICT) RDICT(v)->free();
+ else if (ty==T_ARRAY) RARRAY(v)->free();
+ else if (ty==T_VOID) ;
+ else if (vp->hasPtr()) delete [] vp->begin_();
+ delete vp; /* BUGFIX at Sat Sep 7 12:50:13 CEST 2002 */
+}
+void MiniPS::dump(VALUE v, unsigned indent) {
+ Files::FILEW sout(stdout);
+ dump(sout, v, indent);
+}
+void MiniPS::dump(GenBuffer::Writable& out_, VALUE v, unsigned indent) {
+ if (v==Qnull) out_ << "null";
+ else if (v==Qtrue) out_ << "true";
+ else if (v==Qfalse) out_ << "false";
+ else if ((v&1)!=0) out_ << (v/2); /* prints a signed integer */
+ else {
+ Value *vp=RVALUE(v);
+ unsigned ty=vp->getType();
+ if (ty==T_STRING) {
+ SimBuffer::Static s((char*)vp->begin_(), vp->getLength());
+ SimBuffer::B b;
+ b.appendDumpPS(s, true);
+ out_ << b;
+ } else if (ty==T_SNAME || ty==T_ENAME) {
+ out_.vi_write((char*)vp->begin_(), vp->getLength());
+ } else if (ty==T_REAL) {
+ RREAL(v)->dump(out_);
+ } else if (ty==T_ARRAY) {
+ if (!vp->isDumping()) { /* Imp: thread-safe locking */
+ RARRAY(v)->dump(out_, indent);
+ } else out_ << "[...]";
+ } else if (ty==T_DICT) {
+ if (!vp->isDumping()) { /* Imp: thread-safe locking */
+ RDICT(v)->dump(out_, indent);
+ } else out_ << "<<...>>";
+ } else assert(0 && "unknown MiniPS type");
+ }
+}
+
+/* --- */
+
+/* Sat Sep 7 12:30:19 CEST 2002 */
+const double MiniPS::Real::me_factor[MiniPS::Real::ME_COUNT]={
+ 1.0L, /* 1 bp = 1 bp (big point) */
+ 72.0L, /* 1 in = 72 bp (inch) */
+ 72.0L/72.27, /* 1 pt = 72/72.27 bp (point) */
+ 12.0L*72.0/72.27, /* 1 pc = 12*72/72.27 bp (pica) */
+ 1238.0L/1157.0*72.0/72.27, /* 1 dd = 1238/1157*72/72.27 bp (didot point) [about 1.06601110141206 bp] */
+ 12.0L*1238.0/1157.0*72.0/72.27, /* 1 cc = 12*1238/1157*72/72.27 bp (cicero) */
+ 72.0L/72.27/65536.0, /* 1 sp = 72/72.27/65536 bp (scaled point) */
+ 72.0L/2.54, /* 1 cm = 72/2.54 bp (centimeter) */
+ 7.2L/2.54, /* 1 mm = 7.2/2.54 bp (millimeter) */
+};
+/* Sat Sep 7 12:30:19 CEST 2002 */
+char const* const MiniPS::Real::me_psfactor[MiniPS::Real::ME_COUNT]={
+ "", /* 1 bp = 1 bp (big point) */
+ " 72 mul", /* 1 in = 72 bp (inch) */
+ " 72 mul 72.27 div", /* 1 pt = 72/72.27 bp (point) */
+ " 864 mul 72.27 div", /* 1 pc = 12*72/72.27 bp (pica) */
+ " 891.36 mul 836.164 div", /* 1 dd = 1238/1157*72/72.27 bp (didot point) [about 1.06601110141206 bp] */
+ " 10696.32 mul 836.164 div", /* 1 cc = 12*1238/1157*72/72.27 bp (cicero) */
+ " 0.72 mul 47362.8672 div", /* 1 sp = 72/72.27/65536 bp (scaled point) */
+ " 72 mul 2.54 div", /* 1 cm = 72/2.54 bp (centimeter) */
+ " 720 mul 254 div", /* 1 mm = 7.2/2.54 bp (millimeter) */
+};
+MiniPS::Real::Real(double d_, char const*ptr_, ii_t len_): d(d_), metric(0), dumpPS(false) {
+ ty=T_REAL;
+ char *p=new char[len_+1]; /* Will be freed by MiniPS::delete0(). */
+ memcpy(ptr=p, ptr_, len=len_);
+ p[len_]='\0';
+}
+void MiniPS::Real::dump(GenBuffer::Writable &out_, bool dumpPS_force) {
+ char buf[64]; /* Imp: should be enough?? */
+ if (metric!=0 && (dumpPS_force || dumpPS)) {
+ sprintf(buf, "%" PTS_CFG_PRINTFGLEN "g%s", d, me_psfactor[metric]);
+ } else {
+ sprintf(buf, "%" PTS_CFG_PRINTFGLEN "g", d*me_factor[metric]);
+ }
+ out_ << buf;
+}
+MiniPS::Real::metric_t MiniPS::Real::str2metric(char const str[2]) {
+ switch (str[0]) {
+ case 'b': if (str[1]=='p') return ME_bp; break;
+ case 'i': if (str[1]=='n') return ME_in; break;
+ case 'p': if (str[1]=='t') return ME_pt;
+ if (str[1]=='c') return ME_pc; break;
+ case 'd': if (str[1]=='d') return ME_dd; break;
+ case 'c': if (str[1]=='c') return ME_cc;
+ if (str[1]=='m') return ME_cm; break;
+ case 's': if (str[1]=='p') return ME_sp; break;
+ case 'm': if (str[1]=='m') return ME_mm; break;
+ }
+ return ME_COUNT;
+}
+bool MiniPS::Real::isDimen(char const *str) {
+ double d;
+ slen_t len=strlen(str);
+ if (!toReal(str, len, d)) return true;
+ return len>2 && str2metric(str+len-2)!=ME_COUNT && !toReal(str, len-2, d);
+}
+
+MiniPS::String::String(char const*ptr_, ii_t len_) {
+ char *p=new char[len_+1]; /* Will be freed by MiniPS::delete0(). */
+ memcpy(ptr=p, ptr_, len=len_);
+ p[len_]='\0';
+ ty=T_STRING;
+}
+void MiniPS::String::replace(char const*ap, slen_t alen, char const*bp, slen_t blen) {
+ char *p=new char[alen+blen+1]; /* Will be freed by MiniPS::delete0(). */
+ memcpy(p, ap, alen);
+ memcpy(p+alen, bp, blen);
+ p[alen+blen]='\0';
+ delete [] (char*)ptr;
+ ptr=p;
+}
+
+MiniPS::Sname::Sname(char const*ptr_, ii_t len_) {
+ param_assert(len_>=1 && ptr_[0]=='/');
+ char *p=new char[len_+1]; /* Will be freed by MiniPS::delete0(). */
+ memcpy(ptr=p, ptr_, len=len_);
+ p[len_]='\0';
+ ty=T_SNAME;
+}
+bool MiniPS::Sname::equals(Sname const&other) {
+ return len==other.len && 0==memcmp(ptr, other.ptr, len);
+}
+bool MiniPS::Sname::equals(char const*other) {
+ return 0==strcmp(1+(char*)ptr, other);
+}
+
+MiniPS::Ename::Ename(char const*ptr_, ii_t len_) {
+ param_assert(len_>=1 && ptr_[0]!='/');
+ char *p=new char[len_+1]; /* Will be freed by MiniPS::delete0(). */
+ memcpy(ptr=p, ptr_, len=len_);
+ p[len_]='\0';
+ ty=T_ENAME;
+}
+bool MiniPS::Ename::equals(Ename const&other) {
+ return len==other.len && 0==memcmp(ptr, other.ptr, len);
+}
+bool MiniPS::Ename::equals(char const*other, slen_t otherlen) {
+ return (slen_t)len==otherlen && 0==memcmp(ptr, other, otherlen);
+}
+bool MiniPS::Ename::equals(char const*other) {
+ return 0==strcmp((char*)ptr, other);
+}
+
+MiniPS::Array::Array() {
+ alloced=16;
+ ptr=new VALUE[alloced=16];
+ len=0;
+ ty=T_ARRAY;
+}
+void MiniPS::Array::free() {
+ VALUE *p=(VALUE*)ptr, *pend=p+len;
+ while (p!=pend) MiniPS::delete0(*p++);
+ delete [] (VALUE*)ptr;
+}
+void MiniPS::Array::push(VALUE v) {
+ if (len==alloced) extend(len+1);
+ ((VALUE*)ptr)[len++]=v;
+}
+MiniPS::VALUE MiniPS::Array::get(ii_t index) {
+ return (index<0 || index>=len) ? Qundef : ((VALUE*)ptr)[index];
+}
+void MiniPS::Array::set(ii_t index, VALUE val) {
+ param_assert(index>=0 && index<len);
+ MiniPS::delete0(((VALUE*)ptr)[index]);
+ ((VALUE*)ptr)[index]=val;
+}
+void MiniPS::Array::dump(GenBuffer::Writable &out_, unsigned indent) {
+ dumping=true;
+ if (len==0) {
+ out_ << "[]";
+ } else if (len==1) {
+ out_ << "[ ";
+ MiniPS::dump(out_, ((VALUE*)ptr)[0], indent);
+ out_ << " ]";
+ } else {
+ indent+=2;
+ char *spaces=new char[indent];
+ memset(spaces, ' ', indent);
+ // spaces[indent]='\n';
+ out_ << "[ % " << len << " elements\n";
+ VALUE *p=(VALUE*)ptr, *pend=p+len;
+ while (p!=pend) {
+ out_.vi_write(spaces, indent);
+ MiniPS::dump(out_, *p++, indent);
+ /*if(p!=pend)*/ out_ << "\n";
+ }
+ out_.vi_write(spaces, indent-=2);
+ out_ << "]";
+ delete [] spaces;
+ }
+ dumping=false;
+}
+void MiniPS::Array::extend(ii_t newlen) {
+ if (newlen<=alloced) return;
+ ii_t newalloced=alloced;
+ assert(alloced>=0);
+ while (newlen>newalloced) newalloced<<=1;
+ VALUE *newptr=new VALUE[newalloced];
+ memcpy(newptr, ptr, len*sizeof(VALUE));
+ delete [] (VALUE*)ptr;
+ ptr=newptr;
+ alloced=newalloced;
+ /* len remains unchanged */
+}
+void MiniPS::Array::getFirst(VALUE *&val) {
+ if (len==0) { val=(VALUE*)NULLP; return; }
+ val=(VALUE*)ptr;
+}
+void MiniPS::Array::getNext(VALUE *&val) {
+ val++;
+ if (len+(VALUE*)ptr==val) val=(VALUE*)NULLP;
+}
+
+#if USE_DICT_MAPPING
+MiniPS::Dict::Dict() { /* Sun Mar 24 21:02:41 CET 2002 */
+ ptr=(void*)new Mapping::H(sizeof(VALUE)+1);
+ /* hash value format: a VALUE, and a flag (0 or 1) indicating touchedness */
+ len=0; /* meaningless */
+ ty=T_DICT;
+}
+void MiniPS::Dict::free() {
+ char const*const* keyy; slen_t keylen;
+ VALUE *val = 0; /* pacify gcc-4.2.1 by giving initial value */
+ bool touched;
+ getFirst(keyy, keylen, val, touched);
+ while (keyy!=(char const*const*)NULLP) {
+ MiniPS::delete0(*val);
+ getNext(keyy, keylen, val, touched);
+ }
+ delete (Mapping::H*)ptr;
+}
+void MiniPS::Dict::put(char const*key, VALUE val) {
+ put(key,strlen(key),val);
+}
+MiniPS::VALUE MiniPS::Dict::push(char const*keys, slen_t keylen, VALUE val) {
+ if (keys[0]=='/') { keys++; keylen--; }
+ char *has=((Mapping::H*)ptr)->get(keys,keylen);
+ VALUE ret=Qundef;
+ if (has!=(char const*)NULLP) {
+ memcpy(&ret, has, sizeof(VALUE));
+ // printf("found=/%s.\n", keys);
+ /* No MiniPS::delete0(); deliberately. */
+ memcpy(has, &val, sizeof(VALUE)); has[sizeof(VALUE)]=0;
+ } else {
+ char tmp[sizeof(VALUE)+1];
+ memcpy(tmp, &val, sizeof(VALUE));
+ tmp[sizeof(VALUE)]=0;
+ ((Mapping::H*)ptr)->set(keys,keylen,tmp);
+ }
+ return ret;
+}
+void MiniPS::Dict::put(char const*keys, slen_t keylen, VALUE val) {
+ if (keys[0]=='/') { keys++; keylen--; }
+ char *has=((Mapping::H*)ptr)->get(keys,keylen);
+ if (has!=NULLP) {
+ VALUE ret=Qundef; memcpy(&ret, has, sizeof(VALUE));
+ MiniPS::delete0(ret);
+ memcpy(has, &val, sizeof(VALUE)); has[sizeof(VALUE)]=0;
+ } else {
+ char tmp[sizeof(VALUE)+1];
+ memcpy(tmp, &val, sizeof(VALUE));
+ tmp[sizeof(VALUE)]=0;
+ ((Mapping::H*)ptr)->set(keys,keylen,tmp);
+ }
+}
+MiniPS::VALUE MiniPS::Dict::get(char const*keys, slen_t keylen) {
+ if (keys[0]=='/') { keys++; keylen--; }
+ char *has=((Mapping::H*)ptr)->get(keys,keylen);
+ VALUE ret=Qundef; if (has!=NULLP) memcpy(&ret, has, sizeof(VALUE));
+ return ret;
+}
+MiniPS::VALUE MiniPS::Dict::get1(char const*keys, slen_t keylen) {
+ if (keys[0]=='/') { keys++; keylen--; }
+ char *has=((Mapping::H*)ptr)->get(keys,keylen);
+ VALUE ret=Qundef; if (has!=NULLP) { memcpy(&ret, has, sizeof(VALUE)); has[sizeof(VALUE)]=1; }
+ return ret;
+}
+void MiniPS::Dict::untouch(char const*keys, slen_t keylen) {
+ if (keys[0]=='/') { keys++; keylen--; }
+ char *has=((Mapping::H*)ptr)->get(keys,keylen);
+ if (has!=NULLP) has[sizeof(VALUE)]=0;
+}
+void MiniPS::Dict::getFirst(char const*const*& key, slen_t &keylen, VALUE *&val, bool &touched) {
+ char *has;
+ // key=(char const*const*)NULLP;return;
+ ((Mapping::H*)ptr)->getFirst(key, keylen, has);
+ if (key==(char const*const*)NULLP) return;
+ val=PTS_align_cast(VALUE*,has);
+ touched=has[sizeof(VALUE)]!=0;
+}
+void MiniPS::Dict::getNext (char const*const*& key, slen_t &keylen, VALUE *&val, bool &touched) {
+ char *has;
+ ((Mapping::H*)ptr)->getNext(key, keylen, has);
+ if (key==(char const*const*)NULLP) return;
+ val=PTS_align_cast(VALUE*,has);
+ touched=has[sizeof(VALUE)]!=0;
+}
+void MiniPS::Dict::dump(GenBuffer::Writable &out_, unsigned indent, bool dump_delimiters) {
+ dumping=true;
+ slen_t len=((Mapping::H*)ptr)->getLength();
+ if (len==0) {
+ if (dump_delimiters) out_ << "<<>>";
+ } else {
+ char const*const* keyy; slen_t keylen;
+ VALUE *val = 0; /* pacify gcc-4.2.1 by giving initial value */
+ bool touched;
+ indent+=2;
+ char *spaces=new char[indent];
+ memset(spaces, ' ', indent);
+ // spaces[indent]='\n';
+ if (dump_delimiters) out_ << "<< % " << len << " key(s)\n";
+ getFirst(keyy, keylen, val, touched);
+ while (keyy!=(char const*const*)NULLP) {
+ out_.vi_write(spaces, indent);
+ out_.vi_putcc('/');
+ out_.vi_write(*keyy, keylen); /* Imp: PDF #...-quoting */
+ out_ << " ";
+ MiniPS::dump(out_, *val, indent);
+ out_.vi_putcc('\n');
+ getNext(keyy, keylen, val, touched);
+ }
+ if (dump_delimiters) { out_.vi_write(spaces, indent-=2); out_ << ">>"; }
+ delete [] spaces;
+ }
+ dumping=false;
+}
+void MiniPS::Dict::extend(ii_t) {}
+
+#else /* a MiniPS::Dict implementation with linear search */
+MiniPS::Dict::Dict() {
+ alloced=16;
+ ptr=new VALUE[alloced=16];
+ len=0;
+ ty=T_DICT;
+}
+void MiniPS::Dict::free() {
+ VALUE *p=(VALUE*)ptr, *pend=p+len;
+ while (p!=pend) MiniPS::delete0(*p++);
+ delete [] (VALUE*)ptr;
+}
+void MiniPS::Dict::put(char const*key, VALUE val) {
+ return put(key,strlen(key),val);
+}
+MiniPS::VALUE MiniPS::Dict::push(char const*keys, slen_t keylen, VALUE val) {
+ // param_assert(key[0]=='/');
+ if (keys[0]=='/') { keys++; keylen--; }
+ VALUE *p=(VALUE*)ptr, *pend=p+len;
+ while (p!=pend) {
+ if (MiniPS::RENAME(p[0]&~1)->equals(key,keylen)) {
+ VALUE v=p[1];
+ p[1]=val; return v;
+ }
+ p+=2;
+ }
+ if (len==alloced) extend(len+2);
+ ((VALUE*)ptr)[len++]=(MiniPS::VALUE)new Ename(keys,keylen);
+ ((VALUE*)ptr)[len++]=val;
+ return Qundef;
+}
+void MiniPS::Dict::put(char const*keys, slen_t keylen, VALUE val) {
+ // param_assert(key[0]=='/');
+ if (keys[0]=='/') { keys++; keylen--; }
+ //void MiniPS::Dict::put(VALUE key, VALUE val) {
+ //param_assert(MiniPS::getType(key)==T_ENAME);
+ VALUE *p=(VALUE*)ptr, *pend=p+len;
+ while (p!=pend) {
+ if (MiniPS::RENAME(p[0]&~1)->equals(keys,keylen)) {
+ MiniPS::delete0(p[1]);
+ p[1]=val;
+ return;
+ }
+ p+=2;
+ }
+ if (len==alloced) extend(len+2);
+ ((VALUE*)ptr)[len++]=(MiniPS::VALUE)new Ename(keys,keylen);
+ ((VALUE*)ptr)[len++]=val;
+}
+MiniPS::VALUE MiniPS::Dict::get(char const*key, slen_t keylen) {
+ if (key[0]=='/') { key++; keylen--; }
+ VALUE *p=(VALUE*)ptr, *pend=p+len;
+ while (p!=pend) {
+ //printf("for=%s trying=%s.\n", key, MiniPS::RENAME(p[0]&~1)->begin_());
+ if (MiniPS::RENAME(p[0]&~1)->equals(key, keylen)) return p[1];
+ p+=2;
+ }
+ return Qundef;
+}
+MiniPS::VALUE MiniPS::Dict::get1(char const*key, slen_t keylen) {
+ if (key[0]=='/') { key++; keylen--; }
+ VALUE *p=(VALUE*)ptr, *pend=p+len;
+ while (p!=pend) {
+ //printf("for=%s trying=%s.\n", key, MiniPS::RENAME(p[0]&~1)->begin_());
+ if (MiniPS::RENAME(p[0]&~1)->equals(key,keylen)) {
+ /* dirty, black magic */ p[0]|=1;
+ return p[1];
+ }
+ p+=2;
+ }
+ return Qundef;
+}
+void MiniPS::Dict::untouch(char const*key, slen_t keylen) {
+ if (key[0]=='/') { key++; keylen--; }
+ VALUE *p=(VALUE*)ptr, *pend=p+len;
+ while (p!=pend) {
+ if (MiniPS::RENAME(p[0]&~1)->equals(key,keylen)) { p[0]&=~1; return; }
+ p+=2;
+ }
+}
+void MiniPS::Dict::getFirst(char const*const*& key, slen_t &keylen, VALUE *&val, bool &touched) {
+ // assert(MiniPS::getType(((VALUE*)ptr)[0])==T_ENAME);
+ if (len==0) { key=(char const*const*)NULLP; return; }
+ assert(ptr!=NULLP);
+ Ename *skey=(Ename*)(((VALUE*)ptr)[0]&~1);
+ key=(char**)&skey->ptr;
+ keylen=skey->len;
+ val=((VALUE*)ptr)+1;
+ touched=(((VALUE*)ptr)[0]&1)!=0;
+}
+void MiniPS::Dict::getNext (char const*const*& key, slen_t &keylen, VALUE *&val, bool &touched) {
+ val+=2;
+ if (len+(VALUE*)ptr==(VALUE*)val-1) { key=(char const*const*)NULLP; return; }
+ Ename *skey=RENAME(val[-1]&~1);
+ // assert(MiniPS::getType((VALUE)skey)==T_ENAME);
+ key=(char**)&skey->ptr;
+ keylen=skey->len;
+ touched=(val[-1]&1)!=0;
+}
+
+#if 0 /* obsolete */
+void MiniPS::Dict::getFirst(VALUE *&key, VALUE *&val) {
+ if (len==0) { key=val=(VALUE*)NULLP; return; }
+ assert(ptr!=NULLP);
+ key=(VALUE*)ptr;
+ val=key+1;
+}
+void MiniPS::Dict::getNext(VALUE *&key, VALUE *&val) {
+ key+=2;
+ if (len+(VALUE*)ptr==key) key=val=(VALUE*)NULLP;
+ else val=key+1;
+}
+#endif
+
+void MiniPS::Dict::dump(GenBuffer::Writable &out_, unsigned indent, bool dump_delimiters) {
+ assert(len>=0 && (len&1)==0);
+ if (len==0) {
+ if (dump_delimiters) out_ << "<<>>";
+ } else {
+ indent+=2;
+ char *spaces=new char[indent];
+ memset(spaces, ' ', indent);
+ // spaces[indent]='\n';
+ if (dump_delimiters) out_ << "<< % " << (len/2) << " key(s)\n";
+ VALUE *p=(VALUE*)ptr, *pend=p+len;
+ while (p!=pend) {
+ out_.vi_write(spaces, indent);
+ MiniPS::dump(out_, *p++, indent);
+ out_ << " ";
+ MiniPS::dump(out_, *p++, indent);
+ /*if(p!=pend)*/ out_.vi_putcc('\n'); // out_ << "\n";
+ }
+ if (dump_delimiters) { out_.vi_write(spaces, indent-=2); out_ << ">>"; }
+ delete [] spaces;
+ }
+}
+void MiniPS::Dict::extend(ii_t newlen) {
+ if (newlen<=alloced) return;
+ ii_t newalloced=alloced;
+ assert(alloced>=0);
+ while (newlen>newalloced) newalloced<<=1;
+ VALUE *newptr=new VALUE[newalloced];
+ memcpy(newptr, ptr, len*sizeof(VALUE));
+ delete [] (VALUE*)ptr;
+ ptr=newptr;
+ alloced=newalloced;
+ /* len remains unchanged */
+}
+#endif
+
+/* --- */
+
+MiniPS::Parser::Parser(char const *filename_) {
+ FILE *ff;
+ ff=(filename_[0]=='-' && filename_[1]=='\0')? stdin: fopen(filename_, "r"); /* not "rb" */
+ if (ff==NULLP) Error::sev(Error::EERROR) << "MiniPS::Parser: cannot open file: " << FNQ(filename_) << (Error*)0;
+ f=(FILEP)ff;
+ rd=new Files::FILER(ff);
+ tok=new Tokenizer(*rd);
+ master=(Parser*)NULLP;
+ free_level=4;
+ unread=Tokenizer::NO_UNGOT;
+ depth=0;
+ specRuns=(MiniPS::Dict*)NULLP;
+ specRunsDelete=false;
+}
+MiniPS::Parser::Parser(FILEP f_) {
+ f=f_;
+ rd=new Files::FILER(PTS_align_cast(FILE*,f_));
+ tok=new Tokenizer(*rd);
+ master=(Parser*)NULLP;
+ free_level=3;
+ unread=Tokenizer::NO_UNGOT;
+ depth=0;
+ specRuns=(MiniPS::Dict*)NULLP;
+ specRunsDelete=false;
+}
+MiniPS::Parser::Parser(GenBuffer::Readable *rd_) {
+ f=(FILEP)NULLP;
+ rd=rd_;
+ tok=new Tokenizer(*rd);
+ master=(Parser*)NULLP;
+ free_level=2;
+ unread=Tokenizer::NO_UNGOT;
+ depth=0;
+ specRuns=(MiniPS::Dict*)NULLP;
+ specRunsDelete=false;
+}
+MiniPS::Parser::Parser(Tokenizer *tok_) {
+ master=(Parser*)NULLP;
+ f=(FILEP)NULLP;
+ rd=(GenBuffer::Readable*)NULLP;
+ tok=tok_;
+ master=(Parser*)NULLP;
+ free_level=0;
+ unread=Tokenizer::NO_UNGOT;
+ depth=0;
+ specRuns=(MiniPS::Dict*)NULLP;
+ specRunsDelete=false;
+}
+MiniPS::Parser::Parser(Parser *master_) {
+ f=(FILEP)NULLP;
+ rd=(GenBuffer::Readable*)NULLP;
+ tok=(Tokenizer*)NULLP;
+ master=master_;
+ free_level=1;
+ unread=Tokenizer::NO_UNGOT;
+ depth=0;
+ specRuns=(MiniPS::Dict*)NULLP;
+ specRunsDelete=false;
+}
+MiniPS::Parser::~Parser() {
+ /* We delete the master here! */
+ if (master!=NULLP) delete master; /* recursive ~Parser() call */
+ if (free_level>=2) delete tok;
+ if (free_level>=3) delete rd;
+ if (free_level>=4) fclose(PTS_align_cast(FILE*,f));
+ if (specRunsDelete) MiniPS::delete0((VALUE)specRuns);
+}
+void MiniPS::Parser::addSpecRun(char const* filename_, GenBuffer::Readable *rd_) {
+ if (specRuns==NULLP) {
+ specRunsDelete=true;
+ specRuns=new MiniPS::Dict();
+ }
+ specRuns->put(filename_, (MiniPS::VALUE)new MiniPS::Void(rd_));
+}
+void MiniPS::Parser::setSpecRuns(MiniPS::Dict *newSpecRuns) {
+ if (newSpecRuns!=specRuns) {
+ if (specRunsDelete) MiniPS::delete0((VALUE)specRuns);
+ specRunsDelete=false;
+ specRuns=newSpecRuns;
+ }
+}
+void MiniPS::Parser::setDepth(unsigned depth_) {
+ if (depth_>=MAX_DEPTH) Error::sev(Error::EERROR) << "MiniPS::Parser: `run' inclusion too deep" << (Error*)0;
+ depth=depth_;
+}
+MiniPS::VALUE MiniPS::Parser::parse1(int closer, int sev) {
+ char *beg=0; slen_t len=0; /* pacify g++-2.91 */
+ Real::metric_t metric; Real *r=0; /* pacify g++-2.91 */
+ VALUE v, w;
+ if (master!=NULLP) {
+ from_master:
+ /* vvv EOF_ALLOWED means: the master cannot close our open '>' or ']' */
+ if ((v=master->parse1(EOF_ALLOWED, sev))!=Qundef) return v;
+ MiniPS::delete0(v);
+ delete master;
+ master=(Parser*)NULLP;
+ // fprintf(stderr, "closed master\n");
+ }
+ // return parse1_real(closer);
+
+ int i=0;
+ if (unread!=Tokenizer::NO_UNGOT) {
+ i=unread;
+ unread=Tokenizer::NO_UNGOT;
+ } else i=tok->yylex();
+
+ // fprintf(stderr, "i=%d i='%c'\n", i, i);
+
+ switch (i) {
+ case Tokenizer::EOFF: case ']': case '>':
+ if (closer==i) return Qundef; /* EOF */
+ Error::sev((Error::level_t)sev) << "MiniPS::Parser: premature EOF (early closer: " << (int)i << ')' << (Error*)0;
+ return Qerror; /* parse error */
+ case '(': {
+ beg=tok->lastTokVal().bb->begin_(); len=tok->lastTokVal().bb->getLength();
+ VALUE v=(VALUE)new String(beg, len);
+ i=tok->yylex();
+ beg=tok->lastTokVal().bb->begin_(); len=tok->lastTokVal().bb->getLength();
+ if (i!='E' || len!=3 || 0!=memcmp(beg,"run",3)) { unread=i; return v; }
+ /* Process external file inclusion */
+ assert(master==NULLP);
+ /* Imp: prevent infinite recursion */
+ if (specRuns!=NULLP && Qundef!=(w=specRuns->get(RSTRING(v)->begin_(), RSTRING(v)->getLength()))) {
+ master=new Parser((GenBuffer::Readable*)RVOID(w)->getPtr());
+ } else {
+ master=new Parser(RSTRING(v)->getCstr()); /* Open external file. */
+ }
+ MiniPS::delete0(v);
+ master->setDepth(depth+1);
+ master->setSpecRuns(specRuns);
+ goto from_master;
+ }
+ case '/':
+ beg=tok->lastTokVal().bb->begin_(); len=tok->lastTokVal().bb->getLength();
+ return (VALUE)new Sname(beg, len);
+ case ':': /* Real with metric */
+ return (VALUE)tok->lastTokVal().r;
+ case '.':
+ // fprintf(stderr, "d=%g\n", tok->lastTokVal().d);
+ // fprintf(stderr, "b=(%s)\n", tok->lastTokVal().b());
+ // assert(tok->lastTokVal().bb!=NULLP);
+ // beg=tok->lastTokVal().bb->begin_(); len=tok->lastTokVal().bb->getLength();
+ // r=new Real(tok->lastTokVal().d, beg, len);
+ r=tok->lastTokVal().r;
+ i=tok->yylex();
+ beg=tok->lastTokVal().bb->begin_(); len=tok->lastTokVal().bb->getLength();
+ if (i!='E' || len!=2 || (metric=Real::str2metric(beg))==Real::ME_COUNT) {
+ unread=i;
+ } else {
+ r->setMetric(metric);
+ }
+ return (VALUE)r;
+ case '1':
+ i=tok->yylex();
+ beg=tok->lastTokVal().bb->begin_(); len=tok->lastTokVal().bb->getLength();
+ if (i!='E' || len!=2 || (metric=Real::str2metric(beg))==Real::ME_COUNT) {
+ unread=i;
+ return Qinteger(tok->lastTokVal().i);
+ } else { /* integer with metric is auto-converted to Real */
+ r=new Real(tok->lastTokVal().i, beg, len);
+ r->setMetric(metric);
+ }
+ return (VALUE)r;
+ case 'E': {
+ beg=tok->lastTokVal().bb->begin_(); len=tok->lastTokVal().bb->getLength();
+ // fprintf(stderr, "L=%d\n", bb->getLength());
+ // assert(0);
+ tok->lastTokVal().bb->term0();
+ if (0==strcmp(beg,"true")) return Qtrue;
+ if (0==strcmp(beg,"false")) return Qfalse;
+ if (0==strcmp(beg,"null")) return Qnull;
+ if (closer==EOF_ILLEGAL_POP && 0==strcmp(beg,"pop")) return Qpop;
+ Error::sev((Error::level_t)sev) << "MiniPS::Parser: unknown Ename: " << (*tok->lastTokVal().bb) << (Error*)0;
+ return Qerror;
+ }
+ case '[': {
+ Array *ap=new Array();
+ VALUE v;
+ while (Qundef!=(v=parse1(']', sev))) { if (v==Qerror) return Qerror; ap->push(v); }
+ return (VALUE)ap;
+ }
+ case '<': {
+ Dict *ap=new Dict();
+ VALUE key, val;
+ while (1) {
+ if (Qundef==(key=parse1('>', sev))) break;
+ if (key==Qerror) return Qerror;
+ if (getType(key)!=T_SNAME) {
+ MiniPS::delete0(key);
+ Error::sev(Error::EERROR) << "MiniPS::Parser: dict key must be a /name" << (Error*)0;
+ return Qerror;
+ }
+ val=parse1(EOF_ILLEGAL_POP, sev); /* No EOF allowed here */
+ if (val==Qerror) {
+ MiniPS::delete0(key);
+ return Qerror;
+ }
+ if (val!=Qpop) {
+ // if (Qundef!=ap->push(RSNAME(key)->begin_(),RSNAME(key)->getLength(),val)) Error::sev(Error::EERROR) << "MiniPS::Parser: duplicate dict key" << (Error*)0;
+ /* ^^^ should free if non-fatal error */
+ if (Qundef!=(v=ap->push(RSNAME(key)->begin_(),RSNAME(key)->getLength(),val))) {
+ Error::sev(Error::WARNING) << "MiniPS::Parser: overriding previous dict key: " << RSNAME(key)->begin_() << (Error*)0;
+ MiniPS::delete0(v);
+ }
+ }
+ MiniPS::delete0(key);
+ }
+ return (VALUE)ap;
+ }
+ default:
+ assert(0);
+ }
+ return Qerror; /* NOTREACHED */
+}
+
+void MiniPS::scanf_dict(VALUE job, bool show_warnings, ...) {
+ va_list ap;
+ Dict *dict=RDICT(job);
+ char *key;
+ unsigned ty;
+ char hex3[3];
+ VALUE default_, *dst, got;
+ if (getType(job)!=T_DICT) Error::sev(Error::EERROR) << "scanf_dict: dict expected" << (Error*)0;
+ PTS_va_start(ap, show_warnings);
+ // "InputFile", MiniPS::T_STRING, MiniPS::Qundef, &InputFile,
+ // "OutputFile", MiniPS::T_STRING, MiniPS::Qundef, &OutputFile,
+ // "Profile", MiniPS::T_ARRAY, MiniPS::Qundef, &Profiles,
+ // NULLP
+ while (NULLP!=(key=va_arg(ap, char*))) {
+ slen_t keylen=strlen(key);
+ if (*key=='/') key++;
+ ty=va_arg(ap, unsigned);
+ default_=va_arg(ap, VALUE);
+ dst=va_arg(ap, VALUE*);
+ got=(show_warnings) ? dict->get1(key,keylen) : dict->get(key,keylen);
+ if (got==Qundef) {
+ got = (ty==S_SENUM) ? RDICT(default_)->get(" ",1) /* get the default value */
+ : (ty==S_FUNC) ? ((VALUE(*)(VALUE))default_)(Qundef)
+ : default_;
+ if (got==Qundef) Error::sev(Error::EERROR) << "scanf_dict: required key missing: /" << key << (Error*)0;
+ /* type of default value is unchecked deliberately */
+ } else switch (ty) {
+ case S_RGBSTR:
+ /* Dat: red is: (\377\0\0), (#f00), (#ff0000) */
+ if (getType(got)!=T_STRING || !(
+ RSTRING(got)->getLength()==3 /* Imp: `transparent -red' shouldn't work */
+ || (RSTRING(got)->getLength()==4 && RSTRING(got)->begin_()[0]=='#' && !toHex3(RSTRING(got)->begin_()+1, hex3) && (got=(VALUE)new String(hex3, 3), true))
+ || (RSTRING(got)->getLength()==7 && RSTRING(got)->begin_()[0]=='#' && !toHex6(RSTRING(got)->begin_()+1, hex3) && (got=(VALUE)new String(hex3, 3), true))
+ || (RSTRING(got)->getLength()==6 && !toHex6(RSTRING(got)->begin_(), hex3) && (got=(VALUE)new String(hex3, 3), true))
+ )) Error::sev(Error::EERROR) << "scanf_dict: key /" << key << " must be an RGB color triplet" << (Error*)0;
+ break;
+ case S_SENUM:
+ if (getType(got)!=T_SNAME) Error::sev(Error::EERROR) << "scanf_dict: key /" << key << " must be an enum value (name)" << (Error*)0;
+ got=RDICT(default_)->get(RSNAME(got)->begin_(),RSNAME(got)->getLength());
+ if (got==Qundef) Error::sev(Error::EERROR) << "scanf_dict: key /" << key << " must be a valid enum value" << (Error*)0;
+ break;
+ case S_FUNC:
+ got=((VALUE(*)(VALUE))default_)(got);
+ if (got==Qundef) Error::sev(Error::EERROR) << "scanf_dict: key /" << key << " has invalid value" << (Error*)0;
+ break;
+ case S_UINTEGER:
+ if ((got&1)==0 || got<Qinteger(0)) Error::sev(Error::EERROR) << "scanf_dict: key /" << key << " must be a non-negative integer" << (Error*)0;
+ break;
+ case S_ANY:
+ break;
+ case S_PINTEGER:
+ if ((got&1)==0 || got<=Qinteger(0)) Error::sev(Error::EERROR) << "scanf_dict: key /" << key << " must be a positive integer" << (Error*)0;
+ break;
+ case S_NUMBER:
+ if ((got&1)==0 && getType(got)!=T_REAL) Error::sev(Error::EERROR) << "scanf_dict: key /" << key << " must be real or integer" << (Error*)0;
+ break;
+ case S_PNUMBER:
+ if ((got&1)==0 && getType(got)!=T_REAL) Error::sev(Error::EERROR) << "scanf_dict: key /" << key << " must be real or integer" << (Error*)0;
+ if (((got&1)!=0 && got<=Qinteger(0))
+ || (getType(got)==T_REAL && RREAL(got)->getBp()<=0)
+ ) Error::sev(Error::EERROR) << "scanf_dict: key /" << key << " must be positive" << (Error*)0;
+ break;
+ default:
+ if (getType(got)!=ty) Error::sev(Error::EERROR) << "scanf_dict: key /" << key << " must have type " << getTypeStr(ty) << (Error*)0;
+ }
+ *dst=got;
+ }
+ va_end(ap);
+ if (show_warnings) {
+ // VALUE *keyy, *val;
+ char const*const* keyy; slen_t keylen; VALUE *val;
+ bool touched = false; /* pacify gcc-4.2.1 by giving initial value */
+ dict->getFirst(keyy, keylen, val, touched);
+ // fprintf(stderr, "> %p\n", keyy);
+ PTS_va_start(ap, show_warnings);
+ while (keyy!=(char const*const*)NULLP) {
+ // fprintf(stderr, "untouch len=%u\n", keylen);
+ // fprintf(stderr, "untouching key=(%s)\n", *keyy);
+ if (!touched) Error::sev(Error::WARNING) << "scanf_dict: ignoring unknown key /" << SimBuffer::Static(*keyy,keylen) << (Error*)0;
+ else dict->untouch(*keyy, keylen); /* undo get1 */
+ dict->getNext(keyy, keylen, val, touched);
+ }
+ va_end(ap);
+ }
+}
+
+void MiniPS::setDumpPS(MiniPS::VALUE v, bool g) {
+ /* Sat Sep 7 13:18:35 CEST 2002 */
+ if (getType(v)==T_REAL) RREAL(v)->setDumpPS(g);
+}
+
+bool MiniPS::isZero(MiniPS::VALUE v) {
+ /* Sat Sep 7 15:12:54 CEST 2002 */
+ switch (getType(v)) {
+ case T_REAL: return RREAL(v)->getBp()==0;
+ case T_INTEGER: return int2ii(v)==0;
+ }
+ Error::sev(Error::EERROR) << "isZero: number expected" << (Error*)0;
+ return false; /* NOTREACHED */
+}
+
+bool MiniPS::isEq(MiniPS::VALUE v, double d) {
+ double dif=0;
+ switch (getType(v)) {
+ case T_REAL: dif=RREAL(v)->getBp()-d; break;
+ case T_INTEGER: dif=int2ii(v)-d; break;
+ default: Error::sev(Error::EERROR) << "isEq: number expected" << (Error*)0;
+ }
+ if (dif<0.0) dif=-dif;
+ /* fprintf(stderr,"dif=%g g=%d\n", dif, (dif<0.000001)); */
+ return (dif<0.000001); /* Imp: ... */
+}
+
+void MiniPS::dumpScale(GenBuffer::Writable &out, VALUE v) {
+ double d=0;
+ ii_t ii;
+ switch (getType(v)) {
+ case T_REAL: d = RREAL(v)->getBp(); break;
+ case T_INTEGER: d = int2ii(v); break;
+ default: Error::sev(Error::EERROR) << "dumpScale: number expected" << (Error*)0;
+ }
+ if (d == -72.0) d = 72.0;
+ ii = (ii_t)d / 72 * 72;
+ if (d >= 0 && ii == d) { /* accurate nonnegative integer divisible by 72 */
+ out << (ii / 72);
+ } else if (d < 0 && d == (ii_t)d && 72 % -(ii_t)d == 0) {
+ out << (72 / -(ii_t)d);
+ } else {
+ d = d < 0 ? 72.0 / -d : d / 72.0;
+ char buf[64]; /* Dat: enough */
+ sprintf(buf, "%" PTS_CFG_PRINTFGLEN "g", d);
+ out << buf;
+ }
+}
+
+void MiniPS::dumpAdd3(GenBuffer::Writable &out, MiniPS::VALUE m, MiniPS::VALUE a, MiniPS::VALUE b, MiniPS::VALUE c, MiniPS::VALUE sub, unsigned rounding) {
+ long ll;
+ /* Sat Sep 7 15:30:28 CEST 2002 */
+ bool no_real_real=true;
+ double d=0, dd;
+ long l=0;
+ if ((getType(m)==T_REAL && (isEq(m, 72) || isEq(m, -72))) || /* Imp: not so exact comparison */
+ (getType(m)==T_INTEGER && isEq(m, -72)))
+ m = Qinteger(72);
+ MiniPS::VALUE t[5], *tt;
+ t[0]=a; t[1]=m; t[2]=b; t[3]=c; t[4]=sub;
+ for (tt=t;tt<t+5;tt++) switch (getType(*tt)) {
+ case T_REAL:
+ dd=RREAL(*tt)->getBp();
+ doadd:
+ if (no_real_real) {
+ d=l;
+ no_real_real=false;
+ }
+ if (tt==t+1) { /* multiply by m/72 or 72/-m */
+ if (dd==0.0 || d==0.0) { no_real_real=true; l=0; d=0.0; }
+ else d *= dd >= 0 ? dd / 72 : 72 / -dd;
+ } else if (tt==t+4) d-=dd;
+ else d+=dd;
+ break;
+ case T_INTEGER:
+ ll=int2ii(*tt);
+ if (tt==t+1) { /* multiply by m/72 or 72/-m */
+ if (ll >= 0 && ll % 72 == 0) l *= ll / 72;
+ else if (ll < 0 && 72 % -ll == 0) l *= 72 / -ll;
+ else { dd=ll; goto doadd; }
+ } else if (tt==t+4) l-=ll;
+ else l+=ll;
+ break;
+ default: Error::sev(Error::EERROR) << "dumpAdd3: numbers expected" << (Error*)0;
+ }
+ if (no_real_real) { out << l; return; }
+ if (rounding!=0) {
+ ll=(long)d;
+ if ((double)ll<d) ll++;
+ assert((double)ll>=d); /* Imp: verify possible rounding errors */
+ out << (rounding>=2 && ll<0 ? 0 : ll);
+ } else {
+ char buf[64]; /* Dat: enough */
+ sprintf(buf, "%" PTS_CFG_PRINTFGLEN "g", d);
+ out << buf;
+ }
+}
+
+/* __END__ */
diff --git a/graphics/sam2p/minips.hpp b/graphics/sam2p/minips.hpp
new file mode 100644
index 0000000000..47a3f0d499
--- /dev/null
+++ b/graphics/sam2p/minips.hpp
@@ -0,0 +1,334 @@
+/* minips.hpp -- mini-PostScript parser and structure builder
+ * by pts@fazekas.hu at Sat Mar 9 21:33:04 CET 2002
+ */
+
+#ifdef __GNUC__
+#ifndef __clang__
+#pragma interface
+#endif
+#endif
+
+#ifndef MINIPS_HPP
+#define MINIPS_HPP 1
+
+#include "config2.h"
+#include "gensi.hpp"
+#include "error.hpp"
+
+class MiniPS {
+ public:
+ #if SIZEOF_VOID_P <= SIZEOF_INT
+ typedef signed int ii_t;
+ #elif SIZEOF_VOID_P <= SIZEOF_LONG
+ typedef signed long ii_t;
+ #elif SIZEOF_VOID_P <= SIZEOF_CFG_LONGEST
+ typedef signed PTS_CFG_LONGEST ii_t;
+ #else
+ #error No integral data type to hold a ptr.
+ #endif
+
+ class Real;
+
+ /*union*/ struct TokVal {
+ SimBuffer::B *bb;
+ ii_t i;
+ /* double d; */
+ /*MiniPS::*/Real *r;
+ };
+ /** minips tokenizer */
+ class Tokenizer {
+ public:
+ BEGIN_STATIC_ENUM1(int) EOFF=-1, NO_UNGOT=-2 END_STATIC_ENUM()
+ Tokenizer(GenBuffer::Readable& in_);
+ /** Reads and returns next token.
+ * Token types are named for their first character:
+ * '1': integertype: 31 bits signed (-1073741824 .. 1073741823) is
+ * guaranteed. VALUED
+ * '.': realtype (NOT implemented), double guaranteed. VALUED
+ * 'E': Ename (name without a slash). VALUED
+ * '/': Sname (name beginning with a slash). VALUED
+ * '(': stringtype (also with `<hexadecimal>') VALUED
+ * '[': beginning-of-array (also with `{')
+ * ']': end-of-array (also with '}')
+ * '<': beginning-of-dict (`<<')
+ * '>': end-of-dict (`>>')
+ * -1: EOF
+ */
+ int yylex();
+ inline TokVal const& lastTokVal() const { return tv; }
+ protected:
+ /** Data for last token read. */
+ TokVal tv;
+ SimBuffer::B b;
+ GenBuffer::Readable& in;
+ /* NO_UNGOT for nothing, EOFF for EOF, 0..255 otherwise */
+ int ungot;
+ };
+
+ /* This is somewhat similar to Ruby */
+ typedef ii_t VALUE;
+ /** Qundef is the undefined hash key or array elements. It is an _invalid_ VALUE! */
+ BEGIN_STATIC_ENUM1(VALUE) Qfalse=0, Qtrue=2, Qnull=4, Qundef=6, Qpop=8, Qerror=10, Qmax_=10 END_STATIC_ENUM()
+
+ BEGIN_STATIC_ENUM1(unsigned) T_NULL=1, T_BOOLEAN=2, T_INTEGER=3, T_REAL=4,
+ T_STRING=5, T_ARRAY=6, T_DICT=7, T_SNAME=8, T_ENAME=9, T_VOID=10,
+ S_SENUM=20, /* must be a dict-member; meta-type used by scanf_dict() */
+ S_FUNC=21, /* call a function to determine; meta-type used by scanf_dict() */
+ S_UINTEGER=22, /* non-negative integer; meta-type used by scanf_dict() */
+ S_ANY=23, /* anything; meta-type used by scanf_dict() */
+ S_PINTEGER=24, /* positive integer; meta-type used by scanf_dict() */
+ S_RGBSTR=25, /* an optional 3-byte string, representing an RGB color triplet */
+ S_NUMBER=26, /* real or integer */
+ S_PNUMBER=27 /* positive real or integer */
+ END_STATIC_ENUM()
+
+ /** No virtual methods because of special types. MiniPS composite values
+ * really _contain_ their components; one Value has exactly one reference:
+ * its container component.
+ */
+ class Value { public:
+ inline ii_t getLength() const { return len; }
+ inline ii_t getType() const { return ty; }
+ inline bool hasPtr() const { return ptr!=NULLP; }
+ inline bool isDumping() const { return dumping; }
+ inline char const* getCstr() const { return (char const*)ptr; }
+ inline char* begin_() const { return (char*)ptr; }
+ inline char const* operator()() const { return (char const*)ptr; }
+ protected:
+ ii_t len;
+ void *ptr; /* Will be freed by MiniPS::delete0() except for Void. */
+ unsigned char ty;
+ bool dumping;
+ };
+ /** ptr contains a `void*'. Won't be freed by MiniPS::delete0(). */
+ class Void: public Value { public:
+ inline Void(void *ptr_) { ptr=ptr_; ty=T_VOID; }
+ inline void *getPtr() const { return ptr; }
+ };
+ /** Always null-terminated. */
+ class String: public Value { public:
+ /** Copies from ptr_ */
+ String(char const*ptr_, ii_t len_);
+ /** Replaces (this) with a copy of (a).(b) */
+ void replace(char const*ap, slen_t alen, char const*bp, slen_t blen);
+ };
+ class Sname: public Value { public:
+ /** ptr_ must begin with '/' */
+ Sname(char const*ptr_, ii_t len_);
+ bool equals(Sname const&other);
+ bool equals(char const*other);
+ };
+ class Ename: public Value { public:
+ Ename(char const*ptr_, ii_t len_);
+ bool equals(Ename const&other);
+ bool equals(char const*other);
+ bool equals(char const*other, slen_t otherlen);
+ };
+ class Real: public Value { public:
+ typedef unsigned char metric_t;
+ inline Real(double d_): d(d_), metric(0), dumpPS(false) { ty=T_REAL; ptr=(char*)NULLP; }
+ /** Also supply a string representation of the value (to avoid possible
+ * loss of precision when converting string -> double -> string).
+ */
+ Real(double d_, char const*ptr_, ii_t len_);
+ // inline bool isZero() const { return d==0.0; }
+ inline double getBp() const { return d*me_factor[metric]; }
+ inline void setDumpPS(bool g) { dumpPS=g; }
+ inline void setMetric(metric_t metric_) { metric=metric_; }
+ /** Return true iff the specified null-terminated string is a valid
+ * dimen.
+ */
+ static bool isDimen(char const *);
+ void dump(GenBuffer::Writable &out_, bool dumpPS_force=false);
+ /** @return ME_count on invalid */
+ static metric_t str2metric(char const str[2]);
+ BEGIN_STATIC_ENUM1(metric_t)
+ ME_bp=0, /* 1 bp = 1 bp (big point) */
+ ME_in=1, /* 1 in = 72 bp (inch) */
+ ME_pt=2, /* 1 pt = 72/72.27 bp (point) */
+ ME_pc=3, /* 1 pc = 12*72/72.27 bp (pica) */
+ ME_dd=4, /* 1 dd = 1238/1157*72/72.27 bp (didot point) [about 1.06601110141206 bp] */
+ ME_cc=5, /* 1 cc = 12*1238/1157*72/72.27 bp (cicero) */
+ ME_sp=6, /* 1 sp = 72/72.27/65536 bp (scaled point) */
+ ME_cm=7, /* 1 cm = 72/2.54 bp (centimeter) */
+ ME_mm=8, /* 1 mm = 7.2/2.54 bp (millimeter) */
+ ME_COUNT=9
+ END_STATIC_ENUM()
+ protected:
+ double d;
+ /* vvv metric added at Sat Sep 7 12:26:08 CEST 2002 */
+ metric_t metric;
+ /** Allow PostScript operators such as `div' to appear in the dump */
+ bool dumpPS;
+ /** Factor to convert to bp */
+ static const double me_factor[ME_COUNT];
+ /** PostScript code to do multiplication by me_factor */
+ static char const* const me_psfactor[ME_COUNT];
+ };
+ class Array: public Value { public:
+ Array();
+ void free();
+ void dump(GenBuffer::Writable &out_, unsigned indent);
+ void push(VALUE v);
+ VALUE get(ii_t index);
+ /** Cannot extend. Calls delete0() when overwriting an element */
+ void set(ii_t index, VALUE val);
+ /** val: out */
+ void getFirst(VALUE *&val);
+ /** val: in_out */
+ void getNext(VALUE *&val);
+ protected:
+ ii_t alloced;
+ void extend(ii_t newlen);
+ };
+ /** Keys must be Snames here! (i.e no integer keys allowed). The current
+ * implementation does a linear string search :-(. Dat: might not work
+ * on extremely long keys if slen_t can hold a larger integer than
+ * ii_t.
+ */
+ class Dict: public Value { public:
+ Dict();
+ void free();
+ void dump(GenBuffer::Writable &out_, unsigned indent, bool dump_delimiters=true);
+ /** @return val or Qundef */
+ VALUE get(char const*key, slen_t keylen);
+ /** A hack: get and touch. */
+ VALUE get1(char const*key, slen_t keylen);
+ void untouch(char const*key, slen_t keylen);
+ /** Can extend. */
+ void put(char const*key, VALUE val);
+ /** Calls delete0() when overwriting an element */
+ void put(char const*key, slen_t keylen, VALUE val);
+ /** @return old value for key `key', or Qundef */
+ VALUE push(char const*key, slen_t keylen, VALUE val);
+ /** key: out, val: out */
+ void getFirst(char const*const*& key, slen_t &keylen, VALUE *&val, bool &touched);
+ /** key: in_out, val: in_out */
+ void getNext (char const*const*& key, slen_t &keylen, VALUE *&val, bool &touched);
+ // void getFirst(VALUE *&key, VALUE *&val);
+ // void getNext(VALUE *&key, VALUE *&val);
+ protected:
+ ii_t alloced;
+ void extend(ii_t newlen);
+ };
+
+ static inline Value* RVALUE(VALUE v) { return static_cast<Value*>((void*)v); }
+ static inline Void* RVOID(VALUE v) { return static_cast<Void*>((void*)v); }
+ static inline Array* RARRAY(VALUE v) { return static_cast<Array*>((void*)v); }
+ static inline String* RSTRING(VALUE v){ return static_cast<String*>((void*)v); }
+ static inline Dict* RDICT(VALUE v) { return static_cast<Dict*>((void*)v); }
+ static inline Real* RREAL(VALUE v) { return static_cast<Real*>((void*)v); }
+ static inline Sname* RSNAME(VALUE v) { return static_cast<Sname*>((void*)v); }
+ static inline Ename* RENAME(VALUE v) { return static_cast<Ename*>((void*)v); }
+ static inline bool isDirect(VALUE v) { return (v&1)!=0 || v<=Qmax_; }
+ /** T_NULL .. T_DICT */
+ static unsigned getType(VALUE v);
+ /** "null" .. "dict", "name" (T_SNAME), "ename" (T_ENAME, non-std-PS) */
+ static char const* getTypeStr(unsigned u);
+ static void delete0(VALUE v);
+ /** The current implementation dumps dict keys in order of insertion, but
+ * this is very likely to change soon to an _arbitrary_ order.
+ */
+ static void dump(GenBuffer::Writable& out_, VALUE v, unsigned indent=0);
+ static void dump(VALUE v, unsigned indent=0);
+ static inline VALUE Qinteger(ii_t v) { return (v<<1)+1; }
+ static inline ii_t int2ii(VALUE v) { return v>>1; }
+ /** Fortunate coincidence that 2x+1>0 <=> x>0 */
+ static inline bool isPositive(VALUE v) { return v>0; }
+ static inline VALUE undef2null(VALUE v) { return v==Qundef ? Qnull : v; }
+ // static SimBuffer::B scale72(VALUE v, double d);
+
+ class Parser {
+ /** Define this to avoid including <stdio.h> */
+ typedef class _anon_filet_ {} *FILEP;
+ public:
+ BEGIN_STATIC_ENUM1(int) EOF_ALLOWED=Tokenizer::EOFF, EOF_ILLEGAL=-2, EOF_ILLEGAL_POP=-3 END_STATIC_ENUM()
+ /** Maximum depth of `run' file inclusions. */
+ BEGIN_STATIC_ENUM1(unsigned) MAX_DEPTH=17 END_STATIC_ENUM()
+ Parser(char const *filename_);
+ /** The caller is responsible for closing the FILE* */
+ Parser(FILEP f_);
+ Parser(GenBuffer::Readable *rd_);
+ Parser(Tokenizer *tok_);
+ ~Parser();
+ /** Allocates and returns. Qundef is returned on EOF
+ * @param closer: EOF_ILLEGAL, EOF_ALLOWED, '>' or ']'
+ */
+ VALUE parse1(int closer=EOF_ILLEGAL, int sev=Error::EERROR);
+ void setDepth(unsigned depth_);
+ /** Sets special filename for the `run' operator. `run' will read that
+ * special file from param `rd_', and then it will call rd_->vi_rewind().
+ * Example usage: .addSpecRun("%stdin", new Files::FileR(stdin));
+ */
+ void addSpecRun(char const* filename_, GenBuffer::Readable *rd_);
+ /*MiniPS::*/Dict *getSpecRuns() const { return specRuns; }
+ /** Does not copy the dict, but sets the pointer. */
+ void setSpecRuns(/*MiniPS::*/Dict *);
+ protected:
+ Parser(Parser *master_);
+ // VALUE parse1_real(int closer);
+ /* 0=nothing, 1=master 2=tok, 3=tok+rd, 4=tok+rd+f */
+ unsigned free_level;
+ Parser *master;
+ Tokenizer *tok;
+ GenBuffer::Readable *rd;
+ FILEP f;
+ int unread;
+ unsigned depth;
+ /*MiniPS::*/Dict *specRuns;
+ /** Should MiniPS::delete0() be called on specRuns upon destruction of
+ * (this)?
+ */
+ bool specRunsDelete;
+ };
+
+ /** Assumes that param `job' is a dict, extracts its elements into ...,
+ * emits errors for elements (not found and having default==Qundef), emits
+ * warnings for elements found in `job', but undescribed in `...' (only
+ * if show_warnings==true). Example:
+ *
+ * MiniPS::scanf_dict(job, true,
+ * "InputFile", MiniPS::T_STRING, MiniPS::Qundef, &InputFile,
+ * "OutputFile", MiniPS::T_STRING, MiniPS::Qundef, &OutputFile,
+ * "Profiles", MiniPS::T_ARRAY, MiniPS::Qundef, &Profiles
+ * NULLP
+ * );
+ */
+ static void scanf_dict(VALUE job, bool show_warnings, ...);
+ static void setDumpPS(VALUE v, bool g);
+ /** @param v must be T_REAL or T_INTEGER */
+ static bool isZero(VALUE v);
+ /** @param v must be T_REAL or T_INTEGER
+ * @return true iff v==i
+ */
+ static bool isEq(VALUE v, double d);
+ /** Dumps the human-readable real or integer value of the sum
+ * (mscale/72)*a+b+c-sub to `out'.
+ * @param rounding 0: nothing. 1: round the sum _up_ to integers. 2:
+ * round the sum _up_ to non-negative integers
+ * @param m must be T_REAL or T_INTEGER. mscale = m/72 if m is positive,
+ * or 72/m if m is negative.
+ * @param a must be T_REAL or T_INTEGER
+ * @param b must be T_REAL or T_INTEGER
+ * @param c must be T_REAL or T_INTEGER
+ * @param sub must be T_REAL or T_INTEGER
+ */
+ static void dumpAdd3(GenBuffer::Writable &out, VALUE m, VALUE a, VALUE b, VALUE c, VALUE sub, unsigned rounding=0);
+ static void dumpScale(GenBuffer::Writable &out, VALUE v);
+};
+
+/* Fri Aug 16 17:07:14 CEST 2002 */
+#if 0 /* doesn't work because MiniPS::VALUE is really an `int', so there will be an ambiguous overload */
+inline GenBuffer::Writable& operator<<(GenBuffer::Writable& out_, MiniPS::VALUE v) {
+ MiniPS::dump(out_, v);
+ return out_;
+}
+#endif
+inline GenBuffer::Writable& operator<<(GenBuffer::Writable& out_, MiniPS::Value *v) {
+ MiniPS::dump(out_, (MiniPS::VALUE)v);
+ return out_;
+}
+
+// GenBuffer::Writable& operator<<(GenBuffer::Writable& out_, MiniPS::Value *v) {
+
+#endif
diff --git a/graphics/sam2p/mkdist.sh b/graphics/sam2p/mkdist.sh
new file mode 100755
index 0000000000..8394148bea
--- /dev/null
+++ b/graphics/sam2p/mkdist.sh
@@ -0,0 +1,102 @@
+#! /bin/bash --
+#
+# mkdist.sh by pts@fazekas.hu at Wed Mar 6 09:09:01 CET 2002
+# added debian/changelog support at Fri Mar 5 19:37:45 CET 2004
+# added libevhdns Makefile.in support at Sun Apr 25 12:24:43 CEST 2010
+# based on mkdist.sh of autotrace
+#
+
+if test "$1" = --cd; then
+ MYDIR="${0%/*}"
+ test "$MYDIR" || MYDIR=.
+ cd "$MYDIR"
+fi
+
+# Get the release version number.
+if test -f debian/changelog; then
+ # PRODUCT_AND_VERSION=$PRODUCT-$VERSION
+ PRODUCT_AND_VERSION="`<debian/changelog perl -ne 'print"$1-$2"if/^(\S+) +[(]([-.\w]+?)(?:-\d+)?[)] +\w+;/;last'`"
+ if test "$PRODUCT_AND_VERSION"; then :; else
+ echo "$0: couldn't determine version from debian/changelog" >&2
+ exit 4
+ fi
+elif test -f Makefile.in && grep '^product-and-version:' <Makefile.in >/dev/null; then
+ PRODUCT_AND_VERSION="`make SHELL=/bin/bash -f Makefile.in product-and-version`"
+ if test "$?" != 0 || test -z "$PRODUCT_AND_VERSION"; then
+ echo "$0: couldn't determine version from Makefile.in" >&2
+ exit 7
+ fi
+else
+ echo "$0: missing: debian/changelog or RELEASE= in Makefile.in" >&2
+ exit 2
+fi
+
+if test "$1" = --getversion; then
+ echo "${PRODUCT_AND_VERSION##*-}"
+ exit
+fi
+
+echo "Creating distfile in $PWD"
+
+# Get the list of files.
+if test -f files; then
+ FILES="`cat files`"
+elif test -d CVS; then
+ FILES=$( IFS='
+'
+ find -type d -name CVS | while read D; do
+ F="$D/Entries"
+ export E="${D%/CVS}/"
+ E="${E#./}"
+ perl -ne 'print"$ENV{E}$1\n"if m@^/([^/]+)/[1-9]@' <"$F"
+ done)
+else
+ echo "$0: missing: files or **/CVS/Entries" >&2
+ exit 3
+fi
+
+
+if test -e "$PRODUCT_AND_VERSION"; then
+ echo "$0: directory $PRODUCT_AND_VERSION already exists, remove it first" >&2
+ exit 5
+fi
+
+if test $# -gt 0; then
+ TGZ_NAME="$1.tar.gz"; shift
+else
+ TGZ_NAME="$PRODUCT_AND_VERSION.tar.gz"
+fi
+
+set -e # exit on error
+rm -f "../$TGZ_NAME"
+mkdir "$PRODUCT_AND_VERSION"
+(IFS='
+'; exec tar -c -- $FILES "$@") |
+(cd "$PRODUCT_AND_VERSION" && exec tar -xv)
+# ^^^ tar(1) magically calls mkdir(2) etc.
+
+# vvv Dat: don't include sam2p-.../ in the filenames of the .tar.gz
+#(IFS='
+#'; cd "$PRODUCT_AND_VERSION" && exec tar -czf "../../$TGZ_NAME" -- $FILES "$@")
+
+# vvv Dat: do include sam2p-.../ in the filenames of the .tar.gz
+(IFS='
+'; export PRODUCT_AND_VERSION; exec tar -czf "../$TGZ_NAME" -- `echo "$FILES" | perl -pe '$_="$ENV{PRODUCT_AND_VERSION}/$_"'` "$@")
+
+rm -rf "$PRODUCT_AND_VERSION"
+set +e
+
+if test -s "../$TGZ_NAME"; then :; else
+ echo "$0: failed to create distfile: ../$TGZ_NAME" >&2
+ exit 6
+fi
+
+FULL_TGZ_NAME="`cd ..;echo "$PWD/$TGZ_NAME"`"
+echo "Created distfile: $FULL_TGZ_NAME"
+if type -p pts-xclip >/dev/null; then
+ echo -n "$FULL_TGZ_NAME" | pts-xclip -i
+ echo -n "$FULL_TGZ_NAME" | pts-xclip -i -selection clipboard
+ echo "Name of distfile added to the X11 primary + clipboard."
+fi
+
+# __EOF__
diff --git a/graphics/sam2p/out_gif.cpp b/graphics/sam2p/out_gif.cpp
new file mode 100644
index 0000000000..522242174f
--- /dev/null
+++ b/graphics/sam2p/out_gif.cpp
@@ -0,0 +1,341 @@
+/* out_gif.cpp
+ * by pts@fazekas.hu at Sat Mar 23 11:02:36 CET 2002
+ */
+
+#include "image.hpp"
+
+#if USE_OUT_GIF
+#include <string.h>
+#include <stdio.h>
+
+/**** pts ****/
+#ifdef __cplusplus
+# define AALLOC(var,len,itemtype) var=new itemtype[len]
+# define AFREE(expr) delete [] (expr)
+#else
+# include <stdlib.h> /* malloc(), free() */
+# define AALLOC(var,len,itemtype) var=(itemtype*)malloc(len*sizeof(itemtype));
+# define AFREE(expr) free((expr))
+#endif
+#define HasLZW HAVE_LZW /* Imp: or USE_BUILTIN_LZW? */
+#define True true
+#define False false
+
+/* The code of GIFEncodeImage is based on an early version of ImageMagick. */
+static unsigned int GIFEncodeImage(GenBuffer::Writable& out, char const*ppbeg, register char const*ppend, const unsigned int data_size)
+{
+#define MaxCode(number_bits) ((1 << (number_bits))-1)
+#define MaxHashTable 5003
+#define MaxGIFBits 12
+#if defined(HasLZW)
+#define MaxGIFTable (1 << MaxGIFBits)
+#else
+#define MaxGIFTable max_code
+#endif
+#define GIFOutputCode(code) \
+{ \
+ /* \
+ Emit a code. \
+ */ \
+ if (bits > 0) \
+ datum|=((long) code << bits); \
+ else \
+ datum=(long) code; \
+ bits+=number_bits; \
+ while (bits >= 8) \
+ { \
+ /* \
+ Add a character to current packet. \
+ */ \
+ packet[byte_count++]=(unsigned char) (datum & 0xff); \
+ if (byte_count >= 254) \
+ { \
+ packet[-1]=byte_count; \
+ out.vi_write((char*)packet-1, byte_count+1); \
+ byte_count=0; \
+ } \
+ datum>>=8; \
+ bits-=8; \
+ } \
+ if (free_code > max_code) \
+ { \
+ number_bits++; \
+ if (number_bits == MaxGIFBits) \
+ max_code=MaxGIFTable; \
+ else \
+ max_code=MaxCode(number_bits); \
+ } \
+}
+
+ int
+ bits,
+ byte_count,
+ i,
+ next_pixel,
+ number_bits;
+
+ long
+ datum;
+
+ register int
+ displacement,
+ k;
+
+ register char const*pp;
+
+ short
+ clear_code,
+ end_of_information_code,
+ free_code,
+ *hash_code,
+ *hash_prefix,
+ index,
+ max_code,
+ waiting_code;
+
+ unsigned char
+ *packet,
+ *hash_suffix;
+
+ /*
+ Allocate encoder tables.
+ */
+ AALLOC(packet,257,unsigned char);
+ AALLOC(hash_code,MaxHashTable,short);
+ AALLOC(hash_prefix,MaxHashTable,short);
+ AALLOC(hash_suffix,MaxHashTable,unsigned char);
+ if ((packet == (unsigned char *) NULL) || (hash_code == (short *) NULL) ||
+ (hash_prefix == (short *) NULL) ||
+ (hash_suffix == (unsigned char *) NULL))
+ return(False);
+ packet++;
+ /* Now: packet-1 == place for byte_count */
+ /*
+ Initialize GIF encoder.
+ */
+ number_bits=data_size;
+ max_code=MaxCode(number_bits);
+ clear_code=((short) 1 << (data_size-1));
+ end_of_information_code=clear_code+1;
+ free_code=clear_code+2;
+ byte_count=0;
+ datum=0;
+ bits=0;
+ for (i=0; i < MaxHashTable; i++)
+ hash_code[i]=0;
+ GIFOutputCode(clear_code);
+ /*
+ Encode pixels.
+ */
+ /**** pts ****/
+ pp=ppbeg;
+ waiting_code=*(unsigned char const*)pp++; /* unsigned char BUGFIX at Sun Dec 8 13:17:00 CET 2002 */
+
+ while (pp!=ppend) {
+ /*
+ Probe hash table.
+ */
+ index=*(unsigned char const*)pp++;
+ k=(int) ((int) index << (MaxGIFBits-8))+waiting_code;
+ if (k >= MaxHashTable)
+ k-=MaxHashTable;
+#if defined(HasLZW)
+ if (hash_code[k] > 0)
+ {
+ if ((hash_prefix[k] == waiting_code) && (hash_suffix[k] == index))
+ {
+ waiting_code=hash_code[k];
+ continue;
+ }
+ if (k == 0)
+ displacement=1;
+ else
+ displacement=MaxHashTable-k;
+ next_pixel=False;
+ for ( ; ; )
+ {
+ k-=displacement;
+ if (k < 0)
+ k+=MaxHashTable;
+ if (hash_code[k] == 0)
+ break;
+ if ((hash_prefix[k] == waiting_code) && (hash_suffix[k] == index))
+ {
+ waiting_code=hash_code[k];
+ next_pixel=True;
+ break;
+ }
+ }
+ if (next_pixel != False) /* pacify VC6.0 */
+ continue;
+ }
+#endif
+ GIFOutputCode(waiting_code);
+ // printf("wc=%u\n", waiting_code);
+ if (free_code < MaxGIFTable)
+ {
+ hash_code[k]=free_code++;
+ hash_prefix[k]=waiting_code;
+ hash_suffix[k]=index;
+ }
+ else
+ {
+ /*
+ Fill the hash table with empty entries.
+ */
+ for (k=0; k < MaxHashTable; k++)
+ hash_code[k]=0;
+ /*
+ Reset compressor and issue a clear code.
+ */
+ free_code=clear_code+2;
+ GIFOutputCode(clear_code);
+ number_bits=data_size;
+ max_code=MaxCode(number_bits);
+ }
+ waiting_code=index;
+#if 0 /**** pts ****/
+ if (QuantumTick(i,image) && (image->previous == (Image2 *) NULL))
+ ProgressMonitor(SaveImageText,i,image->packets);
+#endif
+ }
+ /*
+ Flush out the buffered code.
+ */
+ GIFOutputCode(waiting_code);
+ GIFOutputCode(end_of_information_code);
+ if (bits > 0)
+ {
+ /*
+ Add a character to current packet.
+ */
+ packet[byte_count++]=(unsigned char) (datum & 0xff);
+ if (byte_count >= 254)
+ {
+ packet[-1]=byte_count;
+ out.vi_write((char*)packet-1, byte_count+1);
+ byte_count=0;
+ }
+ }
+ /*
+ Flush accumulated data.
+ */
+ if (byte_count > 0)
+ {
+ packet[-1]=byte_count;
+ out.vi_write((char*)packet-1, byte_count+1);
+ }
+ /*
+ Free encoder memory.
+ */
+ AFREE(hash_suffix);
+ AFREE(hash_prefix);
+ AFREE(hash_code);
+ AFREE(packet-1);
+ return pp==ppend;
+}
+
+/** This isn't a complete GIF writer. For example, it doesn't support
+ * animation or multiple sub-images. But it supports transparency and
+ * compression. Only works when . The user should call
+ * packPal() first to ensure img->getBpc()==8, and to get a minimal palette.
+ */
+void out_gif_write(GenBuffer::Writable& out, Image::Indexed *img) {
+ /* Tested and proven to work at Sat Mar 23 13:11:41 CET 2002 */
+ unsigned i, c, bits_per_pixel;
+ signed transp;
+ char hd[19];
+
+ assert(img->getBpc()==8); /* 1 palette entry == 8 bits */
+
+ transp=img->getTransp();
+ memcpy(hd, transp!=-1 ? "GIF89a" : "GIF87a", 6);
+ i=img->getWd(); hd[6]=i; hd[7]=i>>8;
+ i=img->getHt(); hd[8]=i; hd[9]=i>>8;
+
+ // transp=-1; /* With this, transparency will be ignored */
+ c=img->getNcols();
+ bits_per_pixel=1; while (((c-1)>>bits_per_pixel)!=0) bits_per_pixel++;
+ /* ^^^ (c-1) BUGFIX at Mon Oct 20 15:18:24 CEST 2003 */
+ /* 63 -> 6, 64 -> 6, 65 -> 7 */
+ // if (bits_per_pixel>1) bits_per_pixel--; /* BUGFIX at Wed Apr 30 15:55:27 CEST 2003 */ /* BUGFIX at Mon Oct 20 15:18:14 CEST 2003 */
+ // fprintf(stderr, "GIF89 write transp=%d ncols=%d bpp=%d\n", transp, c, bits_per_pixel);
+ assert(1<=bits_per_pixel && bits_per_pixel<=8);
+ c=3*((1<<bits_per_pixel)-c);
+ /* Now: c is the number of padding bytes */
+
+ hd[10]= 0x80 /* have global colormap */
+ | ((8-1) << 4) /* color resolution: bpc==8 */
+ | (bits_per_pixel-1); /* size of global colormap */
+ hd[11]=0; /* background color: currently unused */
+ hd[12]=0; /* reversed */
+ out.vi_write(hd, 13);
+
+ // out.vi_write("\xFF\x00\x00" "\x00\xFF\x00" "\x00\x00\xFF", 9);
+
+ out.vi_write(img->getHeadp(), img->getRowbeg()-img->getHeadp()); /* write colormap */
+ if (c!=0) {
+ char *padding=new char[(unsigned char)c]; /* BUGFIX at Fri Oct 17 18:05:09 CEST 2003 */
+ memset(padding, '\0', (unsigned char)c); /* Not automatic! */
+ out.vi_write(padding, (unsigned char)c);
+ delete [] padding;
+ }
+
+ if (transp!=-1) {
+ /* Write Graphics Control extension. Only GIF89a */
+ hd[0]=0x21; hd[1]=(char)0xf9; hd[2]=0x04;
+ hd[3]=transp!=-1; /* dispose==0 */
+ hd[4]=hd[5]=0; /* delay==0 */
+ hd[6]=transp; /* transparent color index -- or 255 */
+ hd[7]=0;
+ out.vi_write(hd, 8);
+ }
+
+ /* Write image header */
+ hd[8]=',';
+ hd[ 9]=hd[10]=0; /* left */
+ hd[11]=hd[12]=0; /* top */
+ i=img->getWd(); hd[13]=i; hd[14]=i>>8;
+ i=img->getHt(); hd[15]=i; hd[16]=i>>8;
+ hd[17]=0; /* no interlace, no local colormap, no bits in local colormap */
+
+ if ((c=bits_per_pixel)<2) c=4;
+ hd[18]=c; /* compression bits_per_pixel */
+ out.vi_write(hd+8, 11);
+
+#if 0
+ printf("GIFEncodeImage out r r+%u %u; off=%u\n", img->getRlen()*img->getHt(), c+1, img->getRowbeg()-img->getHeadp());
+ FILE *f=fopen("tjo.dat","wb");
+ fprintf(f, "P6 %u %u 255\n", img->getWd(), img->getHt());
+ // fwrite(img->getRowbeg(), 1, img->getRlen()*img->getHt(), f);
+ for (unsigned u=0; u<img->getRlen()*img->getHt(); u++) {
+ char *p=img->getHeadp()+3* *(unsigned char*)(img->getRowbeg()+u);
+ putc(p[0],f);
+ putc(p[1],f);
+ putc(p[2],f);
+ }
+#endif
+
+ i=GIFEncodeImage(out, img->getRowbeg(), img->getRowbeg()+img->getRlen()*img->getHt(), c+1);
+#if 0
+ { char buf[500000];
+ FILE *f=fopen("tjo.dat","rb");
+ int got=fread(buf, 1, sizeof(buf), f);
+ assert(got==486109);
+ assert(got==img->getRlen()*img->getHt());
+ i=GIFEncodeImage(out, buf, buf+img->getRlen()*img->getHt(), c+1);
+ }
+#endif
+ assert(i!=0);
+
+ /* Write trailer */
+ hd[0]=0; hd[1]=';';
+ out.vi_write(hd, 2);
+}
+#else
+#include <stdlib.h>
+void out_gif_write(GenBuffer::Writable&, Image::Indexed *) {
+ assert(0);
+ abort();
+}
+#endif
diff --git a/graphics/sam2p/ps_tiny.c b/graphics/sam2p/ps_tiny.c
new file mode 100644
index 0000000000..615eb287d4
--- /dev/null
+++ b/graphics/sam2p/ps_tiny.c
@@ -0,0 +1,874 @@
+#define DUMMY \
+set -ex; \
+gcc -O3 -s -DNDEBUG=1 -DNO_CONFIG=1 -ansi -pedantic -Wunused \
+ -Wall -W -Wstrict-prototypes -Wtraditional -Wnested-externs -Winline \
+ -Wpointer-arith -Wbad-function-cast -Wcast-qual -Wmissing-prototypes \
+ -Wmissing-declarations ps_tiny.c -o ps_tiny; \
+exit
+/* ps_tiny.c -- read .pin files, write short PostScript code
+ * by pts@fazekas.hu at Sat Aug 24 12:46:14 CEST 2002
+ * -- Sat Aug 24 18:23:08 CEST 2002
+ * -- Sat Aug 24 23:47:02 CEST 2002
+ * -- Mon Sep 2 11:28:19 CEST 2002
+ * %<B added -- Thu Sep 19 09:23:00 CEST 2002
+ * v0.02 WORKS for flatedecode.psm -- Sun Sep 22 00:39:54 CEST 2002
+ * DEVEL
+ */
+
+/*
+ * Imp: extensive documentation
+ * Imp: verify acount + xcount
+ * Imp: uncompressed méretellenõrzés
+ */
+
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h> /* exit() */
+
+#if NO_CONFIG
+ #include <assert.h>
+ #if SIZEOF_INT>=4
+ typedef unsigned slen_t;
+ typedef int slendiff_t;
+ # define SLEN_P ""
+ #else
+ typedef unsigned long slen_t;
+ typedef long slendiff_t;
+ # define SLEN_P "l"
+ #endif
+ typedef char sbool;
+ #if ';'!=59 || 'a'!=97
+ # error ASCII system is required to compile this program.
+ #endif
+#else
+ #include "config2.h" /* by sam2p... */
+ typedef bool sbool;
+#endif
+#if OBJDEP
+# warning PROVIDES: ps_tiny_main
+#endif
+
+#define ULE(a,b) (((a)+0U)<=((b)+0U))
+#define ISWSPACEE(i) ((i)==32 || ULE(i-9,13-9) || i==0)
+#define ISWSPACE(i,j) ((i j)==32 || ULE(i-9,13-9) || i==0)
+
+#define PROGNAME "ps_tiny"
+#define VERSION "0.02"
+
+/* --- Data */
+
+#define SBUFSIZE 4096
+
+/** Data area holding strings; */
+char sbuf[SBUFSIZE], *sbufb;
+
+#define WORDSSIZE 127
+
+/** Pointers inside sbuf, indexed by chars, [0..31] are special */
+char const* words[WORDSSIZE];
+
+static void sbuff(void) {
+ unsigned i;
+ sbuf[0]='\0';
+ sbufb=sbuf+1;
+ for (i=0;i<WORDSSIZE;i++) words[i]=sbuf;
+}
+
+/** @return -1 or the word found */
+static int findword(char const*word) {
+ unsigned i=32;
+ while (i<WORDSSIZE && 0!=strcmp(word,words[i])) i++;
+ return i==WORDSSIZE ? -1 : (int)i;
+}
+
+/** @return -1 or the word found */
+static int findword_stripslash(char const*word) {
+ unsigned i=32;
+ assert(word[0]!='/');
+ while (i<WORDSSIZE && 0!=strcmp(word,words[i]+(words[i][0]=='/'))) i++;
+ return i==WORDSSIZE ? -1 : (int)i;
+}
+
+/* --- Reading */
+
+/** Current byte offset in input. (from 0) */
+slen_t curofs;
+
+/** Current line in input. (from 1) */
+slen_t curline;
+
+/** Offset of the leftmost char of current line in input. (from 0) */
+slen_t leftofs;
+
+/** Current position in input override format string */
+char const* ifmt;
+
+/** Input override string list */
+char const* const* ilist;
+
+/** Current position in current item of ilist */
+char const* iitem;
+
+/** Char unget */
+int ilast;
+
+static void rewindd(void) { ifmt=0; curofs=leftofs=0; curline=1; }
+
+static void setifmt(char const *ifmt_, char const* const* ilist_) {
+ ifmt=ifmt_;
+ ilist=ilist_;
+ iitem="";
+ ilast=-1;
+}
+
+static void noifmt(void) { ifmt=0; }
+
+static int getcc(void) {
+ int c;
+ if (ifmt!=0) {
+ nextitem:
+ if (ilast>=0) { c=ilast; ilast=-1; }
+ else if (iitem[0]!='\0') c=*iitem++;
+ else if (ifmt[0]=='$') { iitem=*ilist++; ifmt++; goto nextitem; }
+ else if (ifmt[0]=='\0') c=-1; /* EOF forever */
+ else c=*ifmt++;
+ /* fprintf(stderr, "igetcc()='%c'\n", c); */
+ } else {
+ if ((c=getchar())=='\n') { leftofs=curofs; curline++; }
+ curofs++;
+ }
+ return c;
+}
+
+static void ungetcc(int c) {
+ if (ifmt!=0) {
+ assert(ilast<0);
+ ilast=c;
+ } else {
+ if (c=='\n') curline--;
+ if (c>=0) { curofs--; ungetc(c,stdin); }
+ }
+}
+
+static void erri(char const*msg1, char const*msg2) {
+ fprintf(stderr, "%s: error at %" SLEN_P "u.%" SLEN_P "u.%" SLEN_P "u: %s%s\n",
+ PROGNAME, curline, curofs-leftofs+1, curofs, msg1, msg2?msg2:"");
+ exit(3);
+}
+
+static void setword(int c, char const*word, int slash) {
+ slen_t len;
+ assert(slash==0 || slash==1);
+ if (words[c][0]!='\0') erri("abbr letter already used",0);
+ if (sbuf+SBUFSIZE-sbufb+(slen_t)0<(len=strlen(word))+slash+1U) erri("words overflow",0);
+ /* fprintf(stderr,"setword(%d,\"%s\");\n", c, word); */
+ words[c]=sbufb;
+ if (slash) *sbufb++='/';
+ strcpy(sbufb, word);
+ sbufb+=len+1;
+ /* assert(c<3 || findword(word)==c); */
+}
+
+/** So a long string from ps_tiny --copy <bts2.ttt will fit */
+/* #define IBUFSIZE 512 */
+#define IBUFSIZE 32000
+
+/** Input buffer for several operations. */
+char ibuf[IBUFSIZE];
+/** Position after last valid char in ibuf */
+char *ibufb;
+
+typedef slendiff_t psint_t;
+
+#if 0
+static psint_t getint(void) {
+ int c, sgn=1;
+ psint_t v, w;
+ while (ISWSPACE(c,=getcc())) ;
+ if (c=='-') { c=getcc(); sgn=-1; }
+ if (!ULE(c-'0','9'-'0')) erri("integer expected",0); /* Dat: EOF err */
+ v=sgn*(c-'0');
+ while (ULE((c=getcc())-'0','9'-'0')) {
+ if ((w=10*v+sgn*(c-'0'))/10!=v) erri("integer overflow",0);
+ /* ^^^ Dat: overflow check is ok between -MAX-1 .. MAX */
+ v=w;
+ }
+ ungetcc(c);
+ return v;
+}
+
+static psint_t getuint(void) {
+ psint_t v=getint();
+ if (v<0) erri("nonnegative integer expected",0);
+ return v;
+}
+#endif
+
+static /*inline*/ sbool is_ps_white(int/*char*/ c) {
+ return c=='\n' || c=='\r' || c=='\t' || c==' ' || c=='\f' || c=='\0';
+}
+
+static /*inline*/ sbool is_ps_name(int/*char*/ c) {
+ /* Dat: we differ from PDF since we do not treat the hashmark (`#') special
+ * in names.
+ * Dat: we differ from PostScript since we accept names =~ /[!-~]/
+ */
+ return c>='!' && c<='~'
+ && c!='/' && c!='%' && c!='{' && c!='}' && c!='<' && c!='>'
+ && c!='[' && c!=']' && c!='(' && c!=')';
+ /* Dat: PS avoids: /{}<>()[]% \n\r\t\000\f\040 */
+}
+
+/** Definition chosen rather arbitrarily by pts */
+static sbool is_wordx(char const *s) {
+ if (!ULE(*s-'A','Z'-'A') && !ULE(*s-'a','z'-'a') && *s!='.') return 0;
+ /* && !ULE(*s-'0','9'-'0') && *s!='-') return 0; */
+ while (*++s!='\0') if (!is_ps_name(*s)) return 0;
+ return 1;
+}
+
+/** @param b: assume null-terminated @return true on error */
+static /*inline*/ sbool toInteger(char *s, psint_t *ret) {
+ int n=0; /* BUGFIX?? found by __CHECKER__ */
+ return sscanf(s, "%" SLEN_P "i%n", ret, &n)<1 || s[n]!='\0';
+}
+
+/** @param b: assume null-terminated @return true on error */
+static /*inline*/ sbool toReal(char *s, double *ret) {
+ int n;
+ char c;
+ /* Dat: glibc accepts "12e", "12E", "12e+" and "12E-" */
+ return sscanf(s, "%lf%n", ret, &n)<1
+ || (c=s[n-1])=='e' || c=='E' || c=='+' || c=='-' || s[n]!='\0';
+}
+
+/** Returns a PostScript token ID, puts token into buf */
+static char gettok(void) {
+ /* Derived from MiniPS::Tokenizer::yylex() of sam2p-0.37 */
+ int c=0; /* dummy initialization */
+ sbool hi;
+ unsigned hv=0; /* =0: pacify G++ 2.91 */
+ slen_t nest;
+ char *ibufend=ibuf+IBUFSIZE;
+ ibufb=ibuf;
+
+#if 0
+ if (ungot==EOFF) return EOFF;
+ if (ungot!=NO_UNGOT) { c=ungot; ungot=NO_UNGOT; goto again; }
+#endif
+ again_getcc:
+ c=getcc();
+ /* again: */
+ switch (c) {
+ case -1: eof:
+ return 0; /*ungot=EOFF */;
+ case '\n': case '\r': case '\t': case ' ': case '\f': case '\0':
+ goto again_getcc;
+ case '%': /* one-line comment */
+ if ((c=getcc())=='<') { /* XMLish tag */
+ char ret='<';
+ if ((c=getcc())=='/') { ret='>'; c=getcc(); } /* close tag */
+ if (!ULE(c-'A','Z'-'A')) erri("invalid tag",0); /* catch EOF */
+ (ibufb=ibuf)[0]=c; ibufb++;
+ while (ULE((c=getcc())-'A','Z'-'A') || ULE(c-'a','z'-'a')) {
+ if (ibufb==ibufend-1) erri("tag too long",0);
+ *ibufb++=c;
+ }
+ if (c<0) erri("unfinished tag",0);
+ *ibufb='\0';
+ ungetcc(c);
+ return ret;
+ }
+ while (c!='\n' && c!='\r' && c!=-1) c=getcc();
+ if (c==-1) goto eof;
+ goto again_getcc;
+ case '{': case '[':
+ *ibufb++=c;
+ return '[';
+ case '}': case ']':
+ *ibufb++=c;
+ return ']';
+ case '>':
+ if (getcc()!='>') goto err;
+ *ibufb++='>'; *ibufb++='>';
+ return ']';
+ case '<':
+ if ((c=getcc())==-1) { uf_hex: erri("unfinished hexstr",0); }
+ if (c=='<') {
+ *ibufb++='<'; *ibufb++='<';
+ return '[';
+ }
+ if (c=='~') erri("a85str unsupported",0);
+ hi=1;
+ while (c!='>') {
+ if (ULE(c-'0','9'-'0')) hv=c-'0';
+ else if (ULE(c-'a','f'-'a')) hv=c-'a'+10;
+ else if (ULE(c-'A','F'-'A')) hv=c-'A'+10;
+ else if (is_ps_white(c)) hv=16;
+ else erri("syntax error in hexstr",0);
+ if (hv==16) ;
+ else if (!hi) { ibufb[-1]|=hv; hi=1; }
+ else if (ibufb==ibufend) erri("hexstr literal too long",0);
+ else { *ibufb++=(char)(hv<<4); hi=0; }
+ if ((c=getcc())==-1) goto uf_hex;
+ }
+ /* This is correct even if an odd number of hex digits have arrived */
+ return '(';
+ case '(':
+ nest=1;
+ while ((c=getcc())!=-1) {
+ if (c==')' && --nest==0) return '(';
+ if (c!='\\') { if (c=='(') nest++; }
+ else switch (c=getcc()) { /* read a backslash escape */
+ case -1: goto uf_str;
+ case 'n': c='\n'; break;
+ case 'r': c='\r'; break;
+ case 't': c='\t'; break;
+ case 'b': c='\010'; break; /* \b and \a conflict between -ansi and -traditional */
+ case 'f': c='\f'; break;
+ default:
+ if (!ULE(c-'0','7'-'0')) break;
+ hv=c-'0'; /* read at most 3 octal chars */
+ if ((c=getcc())==-1) goto uf_str;
+ if (c<'0' || c>'7') { ungetcc(c); c=hv; }
+ hv=8*hv+(c-'0');
+ if ((c=getcc())==-1) goto uf_str;
+ if (c<'0' || c>'7') { ungetcc(c); c=hv; }
+ c=(char)(8*hv+(c-'0'));
+ } /* SWITCH */
+ if (ibufb==ibufend) erri("str literal too long",0);
+ /* putchar(c); */
+ *ibufb++=c;
+ } /* WHILE */
+ /* if (c==')') return '('; */
+ uf_str: erri("unfinished str",0);
+ case ')': goto err;
+ case '/':
+ *ibufb++='/';
+ while (ISWSPACE(c,=getcc())) ;
+ /* ^^^ `/ x' are two token in PostScript, but here we overcome the C
+ * preprocessor's feature of including whitespace.
+ */
+ /* fall-through, b will begin with '/' */
+ default: /* /nametype, /integertype or /realtype */
+ *ibufb++=c;
+ while ((c=getcc())!=-1 && is_ps_name(c)) {
+ if (ibufb==ibufend) erri("token too long",0);
+ *ibufb++=c;
+ }
+ ungetcc(c);
+ if (ibuf[0]=='/') return '/';
+ /* Imp: optimise numbers?? */
+ if (ibufb!=ibufend) {
+ psint_t l;
+ double d;
+ *ibufb='\0';
+ /* Dat: we don't support base-n number such as `16#100' == 256 in real PostScript */
+ if (!toInteger(ibufb, &l)) return '1'; /* throw away integer value */
+ /* Dat: call toInteger _before_ toReal */
+ if (!toReal(ibufb, &d)) return '.';
+ }
+ return 'E'; /* executable /nametype */
+ }
+ err:
+ erri("syntax error, token expected",0);
+ goto again_getcc; /* notreached */
+}
+
+static void getotag(char const*tag) {
+#if 0 /* This code segment cannot ignore comments */
+ char const *p=tag;
+ int c;
+ while (ISWSPACE(c,=getcc())) ;
+ if (c!='%' || (c=getcc())!='<') erri("tag expected: ", tag);
+ while (ISWSPACE(c,=getcc())) ;
+ while (p[0]!='\0') {
+ if (c!=*p++) erri("this tag expected: ", tag);
+ c=getcc();
+ }
+ ungetcc(c);
+#else
+ if (gettok()!='<' || 0!=strcmp(ibuf,tag)) erri("tag expected: ", tag);
+#endif
+}
+
+static void gettagbeg(void) {
+ int c;
+ while (ISWSPACE(c,=getcc())) ;
+ if (c!='>') erri("`>' expected",0);
+}
+
+static void gettagend(void) {
+ int c;
+ while (ISWSPACE(c,=getcc())) ;
+ if (c!='/') erri("`/>' expected",0);
+ while (ISWSPACE(c,=getcc())) ;
+ if (c!='>') erri("`/>' expected",0);
+}
+
+static void getkey(char const *key) {
+ char const *p=key;
+ int c;
+ while (ISWSPACE(c,=getcc())) ;
+ while (p[0]!='\0') {
+ if (c!=*p++) erri("this key expected: ", key);
+ c=getcc();
+ }
+ while (ISWSPACEE(c)) c=getcc();
+ if (c!='=') erri("key `=' expected", 0);
+}
+
+
+/** Loads a value into ibuf, '\0'-terminated. */
+static void getval(void) {
+ sbool g=1;
+ char *ibufend1=ibuf+IBUFSIZE-1, c;
+ ibufb=ibuf;
+ while (ISWSPACE(c,=getcc())) ;
+ while (1) {
+ if (c=='"') g=!g;
+ else if (g && (ISWSPACEE(c) || c=='/' || c=='>')) { ungetcc(c); break; }
+ else if (c<0) erri("unfinished tag val",0);
+ else if (c==0) erri("\\0 disallowed in tag val",0);
+ else if (ibufb==ibufend1) erri("tag val too long",0);
+ else *ibufb++=c;
+ c=getcc();
+ } /* WHILE */
+ *ibufb='\0';
+}
+
+static psint_t getuintval(void) {
+ psint_t ret;
+ getval();
+ /* fprintf(stderr, "[%s]\n", ibuf); */
+ if (toInteger(ibuf, &ret) || ret<0) erri("tag val must be nonnegative integer",0);
+ return ret;
+}
+
+/* --- Writing */
+
+/** Maximum number of characters in a line. */
+#define MAXLINE 78
+
+/** Number of characters already written into this line. (from 0) */
+slen_t wcolc;
+
+/** Last token was a self-closing one */
+sbool wlastclosed;
+
+static void prepare(void) { wcolc=0; wlastclosed=1; }
+
+static void newline(void) {
+ if (wcolc!=0) {
+ putchar('\n');
+ wcolc=0; wlastclosed=1;
+ } else assert(wlastclosed);
+}
+
+/** 2: "\\n"; 1: "\n" */
+static int pstrq_litn_pp=2;
+
+/** @return the byte length of a string as a quoted PostScript ASCII string
+ * literal
+ */
+static slen_t pstrqlen(register char const* p, char const* pend) {
+ slen_t olen=2; /* '(' and ')' */
+ char c;
+ p=ibuf; pend=ibufb; while (p!=pend) {
+ if ((c=*(unsigned char const*)p++)=='\r' || c=='\t' || c=='\010' || c=='\f' || c=='(' || c==')') olen+=2;
+ else if (c=='\n') olen+=pstrq_litn_pp;
+ else if (c>=32 && c<=126) olen++;
+ else if (c>=64 || p==pend || ULE(*p-'0','7'-'0')) olen+=4;
+ else if (c>=8) olen+=3;
+ else olen+=2;
+ }
+ return olen;
+}
+
+/** Prints the specified string as a quoted PostScript ASCII string literal.
+ * Does not modify wcolc etc.
+ */
+static void pstrqput(register char const* p, char const* pend) {
+ char c;
+ putchar('(');
+ p=ibuf; pend=ibufb; while (p!=pend) {
+ if ((ULE((c=*(unsigned char const*)p++)-32, 126-32) && c!='(' && c!=')')
+ || (c=='\n' && pstrq_litn_pp==1)
+ ) { putchar(c); continue; }
+ putchar('\\');
+ if (c=='\n') putchar('n');
+ else if (c=='\r') putchar('r');
+ else if (c=='\t') putchar('t');
+ else if (c=='\010') putchar('b');
+ else if (c=='\f') putchar('f');
+ else if (c=='(') putchar('('); /* BUGFIX at Tue Feb 22 00:22:19 CET 2005 */
+ else if (c==')') putchar(')');
+ else if (c>=64 || p==pend || ULE(*p-'0','7'-'0')) {
+ putchar((c>>6&7)+'0');
+ putchar((c>>3&7)+'0');
+ putchar(( c&7)+'0');
+ } else if (c>=8) {
+ putchar((c>>3) +'0');
+ putchar(( c&7)+'0');
+ } else putchar(c+'0');
+ }
+ putchar(')');
+}
+
+static int copy_longstr_warn_p=1;
+
+/** Copies PostScript code from input to output. Strips comments, superfluous
+ * whitespace etc., substitutes words etc.
+ * @param tag may be NULL, this signals: copy till EOF, doesn't substitute
+ * words
+ */
+static void copy(char const*tag) {
+ int c;
+ slen_t len, olen;
+ while (1) switch (gettok()) {
+ case 0:
+ if (tag) erri("eof before close tag: ", tag);
+ return;
+ case '[': case ']':
+ if (wcolc+(len=ibufb-ibuf)>MAXLINE) newline();
+ wlastclosed=1;
+ write:
+ if (len>MAXLINE) fprintf(stderr, "%s: warning: output line too long\n", PROGNAME);
+ fwrite(ibuf, 1, len, stdout); wcolc+=len;
+ break;
+ case '/':
+ if ((len=ibufb-ibuf)<IBUFSIZE && tag && !(*ibufb='\0') && (c=findword(ibuf))>=0) {
+ ibuf[0]='/';
+ ibuf[1]=c;
+ ibufb=ibuf+2;
+ len=2;
+ }
+ if (wcolc+len>MAXLINE) newline();
+ wlastclosed=0;
+ goto write;
+ case '<': erri("tag unexpected",0);
+ case '>':
+ if (!tag) erri("close tag unexpected",0);
+ if (strlen(tag)!=(len=ibufb-ibuf) || 0!=memcmp(ibuf,tag,len)) erri("this close tag expected: ", tag);
+ /* wlastclosed is left unmodified */
+ gettagbeg();
+ return;
+ case '(':
+ olen=pstrqlen(ibuf,ibufb);
+ if (wcolc+olen>MAXLINE) newline();
+ if (olen>MAXLINE && copy_longstr_warn_p) fprintf(stderr, "%s: warning: output string too long\n", PROGNAME);
+ /* putchar(ibuf[1]); */
+ wcolc+=olen; pstrqput(ibuf,ibufb);
+ wlastclosed=1;
+ break;
+ default: /* case '1': case '.': case 'E': */
+ /* fprintf(stderr,"fw(%s) %c\n", ibuf, findword("32768")); */
+ if ((len=ibufb-ibuf)<IBUFSIZE && tag && !(*ibufb='\0') && (c=findword_stripslash(ibuf))>=0) {
+ ibuf[0]=c;
+ ibufb=ibuf+1;
+ len=1;
+ }
+ if (wcolc+len+!wlastclosed>MAXLINE) newline();
+ else if (!wlastclosed) { putchar(' '); wcolc++; }
+ wlastclosed=0;
+ goto write;
+ }
+}
+
+/** Prefix chars: 32..41 ' '..')' */
+static void cprefix(slen_t olen) {
+ slen_t plen;
+ if (0==olen) erri("empty token","");
+ if (olen>11) erri("compressed token too long (>11)","");
+ plen=olen+(olen>1)+(olen==7);
+ if (wcolc+(wcolc==0)+plen>MAXLINE) newline();
+ if (wcolc==0) { putchar('%'); wcolc=1; }
+ if (plen>=MAXLINE) fprintf(stderr, "%s: warning: output line too long\n", PROGNAME);
+ if (olen==7) { putchar(8+30); putchar(' '); wcolc+=2; } /* Dat: ASCII 37=='%' */
+ else if (olen>1) { putchar(olen+30); wcolc++; }
+}
+
+/** Copies PostScript code from input to output. Strips comments, superfluous
+ * whitespace etc., substitutes words etc. Output is not valid PostScript code,
+ * but it needs decompression (i.e adding spaces to words). Ignores var
+ * `wlastclosed' (sets it to 1 by calling newline()).
+ */
+static void compress0(char const*tag) {
+ int c;
+ slen_t len, olen;
+ newline();
+ while (1) switch (gettok()) {
+ case 0: erri("eof before close tag: ", tag);
+ case '[': case ']':
+ len=ibufb-ibuf;
+ write:
+ cprefix(len);
+ fwrite(ibuf, 1, len, stdout); wcolc+=len;
+ break;
+ case '/':
+ if ((len=ibufb-ibuf)<IBUFSIZE && !(*ibufb='\0') && (c=findword(ibuf))>=0) {
+ /* erri("possibly stupid redef: ", ibuf); */
+ ibuf[0]='/';
+ ibuf[1]=c;
+ ibufb=ibuf+2;
+ len=2;
+ }
+ goto write;
+ case '<': erri("tag unexpected",0);
+ case '>':
+ if (strlen(tag)!=(len=ibufb-ibuf) || 0!=memcmp(ibuf,tag,len)) erri("this close tag expected: ", tag);
+ /* wlastclosed is left unmodified */
+ fputs((wcolc+2>MAXLINE) ? "\n% %%" : "%%", stdout);
+ newline();
+ gettagbeg();
+ return;
+ case '(':
+ cprefix(olen=pstrqlen(ibuf,ibufb));
+ wcolc+=olen; pstrqput(ibuf,ibufb);
+ break;
+ default: /* case '1': case '.': case 'E': */
+ if ((len=ibufb-ibuf)<IBUFSIZE && !(*ibufb='\0') && (c=findword_stripslash(ibuf))>=0) {
+ ibuf[0]=c;
+ ibufb=ibuf+1;
+ len=1;
+ }
+ goto write;
+ }
+}
+
+/** by pts@fazekas.hu at Fri Sep 6 11:34:57 CEST 2002. Copies data from stdin
+ * to stdout till close tag %</tag>. (Note that it isn't safe to copy data of
+ * the ASCII85Encode filter this way
+ */
+static void copydata(char const*tag) {
+ int c;
+ while (ISWSPACE(c,=getcc())) ;
+ /* ungetcc(c); */
+ while (1) {
+ if (c<0) erri("missing close tag: ", tag);
+ if (c!='%') { putchar(c); c=getcc(); continue; }
+ if ((c=getcc())=='<') {
+ if ((c=getcc())=='/') {
+ while (tag[0]!='\0') {
+ if ((c=getcc())!=*tag++) erri("this close tag expected: ", tag);
+ }
+ while (ISWSPACE(c,=getcc())) ;
+ if (c!='>') erri("`>' expected", 0);
+ break;
+ } else {
+ putchar('%');
+ putchar('<');
+ }
+ } else {
+ putchar('%');
+ }
+ }
+}
+
+/* --- Main */
+
+int main(int argc, char**argv) {
+ slen_t acount, xcount, inlining;
+ char tmp[40];
+ (void)argc;
+
+ /* freopen("t.pin","rb",stdin); */
+
+ sbuff();
+ rewindd();
+ prepare();
+ if (argv[0] && argv[1] && 0==strcmp(argv[1],"--copy")) {
+ copy_longstr_warn_p=0;
+ pstrq_litn_pp=1;
+ copy((char const*)0);
+ return 0;
+ }
+
+ { char tok=gettok();
+ slen_t len;
+ len=ibufb-ibuf;
+ if (tok=='<' && len==4 && 0==memcmp(ibuf, "Head", 4)) {
+ gettagbeg();
+ copydata("Head");
+ getotag("Open");
+ } else if (tok=='<' && len==4 && 0==memcmp(ibuf, "Open", 4)) {
+ } else erri("tag %<Head or %<Open expected",0);
+ }
+ gettagbeg();
+ copy("Open");
+
+ getotag("Abbr");
+ getkey("acount"); acount=getuintval();
+ getkey("xcount"); xcount=getuintval();
+ sprintf(tmp,"%" SLEN_P "u dict%%</I>", acount+xcount);
+ setifmt(tmp,0); copy("I"); noifmt();
+ gettagbeg();
+
+#define E_RANGE 3
+#define E_SYNTAX 4
+#define E_COMPRESS 5
+ copy("Abbr");
+ setword(E_RANGE, ")range", 0);
+ setword(E_SYNTAX, ")syntax", 0);
+ setword(E_COMPRESS, ")compress", 0);
+ { int c;
+ for (c=7;c<32;c++) words[c]=words[E_RANGE];
+ for (c=32;c<42;c++) words[c]=words[E_COMPRESS];
+ for (c=47;c<58;c++) words[c]=words[E_SYNTAX]; /* Name:'/', Number:'0'..'9' */
+ words[0U+'<']=words[0U+'>']= /* Hex */
+ words[0U+'[']=words[0U+']']= /* Bracket */
+ words[0U+'{']=words[0U+'}']= /* Brace */
+ words[E_SYNTAX];
+ for (c=127;c<WORDSSIZE;c++) words[c]=words[E_RANGE];
+ }
+
+ { char tok;
+ slen_t len;
+ int c;
+ char ct[2];
+ char const* ilist_[3];
+ psint_t i;
+ sbool g;
+ while (1) {
+ tok=gettok(); len=ibufb-ibuf;
+ if (tok=='<' && len==1 && 0==memcmp(ibuf, "A", 1)) {
+ while (ISWSPACE(c,=getcc())) ;
+ if (c<32 || c>=WORDSSIZE) erri("invalid %<A letter",0);
+ ct[0]=c; ct[1]='\0'; ilist_[0]=ct;
+ getval();
+ if (is_wordx(ibuf)) {
+ setword(c, ibuf, 0);
+ ilist_[1]=words[c]; words[c]=sbuf; /* temp hide */
+ ilist_[2]=words[0][0]=='\0' ? "load def" : words[0];
+ setifmt("/$ /$ $%</I>", ilist_);
+ if (words[1][0]=='\0' && 0==strcmp(ibuf,"def")) setword(1, ct, 0);
+ } else {
+ g=toInteger(ibuf, &i); /* need braces? */
+ if (g) { words[2]=sbuf; c=2; }
+ setword(c, ibuf, 0); /* temp save */
+ ilist_[1]=words[c]; words[c]=sbuf; /* temp hide */
+ ilist_[2]=words[1][0]=='\0' ? "def" : words[1];
+ setifmt(g ? "/$ { $\n} $%</I>" : "/$ $\n $%</I>", ilist_);
+ if (words[0][0]=='\0' && 0==strcmp(ibuf,"load def")) setword(0, ct, 0);
+ }
+ copy("I");
+ noifmt();
+ words[c]=ilist_[1];
+ } else if (tok=='<' && len==1 && 0==memcmp(ibuf, "D", 1)) {
+ /* define both /x and x */
+ while (ISWSPACE(c,=getcc())) ;
+ if (c<32 || c>=WORDSSIZE) erri("invalid %<D letter",0);
+ ct[0]=c; ct[1]='\0'; ilist_[0]=ct;
+ getval();
+ if (!is_wordx(ibuf)) erri("body for %<D must be a single word",0);
+ setword(c, ibuf, 1);
+ } else if (tok=='<' && len==7 && 0==memcmp(ibuf, "TokSubs", 7)) {
+ break;
+ } else erri("tag %<TokSubs or %<A or %<D expected",0);
+ gettagend();
+ }
+ words[2]=sbuf; /* Imp: free chars */
+ }
+
+ getkey("name"); getval(); setword(2, ibuf, 0);
+ if (ibufb-ibuf==1 && words[(unsigned char)ibuf[0]]!=sbuf) erri("abbr used as %<TokSubs name= : ",ibuf);
+ getkey("inlining"); inlining=getuintval();
+ gettagend();
+ { char const* ilist_[2]; ilist_[0]=ilist_[1]=words[2];
+ setifmt(inlining!=0 ? "/${mark exch{dup xcheck{dup type/arraytype eq{$}{dup type/nametype eq{dup currentdict exch known{load dup dup type/arraytype eq exch xcheck and{$ aload pop}if}if}if}ifelse}if}forall counttomark array astore exch pop cvx}bind def%</I>"
+ :"/$ {\n"
+ "mark exch{\n"
+ "dup xcheck{\n"
+ "dup type/arraytype eq{$}{\n"
+ "dup type/nametype eq{\n"
+ "dup currentdict exch known {load}if\n"
+ "}if\n"
+ "}ifelse\n"
+ "}if\n"
+ "}forall\n"
+ "counttomark array astore exch pop cvx\n"
+ "} bind def%</I>", ilist_);
+ copy("I"); noifmt();
+ }
+
+ getotag("Test");
+ gettagbeg();
+ copy("Test");
+
+ getotag("S");
+ getkey("len"); (void)getuintval(); /* Imp: verify slen for overruns */
+ gettagbeg();
+ setifmt("{%</I>",0); copy("I"); noifmt(); /*}*/
+ copy("S");
+
+ { char const* ilist_[2]; ilist_[0]=ilist_[1]=words[2];
+ setifmt(
+ "0\n"
+ "{ % Stack: <dst-str> <i>\n"
+ " currentfile read pop\n"
+ " dup 37 eq{% '%'\n"
+ " pop currentfile read pop\n"
+ " dup 37 eq{pop pop exit}if % exit when '%%'\n"
+ " }if\n"
+ " % Stack: <dst-str> <i> <char-read>\n"
+ " dup 42 lt{\n"
+ " 30 sub\n"
+ " % Stack: <dst-str> <i> <repeat-count>\n"
+ " dup 0 gt{\n"
+ " 3 copy getinterval\n"
+ " % Stack: <dst-str> <i> <repeat-count> <sub-dst-str>\n"
+ " currentfile exch readstring pop pop\n"
+ " % Stack: <dst-str> <i> <repeat-count>\n"
+ " add 1 add\n"
+ " }{pop}ifelse % skip newlines, tabs etc.\n"
+ " }{\n"
+ " 3 copy put\n"
+ " pop 2 add % \\0 as space\n"
+ " }ifelse\n"
+ " % Stack: <dst-str> <new-i>\n"
+ "}$ bind loop\n"
+ "% Stack: <dst-str>\n"
+ "cvx exec $ bind exec\n" /* CONST, VAR és CODE futtatása */
+ "currentfile token pop pop\n" /* A %%BeginData utáni exec beolvasása */
+ "%</I>\n", ilist_);
+ copy("I"); noifmt();
+ }
+
+ getotag("True");
+ gettagbeg();
+ copy("True");
+
+ setifmt("}{currentfile token pop pop%</I>",0);
+ copy("I"); noifmt();
+
+ getotag("False");
+ gettagbeg();
+ copy("False");
+
+ setifmt("}ifelse%</I>",0);
+ copy("I"); noifmt();
+
+ getotag("Defs");
+ gettagbeg();
+ compress0("Defs");
+
+ { char tok=gettok();
+ slen_t len;
+ len=ibufb-ibuf;
+ if (tok=='<' && len==4 && 0==memcmp(ibuf, "Data", 4)) {
+ gettagbeg();
+ copydata("Data");
+ } else if (tok=='<' && len==4 && 0==memcmp(ibuf, "Fini", 4)) {
+ fputs("%%BeginData:\nexec\n`S\n%%EndData\n",stdout);
+ getotag("Fini");
+ gettagbeg();
+ copy("Fini");
+ newline();
+ fputs("%%Trailer\n%%EOF\n", stdout);
+ } else erri("tag %<Data or %<Fini expected",0);
+ }
+
+ if (gettok()!=0) erri("premature EOF",0);
+
+ return 0;
+}
diff --git a/graphics/sam2p/psmlib.psm b/graphics/sam2p/psmlib.psm
new file mode 100644
index 0000000000..d415c28bf8
--- /dev/null
+++ b/graphics/sam2p/psmlib.psm
@@ -0,0 +1,199 @@
+/* psmlib.psm -- utilites for writing PostScript code with the help of
+ * cpp, the C preprocessor
+ * compiled by pts@fazekas.hu at Fri Sep 20 23:38:32 CEST 2002
+ */
+
+#if USE_A85D
+#else
+ #if USE_HEXD
+ #else
+ #define USE_BINARY 1
+ #endif
+#endif
+
+#if USE_INDEXED2
+ #define USE_PALETTE 1
+#else
+ #if USE_TRANSPARENT8
+ #define USE_PALETTE 1
+ #endif
+#endif
+
+#if USE_NO_BIND
+ #define BIND_DEF def
+#else
+ #define BIND_DEF bind def
+#endif
+
+
+#if NDEBUG
+ #define DEBUG(msg)
+ #define ASSERT_TRUE_POP(str) pop
+ #define ASSERT_FALSE_POP(str) pop
+ #define ASSERT_TRUE(what,str)
+ #define ASSERT_INT()
+ #define INT_EQ eq
+ #define INT_NE ne
+ #define INT_LE le
+ #define INT_GT gt
+ #define INT_LT lt
+ #define BOOL_BIN(op,message) op
+ #define INT_BIN(op,message) op
+ #define DEBUGFORCE(msg)
+ #define ASSERT_STACK(list,message)
+#else
+ /-str /stringtype def
+ /-aryb /stringtype def % byte array
+ /-ary /arraytype def
+ /-int /integertype def
+ /-bool /booleantype def
+ /-dict /dicttype def
+ /handleerror.orig /handleerror load def
+ /handleerror {
+ (%stderr) (w) file
+ dup (!!!Fatal: GS error: ) writestring
+ dup $error /errorname get write==only
+ dup ( in ) writestring
+ dup $error /command get write==only
+ dup ( at ) writestring
+ dup $error /position get write==only
+ dup (.\n) writestring
+ flushfile flush
+ handleerror.orig
+ quit
+ }bind def
+ #define ASSERT_TRUE_POP(str) not{ str InternalError }if
+ #define ASSERT_FALSE_POP(str) { str InternalError }if
+ #define ASSERT_TRUE(what,str) what not{ str InternalError }if
+ #define ASSERT_INT(str) dup type/integertype ne{str InternalError}if
+ #define ASSERT_BOOL(str) dup type/booleantype ne{str InternalError}if
+ /DumpStack { % - DumpStack -
+ (Stack: ) print % from bottom to top
+ count 1 sub -1 0{
+ index
+ dup type /stringtype eq {pop ()}if
+ ===only
+ ( ) print
+ } for
+ (.\n) print
+ }bind def
+
+ /TypeStack { % <list> TypeStack <bool>
+ dup length count 2 sub eq {
+ true exch count 2 add 1 index length 1 sub 0 exch 1 exch
+ % Stack: ... true ary count(...)+5 0 1 ary.length-1
+ {
+ % Stack: ... true ary count* i
+ 2 index exch get 2 copy exch
+ % Stack: ... true ary count* ary[i] ary[i] count*
+ index type
+ % Stack: ... true ary count* ary[i] ary[i] stackitem.type
+ ne{
+ pop pop pop pop
+ % Stack: ...
+ false 0 0
+ exit
+ }if
+ pop 1 sub
+ % Stack: ... true ary count*-1
+ } for
+ % Stack: ... true|false ary count*
+ pop pop
+ }{
+ pop false
+ }ifelse
+ ASSERT_BOOL((TypeStack-bool))
+ }bind def
+ /InternalError { % <str> FatalError -
+ (%stderr) (w) file dup dup
+ (Internal muZCat Error: ) writestring
+ 2 index writestring
+ dup (.\n) writestring
+ flushfile
+ pop
+ quit
+ }bind def
+ /Stderr (%stderr) (w) file def
+ #ifdef DEBUGMSG
+ #define DEBUG(msg) msg Stderr exch writestring Stderr flushfile
+ #else
+ #define DEBUG(msg)
+ #endif
+ #define DEBUGFORCE(msg) msg Stderr exch writestring Stderr flushfile
+ #define INT_EQ ASSERT_INT((eq2int)) exch ASSERT_INT((eq1int)) exch eq
+ #define INT_NE ASSERT_INT((ne2int)) exch ASSERT_INT((ne1int)) exch ne
+ #define INT_LE ASSERT_INT((le2int)) exch ASSERT_INT((le1int)) exch le
+ #define INT_GT ASSERT_INT((gt2int)) exch ASSERT_INT((gt1int)) exch gt
+ #define INT_LT ASSERT_INT((lt2int)) exch ASSERT_INT((lt1int)) exch lt
+ #define BOOL_BIN(op,message) ASSERT_BOOL(message) exch ASSERT_BOOL(message) exch op
+ #define INT_BIN(op,message) ASSERT_INT(message) exch ASSERT_INT(message) exch op
+ #define ASSERT_STACK(list,message) TYPE_STACK(list) not{ DumpStack (assert stack: ) message concatstrings InternalError }if
+ #define TYPE_STACK(list) [ list ] TypeStack
+#endif
+
+/* at Sat Sep 21 19:07:59 CEST 2002 */
+#if USE_DEBUG2
+ #define DEBUG2(x) x
+#else
+ #define DEBUG2(x)
+#endif
+
+/* revised, A85D/read_eod at Sun Sep 22 00:27:13 CEST 2002 */
+/* Sample usage:
+ * { TE_read(===) % action to do with normal char
+ * #if !USE_NO_EOF
+ * { TE_read_pop exit } ifelse % action to do on EOF
+ * #endif
+ * } loop
+ */
+#if USE_A85D
+ #define TE_read_eod a85_getc ASSERT_TRUE(dup 511 eq,(EOD expected)) pop
+ #define TE_init /xS 32 def /xD 0 def /xC 0 def
+ #if USE_NO_EOF
+ #define TE_read(true_action) a85_getc true_action
+ #define PSM_A85_GETC \
+ {27 xS ge{exit}if STDIN read pop \
+ dup 122 eq{/xS 27 def/xD 0 def/xC 0 def}{dup 117 gt{ \
+ STDIN read{pop}if/xS 54 xS sub def}{dup 33 ge{xS 32 eq{dup/xC exch def/xD -1670420001 def}{dup 117 sub{1 85 \
+ 7225 614125}xS 28 sub get mul xD add/xD exch def}ifelse/xS xS 1 sub def}if}ifelse}ifelse pop}loop xS 22 eq{511}{xC \
+ 1868977 mul xD add xS 24 and neg bitshift 23 xS lt{xC 3 mul add}if 255 and/xS xS 3 eq{32}{xS 7 mod 3 \
+ eq{22}{xS 8 sub}ifelse}ifelse def}ifelse
+ /** TE_readstring(str) <substr> */
+ #define TE_readstring(str) dup length 1 sub 0 exch 1 exch{a85_getc 3 copy put pop pop}for
+ #else
+ #define TE_read(true_action) a85_getc dup 256 INT_LT { true_action }
+ #define TE_read_pop pop
+ /* #define TE_read_eod TE_read() { ASSERT_TRUE(false,(EOD expected)) } ifelse */
+ #define PSM_A85_GETC \
+ {27 xS ge{exit}if STDIN read not{511}if \
+ dup 122 eq{/xS 27 def/xD 0 def/xC 0 def}{dup 117 gt{ \
+ STDIN read{pop}if/xS 54 xS sub def}{dup 33 ge{xS 32 eq{dup/xC exch def/xD -1670420001 def}{dup 117 sub{1 85 \
+ 7225 614125}xS 28 sub get mul xD add/xD exch def}ifelse/xS xS 1 sub def}if}ifelse}ifelse pop}loop xS 22 eq{511}{xC \
+ 1868977 mul xD add xS 24 and neg bitshift 23 xS lt{xC 3 mul add}if 255 and/xS xS 3 eq{32}{xS 7 mod 3 \
+ eq{22}{xS 8 sub}ifelse}ifelse def}ifelse
+ #endif
+#endif
+#if USE_HEXD
+ #define TE_init
+ #if USE_NO_EOF
+ #define TE_read(true_action) STDIN C readhexstring pop 0 get true_action
+ #define TE_read_eod STDIN read pop pop /* read '>' */
+ #define TE_readstring(str) STDIN str readhexstring pop
+ #else
+ #error PostScript op readhexstring cannot detect EOD!
+ #define TE_read(true_action) STDIN C readhexstring { 0 get true_action }
+ #define TE_read_pop
+ #define TE_read_eod
+ #endif
+#endif
+#if USE_BINARY
+ #define TE_init
+ #define TE_read_eod
+ #if USE_NO_EOF
+ #define TE_read(true_action) STDIN read pop true_action
+ #define TE_readstring(str) STDIN str readstring pop
+ #else
+ #define TE_read(true_action) STDIN read { true_action }
+ #define TE_read_pop
+ #endif
+#endif
diff --git a/graphics/sam2p/pts_defl.c b/graphics/sam2p/pts_defl.c
new file mode 100644
index 0000000000..09ae9ec6d9
--- /dev/null
+++ b/graphics/sam2p/pts_defl.c
@@ -0,0 +1,3670 @@
+#define DUMMY \
+set -ex; \
+"${CC:-gcc}" -DNDEBUG=1 -DPTS_DEFL_MAIN -O3 -ansi \
+ -Wall -W -Wstrict-prototypes -Wtraditional -Wnested-externs -Winline \
+ -Wpointer-arith -Wbad-function-cast -Wcast-qual -Wmissing-prototypes \
+ -Wmissing-declarations pts_defl.c -o flateenc; \
+exit
+/*
+ * pts_defl.c -- C source file ZIP compression ripped from linux-2.6.8.1
+ * by pts@fazekas.hu at Tue Jan 18 15:19:06 CET 2005
+ *
+ * This ZIP compression (ZIP == PostScript /FlateEncode compression filter
+ * (ZLIB RFC 1950)) routine has been ripped from the Linux kernel 2.6.8.1
+ * (directory lib/zlib_deflate), which has been ripped from ZLIB 1.1.3
+ *
+ * To have a UNIX filter program (stdin -> stdout), compile zipfilt.c
+ *
+ * Dat: the exported symbols are: zlib_deflate zlib_deflateEnd
+ * zlib_deflateInit_ zlib_deflateInit2_ zlib_deflateParams
+ * zlib_deflate_workspacesize
+ *
+ */
+
+/* ---- <rip> by pts */
+
+/* +++ deflate.c */
+/* deflate.c -- compress data using the deflation algorithm
+ * Copyright (C) 1995-1996 Jean-loup Gailly.
+ * For conditions of distribution and use, see copyright notice in zlib.h
+ */
+
+/*
+ * ALGORITHM
+ *
+ * The "deflation" process depends on being able to identify portions
+ * of the input text which are identical to earlier input (within a
+ * sliding window trailing behind the input currently being processed).
+ *
+ * The most straightforward technique turns out to be the fastest for
+ * most input files: try all possible matches and select the longest.
+ * The key feature of this algorithm is that insertions into the string
+ * dictionary are very simple and thus fast, and deletions are avoided
+ * completely. Insertions are performed at each input character, whereas
+ * string matches are performed only when the previous match ends. So it
+ * is preferable to spend more time in matches to allow very fast string
+ * insertions and avoid deletions. The matching algorithm for small
+ * strings is inspired from that of Rabin & Karp. A brute force approach
+ * is used to find longer strings when a small match has been found.
+ * A similar algorithm is used in comic (by Jan-Mark Wams) and freeze
+ * (by Leonid Broukhis).
+ * A previous version of this file used a more sophisticated algorithm
+ * (by Fiala and Greene) which is guaranteed to run in linear amortized
+ * time, but has a larger average cost, uses more memory and is patented.
+ * However the F&G algorithm may be faster for some highly redundant
+ * files if the parameter max_chain_length (described below) is too large.
+ *
+ * ACKNOWLEDGEMENTS
+ *
+ * The idea of lazy evaluation of matches is due to Jan-Mark Wams, and
+ * I found it in 'freeze' written by Leonid Broukhis.
+ * Thanks to many people for bug reports and testing.
+ *
+ * REFERENCES
+ *
+ * Deutsch, L.P.,"DEFLATE Compressed Data Format Specification".
+ * Available in ftp://ds.internic.net/rfc/rfc1951.txt
+ *
+ * A description of the Rabin and Karp algorithm is given in the book
+ * "Algorithms" by R. Sedgewick, Addison-Wesley, p252.
+ *
+ * Fiala,E.R., and Greene,D.H.
+ * Data Compression with Finite Windows, Comm.ACM, 32,4 (1989) 490-595
+ *
+ */
+
+#if 0 /**** pts ****/
+# include <linux/module.h>
+#endif
+
+/**** pts ****/
+#if OBJDEP /* sam2p */
+# warning PROVIDES: pts_defl
+#endif
+#if HAVE_CONFIG2_H /* sam2p */
+# include "config2.h"
+#endif
+
+/* #include <linux/zutil.h> */
+/* zutil.h -- internal interface and configuration of the compression library
+ * Copyright (C) 1995-1998 Jean-loup Gailly.
+ * For conditions of distribution and use, see copyright notice in zlib.h
+ */
+
+/* WARNING: this file should *not* be used by applications. It is
+ part of the implementation of the compression library and is
+ subject to change. Applications should only use zlib.h.
+ */
+
+/* @(#) $Id: pts_defl.c,v 1.6 2008/08/28 20:16:47 pts Exp $ */
+
+#ifndef _Z_UTIL_H
+#define _Z_UTIL_H
+
+#if 0 /**** pts ****/
+# include <linux/zlib.h>
+#else
+# include "pts_defl.h"
+#endif
+#if 0 /**** pts ****/
+# include <linux/string.h>
+# include <linux/errno.h>
+# include <linux/kernel.h>
+#endif
+
+/* zlib.h -- interface of the 'zlib' general purpose compression library
+ version 1.1.3, July 9th, 1998
+
+ Copyright (C) 1995-1998 Jean-loup Gailly and Mark Adler
+
+ This software is provided 'as-is', without any express or implied
+ warranty. In no event will the authors be held liable for any damages
+ arising from the use of this software.
+
+ Permission is granted to anyone to use this software for any purpose,
+ including commercial applications, and to alter it and redistribute it
+ freely, subject to the following restrictions:
+
+ 1. The origin of this software must not be misrepresented; you must not
+ claim that you wrote the original software. If you use this software
+ in a product, an acknowledgment in the product documentation would be
+ appreciated but is not required.
+ 2. Altered source versions must be plainly marked as such, and must not be
+ misrepresented as being the original software.
+ 3. This notice may not be removed or altered from any source distribution.
+
+ Jean-loup Gailly Mark Adler
+ jloup@gzip.org madler@alumni.caltech.edu
+
+
+ The data format used by the zlib library is described by RFCs (Request for
+ Comments) 1950 to 1952 in the files ftp://ds.internic.net/rfc/rfc1950.txt
+ (zlib format), rfc1951.txt (deflate format) and rfc1952.txt (gzip format).
+*/
+
+/*#include <linux/zconf.h>*/
+/* zconf.h -- configuration of the zlib compression library
+ * Copyright (C) 1995-1998 Jean-loup Gailly.
+ * For conditions of distribution and use, see copyright notice in zlib.h
+ */
+
+/* @(#) $Id: pts_defl.c,v 1.6 2008/08/28 20:16:47 pts Exp $ */
+
+/*#ifndef _ZCONF_H*/
+/*#define _ZCONF_H*/
+
+#ifndef NULLP /**** pts ****/
+#define NULLP ((void*)0) /* Imp: g++, with const */
+#endif
+
+#if 0 /**** pts ****/ /* Dat: `inline' is not ANSI C */
+# define ZINLINE inline
+#else
+# define ZINLINE
+#endif
+#define ZSTATIC static /**** pts ****/
+
+/* The memory requirements for deflate are (in bytes):
+ (1 << (windowBits+2)) + (1 << (memLevel+9))
+ that is: 128K for windowBits=15 + 128K for memLevel = 8 (default values)
+ plus a few kilobytes for small objects. For example, if you want to reduce
+ the default memory requirements from 256K to 128K, compile with
+ make CFLAGS="-O -DMAX_WBITS=14 -DMAX_MEM_LEVEL=7"
+ Of course this will generally degrade compression (there's no free lunch).
+
+ The memory requirements for inflate are (in bytes) 1 << windowBits
+ that is, 32K for windowBits=15 (default value) plus a few kilobytes
+ for small objects.
+*/
+
+/* Maximum value for memLevel in deflateInit2 */
+#ifndef MAX_MEM_LEVEL
+# define MAX_MEM_LEVEL 8
+#endif
+
+/* Maximum value for windowBits in deflateInit2 and inflateInit2.
+ * WARNING: reducing MAX_WBITS makes minigzip unable to extract .gz files
+ * created by gzip. (Files created by minigzip can still be extracted by
+ * gzip.)
+ */
+#ifndef MAX_WBITS
+# define MAX_WBITS 15 /* 32K LZ77 window */
+#endif
+
+ /* Type declarations */
+
+typedef unsigned char Byte; /* 8 bits */
+typedef unsigned int uInt; /* 16 bits or more */
+typedef unsigned long uLong; /* 32 bits or more */
+typedef void *voidp;
+
+/*#endif*/ /* _ZCONF_H */
+
+/* end of linux/zconf.h */
+
+#if 0
+#define ZLIB_VERSION "1.1.3"
+#endif
+
+/*
+ The 'zlib' compression library provides in-memory compression and
+ decompression functions, including integrity checks of the uncompressed
+ data. This version of the library supports only one compression method
+ (deflation) but other algorithms will be added later and will have the same
+ stream interface.
+
+ Compression can be done in a single step if the buffers are large
+ enough (for example if an input file is mmap'ed), or can be done by
+ repeated calls of the compression function. In the latter case, the
+ application must provide more input and/or consume the output
+ (providing more output space) before each call.
+
+ The library also supports reading and writing files in gzip (.gz) format
+ with an interface similar to that of stdio.
+
+ The library does not install any signal handler. The decoder checks
+ the consistency of the compressed data, so the library should never
+ crash even in case of corrupted input.
+*/
+
+#if 0
+struct zlib_internal_state; /**** pts ****/ /* Dat: was: internal_state */
+
+typedef struct z_stream_s {
+ Byte *next_in; /* next input byte */
+ uInt avail_in; /* number of bytes available at next_in */
+ uLong total_in; /* total nb of input bytes read so far */
+
+ Byte *next_out; /* next output byte should be put there */
+ uInt avail_out; /* remaining free space at next_out */
+ uLong total_out; /* total nb of bytes output so far */
+
+ char *msg; /* last error message, NULLP if no error */
+ struct zlib_internal_state *state; /* not visible by applications */
+
+ void *workspace; /* memory allocated for this stream */
+
+ int data_type; /* best guess about the data type: ascii or binary */
+ uLong adler; /* adler32 value of the uncompressed data */
+ uLong reserved; /* reserved for future use */
+} z_stream;
+
+/*
+ The application must update next_in and avail_in when avail_in has
+ dropped to zero. It must update next_out and avail_out when avail_out
+ has dropped to zero. The application must initialize zalloc, zfree and
+ opaque before calling the init function. All other fields are set by the
+ compression library and must not be updated by the application.
+
+ The opaque value provided by the application will be passed as the first
+ parameter for calls of zalloc and zfree. This can be useful for custom
+ memory management. The compression library attaches no meaning to the
+ opaque value.
+
+ zalloc must return NULLP if there is not enough memory for the object.
+ If zlib is used in a multi-threaded application, zalloc and zfree must be
+ thread safe.
+
+ On 16-bit systems, the functions zalloc and zfree must be able to allocate
+ exactly 65536 bytes, but will not be required to allocate more than this
+ if the symbol MAXSEG_64K is defined (see zconf.h). WARNING: On MSDOS,
+ pointers returned by zalloc for objects of exactly 65536 bytes *must*
+ have their offset normalized to zero. The default allocation function
+ provided by this library ensures this (see zutil.c). To reduce memory
+ requirements and avoid any allocation of 64K objects, at the expense of
+ compression ratio, compile the library with -DMAX_WBITS=14 (see zconf.h).
+
+ The fields total_in and total_out can be used for statistics or
+ progress reports. After compression, total_in holds the total size of
+ the uncompressed data and may be saved for use in the decompressor
+ (particularly if the decompressor wants to decompress everything in
+ a single step).
+*/
+#endif
+typedef z_stream *z_streamp;
+
+ /* constants */
+
+#if 0
+#define Z_NO_FLUSH 0
+#define Z_PARTIAL_FLUSH 1 /* will be removed, use Z_SYNC_FLUSH instead */
+#define Z_PACKET_FLUSH 2
+#define Z_SYNC_FLUSH 3
+#define Z_FULL_FLUSH 4
+#define Z_FINISH 5
+/* Allowed flush values; see deflate() below for details */
+
+#define Z_OK 0
+#define Z_STREAM_END 1
+#define Z_NEED_DICT 2
+#define Z_ERRNO (-1)
+#define Z_STREAM_ERROR (-2)
+#define Z_DATA_ERROR (-3)
+#define Z_MEM_ERROR (-4)
+#define Z_BUF_ERROR (-5)
+#define Z_VERSION_ERROR (-6)
+/* Return codes for the compression/decompression functions. Negative
+ * values are errors, positive values are used for special but normal events.
+ */
+
+#define Z_NO_COMPRESSION 0
+#define Z_BEST_SPEED 1
+#define Z_BEST_COMPRESSION 9
+#define Z_DEFAULT_COMPRESSION (-1)
+/* compression levels */
+#endif
+
+#define Z_FILTERED 1
+#define Z_HUFFMAN_ONLY 2
+#define Z_DEFAULT_STRATEGY 0
+/* compression strategy; see deflateInit2() below for details */
+
+#if 0
+#define Z_BINARY 0
+#define Z_ASCII 1
+#define Z_UNKNOWN 2
+/* Possible values of the data_type field */
+#endif
+
+#define Z_DEFLATED 8
+/* The deflate compression method (the only one supported in this version) */
+
+ /* basic functions */
+
+extern const char * zlib_zlibVersion (void);
+/* The application can compare zlibVersion and ZLIB_VERSION for consistency.
+ If the first character differs, the library code actually used is
+ not compatible with the zlib.h header file used by the application.
+ This check is automatically made by deflateInit and inflateInit.
+ */
+
+extern int zlib_deflate_workspacesize (void);
+/*
+ Returns the number of bytes that needs to be allocated for a per-
+ stream workspace. A pointer to this number of bytes should be
+ returned in stream->workspace before calling zlib_deflateInit().
+*/
+
+/*
+extern int deflateInit (z_streamp strm, int level);
+
+ Initializes the internal stream state for compression. The fields
+ zalloc, zfree and opaque must be initialized before by the caller.
+ If zalloc and zfree are set to NULLP, deflateInit updates them to
+ use default allocation functions.
+
+ The compression level must be Z_DEFAULT_COMPRESSION, or between 0 and 9:
+ 1 gives best speed, 9 gives best compression, 0 gives no compression at
+ all (the input data is simply copied a block at a time).
+ Z_DEFAULT_COMPRESSION requests a default compromise between speed and
+ compression (currently equivalent to level 6).
+
+ deflateInit returns Z_OK if success, Z_MEM_ERROR if there was not
+ enough memory, Z_STREAM_ERROR if level is not a valid compression level,
+ Z_VERSION_ERROR if the zlib library version (zlib_version) is incompatible
+ with the version assumed by the caller (ZLIB_VERSION).
+ msg is set to null if there is no error message. deflateInit does not
+ perform any compression: this will be done by deflate().
+*/
+
+
+extern int zlib_deflate (z_streamp strm, int flush);
+/*
+ deflate compresses as much data as possible, and stops when the input
+ buffer becomes empty or the output buffer becomes full. It may introduce some
+ output latency (reading input without producing any output) except when
+ forced to flush.
+
+ The detailed semantics are as follows. deflate performs one or both of the
+ following actions:
+
+ - Compress more input starting at next_in and update next_in and avail_in
+ accordingly. If not all input can be processed (because there is not
+ enough room in the output buffer), next_in and avail_in are updated and
+ processing will resume at this point for the next call of deflate().
+
+ - Provide more output starting at next_out and update next_out and avail_out
+ accordingly. This action is forced if the parameter flush is non zero.
+ Forcing flush frequently degrades the compression ratio, so this parameter
+ should be set only when necessary (in interactive applications).
+ Some output may be provided even if flush is not set.
+
+ Before the call of deflate(), the application should ensure that at least
+ one of the actions is possible, by providing more input and/or consuming
+ more output, and updating avail_in or avail_out accordingly; avail_out
+ should never be zero before the call. The application can consume the
+ compressed output when it wants, for example when the output buffer is full
+ (avail_out == 0), or after each call of deflate(). If deflate returns Z_OK
+ and with zero avail_out, it must be called again after making room in the
+ output buffer because there might be more output pending.
+
+ If the parameter flush is set to Z_SYNC_FLUSH, all pending output is
+ flushed to the output buffer and the output is aligned on a byte boundary, so
+ that the decompressor can get all input data available so far. (In particular
+ avail_in is zero after the call if enough output space has been provided
+ before the call.) Flushing may degrade compression for some compression
+ algorithms and so it should be used only when necessary.
+
+ If flush is set to Z_FULL_FLUSH, all output is flushed as with
+ Z_SYNC_FLUSH, and the compression state is reset so that decompression can
+ restart from this point if previous compressed data has been damaged or if
+ random access is desired. Using Z_FULL_FLUSH too often can seriously degrade
+ the compression.
+
+ If deflate returns with avail_out == 0, this function must be called again
+ with the same value of the flush parameter and more output space (updated
+ avail_out), until the flush is complete (deflate returns with non-zero
+ avail_out).
+
+ If the parameter flush is set to Z_FINISH, pending input is processed,
+ pending output is flushed and deflate returns with Z_STREAM_END if there
+ was enough output space; if deflate returns with Z_OK, this function must be
+ called again with Z_FINISH and more output space (updated avail_out) but no
+ more input data, until it returns with Z_STREAM_END or an error. After
+ deflate has returned Z_STREAM_END, the only possible operations on the
+ stream are deflateReset or deflateEnd.
+
+ Z_FINISH can be used immediately after deflateInit if all the compression
+ is to be done in a single step. In this case, avail_out must be at least
+ 0.1% larger than avail_in plus 12 bytes. If deflate does not return
+ Z_STREAM_END, then it must be called again as described above.
+
+ deflate() sets strm->adler to the adler32 checksum of all input read
+ so far (that is, total_in bytes).
+
+ deflate() may update data_type if it can make a good guess about
+ the input data type (Z_ASCII or Z_BINARY). In doubt, the data is considered
+ binary. This field is only for information purposes and does not affect
+ the compression algorithm in any manner.
+
+ deflate() returns Z_OK if some progress has been made (more input
+ processed or more output produced), Z_STREAM_END if all input has been
+ consumed and all output has been produced (only when flush is set to
+ Z_FINISH), Z_STREAM_ERROR if the stream state was inconsistent (for example
+ if next_in or next_out was NULLP), Z_BUF_ERROR if no progress is possible
+ (for example avail_in or avail_out was zero).
+*/
+
+
+extern int zlib_deflateEnd (z_streamp strm);
+/*
+ All dynamically allocated data structures for this stream are freed.
+ This function discards any unprocessed input and does not flush any
+ pending output.
+
+ deflateEnd returns Z_OK if success, Z_STREAM_ERROR if the
+ stream state was inconsistent, Z_DATA_ERROR if the stream was freed
+ prematurely (some input or output was discarded). In the error case,
+ msg may be set but then points to a static string (which must not be
+ deallocated).
+*/
+
+
+extern int zlib_inflate_workspacesize (void);
+/*
+ Returns the number of bytes that needs to be allocated for a per-
+ stream workspace. A pointer to this number of bytes should be
+ returned in stream->workspace before calling zlib_inflateInit().
+*/
+
+/*
+extern int zlib_inflateInit (z_streamp strm);
+
+ Initializes the internal stream state for decompression. The fields
+ next_in, avail_in, and workspace must be initialized before by
+ the caller. If next_in is not NULLP and avail_in is large enough (the exact
+ value depends on the compression method), inflateInit determines the
+ compression method from the zlib header and allocates all data structures
+ accordingly; otherwise the allocation will be deferred to the first call of
+ inflate. If zalloc and zfree are set to NULLP, inflateInit updates them to
+ use default allocation functions.
+
+ inflateInit returns Z_OK if success, Z_MEM_ERROR if there was not enough
+ memory, Z_VERSION_ERROR if the zlib library version is incompatible with the
+ version assumed by the caller. msg is set to null if there is no error
+ message. inflateInit does not perform any decompression apart from reading
+ the zlib header if present: this will be done by inflate(). (So next_in and
+ avail_in may be modified, but next_out and avail_out are unchanged.)
+*/
+
+
+extern int zlib_inflate (z_streamp strm, int flush);
+/*
+ inflate decompresses as much data as possible, and stops when the input
+ buffer becomes empty or the output buffer becomes full. It may some
+ introduce some output latency (reading input without producing any output)
+ except when forced to flush.
+
+ The detailed semantics are as follows. inflate performs one or both of the
+ following actions:
+
+ - Decompress more input starting at next_in and update next_in and avail_in
+ accordingly. If not all input can be processed (because there is not
+ enough room in the output buffer), next_in is updated and processing
+ will resume at this point for the next call of inflate().
+
+ - Provide more output starting at next_out and update next_out and avail_out
+ accordingly. inflate() provides as much output as possible, until there
+ is no more input data or no more space in the output buffer (see below
+ about the flush parameter).
+
+ Before the call of inflate(), the application should ensure that at least
+ one of the actions is possible, by providing more input and/or consuming
+ more output, and updating the next_* and avail_* values accordingly.
+ The application can consume the uncompressed output when it wants, for
+ example when the output buffer is full (avail_out == 0), or after each
+ call of inflate(). If inflate returns Z_OK and with zero avail_out, it
+ must be called again after making room in the output buffer because there
+ might be more output pending.
+
+ If the parameter flush is set to Z_SYNC_FLUSH, inflate flushes as much
+ output as possible to the output buffer. The flushing behavior of inflate is
+ not specified for values of the flush parameter other than Z_SYNC_FLUSH
+ and Z_FINISH, but the current implementation actually flushes as much output
+ as possible anyway.
+
+ inflate() should normally be called until it returns Z_STREAM_END or an
+ error. However if all decompression is to be performed in a single step
+ (a single call of inflate), the parameter flush should be set to
+ Z_FINISH. In this case all pending input is processed and all pending
+ output is flushed; avail_out must be large enough to hold all the
+ uncompressed data. (The size of the uncompressed data may have been saved
+ by the compressor for this purpose.) The next operation on this stream must
+ be inflateEnd to deallocate the decompression state. The use of Z_FINISH
+ is never required, but can be used to inform inflate that a faster routine
+ may be used for the single inflate() call.
+
+ If a preset dictionary is needed at this point (see inflateSetDictionary
+ below), inflate sets strm-adler to the adler32 checksum of the
+ dictionary chosen by the compressor and returns Z_NEED_DICT; otherwise
+ it sets strm->adler to the adler32 checksum of all output produced
+ so far (that is, total_out bytes) and returns Z_OK, Z_STREAM_END or
+ an error code as described below. At the end of the stream, inflate()
+ checks that its computed adler32 checksum is equal to that saved by the
+ compressor and returns Z_STREAM_END only if the checksum is correct.
+
+ inflate() returns Z_OK if some progress has been made (more input processed
+ or more output produced), Z_STREAM_END if the end of the compressed data has
+ been reached and all uncompressed output has been produced, Z_NEED_DICT if a
+ preset dictionary is needed at this point, Z_DATA_ERROR if the input data was
+ corrupted (input stream not conforming to the zlib format or incorrect
+ adler32 checksum), Z_STREAM_ERROR if the stream structure was inconsistent
+ (for example if next_in or next_out was NULLP), Z_MEM_ERROR if there was not
+ enough memory, Z_BUF_ERROR if no progress is possible or if there was not
+ enough room in the output buffer when Z_FINISH is used. In the Z_DATA_ERROR
+ case, the application may then call inflateSync to look for a good
+ compression block.
+*/
+
+
+extern int zlib_inflateEnd (z_streamp strm);
+/*
+ All dynamically allocated data structures for this stream are freed.
+ This function discards any unprocessed input and does not flush any
+ pending output.
+
+ inflateEnd returns Z_OK if success, Z_STREAM_ERROR if the stream state
+ was inconsistent. In the error case, msg may be set but then points to a
+ static string (which must not be deallocated).
+*/
+
+ /* Advanced functions */
+
+/*
+ The following functions are needed only in some special applications.
+*/
+
+/*
+extern int deflateInit2 (z_streamp strm,
+ int level,
+ int method,
+ int windowBits,
+ int memLevel,
+ int strategy);
+
+ This is another version of deflateInit with more compression options. The
+ fields next_in, zalloc, zfree and opaque must be initialized before by
+ the caller.
+
+ The method parameter is the compression method. It must be Z_DEFLATED in
+ this version of the library.
+
+ The windowBits parameter is the base two logarithm of the window size
+ (the size of the history buffer). It should be in the range 8..15 for this
+ version of the library. Larger values of this parameter result in better
+ compression at the expense of memory usage. The default value is 15 if
+ deflateInit is used instead.
+
+ The memLevel parameter specifies how much memory should be allocated
+ for the internal compression state. memLevel=1 uses minimum memory but
+ is slow and reduces compression ratio; memLevel=9 uses maximum memory
+ for optimal speed. The default value is 8. See zconf.h for total memory
+ usage as a function of windowBits and memLevel.
+
+ The strategy parameter is used to tune the compression algorithm. Use the
+ value Z_DEFAULT_STRATEGY for normal data, Z_FILTERED for data produced by a
+ filter (or predictor), or Z_HUFFMAN_ONLY to force Huffman encoding only (no
+ string match). Filtered data consists mostly of small values with a
+ somewhat random distribution. In this case, the compression algorithm is
+ tuned to compress them better. The effect of Z_FILTERED is to force more
+ Huffman coding and less string matching; it is somewhat intermediate
+ between Z_DEFAULT and Z_HUFFMAN_ONLY. The strategy parameter only affects
+ the compression ratio but not the correctness of the compressed output even
+ if it is not set appropriately.
+
+ deflateInit2 returns Z_OK if success, Z_MEM_ERROR if there was not enough
+ memory, Z_STREAM_ERROR if a parameter is invalid (such as an invalid
+ method). msg is set to null if there is no error message. deflateInit2 does
+ not perform any compression: this will be done by deflate().
+*/
+
+extern int zlib_deflateSetDictionary (z_streamp strm,
+ const Byte *dictionary,
+ uInt dictLength);
+/*
+ Initializes the compression dictionary from the given byte sequence
+ without producing any compressed output. This function must be called
+ immediately after deflateInit, deflateInit2 or deflateReset, before any
+ call of deflate. The compressor and decompressor must use exactly the same
+ dictionary (see inflateSetDictionary).
+
+ The dictionary should consist of strings (byte sequences) that are likely
+ to be encountered later in the data to be compressed, with the most commonly
+ used strings preferably put towards the end of the dictionary. Using a
+ dictionary is most useful when the data to be compressed is short and can be
+ predicted with good accuracy; the data can then be compressed better than
+ with the default empty dictionary.
+
+ Depending on the size of the compression data structures selected by
+ deflateInit or deflateInit2, a part of the dictionary may in effect be
+ discarded, for example if the dictionary is larger than the window size in
+ deflate or deflate2. Thus the strings most likely to be useful should be
+ put at the end of the dictionary, not at the front.
+
+ Upon return of this function, strm->adler is set to the Adler32 value
+ of the dictionary; the decompressor may later use this value to determine
+ which dictionary has been used by the compressor. (The Adler32 value
+ applies to the whole dictionary even if only a subset of the dictionary is
+ actually used by the compressor.)
+
+ deflateSetDictionary returns Z_OK if success, or Z_STREAM_ERROR if a
+ parameter is invalid (such as NULLP dictionary) or the stream state is
+ inconsistent (for example if deflate has already been called for this stream
+ or if the compression method is bsort). deflateSetDictionary does not
+ perform any compression: this will be done by deflate().
+*/
+
+extern int zlib_deflateCopy (z_streamp dest, z_streamp source);
+/*
+ Sets the destination stream as a complete copy of the source stream.
+
+ This function can be useful when several compression strategies will be
+ tried, for example when there are several ways of pre-processing the input
+ data with a filter. The streams that will be discarded should then be freed
+ by calling deflateEnd. Note that deflateCopy duplicates the internal
+ compression state which can be quite large, so this strategy is slow and
+ can consume lots of memory.
+
+ deflateCopy returns Z_OK if success, Z_MEM_ERROR if there was not
+ enough memory, Z_STREAM_ERROR if the source stream state was inconsistent
+ (such as zalloc being NULLP). msg is left unchanged in both source and
+ destination.
+*/
+
+extern int zlib_deflateReset (z_streamp strm);
+/*
+ This function is equivalent to deflateEnd followed by deflateInit,
+ but does not free and reallocate all the internal compression state.
+ The stream will keep the same compression level and any other attributes
+ that may have been set by deflateInit2.
+
+ deflateReset returns Z_OK if success, or Z_STREAM_ERROR if the source
+ stream state was inconsistent (such as zalloc or state being NULLP).
+*/
+
+extern int zlib_deflateParams (z_streamp strm, int level, int strategy);
+/*
+ Dynamically update the compression level and compression strategy. The
+ interpretation of level and strategy is as in deflateInit2. This can be
+ used to switch between compression and straight copy of the input data, or
+ to switch to a different kind of input data requiring a different
+ strategy. If the compression level is changed, the input available so far
+ is compressed with the old level (and may be flushed); the new level will
+ take effect only at the next call of deflate().
+
+ Before the call of deflateParams, the stream state must be set as for
+ a call of deflate(), since the currently available input may have to
+ be compressed and flushed. In particular, strm->avail_out must be non-zero.
+
+ deflateParams returns Z_OK if success, Z_STREAM_ERROR if the source
+ stream state was inconsistent or if a parameter was invalid, Z_BUF_ERROR
+ if strm->avail_out was zero.
+*/
+
+/*
+extern int inflateInit2 (z_streamp strm, int windowBits);
+
+ This is another version of inflateInit with an extra parameter. The
+ fields next_in, avail_in, zalloc, zfree and opaque must be initialized
+ before by the caller.
+
+ The windowBits parameter is the base two logarithm of the maximum window
+ size (the size of the history buffer). It should be in the range 8..15 for
+ this version of the library. The default value is 15 if inflateInit is used
+ instead. If a compressed stream with a larger window size is given as
+ input, inflate() will return with the error code Z_DATA_ERROR instead of
+ trying to allocate a larger window.
+
+ inflateInit2 returns Z_OK if success, Z_MEM_ERROR if there was not enough
+ memory, Z_STREAM_ERROR if a parameter is invalid (such as a negative
+ memLevel). msg is set to null if there is no error message. inflateInit2
+ does not perform any decompression apart from reading the zlib header if
+ present: this will be done by inflate(). (So next_in and avail_in may be
+ modified, but next_out and avail_out are unchanged.)
+*/
+
+extern int zlib_inflateSetDictionary (z_streamp strm,
+ const Byte *dictionary,
+ uInt dictLength);
+/*
+ Initializes the decompression dictionary from the given uncompressed byte
+ sequence. This function must be called immediately after a call of inflate
+ if this call returned Z_NEED_DICT. The dictionary chosen by the compressor
+ can be determined from the Adler32 value returned by this call of
+ inflate. The compressor and decompressor must use exactly the same
+ dictionary (see deflateSetDictionary).
+
+ inflateSetDictionary returns Z_OK if success, Z_STREAM_ERROR if a
+ parameter is invalid (such as NULLP dictionary) or the stream state is
+ inconsistent, Z_DATA_ERROR if the given dictionary doesn't match the
+ expected one (incorrect Adler32 value). inflateSetDictionary does not
+ perform any decompression: this will be done by subsequent calls of
+ inflate().
+*/
+
+extern int zlib_inflateSync (z_streamp strm);
+/*
+ Skips invalid compressed data until a full flush point (see above the
+ description of deflate with Z_FULL_FLUSH) can be found, or until all
+ available input is skipped. No output is provided.
+
+ inflateSync returns Z_OK if a full flush point has been found, Z_BUF_ERROR
+ if no more input was provided, Z_DATA_ERROR if no flush point has been found,
+ or Z_STREAM_ERROR if the stream structure was inconsistent. In the success
+ case, the application may save the current current value of total_in which
+ indicates where valid compressed data was found. In the error case, the
+ application may repeatedly call inflateSync, providing more input each time,
+ until success or end of the input data.
+*/
+
+extern int zlib_inflateReset (z_streamp strm);
+/*
+ This function is equivalent to inflateEnd followed by inflateInit,
+ but does not free and reallocate all the internal decompression state.
+ The stream will keep attributes that may have been set by inflateInit2.
+
+ inflateReset returns Z_OK if success, or Z_STREAM_ERROR if the source
+ stream state was inconsistent (such as zalloc or state being NULLP).
+*/
+
+extern int zlib_inflateIncomp (z_stream *strm);
+/*
+ This function adds the data at next_in (avail_in bytes) to the output
+ history without performing any output. There must be no pending output,
+ and the decompressor must be expecting to see the start of a block.
+ Calling this function is equivalent to decompressing a stored block
+ containing the data at next_in (except that the data is not output).
+*/
+
+ /* various hacks, don't look :) */
+
+/* deflateInit and inflateInit are macros to allow checking the zlib version
+ * and the compiler's view of z_stream:
+ */
+extern int zlib_deflateInit_ (z_streamp strm, int level,
+ const char *version, int stream_size);
+extern int zlib_inflateInit_ (z_streamp strm,
+ const char *version, int stream_size);
+extern int zlib_deflateInit2_ (z_streamp strm, int level, int method,
+ int windowBits, int memLevel,
+ int strategy, const char *version,
+ int stream_size);
+extern int zlib_inflateInit2_ (z_streamp strm, int windowBits,
+ const char *version, int stream_size);
+#if 0 /**** pts ****/
+#define zlib_deflateInit(strm, level) \
+ zlib_deflateInit_((strm), (level), ZLIB_VERSION, sizeof(z_stream))
+#define zlib_inflateInit(strm) \
+ zlib_inflateInit_((strm), ZLIB_VERSION, sizeof(z_stream))
+#define zlib_deflateInit2(strm, level, method, windowBits, memLevel, strategy) \
+ zlib_deflateInit2_((strm),(level),(method),(windowBits),(memLevel),\
+ (strategy), ZLIB_VERSION, sizeof(z_stream))
+#define zlib_inflateInit2(strm, windowBits) \
+ zlib_inflateInit2_((strm), (windowBits), ZLIB_VERSION, sizeof(z_stream))
+#endif
+
+#if !defined(_Z_UTIL_H) && !defined(NO_DUMMY_DECL)
+ struct zlib_internal_state {int dummy;}; /* hack for buggy compilers */
+#endif
+
+extern const char * zlib_zError (int err);
+extern int zlib_inflateSyncPoint (z_streamp z);
+extern const uLong * zlib_get_crc_table (void);
+
+/**** pts ****/
+#define max(a,b) ((a)<(b) ? (b) : (a))
+
+
+typedef unsigned char uch;
+typedef unsigned short ush;
+typedef unsigned long ulg;
+
+ /* common constants */
+
+#ifndef DEF_WBITS
+# define DEF_WBITS MAX_WBITS
+#endif
+/* default windowBits for decompression. MAX_WBITS is for compression only */
+
+#if MAX_MEM_LEVEL >= 8
+# define DEF_MEM_LEVEL 8
+#else
+# define DEF_MEM_LEVEL MAX_MEM_LEVEL
+#endif
+/* default memLevel */
+
+#define STORED_BLOCK 0
+#define STATIC_TREES 1
+#define DYN_TREES 2
+/* The three kinds of block type */
+
+#define MIN_MATCH 3
+#define MAX_MATCH 258
+/* The minimum and maximum match lengths */
+
+#define PRESET_DICT 0x20 /* preset dictionary flag in zlib header */
+
+ /* target dependencies */
+
+ /* Common defaults */
+
+#ifndef OS_CODE
+# define OS_CODE 0x03 /* assume Unix */
+#endif
+
+ /* functions */
+
+typedef uLong (*check_func) (uLong check, const Byte *buf,
+ uInt len);
+
+
+ /* checksum functions */
+
+#define BASE 65521L /* largest prime smaller than 65536 */
+#define NMAX 5552
+/* NMAX is the largest n such that 255n(n+1)/2 + (n+1)(BASE-1) <= 2^32-1 */
+
+#define DO1(buf,i) {s1 += buf[i]; s2 += s1;}
+#define DO2(buf,i) DO1(buf,i); DO1(buf,i+1);
+#define DO4(buf,i) DO2(buf,i); DO2(buf,i+2);
+#define DO8(buf,i) DO4(buf,i); DO4(buf,i+4);
+#define DO16(buf) DO8(buf,0); DO8(buf,8);
+
+/* ========================================================================= */
+/*
+ Update a running Adler-32 checksum with the bytes buf[0..len-1] and
+ return the updated checksum. If buf is NULLP, this function returns
+ the required initial value for the checksum.
+ An Adler-32 checksum is almost as reliable as a CRC32 but can be computed
+ much faster. Usage example:
+
+ uLong adler = adler32(0L, NULLP, 0);
+
+ while (read_buffer(buffer, length) != EOF) {
+ adler = adler32(adler, buffer, length);
+ }
+ if (adler != original_adler) error();
+*/
+static ZINLINE uLong zlib_adler32(uLong adler,
+ const Byte *buf,
+ uInt len)
+{
+ unsigned long s1 = adler & 0xffff;
+ unsigned long s2 = (adler >> 16) & 0xffff;
+ int k;
+
+ if (buf == NULLP) return 1L;
+
+ while (len > 0) {
+ k = len < NMAX ? len : NMAX;
+ len -= k;
+ while (k >= 16) {
+ DO16(buf);
+ buf += 16;
+ k -= 16;
+ }
+ if (k != 0) do {
+ s1 += *buf++;
+ s2 += s1;
+ } while (--k);
+ s1 %= BASE;
+ s2 %= BASE;
+ }
+ return (s2 << 16) | s1;
+}
+
+#endif /* _Z_UTIL_H */
+
+/* end of zutil.h */
+
+/* #include "defutil.h" */
+
+#define Assert(err, str)
+#define Trace(dummy)
+#define Tracev(dummy)
+#define Tracecv(err, dummy)
+#define Tracevv(dummy)
+
+#define LENGTH_CODES 29
+/* number of length codes, not counting the special END_BLOCK code */
+
+#define LITERALS 256
+/* number of literal bytes 0..255 */
+
+#define L_CODES (LITERALS+1+LENGTH_CODES)
+/* number of Literal or Length codes, including the END_BLOCK code */
+
+#define D_CODES 30
+/* number of distance codes */
+
+#define BL_CODES 19
+/* number of codes used to transfer the bit lengths */
+
+#define HEAP_SIZE (2*L_CODES+1)
+/* maximum heap size */
+
+#define MAX_BITS 15
+/* All codes must not exceed MAX_BITS bits */
+
+#define INIT_STATE 42
+#define BUSY_STATE 113
+#define FINISH_STATE 666
+/* Stream status */
+
+
+/* Data structure describing a single value and its code string. */
+typedef struct ct_data_s {
+ union {
+ ush freq; /* frequency count */
+ ush code; /* bit string */
+ } fc;
+ union {
+ ush dad; /* father node in Huffman tree */
+ ush len; /* length of bit string */
+ } dl;
+} ct_data;
+
+#define Freq fc.freq
+#define Code fc.code
+#define Dad dl.dad
+#define Len dl.len
+
+typedef struct static_tree_desc_s static_tree_desc;
+
+typedef struct tree_desc_s {
+ ct_data *dyn_tree; /* the dynamic tree */
+ int max_code; /* largest code with non zero frequency */
+ static_tree_desc *stat_desc; /* the corresponding static tree */
+} tree_desc;
+
+typedef ush Pos;
+typedef unsigned IPos;
+
+/* A Pos is an index in the character window. We use short instead of int to
+ * save space in the various tables. IPos is used only for parameter passing.
+ */
+
+typedef struct deflate_state {
+ z_streamp strm; /* pointer back to this zlib stream */
+ int status; /* as the name implies */
+ Byte *pending_buf; /* output still pending */
+ ulg pending_buf_size; /* size of pending_buf */
+ Byte *pending_out; /* next pending byte to output to the stream */
+ int pending; /* nb of bytes in the pending buffer */
+ int noheader; /* suppress zlib header and adler32 */
+ Byte data_type; /* UNKNOWN, BINARY or ASCII */
+ Byte method; /* STORED (for zip only) or DEFLATED */
+ int last_flush; /* value of flush param for previous deflate call */
+
+ /* used by deflate.c: */
+
+ uInt w_size; /* LZ77 window size (32K by default) */
+ uInt w_bits; /* log2(w_size) (8..16) */
+ uInt w_mask; /* w_size - 1 */
+
+ Byte *window;
+ /* Sliding window. Input bytes are read into the second half of the window,
+ * and move to the first half later to keep a dictionary of at least wSize
+ * bytes. With this organization, matches are limited to a distance of
+ * wSize-MAX_MATCH bytes, but this ensures that IO is always
+ * performed with a length multiple of the block size. Also, it limits
+ * the window size to 64K, which is quite useful on MSDOS.
+ * To do: use the user input buffer as sliding window.
+ */
+
+ ulg window_size;
+ /* Actual size of window: 2*wSize, except when the user input buffer
+ * is directly used as sliding window.
+ */
+
+ Pos *prev;
+ /* Link to older string with same hash index. To limit the size of this
+ * array to 64K, this link is maintained only for the last 32K strings.
+ * An index in this array is thus a window index modulo 32K.
+ */
+
+ Pos *head; /* Heads of the hash chains or NIL. */
+
+ uInt ins_h; /* hash index of string to be inserted */
+ uInt hash_size; /* number of elements in hash table */
+ uInt hash_bits; /* log2(hash_size) */
+ uInt hash_mask; /* hash_size-1 */
+
+ uInt hash_shift;
+ /* Number of bits by which ins_h must be shifted at each input
+ * step. It must be such that after MIN_MATCH steps, the oldest
+ * byte no longer takes part in the hash key, that is:
+ * hash_shift * MIN_MATCH >= hash_bits
+ */
+
+ long block_start;
+ /* Window position at the beginning of the current output block. Gets
+ * negative when the window is moved backwards.
+ */
+
+ uInt match_length; /* length of best match */
+ IPos prev_match; /* previous match */
+ int match_available; /* set if previous match exists */
+ uInt strstart; /* start of string to insert */
+ uInt match_start; /* start of matching string */
+ uInt lookahead; /* number of valid bytes ahead in window */
+
+ uInt prev_length;
+ /* Length of the best match at previous step. Matches not greater than this
+ * are discarded. This is used in the lazy match evaluation.
+ */
+
+ uInt max_chain_length;
+ /* To speed up deflation, hash chains are never searched beyond this
+ * length. A higher limit improves compression ratio but degrades the
+ * speed.
+ */
+
+ uInt max_lazy_match;
+ /* Attempt to find a better match only when the current match is strictly
+ * smaller than this value. This mechanism is used only for compression
+ * levels >= 4.
+ */
+# define max_insert_length max_lazy_match
+ /* Insert new strings in the hash table only if the match length is not
+ * greater than this length. This saves time but degrades compression.
+ * max_insert_length is used only for compression levels <= 3.
+ */
+
+ int level; /* compression level (1..9) */
+ int strategy; /* favor or force Huffman coding*/
+
+ uInt good_match;
+ /* Use a faster search when the previous match is longer than this */
+
+ int nice_match; /* Stop searching when current match exceeds this */
+
+ /* used by trees.c: */
+ /* Didn't use ct_data typedef below to supress compiler warning */
+ struct ct_data_s dyn_ltree[HEAP_SIZE]; /* literal and length tree */
+ struct ct_data_s dyn_dtree[2*D_CODES+1]; /* distance tree */
+ struct ct_data_s bl_tree[2*BL_CODES+1]; /* Huffman tree for bit lengths */
+
+ struct tree_desc_s l_desc; /* desc. for literal tree */
+ struct tree_desc_s d_desc; /* desc. for distance tree */
+ struct tree_desc_s bl_desc; /* desc. for bit length tree */
+
+ ush bl_count[MAX_BITS+1];
+ /* number of codes at each bit length for an optimal tree */
+
+ int heap[2*L_CODES+1]; /* heap used to build the Huffman trees */
+ int heap_len; /* number of elements in the heap */
+ int heap_max; /* element of largest frequency */
+ /* The sons of heap[n] are heap[2*n] and heap[2*n+1]. heap[0] is not used.
+ * The same heap array is used to build all trees.
+ */
+
+ uch depth[2*L_CODES+1];
+ /* Depth of each subtree used as tie breaker for trees of equal frequency
+ */
+
+ uch *l_buf; /* buffer for literals or lengths */
+
+ uInt lit_bufsize;
+ /* Size of match buffer for literals/lengths. There are 4 reasons for
+ * limiting lit_bufsize to 64K:
+ * - frequencies can be kept in 16 bit counters
+ * - if compression is not successful for the first block, all input
+ * data is still in the window so we can still emit a stored block even
+ * when input comes from standard input. (This can also be done for
+ * all blocks if lit_bufsize is not greater than 32K.)
+ * - if compression is not successful for a file smaller than 64K, we can
+ * even emit a stored file instead of a stored block (saving 5 bytes).
+ * This is applicable only for zip (not gzip or zlib).
+ * - creating new Huffman trees less frequently may not provide fast
+ * adaptation to changes in the input data statistics. (Take for
+ * example a binary file with poorly compressible code followed by
+ * a highly compressible string table.) Smaller buffer sizes give
+ * fast adaptation but have of course the overhead of transmitting
+ * trees more frequently.
+ * - I can't count above 4
+ */
+
+ uInt last_lit; /* running index in l_buf */
+
+ ush *d_buf;
+ /* Buffer for distances. To simplify the code, d_buf and l_buf have
+ * the same number of elements. To use different lengths, an extra flag
+ * array would be necessary.
+ */
+
+ ulg opt_len; /* bit length of current block with optimal trees */
+ ulg static_len; /* bit length of current block with static trees */
+ ulg compressed_len; /* total bit length of compressed file */
+ uInt matches; /* number of string matches in current block */
+ int last_eob_len; /* bit length of EOB code for last block */
+
+#ifdef DEBUG_ZLIB
+ ulg bits_sent; /* bit length of the compressed data */
+#endif
+
+ ush bi_buf;
+ /* Output buffer. bits are inserted starting at the bottom (least
+ * significant bits).
+ */
+ int bi_valid;
+ /* Number of valid bits in bi_buf. All bits above the last valid bit
+ * are always zero.
+ */
+
+} deflate_state;
+
+typedef struct deflate_workspace {
+ /* State memory for the deflator */
+ deflate_state deflate_memory;
+ Byte window_memory[2 * (1 << MAX_WBITS)];
+ Pos prev_memory[1 << MAX_WBITS];
+ Pos head_memory[1 << (MAX_MEM_LEVEL + 7)];
+ char overlay_memory[(1 << (MAX_MEM_LEVEL + 6)) * (sizeof(ush)+2)];
+} deflate_workspace;
+
+/* Output a byte on the stream.
+ * IN assertion: there is enough room in pending_buf.
+ */
+#define put_byte(s, c) {s->pending_buf[s->pending++] = (c);}
+
+
+#define MIN_LOOKAHEAD (MAX_MATCH+MIN_MATCH+1)
+/* Minimum amount of lookahead, except at the end of the input file.
+ * See deflate.c for comments about the MIN_MATCH+1.
+ */
+
+#define MAX_DIST(s) ((s)->w_size-MIN_LOOKAHEAD)
+/* In order to simplify the code, particularly on 16 bit machines, match
+ * distances are limited to MAX_DIST instead of WSIZE.
+ */
+
+ /* in trees.c */
+ZSTATIC void zlib_tr_init (deflate_state *s);
+ZSTATIC int zlib_tr_tally (deflate_state *s, unsigned dist, unsigned lc);
+ZSTATIC ulg zlib_tr_flush_block (deflate_state *s, char *buf, ulg stored_len,
+ int eof);
+ZSTATIC void zlib_tr_align (deflate_state *s);
+ZSTATIC void zlib_tr_stored_block (deflate_state *s, char *buf, ulg stored_len,
+ int eof);
+ZSTATIC void zlib_tr_stored_type_only (deflate_state *);
+
+
+/* ===========================================================================
+ * Output a short LSB first on the stream.
+ * IN assertion: there is enough room in pendingBuf.
+ */
+#define put_short(s, w) { \
+ put_byte(s, (uch)((w) & 0xff)); \
+ put_byte(s, (uch)((ush)(w) >> 8)); \
+}
+
+/* ===========================================================================
+ * Reverse the first len bits of a code, using straightforward code (a faster
+ * method would use a table)
+ * IN assertion: 1 <= len <= 15
+ */
+static ZINLINE unsigned bi_reverse(unsigned code, /* the value to invert */
+ int len) /* its bit length */
+{
+ register unsigned res = 0;
+ do {
+ res |= code & 1;
+ code >>= 1, res <<= 1;
+ } while (--len > 0);
+ return res >> 1;
+}
+
+/* ===========================================================================
+ * Flush the bit buffer, keeping at most 7 bits in it.
+ */
+static ZINLINE void bi_flush(deflate_state *s)
+{
+ if (s->bi_valid == 16) {
+ put_short(s, s->bi_buf);
+ s->bi_buf = 0;
+ s->bi_valid = 0;
+ } else if (s->bi_valid >= 8) {
+ put_byte(s, (Byte)s->bi_buf);
+ s->bi_buf >>= 8;
+ s->bi_valid -= 8;
+ }
+}
+
+/* ===========================================================================
+ * Flush the bit buffer and align the output on a byte boundary
+ */
+static ZINLINE void bi_windup(deflate_state *s)
+{
+ if (s->bi_valid > 8) {
+ put_short(s, s->bi_buf);
+ } else if (s->bi_valid > 0) {
+ put_byte(s, (Byte)s->bi_buf);
+ }
+ s->bi_buf = 0;
+ s->bi_valid = 0;
+#ifdef DEBUG_ZLIB
+ s->bits_sent = (s->bits_sent+7) & ~7;
+#endif
+}
+
+
+/* end of defutil.h */
+
+#if USE_ZLIB_MEM
+# include <string.h> /* memcpy(), memset() */
+# define zmemcpy(a,b,c) memcpy(a,b,c)
+# define zmemset(a,b,c) memset(a,b,c)
+#else
+static void *zmemcpy(void * dest,const void *src,unsigned count) {
+ char *tmp = (char *) dest;
+ char const *s = (char const*) src;
+ while (count--) *tmp++ = *s++;
+ return dest;
+}
+static void *zmemset(void * s,int c,unsigned count) {
+ char *xs = (char *) s;
+ while (count--) *xs++ = c;
+ return s;
+}
+#endif
+
+
+/* ===========================================================================
+ * Function prototypes.
+ */
+typedef enum {
+ need_more, /* block not completed, need more input or more output */
+ block_done, /* block flush performed */
+ finish_started, /* finish started, need only more output at next deflate */
+ finish_done /* finish done, accept no more input or output */
+} block_state;
+
+typedef block_state (*compress_func) (deflate_state *s, int flush);
+/* Compression function. Returns the block state after the call. */
+
+static void fill_window (deflate_state *s);
+static block_state deflate_stored (deflate_state *s, int flush);
+static block_state deflate_fast (deflate_state *s, int flush);
+static block_state deflate_slow (deflate_state *s, int flush);
+static void lm_init (deflate_state *s);
+static void putShortMSB (deflate_state *s, uInt b);
+static void flush_pending (z_streamp strm);
+static int read_buf (z_streamp strm, Byte *buf, unsigned size);
+static uInt longest_match (deflate_state *s, IPos cur_match);
+
+#ifdef DEBUG_ZLIB
+static void check_match (deflate_state *s, IPos start, IPos match,
+ int length);
+#endif
+
+/* ===========================================================================
+ * Local data
+ */
+
+#define NIL 0
+/* Tail of hash chains */
+
+#ifndef TOO_FAR
+# define TOO_FAR 4096
+#endif
+/* Matches of length 3 are discarded if their distance exceeds TOO_FAR */
+
+#define MIN_LOOKAHEAD (MAX_MATCH+MIN_MATCH+1)
+/* Minimum amount of lookahead, except at the end of the input file.
+ * See deflate.c for comments about the MIN_MATCH+1.
+ */
+
+/* Values for max_lazy_match, good_match and max_chain_length, depending on
+ * the desired pack level (0..9). The values given below have been tuned to
+ * exclude worst case performance for pathological files. Better values may be
+ * found for specific files.
+ */
+typedef struct config_s {
+ ush good_length; /* reduce lazy search above this match length */
+ ush max_lazy; /* do not perform lazy search above this match length */
+ ush nice_length; /* quit search above this match length */
+ ush max_chain;
+ compress_func func;
+} config;
+
+static const config configuration_table[10] = {
+/* good lazy nice chain */
+/* 0 */ {0, 0, 0, 0, deflate_stored}, /* store only */
+/* 1 */ {4, 4, 8, 4, deflate_fast}, /* maximum speed, no lazy matches */
+/* 2 */ {4, 5, 16, 8, deflate_fast},
+/* 3 */ {4, 6, 32, 32, deflate_fast},
+
+/* 4 */ {4, 4, 16, 16, deflate_slow}, /* lazy matches */
+/* 5 */ {8, 16, 32, 32, deflate_slow},
+/* 6 */ {8, 16, 128, 128, deflate_slow},
+/* 7 */ {8, 32, 128, 256, deflate_slow},
+/* 8 */ {32, 128, 258, 1024, deflate_slow},
+/* 9 */ {32, 258, 258, 4096, deflate_slow}}; /* maximum compression */
+
+/* Note: the deflate() code requires max_lazy >= MIN_MATCH and max_chain >= 4
+ * For deflate_fast() (levels <= 3) good is ignored and lazy has a different
+ * meaning.
+ */
+
+#define EQUAL 0
+/* result of memcmp for equal strings */
+
+/* ===========================================================================
+ * Update a hash value with the given input byte
+ * IN assertion: all calls to to UPDATE_HASH are made with consecutive
+ * input characters, so that a running hash key can be computed from the
+ * previous key instead of complete recalculation each time.
+ */
+#define UPDATE_HASH(s,h,c) (h = (((h)<<s->hash_shift) ^ (c)) & s->hash_mask)
+
+
+/* ===========================================================================
+ * Insert string str in the dictionary and set match_head to the previous head
+ * of the hash chain (the most recent string with same hash key). Return
+ * the previous length of the hash chain.
+ * IN assertion: all calls to to INSERT_STRING are made with consecutive
+ * input characters and the first MIN_MATCH bytes of str are valid
+ * (except for the last MIN_MATCH-1 bytes of the input file).
+ */
+#define INSERT_STRING(s, str, match_head) \
+ (UPDATE_HASH(s, s->ins_h, s->window[(str) + (MIN_MATCH-1)]), \
+ s->prev[(str) & s->w_mask] = match_head = s->head[s->ins_h], \
+ s->head[s->ins_h] = (Pos)(str))
+
+/* ===========================================================================
+ * Initialize the hash table (avoiding 64K overflow for 16 bit systems).
+ * prev[] will be initialized on the fly.
+ */
+#define CLEAR_HASH(s) \
+ s->head[s->hash_size-1] = NIL; \
+ zmemset((char *)s->head, 0, (unsigned)(s->hash_size-1)*sizeof(*s->head));
+
+/* ========================================================================= */
+int zlib_deflateInit_(
+ z_streamp strm,
+ int level,
+ const char *version,
+ int stream_size
+)
+{
+ return zlib_deflateInit2_(strm, level, Z_DEFLATED, MAX_WBITS,
+ DEF_MEM_LEVEL,
+ Z_DEFAULT_STRATEGY, version, stream_size);
+ /* To do: ignore strm->next_in if we use it as window */
+}
+
+/* ========================================================================= */
+int zlib_deflateInit2_(
+ z_streamp strm,
+ int level,
+ int method,
+ int windowBits,
+ int memLevel,
+ int strategy,
+ const char *version,
+ int stream_size
+)
+{
+ deflate_state *s;
+ int noheader = 0;
+ static char my_version[] = ZLIB_VERSION;
+ deflate_workspace *mem;
+
+ ush *overlay;
+ /* We overlay pending_buf and d_buf+l_buf. This works since the average
+ * output size for (length,distance) codes is <= 24 bits.
+ */
+
+ if (version == NULLP || version[0] != my_version[0] ||
+ stream_size != sizeof(z_stream)) {
+ return Z_VERSION_ERROR;
+ }
+ if (strm == NULLP) return Z_STREAM_ERROR;
+
+ strm->msg = (char*)NULLP; /**** pts ****/
+
+ if (level == Z_DEFAULT_COMPRESSION) level = 6;
+
+ mem = (deflate_workspace *) strm->workspace;
+
+ if (windowBits < 0) { /* undocumented feature: suppress zlib header */
+ noheader = 1;
+ windowBits = -windowBits;
+ }
+ if (memLevel < 1 || memLevel > MAX_MEM_LEVEL || method != Z_DEFLATED ||
+ windowBits < 9 || windowBits > 15 || level < 0 || level > 9 ||
+ strategy < 0 || strategy > Z_HUFFMAN_ONLY) {
+ return Z_STREAM_ERROR;
+ }
+ s = (deflate_state *) &(mem->deflate_memory);
+ strm->state = (struct zlib_internal_state *)s;
+ s->strm = strm;
+
+ s->data_type=strm->data_type; /**** pts ****/ /* BUGFIX at Tue Jan 18 16:01:08 CET 2005 */ /* Imp: report this bugfix to the Linux kernel */
+ s->noheader = noheader;
+ s->w_bits = windowBits;
+ s->w_size = 1 << s->w_bits;
+ s->w_mask = s->w_size - 1;
+
+ s->hash_bits = memLevel + 7;
+ s->hash_size = 1 << s->hash_bits;
+ s->hash_mask = s->hash_size - 1;
+ s->hash_shift = ((s->hash_bits+MIN_MATCH-1)/MIN_MATCH);
+
+ s->window = (Byte *) mem->window_memory;
+ memset(mem->window_memory, 0, s->w_size << 1); /* BUGFIX at Mon Sep 4 17:12:23 CEST 2017, otherwise valgrind reports uninitialized errors */
+ s->prev = (Pos *) mem->prev_memory;
+ s->head = (Pos *) mem->head_memory;
+
+ s->lit_bufsize = 1 << (memLevel + 6); /* 16K elements by default */
+
+ overlay = (ush *) mem->overlay_memory;
+ s->pending_buf = (uch *) overlay;
+ s->pending_buf_size = (ulg)s->lit_bufsize * (sizeof(ush)+2L);
+
+ s->d_buf = overlay + s->lit_bufsize/sizeof(ush);
+ s->l_buf = s->pending_buf + (1+sizeof(ush))*s->lit_bufsize;
+
+ s->level = level;
+ s->strategy = strategy;
+ s->method = (Byte)method;
+
+ return zlib_deflateReset(strm);
+}
+
+#if 0 /**** pts ****/
+/* ========================================================================= */
+int zlib_deflateSetDictionary(
+ z_streamp strm,
+ const Byte *dictionary,
+ uInt dictLength
+)
+{
+ deflate_state *s;
+ uInt length = dictLength;
+ uInt n;
+ IPos hash_head = 0;
+
+ if (strm == NULLP || strm->state == NULLP || dictionary == NULLP)
+ return Z_STREAM_ERROR;
+
+ s = (deflate_state *) strm->state;
+ if (s->status != INIT_STATE) return Z_STREAM_ERROR;
+
+ strm->adler = zlib_adler32(strm->adler, dictionary, dictLength);
+
+ if (length < MIN_MATCH) return Z_OK;
+ if (length > MAX_DIST(s)) {
+ length = MAX_DIST(s);
+#ifndef USE_DICT_HEAD
+ dictionary += dictLength - length; /* use the tail of the dictionary */
+#endif
+ }
+ zmemcpy((char *)s->window, dictionary, length);
+ s->strstart = length;
+ s->block_start = (long)length;
+
+ /* Insert all strings in the hash table (except for the last two bytes).
+ * s->lookahead stays null, so s->ins_h will be recomputed at the next
+ * call of fill_window.
+ */
+ s->ins_h = s->window[0];
+ UPDATE_HASH(s, s->ins_h, s->window[1]);
+ for (n = 0; n <= length - MIN_MATCH; n++) {
+ INSERT_STRING(s, n, hash_head);
+ }
+ if (hash_head) hash_head = 0; /* to make compiler happy */
+ return Z_OK;
+}
+#endif
+
+/* ========================================================================= */
+int zlib_deflateReset(
+ z_streamp strm
+)
+{
+ deflate_state *s;
+
+ if (strm == NULLP || strm->state == NULLP)
+ return Z_STREAM_ERROR;
+
+ strm->total_in = strm->total_out = 0;
+ strm->msg = (char*)NULLP;
+ strm->data_type = Z_UNKNOWN;
+
+ s = (deflate_state *)strm->state;
+ s->pending = 0;
+ s->pending_out = s->pending_buf;
+
+ if (s->noheader < 0) {
+ s->noheader = 0; /* was set to -1 by deflate(..., Z_FINISH); */
+ }
+ s->status = s->noheader ? BUSY_STATE : INIT_STATE;
+ strm->adler = 1;
+ s->last_flush = Z_NO_FLUSH;
+
+ zlib_tr_init(s);
+ lm_init(s);
+
+ return Z_OK;
+}
+
+#if 0 /**** pts ****/
+/* ========================================================================= */
+int zlib_deflateParams(
+ z_streamp strm,
+ int level,
+ int strategy
+)
+{
+ deflate_state *s;
+ compress_func func;
+ int err = Z_OK;
+
+ if (strm == NULLP || strm->state == NULLP) return Z_STREAM_ERROR;
+ s = (deflate_state *) strm->state;
+
+ if (level == Z_DEFAULT_COMPRESSION) {
+ level = 6;
+ }
+ if (level < 0 || level > 9 || strategy < 0 || strategy > Z_HUFFMAN_ONLY) {
+ return Z_STREAM_ERROR;
+ }
+ func = configuration_table[s->level].func;
+
+ if (func != configuration_table[level].func && strm->total_in != 0) {
+ /* Flush the last buffer: */
+ err = zlib_deflate(strm, Z_PARTIAL_FLUSH);
+ }
+ if (s->level != level) {
+ s->level = level;
+ s->max_lazy_match = configuration_table[level].max_lazy;
+ s->good_match = configuration_table[level].good_length;
+ s->nice_match = configuration_table[level].nice_length;
+ s->max_chain_length = configuration_table[level].max_chain;
+ }
+ s->strategy = strategy;
+ return err;
+}
+#endif
+
+/* =========================================================================
+ * Put a short in the pending buffer. The 16-bit value is put in MSB order.
+ * IN assertion: the stream state is correct and there is enough room in
+ * pending_buf.
+ */
+static void putShortMSB(
+ deflate_state *s,
+ uInt b
+)
+{
+ put_byte(s, (Byte)(b >> 8));
+ put_byte(s, (Byte)(b & 0xff));
+}
+
+/* =========================================================================
+ * Flush as much pending output as possible. All deflate() output goes
+ * through this function so some applications may wish to modify it
+ * to avoid allocating a large strm->next_out buffer and copying into it.
+ * (See also read_buf()).
+ */
+static void flush_pending(
+ z_streamp strm
+)
+{
+ deflate_state *s = (deflate_state *) strm->state;
+ unsigned len = s->pending;
+
+ if (len > strm->avail_out) len = strm->avail_out;
+ if (len == 0) return;
+
+ if (strm->next_out != NULLP) {
+ zmemcpy(strm->next_out, s->pending_out, len);
+ strm->next_out += len;
+ }
+ s->pending_out += len;
+ strm->total_out += len;
+ strm->avail_out -= len;
+ s->pending -= len;
+ if (s->pending == 0) {
+ s->pending_out = s->pending_buf;
+ }
+}
+
+/* ========================================================================= */
+int zlib_deflate(
+ z_streamp strm,
+ int flush
+)
+{
+ int old_flush; /* value of flush param for previous deflate call */
+ deflate_state *s;
+
+ if (strm == NULLP || strm->state == NULLP ||
+ flush > Z_FINISH || flush < 0) {
+ return Z_STREAM_ERROR;
+ }
+ s = (deflate_state *) strm->state;
+
+ if ((strm->next_in == NULLP && strm->avail_in != 0) ||
+ (s->status == FINISH_STATE && flush != Z_FINISH)) {
+ return Z_STREAM_ERROR;
+ }
+ if (strm->avail_out == 0) return Z_BUF_ERROR;
+
+ s->strm = strm; /* just in case */
+ old_flush = s->last_flush;
+ s->last_flush = flush;
+
+ /* Write the zlib header */
+ if (s->status == INIT_STATE) {
+
+ uInt header = (Z_DEFLATED + ((s->w_bits-8)<<4)) << 8;
+ uInt level_flags = (s->level-1) >> 1;
+
+ if (level_flags > 3) level_flags = 3;
+ header |= (level_flags << 6);
+ if (s->strstart != 0) header |= PRESET_DICT;
+ header += 31 - (header % 31);
+
+ s->status = BUSY_STATE;
+ putShortMSB(s, header);
+
+ /* Save the adler32 of the preset dictionary: */
+ if (s->strstart != 0) {
+ putShortMSB(s, (uInt)(strm->adler >> 16));
+ putShortMSB(s, (uInt)(strm->adler & 0xffff));
+ }
+ strm->adler = 1L;
+ }
+
+ /* Flush as much pending output as possible */
+ if (s->pending != 0) {
+ flush_pending(strm);
+ if (strm->avail_out == 0) {
+ /* Since avail_out is 0, deflate will be called again with
+ * more output space, but possibly with both pending and
+ * avail_in equal to zero. There won't be anything to do,
+ * but this is not an error situation so make sure we
+ * return OK instead of BUF_ERROR at next call of deflate:
+ */
+ s->last_flush = -1;
+ return Z_OK;
+ }
+
+ /* Make sure there is something to do and avoid duplicate consecutive
+ * flushes. For repeated and useless calls with Z_FINISH, we keep
+ * returning Z_STREAM_END instead of Z_BUFF_ERROR.
+ */
+ } else if (strm->avail_in == 0 && flush <= old_flush &&
+ flush != Z_FINISH) {
+ return Z_BUF_ERROR;
+ }
+
+ /* User must not provide more input after the first FINISH: */
+ if (s->status == FINISH_STATE && strm->avail_in != 0) {
+ return Z_BUF_ERROR;
+ }
+
+ /* Start a new block or continue the current one.
+ */
+ if (strm->avail_in != 0 || s->lookahead != 0 ||
+ (flush != Z_NO_FLUSH && s->status != FINISH_STATE)) {
+ block_state bstate;
+
+ bstate = (*(configuration_table[s->level].func))(s, flush);
+
+ if (bstate == finish_started || bstate == finish_done) {
+ s->status = FINISH_STATE;
+ }
+ if (bstate == need_more || bstate == finish_started) {
+ if (strm->avail_out == 0) {
+ s->last_flush = -1; /* avoid BUF_ERROR next call, see above */
+ }
+ return Z_OK;
+ /* If flush != Z_NO_FLUSH && avail_out == 0, the next call
+ * of deflate should use the same flush parameter to make sure
+ * that the flush is complete. So we don't have to output an
+ * empty block here, this will be done at next call. This also
+ * ensures that for a very small output buffer, we emit at most
+ * one empty block.
+ */
+ }
+ if (bstate == block_done) {
+ if (flush == Z_PARTIAL_FLUSH) {
+ zlib_tr_align(s);
+ } else if (flush == Z_PACKET_FLUSH) {
+ /* Output just the 3-bit `stored' block type value,
+ but not a zero length. */
+ zlib_tr_stored_type_only(s);
+ } else { /* FULL_FLUSH or SYNC_FLUSH */
+ zlib_tr_stored_block(s, (char*)0, 0L, 0);
+ /* For a full flush, this empty block will be recognized
+ * as a special marker by inflate_sync().
+ */
+ if (flush == Z_FULL_FLUSH) {
+ CLEAR_HASH(s); /* forget history */
+ }
+ }
+ flush_pending(strm);
+ if (strm->avail_out == 0) {
+ s->last_flush = -1; /* avoid BUF_ERROR at next call, see above */
+ return Z_OK;
+ }
+ }
+ }
+ Assert(strm->avail_out > 0, "bug2");
+
+ if (flush != Z_FINISH) return Z_OK;
+ if (s->noheader) return Z_STREAM_END;
+
+ /* Write the zlib trailer (adler32) */
+ putShortMSB(s, (uInt)(strm->adler >> 16));
+ putShortMSB(s, (uInt)(strm->adler & 0xffff));
+ flush_pending(strm);
+ /* If avail_out is zero, the application will call deflate again
+ * to flush the rest.
+ */
+ s->noheader = -1; /* write the trailer only once! */
+ return s->pending != 0 ? Z_OK : Z_STREAM_END;
+}
+
+/* ========================================================================= */
+int zlib_deflateEnd(
+ z_streamp strm
+)
+{
+ int status;
+ deflate_state *s;
+
+ if (strm == NULLP || strm->state == NULLP) return Z_STREAM_ERROR;
+ s = (deflate_state *) strm->state;
+
+ status = s->status;
+ if (status != INIT_STATE && status != BUSY_STATE &&
+ status != FINISH_STATE) {
+ return Z_STREAM_ERROR;
+ }
+
+ strm->state = (struct zlib_internal_state*)NULLP; /**** pts ****/
+
+ return status == BUSY_STATE ? Z_DATA_ERROR : Z_OK;
+}
+
+#if 0 /**** pts ****/
+/* =========================================================================
+ * Copy the source state to the destination state.
+ */
+int zlib_deflateCopy (
+ z_streamp dest,
+ z_streamp source
+)
+{
+#ifdef MAXSEG_64K
+ return Z_STREAM_ERROR;
+#else
+ deflate_state *ds;
+ deflate_state *ss;
+ ush *overlay;
+ deflate_workspace *mem;
+
+
+ if (source == NULLP || dest == NULLP || source->state == NULLP) {
+ return Z_STREAM_ERROR;
+ }
+
+ ss = (deflate_state *) source->state;
+
+ *dest = *source;
+
+ mem = (deflate_workspace *) dest->workspace;
+
+ ds = &(mem->deflate_memory);
+
+ dest->state = (struct zlib_internal_state *) ds;
+ *ds = *ss;
+ ds->strm = dest;
+
+ ds->window = (Byte *) mem->window_memory;
+ ds->prev = (Pos *) mem->prev_memory;
+ ds->head = (Pos *) mem->head_memory;
+ overlay = (ush *) mem->overlay_memory;
+ ds->pending_buf = (uch *) overlay;
+
+ zmemcpy(ds->window, ss->window, ds->w_size * 2 * sizeof(Byte));
+ zmemcpy(ds->prev, ss->prev, ds->w_size * sizeof(Pos));
+ zmemcpy(ds->head, ss->head, ds->hash_size * sizeof(Pos));
+ zmemcpy(ds->pending_buf, ss->pending_buf, (uInt)ds->pending_buf_size);
+
+ ds->pending_out = ds->pending_buf + (ss->pending_out - ss->pending_buf);
+ ds->d_buf = overlay + ds->lit_bufsize/sizeof(ush);
+ ds->l_buf = ds->pending_buf + (1+sizeof(ush))*ds->lit_bufsize;
+
+ ds->l_desc.dyn_tree = ds->dyn_ltree;
+ ds->d_desc.dyn_tree = ds->dyn_dtree;
+ ds->bl_desc.dyn_tree = ds->bl_tree;
+
+ return Z_OK;
+#endif
+}
+#endif
+
+/* ===========================================================================
+ * Read a new buffer from the current input stream, update the adler32
+ * and total number of bytes read. All deflate() input goes through
+ * this function so some applications may wish to modify it to avoid
+ * allocating a large strm->next_in buffer and copying from it.
+ * (See also flush_pending()).
+ */
+static int read_buf(
+ z_streamp strm,
+ Byte *buf,
+ unsigned size
+)
+{
+ unsigned len = strm->avail_in;
+
+ if (len > size) len = size;
+ if (len == 0) return 0;
+
+ strm->avail_in -= len;
+
+ if (!((deflate_state *)(strm->state))->noheader) {
+ strm->adler = zlib_adler32(strm->adler, strm->next_in, len);
+ }
+ zmemcpy(buf, strm->next_in, len);
+ strm->next_in += len;
+ strm->total_in += len;
+
+ return (int)len;
+}
+
+/* ===========================================================================
+ * Initialize the "longest match" routines for a new zlib stream
+ */
+static void lm_init(
+ deflate_state *s
+)
+{
+ s->window_size = (ulg)2L*s->w_size;
+
+ CLEAR_HASH(s);
+
+ /* Set the default configuration parameters:
+ */
+ s->max_lazy_match = configuration_table[s->level].max_lazy;
+ s->good_match = configuration_table[s->level].good_length;
+ s->nice_match = configuration_table[s->level].nice_length;
+ s->max_chain_length = configuration_table[s->level].max_chain;
+
+ s->strstart = 0;
+ s->block_start = 0L;
+ s->lookahead = 0;
+ s->match_length = s->prev_length = MIN_MATCH-1;
+ s->match_available = 0;
+ s->ins_h = 0;
+}
+
+/* ===========================================================================
+ * Set match_start to the longest match starting at the given string and
+ * return its length. Matches shorter or equal to prev_length are discarded,
+ * in which case the result is equal to prev_length and match_start is
+ * garbage.
+ * IN assertions: cur_match is the head of the hash chain for the current
+ * string (strstart) and its distance is <= MAX_DIST, and prev_length >= 1
+ * OUT assertion: the match length is not greater than s->lookahead.
+ */
+/* For 80x86 and 680x0, an optimized version will be provided in match.asm or
+ * match.S. The code will be functionally equivalent.
+ */
+static uInt longest_match(
+ deflate_state *s,
+ IPos cur_match /* current match */
+)
+{
+ unsigned chain_length = s->max_chain_length;/* max hash chain length */
+ register Byte *scan = s->window + s->strstart; /* current string */
+ register Byte *match; /* matched string */
+ register int len; /* length of current match */
+ int best_len = s->prev_length; /* best match length so far */
+ int nice_match = s->nice_match; /* stop if match long enough */
+ IPos limit = s->strstart > (IPos)MAX_DIST(s) ?
+ s->strstart - (IPos)MAX_DIST(s) : NIL;
+ /* Stop when cur_match becomes <= limit. To simplify the code,
+ * we prevent matches with the string of window index 0.
+ */
+ Pos *prev = s->prev;
+ uInt wmask = s->w_mask;
+
+#ifdef UNALIGNED_OK
+ /* Compare two bytes at a time. Note: this is not always beneficial.
+ * Try with and without -DUNALIGNED_OK to check.
+ */
+ register Byte *strend = s->window + s->strstart + MAX_MATCH - 1;
+ register ush scan_start = *(ush*)scan;
+ register ush scan_end = *(ush*)(scan+best_len-1);
+#else
+ register Byte *strend = s->window + s->strstart + MAX_MATCH;
+ register Byte scan_end1 = scan[best_len-1];
+ register Byte scan_end = scan[best_len];
+#endif
+
+ /* The code is optimized for HASH_BITS >= 8 and MAX_MATCH-2 multiple of 16.
+ * It is easy to get rid of this optimization if necessary.
+ */
+ Assert(s->hash_bits >= 8 && MAX_MATCH == 258, "Code too clever");
+
+ /* Do not waste too much time if we already have a good match: */
+ if (s->prev_length >= s->good_match) {
+ chain_length >>= 2;
+ }
+ /* Do not look for matches beyond the end of the input. This is necessary
+ * to make deflate deterministic.
+ */
+ if ((uInt)nice_match > s->lookahead) nice_match = s->lookahead;
+
+ Assert((ulg)s->strstart <= s->window_size-MIN_LOOKAHEAD, "need lookahead");
+
+ do {
+ Assert(cur_match < s->strstart, "no future");
+ match = s->window + cur_match;
+
+ /* Skip to next match if the match length cannot increase
+ * or if the match length is less than 2:
+ */
+#if (defined(UNALIGNED_OK) && MAX_MATCH == 258)
+ /* This code assumes sizeof(unsigned short) == 2. Do not use
+ * UNALIGNED_OK if your compiler uses a different size.
+ */
+ if (*(ush*)(match+best_len-1) != scan_end ||
+ *(ush*)match != scan_start) continue;
+
+ /* It is not necessary to compare scan[2] and match[2] since they are
+ * always equal when the other bytes match, given that the hash keys
+ * are equal and that HASH_BITS >= 8. Compare 2 bytes at a time at
+ * strstart+3, +5, ... up to strstart+257. We check for insufficient
+ * lookahead only every 4th comparison; the 128th check will be made
+ * at strstart+257. If MAX_MATCH-2 is not a multiple of 8, it is
+ * necessary to put more guard bytes at the end of the window, or
+ * to check more often for insufficient lookahead.
+ */
+ Assert(scan[2] == match[2], "scan[2]?");
+ scan++, match++;
+ do {
+ } while (*(ush*)(scan+=2) == *(ush*)(match+=2) &&
+ *(ush*)(scan+=2) == *(ush*)(match+=2) &&
+ *(ush*)(scan+=2) == *(ush*)(match+=2) &&
+ *(ush*)(scan+=2) == *(ush*)(match+=2) &&
+ scan < strend);
+ /* The funny "do {}" generates better code on most compilers */
+
+ /* Here, scan <= window+strstart+257 */
+ Assert(scan <= s->window+(unsigned)(s->window_size-1), "wild scan");
+ if (*scan == *match) scan++;
+
+ len = (MAX_MATCH - 1) - (int)(strend-scan);
+ scan = strend - (MAX_MATCH-1);
+
+#else /* UNALIGNED_OK */
+
+ if (match[best_len] != scan_end ||
+ match[best_len-1] != scan_end1 ||
+ *match != *scan ||
+ *++match != scan[1]) continue;
+
+ /* The check at best_len-1 can be removed because it will be made
+ * again later. (This heuristic is not always a win.)
+ * It is not necessary to compare scan[2] and match[2] since they
+ * are always equal when the other bytes match, given that
+ * the hash keys are equal and that HASH_BITS >= 8.
+ */
+ scan += 2, match++;
+ Assert(*scan == *match, "match[2]?");
+
+ /* We check for insufficient lookahead only every 8th comparison;
+ * the 256th check will be made at strstart+258.
+ */
+ do {
+ } while (*++scan == *++match && *++scan == *++match &&
+ *++scan == *++match && *++scan == *++match &&
+ *++scan == *++match && *++scan == *++match &&
+ *++scan == *++match && *++scan == *++match &&
+ scan < strend);
+
+ Assert(scan <= s->window+(unsigned)(s->window_size-1), "wild scan");
+
+ len = MAX_MATCH - (int)(strend - scan);
+ scan = strend - MAX_MATCH;
+
+#endif /* UNALIGNED_OK */
+
+ if (len > best_len) {
+ s->match_start = cur_match;
+ best_len = len;
+ if (len >= nice_match) break;
+#ifdef UNALIGNED_OK
+ scan_end = *(ush*)(scan+best_len-1);
+#else
+ scan_end1 = scan[best_len-1];
+ scan_end = scan[best_len];
+#endif
+ }
+ } while ((cur_match = prev[cur_match & wmask]) > limit
+ && --chain_length != 0);
+
+ if ((uInt)best_len <= s->lookahead) return best_len;
+ return s->lookahead;
+}
+
+#ifdef DEBUG_ZLIB
+/* ===========================================================================
+ * Check that the match at match_start is indeed a match.
+ */
+static void check_match(
+ deflate_state *s,
+ IPos start,
+ IPos match,
+ int length
+)
+{
+ /* check that the match is indeed a match */
+ if (memcmp((char *)s->window + match,
+ (char *)s->window + start, length) != EQUAL) {
+ fprintf(stderr, " start %u, match %u, length %d\n",
+ start, match, length);
+ do {
+ fprintf(stderr, "%c%c", s->window[match++], s->window[start++]);
+ } while (--length != 0);
+ z_error("invalid match");
+ }
+ if (z_verbose > 1) {
+ fprintf(stderr,"\\[%d,%d]", start-match, length);
+ do { putc(s->window[start++], stderr); } while (--length != 0);
+ }
+}
+#else
+# define check_match(s, start, match, length)
+#endif
+
+/* ===========================================================================
+ * Fill the window when the lookahead becomes insufficient.
+ * Updates strstart and lookahead.
+ *
+ * IN assertion: lookahead < MIN_LOOKAHEAD
+ * OUT assertions: strstart <= window_size-MIN_LOOKAHEAD
+ * At least one byte has been read, or avail_in == 0; reads are
+ * performed for at least two bytes (required for the zip translate_eol
+ * option -- not supported here).
+ */
+static void fill_window(
+ deflate_state *s
+)
+{
+ register unsigned n, m;
+ register Pos *p;
+ unsigned more; /* Amount of free space at the end of the window. */
+ uInt wsize = s->w_size;
+
+ do {
+ more = (unsigned)(s->window_size -(ulg)s->lookahead -(ulg)s->strstart);
+
+ /* Deal with !@#$% 64K limit: */
+ if (more == 0 && s->strstart == 0 && s->lookahead == 0) {
+ more = wsize;
+
+ } else if (more == (unsigned)(-1)) {
+ /* Very unlikely, but possible on 16 bit machine if strstart == 0
+ * and lookahead == 1 (input done one byte at time)
+ */
+ more--;
+
+ /* If the window is almost full and there is insufficient lookahead,
+ * move the upper half to the lower one to make room in the upper half.
+ */
+ } else if (s->strstart >= wsize+MAX_DIST(s)) {
+
+ zmemcpy((char *)s->window, (char *)s->window+wsize,
+ (unsigned)wsize);
+ s->match_start -= wsize;
+ s->strstart -= wsize; /* we now have strstart >= MAX_DIST */
+ s->block_start -= (long) wsize;
+
+ /* Slide the hash table (could be avoided with 32 bit values
+ at the expense of memory usage). We slide even when level == 0
+ to keep the hash table consistent if we switch back to level > 0
+ later. (Using level 0 permanently is not an optimal usage of
+ zlib, so we don't care about this pathological case.)
+ */
+ n = s->hash_size;
+ p = &s->head[n];
+ do {
+ m = *--p;
+ *p = (Pos)(m >= wsize ? m-wsize : NIL);
+ } while (--n);
+
+ n = wsize;
+ p = &s->prev[n];
+ do {
+ m = *--p;
+ *p = (Pos)(m >= wsize ? m-wsize : NIL);
+ /* If n is not on any hash chain, prev[n] is garbage but
+ * its value will never be used.
+ */
+ } while (--n);
+ more += wsize;
+ }
+ if (s->strm->avail_in == 0) return;
+
+ /* If there was no sliding:
+ * strstart <= WSIZE+MAX_DIST-1 && lookahead <= MIN_LOOKAHEAD - 1 &&
+ * more == window_size - lookahead - strstart
+ * => more >= window_size - (MIN_LOOKAHEAD-1 + WSIZE + MAX_DIST-1)
+ * => more >= window_size - 2*WSIZE + 2
+ * In the BIG_MEM or MMAP case (not yet supported),
+ * window_size == input_size + MIN_LOOKAHEAD &&
+ * strstart + s->lookahead <= input_size => more >= MIN_LOOKAHEAD.
+ * Otherwise, window_size == 2*WSIZE so more >= 2.
+ * If there was sliding, more >= WSIZE. So in all cases, more >= 2.
+ */
+ Assert(more >= 2, "more < 2");
+
+ n = read_buf(s->strm, s->window + s->strstart + s->lookahead, more);
+ s->lookahead += n;
+
+ /* Initialize the hash value now that we have some input: */
+ if (s->lookahead >= MIN_MATCH) {
+ s->ins_h = s->window[s->strstart];
+ UPDATE_HASH(s, s->ins_h, s->window[s->strstart+1]);
+#if MIN_MATCH != 3
+ Call UPDATE_HASH() MIN_MATCH-3 more times
+#endif
+ }
+ /* If the whole input has less than MIN_MATCH bytes, ins_h is garbage,
+ * but this is not important since only literal bytes will be emitted.
+ */
+
+ } while (s->lookahead < MIN_LOOKAHEAD && s->strm->avail_in != 0);
+}
+
+/* ===========================================================================
+ * Flush the current block, with given end-of-file flag.
+ * IN assertion: strstart is set to the end of the current match.
+ */
+#define FLUSH_BLOCK_ONLY(s, eof) { \
+ zlib_tr_flush_block(s, (s->block_start >= 0L ? \
+ (char *)&s->window[(unsigned)s->block_start] : \
+ (char *)/****pts****/NULLP), \
+ (ulg)((long)s->strstart - s->block_start), \
+ (eof)); \
+ s->block_start = s->strstart; \
+ flush_pending(s->strm); \
+ Tracev((stderr,"[FLUSH]")); \
+}
+
+/* Same but force premature exit if necessary. */
+#define FLUSH_BLOCK(s, eof) { \
+ FLUSH_BLOCK_ONLY(s, eof); \
+ if (s->strm->avail_out == 0) return (eof) ? finish_started : need_more; \
+}
+
+/* ===========================================================================
+ * Copy without compression as much as possible from the input stream, return
+ * the current block state.
+ * This function does not insert new strings in the dictionary since
+ * uncompressible data is probably not useful. This function is used
+ * only for the level=0 compression option.
+ * NOTE: this function should be optimized to avoid extra copying from
+ * window to pending_buf.
+ */
+static block_state deflate_stored(
+ deflate_state *s,
+ int flush
+)
+{
+ /* Stored blocks are limited to 0xffff bytes, pending_buf is limited
+ * to pending_buf_size, and each stored block has a 5 byte header:
+ */
+ ulg max_block_size = 0xffff;
+ ulg max_start;
+
+ if (max_block_size > s->pending_buf_size - 5) {
+ max_block_size = s->pending_buf_size - 5;
+ }
+
+ /* Copy as much as possible from input to output: */
+ for (;;) {
+ /* Fill the window as much as possible: */
+ if (s->lookahead <= 1) {
+
+ Assert(s->strstart < s->w_size+MAX_DIST(s) ||
+ s->block_start >= (long)s->w_size, "slide too late");
+
+ fill_window(s);
+ if (s->lookahead == 0 && flush == Z_NO_FLUSH) return need_more;
+
+ if (s->lookahead == 0) break; /* flush the current block */
+ }
+ Assert(s->block_start >= 0L, "block gone");
+
+ s->strstart += s->lookahead;
+ s->lookahead = 0;
+
+ /* Emit a stored block if pending_buf will be full: */
+ max_start = s->block_start + max_block_size;
+ if (s->strstart == 0 || (ulg)s->strstart >= max_start) {
+ /* strstart == 0 is possible when wraparound on 16-bit machine */
+ s->lookahead = (uInt)(s->strstart - max_start);
+ s->strstart = (uInt)max_start;
+ FLUSH_BLOCK(s, 0);
+ }
+ /* Flush if we may have to slide, otherwise block_start may become
+ * negative and the data will be gone:
+ */
+ if (s->strstart - (uInt)s->block_start >= MAX_DIST(s)) {
+ FLUSH_BLOCK(s, 0);
+ }
+ }
+ FLUSH_BLOCK(s, flush == Z_FINISH);
+ return flush == Z_FINISH ? finish_done : block_done;
+}
+
+/* ===========================================================================
+ * Compress as much as possible from the input stream, return the current
+ * block state.
+ * This function does not perform lazy evaluation of matches and inserts
+ * new strings in the dictionary only for unmatched strings or for short
+ * matches. It is used only for the fast compression options.
+ */
+static block_state deflate_fast(
+ deflate_state *s,
+ int flush
+)
+{
+ IPos hash_head = NIL; /* head of the hash chain */
+ int bflush; /* set if current block must be flushed */
+
+ for (;;) {
+ /* Make sure that we always have enough lookahead, except
+ * at the end of the input file. We need MAX_MATCH bytes
+ * for the next match, plus MIN_MATCH bytes to insert the
+ * string following the next match.
+ */
+ if (s->lookahead < MIN_LOOKAHEAD) {
+ fill_window(s);
+ if (s->lookahead < MIN_LOOKAHEAD && flush == Z_NO_FLUSH) {
+ return need_more;
+ }
+ if (s->lookahead == 0) break; /* flush the current block */
+ }
+
+ /* Insert the string window[strstart .. strstart+2] in the
+ * dictionary, and set hash_head to the head of the hash chain:
+ */
+ if (s->lookahead >= MIN_MATCH) {
+ INSERT_STRING(s, s->strstart, hash_head);
+ }
+
+ /* Find the longest match, discarding those <= prev_length.
+ * At this point we have always match_length < MIN_MATCH
+ */
+ if (hash_head != NIL && s->strstart - hash_head <= MAX_DIST(s)) {
+ /* To simplify the code, we prevent matches with the string
+ * of window index 0 (in particular we have to avoid a match
+ * of the string with itself at the start of the input file).
+ */
+ if (s->strategy != Z_HUFFMAN_ONLY) {
+ s->match_length = longest_match (s, hash_head);
+ }
+ /* longest_match() sets match_start */
+ }
+ if (s->match_length >= MIN_MATCH) {
+ check_match(s, s->strstart, s->match_start, s->match_length);
+
+ bflush = zlib_tr_tally(s, s->strstart - s->match_start,
+ s->match_length - MIN_MATCH);
+
+ s->lookahead -= s->match_length;
+
+ /* Insert new strings in the hash table only if the match length
+ * is not too large. This saves time but degrades compression.
+ */
+ if (s->match_length <= s->max_insert_length &&
+ s->lookahead >= MIN_MATCH) {
+ s->match_length--; /* string at strstart already in hash table */
+ do {
+ s->strstart++;
+ INSERT_STRING(s, s->strstart, hash_head);
+ /* strstart never exceeds WSIZE-MAX_MATCH, so there are
+ * always MIN_MATCH bytes ahead.
+ */
+ } while (--s->match_length != 0);
+ s->strstart++;
+ } else {
+ s->strstart += s->match_length;
+ s->match_length = 0;
+ s->ins_h = s->window[s->strstart];
+ UPDATE_HASH(s, s->ins_h, s->window[s->strstart+1]);
+#if MIN_MATCH != 3
+ Call UPDATE_HASH() MIN_MATCH-3 more times
+#endif
+ /* If lookahead < MIN_MATCH, ins_h is garbage, but it does not
+ * matter since it will be recomputed at next deflate call.
+ */
+ }
+ } else {
+ /* No match, output a literal byte */
+ Tracevv((stderr,"%c", s->window[s->strstart]));
+ bflush = zlib_tr_tally (s, 0, s->window[s->strstart]);
+ s->lookahead--;
+ s->strstart++;
+ }
+ if (bflush) FLUSH_BLOCK(s, 0);
+ }
+ FLUSH_BLOCK(s, flush == Z_FINISH);
+ return flush == Z_FINISH ? finish_done : block_done;
+}
+
+/* ===========================================================================
+ * Same as above, but achieves better compression. We use a lazy
+ * evaluation for matches: a match is finally adopted only if there is
+ * no better match at the next window position.
+ */
+static block_state deflate_slow(
+ deflate_state *s,
+ int flush
+)
+{
+ IPos hash_head = NIL; /* head of hash chain */
+ int bflush; /* set if current block must be flushed */
+
+ /* Process the input block. */
+ for (;;) {
+ /* Make sure that we always have enough lookahead, except
+ * at the end of the input file. We need MAX_MATCH bytes
+ * for the next match, plus MIN_MATCH bytes to insert the
+ * string following the next match.
+ */
+ if (s->lookahead < MIN_LOOKAHEAD) {
+ fill_window(s);
+ if (s->lookahead < MIN_LOOKAHEAD && flush == Z_NO_FLUSH) {
+ return need_more;
+ }
+ if (s->lookahead == 0) break; /* flush the current block */
+ }
+
+ /* Insert the string window[strstart .. strstart+2] in the
+ * dictionary, and set hash_head to the head of the hash chain:
+ */
+ if (s->lookahead >= MIN_MATCH) {
+ INSERT_STRING(s, s->strstart, hash_head);
+ }
+
+ /* Find the longest match, discarding those <= prev_length.
+ */
+ s->prev_length = s->match_length, s->prev_match = s->match_start;
+ s->match_length = MIN_MATCH-1;
+
+ if (hash_head != NIL && s->prev_length < s->max_lazy_match &&
+ s->strstart - hash_head <= MAX_DIST(s)) {
+ /* To simplify the code, we prevent matches with the string
+ * of window index 0 (in particular we have to avoid a match
+ * of the string with itself at the start of the input file).
+ */
+ if (s->strategy != Z_HUFFMAN_ONLY) {
+ s->match_length = longest_match (s, hash_head);
+ }
+ /* longest_match() sets match_start */
+
+ if (s->match_length <= 5 && (s->strategy == Z_FILTERED ||
+ (s->match_length == MIN_MATCH &&
+ s->strstart - s->match_start > TOO_FAR))) {
+
+ /* If prev_match is also MIN_MATCH, match_start is garbage
+ * but we will ignore the current match anyway.
+ */
+ s->match_length = MIN_MATCH-1;
+ }
+ }
+ /* If there was a match at the previous step and the current
+ * match is not better, output the previous match:
+ */
+ if (s->prev_length >= MIN_MATCH && s->match_length <= s->prev_length) {
+ uInt max_insert = s->strstart + s->lookahead - MIN_MATCH;
+ /* Do not insert strings in hash table beyond this. */
+
+ check_match(s, s->strstart-1, s->prev_match, s->prev_length);
+
+ bflush = zlib_tr_tally(s, s->strstart -1 - s->prev_match,
+ s->prev_length - MIN_MATCH);
+
+ /* Insert in hash table all strings up to the end of the match.
+ * strstart-1 and strstart are already inserted. If there is not
+ * enough lookahead, the last two strings are not inserted in
+ * the hash table.
+ */
+ s->lookahead -= s->prev_length-1;
+ s->prev_length -= 2;
+ do {
+ if (++s->strstart <= max_insert) {
+ INSERT_STRING(s, s->strstart, hash_head);
+ }
+ } while (--s->prev_length != 0);
+ s->match_available = 0;
+ s->match_length = MIN_MATCH-1;
+ s->strstart++;
+
+ if (bflush) FLUSH_BLOCK(s, 0);
+
+ } else if (s->match_available) {
+ /* If there was no match at the previous position, output a
+ * single literal. If there was a match but the current match
+ * is longer, truncate the previous match to a single literal.
+ */
+ Tracevv((stderr,"%c", s->window[s->strstart-1]));
+ if (zlib_tr_tally (s, 0, s->window[s->strstart-1])) {
+ FLUSH_BLOCK_ONLY(s, 0);
+ }
+ s->strstart++;
+ s->lookahead--;
+ if (s->strm->avail_out == 0) return need_more;
+ } else {
+ /* There is no previous match to compare with, wait for
+ * the next step to decide.
+ */
+ s->match_available = 1;
+ s->strstart++;
+ s->lookahead--;
+ }
+ }
+ Assert (flush != Z_NO_FLUSH, "no flush?");
+ if (s->match_available) {
+ Tracevv((stderr,"%c", s->window[s->strstart-1]));
+ zlib_tr_tally (s, 0, s->window[s->strstart-1]);
+ s->match_available = 0;
+ }
+ FLUSH_BLOCK(s, flush == Z_FINISH);
+ return flush == Z_FINISH ? finish_done : block_done;
+}
+
+int zlib_deflate_workspacesize(void)
+{
+ return sizeof(deflate_workspace);
+}
+
+/* +++ trees.c */
+/* trees.c -- output deflated data using Huffman coding
+ * Copyright (C) 1995-1996 Jean-loup Gailly
+ * For conditions of distribution and use, see copyright notice in zlib.h
+ */
+
+/*
+ * ALGORITHM
+ *
+ * The "deflation" process uses several Huffman trees. The more
+ * common source values are represented by shorter bit sequences.
+ *
+ * Each code tree is stored in a compressed form which is itself
+ * a Huffman encoding of the lengths of all the code strings (in
+ * ascending order by source values). The actual code strings are
+ * reconstructed from the lengths in the inflate process, as described
+ * in the deflate specification.
+ *
+ * REFERENCES
+ *
+ * Deutsch, L.P.,"'Deflate' Compressed Data Format Specification".
+ * Available in ftp.uu.net:/pub/archiving/zip/doc/deflate-1.1.doc
+ *
+ * Storer, James A.
+ * Data Compression: Methods and Theory, pp. 49-50.
+ * Computer Science Press, 1988. ISBN 0-7167-8156-5.
+ *
+ * Sedgewick, R.
+ * Algorithms, p290.
+ * Addison-Wesley, 1983. ISBN 0-201-06672-6.
+ */
+
+/* From: trees.c,v 1.11 1996/07/24 13:41:06 me Exp $ */
+
+/* #include "deflate.h" */
+#if 0 /**** pts ****/
+# include <linux/zutil.h>
+# include "defutil.h"
+# ifdef DEBUG_ZLIB
+# include <ctype.h>
+# endif
+#endif
+
+
+/* ===========================================================================
+ * Constants
+ */
+
+#define MAX_BL_BITS 7
+/* Bit length codes must not exceed MAX_BL_BITS bits */
+
+#define END_BLOCK 256
+/* end of block literal code */
+
+#define REP_3_6 16
+/* repeat previous bit length 3-6 times (2 bits of repeat count) */
+
+#define REPZ_3_10 17
+/* repeat a zero length 3-10 times (3 bits of repeat count) */
+
+#define REPZ_11_138 18
+/* repeat a zero length 11-138 times (7 bits of repeat count) */
+
+static const int extra_lbits[LENGTH_CODES] /* extra bits for each length code */
+ = {0,0,0,0,0,0,0,0,1,1,1,1,2,2,2,2,3,3,3,3,4,4,4,4,5,5,5,5,0};
+
+static const int extra_dbits[D_CODES] /* extra bits for each distance code */
+ = {0,0,0,0,1,1,2,2,3,3,4,4,5,5,6,6,7,7,8,8,9,9,10,10,11,11,12,12,13,13};
+
+static const int extra_blbits[BL_CODES]/* extra bits for each bit length code */
+ = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,3,7};
+
+static const uch bl_order[BL_CODES]
+ = {16,17,18,0,8,7,9,6,10,5,11,4,12,3,13,2,14,1,15};
+/* The lengths of the bit length codes are sent in order of decreasing
+ * probability, to avoid transmitting the lengths for unused bit length codes.
+ */
+
+#define Buf_size (8 * 2*sizeof(char))
+/* Number of bits used within bi_buf. (bi_buf might be implemented on
+ * more than 16 bits on some systems.)
+ */
+
+/* ===========================================================================
+ * Local data. These are initialized only once.
+ */
+
+static ct_data static_ltree[L_CODES+2];
+/* The static literal tree. Since the bit lengths are imposed, there is no
+ * need for the L_CODES extra codes used during heap construction. However
+ * The codes 286 and 287 are needed to build a canonical tree (see zlib_tr_init
+ * below).
+ */
+
+static ct_data static_dtree[D_CODES];
+/* The static distance tree. (Actually a trivial tree since all codes use
+ * 5 bits.)
+ */
+
+static uch dist_code[512];
+/* distance codes. The first 256 values correspond to the distances
+ * 3 .. 258, the last 256 values correspond to the top 8 bits of
+ * the 15 bit distances.
+ */
+
+static uch length_code[MAX_MATCH-MIN_MATCH+1];
+/* length code for each normalized match length (0 == MIN_MATCH) */
+
+static int base_length[LENGTH_CODES];
+/* First normalized length for each code (0 = MIN_MATCH) */
+
+static int base_dist[D_CODES];
+/* First normalized distance for each code (0 = distance of 1) */
+
+struct static_tree_desc_s {
+ const ct_data *static_tree; /* static tree or NULLP */
+ const int *extra_bits; /* extra bits for each code or NULLP */
+ int extra_base; /* base index for extra_bits */
+ int elems; /* max number of elements in the tree */
+ int max_length; /* max bit length for the codes */
+};
+
+static static_tree_desc static_l_desc =
+{static_ltree, extra_lbits, LITERALS+1, L_CODES, MAX_BITS};
+
+static static_tree_desc static_d_desc =
+{static_dtree, extra_dbits, 0, D_CODES, MAX_BITS};
+
+static static_tree_desc static_bl_desc =
+{(const ct_data *)0, extra_blbits, 0, BL_CODES, MAX_BL_BITS};
+
+/* ===========================================================================
+ * Local (static) routines in this file.
+ */
+
+static void tr_static_init (void);
+static void init_block (deflate_state *s);
+static void pqdownheap (deflate_state *s, ct_data *tree, int k);
+static void gen_bitlen (deflate_state *s, tree_desc *desc);
+static void gen_codes (ct_data *tree, int max_code, ush *bl_count);
+static void build_tree (deflate_state *s, tree_desc *desc);
+static void scan_tree (deflate_state *s, ct_data *tree, int max_code);
+static void send_tree (deflate_state *s, ct_data *tree, int max_code);
+static int build_bl_tree (deflate_state *s);
+static void send_all_trees (deflate_state *s, int lcodes, int dcodes,
+ int blcodes);
+static void compress_block (deflate_state *s, ct_data *ltree,
+ ct_data *dtree);
+static void set_data_type (deflate_state *s);
+static unsigned bi_reverse (unsigned value, int length);
+static void bi_windup (deflate_state *s);
+static void bi_flush (deflate_state *s);
+static void copy_block (deflate_state *s, char *buf, unsigned len,
+ int header);
+
+#ifndef DEBUG_ZLIB
+# define send_code(s, c, tree) send_bits(s, tree[c].Code, tree[c].Len)
+ /* Send a code of the given tree. c and tree must not have side effects */
+
+#else /* DEBUG_ZLIB */
+# define send_code(s, c, tree) \
+ { if (z_verbose>2) fprintf(stderr,"\ncd %3d ",(c)); \
+ send_bits(s, tree[c].Code, tree[c].Len); }
+#endif
+
+#define d_code(dist) \
+ ((dist) < 256 ? dist_code[dist] : dist_code[256+((dist)>>7)])
+/* Mapping from a distance to a distance code. dist is the distance - 1 and
+ * must not have side effects. dist_code[256] and dist_code[257] are never
+ * used.
+ */
+
+/* ===========================================================================
+ * Send a value on a given number of bits.
+ * IN assertion: length <= 16 and value fits in length bits.
+ */
+#ifdef DEBUG_ZLIB
+static void send_bits (deflate_state *s, int value, int length);
+
+static void send_bits(
+ deflate_state *s,
+ int value, /* value to send */
+ int length /* number of bits */
+)
+{
+ Tracevv((stderr," l %2d v %4x ", length, value));
+ Assert(length > 0 && length <= 15, "invalid length");
+ s->bits_sent += (ulg)length;
+
+ /* If not enough room in bi_buf, use (valid) bits from bi_buf and
+ * (16 - bi_valid) bits from value, leaving (width - (16-bi_valid))
+ * unused bits in value.
+ */
+ if (s->bi_valid > (int)Buf_size - length) {
+ s->bi_buf |= (value << s->bi_valid);
+ put_short(s, s->bi_buf);
+ s->bi_buf = (ush)value >> (Buf_size - s->bi_valid);
+ s->bi_valid += length - Buf_size;
+ } else {
+ s->bi_buf |= value << s->bi_valid;
+ s->bi_valid += length;
+ }
+}
+#else /* !DEBUG_ZLIB */
+
+#define send_bits(s, value, length) \
+{ int len = length;\
+ if (s->bi_valid > (int)Buf_size - len) {\
+ int val = value;\
+ s->bi_buf |= (val << s->bi_valid);\
+ put_short(s, s->bi_buf);\
+ s->bi_buf = (ush)val >> (Buf_size - s->bi_valid);\
+ s->bi_valid += len - Buf_size;\
+ } else {\
+ s->bi_buf |= (value) << s->bi_valid;\
+ s->bi_valid += len;\
+ }\
+}
+#endif /* DEBUG_ZLIB */
+
+/* ===========================================================================
+ * Initialize the various 'constant' tables. In a multi-threaded environment,
+ * this function may be called by two threads concurrently, but this is
+ * harmless since both invocations do exactly the same thing.
+ */
+static void tr_static_init(void)
+{
+ static int static_init_done;
+ int n; /* iterates over tree elements */
+ int bits; /* bit counter */
+ int length; /* length value */
+ int code; /* code value */
+ int dist; /* distance index */
+ ush bl_count[MAX_BITS+1];
+ /* number of codes at each bit length for an optimal tree */
+
+ if (static_init_done) return;
+
+ /* Initialize the mapping length (0..255) -> length code (0..28) */
+ length = 0;
+ for (code = 0; code < LENGTH_CODES-1; code++) {
+ base_length[code] = length;
+ for (n = 0; n < (1<<extra_lbits[code]); n++) {
+ length_code[length++] = (uch)code;
+ }
+ }
+ Assert (length == 256, "tr_static_init: length != 256");
+ /* Note that the length 255 (match length 258) can be represented
+ * in two different ways: code 284 + 5 bits or code 285, so we
+ * overwrite length_code[255] to use the best encoding:
+ */
+ length_code[length-1] = (uch)code;
+
+ /* Initialize the mapping dist (0..32K) -> dist code (0..29) */
+ dist = 0;
+ for (code = 0 ; code < 16; code++) {
+ base_dist[code] = dist;
+ for (n = 0; n < (1<<extra_dbits[code]); n++) {
+ dist_code[dist++] = (uch)code;
+ }
+ }
+ Assert (dist == 256, "tr_static_init: dist != 256");
+ dist >>= 7; /* from now on, all distances are divided by 128 */
+ for ( ; code < D_CODES; code++) {
+ base_dist[code] = dist << 7;
+ for (n = 0; n < (1<<(extra_dbits[code]-7)); n++) {
+ dist_code[256 + dist++] = (uch)code;
+ }
+ }
+ Assert (dist == 256, "tr_static_init: 256+dist != 512");
+
+ /* Construct the codes of the static literal tree */
+ for (bits = 0; bits <= MAX_BITS; bits++) bl_count[bits] = 0;
+ n = 0;
+ while (n <= 143) static_ltree[n++].Len = 8, bl_count[8]++;
+ while (n <= 255) static_ltree[n++].Len = 9, bl_count[9]++;
+ while (n <= 279) static_ltree[n++].Len = 7, bl_count[7]++;
+ while (n <= 287) static_ltree[n++].Len = 8, bl_count[8]++;
+ /* Codes 286 and 287 do not exist, but we must include them in the
+ * tree construction to get a canonical Huffman tree (longest code
+ * all ones)
+ */
+ gen_codes((ct_data *)static_ltree, L_CODES+1, bl_count);
+
+ /* The static distance tree is trivial: */
+ for (n = 0; n < D_CODES; n++) {
+ static_dtree[n].Len = 5;
+ static_dtree[n].Code = bi_reverse((unsigned)n, 5);
+ }
+ static_init_done = 1;
+}
+
+/* ===========================================================================
+ * Initialize the tree data structures for a new zlib stream.
+ */
+ZSTATIC void zlib_tr_init(
+ deflate_state *s
+)
+{
+ tr_static_init();
+
+ s->compressed_len = 0L;
+
+ s->l_desc.dyn_tree = s->dyn_ltree;
+ s->l_desc.stat_desc = &static_l_desc;
+
+ s->d_desc.dyn_tree = s->dyn_dtree;
+ s->d_desc.stat_desc = &static_d_desc;
+
+ s->bl_desc.dyn_tree = s->bl_tree;
+ s->bl_desc.stat_desc = &static_bl_desc;
+
+ s->bi_buf = 0;
+ s->bi_valid = 0;
+ s->last_eob_len = 8; /* enough lookahead for inflate */
+#ifdef DEBUG_ZLIB
+ s->bits_sent = 0L;
+#endif
+
+ /* Initialize the first block of the first file: */
+ init_block(s);
+}
+
+/* ===========================================================================
+ * Initialize a new block.
+ */
+static void init_block(
+ deflate_state *s
+)
+{
+ int n; /* iterates over tree elements */
+
+ /* Initialize the trees. */
+ for (n = 0; n < L_CODES; n++) s->dyn_ltree[n].Freq = 0;
+ for (n = 0; n < D_CODES; n++) s->dyn_dtree[n].Freq = 0;
+ for (n = 0; n < BL_CODES; n++) s->bl_tree[n].Freq = 0;
+
+ s->dyn_ltree[END_BLOCK].Freq = 1;
+ s->opt_len = s->static_len = 0L;
+ s->last_lit = s->matches = 0;
+}
+
+#define SMALLEST 1
+/* Index within the heap array of least frequent node in the Huffman tree */
+
+
+/* ===========================================================================
+ * Remove the smallest element from the heap and recreate the heap with
+ * one less element. Updates heap and heap_len.
+ */
+#define pqremove(s, tree, top) \
+{\
+ top = s->heap[SMALLEST]; \
+ s->heap[SMALLEST] = s->heap[s->heap_len--]; \
+ pqdownheap(s, tree, SMALLEST); \
+}
+
+/* ===========================================================================
+ * Compares to subtrees, using the tree depth as tie breaker when
+ * the subtrees have equal frequency. This minimizes the worst case length.
+ */
+#define smaller(tree, n, m, depth) \
+ (tree[n].Freq < tree[m].Freq || \
+ (tree[n].Freq == tree[m].Freq && depth[n] <= depth[m]))
+
+/* ===========================================================================
+ * Restore the heap property by moving down the tree starting at node k,
+ * exchanging a node with the smallest of its two sons if necessary, stopping
+ * when the heap property is re-established (each father smaller than its
+ * two sons).
+ */
+static void pqdownheap(
+ deflate_state *s,
+ ct_data *tree, /* the tree to restore */
+ int k /* node to move down */
+)
+{
+ int v = s->heap[k];
+ int j = k << 1; /* left son of k */
+ while (j <= s->heap_len) {
+ /* Set j to the smallest of the two sons: */
+ if (j < s->heap_len &&
+ smaller(tree, s->heap[j+1], s->heap[j], s->depth)) {
+ j++;
+ }
+ /* Exit if v is smaller than both sons */
+ if (smaller(tree, v, s->heap[j], s->depth)) break;
+
+ /* Exchange v with the smallest son */
+ s->heap[k] = s->heap[j]; k = j;
+
+ /* And continue down the tree, setting j to the left son of k */
+ j <<= 1;
+ }
+ s->heap[k] = v;
+}
+
+/* ===========================================================================
+ * Compute the optimal bit lengths for a tree and update the total bit length
+ * for the current block.
+ * IN assertion: the fields freq and dad are set, heap[heap_max] and
+ * above are the tree nodes sorted by increasing frequency.
+ * OUT assertions: the field len is set to the optimal bit length, the
+ * array bl_count contains the frequencies for each bit length.
+ * The length opt_len is updated; static_len is also updated if stree is
+ * not null.
+ */
+static void gen_bitlen(
+ deflate_state *s,
+ tree_desc *desc /* the tree descriptor */
+)
+{
+ ct_data *tree = desc->dyn_tree;
+ int max_code = desc->max_code;
+ const ct_data *stree = desc->stat_desc->static_tree;
+ const int *extra = desc->stat_desc->extra_bits;
+ int base = desc->stat_desc->extra_base;
+ int max_length = desc->stat_desc->max_length;
+ int h; /* heap index */
+ int n, m; /* iterate over the tree elements */
+ int bits; /* bit length */
+ int xbits; /* extra bits */
+ ush f; /* frequency */
+ int overflow = 0; /* number of elements with bit length too large */
+
+ for (bits = 0; bits <= MAX_BITS; bits++) s->bl_count[bits] = 0;
+
+ /* In a first pass, compute the optimal bit lengths (which may
+ * overflow in the case of the bit length tree).
+ */
+ tree[s->heap[s->heap_max]].Len = 0; /* root of the heap */
+
+ for (h = s->heap_max+1; h < HEAP_SIZE; h++) {
+ n = s->heap[h];
+ bits = tree[tree[n].Dad].Len + 1;
+ if (bits > max_length) bits = max_length, overflow++;
+ tree[n].Len = (ush)bits;
+ /* We overwrite tree[n].Dad which is no longer needed */
+
+ if (n > max_code) continue; /* not a leaf node */
+
+ s->bl_count[bits]++;
+ xbits = 0;
+ if (n >= base) xbits = extra[n-base];
+ f = tree[n].Freq;
+ s->opt_len += (ulg)f * (bits + xbits);
+ if (stree) s->static_len += (ulg)f * (stree[n].Len + xbits);
+ }
+ if (overflow == 0) return;
+
+ Trace((stderr,"\nbit length overflow\n"));
+ /* This happens for example on obj2 and pic of the Calgary corpus */
+
+ /* Find the first bit length which could increase: */
+ do {
+ bits = max_length-1;
+ while (s->bl_count[bits] == 0) bits--;
+ s->bl_count[bits]--; /* move one leaf down the tree */
+ s->bl_count[bits+1] += 2; /* move one overflow item as its brother */
+ s->bl_count[max_length]--;
+ /* The brother of the overflow item also moves one step up,
+ * but this does not affect bl_count[max_length]
+ */
+ overflow -= 2;
+ } while (overflow > 0);
+
+ /* Now recompute all bit lengths, scanning in increasing frequency.
+ * h is still equal to HEAP_SIZE. (It is simpler to reconstruct all
+ * lengths instead of fixing only the wrong ones. This idea is taken
+ * from 'ar' written by Haruhiko Okumura.)
+ */
+ for (bits = max_length; bits != 0; bits--) {
+ n = s->bl_count[bits];
+ while (n != 0) {
+ m = s->heap[--h];
+ if (m > max_code) continue;
+ if (tree[m].Len != (unsigned) bits) {
+ Trace((stderr,"code %d bits %d->%d\n", m, tree[m].Len, bits));
+ s->opt_len += ((long)bits - (long)tree[m].Len)
+ *(long)tree[m].Freq;
+ tree[m].Len = (ush)bits;
+ }
+ n--;
+ }
+ }
+}
+
+/* ===========================================================================
+ * Generate the codes for a given tree and bit counts (which need not be
+ * optimal).
+ * IN assertion: the array bl_count contains the bit length statistics for
+ * the given tree and the field len is set for all tree elements.
+ * OUT assertion: the field code is set for all tree elements of non
+ * zero code length.
+ */
+static void gen_codes(
+ ct_data *tree, /* the tree to decorate */
+ int max_code, /* largest code with non zero frequency */
+ ush *bl_count /* number of codes at each bit length */
+)
+{
+ ush next_code[MAX_BITS+1]; /* next code value for each bit length */
+ ush code = 0; /* running code value */
+ int bits; /* bit index */
+ int n; /* code index */
+
+ /* The distribution counts are first used to generate the code values
+ * without bit reversal.
+ */
+ for (bits = 1; bits <= MAX_BITS; bits++) {
+ next_code[bits] = code = (code + bl_count[bits-1]) << 1;
+ }
+ /* Check that the bit counts in bl_count are consistent. The last code
+ * must be all ones.
+ */
+ Assert (code + bl_count[MAX_BITS]-1 == (1<<MAX_BITS)-1,
+ "inconsistent bit counts");
+ Tracev((stderr,"\ngen_codes: max_code %d ", max_code));
+
+ for (n = 0; n <= max_code; n++) {
+ int len = tree[n].Len;
+ if (len == 0) continue;
+ /* Now reverse the bits */
+ tree[n].Code = bi_reverse(next_code[len]++, len);
+
+ Tracecv(tree != static_ltree, (stderr,"\nn %3d %c l %2d c %4x (%x) ",
+ n, (isgraph(n) ? n : ' '), len, tree[n].Code, next_code[len]-1));
+ }
+}
+
+/* ===========================================================================
+ * Construct one Huffman tree and assigns the code bit strings and lengths.
+ * Update the total bit length for the current block.
+ * IN assertion: the field freq is set for all tree elements.
+ * OUT assertions: the fields len and code are set to the optimal bit length
+ * and corresponding code. The length opt_len is updated; static_len is
+ * also updated if stree is not null. The field max_code is set.
+ */
+static void build_tree(
+ deflate_state *s,
+ tree_desc *desc /* the tree descriptor */
+)
+{
+ ct_data *tree = desc->dyn_tree;
+ const ct_data *stree = desc->stat_desc->static_tree;
+ int elems = desc->stat_desc->elems;
+ int n, m; /* iterate over heap elements */
+ int max_code = -1; /* largest code with non zero frequency */
+ int node; /* new node being created */
+
+ /* Construct the initial heap, with least frequent element in
+ * heap[SMALLEST]. The sons of heap[n] are heap[2*n] and heap[2*n+1].
+ * heap[0] is not used.
+ */
+ s->heap_len = 0, s->heap_max = HEAP_SIZE;
+
+ for (n = 0; n < elems; n++) {
+ if (tree[n].Freq != 0) {
+ s->heap[++(s->heap_len)] = max_code = n;
+ s->depth[n] = 0;
+ } else {
+ tree[n].Len = 0;
+ }
+ }
+
+ /* The pkzip format requires that at least one distance code exists,
+ * and that at least one bit should be sent even if there is only one
+ * possible code. So to avoid special checks later on we force at least
+ * two codes of non zero frequency.
+ */
+ while (s->heap_len < 2) {
+ node = s->heap[++(s->heap_len)] = (max_code < 2 ? ++max_code : 0);
+ tree[node].Freq = 1;
+ s->depth[node] = 0;
+ s->opt_len--; if (stree) s->static_len -= stree[node].Len;
+ /* node is 0 or 1 so it does not have extra bits */
+ }
+ desc->max_code = max_code;
+
+ /* The elements heap[heap_len/2+1 .. heap_len] are leaves of the tree,
+ * establish sub-heaps of increasing lengths:
+ */
+ for (n = s->heap_len/2; n >= 1; n--) pqdownheap(s, tree, n);
+
+ /* Construct the Huffman tree by repeatedly combining the least two
+ * frequent nodes.
+ */
+ node = elems; /* next internal node of the tree */
+ do {
+ pqremove(s, tree, n); /* n = node of least frequency */
+ m = s->heap[SMALLEST]; /* m = node of next least frequency */
+
+ s->heap[--(s->heap_max)] = n; /* keep the nodes sorted by frequency */
+ s->heap[--(s->heap_max)] = m;
+
+ /* Create a new node father of n and m */
+ tree[node].Freq = tree[n].Freq + tree[m].Freq;
+ s->depth[node] = (uch) (max(s->depth[n], s->depth[m]) + 1);
+ tree[n].Dad = tree[m].Dad = (ush)node;
+#ifdef DUMP_BL_TREE
+ if (tree == s->bl_tree) {
+ fprintf(stderr,"\nnode %d(%d), sons %d(%d) %d(%d)",
+ node, tree[node].Freq, n, tree[n].Freq, m, tree[m].Freq);
+ }
+#endif
+ /* and insert the new node in the heap */
+ s->heap[SMALLEST] = node++;
+ pqdownheap(s, tree, SMALLEST);
+
+ } while (s->heap_len >= 2);
+
+ s->heap[--(s->heap_max)] = s->heap[SMALLEST];
+
+ /* At this point, the fields freq and dad are set. We can now
+ * generate the bit lengths.
+ */
+ gen_bitlen(s, (tree_desc *)desc);
+
+ /* The field len is now set, we can generate the bit codes */
+ gen_codes ((ct_data *)tree, max_code, s->bl_count);
+}
+
+/* ===========================================================================
+ * Scan a literal or distance tree to determine the frequencies of the codes
+ * in the bit length tree.
+ */
+static void scan_tree(
+ deflate_state *s,
+ ct_data *tree, /* the tree to be scanned */
+ int max_code /* and its largest code of non zero frequency */
+)
+{
+ int n; /* iterates over all tree elements */
+ int prevlen = -1; /* last emitted length */
+ int curlen; /* length of current code */
+ int nextlen = tree[0].Len; /* length of next code */
+ int count = 0; /* repeat count of the current code */
+ int max_count = 7; /* max repeat count */
+ int min_count = 4; /* min repeat count */
+
+ if (nextlen == 0) max_count = 138, min_count = 3;
+ tree[max_code+1].Len = (ush)0xffff; /* guard */
+
+ for (n = 0; n <= max_code; n++) {
+ curlen = nextlen; nextlen = tree[n+1].Len;
+ if (++count < max_count && curlen == nextlen) {
+ continue;
+ } else if (count < min_count) {
+ s->bl_tree[curlen].Freq += count;
+ } else if (curlen != 0) {
+ if (curlen != prevlen) s->bl_tree[curlen].Freq++;
+ s->bl_tree[REP_3_6].Freq++;
+ } else if (count <= 10) {
+ s->bl_tree[REPZ_3_10].Freq++;
+ } else {
+ s->bl_tree[REPZ_11_138].Freq++;
+ }
+ count = 0; prevlen = curlen;
+ if (nextlen == 0) {
+ max_count = 138, min_count = 3;
+ } else if (curlen == nextlen) {
+ max_count = 6, min_count = 3;
+ } else {
+ max_count = 7, min_count = 4;
+ }
+ }
+}
+
+/* ===========================================================================
+ * Send a literal or distance tree in compressed form, using the codes in
+ * bl_tree.
+ */
+static void send_tree(
+ deflate_state *s,
+ ct_data *tree, /* the tree to be scanned */
+ int max_code /* and its largest code of non zero frequency */
+)
+{
+ int n; /* iterates over all tree elements */
+ int prevlen = -1; /* last emitted length */
+ int curlen; /* length of current code */
+ int nextlen = tree[0].Len; /* length of next code */
+ int count = 0; /* repeat count of the current code */
+ int max_count = 7; /* max repeat count */
+ int min_count = 4; /* min repeat count */
+
+ /* tree[max_code+1].Len = -1; */ /* guard already set */
+ if (nextlen == 0) max_count = 138, min_count = 3;
+
+ for (n = 0; n <= max_code; n++) {
+ curlen = nextlen; nextlen = tree[n+1].Len;
+ if (++count < max_count && curlen == nextlen) {
+ continue;
+ } else if (count < min_count) {
+ do { send_code(s, curlen, s->bl_tree); } while (--count != 0);
+
+ } else if (curlen != 0) {
+ if (curlen != prevlen) {
+ send_code(s, curlen, s->bl_tree); count--;
+ }
+ Assert(count >= 3 && count <= 6, " 3_6?");
+ send_code(s, REP_3_6, s->bl_tree); send_bits(s, count-3, 2);
+
+ } else if (count <= 10) {
+ send_code(s, REPZ_3_10, s->bl_tree); send_bits(s, count-3, 3);
+
+ } else {
+ send_code(s, REPZ_11_138, s->bl_tree); send_bits(s, count-11, 7);
+ }
+ count = 0; prevlen = curlen;
+ if (nextlen == 0) {
+ max_count = 138, min_count = 3;
+ } else if (curlen == nextlen) {
+ max_count = 6, min_count = 3;
+ } else {
+ max_count = 7, min_count = 4;
+ }
+ }
+}
+
+/* ===========================================================================
+ * Construct the Huffman tree for the bit lengths and return the index in
+ * bl_order of the last bit length code to send.
+ */
+static int build_bl_tree(
+ deflate_state *s
+)
+{
+ int max_blindex; /* index of last bit length code of non zero freq */
+
+ /* Determine the bit length frequencies for literal and distance trees */
+ scan_tree(s, (ct_data *)s->dyn_ltree, s->l_desc.max_code);
+ scan_tree(s, (ct_data *)s->dyn_dtree, s->d_desc.max_code);
+
+ /* Build the bit length tree: */
+ build_tree(s, (tree_desc *)(&(s->bl_desc)));
+ /* opt_len now includes the length of the tree representations, except
+ * the lengths of the bit lengths codes and the 5+5+4 bits for the counts.
+ */
+
+ /* Determine the number of bit length codes to send. The pkzip format
+ * requires that at least 4 bit length codes be sent. (appnote.txt says
+ * 3 but the actual value used is 4.)
+ */
+ for (max_blindex = BL_CODES-1; max_blindex >= 3; max_blindex--) {
+ if (s->bl_tree[bl_order[max_blindex]].Len != 0) break;
+ }
+ /* Update opt_len to include the bit length tree and counts */
+ s->opt_len += 3*(max_blindex+1) + 5+5+4;
+ Tracev((stderr, "\ndyn trees: dyn %ld, stat %ld",
+ s->opt_len, s->static_len));
+
+ return max_blindex;
+}
+
+/* ===========================================================================
+ * Send the header for a block using dynamic Huffman trees: the counts, the
+ * lengths of the bit length codes, the literal tree and the distance tree.
+ * IN assertion: lcodes >= 257, dcodes >= 1, blcodes >= 4.
+ */
+static void send_all_trees(
+ deflate_state *s,
+ int lcodes, /* number of codes for each tree */
+ int dcodes, /* number of codes for each tree */
+ int blcodes /* number of codes for each tree */
+)
+{
+ int rank; /* index in bl_order */
+
+ Assert (lcodes >= 257 && dcodes >= 1 && blcodes >= 4, "not enough codes");
+ Assert (lcodes <= L_CODES && dcodes <= D_CODES && blcodes <= BL_CODES,
+ "too many codes");
+ Tracev((stderr, "\nbl counts: "));
+ send_bits(s, lcodes-257, 5); /* not +255 as stated in appnote.txt */
+ send_bits(s, dcodes-1, 5);
+ send_bits(s, blcodes-4, 4); /* not -3 as stated in appnote.txt */
+ for (rank = 0; rank < blcodes; rank++) {
+ Tracev((stderr, "\nbl code %2d ", bl_order[rank]));
+ send_bits(s, s->bl_tree[bl_order[rank]].Len, 3);
+ }
+ Tracev((stderr, "\nbl tree: sent %ld", s->bits_sent));
+
+ send_tree(s, (ct_data *)s->dyn_ltree, lcodes-1); /* literal tree */
+ Tracev((stderr, "\nlit tree: sent %ld", s->bits_sent));
+
+ send_tree(s, (ct_data *)s->dyn_dtree, dcodes-1); /* distance tree */
+ Tracev((stderr, "\ndist tree: sent %ld", s->bits_sent));
+}
+
+/* ===========================================================================
+ * Send a stored block
+ */
+ZSTATIC void zlib_tr_stored_block(
+ deflate_state *s,
+ char *buf, /* input block */
+ ulg stored_len, /* length of input block */
+ int eof /* true if this is the last block for a file */
+)
+{
+ send_bits(s, (STORED_BLOCK<<1)+eof, 3); /* send block type */
+ s->compressed_len = (s->compressed_len + 3 + 7) & (ulg)~7L;
+ s->compressed_len += (stored_len + 4) << 3;
+
+ copy_block(s, buf, (unsigned)stored_len, 1); /* with header */
+}
+
+/* Send just the `stored block' type code without any length bytes or data.
+ */
+ZSTATIC void zlib_tr_stored_type_only(
+ deflate_state *s
+)
+{
+ send_bits(s, (STORED_BLOCK << 1), 3);
+ bi_windup(s);
+ s->compressed_len = (s->compressed_len + 3) & ~7L;
+}
+
+
+/* ===========================================================================
+ * Send one empty static block to give enough lookahead for inflate.
+ * This takes 10 bits, of which 7 may remain in the bit buffer.
+ * The current inflate code requires 9 bits of lookahead. If the
+ * last two codes for the previous block (real code plus EOB) were coded
+ * on 5 bits or less, inflate may have only 5+3 bits of lookahead to decode
+ * the last real code. In this case we send two empty static blocks instead
+ * of one. (There are no problems if the previous block is stored or fixed.)
+ * To simplify the code, we assume the worst case of last real code encoded
+ * on one bit only.
+ */
+ZSTATIC void zlib_tr_align(
+ deflate_state *s
+)
+{
+ send_bits(s, STATIC_TREES<<1, 3);
+ send_code(s, END_BLOCK, static_ltree);
+ s->compressed_len += 10L; /* 3 for block type, 7 for EOB */
+ bi_flush(s);
+ /* Of the 10 bits for the empty block, we have already sent
+ * (10 - bi_valid) bits. The lookahead for the last real code (before
+ * the EOB of the previous block) was thus at least one plus the length
+ * of the EOB plus what we have just sent of the empty static block.
+ */
+ if (1 + s->last_eob_len + 10 - s->bi_valid < 9) {
+ send_bits(s, STATIC_TREES<<1, 3);
+ send_code(s, END_BLOCK, static_ltree);
+ s->compressed_len += 10L;
+ bi_flush(s);
+ }
+ s->last_eob_len = 7;
+}
+
+/* ===========================================================================
+ * Determine the best encoding for the current block: dynamic trees, static
+ * trees or store, and output the encoded block to the zip file. This function
+ * returns the total compressed length for the file so far.
+ */
+ZSTATIC ulg zlib_tr_flush_block(
+ deflate_state *s,
+ char *buf, /* input block, or NULLP if too old */
+ ulg stored_len, /* length of input block */
+ int eof /* true if this is the last block for a file */
+)
+{
+ ulg opt_lenb, static_lenb; /* opt_len and static_len in bytes */
+ int max_blindex = 0; /* index of last bit length code of non zero freq */
+
+ /* Build the Huffman trees unless a stored block is forced */
+ if (s->level > 0) {
+
+ /* Check if the file is ascii or binary */
+ if (s->data_type == Z_UNKNOWN) set_data_type(s);
+
+ /* Construct the literal and distance trees */
+ build_tree(s, (tree_desc *)(&(s->l_desc)));
+ Tracev((stderr, "\nlit data: dyn %ld, stat %ld", s->opt_len,
+ s->static_len));
+
+ build_tree(s, (tree_desc *)(&(s->d_desc)));
+ Tracev((stderr, "\ndist data: dyn %ld, stat %ld", s->opt_len,
+ s->static_len));
+ /* At this point, opt_len and static_len are the total bit lengths of
+ * the compressed block data, excluding the tree representations.
+ */
+
+ /* Build the bit length tree for the above two trees, and get the index
+ * in bl_order of the last bit length code to send.
+ */
+ max_blindex = build_bl_tree(s);
+
+ /* Determine the best encoding. Compute first the block length in bytes*/
+ opt_lenb = (s->opt_len+3+7)>>3;
+ static_lenb = (s->static_len+3+7)>>3;
+
+ Tracev((stderr, "\nopt %lu(%lu) stat %lu(%lu) stored %lu lit %u ",
+ opt_lenb, s->opt_len, static_lenb, s->static_len, stored_len,
+ s->last_lit));
+
+ if (static_lenb <= opt_lenb) opt_lenb = static_lenb;
+
+ } else {
+ Assert(buf != (char*)0, "lost buf");
+ opt_lenb = static_lenb = stored_len + 5; /* force a stored block */
+ }
+
+ /* If compression failed and this is the first and last block,
+ * and if the .zip file can be seeked (to rewrite the local header),
+ * the whole file is transformed into a stored file:
+ */
+#ifdef STORED_FILE_OK
+# ifdef FORCE_STORED_FILE
+ if (eof && s->compressed_len == 0L) { /* force stored file */
+# else
+ if (stored_len <= opt_lenb && eof && s->compressed_len==0L && seekable()) {
+# endif
+ /* Since LIT_BUFSIZE <= 2*WSIZE, the input data must be there: */
+ if (buf == (char*)0) error ("block vanished");
+
+ copy_block(s, buf, (unsigned)stored_len, 0); /* without header */
+ s->compressed_len = stored_len << 3;
+ s->method = STORED;
+ } else
+#endif /* STORED_FILE_OK */
+
+#ifdef FORCE_STORED
+ if (buf != (char*)0) { /* force stored block */
+#else
+ if (stored_len+4 <= opt_lenb && buf != (char*)0) {
+ /* 4: two words for the lengths */
+#endif
+ /* The test buf != NULLP is only necessary if LIT_BUFSIZE > WSIZE.
+ * Otherwise we can't have processed more than WSIZE input bytes since
+ * the last block flush, because compression would have been
+ * successful. If LIT_BUFSIZE <= WSIZE, it is never too late to
+ * transform a block into a stored block.
+ */
+ zlib_tr_stored_block(s, buf, stored_len, eof);
+
+#ifdef FORCE_STATIC
+ } else if (static_lenb >= 0) { /* force static trees */
+#else
+ } else if (static_lenb == opt_lenb) {
+#endif
+ send_bits(s, (STATIC_TREES<<1)+eof, 3);
+ compress_block(s, (ct_data *)static_ltree, (ct_data *)static_dtree);
+ s->compressed_len += 3 + s->static_len;
+ } else {
+ send_bits(s, (DYN_TREES<<1)+eof, 3);
+ send_all_trees(s, s->l_desc.max_code+1, s->d_desc.max_code+1,
+ max_blindex+1);
+ compress_block(s, (ct_data *)s->dyn_ltree, (ct_data *)s->dyn_dtree);
+ s->compressed_len += 3 + s->opt_len;
+ }
+ Assert (s->compressed_len == s->bits_sent, "bad compressed size");
+ init_block(s);
+
+ if (eof) {
+ bi_windup(s);
+ s->compressed_len += 7; /* align on byte boundary */
+ }
+ Tracev((stderr,"\ncomprlen %lu(%lu) ", s->compressed_len>>3,
+ s->compressed_len-7*eof));
+
+ return s->compressed_len >> 3;
+}
+
+/* ===========================================================================
+ * Save the match info and tally the frequency counts. Return true if
+ * the current block must be flushed.
+ */
+ZSTATIC int zlib_tr_tally(
+ deflate_state *s,
+ unsigned dist, /* distance of matched string */
+ unsigned lc /* match length-MIN_MATCH or unmatched char (if dist==0) */
+)
+{
+ s->d_buf[s->last_lit] = (ush)dist;
+ s->l_buf[s->last_lit++] = (uch)lc;
+ if (dist == 0) {
+ /* lc is the unmatched char */
+ s->dyn_ltree[lc].Freq++;
+ } else {
+ s->matches++;
+ /* Here, lc is the match length - MIN_MATCH */
+ dist--; /* dist = match distance - 1 */
+ Assert((ush)dist < (ush)MAX_DIST(s) &&
+ (ush)lc <= (ush)(MAX_MATCH-MIN_MATCH) &&
+ (ush)d_code(dist) < (ush)D_CODES, "zlib_tr_tally: bad match");
+
+ s->dyn_ltree[length_code[lc]+LITERALS+1].Freq++;
+ s->dyn_dtree[d_code(dist)].Freq++;
+ }
+
+ /* Try to guess if it is profitable to stop the current block here */
+ if ((s->last_lit & 0xfff) == 0 && s->level > 2) {
+ /* Compute an upper bound for the compressed length */
+ ulg out_length = (ulg)s->last_lit*8L;
+ ulg in_length = (ulg)((long)s->strstart - s->block_start);
+ int dcode;
+ for (dcode = 0; dcode < D_CODES; dcode++) {
+ out_length += (ulg)s->dyn_dtree[dcode].Freq *
+ (5L+extra_dbits[dcode]);
+ }
+ out_length >>= 3;
+ Tracev((stderr,"\nlast_lit %u, in %ld, out ~%ld(%ld%%) ",
+ s->last_lit, in_length, out_length,
+ 100L - out_length*100L/in_length));
+ if (s->matches < s->last_lit/2 && out_length < in_length/2) return 1;
+ }
+ return (s->last_lit == s->lit_bufsize-1);
+ /* We avoid equality with lit_bufsize because of wraparound at 64K
+ * on 16 bit machines and because stored blocks are restricted to
+ * 64K-1 bytes.
+ */
+}
+
+/* ===========================================================================
+ * Send the block data compressed using the given Huffman trees
+ */
+static void compress_block(
+ deflate_state *s,
+ ct_data *ltree, /* literal tree */
+ ct_data *dtree /* distance tree */
+)
+{
+ unsigned dist; /* distance of matched string */
+ int lc; /* match length or unmatched char (if dist == 0) */
+ unsigned lx = 0; /* running index in l_buf */
+ unsigned code; /* the code to send */
+ int extra; /* number of extra bits to send */
+
+ if (s->last_lit != 0) do {
+ dist = s->d_buf[lx];
+ lc = s->l_buf[lx++];
+ if (dist == 0) {
+ send_code(s, lc, ltree); /* send a literal byte */
+ Tracecv(isgraph(lc), (stderr," '%c' ", lc));
+ } else {
+ /* Here, lc is the match length - MIN_MATCH */
+ code = length_code[lc];
+ send_code(s, code+LITERALS+1, ltree); /* send the length code */
+ extra = extra_lbits[code];
+ if (extra != 0) {
+ lc -= base_length[code];
+ send_bits(s, lc, extra); /* send the extra length bits */
+ }
+ dist--; /* dist is now the match distance - 1 */
+ code = d_code(dist);
+ Assert (code < D_CODES, "bad d_code");
+
+ send_code(s, code, dtree); /* send the distance code */
+ extra = extra_dbits[code];
+ if (extra != 0) {
+ dist -= base_dist[code];
+ send_bits(s, dist, extra); /* send the extra distance bits */
+ }
+ } /* literal or match pair ? */
+
+ /* Check that the overlay between pending_buf and d_buf+l_buf is ok: */
+ Assert(s->pending < s->lit_bufsize + 2*lx, "pendingBuf overflow");
+
+ } while (lx < s->last_lit);
+
+ send_code(s, END_BLOCK, ltree);
+ s->last_eob_len = ltree[END_BLOCK].Len;
+}
+
+/* ===========================================================================
+ * Set the data type to ASCII or BINARY, using a crude approximation:
+ * binary if more than 20% of the bytes are <= 6 or >= 128, ascii otherwise.
+ * IN assertion: the fields freq of dyn_ltree are set and the total of all
+ * frequencies does not exceed 64K (to fit in an int on 16 bit machines).
+ */
+static void set_data_type(
+ deflate_state *s
+)
+{
+ int n = 0;
+ unsigned ascii_freq = 0;
+ unsigned bin_freq = 0;
+ while (n < 7) bin_freq += s->dyn_ltree[n++].Freq;
+ while (n < 128) ascii_freq += s->dyn_ltree[n++].Freq;
+ while (n < LITERALS) bin_freq += s->dyn_ltree[n++].Freq;
+ s->data_type = (Byte)(bin_freq > (ascii_freq >> 2) ? Z_BINARY : Z_ASCII);
+}
+
+/* ===========================================================================
+ * Copy a stored block, storing first the length and its
+ * one's complement if requested.
+ */
+static void copy_block(
+ deflate_state *s,
+ char *buf, /* the input data */
+ unsigned len, /* its length */
+ int header /* true if block header must be written */
+)
+{
+ bi_windup(s); /* align on byte boundary */
+ s->last_eob_len = 8; /* enough lookahead for inflate */
+
+ if (header) {
+ put_short(s, (ush)len);
+ put_short(s, (ush)~len);
+#ifdef DEBUG_ZLIB
+ s->bits_sent += 2*16;
+#endif
+ }
+#ifdef DEBUG_ZLIB
+ s->bits_sent += (ulg)len<<3;
+#endif
+ /* bundle up the put_byte(s, *buf++) calls */
+ zmemcpy(&s->pending_buf[s->pending], buf, len);
+ s->pending += len;
+}
+
+/* end of deftree.c */
+
+/* ---- </rip> by pts */
+
+#if PTS_DEFL_MAIN
+
+/*
+ * Usage: flateenc [-<level>] < <inputfile> > <outputfile>
+ * <level> is one of: 0: no compression; 1: low & fast; 9: high & slow
+ */
+
+#include "pts_defl.h"
+#include <unistd.h> /* read(), write() */
+#include <stdio.h>
+#include <stdlib.h> /* abort() */
+
+int main(int argc, char **argv) {
+ char ibuf[4096], obuf[6000]; /* Dat: 4096->6000 should be enough */
+ char workspace[sizeof(deflate_workspace)]; /* Dat: as returned by zlib_deflate_workspacesize in ZLIB 1.1.3 */
+ int got, zgot;
+ /** Compression level: 0..9 or Z_DEFAULT_COMPRESSION */
+ int level=Z_DEFAULT_COMPRESSION;
+ z_stream zs;
+ (void)argc;
+ if (argv && argv[0] && argv[1] && argv[1][0]=='-' && argv[1][1]>='0' && argv[1][1]<='9')
+ level=argv[1][1]-'0';
+ /* printf("ws=%d\n", zlib_deflate_workspacesize()); */
+ if (zlib_deflate_workspacesize()+(unsigned)0<sizeof(workspace)) abort();
+ zs.total_in=0;
+ zs.total_out=0;
+ zs.workspace=workspace;
+ zs.msg=(char*)NULLP;
+ zs.state=(struct zlib_internal_state*)NULLP;
+ zs.data_type=Z_UNKNOWN; /* Imp: do we have to initialize it? */
+ if (Z_OK!=zlib_deflateInit(&zs, level)) abort();
+ while (0<(got=read(0, ibuf, sizeof(ibuf)))) {
+ zs.next_in=ibuf; zs.avail_in=got;
+ zs.next_out=obuf; zs.avail_out=sizeof(obuf);
+ if (Z_OK!=zlib_deflate(&zs, 0)) abort();
+#ifdef DEBUG_PTS_DEFL
+ fprintf(stderr, "ai=%d ao=%d no=%d\n", zs.avail_in, zs.avail_out, (char*)zs.next_out-obuf);
+#endif
+ if (0!=zs.avail_in) abort();
+ got=sizeof(obuf)-zs.avail_out;
+ if (got>0 && got!=write(1, zs.next_out-got, got)) abort();
+ }
+ if (0!=got) abort();
+ do { /* flush all output */
+ zs.next_in=NULL; zs.avail_in=0;
+ zs.next_out=obuf; zs.avail_out=sizeof(obuf);
+ if (Z_STREAM_END!=(zgot=zlib_deflate(&zs, Z_FINISH)) && Z_OK!=zgot) abort();
+#ifdef DEBUG_PTS_DEFL
+ fprintf(stderr, "ai=%d ao=%d flush\n", zs.avail_in, zs.avail_out);
+#endif
+ got=sizeof(obuf)-zs.avail_out;
+ if (got>0 && got!=write(1, zs.next_out-got, got)) abort();
+ } while (zgot==Z_OK);
+ if (Z_OK!=zlib_deflateEnd(&zs)) abort();
+ return 0;
+}
+
+#endif
diff --git a/graphics/sam2p/pts_defl.h b/graphics/sam2p/pts_defl.h
new file mode 100644
index 0000000000..64e91a5e5a
--- /dev/null
+++ b/graphics/sam2p/pts_defl.h
@@ -0,0 +1,101 @@
+/*
+ * pts_defl.h -- C header file ZIP compression ripped from linux-2.6.8.1
+ * by pts@fazekas.hu at Tue Jan 18 15:19:06 CET 2005
+ *
+ * This ZIP compression (ZIP == PostScript /FlateEncode compression filter
+ * (ZLIB RFC 1950)) routine has been ripped from the Linux kernel 2.6.8.1
+ * (directory lib/zlib_deflate), which has been ripped from ZLIB 1.1.3
+ *
+ * This is a minimal .h file, to avoid namespace pollution.
+ * See more in the beginning of pts_defl.c
+ * For documentation comments, see pts_defl.c
+ *
+ */
+
+#ifndef PTS_DEFL_H
+#define PTS_DEFL_H
+
+#define PTS_DEFL_RIPPED_ZLIB 1
+
+/** Must be at least zlib_deflate_workspacesize(): 267946 on Linux i386 */
+#define ZLIB_DEFLATE_WORKSPACESIZE_MIN 270000
+
+#define ZLIB_VERSION "1.1.3"
+
+#define Z_NO_FLUSH 0
+#define Z_PARTIAL_FLUSH 1 /* will be removed, use Z_SYNC_FLUSH instead */
+#define Z_PACKET_FLUSH 2
+#define Z_SYNC_FLUSH 3
+#define Z_FULL_FLUSH 4
+#define Z_FINISH 5
+/* Allowed flush values; see deflate() below for details */
+
+#define Z_OK 0
+#define Z_STREAM_END 1
+#define Z_NEED_DICT 2
+#define Z_ERRNO (-1)
+#define Z_STREAM_ERROR (-2)
+#define Z_DATA_ERROR (-3)
+#define Z_MEM_ERROR (-4)
+#define Z_BUF_ERROR (-5)
+#define Z_VERSION_ERROR (-6)
+/* Return codes for the compression/decompression functions. Negative
+ * values are errors, positive values are used for special but normal events.
+ */
+
+#define Z_NO_COMPRESSION 0
+#define Z_BEST_SPEED 1
+#define Z_BEST_COMPRESSION 9
+#define Z_DEFAULT_COMPRESSION (-1)
+/* compression levels */
+
+#define Z_BINARY 0
+#define Z_ASCII 1
+#define Z_UNKNOWN 2
+/* Possible values of the data_type field */
+
+struct zlib_internal_state; /**** pts ****/ /* Dat: was: internal_state */
+
+typedef struct z_stream_s {
+ unsigned char *next_in; /* next input byte */
+ unsigned int avail_in; /* number of bytes available at next_in */
+ unsigned long total_in; /* total nb of input bytes read so far */
+
+ unsigned char *next_out; /* next output byte should be put there */
+ unsigned int avail_out; /* remaining free space at next_out */
+ unsigned long total_out; /* total nb of bytes output so far */
+
+ char *msg; /* last error message, NULLP if no error */
+ struct zlib_internal_state *state; /* not visible by applications */
+
+ void *workspace; /* memory allocated for this stream */
+
+ int data_type; /* best guess about the data type: ascii or binary */
+ unsigned long adler; /* adler32 value of the uncompressed data */
+ unsigned long reserved; /* reserved for future use */
+} z_stream;
+
+#ifdef __cplusplus
+#define EXTERN_C extern "C"
+#else
+#define EXTERN_C extern
+#endif
+
+EXTERN_C int zlib_deflate_workspacesize (void);
+EXTERN_C int zlib_deflate (z_stream* strm, int flush);
+EXTERN_C int zlib_deflateEnd (z_stream* strm);
+EXTERN_C int zlib_deflateParams (z_stream* strm, int level, int strategy);
+
+EXTERN_C int zlib_deflateInit_ (z_stream* strm, int level,
+ const char *version, int stream_size);
+EXTERN_C int zlib_deflateInit2_ (z_stream* strm, int level, int method,
+ int windowBits, int memLevel,
+ int strategy, const char *version,
+ int stream_size);
+#define zlib_deflateInit(strm, level) \
+ zlib_deflateInit_((strm), (level), ZLIB_VERSION, sizeof(z_stream))
+#define zlib_deflateInit2(strm, level, method, windowBits, memLevel, strategy) \
+ zlib_deflateInit2_((strm),(level),(method),(windowBits),(memLevel),\
+ (strategy), ZLIB_VERSION, sizeof(z_stream))
+
+#endif
diff --git a/graphics/sam2p/pts_fax.c b/graphics/sam2p/pts_fax.c
new file mode 100644
index 0000000000..46f48e23fb
--- /dev/null
+++ b/graphics/sam2p/pts_fax.c
@@ -0,0 +1,3222 @@
+/*
+ * pts_fax.c -- a compact CCITTFax compressor and uncompressor) implementation
+ * compiled by pts@fazekas.hu at Sun Jul 7 19:51:42 CEST 2002
+ *
+ * algorithm ripped from GNU Ghostscript, implementation and (C):
+ *
+Copyright (C) 1993, 1995, 1996, 1997, 1998, 1999 Aladdin Enterprises. All
+rights reserved.
+
+GNU Ghostscript is free software; you can redistribute it and/or
+modify it under the terms of version 2 of the GNU General Public
+License as published by the Free Software Foundation.
+
+GNU Ghostscript is distributed in the hope that it will be
+useful, but WITHOUT ANY WARRANTY; without even the implied warranty
+of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program so you can know your rights and responsibilities.
+It should be in a file named doc/COPYING. If not, write to the
+Free Software Foundation, Inc., 59 Temple Place Suite 330, Boston, MA
+02111-1307, USA.
+ */
+
+#include "pts_fax.h"
+#if 0 /* doesn't work in C++ */
+# define intern static
+# define impl static
+# define intern_const static const
+# define impl_const static const
+#else
+# define intern static
+# define impl static
+# define intern_const extern const
+# define impl_const const
+#endif
+/* #define cxxintern extern */
+
+#ifdef __GNUC__
+#ifndef __clang__
+#pragma implementation
+#endif
+#endif
+
+/* misc_types.h by pts@fazekas.hu at Sat Jul 6 19:20:17 CEST 2002 */
+#ifndef MISC_TYPES_H
+#define MISC_TYPES_H 1
+
+/* #include "config2.h" */
+
+#define BEGIN do {
+#define END } while (0)
+#ifndef DO_NOTHING
+# define DO_NOTHING BEGIN END
+#endif
+
+# define if_debug0(c,s) DO_NOTHING
+# define if_debug1(c,s,a1) DO_NOTHING
+# define if_debug2(c,s,a1,a2) DO_NOTHING
+# define if_debug3(c,s,a1,a2,a3) DO_NOTHING
+# define if_debug4(c,s,a1,a2,a3,a4) DO_NOTHING
+# define if_debug5(c,s,a1,a2,a3,a4,a5) DO_NOTHING
+# define if_debug6(c,s,a1,a2,a3,a4,a5,a6) DO_NOTHING
+# define if_debug7(c,s,a1,a2,a3,a4,a5,a6,a7) DO_NOTHING
+# define if_debug8(c,s,a1,a2,a3,a4,a5,a6,a7,a8) DO_NOTHING
+# define if_debug9(c,s,a1,a2,a3,a4,a5,a6,a7,a8,a9) DO_NOTHING
+# define if_debug10(c,s,a1,a2,a3,a4,a5,a6,a7,a8,a9,a10) DO_NOTHING
+# define if_debug11(c,s,a1,a2,a3,a4,a5,a6,a7,a8,a9,a10,a11) DO_NOTHING
+# define if_debug12(c,s,a1,a2,a3,a4,a5,a6,a7,a8,a9,a10,a11,a12) DO_NOTHING
+
+/* to the one that all the compilers seem to have.... */
+#ifndef min
+# define min(a, b) (((a) < (b)) ? (a) : (b))
+#endif
+#ifndef max
+# define max(a, b) (((a) > (b)) ? (a) : (b))
+#endif
+
+/* Define a standard way to round values to a (constant) modulus. */
+#define ROUND_DOWN(value, modulus)\
+ ( (modulus) & ((modulus) - 1) ? /* not a power of 2 */\
+ (value) - (value) % (modulus) :\
+ (value) & -(modulus) )
+#define ROUND_UP(value, modulus)\
+ ( (modulus) & ((modulus) - 1) ? /* not a power of 2 */\
+ ((value) + ((modulus) - 1)) / (modulus) * (modulus) :\
+ ((value) + ((modulus) - 1)) & -(modulus) )
+
+#define countof(a) (sizeof(a) / sizeof((a)[0]))
+
+#define gs_alloc_bytes(a, n, c) ss->xalloc_(n)
+#define gs_free_object(a, ptr, c) ss->free_(ptr)
+
+#endif /* gstypes.h */
+/* end of former misc_types.h */
+
+/* gsbittab.h */
+/*$Id: pts_fax.c,v 1.3 2005/02/21 13:09:56 pts Exp $ */
+/* Interface to tables for bit operations */
+
+#ifndef gsbittab_INCLUDED
+# define gsbittab_INCLUDED
+
+/*
+ * Generate tables for transforming 2, 4, 6, or 8 bits.
+ */
+#define btab2_(v0,v2,v1)\
+ v0,v1+v0,v2+v0,v2+v1+v0
+#define bit_table_2(v0,v2,v1) btab2_(v0,v2,v1)
+#define btab4_(v0,v8,v4,v2,v1)\
+ btab2_(v0,v2,v1), btab2_(v4+v0,v2,v1),\
+ btab2_(v8+v0,v2,v1), btab2_(v8+v4+v0,v2,v1)
+#define bit_table_4(v0,v8,v4,v2,v1) btab4_(v0,v8,v4,v2,v1)
+#define btab6_(v0,v20,v10,v8,v4,v2,v1)\
+ btab4_(v0,v8,v4,v2,v1), btab4_(v10+v0,v8,v4,v2,v1),\
+ btab4_(v20+v0,v8,v4,v2,v1), btab4_(v20+v10+v0,v8,v4,v2,v1)
+#define bit_table_6(v0,v20,v10,v8,v4,v2,v1) btab6_(v0,v20,v10,v8,v4,v2,v1)
+#define bit_table_8(v0,v80,v40,v20,v10,v8,v4,v2,v1)\
+ btab6_(v0,v20,v10,v8,v4,v2,v1), btab6_(v40+v0,v20,v10,v8,v4,v2,v1),\
+ btab6_(v80+v0,v20,v10,v8,v4,v2,v1), btab6_(v80+v40+v0,v20,v10,v8,v4,v2,v1)
+
+/*
+ * byte_reverse_bits[B] = the unsigned char B with the order of bits reversed.
+ */
+intern_const unsigned char byte_reverse_bits[256];
+
+/*
+ * byte_right_mask[N] = a unsigned char with N trailing 1s, 0 <= N <= 8.
+ */
+intern_const unsigned char byte_right_mask[9];
+
+/*
+ * byte_count_bits[B] = the number of 1-bits in a unsigned char with value B.
+ */
+intern_const unsigned char byte_count_bits[256];
+
+/*
+ * byte_bit_run_length_N[B], for 0 <= N <= 7, gives the length of the
+ * run of 1-bits starting at bit N in a unsigned char with value B,
+ * numbering the bits in the unsigned char as 01234567. If the run includes
+ * the low-order bit (i.e., might be continued into a following unsigned char),
+ * the run length is increased by 8.
+ */
+intern_const unsigned char
+ byte_bit_run_length_0[256], byte_bit_run_length_1[256],
+ byte_bit_run_length_2[256], byte_bit_run_length_3[256],
+ byte_bit_run_length_4[256], byte_bit_run_length_5[256],
+ byte_bit_run_length_6[256], byte_bit_run_length_7[256];
+
+/*
+ * byte_bit_run_length[N] points to byte_bit_run_length_N.
+ * byte_bit_run_length_neg[N] = byte_bit_run_length[-N & 7].
+ */
+intern_const unsigned char *const byte_bit_run_length[8];
+intern_const unsigned char *const byte_bit_run_length_neg[8];
+
+/*
+ * byte_acegbdfh_to_abcdefgh[acegbdfh] = abcdefgh, where the letters
+ * denote the individual bits of the unsigned char.
+ */
+intern_const unsigned char byte_acegbdfh_to_abcdefgh[256];
+
+#endif /* gsbittab_INCLUDED */
+
+/* end of former gsbittab.h */
+
+/* shc.h */
+/*$Id: pts_fax.c,v 1.3 2005/02/21 13:09:56 pts Exp $ */
+/* Common definitions for filters using Huffman coding */
+
+#ifndef shc_INCLUDED
+# define shc_INCLUDED
+
+/* #include "gsbittab.h" */
+
+#define hc_bits_size (SIZEOF_INT * 8)
+#define s_hce_init_inline(ss)\
+ ((ss)->bits = 0, (ss)->bits_left = hc_bits_size)
+#define s_hcd_init_inline(ss)\
+ ((ss)->bits = 0, (ss)->bits_left = 0)
+
+/*
+ * These definitions are valid for code lengths up to 16 bits
+ * and non-negative decoded values up to 15 bits.
+ *
+ * We define 3 different representations of the code: encoding tables,
+ * decoding tables, and a definition table which can be generated easily
+ * from frequency information and which in turn can easily generate
+ * the encoding and decoding tables.
+ *
+ * The definition table has two parts: a list of the number of i-bit
+ * codes for each i >= 1, and the decoded values corresponding to
+ * the code values in increasing lexicographic order (which will also
+ * normally be decreasing code frequency). Calling these two lists
+ * L[1..M] and V[0..N-1] respectively, we have the following invariants:
+ * - 1 <= M <= max_hc_length, N >= 2.
+ * - L[0] = 0.
+ * - for i=1..M, L[i] >= 0.
+ * - sum(i=1..M: L[i]) = N.
+ * - sum(i=1..M: L[i] * 2^-i) = 1.
+ * - V[0..N-1] are a permutation of the integers 0..N-1.
+ */
+#define max_hc_length 16
+typedef struct hc_definition_s {
+ unsigned short *counts; /* [0..M] */
+ unsigned int num_counts; /* M */
+ unsigned short *values; /* [0..N-1] */
+ unsigned int num_values; /* N */
+} hc_definition;
+
+/**** pts ****/
+struct stream_hc_state_s;
+/* definition moved to pts_fax.h */
+
+/* ------ Encoding tables ------ */
+
+/* Define the structure for the encoding tables. */
+typedef struct hce_code_s {
+ unsigned short code;
+ unsigned short code_length;
+} hce_code;
+
+#define hce_entry(c, len) { c, len }
+
+typedef struct hce_table_s {
+ unsigned int count;
+ hce_code *codes;
+} hce_table;
+
+#define hce_bits_available(n)\
+ (ss->bits_left >= (n) || wlimit - q > ((n) - ss->bits_left - 1) >> 3)
+
+/* ------ Encoding utilities ------ */
+
+/*
+ * Put a code on the output. The client is responsible for ensuring
+ * that q does not exceed pw->limit.
+ */
+
+#ifdef DEBUG
+# define hc_print_value(code, clen)\
+ (gs_debug_c('W') ?\
+ (dlprintf2("[W]0x%x,%d\n", code, clen), 0) : 0)
+# define hc_print_value_then(code, clen) hc_print_value(code, clen),
+#else
+# define hc_print_value(code, clen) 0
+# define hc_print_value_then(code, clen) /* */
+#endif
+#define hc_print_code(rp) hc_print_value((rp)->code, (rp)->code_length)
+
+/* Declare variables that hold the encoder state. */
+#define hce_declare_state\
+ register unsigned int bits;\
+ register int bits_left
+
+/* Load the state from the stream. */
+/* Free variables: ss, bits, bits_left. */
+#define hce_load_state()\
+ bits = ss->bits, bits_left = ss->bits_left
+
+/* Store the state back in the stream. */
+/* Free variables: ss, bits, bits_left. */
+#define hce_store_state()\
+ ss->bits = bits, ss->bits_left = bits_left
+
+/* Put a code on the stream. */
+intern void hc_put_code_proc _((bool, unsigned char *, unsigned int));
+
+#define hc_put_value(ss, q, code, clen)\
+ (hc_print_value_then(code, clen)\
+ ((bits_left -= (clen)) >= 0 ?\
+ (bits += (code) << bits_left) :\
+ (hc_put_code_proc((ss)->FirstBitLowOrder,\
+ q += hc_bits_size >> 3,\
+ (bits + ((code) >> -bits_left))),\
+ bits = (code) << (bits_left += hc_bits_size))))
+#define hc_put_code(ss, q, cp)\
+ hc_put_value(ss, q, (cp)->code, (cp)->code_length)
+
+/*
+ * Force out the final bits to the output.
+ * Note that this does a store_state, but not a load_state.
+ */
+intern unsigned char *hc_put_last_bits_proc _((struct stream_hc_state_s *, unsigned char *, unsigned int, int));
+
+#define hc_put_last_bits(ss, q)\
+ hc_put_last_bits_proc(ss, q, bits, bits_left)
+
+/* ------ Decoding tables ------ */
+
+/*
+ * Define the structure for the decoding tables.
+ * First-level nodes are either leaves, which have
+ * value = decoded value
+ * code_length <= initial_bits
+ * or non-leaves, which have
+ * value = the index of a sub-table
+ * code_length = initial_bits + the number of additional dispatch bits
+ * Second-level nodes are always leaves, with
+ * code_length = the actual number of bits in the code - initial_bits.
+ */
+
+typedef struct hcd_code_s {
+ short value;
+ unsigned short code_length;
+} hcd_code;
+
+typedef struct hcd_table_s {
+ unsigned int count;
+ unsigned int initial_bits;
+ hcd_code *codes;
+} hcd_table;
+
+/* Declare variables that hold the decoder state. */
+#define hcd_declare_state\
+ register const unsigned char *p;\
+ const unsigned char *rlimit;\
+ unsigned int bits;\
+ int bits_left
+
+/* Load the state from the stream. */
+/* Free variables: pr, ss, p, rlimit, bits, bits_left. */
+#define hcd_load_state()\
+ p = pr->ptr,\
+ rlimit = pr->limit,\
+ bits = ss->bits,\
+ bits_left = ss->bits_left
+
+/* Store the state back in the stream. */
+/* Put back any complete bytes into the input buffer. */
+/* Free variables: pr, ss, p, bits, bits_left. */
+#define hcd_store_state()\
+ pr->ptr = p -= (bits_left >> 3),\
+ ss->bits = bits >>= (bits_left & ~7),\
+ ss->bits_left = bits_left &= 7
+
+/* Macros to get blocks of bits from the input stream. */
+/* Invariants: 0 <= bits_left <= bits_size; */
+/* bits [bits_left-1..0] contain valid data. */
+
+#define hcd_bits_available(n)\
+ (bits_left >= (n) || rlimit - p > ((n) - bits_left - 1) >> 3)
+/* For hcd_ensure_bits, n must not be greater than 8. */
+#define HCD_ENSURE_BITS_ELSE(n)\
+ if (bits_left >= n)\
+ DO_NOTHING;\
+ else HCD_MORE_BITS_ELSE
+#define hcd_ensure_bits(n, outl)\
+ BEGIN HCD_ENSURE_BITS_ELSE(n) goto outl; END
+
+/* Load more bits into the buffer. */
+#define HCD_MORE_BITS_1_ELSE\
+ if (p < rlimit) {\
+ int c = *++p;\
+\
+ if (ss->FirstBitLowOrder)\
+ c = byte_reverse_bits[c];\
+ bits = (bits << 8) + c, bits_left += 8;\
+ } else
+#if hc_bits_size == 16
+# define HCD_MORE_BITS_ELSE HCD_MORE_BITS_1_ELSE
+#else /* hc_bits_size >= 32 */
+# define HCD_MORE_BITS_ELSE\
+ if (rlimit - p >= 3) {\
+ if (ss->FirstBitLowOrder)\
+ bits = (bits << 24) + ((unsigned int)byte_reverse_bits[p[1]] << 16) + ((unsigned int)byte_reverse_bits[p[2]] << 8) + byte_reverse_bits[p[3]];\
+ else\
+ bits = (bits << 24) + ((unsigned int)p[1] << 16) + ((unsigned int)p[2] << 8) + p[3];\
+ bits_left += 24, p += 3;\
+ } else HCD_MORE_BITS_1_ELSE
+#endif
+#define hcd_more_bits(outl)\
+ BEGIN HCD_MORE_BITS_ELSE goto outl; END
+
+#define hcd_peek_bits(n) ((bits >> (bits_left - (n))) & ((1 << (n)) - 1))
+
+/* hcd_peek_var_bits requires bits_left <= 8. */
+#define hcd_peek_var_bits(n)\
+ ((bits >> (bits_left - (n))) & byte_right_mask[n])
+
+/* hcd_peek_bits_left requires bits_left <= 8. */
+#define hcd_peek_bits_left()\
+ (bits & byte_right_mask[bits_left])
+
+#define hcd_skip_bits(n) (bits_left -= (n))
+
+#endif /* shc_INCLUDED */
+
+/* end of former shc.h */
+
+/* scf.h */
+/*$Id: pts_fax.c,v 1.3 2005/02/21 13:09:56 pts Exp $ */
+/* Common definitions for CCITTFax encoding and decoding filters */
+
+#ifndef scf_INCLUDED
+# define scf_INCLUDED
+
+/* #include "shc.h" */
+
+/*
+ * The CCITT Group 3 (T.4) and Group 4 (T.6) fax specifications map
+ * run lengths to Huffman codes. White and black have different mappings.
+ * If the run length is 64 or greater, two or more codes are needed:
+ * - One or more 'make-up' codes for 2560 pixels;
+ * - A 'make-up' code that encodes the multiple of 64;
+ * - A 'termination' code for the remainder.
+ * For runs of 63 or less, only the 'termination' code is needed.
+ */
+
+/* ------ Encoding tables ------ */
+
+/*
+ * The maximum possible length of a scan line is determined by the
+ * requirement that 3 runs have to fit into the stream buffer.
+ * A run of length N requires approximately ceil(N / 2560) makeup codes,
+ * hence 1.5 * ceil(N / 2560) bytes. Taking the largest safe stream
+ * buffer size as 32K, we arrive at the following maximum width:
+ */
+#if SIZEOF_INT > 2
+# define cfe_max_width (2560 * 32000 * 2 / 3)
+#else
+# define cfe_max_width (max_int - 40) /* avoid overflows */
+#endif
+/* The +5 in cfe_max_code_bytes is a little conservative. */
+#define cfe_max_code_bytes(width) ((width) / 2560 * 3 / 2 + 5)
+
+typedef hce_code cfe_run;
+
+/* Codes common to 1-D and 2-D encoding. */
+/* The decoding algorithms know that EOL is 0....01. */
+#define run_eol_code_length 12
+#define run_eol_code_value 1
+intern_const cfe_run cf_run_eol;
+typedef struct cf_runs_s {
+ cfe_run termination[64];
+ cfe_run make_up[41];
+} cf_runs;
+intern_const cf_runs
+ cf_white_runs, cf_black_runs;
+intern_const cfe_run cf_uncompressed[6];
+intern_const cfe_run cf_uncompressed_exit[10]; /* indexed by 2 x length of */
+
+ /* white run + (1 if next run black, 0 if white) */
+/* 1-D encoding. */
+intern_const cfe_run cf1_run_uncompressed;
+
+/* 2-D encoding. */
+intern_const cfe_run cf2_run_pass;
+
+#define cf2_run_pass_length 4
+#define cf2_run_pass_value 0x1
+#define cf2_run_vertical_offset 3
+intern_const cfe_run cf2_run_vertical[7]; /* indexed by b1 - a1 + offset */
+intern_const cfe_run cf2_run_horizontal;
+
+#define cf2_run_horizontal_value 1
+#define cf2_run_horizontal_length 3
+intern_const cfe_run cf2_run_uncompressed;
+
+/* 2-D Group 3 encoding. */
+intern_const cfe_run cf2_run_eol_1d;
+intern_const cfe_run cf2_run_eol_2d;
+
+/* ------ Decoding tables ------ */
+
+typedef hcd_code cfd_node;
+
+#define run_length value
+
+/*
+ * The value in the decoding tables is either a white or black run length,
+ * or a (negative) exceptional value.
+ */
+#define run_error (-1)
+#define run_zeros (-2) /* EOL follows, possibly with more padding first */
+#define run_uncompressed (-3)
+/* 2-D codes */
+#define run2_pass (-4)
+#define run2_horizontal (-5)
+
+#define cfd_white_initial_bits 8
+#define cfd_white_min_bits 4 /* shortest white run */
+/* intern_const cfd_node cf_white_decode[]; */
+
+#define cfd_black_initial_bits 7
+#define cfd_black_min_bits 2 /* shortest black run */
+/* intern_const cfd_node cf_black_decode[]; */
+
+#define cfd_2d_initial_bits 7
+#define cfd_2d_min_bits 4 /* shortest non-H/V 2-D run */
+/* intern_const cfd_node cf_2d_decode[]; */
+
+#define cfd_uncompressed_initial_bits 6 /* must be 6 */
+/* intern_const cfd_node cf_uncompressed_decode[]; */
+
+/* ------ Run detection macros ------ */
+
+/*
+ * For the run detection macros:
+ * white_byte is 0 or 0xff for BlackIs1 or !BlackIs1 respectively;
+ * data holds p[-1], inverted if !BlackIs1;
+ * count is the number of valid bits remaining in the scan line.
+ */
+
+/* Aliases for bit processing tables. */
+#define cf_byte_run_length byte_bit_run_length_neg
+#define cf_byte_run_length_0 byte_bit_run_length_0
+
+/* Skip over white pixels to find the next black pixel in the input. */
+/* Store the run length in rlen, and update data, p, and count. */
+/* There are many more white pixels in typical input than black pixels, */
+/* and the runs of white pixels tend to be much longer, so we use */
+/* substantially different loops for the two cases. */
+
+#define skip_white_pixels(data, p, count, white_byte, rlen)\
+BEGIN\
+ rlen = cf_byte_run_length[count & 7][data ^ 0xff];\
+ if ( rlen >= 8 ) { /* run extends past unsigned char boundary */\
+ if ( white_byte == 0 ) {\
+ if ( p[0] ) { data = p[0]; p += 1; rlen -= 8; }\
+ else if ( p[1] ) { data = p[1]; p += 2; }\
+ else {\
+ while ( !(p[2] | p[3] | p[4] | p[5]) )\
+ p += 4, rlen += 32;\
+ if ( p[2] ) {\
+ data = p[2]; p += 3; rlen += 8;\
+ } else if ( p[3] ) {\
+ data = p[3]; p += 4; rlen += 16;\
+ } else if ( p[4] ) {\
+ data = p[4]; p += 5; rlen += 24;\
+ } else /* p[5] */ {\
+ data = p[5]; p += 6; rlen += 32;\
+ }\
+ }\
+ } else {\
+ if ( p[0] != 0xff ) { data = (unsigned char)~p[0]; p += 1; rlen -= 8; }\
+ else if ( p[1] != 0xff ) { data = (unsigned char)~p[1]; p += 2; }\
+ else {\
+ while ( (p[2] & p[3] & p[4] & p[5]) == 0xff )\
+ p += 4, rlen += 32;\
+ if ( p[2] != 0xff ) {\
+ data = (unsigned char)~p[2]; p += 3; rlen += 8;\
+ } else if ( p[3] != 0xff ) {\
+ data = (unsigned char)~p[3]; p += 4; rlen += 16;\
+ } else if ( p[4] != 0xff ) {\
+ data = (unsigned char)~p[4]; p += 5; rlen += 24;\
+ } else /* p[5] != 0xff */ {\
+ data = (unsigned char)~p[5]; p += 6; rlen += 32;\
+ }\
+ }\
+ }\
+ rlen += cf_byte_run_length_0[data ^ 0xff];\
+ }\
+ count -= rlen;\
+END
+
+/* Skip over black pixels to find the next white pixel in the input. */
+/* Store the run length in rlen, and update data, p, and count. */
+
+#define skip_black_pixels(data, p, count, white_byte, rlen)\
+BEGIN\
+ rlen = cf_byte_run_length[count & 7][data];\
+ if ( rlen >= 8 ) {\
+ if ( white_byte == 0 )\
+ for ( ; ; p += 4, rlen += 32 ) {\
+ if ( p[0] != 0xff ) { data = p[0]; p += 1; rlen -= 8; break; }\
+ if ( p[1] != 0xff ) { data = p[1]; p += 2; break; }\
+ if ( p[2] != 0xff ) { data = p[2]; p += 3; rlen += 8; break; }\
+ if ( p[3] != 0xff ) { data = p[3]; p += 4; rlen += 16; break; }\
+ }\
+ else\
+ for ( ; ; p += 4, rlen += 32 ) {\
+ if ( p[0] ) { data = (unsigned char)~p[0]; p += 1; rlen -= 8; break; }\
+ if ( p[1] ) { data = (unsigned char)~p[1]; p += 2; break; }\
+ if ( p[2] ) { data = (unsigned char)~p[2]; p += 3; rlen += 8; break; }\
+ if ( p[3] ) { data = (unsigned char)~p[3]; p += 4; rlen += 16; break; }\
+ }\
+ rlen += cf_byte_run_length_0[data];\
+ }\
+ count -= rlen;\
+END
+
+#endif /* scf_INCLUDED */
+
+/* end of former scf.h */
+
+#if USE_BUILTIN_FAXE
+#if OBJDEP
+# warning PROVIDES: pts_faxe
+#endif
+/* scfe.c */
+/*$Id: pts_fax.c,v 1.3 2005/02/21 13:09:56 pts Exp $ */
+/* CCITTFax encoding filter */
+/* #include "config2.h" */
+/* #include "scf.h" */
+/* #include "scfx.h" */
+
+/* ------ Macros and support routines ------ */
+
+/* Statistics */
+
+#ifdef DEBUG
+
+typedef struct stats_runs_s {
+ unsigned long termination[64];
+ unsigned long make_up[41];
+} stats_runs_t;
+static stats_runs_t stats_white_runs, stats_black_runs;
+
+#define COUNT_RUN(tab, i) (tab)[i]++;
+
+static void
+print_run_stats(const stats_runs_t * stats)
+{
+ int i;
+ unsigned long total;
+
+ for (i = 0, total = 0; i < 41; i++)
+ dprintf1(" %lu", stats->make_up[i]),
+ total += stats->make_up[i];
+ dprintf1(" total=%lu\n\t", total);
+ for (i = 0, total = 0; i < 64; i++)
+ dprintf1(" %lu", stats->termination[i]),
+ total += stats->termination[i];
+ dprintf1(" total=%lu\n", total);
+}
+
+#else /* !DEBUG */
+
+#define COUNT_RUN(cnt, i) DO_NOTHING
+
+#endif /* DEBUG */
+
+/* Put a run onto the output stream. */
+/* Free variables: q, bits, bits_left. */
+
+#define CF_PUT_RUN(ss, lenv, rt, stats)\
+BEGIN\
+ cfe_run rr;\
+\
+ if ( lenv >= 64 ) {\
+ hce_store_state();\
+ q = cf_put_long_run(ss, q, lenv, &rt);\
+ hce_load_state();\
+ lenv &= 63;\
+ }\
+ rr = rt.termination[lenv];\
+ COUNT_RUN(stats.termination, lenv);\
+ hc_put_value(ss, q, rr.code, rr.code_length);\
+END
+
+static unsigned char *
+cf_put_long_run(stream_CFE_state * ss, unsigned char * q, int lenv, const cf_runs * prt)
+{
+ hce_declare_state;
+ cfe_run rr;
+
+#ifdef DEBUG
+ stats_runs_t *pstats =
+ (prt == &cf_white_runs ? &stats_white_runs : &stats_black_runs);
+
+#endif
+
+ hce_load_state();
+ while (lenv >= 2560 + 64) {
+ rr = prt->make_up[40];
+ COUNT_RUN(pstats->make_up, 40);
+ hc_put_value(ss, q, rr.code, rr.code_length);
+ lenv -= 2560;
+ }
+ rr = prt->make_up[lenv >> 6];
+ COUNT_RUN(pstats->make_up, lenv >> 6);
+ hc_put_value(ss, q, rr.code, rr.code_length);
+ hce_store_state();
+ return q;
+}
+
+#define CF_PUT_WHITE_RUN(ss, lenv)\
+ CF_PUT_RUN(ss, lenv, cf_white_runs, stats_white_runs)
+
+#define CF_PUT_BLACK_RUN(ss, lenv)\
+ CF_PUT_RUN(ss, lenv, cf_black_runs, stats_black_runs)
+
+/* ------ CCITTFaxEncode ------ */
+
+/* private_st_CFE_state(); */
+
+static void s_CFE_release _((stream_state *));
+
+/* Set default parameter values. */
+static void
+s_CFE_set_defaults(register stream_state * st)
+{
+ stream_CFE_state *const ss = (stream_CFE_state *) st;
+
+ s_CFE_set_defaults_inline(ss);
+}
+
+/* Initialize CCITTFaxEncode filter */
+static int
+s_CFE_init(register stream_state * st)
+{
+ stream_CFE_state *const ss = (stream_CFE_state *) st;
+ int columns = ss->Columns;
+
+ /*
+ * The worst case for encoding is alternating white and black pixels.
+ * For 1-D encoding, the worst case is 9 bits per 2 pixels; for 2-D
+ * (horizontal), 12 bits per 2 pixels. To fill out a scan line,
+ * we may add up to 6 12-bit EOL codes.
+ */
+ /**** pts: added UL ****/
+ int code_bytes =
+ ((columns * (ss->K == 0 ? 9UL : 12UL)) >> 4) + 20; /* add slop */
+ int raster = ss->raster =
+ ROUND_UP((columns + 7) >> 3, ss->DecodedByteAlign);
+
+ s_hce_init_inline(ss);
+ ss->lbuf = ss->lprev = ss->lcode = 0; /* in case we have to release */
+ if (columns > cfe_max_width)
+ return PTSFAX_ERRC;
+/****** WRONG ******/
+ /* Because skip_white_pixels can look as many as 4 bytes ahead, */
+ /* we need to allow 4 extra bytes at the end of the row buffers. */
+ ss->lbuf = (unsigned char*)gs_alloc_bytes(st->memory, raster + 4, "CFE lbuf");
+ ss->lcode = (unsigned char*)gs_alloc_bytes(st->memory, code_bytes, "CFE lcode");
+ if (ss->lbuf == 0 || ss->lcode == 0) {
+ s_CFE_release(st);
+ return PTSFAX_ERRC;
+/****** WRONG ******/
+ }
+ if (ss->K != 0) {
+ ss->lprev = (unsigned char*)gs_alloc_bytes(st->memory, raster + 4, "CFE lprev");
+ if (ss->lprev == 0) {
+ s_CFE_release(st);
+ return PTSFAX_ERRC;
+/****** WRONG ******/
+ }
+ /* Clear the initial reference line for 2-D encoding. */
+ /* Make sure it is terminated properly. */
+ ss->memset_(ss->lprev, (ss->BlackIs1 ? 0 : 0xff), raster);
+ if (columns & 7)
+ ss->lprev[raster - 1] ^= 0x80 >> (columns & 7);
+ else
+ ss->lprev[raster] = ~ss->lprev[0];
+ }
+ ss->read_count = raster;
+ ss->write_count = 0;
+ ss->k_left = (ss->K > 0 ? 1 : ss->K);
+ ss->max_code_bytes = code_bytes;
+ return 0;
+}
+
+/* Release the filter. */
+static void
+s_CFE_release(stream_state * st)
+{
+ stream_CFE_state *const ss = (stream_CFE_state *) st;
+
+ gs_free_object(st->memory, ss->lprev, "CFE lprev(close)");
+ gs_free_object(st->memory, ss->lcode, "CFE lcode(close)");
+ gs_free_object(st->memory, ss->lbuf, "CFE lbuf(close)");
+}
+
+/* Flush the buffer */
+static void cf_encode_1d _((stream_CFE_state *, const unsigned char *,
+ stream_cursor_write *));
+static void cf_encode_2d _((stream_CFE_state *, const unsigned char *,
+ stream_cursor_write *, const unsigned char *));
+static int
+s_CFE_process(stream_state * st, stream_cursor_read * pr,
+ stream_cursor_write * pw, bool last)
+{
+ stream_CFE_state *const ss = (stream_CFE_state *) st;
+ const unsigned char *rlimit = pr->limit;
+ unsigned char *wlimit = pw->limit;
+ int raster = ss->raster;
+ unsigned char end_mask = 1 << (-ss->Columns & 7);
+ int status = 0;
+
+ for (;;) {
+ stream_cursor_write w;
+
+ if_debug2('w', "[w]CFE: read_count = %d, write_count=%d,\n",
+ ss->read_count, ss->write_count);
+ if_debug6('w', " pr = 0x%lx(%d)0x%lx, pw = 0x%lx(%d)0x%lx\n",
+ (unsigned long) pr->ptr, (int)(rlimit - pr->ptr), (unsigned long) rlimit,
+ (unsigned long) pw->ptr, (int)(wlimit - pw->ptr), (unsigned long) wlimit);
+ if (ss->write_count) {
+ /* Copy more of an encoded line to the caller. */
+ int wcount = wlimit - pw->ptr;
+ int ccount = min(wcount, ss->write_count);
+
+ ss->memcpy_(pw->ptr + 1, ss->lcode + ss->code_bytes - ss->write_count,
+ ccount);
+ pw->ptr += ccount;
+ if ((ss->write_count -= ccount) > 0) {
+ status = 1;
+ break;
+ }
+ }
+ if (ss->read_count) {
+ /* Copy more of an unencoded line from the caller. */
+ int rcount = rlimit - pr->ptr;
+ int ccount = min(rcount, ss->read_count);
+
+ if (rcount == 0 && last)
+ break;
+ ss->memcpy_(ss->lbuf + raster - ss->read_count,
+ pr->ptr + 1, ccount);
+ pr->ptr += ccount;
+ if ((ss->read_count -= ccount) != 0)
+ break;
+ }
+ /*
+ * We have a full scan line in lbuf. Ensure that it ends with
+ * two polarity changes.
+ */
+ {
+ unsigned char *end = ss->lbuf + raster - 1;
+ unsigned char end_bit = *end & end_mask;
+ unsigned char not_bit = end_bit ^ end_mask;
+
+ *end &= -end_mask;
+ if (end_mask == 1)
+ end[1] = (end_bit ? 0x40 : 0x80);
+ else if (end_mask == 2)
+ *end |= not_bit >> 1, end[1] = end_bit << 7;
+ else
+ *end |= (not_bit >> 1) | (end_bit >> 2);
+ }
+ /*
+ * Write the output directly to the caller's buffer if it's large
+ * enough, otherwise to our own buffer.
+ */
+ if (wlimit - pw->ptr >= ss->max_code_bytes) {
+ w = *pw;
+ } else {
+ w.ptr = ss->lcode - 1;
+ w.limit = w.ptr + ss->max_code_bytes;
+ }
+#ifdef DEBUG
+ if (ss->K > 0) {
+ if_debug1('w', "[w]new row, k_left=%d\n",
+ ss->k_left);
+ } else {
+ if_debug0('w', "[w]new row\n");
+ }
+#endif
+ /*
+ * Write an EOL (actually a "beginning of line") if requested.
+ */
+ if (ss->EndOfLine) {
+ const cfe_run *rp =
+ (ss->K <= 0 ? &cf_run_eol :
+ ss->k_left > 1 ? &cf2_run_eol_2d :
+ &cf2_run_eol_1d);
+ cfe_run run;
+
+ hce_declare_state;
+
+ hce_load_state();
+ if (ss->EncodedByteAlign) {
+ run = *rp;
+ /* Pad the run on the left */
+ /* so it winds up unsigned char-aligned. */
+ run.code_length +=
+ (bits_left - run_eol_code_length) & 7;
+ if (run.code_length > 16) /* <= 23 */
+ bits_left -= run.code_length & 7,
+ run.code_length = 16;
+ rp = &run;
+ }
+ hc_put_code(ss, w.ptr, rp);
+ hce_store_state();
+ } else if (ss->EncodedByteAlign)
+ ss->bits_left &= ~7;
+ /* Encode the line. */
+ if (ss->K == 0)
+ cf_encode_1d(ss, ss->lbuf, &w); /* pure 1-D */
+ else if (ss->K < 0)
+ cf_encode_2d(ss, ss->lbuf, &w, ss->lprev); /* pure 2-D */
+ else if (--(ss->k_left)) /* mixed, use 2-D */
+ cf_encode_2d(ss, ss->lbuf, &w, ss->lprev);
+ else { /* mixed, use 1-D */
+ cf_encode_1d(ss, ss->lbuf, &w);
+ ss->k_left = ss->K;
+ }
+ /*
+ * If we didn't write directly to the client's buffer, schedule
+ * the output data to be written.
+ */
+ if (w.limit == wlimit)
+ pw->ptr = w.ptr;
+ else
+ ss->write_count = ss->code_bytes = w.ptr - (ss->lcode - 1);
+ if (ss->K != 0) {
+ /* In 2-D modes, swap the current and previous scan lines. */
+ unsigned char *temp = ss->lbuf;
+
+ ss->lbuf = ss->lprev;
+ ss->lprev = temp;
+ }
+ /* Note that the input buffer needs refilling. */
+ ss->read_count = raster;
+ }
+ /*
+ * When we exit from the loop, we know that write_count = 0, and
+ * there is no line waiting to be processed in the input buffer.
+ */
+ if (last && status == 0) {
+ const cfe_run *rp =
+ (ss->K > 0 ? &cf2_run_eol_1d : &cf_run_eol);
+ int i = (!ss->EndOfBlock ? 0 : ss->K < 0 ? 2 : 6);
+ unsigned int bits_to_write =
+ hc_bits_size - ss->bits_left + i * rp->code_length;
+ unsigned char *q = pw->ptr;
+
+ hce_declare_state;
+
+ if (0U+(wlimit - q) < (bits_to_write + 7) >> 3) { /* PTS_UNSIGNED */
+ status = 1;
+ goto out;
+ }
+ hce_load_state();
+ if (ss->EncodedByteAlign)
+ bits_left &= ~7;
+ while (--i >= 0)
+ hc_put_code(ss, q, rp);
+ /* Force out the last unsigned char or bytes. */
+ pw->ptr = hc_put_last_bits((stream_hc_state *) ss, q);
+ }
+ out:
+ if_debug9('w', "[w]CFE exit %d: read_count = %d, write_count = %d,\n pr = 0x%lx(%d)0x%lx; pw = 0x%lx(%d)0x%lx\n",
+ status, ss->read_count, ss->write_count,
+ (unsigned long) pr->ptr, (int)(rlimit - pr->ptr), (unsigned long) rlimit,
+ (unsigned long) pw->ptr, (int)(wlimit - pw->ptr), (unsigned long) wlimit);
+#ifdef DEBUG
+ if (pr->ptr > rlimit || pw->ptr > wlimit) {
+ lprintf("Pointer overrun!\n");
+ status = PTSFAX_ERRC;
+ }
+ if (gs_debug_c('w') && status == 1) {
+ dlputs("[w]white runs:");
+ print_run_stats(&stats_white_runs);
+ dlputs("[w]black runs:");
+ print_run_stats(&stats_black_runs);
+ }
+#endif
+ return status;
+}
+
+/* Encode a 1-D scan line. */
+static void
+cf_encode_1d(stream_CFE_state * ss, const unsigned char * lbuf, stream_cursor_write * pw)
+{
+ unsigned int count = ss->raster << 3;
+ unsigned char *q = pw->ptr;
+ int end_count = -ss->Columns & 7;
+ int rlen;
+
+ hce_declare_state;
+ const unsigned char *p = lbuf;
+ unsigned char invert = (ss->BlackIs1 ? 0 : 0xff);
+
+ /* Invariant: data = p[-1] ^ invert. */
+ unsigned int data = *p++ ^ invert;
+
+ hce_load_state();
+ while (count != 0U+end_count) { /* PTS_UNSIGNED */
+ /* Parse a white run. */
+ skip_white_pixels(data, p, count, invert, rlen);
+ CF_PUT_WHITE_RUN(ss, rlen);
+ if (count == 0U+end_count) /* PTS_UNSIGNED */
+ break;
+ /* Parse a black run. */
+ skip_black_pixels(data, p, count, invert, rlen);
+ CF_PUT_BLACK_RUN(ss, rlen);
+ }
+ hce_store_state();
+ pw->ptr = q;
+}
+
+/* Encode a 2-D scan line. */
+static void
+cf_encode_2d(stream_CFE_state * ss, const unsigned char * lbuf, stream_cursor_write * pw,
+ const unsigned char * lprev)
+{
+ unsigned char invert_white = (ss->BlackIs1 ? 0 : 0xff);
+ unsigned char invert = invert_white;
+ unsigned int count = ss->raster << 3;
+ int end_count = -ss->Columns & 7;
+ const unsigned char *p = lbuf;
+ unsigned char *q = pw->ptr;
+ unsigned int data = *p++ ^ invert;
+
+ hce_declare_state;
+ /*
+ * In order to handle the nominal 'changing white' at the beginning of
+ * each scan line, we need to suppress the test for an initial black bit
+ * in the reference line when we are at the very beginning of the scan
+ * line. To avoid an extra test, we use two different mask tables.
+ */
+ static const unsigned char initial_count_bit[8] =
+ {
+ 0, 1, 2, 4, 8, 0x10, 0x20, 0x40
+ };
+ static const unsigned char further_count_bit[8] =
+ {
+ 0x80, 1, 2, 4, 8, 0x10, 0x20, 0x40
+ };
+ const unsigned char *count_bit = initial_count_bit;
+
+ hce_load_state();
+ while (count != 0U+end_count) { /* PTS_UNSIGNED */
+ /*
+ * If invert == invert_white, white and black have their
+ * correct meanings; if invert == ~invert_white,
+ * black and white are interchanged.
+ */
+ unsigned int a0 = count;
+ unsigned int a1;
+
+#define b1 (a1 - diff) /* only for printing */
+ int diff;
+ unsigned int prev_count = count;
+ const unsigned char *prev_p = p - lbuf + lprev;
+ unsigned char prev_data = prev_p[-1] ^ invert;
+ int rlen;
+
+ /* Find the a1 and b1 transitions. */
+ skip_white_pixels(data, p, count, invert, rlen);
+ a1 = count;
+ if ((prev_data & count_bit[prev_count & 7])) {
+ /* Look for changing white first. */
+ skip_black_pixels(prev_data, prev_p, prev_count, invert, rlen);
+ }
+ count_bit = further_count_bit; /* no longer at beginning */
+ pass:
+ if (prev_count != 0U+end_count) /* PTS_UNSIGNED */
+ skip_white_pixels(prev_data, prev_p, prev_count, invert, rlen);
+ diff = a1 - prev_count; /* i.e., logical b1 - a1 */
+ /* In all the comparisons below, remember that count */
+ /* runs downward, not upward, so the comparisons are */
+ /* reversed. */
+ if (diff <= -2) {
+ /* Could be a pass mode. Find b2. */
+ if (prev_count != 0U+ end_count) /* PTS_UNSIGNED */
+ skip_black_pixels(prev_data, prev_p,
+ prev_count, invert, rlen);
+ if (prev_count > a1) {
+ /* Use pass mode. */
+ if_debug4('W', "[W]pass: count = %d, a1 = %d, b1 = %d, new count = %d\n",
+ a0, a1, b1, prev_count);
+ hc_put_value(ss, q, cf2_run_pass_value, cf2_run_pass_length);
+ a0 = prev_count;
+ goto pass;
+ }
+ }
+ /* Check for vertical coding. */
+ if (diff <= 3 && diff >= -3) {
+ /* Use vertical coding. */
+ const cfe_run *cp = &cf2_run_vertical[diff + 3];
+
+ if_debug5('W', "[W]vertical %d: count = %d, a1 = %d, b1 = %d, new count = %d\n",
+ diff, a0, a1, b1, count);
+ hc_put_code(ss, q, cp);
+ invert = ~invert; /* a1 polarity changes */
+ data ^= 0xff;
+ continue;
+ }
+ /* No luck, use horizontal coding. */
+ if (count != 0U+end_count) /* PTS_UNSIGNED */
+ skip_black_pixels(data, p, count, invert, rlen); /* find a2 */
+ hc_put_value(ss, q, cf2_run_horizontal_value,
+ cf2_run_horizontal_length);
+ a0 -= a1;
+ a1 -= count;
+ if (invert == invert_white) {
+ if_debug3('W', "[W]horizontal: white = %d, black = %d, new count = %d\n",
+ a0, a1, count);
+ CF_PUT_WHITE_RUN(ss, a0);
+ CF_PUT_BLACK_RUN(ss, a1);
+ } else {
+ if_debug3('W', "[W]horizontal: black = %d, white = %d, new count = %d\n",
+ a0, a1, count);
+ CF_PUT_BLACK_RUN(ss, a0);
+ CF_PUT_WHITE_RUN(ss, a1);
+#undef b1
+ }
+ }
+ hce_store_state();
+ pw->ptr = q;
+}
+
+/* Stream template */
+const stream_template s_CFE_template = {
+ /*0, &st_CFE_state*/ s_CFE_init, s_CFE_process, 1, 1,
+ s_CFE_release, s_CFE_set_defaults, 0
+};
+/* end of former scfe.c */
+
+/* scfetab.c */
+/*$Id: pts_fax.c,v 1.3 2005/02/21 13:09:56 pts Exp $ */
+/* Tables for CCITTFaxEncode filter */
+/* #include "scommon.h" */ /* for scf.h */
+/* #include "scf.h" */
+
+/* We make this a separate file so that it can be used by */
+/* the program that generates the tables for the CCITTFaxDecode filter. */
+
+/* ------ Run encoding tables ------ */
+
+/* Abbreviate hce_entry to make the file smaller. */
+#define RUN(c,len) hce_entry(c,len)
+
+/* Define the end-of-line code. */
+/* Code in scfd.c and scfdgen.c knows that the run value is 1. */
+impl_const cfe_run cf_run_eol =
+RUN(run_eol_code_value, run_eol_code_length);
+
+/* Define the 1-D code that signals uncompressed data. */
+impl_const cfe_run cf1_run_uncompressed =
+RUN(0xf, 12);
+
+/* Define the 2-D run codes. */
+impl_const cfe_run cf2_run_pass =
+RUN(cf2_run_pass_value, cf2_run_pass_length);
+impl_const cfe_run cf2_run_vertical[7] =
+{
+ RUN(0x3, 7),
+ RUN(0x3, 6),
+ RUN(0x3, 3),
+ RUN(0x1, 1),
+ RUN(0x2, 3),
+ RUN(0x2, 6),
+ RUN(0x2, 7)
+};
+impl_const cfe_run cf2_run_horizontal =
+RUN(cf2_run_horizontal_value, cf2_run_horizontal_length);
+impl_const cfe_run cf2_run_uncompressed =
+RUN(0xf, 10);
+
+/* EOL codes for Group 3 2-D. */
+/* Code in scfd.c knows that these are 0...01x. */
+impl_const cfe_run cf2_run_eol_1d =
+RUN((run_eol_code_value << 1) + 1, run_eol_code_length + 1);
+impl_const cfe_run cf2_run_eol_2d =
+RUN((run_eol_code_value << 1) + 0, run_eol_code_length + 1);
+
+/* White run codes. */
+impl_const cf_runs cf_white_runs =
+{
+ { /* Termination codes */
+ RUN(0x35, 8), RUN(0x7, 6), RUN(0x7, 4), RUN(0x8, 4),
+ RUN(0xb, 4), RUN(0xc, 4), RUN(0xe, 4), RUN(0xf, 4),
+ RUN(0x13, 5), RUN(0x14, 5), RUN(0x7, 5), RUN(0x8, 5),
+ RUN(0x8, 6), RUN(0x3, 6), RUN(0x34, 6), RUN(0x35, 6),
+ RUN(0x2a, 6), RUN(0x2b, 6), RUN(0x27, 7), RUN(0xc, 7),
+ RUN(0x8, 7), RUN(0x17, 7), RUN(0x3, 7), RUN(0x4, 7),
+ RUN(0x28, 7), RUN(0x2b, 7), RUN(0x13, 7), RUN(0x24, 7),
+ RUN(0x18, 7), RUN(0x2, 8), RUN(0x3, 8), RUN(0x1a, 8),
+ RUN(0x1b, 8), RUN(0x12, 8), RUN(0x13, 8), RUN(0x14, 8),
+ RUN(0x15, 8), RUN(0x16, 8), RUN(0x17, 8), RUN(0x28, 8),
+ RUN(0x29, 8), RUN(0x2a, 8), RUN(0x2b, 8), RUN(0x2c, 8),
+ RUN(0x2d, 8), RUN(0x4, 8), RUN(0x5, 8), RUN(0xa, 8),
+ RUN(0xb, 8), RUN(0x52, 8), RUN(0x53, 8), RUN(0x54, 8),
+ RUN(0x55, 8), RUN(0x24, 8), RUN(0x25, 8), RUN(0x58, 8),
+ RUN(0x59, 8), RUN(0x5a, 8), RUN(0x5b, 8), RUN(0x4a, 8),
+ RUN(0x4b, 8), RUN(0x32, 8), RUN(0x33, 8), RUN(0x34, 8)
+ },
+ { /* Make-up codes */
+ RUN(0, 0) /* dummy */ , RUN(0x1b, 5), RUN(0x12, 5), RUN(0x17, 6),
+ RUN(0x37, 7), RUN(0x36, 8), RUN(0x37, 8), RUN(0x64, 8),
+ RUN(0x65, 8), RUN(0x68, 8), RUN(0x67, 8), RUN(0xcc, 9),
+ RUN(0xcd, 9), RUN(0xd2, 9), RUN(0xd3, 9), RUN(0xd4, 9),
+ RUN(0xd5, 9), RUN(0xd6, 9), RUN(0xd7, 9), RUN(0xd8, 9),
+ RUN(0xd9, 9), RUN(0xda, 9), RUN(0xdb, 9), RUN(0x98, 9),
+ RUN(0x99, 9), RUN(0x9a, 9), RUN(0x18, 6), RUN(0x9b, 9),
+ RUN(0x8, 11), RUN(0xc, 11), RUN(0xd, 11), RUN(0x12, 12),
+ RUN(0x13, 12), RUN(0x14, 12), RUN(0x15, 12), RUN(0x16, 12),
+ RUN(0x17, 12), RUN(0x1c, 12), RUN(0x1d, 12), RUN(0x1e, 12),
+ RUN(0x1f, 12)
+ }
+};
+
+/* Black run codes. */
+impl_const cf_runs cf_black_runs =
+{
+ { /* Termination codes */
+ RUN(0x37, 10), RUN(0x2, 3), RUN(0x3, 2), RUN(0x2, 2),
+ RUN(0x3, 3), RUN(0x3, 4), RUN(0x2, 4), RUN(0x3, 5),
+ RUN(0x5, 6), RUN(0x4, 6), RUN(0x4, 7), RUN(0x5, 7),
+ RUN(0x7, 7), RUN(0x4, 8), RUN(0x7, 8), RUN(0x18, 9),
+ RUN(0x17, 10), RUN(0x18, 10), RUN(0x8, 10), RUN(0x67, 11),
+ RUN(0x68, 11), RUN(0x6c, 11), RUN(0x37, 11), RUN(0x28, 11),
+ RUN(0x17, 11), RUN(0x18, 11), RUN(0xca, 12), RUN(0xcb, 12),
+ RUN(0xcc, 12), RUN(0xcd, 12), RUN(0x68, 12), RUN(0x69, 12),
+ RUN(0x6a, 12), RUN(0x6b, 12), RUN(0xd2, 12), RUN(0xd3, 12),
+ RUN(0xd4, 12), RUN(0xd5, 12), RUN(0xd6, 12), RUN(0xd7, 12),
+ RUN(0x6c, 12), RUN(0x6d, 12), RUN(0xda, 12), RUN(0xdb, 12),
+ RUN(0x54, 12), RUN(0x55, 12), RUN(0x56, 12), RUN(0x57, 12),
+ RUN(0x64, 12), RUN(0x65, 12), RUN(0x52, 12), RUN(0x53, 12),
+ RUN(0x24, 12), RUN(0x37, 12), RUN(0x38, 12), RUN(0x27, 12),
+ RUN(0x28, 12), RUN(0x58, 12), RUN(0x59, 12), RUN(0x2b, 12),
+ RUN(0x2c, 12), RUN(0x5a, 12), RUN(0x66, 12), RUN(0x67, 12)
+ },
+ { /* Make-up codes. */
+ RUN(0, 0) /* dummy */ , RUN(0xf, 10), RUN(0xc8, 12), RUN(0xc9, 12),
+ RUN(0x5b, 12), RUN(0x33, 12), RUN(0x34, 12), RUN(0x35, 12),
+ RUN(0x6c, 13), RUN(0x6d, 13), RUN(0x4a, 13), RUN(0x4b, 13),
+ RUN(0x4c, 13), RUN(0x4d, 13), RUN(0x72, 13), RUN(0x73, 13),
+ RUN(0x74, 13), RUN(0x75, 13), RUN(0x76, 13), RUN(0x77, 13),
+ RUN(0x52, 13), RUN(0x53, 13), RUN(0x54, 13), RUN(0x55, 13),
+ RUN(0x5a, 13), RUN(0x5b, 13), RUN(0x64, 13), RUN(0x65, 13),
+ RUN(0x8, 11), RUN(0xc, 11), RUN(0xd, 11), RUN(0x12, 12),
+ RUN(0x13, 12), RUN(0x14, 12), RUN(0x15, 12), RUN(0x16, 12),
+ RUN(0x17, 12), RUN(0x1c, 12), RUN(0x1d, 12), RUN(0x1e, 12),
+ RUN(0x1f, 12)
+ }
+};
+
+/* Uncompressed codes. */
+impl_const cfe_run cf_uncompressed[6] =
+{
+ RUN(1, 1),
+ RUN(1, 2),
+ RUN(1, 3),
+ RUN(1, 4),
+ RUN(1, 5),
+ RUN(1, 6)
+};
+
+/* Uncompressed exit codes. */
+impl_const cfe_run cf_uncompressed_exit[10] =
+{
+ RUN(2, 8), RUN(3, 8),
+ RUN(2, 9), RUN(3, 9),
+ RUN(2, 10), RUN(3, 10),
+ RUN(2, 11), RUN(3, 11),
+ RUN(2, 12), RUN(3, 12)
+};
+
+#if 0
+/* Some C compilers insist on having executable code in every file.... */
+void scfetab_dummy _((void)); /* for picky compilers */
+void
+scfetab_dummy(void)
+{
+}
+#endif
+
+/* end of former scfetab.c */
+
+#endif /* USE_BUILTIN_FAXE */
+
+#if USE_BUILTIN_FAXD
+#if OBJDEP
+# warning PROVIDES: pts_faxd
+#endif
+/* scfdtab.c; must be before scfd.c */
+/* #include "scommon.h" */ /* for scf.h */
+/* #include "scf.h" */
+
+/* White decoding table. */
+impl_const cfd_node cf_white_decode[] = {
+ { 256, 12 },
+ { 272, 12 },
+ { 29, 8 },
+ { 30, 8 },
+ { 45, 8 },
+ { 46, 8 },
+ { 22, 7 },
+ { 22, 7 },
+ { 23, 7 },
+ { 23, 7 },
+ { 47, 8 },
+ { 48, 8 },
+ { 13, 6 },
+ { 13, 6 },
+ { 13, 6 },
+ { 13, 6 },
+ { 20, 7 },
+ { 20, 7 },
+ { 33, 8 },
+ { 34, 8 },
+ { 35, 8 },
+ { 36, 8 },
+ { 37, 8 },
+ { 38, 8 },
+ { 19, 7 },
+ { 19, 7 },
+ { 31, 8 },
+ { 32, 8 },
+ { 1, 6 },
+ { 1, 6 },
+ { 1, 6 },
+ { 1, 6 },
+ { 12, 6 },
+ { 12, 6 },
+ { 12, 6 },
+ { 12, 6 },
+ { 53, 8 },
+ { 54, 8 },
+ { 26, 7 },
+ { 26, 7 },
+ { 39, 8 },
+ { 40, 8 },
+ { 41, 8 },
+ { 42, 8 },
+ { 43, 8 },
+ { 44, 8 },
+ { 21, 7 },
+ { 21, 7 },
+ { 28, 7 },
+ { 28, 7 },
+ { 61, 8 },
+ { 62, 8 },
+ { 63, 8 },
+ { 0, 8 },
+ { 320, 8 },
+ { 384, 8 },
+ { 10, 5 },
+ { 10, 5 },
+ { 10, 5 },
+ { 10, 5 },
+ { 10, 5 },
+ { 10, 5 },
+ { 10, 5 },
+ { 10, 5 },
+ { 11, 5 },
+ { 11, 5 },
+ { 11, 5 },
+ { 11, 5 },
+ { 11, 5 },
+ { 11, 5 },
+ { 11, 5 },
+ { 11, 5 },
+ { 27, 7 },
+ { 27, 7 },
+ { 59, 8 },
+ { 60, 8 },
+ { 288, 9 },
+ { 290, 9 },
+ { 18, 7 },
+ { 18, 7 },
+ { 24, 7 },
+ { 24, 7 },
+ { 49, 8 },
+ { 50, 8 },
+ { 51, 8 },
+ { 52, 8 },
+ { 25, 7 },
+ { 25, 7 },
+ { 55, 8 },
+ { 56, 8 },
+ { 57, 8 },
+ { 58, 8 },
+ { 192, 6 },
+ { 192, 6 },
+ { 192, 6 },
+ { 192, 6 },
+ { 1664, 6 },
+ { 1664, 6 },
+ { 1664, 6 },
+ { 1664, 6 },
+ { 448, 8 },
+ { 512, 8 },
+ { 292, 9 },
+ { 640, 8 },
+ { 576, 8 },
+ { 294, 9 },
+ { 296, 9 },
+ { 298, 9 },
+ { 300, 9 },
+ { 302, 9 },
+ { 256, 7 },
+ { 256, 7 },
+ { 2, 4 },
+ { 2, 4 },
+ { 2, 4 },
+ { 2, 4 },
+ { 2, 4 },
+ { 2, 4 },
+ { 2, 4 },
+ { 2, 4 },
+ { 2, 4 },
+ { 2, 4 },
+ { 2, 4 },
+ { 2, 4 },
+ { 2, 4 },
+ { 2, 4 },
+ { 2, 4 },
+ { 2, 4 },
+ { 3, 4 },
+ { 3, 4 },
+ { 3, 4 },
+ { 3, 4 },
+ { 3, 4 },
+ { 3, 4 },
+ { 3, 4 },
+ { 3, 4 },
+ { 3, 4 },
+ { 3, 4 },
+ { 3, 4 },
+ { 3, 4 },
+ { 3, 4 },
+ { 3, 4 },
+ { 3, 4 },
+ { 3, 4 },
+ { 128, 5 },
+ { 128, 5 },
+ { 128, 5 },
+ { 128, 5 },
+ { 128, 5 },
+ { 128, 5 },
+ { 128, 5 },
+ { 128, 5 },
+ { 8, 5 },
+ { 8, 5 },
+ { 8, 5 },
+ { 8, 5 },
+ { 8, 5 },
+ { 8, 5 },
+ { 8, 5 },
+ { 8, 5 },
+ { 9, 5 },
+ { 9, 5 },
+ { 9, 5 },
+ { 9, 5 },
+ { 9, 5 },
+ { 9, 5 },
+ { 9, 5 },
+ { 9, 5 },
+ { 16, 6 },
+ { 16, 6 },
+ { 16, 6 },
+ { 16, 6 },
+ { 17, 6 },
+ { 17, 6 },
+ { 17, 6 },
+ { 17, 6 },
+ { 4, 4 },
+ { 4, 4 },
+ { 4, 4 },
+ { 4, 4 },
+ { 4, 4 },
+ { 4, 4 },
+ { 4, 4 },
+ { 4, 4 },
+ { 4, 4 },
+ { 4, 4 },
+ { 4, 4 },
+ { 4, 4 },
+ { 4, 4 },
+ { 4, 4 },
+ { 4, 4 },
+ { 4, 4 },
+ { 5, 4 },
+ { 5, 4 },
+ { 5, 4 },
+ { 5, 4 },
+ { 5, 4 },
+ { 5, 4 },
+ { 5, 4 },
+ { 5, 4 },
+ { 5, 4 },
+ { 5, 4 },
+ { 5, 4 },
+ { 5, 4 },
+ { 5, 4 },
+ { 5, 4 },
+ { 5, 4 },
+ { 5, 4 },
+ { 14, 6 },
+ { 14, 6 },
+ { 14, 6 },
+ { 14, 6 },
+ { 15, 6 },
+ { 15, 6 },
+ { 15, 6 },
+ { 15, 6 },
+ { 64, 5 },
+ { 64, 5 },
+ { 64, 5 },
+ { 64, 5 },
+ { 64, 5 },
+ { 64, 5 },
+ { 64, 5 },
+ { 64, 5 },
+ { 6, 4 },
+ { 6, 4 },
+ { 6, 4 },
+ { 6, 4 },
+ { 6, 4 },
+ { 6, 4 },
+ { 6, 4 },
+ { 6, 4 },
+ { 6, 4 },
+ { 6, 4 },
+ { 6, 4 },
+ { 6, 4 },
+ { 6, 4 },
+ { 6, 4 },
+ { 6, 4 },
+ { 6, 4 },
+ { 7, 4 },
+ { 7, 4 },
+ { 7, 4 },
+ { 7, 4 },
+ { 7, 4 },
+ { 7, 4 },
+ { 7, 4 },
+ { 7, 4 },
+ { 7, 4 },
+ { 7, 4 },
+ { 7, 4 },
+ { 7, 4 },
+ { 7, 4 },
+ { 7, 4 },
+ { 7, 4 },
+ { 7, 4 },
+ { -2, 3 },
+ { -2, 3 },
+ { -1, 0 },
+ { -1, 0 },
+ { -1, 0 },
+ { -1, 0 },
+ { -1, 0 },
+ { -1, 0 },
+ { -1, 0 },
+ { -1, 0 },
+ { -1, 0 },
+ { -1, 0 },
+ { -1, 0 },
+ { -1, 0 },
+ { -1, 0 },
+ { -3, 4 },
+ { 1792, 3 },
+ { 1792, 3 },
+ { 1984, 4 },
+ { 2048, 4 },
+ { 2112, 4 },
+ { 2176, 4 },
+ { 2240, 4 },
+ { 2304, 4 },
+ { 1856, 3 },
+ { 1856, 3 },
+ { 1920, 3 },
+ { 1920, 3 },
+ { 2368, 4 },
+ { 2432, 4 },
+ { 2496, 4 },
+ { 2560, 4 },
+ { 1472, 1 },
+ { 1536, 1 },
+ { 1600, 1 },
+ { 1728, 1 },
+ { 704, 1 },
+ { 768, 1 },
+ { 832, 1 },
+ { 896, 1 },
+ { 960, 1 },
+ { 1024, 1 },
+ { 1088, 1 },
+ { 1152, 1 },
+ { 1216, 1 },
+ { 1280, 1 },
+ { 1344, 1 },
+ { 1408, 1 }
+};
+
+/* Black decoding table. */
+impl_const cfd_node cf_black_decode[] = {
+ { 128, 12 },
+ { 160, 13 },
+ { 224, 12 },
+ { 256, 12 },
+ { 10, 7 },
+ { 11, 7 },
+ { 288, 12 },
+ { 12, 7 },
+ { 9, 6 },
+ { 9, 6 },
+ { 8, 6 },
+ { 8, 6 },
+ { 7, 5 },
+ { 7, 5 },
+ { 7, 5 },
+ { 7, 5 },
+ { 6, 4 },
+ { 6, 4 },
+ { 6, 4 },
+ { 6, 4 },
+ { 6, 4 },
+ { 6, 4 },
+ { 6, 4 },
+ { 6, 4 },
+ { 5, 4 },
+ { 5, 4 },
+ { 5, 4 },
+ { 5, 4 },
+ { 5, 4 },
+ { 5, 4 },
+ { 5, 4 },
+ { 5, 4 },
+ { 1, 3 },
+ { 1, 3 },
+ { 1, 3 },
+ { 1, 3 },
+ { 1, 3 },
+ { 1, 3 },
+ { 1, 3 },
+ { 1, 3 },
+ { 1, 3 },
+ { 1, 3 },
+ { 1, 3 },
+ { 1, 3 },
+ { 1, 3 },
+ { 1, 3 },
+ { 1, 3 },
+ { 1, 3 },
+ { 4, 3 },
+ { 4, 3 },
+ { 4, 3 },
+ { 4, 3 },
+ { 4, 3 },
+ { 4, 3 },
+ { 4, 3 },
+ { 4, 3 },
+ { 4, 3 },
+ { 4, 3 },
+ { 4, 3 },
+ { 4, 3 },
+ { 4, 3 },
+ { 4, 3 },
+ { 4, 3 },
+ { 4, 3 },
+ { 3, 2 },
+ { 3, 2 },
+ { 3, 2 },
+ { 3, 2 },
+ { 3, 2 },
+ { 3, 2 },
+ { 3, 2 },
+ { 3, 2 },
+ { 3, 2 },
+ { 3, 2 },
+ { 3, 2 },
+ { 3, 2 },
+ { 3, 2 },
+ { 3, 2 },
+ { 3, 2 },
+ { 3, 2 },
+ { 3, 2 },
+ { 3, 2 },
+ { 3, 2 },
+ { 3, 2 },
+ { 3, 2 },
+ { 3, 2 },
+ { 3, 2 },
+ { 3, 2 },
+ { 3, 2 },
+ { 3, 2 },
+ { 3, 2 },
+ { 3, 2 },
+ { 3, 2 },
+ { 3, 2 },
+ { 3, 2 },
+ { 3, 2 },
+ { 2, 2 },
+ { 2, 2 },
+ { 2, 2 },
+ { 2, 2 },
+ { 2, 2 },
+ { 2, 2 },
+ { 2, 2 },
+ { 2, 2 },
+ { 2, 2 },
+ { 2, 2 },
+ { 2, 2 },
+ { 2, 2 },
+ { 2, 2 },
+ { 2, 2 },
+ { 2, 2 },
+ { 2, 2 },
+ { 2, 2 },
+ { 2, 2 },
+ { 2, 2 },
+ { 2, 2 },
+ { 2, 2 },
+ { 2, 2 },
+ { 2, 2 },
+ { 2, 2 },
+ { 2, 2 },
+ { 2, 2 },
+ { 2, 2 },
+ { 2, 2 },
+ { 2, 2 },
+ { 2, 2 },
+ { 2, 2 },
+ { 2, 2 },
+ { -2, 4 },
+ { -2, 4 },
+ { -1, 0 },
+ { -1, 0 },
+ { -1, 0 },
+ { -1, 0 },
+ { -1, 0 },
+ { -1, 0 },
+ { -1, 0 },
+ { -1, 0 },
+ { -1, 0 },
+ { -1, 0 },
+ { -1, 0 },
+ { -1, 0 },
+ { -1, 0 },
+ { -3, 5 },
+ { 1792, 4 },
+ { 1792, 4 },
+ { 1984, 5 },
+ { 2048, 5 },
+ { 2112, 5 },
+ { 2176, 5 },
+ { 2240, 5 },
+ { 2304, 5 },
+ { 1856, 4 },
+ { 1856, 4 },
+ { 1920, 4 },
+ { 1920, 4 },
+ { 2368, 5 },
+ { 2432, 5 },
+ { 2496, 5 },
+ { 2560, 5 },
+ { 18, 3 },
+ { 18, 3 },
+ { 18, 3 },
+ { 18, 3 },
+ { 18, 3 },
+ { 18, 3 },
+ { 18, 3 },
+ { 18, 3 },
+ { 52, 5 },
+ { 52, 5 },
+ { 640, 6 },
+ { 704, 6 },
+ { 768, 6 },
+ { 832, 6 },
+ { 55, 5 },
+ { 55, 5 },
+ { 56, 5 },
+ { 56, 5 },
+ { 1280, 6 },
+ { 1344, 6 },
+ { 1408, 6 },
+ { 1472, 6 },
+ { 59, 5 },
+ { 59, 5 },
+ { 60, 5 },
+ { 60, 5 },
+ { 1536, 6 },
+ { 1600, 6 },
+ { 24, 4 },
+ { 24, 4 },
+ { 24, 4 },
+ { 24, 4 },
+ { 25, 4 },
+ { 25, 4 },
+ { 25, 4 },
+ { 25, 4 },
+ { 1664, 6 },
+ { 1728, 6 },
+ { 320, 5 },
+ { 320, 5 },
+ { 384, 5 },
+ { 384, 5 },
+ { 448, 5 },
+ { 448, 5 },
+ { 512, 6 },
+ { 576, 6 },
+ { 53, 5 },
+ { 53, 5 },
+ { 54, 5 },
+ { 54, 5 },
+ { 896, 6 },
+ { 960, 6 },
+ { 1024, 6 },
+ { 1088, 6 },
+ { 1152, 6 },
+ { 1216, 6 },
+ { 64, 3 },
+ { 64, 3 },
+ { 64, 3 },
+ { 64, 3 },
+ { 64, 3 },
+ { 64, 3 },
+ { 64, 3 },
+ { 64, 3 },
+ { 13, 1 },
+ { 13, 1 },
+ { 13, 1 },
+ { 13, 1 },
+ { 13, 1 },
+ { 13, 1 },
+ { 13, 1 },
+ { 13, 1 },
+ { 13, 1 },
+ { 13, 1 },
+ { 13, 1 },
+ { 13, 1 },
+ { 13, 1 },
+ { 13, 1 },
+ { 13, 1 },
+ { 13, 1 },
+ { 23, 4 },
+ { 23, 4 },
+ { 50, 5 },
+ { 51, 5 },
+ { 44, 5 },
+ { 45, 5 },
+ { 46, 5 },
+ { 47, 5 },
+ { 57, 5 },
+ { 58, 5 },
+ { 61, 5 },
+ { 256, 5 },
+ { 16, 3 },
+ { 16, 3 },
+ { 16, 3 },
+ { 16, 3 },
+ { 17, 3 },
+ { 17, 3 },
+ { 17, 3 },
+ { 17, 3 },
+ { 48, 5 },
+ { 49, 5 },
+ { 62, 5 },
+ { 63, 5 },
+ { 30, 5 },
+ { 31, 5 },
+ { 32, 5 },
+ { 33, 5 },
+ { 40, 5 },
+ { 41, 5 },
+ { 22, 4 },
+ { 22, 4 },
+ { 14, 1 },
+ { 14, 1 },
+ { 14, 1 },
+ { 14, 1 },
+ { 14, 1 },
+ { 14, 1 },
+ { 14, 1 },
+ { 14, 1 },
+ { 14, 1 },
+ { 14, 1 },
+ { 14, 1 },
+ { 14, 1 },
+ { 14, 1 },
+ { 14, 1 },
+ { 14, 1 },
+ { 14, 1 },
+ { 15, 2 },
+ { 15, 2 },
+ { 15, 2 },
+ { 15, 2 },
+ { 15, 2 },
+ { 15, 2 },
+ { 15, 2 },
+ { 15, 2 },
+ { 128, 5 },
+ { 192, 5 },
+ { 26, 5 },
+ { 27, 5 },
+ { 28, 5 },
+ { 29, 5 },
+ { 19, 4 },
+ { 19, 4 },
+ { 20, 4 },
+ { 20, 4 },
+ { 34, 5 },
+ { 35, 5 },
+ { 36, 5 },
+ { 37, 5 },
+ { 38, 5 },
+ { 39, 5 },
+ { 21, 4 },
+ { 21, 4 },
+ { 42, 5 },
+ { 43, 5 },
+ { 0, 3 },
+ { 0, 3 },
+ { 0, 3 },
+ { 0, 3 }
+};
+
+/* 2-D decoding table. */
+impl_const cfd_node cf_2d_decode[] = {
+ { 128, 11 },
+ { 144, 10 },
+ { 6, 7 },
+ { 0, 7 },
+ { 5, 6 },
+ { 5, 6 },
+ { 1, 6 },
+ { 1, 6 },
+ { -4, 4 },
+ { -4, 4 },
+ { -4, 4 },
+ { -4, 4 },
+ { -4, 4 },
+ { -4, 4 },
+ { -4, 4 },
+ { -4, 4 },
+ { -5, 3 },
+ { -5, 3 },
+ { -5, 3 },
+ { -5, 3 },
+ { -5, 3 },
+ { -5, 3 },
+ { -5, 3 },
+ { -5, 3 },
+ { -5, 3 },
+ { -5, 3 },
+ { -5, 3 },
+ { -5, 3 },
+ { -5, 3 },
+ { -5, 3 },
+ { -5, 3 },
+ { -5, 3 },
+ { 4, 3 },
+ { 4, 3 },
+ { 4, 3 },
+ { 4, 3 },
+ { 4, 3 },
+ { 4, 3 },
+ { 4, 3 },
+ { 4, 3 },
+ { 4, 3 },
+ { 4, 3 },
+ { 4, 3 },
+ { 4, 3 },
+ { 4, 3 },
+ { 4, 3 },
+ { 4, 3 },
+ { 4, 3 },
+ { 2, 3 },
+ { 2, 3 },
+ { 2, 3 },
+ { 2, 3 },
+ { 2, 3 },
+ { 2, 3 },
+ { 2, 3 },
+ { 2, 3 },
+ { 2, 3 },
+ { 2, 3 },
+ { 2, 3 },
+ { 2, 3 },
+ { 2, 3 },
+ { 2, 3 },
+ { 2, 3 },
+ { 2, 3 },
+ { 3, 1 },
+ { 3, 1 },
+ { 3, 1 },
+ { 3, 1 },
+ { 3, 1 },
+ { 3, 1 },
+ { 3, 1 },
+ { 3, 1 },
+ { 3, 1 },
+ { 3, 1 },
+ { 3, 1 },
+ { 3, 1 },
+ { 3, 1 },
+ { 3, 1 },
+ { 3, 1 },
+ { 3, 1 },
+ { 3, 1 },
+ { 3, 1 },
+ { 3, 1 },
+ { 3, 1 },
+ { 3, 1 },
+ { 3, 1 },
+ { 3, 1 },
+ { 3, 1 },
+ { 3, 1 },
+ { 3, 1 },
+ { 3, 1 },
+ { 3, 1 },
+ { 3, 1 },
+ { 3, 1 },
+ { 3, 1 },
+ { 3, 1 },
+ { 3, 1 },
+ { 3, 1 },
+ { 3, 1 },
+ { 3, 1 },
+ { 3, 1 },
+ { 3, 1 },
+ { 3, 1 },
+ { 3, 1 },
+ { 3, 1 },
+ { 3, 1 },
+ { 3, 1 },
+ { 3, 1 },
+ { 3, 1 },
+ { 3, 1 },
+ { 3, 1 },
+ { 3, 1 },
+ { 3, 1 },
+ { 3, 1 },
+ { 3, 1 },
+ { 3, 1 },
+ { 3, 1 },
+ { 3, 1 },
+ { 3, 1 },
+ { 3, 1 },
+ { 3, 1 },
+ { 3, 1 },
+ { 3, 1 },
+ { 3, 1 },
+ { 3, 1 },
+ { 3, 1 },
+ { 3, 1 },
+ { 3, 1 },
+ { -2, 4 },
+ { -1, 0 },
+ { -1, 0 },
+ { -1, 0 },
+ { -1, 0 },
+ { -1, 0 },
+ { -1, 0 },
+ { -1, 0 },
+ { -1, 0 },
+ { -1, 0 },
+ { -1, 0 },
+ { -1, 0 },
+ { -1, 0 },
+ { -1, 0 },
+ { -1, 0 },
+ { -1, 0 },
+ { -1, 0 },
+ { -1, 0 },
+ { -1, 0 },
+ { -1, 0 },
+ { -1, 0 },
+ { -1, 0 },
+ { -1, 0 },
+ { -3, 3 }
+};
+
+/* Uncompresssed decoding table. */
+impl_const cfd_node cf_uncompressed_decode[] = {
+ { 64, 12 },
+ { 5, 6 },
+ { 4, 5 },
+ { 4, 5 },
+ { 3, 4 },
+ { 3, 4 },
+ { 3, 4 },
+ { 3, 4 },
+ { 2, 3 },
+ { 2, 3 },
+ { 2, 3 },
+ { 2, 3 },
+ { 2, 3 },
+ { 2, 3 },
+ { 2, 3 },
+ { 2, 3 },
+ { 1, 2 },
+ { 1, 2 },
+ { 1, 2 },
+ { 1, 2 },
+ { 1, 2 },
+ { 1, 2 },
+ { 1, 2 },
+ { 1, 2 },
+ { 1, 2 },
+ { 1, 2 },
+ { 1, 2 },
+ { 1, 2 },
+ { 1, 2 },
+ { 1, 2 },
+ { 1, 2 },
+ { 1, 2 },
+ { 0, 1 },
+ { 0, 1 },
+ { 0, 1 },
+ { 0, 1 },
+ { 0, 1 },
+ { 0, 1 },
+ { 0, 1 },
+ { 0, 1 },
+ { 0, 1 },
+ { 0, 1 },
+ { 0, 1 },
+ { 0, 1 },
+ { 0, 1 },
+ { 0, 1 },
+ { 0, 1 },
+ { 0, 1 },
+ { 0, 1 },
+ { 0, 1 },
+ { 0, 1 },
+ { 0, 1 },
+ { 0, 1 },
+ { 0, 1 },
+ { 0, 1 },
+ { 0, 1 },
+ { 0, 1 },
+ { 0, 1 },
+ { 0, 1 },
+ { 0, 1 },
+ { 0, 1 },
+ { 0, 1 },
+ { 0, 1 },
+ { 0, 1 },
+ { -1, 0 },
+ { -1, 0 },
+ { 8, 6 },
+ { 9, 6 },
+ { 6, 5 },
+ { 6, 5 },
+ { 7, 5 },
+ { 7, 5 },
+ { 4, 4 },
+ { 4, 4 },
+ { 4, 4 },
+ { 4, 4 },
+ { 5, 4 },
+ { 5, 4 },
+ { 5, 4 },
+ { 5, 4 },
+ { 2, 3 },
+ { 2, 3 },
+ { 2, 3 },
+ { 2, 3 },
+ { 2, 3 },
+ { 2, 3 },
+ { 2, 3 },
+ { 2, 3 },
+ { 3, 3 },
+ { 3, 3 },
+ { 3, 3 },
+ { 3, 3 },
+ { 3, 3 },
+ { 3, 3 },
+ { 3, 3 },
+ { 3, 3 },
+ { 0, 2 },
+ { 0, 2 },
+ { 0, 2 },
+ { 0, 2 },
+ { 0, 2 },
+ { 0, 2 },
+ { 0, 2 },
+ { 0, 2 },
+ { 0, 2 },
+ { 0, 2 },
+ { 0, 2 },
+ { 0, 2 },
+ { 0, 2 },
+ { 0, 2 },
+ { 0, 2 },
+ { 0, 2 },
+ { 1, 2 },
+ { 1, 2 },
+ { 1, 2 },
+ { 1, 2 },
+ { 1, 2 },
+ { 1, 2 },
+ { 1, 2 },
+ { 1, 2 },
+ { 1, 2 },
+ { 1, 2 },
+ { 1, 2 },
+ { 1, 2 },
+ { 1, 2 },
+ { 1, 2 },
+ { 1, 2 },
+ { 1, 2 }
+};
+
+#if 0
+/* Dummy executable code to pacify compilers. */
+void scfdtab_dummy _((void));
+void
+scfdtab_dummy()
+{
+}
+#endif
+/* end of former scfdtab.c */
+/* scfd.c */
+/*$Id: pts_fax.c,v 1.3 2005/02/21 13:09:56 pts Exp $ */
+/* CCITTFax decoding filter */
+/* #include "gstypes.h" */
+/* #include "scf.h" */
+/* #include "scfx.h" */
+
+/* Utility procedures */
+int stream_move _((stream_cursor_read *, stream_cursor_write *)); /* in stream.c */
+
+/* ------ CCITTFaxDecode ------ */
+
+/* private_st_CFD_state(); */
+
+/* Set default parameter values. */
+static void
+s_CFD_set_defaults(register stream_state * st)
+{
+ stream_CFD_state *const ss = (stream_CFD_state *) st;
+
+ s_CFD_set_defaults_inline(ss);
+}
+
+/* Initialize CCITTFaxDecode filter */
+static int
+s_CFD_init(stream_state * st)
+{
+ stream_CFD_state *const ss = (stream_CFD_state *) st;
+ int raster = ss->raster =
+ ROUND_UP((ss->Columns + 7) >> 3, ss->DecodedByteAlign);
+ unsigned char white = (ss->BlackIs1 ? 0 : 0xff);
+
+ s_hcd_init_inline(ss);
+ /* Because skip_white_pixels can look as many as 4 bytes ahead, */
+ /* we need to allow 4 extra bytes at the end of the row buffers. */
+ ss->lbuf = (unsigned char*)gs_alloc_bytes(st->memory, raster + 4, "CFD lbuf");
+ ss->lprev = 0;
+ if (ss->lbuf == 0)
+ return PTSFAX_ERRC;
+/****** WRONG ******/
+ if (ss->K != 0) {
+ ss->lprev = (unsigned char*)gs_alloc_bytes(st->memory, raster + 4, "CFD lprev");
+ if (ss->lprev == 0)
+ return PTSFAX_ERRC;
+/****** WRONG ******/
+ /* Clear the initial reference line for 2-D encoding. */
+ ss->memset_(ss->lbuf, white, raster);
+ /* Ensure that the scan of the reference line will stop. */
+ ss->lbuf[raster] = 0xa0;
+ }
+ ss->k_left = min(ss->K, 0);
+ ss->run_color = 0;
+ ss->damaged_rows = 0;
+ ss->skipping_damage = false;
+ ss->cbit = 0;
+ ss->uncomp_run = 0;
+ ss->rows_left = (ss->Rows <= 0 || ss->EndOfBlock ? -1 : ss->Rows + 1);
+ ss->rpos = ss->wpos = raster - 1;
+ ss->eol_count = 0;
+ ss->invert = white;
+ ss->min_left = 1;
+ return 0;
+}
+
+/* Release the filter. */
+static void
+s_CFD_release(stream_state * st)
+{
+ stream_CFD_state *const ss = (stream_CFD_state *) st;
+
+ gs_free_object(st->memory, ss->lprev, "CFD lprev(close)");
+ gs_free_object(st->memory, ss->lbuf, "CFD lbuf(close)");
+}
+
+/* Declare the variables that hold the state. */
+#define cfd_declare_state\
+ hcd_declare_state;\
+ register unsigned char *q;\
+ int qbit
+/* Load the state from the stream. */
+#define cfd_load_state()\
+ hcd_load_state(),\
+ q = ss->lbuf + ss->wpos, qbit = ss->cbit
+/* Store the state back in the stream. */
+#define cfd_store_state()\
+ hcd_store_state(),\
+ ss->wpos = q - ss->lbuf, ss->cbit = qbit
+
+/* Macros to get blocks of bits from the input stream. */
+/* Invariants: 0 <= bits_left <= bits_size; */
+/* bits [bits_left-1..0] contain valid data. */
+
+#define avail_bits(n) hcd_bits_available(n)
+#define ensure_bits(n, outl) hcd_ensure_bits(n, outl)
+#define peek_bits(n) hcd_peek_bits(n)
+#define peek_var_bits(n) hcd_peek_var_bits(n)
+#define skip_bits(n) hcd_skip_bits(n)
+
+/* Get a run from the stream. */
+#ifdef DEBUG
+# define IF_DEBUG(expr) expr
+#else
+# define IF_DEBUG(expr) DO_NOTHING
+#endif
+#define get_run(decode, initial_bits, min_bits, runlen, str, locl, outl)\
+ BEGIN\
+ const cfd_node *np;\
+ int clen;\
+\
+ HCD_ENSURE_BITS_ELSE(initial_bits) {\
+ /* We might still have enough bits for the specific code. */\
+ if (bits_left < min_bits) goto outl;\
+ np = &decode[hcd_peek_bits_left() << (initial_bits - bits_left)];\
+ if ((clen = np->code_length) > bits_left) goto outl;\
+ goto locl;\
+ }\
+ np = &decode[peek_bits(initial_bits)];\
+ if ((clen = np->code_length) > initial_bits) {\
+ IF_DEBUG(unsigned int init_bits = peek_bits(initial_bits));\
+ if (!avail_bits(clen)) goto outl;\
+ clen -= initial_bits;\
+ skip_bits(initial_bits);\
+ ensure_bits(clen, outl); /* can't goto outl */\
+ np = &decode[np->run_length + peek_var_bits(clen)];\
+ if_debug4('W', "%s xcode=0x%x,%d rlen=%d\n", str,\
+ (init_bits << np->code_length) +\
+ peek_var_bits(np->code_length),\
+ initial_bits + np->code_length,\
+ np->run_length);\
+ skip_bits(np->code_length);\
+ } else {\
+ locl: if_debug4('W', "%s code=0x%x,%d rlen=%d\n", str,\
+ peek_var_bits(clen), clen, np->run_length);\
+ skip_bits(clen);\
+ }\
+ runlen = np->run_length;\
+ END
+
+/* Skip data bits for a white run. */
+/* rlen is either less than 64, or a multiple of 64. */
+#define skip_data(rlen, makeup_label)\
+ if ( (qbit -= rlen) < 0 )\
+ { q -= qbit >> 3, qbit &= 7;\
+ if ( rlen >= 64 ) goto makeup_label;\
+ }
+
+/* Invert data bits for a black run. */
+/* If rlen >= 64, execute makeup_action: this is to handle */
+/* makeup codes efficiently, since these are always a multiple of 64. */
+#define invert_data(rlen, black_byte, makeup_action, d)\
+ if ( rlen > qbit )\
+ { *q++ ^= (1 << qbit) - 1;\
+ rlen -= qbit;\
+ switch ( rlen >> 3 )\
+ {\
+ case 7: /* original rlen possibly >= 64 */\
+ if ( rlen + qbit >= 64 ) goto d;\
+ *q++ = black_byte;\
+ case 6: *q++ = black_byte;\
+ case 5: *q++ = black_byte;\
+ case 4: *q++ = black_byte;\
+ case 3: *q++ = black_byte;\
+ case 2: *q++ = black_byte;\
+ case 1: *q = black_byte;\
+ rlen &= 7;\
+ if ( !rlen ) { qbit = 0; break; }\
+ q++;\
+ case 0: /* know rlen != 0 */\
+ qbit = 8 - rlen;\
+ *q ^= 0xff << qbit;\
+ break;\
+ default: /* original rlen >= 64 */\
+d: ss->memset_(q, black_byte, rlen >> 3);\
+ q += rlen >> 3;\
+ rlen &= 7;\
+ if ( !rlen ) qbit = 0, q--;\
+ else qbit = 8 - rlen, *q ^= 0xff << qbit;\
+ makeup_action;\
+ }\
+ }\
+ else\
+ qbit -= rlen,\
+ *q ^= ((1 << rlen) - 1) << qbit
+
+/* Buffer refill for CCITTFaxDecode filter */
+static int cf_decode_eol _((stream_CFD_state *, stream_cursor_read *));
+static int cf_decode_1d _((stream_CFD_state *, stream_cursor_read *));
+static int cf_decode_2d _((stream_CFD_state *, stream_cursor_read *));
+static int cf_decode_uncompressed _((stream_CFD_state *, stream_cursor_read *));
+static int
+s_CFD_process(stream_state * st, stream_cursor_read * pr,
+ stream_cursor_write * pw, bool last)
+{
+ stream_CFD_state *const ss = (stream_CFD_state *) st;
+ int wstop = ss->raster - 1;
+ int eol_count = ss->eol_count;
+ int k_left = ss->k_left;
+ int rows_left = ss->rows_left;
+ int status = 0;
+
+ (void)last; /**** pts ****/
+
+#ifdef DEBUG
+ const unsigned char *rstart = pr->ptr;
+ const unsigned char *wstart = pw->ptr;
+
+#endif
+
+ top:
+#ifdef DEBUG
+ {
+ hcd_declare_state;
+ hcd_load_state();
+ if_debug8('w', "\
+[w]CFD_process top: eol_count=%d, k_left=%d, rows_left=%d\n\
+ bits=0x%lx, bits_left=%d, read %u, wrote %u%s\n",
+ eol_count, k_left, rows_left,
+ (unsigned long) bits, bits_left,
+ (unsigned int) (p - rstart), (unsigned int) (pw->ptr - wstart),
+ (ss->skipping_damage ? ", skipping damage" : ""));
+ }
+#endif
+ if (ss->skipping_damage) { /* Skip until we reach an EOL. */
+ hcd_declare_state;
+ int skip;
+
+ status = 0;
+ do {
+ switch ((skip = cf_decode_eol(ss, pr))) {
+ default: /* not EOL */
+ hcd_load_state();
+ skip_bits(-skip);
+ hcd_store_state();
+ continue;
+ case 0: /* need more input */
+ goto out;
+ case 1: /* EOL */
+ { /* Back up over the EOL. */
+ hcd_load_state();
+ bits_left += run_eol_code_length;
+ hcd_store_state();
+ }
+ ss->skipping_damage = false;
+ }
+ }
+ while (ss->skipping_damage);
+ ss->damaged_rows++;
+ }
+ /*
+ * Check for a completed input scan line. This isn't quite as
+ * simple as it seems, because we could have run out of input data
+ * between a makeup code and a 0-length termination code, or in a
+ * 2-D line before a final horizontal code with a 0-length second
+ * run. There's probably a way to think about this situation that
+ * doesn't require a special check, but I haven't found it yet.
+ */
+ if (ss->wpos == wstop && ss->cbit <= (-ss->Columns & 7) &&
+ (k_left == 0 ? !(ss->run_color & ~1) : ss->run_color == 0)
+ ) { /* Check for completed data to be copied to the client. */
+ /* (We could avoid the extra copy step for 1-D, but */
+ /* it's simpler not to, and it doesn't cost much.) */
+ if (ss->rpos < ss->wpos) {
+ stream_cursor_read cr;
+
+ cr.ptr = ss->lbuf + ss->rpos;
+ cr.limit = ss->lbuf + ss->wpos;
+ status = stream_move(&cr, pw);
+ ss->rpos = cr.ptr - ss->lbuf;
+ if (status)
+ goto out;
+ }
+ if (rows_left > 0 && --rows_left == 0) {
+ status = EOFC;
+ goto out;
+ }
+ if (ss->K != 0) {
+ unsigned char *prev_bits = ss->lprev;
+
+ ss->lprev = ss->lbuf;
+ ss->lbuf = prev_bits;
+ if (ss->K > 0)
+ k_left = (k_left == 0 ? ss->K : k_left) - 1;
+ }
+ ss->rpos = ss->wpos = -1;
+ ss->eol_count = eol_count = 0;
+ ss->cbit = 0;
+ ss->invert = (ss->BlackIs1 ? 0 : 0xff);
+ ss->memset_(ss->lbuf, ss->invert, wstop + 1);
+ ss->run_color = 0;
+ /*
+ * If EndOfLine is true, we want to include the unsigned char padding
+ * in the string of initial zeros in the EOL. If EndOfLine
+ * is false, we aren't sure what we should do....
+ */
+ if (ss->EncodedByteAlign & !ss->EndOfLine)
+ ss->bits_left &= ~7;
+ }
+ /* If we're between scan lines, scan for EOLs. */
+ if (ss->wpos < 0) {
+ while ((status = cf_decode_eol(ss, pr)) > 0) {
+ if_debug0('w', "[w]EOL\n");
+ /* If we are in a Group 3 mixed regime, */
+ /* check the next bit for 1- vs. 2-D. */
+ if (ss->K > 0) {
+ hcd_declare_state;
+ hcd_load_state();
+ ensure_bits(1, out); /* can't fail */
+ k_left = (peek_bits(1) ? 0 : 1);
+ skip_bits(1);
+ hcd_store_state();
+ }
+ ++eol_count;
+ /*
+ * According to Adobe, the decoder should always check for
+ * the EOD sequence, regardless of EndOfBlock: the Red Book's
+ * documentation of EndOfBlock is wrong.
+ */
+ if (eol_count == (ss->K < 0 ? 2 : 6)) {
+ status = EOFC;
+ goto out;
+ }
+ }
+ if (status == 0) /* input empty while scanning EOLs */
+ goto out;
+ switch (eol_count) {
+ case 0:
+ if (ss->EndOfLine) { /* EOL is required, but none is present. */
+ status = PTSFAX_ERRC;
+ goto check;
+ }
+ case 1:
+ break;
+ default:
+ status = PTSFAX_ERRC;
+ goto check;
+ }
+ }
+ /* Now decode actual data. */
+ if (k_left < 0) {
+ if_debug0('w', "[w2]new row\n");
+ status = cf_decode_2d(ss, pr);
+ } else if (k_left == 0) {
+ if_debug0('w', "[w1]new row\n");
+ status = cf_decode_1d(ss, pr);
+ } else {
+ if_debug1('w', "[w1]new 2-D row, %d left\n", k_left);
+ status = cf_decode_2d(ss, pr);
+ }
+ if_debug3('w', "[w]CFD status = %d, wpos = %d, cbit = %d\n",
+ status, ss->wpos, ss->cbit);
+ check:switch (status) {
+ case 1: /* output full */
+ goto top;
+ case PTSFAX_ERRC:
+ /* Check for special handling of damaged rows. */
+ if (ss->damaged_rows >= ss->DamagedRowsBeforeError ||
+ !(ss->EndOfLine && ss->K >= 0)
+ )
+ break;
+ /* Substitute undamaged data if appropriate. */
+/****** NOT IMPLEMENTED YET ******/
+ {
+ ss->wpos = wstop;
+ ss->cbit = -ss->Columns & 7;
+ ss->run_color = 0;
+ }
+ ss->skipping_damage = true;
+ goto top;
+ default:
+ ss->damaged_rows = 0; /* finished a good row */
+ }
+ out:ss->k_left = k_left;
+ ss->rows_left = rows_left;
+ ss->eol_count = eol_count;
+ return status;
+}
+
+/*
+ * Decode a leading EOL, if any.
+ * If an EOL is present, skip over it and return 1;
+ * if no EOL is present, read no input and return -N, where N is the
+ * number of initial bits that can be skipped in the search for an EOL;
+ * if more input is needed, return 0.
+ * Note that if we detected an EOL, we know that we can back up over it;
+ * if we detected an N-bit non-EOL, we know that at least N bits of data
+ * are available in the buffer.
+ */
+static int
+cf_decode_eol(stream_CFD_state * ss, stream_cursor_read * pr)
+{
+ hcd_declare_state;
+ int zeros;
+ int look_ahead;
+
+ hcd_load_state();
+ for (zeros = 0; zeros < run_eol_code_length - 1; zeros++) {
+ ensure_bits(1, out);
+ if (peek_bits(1))
+ return -(zeros + 1);
+ skip_bits(1);
+ }
+ /* We definitely have an EOL. Skip further zero bits. */
+ look_ahead = (ss->K > 0 ? 2 : 1);
+ for (;;) {
+ ensure_bits(look_ahead, back);
+ if (peek_bits(1))
+ break;
+ skip_bits(1);
+ }
+ skip_bits(1);
+ hcd_store_state();
+ return 1;
+ back: /*
+ * We ran out of data while skipping zeros.
+ * We know we are at a unsigned char boundary, and have just skipped
+ * at least run_eol_code_length - 1 zeros. However,
+ * bits_left may be 1 if look_ahead == 2.
+ */
+ bits &= (1 << bits_left) - 1;
+ bits_left += run_eol_code_length - 1;
+ hcd_store_state();
+ out:return 0;
+}
+
+/* Decode a 1-D scan line. */
+static int
+cf_decode_1d(stream_CFD_state * ss, stream_cursor_read * pr)
+{
+ cfd_declare_state;
+ unsigned char black_byte = (ss->BlackIs1 ? 0xff : 0);
+ int end_bit = -ss->Columns & 7;
+ unsigned char *stop = ss->lbuf - 1 + ss->raster;
+ int run_color = ss->run_color;
+ int status;
+ int bcnt;
+
+ cfd_load_state();
+ if_debug1('w', "[w1]entry run_color = %d\n", ss->run_color);
+ if (ss->run_color > 0)
+ goto db;
+ else
+ goto dw;
+#define q_at_stop() (q >= stop && (qbit <= end_bit || q > stop))
+ top:run_color = 0;
+ if (q_at_stop())
+ goto done;
+ dw: /* Decode a white run. */
+ get_run(cf_white_decode, cfd_white_initial_bits, cfd_white_min_bits,
+ bcnt, "[w1]white", dwl, out0);
+ if (bcnt < 0) { /* exceptional situation */
+ switch (bcnt) {
+ case run_uncompressed: /* Uncompressed data. */
+ cfd_store_state();
+ bcnt = cf_decode_uncompressed(ss, pr);
+ if (bcnt < 0)
+ return bcnt;
+ cfd_load_state();
+ if (bcnt)
+ goto db;
+ else
+ goto dw;
+ /*case run_error: */
+ /*case run_zeros: *//* Premature end-of-line. */
+ default:
+ status = PTSFAX_ERRC;
+ goto out;
+ }
+ }
+ skip_data(bcnt, dwx);
+ if (q_at_stop()) {
+ run_color = 0; /* not inside a run */
+ goto done;
+ }
+ run_color = 1;
+ db: /* Decode a black run. */
+ get_run(cf_black_decode, cfd_black_initial_bits, cfd_black_min_bits,
+ bcnt, "[w1]black", dbl, out1);
+ if (bcnt < 0) { /* All exceptional codes are invalid here. */
+/****** WRONG, uncompressed IS ALLOWED ******/
+ status = PTSFAX_ERRC;
+ goto out;
+ }
+ /* Invert bits designated by black run. */
+ invert_data(bcnt, black_byte, goto dbx, idb);
+ goto top;
+ dwx: /* If we run out of data after a makeup code, */
+ /* note that we are still processing a white run. */
+ run_color = -1;
+ goto dw;
+ dbx: /* If we run out of data after a makeup code, */
+ /* note that we are still processing a black run. */
+ run_color = 2;
+ goto db;
+ done:if (q > stop || qbit < end_bit)
+ status = PTSFAX_ERRC;
+ else
+ status = 1;
+ out:cfd_store_state();
+ ss->run_color = run_color;
+ if_debug1('w', "[w1]exit run_color = %d\n", run_color);
+ return status;
+ out0: /* We already set run_color to 0 or -1. */
+ status = 0;
+ goto out;
+ out1: /* We already set run_color to 1 or 2. */
+ status = 0;
+ goto out;
+}
+
+/* Decode a 2-D scan line. */
+static int
+cf_decode_2d(stream_CFD_state * ss, stream_cursor_read * pr)
+{
+ cfd_declare_state;
+ unsigned char invert_white = (ss->BlackIs1 ? 0 : 0xff);
+ unsigned char black_byte = ~invert_white;
+ unsigned char invert = ss->invert;
+ int end_count = -ss->Columns & 7;
+ unsigned int raster = ss->raster;
+ unsigned char *q0 = ss->lbuf;
+ unsigned char *prev_q01 = ss->lprev + 1;
+ unsigned char *endptr = q0 - 1 + raster;
+ int init_count = raster << 3;
+ register int count;
+ int rlen;
+ int status;
+
+ cfd_load_state();
+ count = ((endptr - q) << 3) + qbit;
+ endptr[1] = 0xa0; /* a unsigned char with some 0s and some 1s, */
+ /* to ensure run scan will stop */
+ if_debug1('W', "[w2]raster=%d\n", raster);
+ switch (ss->run_color) {
+ case -2:
+ ss->run_color = 0;
+ goto hww;
+ case -1:
+ ss->run_color = 0;
+ goto hbw;
+ case 1:
+ ss->run_color = 0;
+ goto hwb;
+ case 2:
+ ss->run_color = 0;
+ goto hbb;
+ /*case 0: */
+ }
+ top:if (count <= end_count) {
+ status = (count < end_count ? PTSFAX_ERRC : 1);
+ goto out;
+ }
+ /* If invert == invert_white, white and black have their */
+ /* correct meanings; if invert == ~invert_white, */
+ /* black and white are interchanged. */
+ if_debug1('W', "[w2]%4d:\n", count);
+#ifdef DEBUG
+ /* Check the invariant between q, qbit, and count. */
+ {
+ int pcount = (endptr - q) * 8 + qbit;
+
+ if (pcount != count)
+ dlprintf2("[w2]Error: count=%d pcount=%d\n",
+ count, pcount);
+ }
+#endif
+ /*
+ * We could just use get_run here, but we can do better. However,
+ * we must be careful to handle the case where the very last codes
+ * in the input stream are 1-bit "vertical 0" codes: we can't just
+ * use ensure_bits(3, ...) and go to get more data if it fails.
+ */
+ ensure_bits(3, out3);
+#define vertical_0 (countof(cf2_run_vertical) / 2)
+ switch (peek_bits(3)) {
+ default /*4..7*/ : /* vertical(0) */
+v0: skip_bits(1);
+ rlen = vertical_0;
+ break;
+ case 2: /* vertical(+1) */
+ skip_bits(3);
+ rlen = vertical_0 + 1;
+ break;
+ case 3: /* vertical(-1) */
+ skip_bits(3);
+ rlen = vertical_0 - 1;
+ break;
+ case 1: /* horizontal */
+ skip_bits(3);
+ if (invert == invert_white)
+ goto hww;
+ else
+ goto hbb;
+ case 0: /* everything else */
+ get_run(cf_2d_decode, cfd_2d_initial_bits, cfd_2d_min_bits,
+ rlen, "[w2]", d2l, out0);
+ /* rlen may be run2_pass, run_uncompressed, or */
+ /* 0..countof(cf2_run_vertical)-1. */
+ if (rlen < 0)
+ switch (rlen) {
+ case run2_pass:
+ break;
+ case run_uncompressed:
+ {
+ int which;
+
+ cfd_store_state();
+ which = cf_decode_uncompressed(ss, pr);
+ if (which < 0) {
+ status = which;
+ goto out;
+ }
+ cfd_load_state();
+/****** ADJUST count ******/
+ invert = (which ? ~invert_white : invert_white);
+ }
+ goto top;
+ default: /* run_error, run_zeros */
+ status = PTSFAX_ERRC;
+ goto out;
+ }
+ }
+ /* Interpreting the run requires scanning the */
+ /* previous ('reference') line. */
+ {
+ int prev_count = count;
+ unsigned char prev_data;
+ int dlen;
+ static const unsigned char count_bit[8] =
+ {0x80, 1, 2, 4, 8, 0x10, 0x20, 0x40};
+ unsigned char *prev_q = prev_q01 + (q - q0);
+ int plen;
+
+ if (!(count & 7))
+ prev_q++; /* because of skip macros */
+ prev_data = prev_q[-1] ^ invert;
+ /* Find the b1 transition. */
+ if ((prev_data & count_bit[prev_count & 7]) &&
+ (prev_count < init_count || invert != invert_white)
+ ) { /* Look for changing white first. */
+ if_debug1('W', " data=0x%x", prev_data);
+ skip_black_pixels(prev_data, prev_q,
+ prev_count, invert, plen);
+ if (prev_count < end_count) /* overshot */
+ prev_count = end_count;
+ if_debug1('W', " b1 other=%d", prev_count);
+ }
+ if (prev_count != end_count) {
+ if_debug1('W', " data=0x%x", prev_data);
+ skip_white_pixels(prev_data, prev_q,
+ prev_count, invert, plen);
+ if (prev_count < end_count) /* overshot */
+ prev_count = end_count;
+ if_debug1('W', " b1 same=%d", prev_count);
+ }
+ /* b1 = prev_count; */
+ if (rlen == run2_pass) { /* Pass mode. Find b2. */
+ if (prev_count != end_count) {
+ if_debug1('W', " data=0x%x", prev_data);
+ skip_black_pixels(prev_data, prev_q,
+ prev_count, invert, plen);
+ if (prev_count < end_count) /* overshot */
+ prev_count = end_count;
+ }
+ /* b2 = prev_count; */
+ if_debug2('W', " b2=%d, pass %d\n",
+ prev_count, count - prev_count);
+ } else { /* Vertical coding. */
+ /* Remember that count counts *down*. */
+ prev_count += rlen - vertical_0; /* a1 */
+ if_debug2('W', " vertical %d -> %d\n",
+ rlen - vertical_0, prev_count);
+ }
+ /* Now either invert or skip from count */
+ /* to prev_count, and reset count. */
+ if (invert == invert_white) { /* Skip data bits. */
+ q = endptr - (prev_count >> 3);
+ qbit = prev_count & 7;
+ } else { /* Invert data bits. */
+ dlen = count - prev_count;
+ invert_data(dlen, black_byte, DO_NOTHING, idd);
+ }
+ count = prev_count;
+ if (rlen >= 0) /* vertical mode */
+ invert = ~invert; /* polarity changes */
+ }
+ goto top;
+ out3:
+ if (bits_left > 0 && peek_bits(1)) {
+ /* This is a 1-bit "vertical 0" code, which we can still process. */
+ goto v0;
+ }
+ /* falls through */
+ out0:status = 0;
+ /* falls through */
+ out:cfd_store_state();
+ ss->invert = invert;
+ return status;
+ /*
+ * We handle horizontal decoding here, so that we can
+ * branch back into it if we run out of input data.
+ */
+ /* White, then black. */
+ hww:get_run(cf_white_decode, cfd_white_initial_bits, cfd_white_min_bits,
+ rlen, " white", wwl, outww);
+ if ((count -= rlen) < end_count) {
+ status = PTSFAX_ERRC;
+ goto out;
+ }
+ skip_data(rlen, hww);
+ /* Handle the second half of a white-black horizontal code. */
+ hwb:get_run(cf_black_decode, cfd_black_initial_bits, cfd_black_min_bits,
+ rlen, " black", wbl, outwb);
+ if ((count -= rlen) < end_count) {
+ status = PTSFAX_ERRC;
+ goto out;
+ }
+ invert_data(rlen, black_byte, goto hwb, ihwb);
+ goto top;
+ outww:ss->run_color = -2;
+ goto out0;
+ outwb:ss->run_color = 1;
+ goto out0;
+ /* Black, then white. */
+ hbb:get_run(cf_black_decode, cfd_black_initial_bits, cfd_black_min_bits,
+ rlen, " black", bbl, outbb);
+ if ((count -= rlen) < end_count) {
+ status = PTSFAX_ERRC;
+ goto out;
+ }
+ invert_data(rlen, black_byte, goto hbb, ihbb);
+ /* Handle the second half of a black-white horizontal code. */
+ hbw:get_run(cf_white_decode, cfd_white_initial_bits, cfd_white_min_bits,
+ rlen, " white", bwl, outbw);
+ if ((count -= rlen) < end_count) {
+ status = PTSFAX_ERRC;
+ goto out;
+ }
+ skip_data(rlen, hbw);
+ goto top;
+ outbb:ss->run_color = 2;
+ goto out0;
+ outbw:ss->run_color = -1;
+ goto out0;
+}
+
+#if 1 /*************** */
+static int
+cf_decode_uncompressed(stream_CFD_state * ss, stream_cursor_read * pr)
+{
+ (void)ss;
+ (void)pr;
+ /**** pts ****/
+ return PTSFAX_ERRC;
+}
+#else /*************** */
+
+/* Decode uncompressed data. */
+/* (Not tested: no sample data available!) */
+/****** DOESN'T CHECK FOR OVERFLOWING SCAN LINE ******/
+static int
+cf_decode_uncompressed(stream * s)
+{
+ cfd_declare_state;
+ const cfd_node *np;
+ int clen, rlen;
+
+ cfd_load_state();
+ while (1) {
+ ensure_bits(cfd_uncompressed_initial_bits, NOOUT);
+ np = &cf_uncompressed_decode[peek_bits(cfd_uncompressed_initial_bits)];
+ clen = np->code_length;
+ rlen = np->run_length;
+ if (clen > cfd_uncompressed_initial_bits) { /* Must be an exit code. */
+ break;
+ }
+ if (rlen == cfd_uncompressed_initial_bits) { /* Longest representable white run */
+ if_debug1('W', "[wu]%d\n", rlen);
+ if ((qbit -= cfd_uncompressed_initial_bits) < 0)
+ qbit += 8, q++;
+ } else {
+ if_debug1('W', "[wu]%d+1\n", rlen);
+ if (qbit -= rlen < 0)
+ qbit += 8, q++;
+ *q ^= 1 << qbit;
+ }
+ skip_bits(clen);
+ }
+ clen -= cfd_uncompressed_initial_bits;
+ skip_bits(cfd_uncompressed_initial_bits);
+ ensure_bits(clen, NOOUT);
+ np = &cf_uncompressed_decode[rlen + peek_var_bits(clen)];
+ rlen = np->run_length;
+ skip_bits(np->code_length);
+ if_debug1('w', "[wu]exit %d\n", rlen);
+ if (rlen >= 0) { /* Valid exit code, rlen = 2 * run length + next polarity */
+ if ((qbit -= rlen >> 1) < 0)
+ qbit += 8, q++;
+ rlen &= 1;
+ }
+ out:
+/******* WRONG ******/
+ cfd_store_state();
+ return rlen;
+}
+
+#endif /*************** */
+
+/* Move as much data as possible from one buffer to another. */
+/* Return 0 if the input became empty, 1 if the output became full. */
+int
+stream_move(stream_cursor_read * pr, stream_cursor_write * pw)
+{
+ unsigned int rcount = pr->limit - pr->ptr;
+ unsigned int wcount = pw->limit - pw->ptr;
+ unsigned int count;
+ int status;
+
+ if (rcount <= wcount)
+ count = rcount, status = 0;
+ else
+ count = wcount, status = 1;
+
+ /**** pts ****/ /* Dat: memcpy should be enough instead of memmove */
+ #if 0
+ memmove(pw->ptr + 1, pr->ptr + 1, count);
+ pr->ptr += count;
+ pw->ptr += count;
+ #else
+ while (count--!=0) *++pw->ptr=*++pr->ptr;
+ #endif
+ return status;
+}
+
+#if 1 /**** pts ****/
+/* Stream template */
+const stream_template s_CFD_template =
+{/*0, &st_CFD_state*/ s_CFD_init, s_CFD_process, 1, 1, s_CFD_release,
+ s_CFD_set_defaults, 0
+};
+#endif
+
+/* end of former scfd.c */
+
+
+#endif /* USE_BUILTIN_FAXD */
+
+#if USE_BUILTIN_FAXE || USE_BUILTIN_FAXD
+/* shc.c */
+/*$Id: pts_fax.c,v 1.3 2005/02/21 13:09:56 pts Exp $ */
+/* Support code for shc.h */
+/* #include "scommon.h" */
+/* #include "shc.h" */
+/* #include "scfx.h" */ /**** pts ****/ /* struct stream_hc_state_s */
+
+/* ------ Encoding ------ */
+
+/* Empty the 1-word buffer onto the output stream. */
+/* q has already been incremented. */
+static void
+hc_put_code_proc(bool reverse_bits, unsigned char * q, unsigned int cw)
+{
+#define cb(n) ((unsigned char)(cw >> (n * 8)))
+ if (reverse_bits) {
+#if hc_bits_size > 16
+ q[-3] = byte_reverse_bits[cb(3)];
+ q[-2] = byte_reverse_bits[cb(2)];
+#endif
+ q[-1] = byte_reverse_bits[cb(1)];
+ q[0] = byte_reverse_bits[cb(0)];
+ } else {
+#if hc_bits_size > 16
+ q[-3] = cb(3);
+ q[-2] = cb(2);
+#endif
+ q[-1] = cb(1);
+ q[0] = cb(0);
+ }
+#undef cb
+}
+
+/* Put out any final bytes. */
+/* Note that this does a store_state, but not a load_state. */
+static unsigned char *
+hc_put_last_bits_proc(stream_hc_state * ss, unsigned char * q, unsigned int bits, int bits_left)
+{
+ while (bits_left < hc_bits_size) {
+ unsigned char c = (unsigned char) (bits >> (hc_bits_size - 8));
+
+ if (ss->FirstBitLowOrder)
+ c = byte_reverse_bits[c];
+ *++q = c;
+ bits <<= 8;
+ bits_left += 8;
+ }
+ ss->bits = bits;
+ ss->bits_left = bits_left;
+ return q;
+}
+
+/* end of former shc.c */
+
+
+/* gsbittab.c */
+/*$Id: pts_fax.c,v 1.3 2005/02/21 13:09:56 pts Exp $ */
+/* Tables for bit operations */
+/* #include "gstypes.h" */
+/* #include "gsbittab.h" */
+
+/* ---------------- Byte processing tables ---------------- */
+
+/*
+ * byte_reverse_bits[B] = the unsigned char B with the order of bits reversed.
+ */
+impl_const unsigned char byte_reverse_bits[256] = {
+ bit_table_8(0, 1, 2, 4, 8, 0x10, 0x20, 0x40, 0x80)
+};
+
+/*
+ * byte_right_mask[N] = a unsigned char with N trailing 1s, 0 <= N <= 8.
+ */
+impl_const unsigned char byte_right_mask[9] = {
+ 0, 1, 3, 7, 0xf, 0x1f, 0x3f, 0x7f, 0xff
+};
+
+/*
+ * byte_count_bits[B] = the number of 1-bits in a unsigned char with value B.
+ */
+impl_const unsigned char byte_count_bits[256] = {
+ bit_table_8(0, 1, 1, 1, 1, 1, 1, 1, 1)
+};
+
+/* ---------------- Scanning tables ---------------- */
+
+/*
+ * byte_bit_run_length_N[B], for 0 <= N <= 7, gives the length of the
+ * run of 1-bits starting at bit N in a unsigned char with value B,
+ * numbering the bits in the unsigned char as 01234567. If the run includes
+ * the low-order bit (i.e., might be continued into a following unsigned char),
+ * the run length is increased by 8.
+ */
+
+#define t8(n) n,n,n,n,n+1,n+1,n+2,n+11
+#define r8(n) n,n,n,n,n,n,n,n
+#define r16(n) r8(n),r8(n)
+#define r32(n) r16(n),r16(n)
+#define r64(n) r32(n),r32(n)
+#define r128(n) r64(n),r64(n)
+impl_const unsigned char byte_bit_run_length_0[256] = {
+ r128(0), r64(1), r32(2), r16(3), r8(4), t8(5)
+};
+impl_const unsigned char byte_bit_run_length_1[256] = {
+ r64(0), r32(1), r16(2), r8(3), t8(4),
+ r64(0), r32(1), r16(2), r8(3), t8(4)
+};
+impl_const unsigned char byte_bit_run_length_2[256] = {
+ r32(0), r16(1), r8(2), t8(3),
+ r32(0), r16(1), r8(2), t8(3),
+ r32(0), r16(1), r8(2), t8(3),
+ r32(0), r16(1), r8(2), t8(3)
+};
+impl_const unsigned char byte_bit_run_length_3[256] = {
+ r16(0), r8(1), t8(2), r16(0), r8(1), t8(2),
+ r16(0), r8(1), t8(2), r16(0), r8(1), t8(2),
+ r16(0), r8(1), t8(2), r16(0), r8(1), t8(2),
+ r16(0), r8(1), t8(2), r16(0), r8(1), t8(2)
+};
+impl_const unsigned char byte_bit_run_length_4[256] = {
+ r8(0), t8(1), r8(0), t8(1), r8(0), t8(1), r8(0), t8(1),
+ r8(0), t8(1), r8(0), t8(1), r8(0), t8(1), r8(0), t8(1),
+ r8(0), t8(1), r8(0), t8(1), r8(0), t8(1), r8(0), t8(1),
+ r8(0), t8(1), r8(0), t8(1), r8(0), t8(1), r8(0), t8(1),
+};
+
+#define rr8(a,b,c,d,e,f,g,h)\
+ a,b,c,d,e,f,g,h, a,b,c,d,e,f,g,h, a,b,c,d,e,f,g,h, a,b,c,d,e,f,g,h,\
+ a,b,c,d,e,f,g,h, a,b,c,d,e,f,g,h, a,b,c,d,e,f,g,h, a,b,c,d,e,f,g,h,\
+ a,b,c,d,e,f,g,h, a,b,c,d,e,f,g,h, a,b,c,d,e,f,g,h, a,b,c,d,e,f,g,h,\
+ a,b,c,d,e,f,g,h, a,b,c,d,e,f,g,h, a,b,c,d,e,f,g,h, a,b,c,d,e,f,g,h,\
+ a,b,c,d,e,f,g,h, a,b,c,d,e,f,g,h, a,b,c,d,e,f,g,h, a,b,c,d,e,f,g,h,\
+ a,b,c,d,e,f,g,h, a,b,c,d,e,f,g,h, a,b,c,d,e,f,g,h, a,b,c,d,e,f,g,h,\
+ a,b,c,d,e,f,g,h, a,b,c,d,e,f,g,h, a,b,c,d,e,f,g,h, a,b,c,d,e,f,g,h,\
+ a,b,c,d,e,f,g,h, a,b,c,d,e,f,g,h, a,b,c,d,e,f,g,h, a,b,c,d,e,f,g,h
+impl_const unsigned char byte_bit_run_length_5[256] = {
+ rr8(0, 0, 0, 0, 1, 1, 2, 11)
+};
+impl_const unsigned char byte_bit_run_length_6[256] = {
+ rr8(0, 0, 1, 10, 0, 0, 1, 10)
+};
+impl_const unsigned char byte_bit_run_length_7[256] = {
+ rr8(0, 9, 0, 9, 0, 9, 0, 9)
+};
+
+/* Pointer tables indexed by bit number. */
+
+impl_const unsigned char *const byte_bit_run_length[8] = {
+ byte_bit_run_length_0, byte_bit_run_length_1,
+ byte_bit_run_length_2, byte_bit_run_length_3,
+ byte_bit_run_length_4, byte_bit_run_length_5,
+ byte_bit_run_length_6, byte_bit_run_length_7
+};
+impl_const unsigned char *const byte_bit_run_length_neg[8] = {
+ byte_bit_run_length_0, byte_bit_run_length_7,
+ byte_bit_run_length_6, byte_bit_run_length_5,
+ byte_bit_run_length_4, byte_bit_run_length_3,
+ byte_bit_run_length_2, byte_bit_run_length_1
+};
+
+/*
+ * byte_acegbdfh_to_abcdefgh[acegbdfh] = abcdefgh, where the letters
+ * denote the individual bits of the unsigned char.
+ */
+impl_const unsigned char byte_acegbdfh_to_abcdefgh[256] = {
+ bit_table_8(0, 0x80, 0x20, 0x08, 0x02, 0x40, 0x10, 0x04, 0x01)
+};
+
+#if 0
+/* Some C compilers insist on having executable code in every file.... */
+void gsbittab_dummy _((void)); /* for picky compilers */
+void
+gsbittab_dummy(void)
+{
+}
+#endif
+
+/* end of former gsbittab.c */
+#endif /* USE_BUILTIN_FAXE || USE_BUILTIN_FAXD */
+
+/* end of pts_fax.c */
diff --git a/graphics/sam2p/pts_fax.h b/graphics/sam2p/pts_fax.h
new file mode 100644
index 0000000000..dd4ee052b1
--- /dev/null
+++ b/graphics/sam2p/pts_fax.h
@@ -0,0 +1,515 @@
+/*
+ * pts_fax.h -- a compact CCITTFax compressor and uncompressor) interface
+ * compiled by pts@fazekas.hu at Sun Jul 7 19:51:42 CEST 2002
+ *
+ * For usage example, see fax_test.c.
+ *
+ * algorithm ripped from GNU Ghostscript, implementation and (C):
+ *
+Copyright (C) 1993, 1995, 1996, 1997, 1998, 1999 Aladdin Enterprises. All
+rights reserved.
+
+GNU Ghostscript is free software; you can redistribute it and/or
+modify it under the terms of version 2 of the GNU General Public
+License as published by the Free Software Foundation.
+
+GNU Ghostscript is distributed in the hope that it will be
+useful, but WITHOUT ANY WARRANTY; without even the implied warranty
+of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program so you can know your rights and responsibilities.
+It should be in a file named doc/COPYING. If not, write to the
+Free Software Foundation, Inc., 59 Temple Place Suite 330, Boston, MA
+02111-1307, USA.
+ */
+
+/*$Id: pts_fax.h,v 1.4 2005/07/20 21:15:08 pts Exp $ */
+/* CCITTFax filter state definition */
+/* Requires strimpl.h */
+
+#ifndef PTS_FAX_H
+# define PTS_FAX_H 1
+
+#ifdef __GNUC__
+#ifndef __clang__
+#pragma interface
+#endif
+#endif
+
+/* #include "scommon.h" */
+/*$Id: pts_fax.h,v 1.4 2005/07/20 21:15:08 pts Exp $ */
+/* Definitions common to stream clients and implementors */
+
+/* #ifndef scommon_DEFINED */
+/* # define scommon_DEFINED */
+
+/**** pts ****/
+#if 0
+#include "gsmemory.h"
+#include "gsstype.h" /* for extern_st */
+#endif
+
+/**** pts ****/
+#include "config2.h"
+/* ^^^ should #define SIZEOF_INT
+ * ^^^ should #define _, and ___
+ * ^^^ should #define? USE_BULITIN_FAXD
+ * ^^^ should #define? USE_BULITIN_FAXE
+ * ^^^ should define const
+ */
+#if 0 /* example for Linux i386 gcc 2.95: */
+ #define SIZEOF_INT 4
+ #if ((defined(__STDC__) || defined(__PROTOTYPES__)) && !defined(NO_PROTO)) || defined(__cplusplus)
+ # define _(args) args
+ # define OF(args) args
+ # define ___(arg2s,arg1s,argafter) arg2s /* Dat: no direct comma allowed in args :-( */
+ #else
+ # define _(args) ()
+ # define OF(args) ()
+ # define ___(arg2s,arg1s,argafter) arg1s argafter /* Dat: no direct comma allowed in args :-( */
+ #endif
+ #define USE_BUILTIN_FAXE 1
+ #define USE_BUILITN_FAXD 1
+#endif
+
+typedef void (*gssss_memset_t)(void *s, int c, unsigned n); /* Imp: not `unsigned' len */
+/** The function must not return out of memory. */
+typedef void* (*gssss_xalloc_t)(unsigned len); /* Imp: not `unsigned' len */
+typedef void (*gssss_free_t)(void *ptr);
+typedef void (*gssss_memcpy_t)(void *dest, const void *src, unsigned len); /* Imp: not `unsigned' len */
+
+/*
+ * There are three major structures involved in the stream package.
+ *
+ * A stream is an "object" that owns a buffer, which it uses to implement
+ * unsigned char-oriented sequential access in a standard way, and a set of
+ * procedures that handle things like buffer refilling. See stream.h
+ * for more information about streams.
+ */
+#ifndef stream_DEFINED
+# define stream_DEFINED
+typedef struct stream_s stream;
+
+#endif
+/*
+ * A stream_state records the state specific to a given variety of stream.
+ * The buffer processing function of a stream maintains this state.
+ */
+typedef struct stream_state_s stream_state;
+
+/*
+ * A stream_template provides the information needed to create a stream.
+ * The client must fill in any needed setup parameters in the appropriate
+ * variety of stream_state, and then call the initialization function
+ * provided by the template. See strimpl.h for more information about
+ * stream_templates.
+ */
+typedef struct stream_template_s stream_template;
+
+/*
+ * The stream package works with bytes, not chars.
+ * This is to ensure unsigned representation on all systems.
+ * A stream currently can only be read or written, not both.
+ * Note also that the read procedure returns an int, not a char or a unsigned char;
+ * we use negative values to indicate exceptional conditions.
+ * (We cast these values to int explicitly, because some compilers
+ * don't do this if the other arm of a conditional is a unsigned char.)
+ */
+/* End of data */
+#define PTSFAX_EOFC ((int)(-1))
+/* Error */
+#define PTSFAX_ERRC ((int)(-2))
+/* Interrupt */
+/* #define INTC ((int)(-3)) */
+/****** INTC IS NOT USED YET ******/
+/* Callout */
+/* #define CALLC ((int)(-4)) */
+#define max_stream_exception 4
+/* The following hack is needed for initializing scan_char_array in iscan.c. */
+#define stream_exception_repeat(x) x, x, x, x
+
+/*
+ * Define cursors for reading from or writing into a buffer.
+ * We lay them out this way so that we can alias
+ * the write pointer and the read limit.
+ */
+typedef struct stream_cursor_read_s {
+ const unsigned char *ptr;
+ const unsigned char *limit;
+ unsigned char *_skip;
+} stream_cursor_read;
+typedef struct stream_cursor_write_s {
+ const unsigned char *_skip;
+ unsigned char *ptr;
+ unsigned char *limit;
+} stream_cursor_write;
+typedef union stream_cursor_s {
+ stream_cursor_read r;
+ stream_cursor_write w;
+} stream_cursor;
+
+/*
+ * Define the prototype for the procedures known to both the generic
+ * stream code and the stream implementations.
+ */
+
+/* Initialize the stream state (after the client parameters are set). */
+#define stream_proc_init(proc)\
+ int proc _((stream_state *))
+
+/* Process a buffer. See strimpl.h for details. */
+#define stream_proc_process(proc)\
+ int proc _((stream_state *, stream_cursor_read *,\
+ stream_cursor_write *, bool))
+
+/* Release the stream state when closing. */
+#define stream_proc_release(proc)\
+ void proc _((stream_state *))
+
+/* Initialize the client parameters to default values. */
+#define stream_proc_set_defaults(proc)\
+ void proc _((stream_state *))
+
+/* Reinitialize any internal stream state. Note that this does not */
+/* affect buffered data. We declare this as returning an int so that */
+/* it can be the same as the init procedure; however, reinit cannot fail. */
+#define stream_proc_reinit(proc)\
+ int proc _((stream_state *))
+
+/* Report an error. Note that this procedure is stored in the state, */
+/* not in the main stream structure. */
+#define stream_proc_report_error(proc)\
+ int proc _((stream_state *, const char *))
+stream_proc_report_error(s_no_report_error);
+
+/*
+ * Some types of streams have the ability to read their parameters from
+ * a parameter list, and to write all (or only the non-default)
+ * parameters to a parameter list. Since these are not virtual
+ * procedures for the stream (they operate on stream_state structures
+ * even if no actual stream has been created), we name them differently.
+ */
+#define stream_state_proc_get_params(proc, state_type)\
+ int proc _((gs_param_list *plist, const state_type *ss, bool all))
+#define stream_state_proc_put_params(proc, state_type)\
+ int proc _((gs_param_list *plist, state_type *ss))
+
+/*
+ * Define a generic stream state. If a processing procedure has no
+ * state of its own, it can use stream_state; otherwise, it must
+ * create a "subclass". There is a hack in stream.h to allow the stream
+ * itself to serve as the "state" of a couple of heavily used stream types.
+ *
+ * In order to simplify the structure descriptors for concrete streams,
+ * we require that the generic stream state not contain any pointers
+ * to garbage-collectable storage.
+ */
+#define STREAM_MAX_ERROR_STRING 79
+#define stream_state_common\
+ const stream_template *template_; /**** pts C++ */\
+ gssss_memset_t memset_;\
+ gssss_xalloc_t xalloc_;\
+ gssss_free_t free_;\
+ gssss_memcpy_t memcpy_;\
+ /* gs_memory_t *memory; */ /**** pts ****/ \
+ stream_proc_report_error((*report_error));\
+ int min_left; /* required bytes for lookahead */ \
+ char error_string[STREAM_MAX_ERROR_STRING + 1]
+struct stream_state_s {
+ stream_state_common;
+};
+
+/* extern_st(st_stream_state); */ /**** pts ****/
+#define public_st_stream_state() /* in stream.c */\
+ gs_public_st_simple(st_stream_state, stream_state, "stream_state")
+
+/**** pts ****/
+/* original strimpl.h coming */
+/*$Id: pts_fax.h,v 1.4 2005/07/20 21:15:08 pts Exp $ */
+/* Definitions for stream implementors */
+/* Requires stdio.h */
+
+/*
+ * The 'process' procedure does the real work of the stream.
+ * It must process as much input information (from pr->ptr + 1 through
+ * pr->limit) as it can, subject to space available for output
+ * (pw->ptr + 1 through pw->limit), updating pr->ptr and pw->ptr.
+ *
+ * The procedure return value must be one of:
+ * PTSFAX_EOFC - an end-of-data pattern was detected in the input,
+ * or no more input can be processed for some other reason (e.g.,
+ * the stream was told only to read a certain amount of data).
+ * PTSFAX_ERRC - a syntactic error was detected in the input.
+ * 0 - more input data is needed.
+ * 1 - more output space is needed.
+ * If the procedure returns PTSFAX_EOFC, it can assume it will never be called
+ * again for that stream.
+ *
+ * If the procedure is called with last = 1, this is an indication that
+ * no more input will ever be supplied (after the input in the current
+ * buffer defined by *pr); the procedure should produce as much output
+ * as possible, including an end-of-data marker if applicable. In this
+ * case:
+ * - If the procedure returns 1, it may be called again (also with
+ * last = 1).
+ * - If the procedure returns any other value other than 1, the
+ * procedure will never be called again for that stream.
+ * - If the procedure returns 0, this is taken as equivalent to
+ * returning PTSFAX_EOFC.
+ * - If the procedure returns PTSFAX_EOFC (or 0), the stream's end_status
+ * is set to PTSFAX_EOFC, meaning no more writing is allowed.
+ *
+ * Note that these specifications do not distinguish input from output
+ * streams. This is deliberate: The processing procedures should work
+ * regardless of which way they are oriented in a stream pipeline.
+ * (The PostScript language does take a position as whether any given
+ * filter may be used for input or output, but this occurs at a higher level.)
+ *
+ * The value returned by the process procedure of a stream whose data source
+ * or sink is external (i.e., not another stream) is interpreted slightly
+ * differently. For an external data source, a return value of 0 means
+ * "no more input data are available now, but more might become available
+ * later." For an external data sink, a return value of 1 means "there is
+ * no more room for output data now, but there might be room later."
+ *
+ * It appears that the Adobe specifications, read correctly, require that when
+ * the process procedure of a decoding filter has filled up the output
+ * buffer, it must still peek ahead in the input to determine whether or not
+ * the next thing in the input stream is EOD. If the next thing is an EOD (or
+ * end-of-data, indicated by running out of input data with last = true), the
+ * process procedure must return PTSFAX_EOFC; if the next thing is definitely not
+ * an EOD, the process procedure must return 1 (output full) (without, of
+ * course, consuming the non-EOD datum); if the procedure cannot determine
+ * whether or not the next thing is an EOD, it must return 0 (need more input).
+ * Decoding filters that don't have EOD (for example, NullDecode) can use
+ * a simpler algorithm: if the output buffer is full, then if there is more
+ * input, return 1, otherwise return 0 (which is taken as PTSFAX_EOFC if last
+ * is true). All this may seem a little awkward, but it is needed in order
+ * to have consistent behavior regardless of where buffer boundaries fall --
+ * in particular, if a buffer boundary falls just before an EOD. It is
+ * actually quite easy to implement if the main loop of the process
+ * procedure tests for running out of input rather than for filling the
+ * output: with this structure, exhausting the input always returns 0,
+ * and discovering that the output buffer is full when attempting to store
+ * more output always returns 1.
+ *
+ * Even this algorithm for handling end-of-buffer is not sufficient if an
+ * EOD falls just after a buffer boundary, but the generic stream code
+ * handles this case: the process procedures need only do what was just
+ * described.
+ */
+
+/*
+ * The set_defaults procedure in the template has a dual purpose: it sets
+ * default values for all parameters that the client can set before calling
+ * the init procedure, and it also must initialize all pointers in the
+ * stream state to a value that will be valid for the garbage collector
+ * (normally 0). The latter implies that:
+ *
+ * Any stream whose state includes additional pointers (beyond those
+ * in stream_state_common) must have a set_defaults procedure.
+ */
+
+/*
+ * Note that all decoding filters that require an explicit EOD in the
+ * source data must have an init procedure that sets min_left = 1.
+ * This effectively provides a 1-unsigned char lookahead in the source data,
+ * which is required so that the stream can close itself "after reading
+ * the last unsigned char of data" (per Adobe specification), as noted above.
+ */
+
+/*
+ * Define a template for creating a stream.
+ *
+ * The meaning of min_in_size and min_out_size is the following:
+ * If the amount of input information is at least min_in_size,
+ * and the available output space is at least min_out_size,
+ * the process procedure guarantees that it will make some progress.
+ * (It may make progress even if this condition is not met, but this is
+ * not guaranteed.)
+ */
+struct stream_template_s {
+
+ /* Define the structure type for the stream state. */
+ /* gs_memory_type_ptr_t stype; */ /**** pts ****/
+
+ /* Define an optional initialization procedure. */
+ stream_proc_init((*init));
+
+ /* Define the processing procedure. */
+ /* (The init procedure can reset other procs if it wants.) */
+ stream_proc_process((*process));
+
+ /* Define the minimum buffer sizes. */
+ unsigned int min_in_size; /* minimum size for process input */
+ unsigned int min_out_size; /* minimum size for process output */
+
+ /* Define an optional releasing procedure. */
+ stream_proc_release((*release));
+
+ /* Define an optional parameter defaulting and pointer initialization */
+ /* procedure. */
+ stream_proc_set_defaults((*set_defaults));
+
+ /* Define an optional reinitialization procedure. */
+ stream_proc_reinit((*reinit));
+
+};
+
+
+#if 0
+/* Hex decoding utility procedure */
+typedef enum {
+ hex_ignore_garbage = 0,
+ hex_ignore_whitespace = 1,
+ hex_ignore_leading_whitespace = 2
+} hex_syntax;
+int s_hex_process _((stream_cursor_read *, stream_cursor_write *, int *, hex_syntax)); /* in sstring.c */
+#endif
+/* end of former strimpl.h */
+/* #endif */ /* scommon_INCLUDED */
+/* end of former scommon.h */
+
+
+
+/* ------ Common state ------ */
+
+/*
+ * Define the common stream state for Huffman-coded filters.
+ * Invariants when writing:
+ * 0 <= bits_left <= hc_bits_size;
+ * Only the leftmost (hc_bits_size - bits_left) bits of bits
+ * contain valid data.
+ */
+#define stream_hc_state_common\
+ stream_state_common;\
+ /* The client sets the following before initialization. */\
+ bool FirstBitLowOrder;\
+ /* The following are updated dynamically. */\
+ unsigned int bits; /* most recent bits of input or */\
+ /* current bits of output */\
+ int bits_left /* # of valid low bits (input) or */\
+ /* unused low bits (output) in above, */\
+ /* 0 <= bits_left <= 7 */
+typedef struct stream_hc_state_s {
+ stream_hc_state_common;
+} stream_hc_state;
+
+/* Common state */
+#define stream_CF_state_common\
+ stream_hc_state_common;\
+ /* The client sets the following before initialization. */\
+ bool Uncompressed;\
+ int K;\
+ bool EndOfLine;\
+ bool EncodedByteAlign;\
+ int Columns;\
+ int Rows;\
+ bool EndOfBlock;\
+ bool BlackIs1;\
+ int DamagedRowsBeforeError; /* (Decode only) */\
+ /*bool FirstBitLowOrder;*/ /* in stream_hc_state_common */\
+ int DecodedByteAlign;\
+ /* The init procedure sets the following. */\
+ unsigned int raster;\
+ unsigned char *lbuf; /* current scan line buffer */\
+ /* (only if decoding or 2-D encoding) */\
+ unsigned char *lprev; /* previous scan line buffer (only if 2-D) */\
+ /* The following are updated dynamically. */\
+ int k_left /* number of next rows to encode in 2-D */\
+ /* (only if K > 0) */
+typedef struct stream_CF_state_s {
+ stream_CF_state_common;
+} stream_CF_state;
+
+/* Define common default parameter setting. */
+#define s_CF_set_defaults_inline(ss)\
+ ((ss)->Uncompressed = false,\
+ (ss)->K = 0,\
+ (ss)->EndOfLine = false,\
+ (ss)->EncodedByteAlign = false,\
+ (ss)->Columns = 1728,\
+ (ss)->Rows = 0,\
+ (ss)->EndOfBlock = true,\
+ (ss)->BlackIs1 = false,\
+ /* Added by Adobe since the Red Book */\
+ (ss)->DamagedRowsBeforeError = 0, /* always set, for s_CF_get_params */\
+ (ss)->FirstBitLowOrder = false,\
+ /* Added by us */\
+ (ss)->DecodedByteAlign = 1,\
+ /* Clear pointers */\
+ (ss)->lbuf = 0, (ss)->lprev = 0)
+
+/* CCITTFaxEncode */
+typedef struct stream_CFE_state_s {
+ stream_CF_state_common;
+ /* The init procedure sets the following. */
+ int max_code_bytes; /* max # of bytes for an encoded line */
+ unsigned char *lcode; /* buffer for encoded output line */
+ /* The following change dynamically. */
+ int read_count; /* # of bytes to copy into lbuf */
+ int write_count; /* # of bytes to copy out of lcode */
+ int code_bytes; /* # of occupied bytes in lcode */
+} stream_CFE_state;
+
+#define private_st_CFE_state() /* in scfe.c */\
+ gs_private_st_ptrs3(st_CFE_state, stream_CFE_state, "CCITTFaxEncode state",\
+ cfe_enum_ptrs, cfe_reloc_ptrs, lbuf, lprev, lcode)
+#define s_CFE_set_defaults_inline(ss)\
+ (s_CF_set_defaults_inline(ss), (ss)->lcode = 0)
+#if USE_BUILTIN_FAXE
+/**** pts ****/
+#if SIZEOF_INT > 2
+# define cfe_max_width (2560 * 32000 * 2 / 3)
+#else
+# define cfe_max_width ((int)((unsigned)-1/2 - 40)) /* avoid overflows */
+#endif
+#ifdef __cplusplus
+extern "C"
+#else
+extern
+#endif
+const stream_template s_CFE_template;
+#endif
+
+/* CCITTFaxDecode */
+typedef struct stream_CFD_state_s {
+ stream_CF_state_common;
+ int cbit; /* bits left to fill in current decoded */
+ /* unsigned char at lbuf[wpos] (0..7) */
+ int rows_left; /* number of rows left */
+ int rpos; /* rptr for copying lbuf to client */
+ int wpos; /* rlimit/wptr for filling lbuf or */
+ /* copying to client */
+ int eol_count; /* number of EOLs seen so far */
+ unsigned char invert; /* current value of 'white' */
+ /* for 2-D decoding */
+ int run_color; /* -1 if processing white run, */
+ /* 0 if between runs but white is next, */
+ /* 1 if between runs and black is next, */
+ /* 2 if processing black run */
+ int damaged_rows; /* # of consecutive damaged rows preceding */
+ /* the current row */
+ bool skipping_damage; /* true if skipping a damaged row looking */
+ /* for EOL */
+ /* The following are not used yet. */
+ int uncomp_run; /* non-0 iff we are in an uncompressed */
+ /* run straddling a scan line (-1 if white, */
+ /* 1 if black) */
+ int uncomp_left; /* # of bits left in the run */
+ int uncomp_exit; /* non-0 iff this is an exit run */
+ /* (-1 if next run white, 1 if black) */
+} stream_CFD_state;
+
+#define private_st_CFD_state() /* in scfd.c */\
+ gs_private_st_ptrs2(st_CFD_state, stream_CFD_state, "CCITTFaxDecode state",\
+ cfd_enum_ptrs, cfd_reloc_ptrs, lbuf, lprev)
+#define s_CFD_set_defaults_inline(ss)\
+ s_CF_set_defaults_inline(ss)
+#if USE_BUILTIN_FAXD
+extern const stream_template s_CFD_template;
+#endif
+
+#endif /* pts_fax.h */
diff --git a/graphics/sam2p/pts_lzw.c b/graphics/sam2p/pts_lzw.c
new file mode 100644
index 0000000000..4d6b9439b0
--- /dev/null
+++ b/graphics/sam2p/pts_lzw.c
@@ -0,0 +1,1490 @@
+#define DUMMY \
+set -ex; \
+g++ -DNDEBUG=1 -O3 -ansi -pedantic \
+ -Wall -W -Wstrict-prototypes -Wtraditional -Wnested-externs -Winline \
+ -Wpointer-arith -Wbad-function-cast -Wcast-qual -Wmissing-prototypes \
+ -Wmissing-declarations pts_lzw.c -c; \
+exit
+/* pts_lzw.c -- a real, effective implementation of PostScript
+ * LanguageLevel2 and PDF /LZWEncode and /LZWDecode filters (same as the LZW
+ * compression used in TIFF raster image files)
+ *
+ * based on tif_lzw.c in libtiff-v3.4beta037 by Sam Leffler and Silicon Graphics.
+ * by pts@fazekas.hu at Sun Dec 30 15:04:19 CET 2001
+ * encoding and decoding works at Sun Dec 30 17:05:23 CET 2001
+ * modified for sam2p at Mon Mar 4 00:21:59 CET 2002
+ *
+ * Note that the LZW compression (but not uncompression) is patented by
+ * Unisys (patent number #4,558,302), so use this program at your own legal
+ * risk!
+ *
+ * Predictors and PostScript LanguageLevel3 filter options are not supported.
+ *
+ * Test: linux-2.2.8.tar.gz
+ * -- uncompressed: 58 388 480 bytes
+ * -- LZWEncode (lzw_codec.c): 26 518 397 bytes (uncompression OK)
+ * -- FlateEncode (almost gzip): 13 808 890 bytes (uncompression: zcat)
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You 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
+ */
+/* Imp: check #ifdef _WINDOWS */
+/* Dat: a strip is an interval of rows. Each strip -- probably except for the
+ * last -- has a same number of rows. Strips are useful for TIFF writers
+ * to better organize data in memory or disk.
+ */
+
+#ifdef __GNUC__
+#ifndef __clang__
+#pragma implementation
+#endif
+#endif
+
+#if _MSC_VER > 1000
+# undef __PROTOTYPES__
+# define __PROTOTYPES__ 1
+# pragma warning(disable: 4127) /* conditional expression is constant */
+# pragma warning(disable: 4244) /* =' : conversion from 'int ' to 'unsigned char ', possible loss of data */
+#endif
+
+
+/* Original: /d1/sam/tiff/libtiff/RCS/tif_lzw.c,v 1.73 1997/08/29 21:45:54 sam Exp */
+
+/*
+ * Copyright (c) 1988-1997 Sam Leffler
+ * Copyright (c) 1991-1997 Silicon Graphics, Inc.
+ *
+ * Permission to use, copy, modify, distribute, and sell this software and
+ * its documentation for any purpose is hereby granted without fee, provided
+ * that (i) the above copyright notices and this permission notice appear in
+ * all copies of the software and related documentation, and (ii) the names of
+ * Sam Leffler and Silicon Graphics may not be used in any advertising or
+ * publicity relating to the software without the specific, prior written
+ * permission of Sam Leffler and Silicon Graphics.
+ *
+ * THE SOFTWARE IS PROVIDED "AS-IS" AND WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS, IMPLIED OR OTHERWISE, INCLUDING WITHOUT LIMITATION, ANY
+ * WARRANTY OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE.
+ *
+ * IN NO EVENT SHALL SAM LEFFLER OR SILICON GRAPHICS BE LIABLE FOR
+ * ANY SPECIAL, INCIDENTAL, INDIRECT OR CONSEQUENTIAL DAMAGES OF ANY KIND,
+ * OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
+ * WHETHER OR NOT ADVISED OF THE POSSIBILITY OF DAMAGE, AND ON ANY THEORY OF
+ * LIABILITY, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE
+ * OF THIS SOFTWARE.
+ */
+
+/**** pts ****/
+#if OBJDEP
+# warning PROVIDES: pts_lzw
+#endif
+#define LZW_SUPPORT 1
+#if 0 /* conflicts with some system defs */
+typedef unsigned short u_short;
+typedef unsigned char u_char;
+typedef unsigned long u_long;
+#endif
+#define TO_RDONLY 1
+#define _TIFFmalloc malloc
+#define _TIFFfree free
+#define _TIFFmemset memset
+#include <stdlib.h>
+#include <string.h>
+
+/*
+ * ``Library-private'' definitions.
+ */
+
+/*
+ * TIFF I/O Library Definitions.
+ */
+/*
+ * Tag Image File Format (TIFF)
+ *
+ * Based on Rev 6.0 from:
+ * Developer's Desk
+ * Aldus Corporation
+ * 411 First Ave. South
+ * Suite 200
+ * Seattle, WA 98104
+ * 206-622-5500
+ */
+#define TIFF_VERSION 42
+
+/*
+ * NB: In the comments below,
+ * - items marked with a + are obsoleted by revision 5.0,
+ * - items marked with a ! are introduced in revision 6.0.
+ * - items marked with a % are introduced post revision 6.0.
+ * - items marked with a $ are obsoleted by revision 6.0.
+ */
+
+/* --- */
+
+/*
+ * This define can be used in code that requires
+ * compilation-related definitions specific to a
+ * version or versions of the library. Runtime
+ * version checking should be done based on the
+ * string returned by TIFFGetVersion.
+ */
+#define TIFFLIB_VERSION 19970127 /* January 27, 1997 */
+
+/*
+ * The following typedefs define the intrinsic size of
+ * data types used in the *exported* interfaces. These
+ * definitions depend on the proper definition of types
+ * in tiff.h. Note also that the varargs interface used
+ * to pass tag types and values uses the types defined in
+ * tiff.h directly.
+ *
+ * NB: ttag_t is unsigned int and not unsigned short because
+ * ANSI C requires that the type before the ellipsis be a
+ * promoted type (i.e. one of int, unsigned int, pointer,
+ * or double) and because we defined pseudo-tags that are
+ * outside the range of legal Aldus-assigned tags.
+ * NB: tsize_t is int32 and not uint32 because some functions
+ * return -1.
+ * NB: toff_t is not off_t for many reasons; TIFFs max out at
+ * 32-bit file offsets being the most important
+ */
+
+#ifndef NULL
+#define NULL 0
+#endif
+
+typedef struct pts_lzw_state TIFF;
+#include "pts_lzw.h"
+
+/**** pts ****/
+static int TIFFInitLZW(TIFF*);
+static void TIFFError(char const*a, char const*b);
+#if 0 /**** pts ****/
+static void TIFFWarning(char const*a, char const*b, int c);
+void TIFFWarning(char const*a, char const*b, int c) {
+ fprintf(stderr, "Warning: %s: ", a);
+ fprintf(stderr, b, c);
+ fprintf(stderr, "\n");
+}
+#endif
+static int TIFFAppendTo(TIFF*, tidataval_t*, tsize_t); /* tif_write.h */
+#if 0
+static void TIFFReverseBits(unsigned char *, unsigned long);
+#endif
+
+#ifdef LZW_SUPPORT
+/*
+ * TIFF Library.
+ * Rev 5.0 Lempel-Ziv & Welch Compression Support
+ *
+ * This code is derived from the compress program whose code is
+ * derived from software contributed to Berkeley by James A. Woods,
+ * derived from original work by Spencer Thomas and Joseph Orost.
+ *
+ * The original Berkeley copyright notice appears below in its entirety.
+ */
+
+#include <assert.h>
+/* #include <stdio.h> */
+
+/*
+ * Internal version of TIFFFlushData that can be
+ * called by ``encodestrip routines'' w/o concern
+ * for infinite recursion.
+ */
+static int
+TIFFFlushData1(TIFF* tif)
+{
+ if (tif->tif_rawcc > 0) {
+#if 0
+ if (tif->tif_revbits_p)
+ TIFFReverseBits((unsigned char *)tif->tif_rawdata,
+ tif->tif_rawcc);
+#endif
+ if (!TIFFAppendTo(tif,
+ /* isTiled(tif) ? tif->tif_curtile : tif->tif_curstrip, */
+ tif->tif_rawdata, tif->tif_rawcc))
+ return (0);
+ tif->tif_rawcc = 0;
+ tif->tif_rawcp = tif->tif_rawdata;
+ }
+ return (1);
+}
+
+
+
+/*
+ * NB: The 5.0 spec describes a different algorithm than Aldus
+ * implements. Specifically, Aldus does code length transitions
+ * one code earlier than should be done (for real LZW).
+ * Earlier versions of this library implemented the correct
+ * LZW algorithm, but emitted codes in a bit order opposite
+ * to the TIFF spec. Thus, to maintain compatibility w/ Aldus
+ * we interpret MSB-LSB ordered codes to be images written w/
+ * old versions of this library, but otherwise adhere to the
+ * Aldus "off by one" algorithm.
+ *
+ * Future revisions to the TIFF spec are expected to "clarify this issue".
+ */
+#define LZW_COMPAT /* include backwards compatibility code */
+/*
+ * Each strip of data is supposed to be terminated by a CODE_EOI.
+ * If the following #define is included, the decoder will also
+ * check for end-of-strip w/o seeing this code. This makes the
+ * library more robust, but also slower.
+ */
+#define LZW_CHECKEOS /* include checks for strips w/o EOI code */
+#undef LZW_CHECKEOS /**** pts ****/
+
+#define MAXCODE(n) ((1L<<(n))-1)
+/*
+ * The TIFF spec specifies that encoded bit
+ * strings range from 9 to 12 bits.
+ */
+#define BITS_MIN 9 /* start with 9 bits */
+#define BITS_MAX 12 /* max of 12 bit strings */
+/* predefined codes */
+#define CODE_CLEAR 256 /* code to clear string table */
+#define CODE_EOI 257 /* end-of-information code */
+#define CODE_FIRST 258 /* first free code entry */
+#define CODE_MAX MAXCODE(BITS_MAX)
+#define HSIZE 9001L /* 91% occupancy */
+#define HSHIFT (13-8)
+#ifdef LZW_COMPAT
+/* NB: +1024 is for compatibility with old files */
+#define CSIZE (MAXCODE(BITS_MAX)+1024L)
+#else
+#define CSIZE (MAXCODE(BITS_MAX)+1L)
+#endif
+
+/*
+ * State block for each open TIFF file using LZW
+ * compression/decompression. Note that the predictor
+ * state block must be first in this data structure.
+ */
+typedef struct {
+#if 0 /****pts****/
+ TIFFPredictorState predict; /* predictor super class */
+#endif
+
+ unsigned short nbits; /* # of bits/code */
+ unsigned short maxcode; /* maximum code for lzw_nbits */
+ unsigned short free_ent; /* next free entry in hash table */
+ long nextdata; /* next bits of i/o */
+ long nextbits; /* # of valid bits in lzw_nextdata */
+} LZWBaseState;
+
+#define lzw_nbits base.nbits
+#define lzw_maxcode base.maxcode
+#define lzw_free_ent base.free_ent
+#define lzw_nextdata base.nextdata
+#define lzw_nextbits base.nextbits
+
+/*
+ * Decoding-specific state.
+ */
+typedef struct code_ent {
+ struct code_ent *next;
+ unsigned short length; /* string len, including this token */
+ unsigned char value; /* data value */
+ unsigned char firstchar; /* first token of string */
+} code_t;
+
+typedef int (*decodeFunc)(TIFF*, tidataval_t*, tsize_t);
+
+typedef struct {
+ LZWBaseState base;
+ long dec_nbitsmask; /* lzw_nbits 1 bits, right adjusted */
+ long dec_restart; /* restart count */
+#ifdef LZW_CHECKEOS
+ long dec_bitsleft; /* available bits in raw data */
+#endif
+ decodeFunc dec_decode; /* regular or backwards compatible */
+ code_t* dec_codep; /* current recognized code */
+ code_t* dec_oldcodep; /* previously recognized code */
+ code_t* dec_free_entp; /* next free entry */
+ code_t* dec_maxcodep; /* max available entry */
+ code_t* dec_codetab; /* kept separate for small machines */
+} LZWDecodeState;
+
+/*
+ * Encoding-specific state.
+ */
+typedef unsigned short hcode_t; /* codes fit in 16 bits */
+typedef struct {
+ long hash;
+ hcode_t code;
+} hash_t;
+
+typedef struct {
+ LZWBaseState base;
+ int enc_oldcode; /* last code encountered */
+ long enc_checkpoint; /* point at which to clear table */
+#define CHECK_GAP 10000 /* enc_ratio check interval */
+ long enc_ratio; /* current compression ratio */
+ long enc_incount; /* (input) data bytes encoded */
+ long enc_outcount; /* encoded (output) bytes */
+ tidataval_t* enc_rawlimit; /* bound on tif_rawdata buffer */
+ hash_t* enc_hashtab; /* kept separate for small machines */
+} LZWEncodeState;
+
+#define LZWState(tif) ((LZWBaseState*) (void*) (tif)->tif_data)
+#define DecoderState(tif) ((LZWDecodeState*)(void*) LZWState(tif))
+#define EncoderState(tif) ((LZWEncodeState*)(void*) LZWState(tif))
+/* ^^^ Dat: (void*) -> suppress gcc warning from -Wcast-align */
+
+static void cl_hash(LZWEncodeState*);
+
+#if 0 /**** pts ****/ /* LZW decoder is not needed */
+
+static int LZWDecode(TIFF*, tidataval_t*, tsize_t);
+#ifdef LZW_COMPAT
+static int LZWDecodeCompat(TIFF*, tidataval_t*, tsize_t);
+#endif
+
+/*
+ * LZW Decoder.
+ */
+
+#ifdef LZW_CHECKEOS
+/*
+ * This check shouldn't be necessary because each
+ * strip is suppose to be terminated with CODE_EOI.
+ */
+#define NextCode(_tif, _sp, _bp, _code, _get) { \
+ if ((_sp)->dec_bitsleft < nbits) { \
+ TIFFWarning(_tif->tif_name, \
+ "LZWDecode: Strip %d not terminated with EOI code", \
+ /*_tif->tif_curstrip*/ 0); \
+ _code = CODE_EOI; \
+ } else { \
+ _get(_sp,_bp,_code); \
+ (_sp)->dec_bitsleft -= nbits; \
+ } \
+}
+#else
+#define NextCode(tif, sp, bp, code, get) get(sp, bp, code)
+#endif
+
+static int
+LZWSetupDecode(TIFF* tif)
+{
+ LZWDecodeState* sp = DecoderState(tif);
+ static const char module[] = " LZWSetupDecode";
+ int code;
+
+ assert(sp != NULL);
+ if (sp->dec_codetab == NULL) {
+ sp->dec_codetab = (code_t*)_TIFFmalloc(CSIZE*sizeof (code_t));
+ if (sp->dec_codetab == NULL) {
+ TIFFError(module, "No space for LZW code table");
+ return (0);
+ }
+ /*
+ * Pre-load the table.
+ */
+ for (code = 255; code >= 0; code--) {
+ sp->dec_codetab[code].value = code;
+ sp->dec_codetab[code].firstchar = code;
+ sp->dec_codetab[code].length = 1;
+ sp->dec_codetab[code].next = NULL;
+ }
+ }
+ return (1);
+}
+
+/*
+ * Setup state for decoding a strip.
+ */
+static int
+LZWPreDecode(TIFF* tif)
+{
+ LZWDecodeState *sp = DecoderState(tif);
+
+ assert(sp != NULL);
+ /*
+ * Check for old bit-reversed codes.
+ */
+ if (tif->tif_rawdata[0] == 0 && (tif->tif_rawdata[1] & 0x1)) {
+#ifdef LZW_COMPAT
+ if (!sp->dec_decode) {
+ TIFFWarning(tif->tif_name,
+ "Old-style LZW codes, convert file %d", 0);
+#if 0 /**** pts ****/
+ /*
+ * Override default decoding methods with
+ * ones that deal with the old coding.
+ * Otherwise the predictor versions set
+ * above will call the compatibility routines
+ * through the dec_decode method.
+ */
+ tif->tif_decoderow = LZWDecodeCompat;
+ tif->tif_decodestrip = LZWDecodeCompat;
+ tif->tif_decodetile = LZWDecodeCompat;
+ /*
+ * If doing horizontal differencing, must
+ * re-setup the predictor logic since we
+ * switched the basic decoder methods...
+ */
+ (*tif->tif_setupdecode)(tif);
+#endif
+ LZWSetupDecode(tif);
+ sp->dec_decode = LZWDecodeCompat;
+ }
+ sp->lzw_maxcode = MAXCODE(BITS_MIN);
+#else /* !LZW_COMPAT */
+ if (!sp->dec_decode) {
+ TIFFError(tif->tif_name,
+ "Old-style LZW codes not supported");
+ sp->dec_decode = LZWDecode;
+ }
+ return (0);
+#endif/* !LZW_COMPAT */
+ } else {
+ sp->lzw_maxcode = MAXCODE(BITS_MIN)-1;
+ sp->dec_decode = LZWDecode;
+ }
+ sp->lzw_nbits = BITS_MIN;
+ sp->lzw_nextbits = 0;
+ sp->lzw_nextdata = 0;
+
+ sp->dec_restart = 0;
+ sp->dec_nbitsmask = MAXCODE(BITS_MIN);
+#ifdef LZW_CHECKEOS
+ sp->dec_bitsleft = tif->tif_rawcc << 3;
+#endif
+ sp->dec_free_entp = sp->dec_codetab + CODE_FIRST;
+ /*
+ * Zero entries that are not yet filled in. We do
+ * this to guard against bogus input data that causes
+ * us to index into undefined entries. If you can
+ * come up with a way to safely bounds-check input codes
+ * while decoding then you can remove this operation.
+ */
+ _TIFFmemset(sp->dec_free_entp, 0, (CSIZE-CODE_FIRST)*sizeof (code_t));
+ sp->dec_oldcodep = &sp->dec_codetab[-1];
+ sp->dec_maxcodep = &sp->dec_codetab[sp->dec_nbitsmask-1];
+ return (1);
+}
+
+/*
+ * Decode a "hunk of data".
+ */
+#define GetNextCode(sp, bp, code) { \
+ nextdata = (nextdata<<8) | *(bp)++; \
+ nextbits += 8; \
+ if (nextbits < nbits) { \
+ nextdata = (nextdata<<8) | *(bp)++; \
+ nextbits += 8; \
+ } \
+ code = (hcode_t)((nextdata >> (nextbits-nbits)) & nbitsmask); \
+ nextbits -= nbits; \
+}
+
+static void
+codeLoop(TIFF* tif)
+{
+ TIFFError(tif->tif_name,
+ "LZWDecode: Bogus encoding, loop in the code table; scanline %d"
+ /*,tif->tif_row*/);
+}
+
+static int
+LZWDecode(TIFF* tif, tidataval_t* op0, tsize_t occ0)
+{
+ LZWDecodeState *sp = DecoderState(tif);
+ char *op = (char*) op0;
+ long occ = (long) occ0;
+ char *tp;
+ unsigned char *bp;
+ hcode_t code;
+ int len;
+ long nbits, nextbits, nextdata, nbitsmask;
+ code_t *codep, *free_entp, *maxcodep, *oldcodep;
+
+ assert(sp != NULL);
+ /*
+ * Restart interrupted output operation.
+ */
+ if (sp->dec_restart) {
+ long residue;
+
+ codep = sp->dec_codep;
+ residue = codep->length - sp->dec_restart;
+ if (residue > occ) {
+ /*
+ * Residue from previous decode is sufficient
+ * to satisfy decode request. Skip to the
+ * start of the decoded string, place decoded
+ * values in the output buffer, and return.
+ */
+ sp->dec_restart += occ;
+ do {
+ codep = codep->next;
+ } while (--residue > occ && codep);
+ if (codep) {
+ tp = op + occ;
+ do {
+ *--tp = codep->value;
+ codep = codep->next;
+ } while (--occ && codep);
+ }
+ return occ0-occ;
+ }
+ /*
+ * Residue satisfies only part of the decode request.
+ */
+ op += residue, occ -= residue;
+ tp = op;
+ do {
+ int t;
+ --tp;
+ t = codep->value;
+ codep = codep->next;
+ *tp = t;
+ } while (--residue && codep);
+ sp->dec_restart = 0;
+ }
+
+ bp = (unsigned char *)tif->tif_rawcp; /* reading from here */
+ nbits = sp->lzw_nbits;
+ nextdata = sp->lzw_nextdata;
+ nextbits = sp->lzw_nextbits;
+ nbitsmask = sp->dec_nbitsmask;
+ oldcodep = sp->dec_oldcodep;
+ free_entp = sp->dec_free_entp;
+ maxcodep = sp->dec_maxcodep;
+
+ while (occ > 0 && bp<tif->tif_rawend /**** pts ****/) {
+ NextCode(tif, sp, bp, code, GetNextCode);
+ #if 0
+ if (bp>tif->tif_rawend) fprintf(stderr, "over %d\n", tif->tif_rawend-bp);
+ assert(bp<=tif->tif_rawend);
+ #endif
+ if (code == CODE_EOI)
+ break;
+ if (code == CODE_CLEAR) {
+ free_entp = sp->dec_codetab + CODE_FIRST;
+ nbits = BITS_MIN;
+ nbitsmask = MAXCODE(BITS_MIN);
+ maxcodep = sp->dec_codetab + nbitsmask-1;
+
+#if 1 /**** pts ****/
+ NextCode(tif, sp, bp, code, GetNextCode);
+ if (code == CODE_EOI)
+ break;
+ *op++ = code, occ--;
+ oldcodep = sp->dec_codetab + code; /* ! */
+#endif
+ continue;
+ }
+ codep = sp->dec_codetab + code;
+
+ /*
+ * Add the new entry to the code table.
+ */
+ assert(&sp->dec_codetab[0] <= free_entp && free_entp < &sp->dec_codetab[CSIZE]);
+ free_entp->next = oldcodep;
+ free_entp->firstchar = free_entp->next->firstchar;
+ free_entp->length = free_entp->next->length+1;
+ free_entp->value = (codep < free_entp) ?
+ codep->firstchar : free_entp->firstchar;
+ if (++free_entp > maxcodep) {
+ if (++nbits > BITS_MAX) /* should not happen */
+ nbits = BITS_MAX;
+ nbitsmask = MAXCODE(nbits);
+ maxcodep = sp->dec_codetab + nbitsmask-1;
+ }
+ oldcodep = codep;
+ if (code >= 256) {
+ /*
+ * Code maps to a string, copy string
+ * value to output (written in reverse).
+ */
+ if (codep->length > occ) {
+ /*
+ * String is too long for decode buffer,
+ * locate portion that will fit, copy to
+ * the decode buffer, and setup restart
+ * logic for the next decoding call.
+ */
+ sp->dec_codep = codep;
+ do {
+ codep = codep->next;
+ } while (codep && codep->length > occ);
+ if (codep) {
+ sp->dec_restart = occ;
+ tp = op + occ;
+ do {
+ *--tp = codep->value;
+ codep = codep->next;
+ } while (--occ && codep);
+ if (codep) {
+ codeLoop(tif);
+ return -1;
+ }
+ }
+ break;
+ }
+ len = codep->length;
+ tp = op + len;
+ do {
+ int t;
+ --tp;
+ t = codep->value;
+ codep = codep->next;
+ *tp = t;
+ } while (codep && tp > op);
+ if (codep) {
+ codeLoop(tif);
+ return -1;
+ /* break; */
+ }
+ op += len, occ -= len;
+ } else
+ *op++ = code, occ--;
+ }
+
+ tif->tif_rawcp = (tidataval_t*) bp;
+ sp->lzw_nbits = (unsigned short) nbits;
+ sp->lzw_nextdata = nextdata;
+ sp->lzw_nextbits = nextbits;
+ sp->dec_nbitsmask = nbitsmask;
+ sp->dec_oldcodep = oldcodep;
+ sp->dec_free_entp = free_entp;
+ sp->dec_maxcodep = maxcodep;
+
+#if 0 /**** pts ****/
+ if (occ > 0) {
+ TIFFError(tif->tif_name,
+ "LZWDecode: Not enough data at scanline %d (short %d bytes)"
+ /*,tif->tif_row, occ*/);
+ return (0);
+ }
+#endif
+ return occ0-occ;
+}
+
+#ifdef LZW_COMPAT
+/*
+ * Decode a "hunk of data" for old images.
+ */
+#define GetNextCodeCompat(sp, bp, code) { \
+ nextdata |= (unsigned long) *(bp)++ << nextbits; \
+ nextbits += 8; \
+ if (nextbits < nbits) { \
+ nextdata |= (unsigned long) *(bp)++ << nextbits; \
+ nextbits += 8; \
+ } \
+ code = (hcode_t)(nextdata & nbitsmask); \
+ nextdata >>= nbits; \
+ nextbits -= nbits; \
+}
+
+static int
+LZWDecodeCompat(TIFF* tif, tidataval_t* op0, tsize_t occ0)
+{
+ LZWDecodeState *sp = DecoderState(tif);
+ char *op = (char*) op0;
+ long occ = (long) occ0;
+ char *tp;
+ unsigned char *bp;
+ int code, nbits;
+ long nextbits, nextdata, nbitsmask;
+ code_t *codep, *free_entp, *maxcodep, *oldcodep;
+
+ assert(0);
+ assert(sp != NULL);
+ /*
+ * Restart interrupted output operation.
+ */
+ if (sp->dec_restart) {
+ long residue;
+
+ codep = sp->dec_codep;
+ residue = codep->length - sp->dec_restart;
+ if (residue > occ) {
+ /*
+ * Residue from previous decode is sufficient
+ * to satisfy decode request. Skip to the
+ * start of the decoded string, place decoded
+ * values in the output buffer, and return.
+ */
+ sp->dec_restart += occ;
+ do {
+ codep = codep->next;
+ } while (--residue > occ);
+ tp = op + occ;
+ do {
+ *--tp = codep->value;
+ codep = codep->next;
+ } while (--occ);
+ return occ0-occ;
+ }
+ /*
+ * Residue satisfies only part of the decode request.
+ */
+ op += residue, occ -= residue;
+ tp = op;
+ do {
+ *--tp = codep->value;
+ codep = codep->next;
+ } while (--residue);
+ sp->dec_restart = 0;
+ }
+
+ bp = (unsigned char *)tif->tif_rawcp;
+ nbits = sp->lzw_nbits;
+ nextdata = sp->lzw_nextdata;
+ nextbits = sp->lzw_nextbits;
+ nbitsmask = sp->dec_nbitsmask;
+ oldcodep = sp->dec_oldcodep;
+ free_entp = sp->dec_free_entp;
+ maxcodep = sp->dec_maxcodep;
+
+ while (occ > 0 && bp<tif->tif_rawend) {
+ NextCode(tif, sp, bp, code, GetNextCodeCompat);
+ if (code == CODE_EOI)
+ break;
+ if (code == CODE_CLEAR) {
+ free_entp = sp->dec_codetab + CODE_FIRST;
+ nbits = BITS_MIN;
+ nbitsmask = MAXCODE(BITS_MIN);
+ maxcodep = sp->dec_codetab + nbitsmask;
+ NextCode(tif, sp, bp, code, GetNextCodeCompat);
+ if (code == CODE_EOI)
+ break;
+ *op++ = code, occ--;
+ oldcodep = sp->dec_codetab + code;
+ continue;
+ }
+ codep = sp->dec_codetab + code;
+
+ /*
+ * Add the new entry to the code table.
+ */
+ assert(&sp->dec_codetab[0] <= free_entp && free_entp < &sp->dec_codetab[CSIZE]);
+ free_entp->next = oldcodep;
+ free_entp->firstchar = free_entp->next->firstchar;
+ free_entp->length = free_entp->next->length+1;
+ free_entp->value = (codep < free_entp) ?
+ codep->firstchar : free_entp->firstchar;
+ if (++free_entp > maxcodep) {
+ if (++nbits > BITS_MAX) /* should not happen */
+ nbits = BITS_MAX;
+ nbitsmask = MAXCODE(nbits);
+ maxcodep = sp->dec_codetab + nbitsmask;
+ }
+ oldcodep = codep;
+ if (code >= 256) {
+ /*
+ * Code maps to a string, copy string
+ * value to output (written in reverse).
+ */
+ if (codep->length > occ) {
+ /*
+ * String is too long for decode buffer,
+ * locate portion that will fit, copy to
+ * the decode buffer, and setup restart
+ * logic for the next decoding call.
+ */
+ sp->dec_codep = codep;
+ do {
+ codep = codep->next;
+ } while (codep->length > occ);
+ sp->dec_restart = occ;
+ tp = op + occ;
+ do {
+ *--tp = codep->value;
+ codep = codep->next;
+ } while (--occ);
+ break;
+ }
+ op += codep->length, occ -= codep->length;
+ tp = op;
+ do {
+ *--tp = codep->value;
+ } while (0!=(codep = codep->next));
+ } else
+ *op++ = code, occ--;
+ }
+
+ tif->tif_rawcp = (tidataval_t*) bp;
+ sp->lzw_nbits = nbits;
+ sp->lzw_nextdata = nextdata;
+ sp->lzw_nextbits = nextbits;
+ sp->dec_nbitsmask = nbitsmask;
+ sp->dec_oldcodep = oldcodep;
+ sp->dec_free_entp = free_entp;
+ sp->dec_maxcodep = maxcodep;
+
+#if 0 /**** pts ****/
+ if (occ > 0) {
+ TIFFError(tif->tif_name,
+ "LZWDecodeCompat: Not enough data at scanline %d (short %d bytes)"
+ /*,tif->tif_row, occ*/);
+ return (0);
+ }
+#endif
+ return occ0-occ;
+}
+#endif /* LZW_COMPAT */
+
+#endif /**** pts ****/
+
+/* --- */
+
+/*
+ * LZW Encoding.
+ */
+
+static int
+LZWSetupEncode(TIFF* tif)
+{
+ LZWEncodeState* sp = EncoderState(tif);
+ static const char module[] = "LZWSetupEncode";
+
+ assert(sp != NULL);
+ sp->enc_hashtab = (hash_t*) _TIFFmalloc(HSIZE*sizeof (hash_t));
+ if (sp->enc_hashtab == NULL) {
+ TIFFError(module, "No space for LZW hash table");
+ return (0);
+ }
+ return (1);
+}
+
+/*
+ * Reset encoding state at the start of a strip.
+ */
+static int
+LZWPreEncode(TIFF* tif)
+{
+ LZWEncodeState *sp = EncoderState(tif);
+
+ assert(sp != NULL);
+ sp->lzw_nbits = BITS_MIN;
+ sp->lzw_maxcode = MAXCODE(BITS_MIN);
+ sp->lzw_free_ent = CODE_FIRST;
+ sp->lzw_nextbits = 0;
+ sp->lzw_nextdata = 0;
+ sp->enc_checkpoint = CHECK_GAP;
+ sp->enc_ratio = 0;
+ sp->enc_incount = 0;
+ sp->enc_outcount = 0;
+ /*
+ * The 4 here insures there is space for 2 max-sized
+ * codes in LZWEncode and LZWPostDecode.
+ */
+ sp->enc_rawlimit = tif->tif_rawdata + tif->tif_rawdatasize-1 - 4;
+ cl_hash(sp); /* clear hash table */
+ sp->enc_oldcode = (hcode_t) -1; /* generates CODE_CLEAR in LZWEncode */
+ return (1);
+}
+
+#define CALCRATIO(sp, rat) { \
+ if (incount > 0x007fffff) { /* NB: shift will overflow */\
+ rat = outcount >> 8; \
+ rat = (rat == 0 ? 0x7fffffff : incount/rat); \
+ } else \
+ rat = (incount<<8) / outcount; \
+}
+#define PutNextCode(op, c) { \
+ nextdata = (nextdata << nbits) | c; \
+ nextbits += nbits; \
+ *op++ = (unsigned char)(nextdata >> (nextbits-8)); \
+ nextbits -= 8; \
+ if (nextbits >= 8) { \
+ *op++ = (unsigned char)(nextdata >> (nextbits-8)); \
+ nextbits -= 8; \
+ } \
+ outcount += nbits; \
+}
+
+/*
+ * Encode a chunk of pixels.
+ *
+ * Uses an open addressing double hashing (no chaining) on the
+ * prefix code/next character combination. We do a variant of
+ * Knuth's algorithm D (vol. 3, sec. 6.4) along with G. Knott's
+ * relatively-prime secondary probe. Here, the modular division
+ * first probe is gives way to a faster exclusive-or manipulation.
+ * Also do block compression with an adaptive reset, whereby the
+ * code table is cleared when the compression ratio decreases,
+ * but after the table fills. The variable-length output codes
+ * are re-sized at this point, and a CODE_CLEAR is generated
+ * for the decoder.
+ */
+static int
+LZWEncode(TIFF* tif, tidataval_t* bp, tsize_t cc)
+{
+ register LZWEncodeState *sp = EncoderState(tif);
+ register long fcode;
+ register hash_t *hp;
+ register int h, c;
+ hcode_t ent;
+ long disp;
+ long incount, outcount, checkpoint;
+ long nextdata, nextbits;
+ int free_ent, maxcode, nbits;
+ tidataval_t* op, *limit;
+
+ if (sp == NULL)
+ return (0);
+ /*
+ * Load local state.
+ */
+ incount = sp->enc_incount;
+ outcount = sp->enc_outcount;
+ checkpoint = sp->enc_checkpoint;
+ nextdata = sp->lzw_nextdata;
+ nextbits = sp->lzw_nextbits;
+ free_ent = sp->lzw_free_ent;
+ maxcode = sp->lzw_maxcode;
+ nbits = sp->lzw_nbits;
+ op = tif->tif_rawcp;
+ limit = sp->enc_rawlimit;
+ ent = sp->enc_oldcode;
+
+ if (ent == (hcode_t) -1 && cc > 0) {
+ /*
+ * NB: This is safe because it can only happen
+ * at the start of a strip where we know there
+ * is space in the data buffer.
+ */
+ PutNextCode(op, CODE_CLEAR);
+ ent = *bp++; cc--; incount++;
+ }
+ while (cc > 0) {
+ c = *bp++; cc--; incount++;
+ fcode = ((long)c << BITS_MAX) + ent;
+ h = (c << HSHIFT) ^ ent; /* xor hashing */
+#ifdef _WINDOWS /* ?? */
+ /*
+ * Check hash index for an overflow.
+ */
+ if (h >= HSIZE)
+ h -= HSIZE;
+#endif
+ hp = &sp->enc_hashtab[h];
+ if (hp->hash == fcode) {
+ ent = hp->code;
+ continue;
+ }
+ if (hp->hash >= 0) {
+ /*
+ * Primary hash failed, check secondary hash.
+ */
+ disp = HSIZE - h;
+ if (h == 0)
+ disp = 1;
+ do {
+ /*
+ * Avoid pointer arithmetic 'cuz of
+ * wraparound problems with segments.
+ */
+ if ((h -= disp) < 0)
+ h += HSIZE;
+ hp = &sp->enc_hashtab[h];
+ if (hp->hash == fcode) {
+ ent = hp->code;
+ goto hit;
+ }
+ } while (hp->hash >= 0);
+ }
+ /*
+ * New entry, emit code and add to table.
+ */
+ /*
+ * Verify there is space in the buffer for the code
+ * and any potential Clear code that might be emitted
+ * below. The value of limit is setup so that there
+ * are at least 4 bytes free--room for 2 codes.
+ */
+ if (op > limit) {
+ tif->tif_rawcc = (tsize_t)(op - tif->tif_rawdata);
+ TIFFFlushData1(tif);
+ op = tif->tif_rawdata;
+ }
+ PutNextCode(op, ent);
+ ent = c;
+ hp->code = free_ent++;
+ hp->hash = fcode;
+ if (free_ent == CODE_MAX-1) {
+ /* table is full, emit clear code and reset */
+ cl_hash(sp);
+ sp->enc_ratio = 0;
+ incount = 0;
+ outcount = 0;
+ free_ent = CODE_FIRST;
+ PutNextCode(op, CODE_CLEAR);
+ nbits = BITS_MIN;
+ maxcode = MAXCODE(BITS_MIN);
+ } else {
+ /*
+ * If the next entry is going to be too big for
+ * the code size, then increase it, if possible.
+ */
+ if (free_ent > maxcode) {
+ nbits++;
+ assert(nbits <= BITS_MAX);
+ maxcode = (int) MAXCODE(nbits);
+ } else if (incount >= checkpoint) {
+ long rat;
+ /*
+ * Check compression ratio and, if things seem
+ * to be slipping, clear the hash table and
+ * reset state. The compression ratio is a
+ * 24+8-bit fractional number.
+ */
+ checkpoint = incount+CHECK_GAP;
+ CALCRATIO(sp, rat);
+ if (rat <= sp->enc_ratio) {
+ cl_hash(sp);
+ sp->enc_ratio = 0;
+ incount = 0;
+ outcount = 0;
+ free_ent = CODE_FIRST;
+ PutNextCode(op, CODE_CLEAR);
+ nbits = BITS_MIN;
+ maxcode = MAXCODE(BITS_MIN);
+ } else
+ sp->enc_ratio = rat;
+ }
+ }
+ hit:
+ ;
+ }
+
+ /*
+ * Restore global state.
+ */
+ sp->enc_incount = incount;
+ sp->enc_outcount = outcount;
+ sp->enc_checkpoint = checkpoint;
+ sp->enc_oldcode = ent;
+ sp->lzw_nextdata = nextdata;
+ sp->lzw_nextbits = nextbits;
+ sp->lzw_free_ent = free_ent;
+ sp->lzw_maxcode = maxcode;
+ sp->lzw_nbits = nbits;
+ tif->tif_rawcp = op;
+ return (1);
+}
+
+/*
+ * Finish off an encoded strip by flushing the last
+ * string and tacking on an End Of Information code.
+ */
+static int
+LZWPostEncode(TIFF* tif)
+{
+ register LZWEncodeState *sp = EncoderState(tif);
+ tidataval_t* op = tif->tif_rawcp;
+ long nextbits = sp->lzw_nextbits;
+ long nextdata = sp->lzw_nextdata;
+ long outcount = sp->enc_outcount;
+ int nbits = sp->lzw_nbits;
+
+ if (op > sp->enc_rawlimit) {
+ /* fprintf(stderr, "Yupp!\n"); */
+ tif->tif_rawcc = (tsize_t)(op - tif->tif_rawdata);
+ TIFFFlushData1(tif);
+ op = tif->tif_rawdata;
+ }
+ if (sp->enc_oldcode != (hcode_t) -1) {
+ /* fprintf(stderr, "EIK\n"); */
+ PutNextCode(op, sp->enc_oldcode);
+ sp->enc_oldcode = (hcode_t) -1;
+ }
+ PutNextCode(op, CODE_EOI);
+ if (nextbits > 0)
+ *op++ = (unsigned char)(nextdata << (8-nextbits));
+ tif->tif_rawcc = (tsize_t)(op - tif->tif_rawdata);
+ return (1);
+}
+
+/*
+ * Reset encoding hash table.
+ */
+static void
+cl_hash(LZWEncodeState* sp)
+{
+ register hash_t *hp = &sp->enc_hashtab[HSIZE-1];
+ register long i = HSIZE-8;
+
+ do {
+ i -= 8;
+ hp[-7].hash = -1;
+ hp[-6].hash = -1;
+ hp[-5].hash = -1;
+ hp[-4].hash = -1;
+ hp[-3].hash = -1;
+ hp[-2].hash = -1;
+ hp[-1].hash = -1;
+ hp[ 0].hash = -1;
+ hp -= 8;
+ } while (i >= 0);
+ for (i += 8; i > 0; i--, hp--)
+ hp->hash = -1;
+}
+
+static void
+LZWCleanup(TIFF* tif)
+{
+ if (tif->tif_data) {
+ if (tif->tif_reading_p) {
+ if (DecoderState(tif)->dec_codetab)
+ _TIFFfree(DecoderState(tif)->dec_codetab);
+ } else {
+ if (EncoderState(tif)->enc_hashtab)
+ _TIFFfree(EncoderState(tif)->enc_hashtab);
+ }
+ _TIFFfree(tif->tif_data);
+ tif->tif_data = NULL;
+ }
+ _TIFFfree(tif->tif_rawdata);
+}
+
+static int
+TIFFInitLZW(TIFF* tif)
+{
+ /* assert(scheme == COMPRESSION_LZW); */
+ /*
+ * Allocate state block so tag methods have storage to record values.
+ */
+ if (tif->tif_reading_p) {
+ tif->tif_data = (tidataval_t*) _TIFFmalloc(sizeof (LZWDecodeState));
+ if (tif->tif_data == NULL)
+ goto bad;
+ DecoderState(tif)->dec_codetab = NULL;
+ DecoderState(tif)->dec_decode = NULL;
+ } else {
+ tif->tif_data = (tidataval_t*) _TIFFmalloc(sizeof (LZWEncodeState));
+ if (tif->tif_data == NULL)
+ goto bad;
+ EncoderState(tif)->enc_hashtab = NULL;
+ }
+#if 0 /**** pts ****/
+ /*
+ * Install codec methods.
+ */
+ tif->tif_setupdecode = LZWSetupDecode;
+ tif->tif_predecode = LZWPreDecode;
+ tif->tif_decoderow = LZWDecode;
+ tif->tif_decodestrip = LZWDecode;
+ tif->tif_decodetile = LZWDecode;
+ tif->tif_setupencode = LZWSetupEncode;
+ tif->tif_preencode = LZWPreEncode;
+ tif->tif_postencode = LZWPostEncode;
+ tif->tif_encoderow = LZWEncode;
+ tif->tif_encodestrip = LZWEncode;
+ tif->tif_encodetile = LZWEncode;
+ tif->tif_cleanup = LZWCleanup;
+#endif
+#if 0 /**** pts ****/
+ /*
+ * Setup predictor setup.
+ */
+ (void) TIFFPredictorInit(tif);
+#endif
+ return (1);
+bad:
+ TIFFError("TIFFInitLZW", "No space for LZW state block");
+ return (0);
+}
+
+/*
+ * Copyright (c) 1985, 1986 The Regents of the University of California.
+ * All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * James A. Woods, derived from original work by Spencer Thomas
+ * and Joseph Orost.
+ *
+ * Redistribution and use in source and binary forms are permitted
+ * provided that the above copyright notice and this paragraph are
+ * duplicated in all such forms and that any documentation,
+ * advertising materials, and other materials related to such
+ * distribution and use acknowledge that the software was developed
+ * by the University of California, Berkeley. The name of the
+ * University may not be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
+ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+ */
+#endif /* LZW_SUPPORT */
+
+#if 0
+#ifdef __cplusplus
+extern "C"
+#else
+extern
+#endif
+FILE *fdopen (int fildes, const char *mode); /* POSIX, but not ANSI */
+#else
+#undef _POSIX_SOURCE
+#define _POSIX_SOURCE 1
+#undef _POSIX_C_SOURCE /* Sat Jun 1 14:25:53 CEST 2002 */
+#define _POSIX_C_SOURCE 2
+#include <stdio.h>
+#endif
+
+#if 0 /**** pts: never needed, because output FillOrder is always 1 */
+void
+TIFFReverseBits(register unsigned char* cp, register unsigned long n)
+{
+ char *TIFFBitRevTable=...; /**** pts ****/
+ for (; n > 8; n -= 8) {
+ cp[0] = TIFFBitRevTable[cp[0]];
+ cp[1] = TIFFBitRevTable[cp[1]];
+ cp[2] = TIFFBitRevTable[cp[2]];
+ cp[3] = TIFFBitRevTable[cp[3]];
+ cp[4] = TIFFBitRevTable[cp[4]];
+ cp[5] = TIFFBitRevTable[cp[5]];
+ cp[6] = TIFFBitRevTable[cp[6]];
+ cp[7] = TIFFBitRevTable[cp[7]];
+ cp += 8;
+ }
+ while (n-- > 0)
+ *cp = TIFFBitRevTable[*cp], cp++;
+}
+#endif
+
+static void TIFFError(char const*a, char const*b) {
+ fprintf(stderr, "%s: %s\n", a, b);
+}
+static int TIFFAppendTo(TIFF*tif, tidataval_t* data, tsize_t cc) {
+ (void)tif;
+ (void)data;
+ (void)cc;
+ /* fwrite(data, 1, cc, (FILE*)tif->tif_sout);
+ if (ferror((FILE*)tif->tif_sout)) return 0; */
+ if (-1==tif->tif_writer((char*)data, cc, tif->tif_sout)) return 0;
+#if 0 /**** pts ****/ /* tif_write.h */
+ (void)strip;
+ TIFFDirectory *td = &tif->tif_dir;
+ static const char module[] = "TIFFAppendToStrip";
+
+ if (td->td_stripoffset[strip] == 0 || tif->tif_curoff == 0) {
+ /*
+ * No current offset, set the current strip.
+ */
+ if (td->td_stripoffset[strip] != 0) {
+ if (!SeekOK(tif, td->td_stripoffset[strip])) {
+ TIFFError(module,
+ "%s: Seek error at scanline %lu",
+ tif->tif_name, (unsigned long) tif->tif_row);
+ return (0);
+ }
+ } else
+ td->td_stripoffset[strip] =
+ TIFFSeekFile(tif, (toff_t) 0, SEEK_END);
+ tif->tif_curoff = td->td_stripoffset[strip];
+ }
+ if (!WriteOK(tif, data, cc)) {
+ TIFFError(module, "%s: Write error at scanline %lu",
+ tif->tif_name, (unsigned long) tif->tif_row);
+ return (0);
+ }
+ tif->tif_curoff += cc;
+ td->td_stripbytecount[strip] += cc;
+#endif
+ return (1);
+}
+
+#if 0
+static tidataval_t readbuf[4096];
+unsigned int readlen;
+static char *inname;
+typedef int (*filter_t)(FILE *sin, FILE*sout);
+/** /LZWEncode filter, STDIN -> STDOUT */
+static int lzw_encode(FILE *sin, FILE *sout) {
+ TIFF tif;
+ tif.tif_sout=sout;
+ tif.tif_reading_p=0;
+#if 0
+ tif.tif_revbits_p=0;
+#endif
+ tif.tif_name=inname;
+ tif.tif_rawdata=(tidataval_t*)_TIFFmalloc(tif.tif_rawdatasize=4096); /* Imp: check */
+ tif.tif_rawcp=tif.tif_rawdata;
+ tif.tif_rawcc=0;
+ if (TIFFInitLZW(&tif) &&
+ LZWSetupEncode(&tif) &&
+ LZWPreEncode(&tif) /* for each strip */) {
+ while ((readlen=fread(readbuf, 1, sizeof(readbuf), sin))!=0) {
+ if (!LZWEncode(&tif, readbuf, readlen)) goto err;
+ /* fprintf(stderr, "readlen=%d\n", readlen); */
+ }
+ if (!LZWPostEncode(&tif)) goto err; /* for each strip */
+ LZWCleanup(&tif);
+ if (!TIFFFlushData1(&tif)) { _TIFFfree(tif.tif_rawdata); fflush(sout); return 0; }
+ fflush(sout);
+ } else { err:
+ fflush(sout);
+ LZWCleanup(&tif);
+ _TIFFfree(tif.tif_rawdata);
+ return 0;
+ }
+ return 1;
+}
+/** /LZWEncode filter, STDIN -> STDOUT */
+static int lzw_decode(FILE *sin, FILE *sout) {
+ TIFF tif;
+ /* tidataval_t *rawend0; */
+ /* char *xbuf; */
+ int got;
+ unsigned int left;
+ tif.tif_reading_p=1;
+#if 0
+ tif.tif_revbits_p=0;
+#endif
+ tif.tif_name=inname;
+ tif.tif_rawdata=(tidataval_t*)_TIFFmalloc(tif.tif_rawdatasize=4096); /* Imp: check */
+ tif.tif_rawcc=0;
+ left=0;
+ if (TIFFInitLZW(&tif) &&
+ LZWSetupDecode(&tif) &&
+ LZWPreDecode(&tif) /* for each strip */) {
+ /* vvv Dat: fread returns >=0 ! */
+ while ((readlen=left+fread(tif.tif_rawdata+left, 1, tif.tif_rawdatasize-left, sin))!=0) {
+ #if DEBUGMSG
+ fprintf(stderr, "readlen+=%d\n", readlen);
+ #endif
+ while (readlen<=3) {
+ if ((got=fread(tif.tif_rawdata+readlen, 1, tif.tif_rawdatasize-readlen, sin))==0) {
+ tif.tif_rawend=tif.tif_rawdata+readlen;
+ goto star;
+ }
+ readlen+=got;
+ }
+ tif.tif_rawend=tif.tif_rawdata+readlen-3;
+ star:
+ tif.tif_rawcp=tif.tif_rawdata;
+ #if DEBUGMSG
+ fprintf(stderr, "readlen:=%d\n", readlen);
+ #endif
+ while (1) {
+ if (-1==(got=(DecoderState(&tif)->dec_decode)(&tif, readbuf, sizeof(readbuf)))) goto err;
+ #if DEBUGMSG
+ fprintf(stderr, "OK, written: %d %d\n", got, tif.tif_rawend-tif.tif_rawcp);
+ #endif
+ if (0==got) break;
+ fwrite(readbuf, 1, got, sout);
+ }
+ left=tif.tif_rawdata+readlen-tif.tif_rawcp;
+ got=left;
+ #if DEBUGMSG
+ fprintf(stderr, "left=%d\n", left); fflush(stderr);
+ #endif
+ while (got--!=0) { tif.tif_rawdata[got]=tif.tif_rawcp[got]; }
+ }
+#if 0
+ if (!LZWPostDecode(&tif)) { LZWCleanup(&tif); return 0; } /* for each strip */
+#endif
+ LZWCleanup(&tif);
+ fflush(sout);
+ } else { err:
+ fflush(sout);
+ LZWCleanup(&tif);
+ _TIFFfree(tif.tif_rawdata);
+ return 0;
+ }
+ return 1;
+}
+#endif
+
+static int feeder(char *readbuf, unsigned readlen, TIFF *tif) {
+ /*(void)LZWPreDecode;*/ /* Imp: better avoid gcc warning... */
+ if (readlen!=0) {
+ if (!LZWEncode(tif, (tidataval_t*)readbuf, readlen)) { e1:
+ LZWCleanup(tif); e2:
+ _TIFFfree(tif->tif_rawdata);
+ return 0;
+ }
+ } else {
+ if (!LZWPostEncode(tif)) goto e1;
+ if (!TIFFFlushData1(tif)) goto e2;
+ LZWCleanup(tif);
+ }
+ return 1;
+}
+
+/** /LZWEncode filter, STDIN -> STDOUT */
+int pts_lzw_init(TIFF *tif) {
+ /* tif_sout and tif_writer are already filled */
+ tif->tif_feeder=feeder;
+ tif->tif_reading_p=0;
+#if 0
+ tif->tif_revbits_p=0;
+#endif
+ tif->tif_name="//.filter";/*inname;*/
+ tif->tif_rawdata=(tidataval_t*)_TIFFmalloc(tif->tif_rawdatasize=4096); /* Imp: check */
+ tif->tif_rawcp=tif->tif_rawdata;
+ tif->tif_rawcc=0;
+ if (TIFFInitLZW(tif) &&
+ LZWSetupEncode(tif) &&
+ LZWPreEncode(tif) /* for each strip */) {
+ return 1;
+ }
+ LZWCleanup(tif);
+ _TIFFfree(tif->tif_rawdata);
+ return 0;
+}
+
+
+#if 0
+/**** pts ****/
+int main(int argc, char **argv) {
+ filter_t filter;
+ FILE *sin, *sout;
+ inname="STDIN";
+
+ if (argc>=2 && argc<=4 && argv[1][0]=='e') {
+ filter=lzw_encode;
+ } else if (argc>=2 && argc<=4 && argv[1][0]=='d') {
+ filter=lzw_decode;
+ } else {
+ fprintf(stderr,
+ "This is PotterSoftware LZW codec v0.1, (C) pts@fazekas.hu in Late Dec 2001\n"
+ "THIS SOFTWARE COMES WITH ABSOLUTELY NO WARRANTY! USE AT YOUR OWN RISK!\n"
+ "This program is free software, covered by the GNU GPL.\n"
+ " Derived from code Copyright (c) 1988-1997 Sam Leffler\n"
+ " Derived from code Copyright (c) 1991-1997 Silicon Graphics, Inc.\n\n"
+ "Usage: %s encode|decode [INFILE] [OUTFILE]\n\n"
+ "Unspecified file names mean STDIN or STDOUT.\n"
+ "Encoding is /LZWEncode compression, decoding is /LZWDecode uncompression.\n\n"
+ "Note that the LZW compression (but not uncompression) is patented by\n"
+ "Unisys (patent number #4,558,302), so use this program at your own legal\n"
+ "risk!\n"
+ ,argv[0]);
+ return 2;
+ }
+ if (argc>=3) sin= fopen(inname=argv[2],"rb");
+ else sin= fdopen(0, "rb");
+ if (sin==0) {
+ fprintf(stderr, "%s: error opening infile\n", argv[0]);
+ return 3;
+ }
+ if (argc>=4) sout=fopen(inname=argv[3],"wb");
+ else sout=fdopen(1, "wb");
+ if (sout==0) {
+ fprintf(stderr, "%s: error opening outfile\n", argv[0]);
+ return 4;
+ }
+ return !filter(sin, sout);
+ /* fclose(sout); fclose(sin); */
+}
+#endif
diff --git a/graphics/sam2p/pts_lzw.h b/graphics/sam2p/pts_lzw.h
new file mode 100644
index 0000000000..4e132b453f
--- /dev/null
+++ b/graphics/sam2p/pts_lzw.h
@@ -0,0 +1,59 @@
+/*
+ * pts_lzw.h -- a compact LZW compressor (not uncompressor) interface
+ * compiled by pts@fazekas.hu at Mon Mar 4 00:31:20 CET 2002
+ */
+
+#ifndef PTS_LZW_H
+#define PTS_LZW_H 1
+
+#ifdef __GNUC__
+#ifndef __clang__
+#pragma interface
+#endif
+#endif
+
+#include "config2.h" /* PTS_const */
+
+/**** pts ****/
+#ifndef ___
+#if (defined(__STDC__) || defined(__cplusplus)) && !defined(NO_PROTO)
+# define _(args) args
+# define OF(args) args
+# define ___(arg2s,arg1s,argafter) arg2s /* Dat: no direct comma allowed in args :-( */
+#else
+# define _(args) ()
+# define OF(args) ()
+# define ___(arg2s,arg1s,argafter) arg1s argafter /* Dat: no direct comma allowed in args :-( */
+#endif
+#endif
+typedef char tbool_t;
+typedef unsigned char tidataval_t; /* internal image data value type */
+typedef unsigned int tsize_t; /* i/o size in bytes */
+typedef int (*tiwriter_t) OF((char *block, unsigned len, void *zfile));
+struct pts_lzw_state;
+struct pts_lzw_state {
+ /*FILE*/void* tif_sout; /**** pts ****/ /* for encode */
+ tiwriter_t tif_writer;
+ int (*tif_feeder)(char *readbuf, unsigned readlen, struct pts_lzw_state *tif);
+#if 0
+ tbool_t tif_revbits_p; /**** pts ****/
+#endif
+ tbool_t tif_reading_p; /**** pts ****/
+ char PTS_const* tif_name; /* name of open file, used for debugging */
+/* compression scheme hooks */
+ tidataval_t* tif_data; /* compression scheme private data */
+/* input/output buffering */
+ tidataval_t* tif_rawend; /**** pts ****/
+ tidataval_t* tif_rawdata; /* raw data buffer */
+ tsize_t tif_rawdatasize;/* # of bytes in raw data buffer */
+ tidataval_t* tif_rawcp; /* current spot in raw buffer */
+ tsize_t tif_rawcc; /* bytes unread from raw buffer */
+};
+
+extern
+#ifdef __cplusplus
+"C"
+#endif
+int pts_lzw_init OF((struct pts_lzw_state*));
+
+#endif
diff --git a/graphics/sam2p/resource.h b/graphics/sam2p/resource.h
new file mode 100644
index 0000000000..2c0fb15a53
--- /dev/null
+++ b/graphics/sam2p/resource.h
@@ -0,0 +1,44 @@
+//{{NO_DEPENDENCIES}}
+// Microsoft Developer Studio generated include file.
+// Used by vcsam2p.rc
+//
+#define IDC_MYICON 2
+#define IDOK2 3
+#define IDD_VCSAM2P_DIALOG 102
+#define IDD_ABOUTBOX 103
+#define IDS_APP_TITLE 103
+#define IDM_ABOUT 104
+#define IDM_EXIT 105
+#define IDS_HELLO 106
+#define IDI_VCSAM2P 107
+#define IDI_SMALL 108
+#define IDC_VCSAM2P 109
+#define IDR_MAINFRAME 128
+#define IDI_SAM2P16 131
+#define IDI_SAM2P32 132
+#define IDD_RUN 133
+#define IDC_PRODUCT 1000
+#define IDC_EDIT1 1001
+#define IDC_ELOG 1001
+#define IDC_INFO 1001
+#define IDC_EDIT2 1002
+#define IDM_OPEN 32771
+#define IDM_SAVE 32772
+#define IDM_WEBSITE 32773
+#define IDM_SAVE_AS 32774
+#define IDM_NEW 32775
+#define IDM_PARAMETERS 32776
+#define IDC_STATIC -1
+#define IDC_COPYRIGHT -1
+
+// Next default values for new objects
+//
+#ifdef APSTUDIO_INVOKED
+#ifndef APSTUDIO_READONLY_SYMBOLS
+#define _APS_3D_CONTROLS 1
+#define _APS_NEXT_RESOURCE_VALUE 134
+#define _APS_NEXT_COMMAND_VALUE 32777
+#define _APS_NEXT_CONTROL_VALUE 1003
+#define _APS_NEXT_SYMED_VALUE 110
+#endif
+#endif
diff --git a/graphics/sam2p/rule.cpp b/graphics/sam2p/rule.cpp
new file mode 100644
index 0000000000..418c3de7d2
--- /dev/null
+++ b/graphics/sam2p/rule.cpp
@@ -0,0 +1,1104 @@
+/*
+ * rule.cpp -- generic Rule handling
+ * by pts@fazekas.hu at Fri Mar 15 21:13:47 CET 2002
+ */
+
+#ifdef __GNUC__
+#ifndef __clang__
+#pragma implementation
+#endif
+#endif
+
+#include "rule.hpp"
+#include "error.hpp"
+#include <string.h> /* strlen() */
+
+bool Rule::Cache::isPDF() const {
+ return 80<=FileFormat && FileFormat<100;
+}
+bool Rule::Cache::isPDFB() const {
+ return 90<=FileFormat && FileFormat<100;
+}
+bool Rule::Cache::isIndexed() const {
+ return SampleFormat==Image::SF_Indexed1
+ || SampleFormat==Image::SF_Indexed2
+ || SampleFormat==Image::SF_Indexed4
+ || SampleFormat==Image::SF_Indexed8;
+}
+bool Rule::Cache::isTransparentM() const {
+ return SampleFormat==Image::SF_Mask
+ || SampleFormat==Image::SF_Transparent2
+ || SampleFormat==Image::SF_Transparent4
+ || SampleFormat==Image::SF_Transparent8;
+}
+bool Rule::Cache::isOneBit() const {
+ return SampleFormat==Image::SF_Mask
+ || SampleFormat==Image::SF_Indexed1
+ || SampleFormat==Image::SF_Gray1;
+}
+#if 0
+bool Rule::Cache::is8() const {
+ return SampleFormat==Image::SF_Indexed1
+ || SampleFormat==Image::SF_Indexed2
+ || SampleFormat==Image::SF_Indexed4
+ || SampleFormat==Image::SF_Indexed8;
+}
+#endif
+bool Rule::Cache::isGray() const {
+ return SampleFormat==Image::SF_Gray1
+ || SampleFormat==Image::SF_Gray2
+ || SampleFormat==Image::SF_Gray4
+ || SampleFormat==Image::SF_Gray8;
+}
+bool Rule::Cache::isRGB() const {
+ return SampleFormat==Image::SF_Rgb1
+ || SampleFormat==Image::SF_Rgb2
+ || SampleFormat==Image::SF_Rgb4
+ || SampleFormat==Image::SF_Rgb8;
+}
+bool Rule::Cache::isBinSB() const {
+ return TransferEncoding==TE_Binary
+ || TransferEncoding==TE_MSBfirst
+ || TransferEncoding==TE_LSBfirst;
+}
+bool Rule::Cache::isPS() const {
+ return FileFormat>=100;
+}
+bool Rule::Cache::isPSL2() const {
+ return FileFormat>=120;
+}
+bool Rule::Cache::isPSL3() const {
+ return FileFormat>=130;
+}
+bool Rule::Cache::hasPredictor() const {
+ return Predictor!=PR_None;
+}
+bool Rule::Cache::isDCTE() const {
+ /* Dat: _not_ CO_JAI */
+ return Compression==CO_DCT || Compression==CO_IJG;
+}
+bool Rule::Cache::isZIPOK() const {
+ return Compression!=CO_ZIP ||
+ ( FileFormat!=FF_PSL1 && FileFormat!=FF_PSLC && FileFormat!=FF_PSL2
+ && FileFormat!=FF_PDF10 && FileFormat!=FF_PDFB10
+ );
+}
+
+static MiniPS::Dict *y_FileFormat=(MiniPS::Dict*)NULLP,
+ *y_SampleFormat, *y_TransferEncoding,
+ *y_Compression, *y_Scale;
+static class ValueDeleter {
+ public:
+ ~ValueDeleter() {
+ MiniPS::delete0((MiniPS::VALUE)y_FileFormat);
+ MiniPS::delete0((MiniPS::VALUE)y_SampleFormat);
+ MiniPS::delete0((MiniPS::VALUE)y_TransferEncoding);
+ MiniPS::delete0((MiniPS::VALUE)y_Compression);
+ MiniPS::delete0((MiniPS::VALUE)y_Scale);
+ }
+} value_deleter;
+
+static const slen_t SampleFormat_MAXLEN=32;
+static void init_dicts() {
+ register MiniPS::Dict*y;
+
+ /** TODO: Make this thread-safe. */
+ if (y_FileFormat!=NULLP) return;
+
+ y=y_FileFormat=new MiniPS::Dict();
+ y->put("/PSL1", MiniPS::Qinteger(Rule::Cache::FF_PSL1));
+ y->put("/PSLC", MiniPS::Qinteger(Rule::Cache::FF_PSLC));
+ y->put("/PSL2", MiniPS::Qinteger(Rule::Cache::FF_PSL2));
+ y->put("/PSL3", MiniPS::Qinteger(Rule::Cache::FF_PSL3));
+ y->put("/PDFB1.0",MiniPS::Qinteger(Rule::Cache::FF_PDFB10));
+ y->put("/PDFB1.2",MiniPS::Qinteger(Rule::Cache::FF_PDFB12));
+ y->put("/PDF1.0", MiniPS::Qinteger(Rule::Cache::FF_PDF10));
+ y->put("/PDF1.2", MiniPS::Qinteger(Rule::Cache::FF_PDF12));
+ y->put("/GIF89a", MiniPS::Qinteger(Rule::Cache::FF_GIF89a));
+ y->put("/GIF", MiniPS::Qinteger(Rule::Cache::FF_GIF89a));
+ y->put("/Empty", MiniPS::Qinteger(Rule::Cache::FF_Empty));
+ y->put("/Meta", MiniPS::Qinteger(Rule::Cache::FF_Meta));
+ y->put("/PNM", MiniPS::Qinteger(Rule::Cache::FF_PNM));
+ y->put("/PAM", MiniPS::Qinteger(Rule::Cache::FF_PAM));
+ y->put("/PIP", MiniPS::Qinteger(Rule::Cache::FF_PIP));
+ y->put("/JPEG", MiniPS::Qinteger(Rule::Cache::FF_JPEG));
+ y->put("/JPG", MiniPS::Qinteger(Rule::Cache::FF_JPEG));
+ y->put("/TIFF", MiniPS::Qinteger(Rule::Cache::FF_TIFF));
+ y->put("/TIF", MiniPS::Qinteger(Rule::Cache::FF_TIFF));
+ y->put("/PNG", MiniPS::Qinteger(Rule::Cache::FF_PNG));
+ y->put("/XPM", MiniPS::Qinteger(Rule::Cache::FF_XPM));
+ y->put("/BMP", MiniPS::Qinteger(Rule::Cache::FF_BMP));
+ y->put("/XWD", MiniPS::Qinteger(Rule::Cache::FF_XWD));
+ y->put("/X11", MiniPS::Qinteger(Rule::Cache::FF_X11));
+
+ /* vvv strlen must be shorter then SampleFormat_MAXLEN */
+ y=y_SampleFormat=new MiniPS::Dict();
+ y->put("/Opaque", MiniPS::Qinteger(Image::SF_Opaque));
+ y->put("/Transparent", MiniPS::Qinteger(Image::SF_Transparent));
+ y->put("/Transparent2", MiniPS::Qinteger(Image::SF_Transparent2));
+ y->put("/Transparent4", MiniPS::Qinteger(Image::SF_Transparent4));
+ y->put("/Transparent8", MiniPS::Qinteger(Image::SF_Transparent8));
+ y->put("/Gray1", MiniPS::Qinteger(Image::SF_Gray1));
+ y->put("/Gray2", MiniPS::Qinteger(Image::SF_Gray2));
+ y->put("/Gray4", MiniPS::Qinteger(Image::SF_Gray4));
+ y->put("/Gray8", MiniPS::Qinteger(Image::SF_Gray8));
+ y->put("/Indexed1", MiniPS::Qinteger(Image::SF_Indexed1));
+ y->put("/Indexed2", MiniPS::Qinteger(Image::SF_Indexed2));
+ y->put("/Indexed4", MiniPS::Qinteger(Image::SF_Indexed4));
+ y->put("/Indexed8", MiniPS::Qinteger(Image::SF_Indexed8));
+ y->put("/Mask", MiniPS::Qinteger(Image::SF_Mask));
+ y->put("/Rgb1", MiniPS::Qinteger(Image::SF_Rgb1)); /* recommended */
+ y->put("/Rgb2", MiniPS::Qinteger(Image::SF_Rgb2));
+ y->put("/Rgb4", MiniPS::Qinteger(Image::SF_Rgb4));
+ y->put("/Rgb8", MiniPS::Qinteger(Image::SF_Rgb8));
+ y->put("/RGB1", MiniPS::Qinteger(Image::SF_Rgb1)); /* obsolete */
+ y->put("/RGB2", MiniPS::Qinteger(Image::SF_Rgb2));
+ y->put("/RGB4", MiniPS::Qinteger(Image::SF_Rgb4));
+ y->put("/RGB8", MiniPS::Qinteger(Image::SF_Rgb8));
+ y->put("/Asis", MiniPS::Qinteger(Image::SF_Asis));
+ y->put("/Bbox", MiniPS::Qinteger(Image::SF_Bbox));
+
+ y=y_TransferEncoding=new MiniPS::Dict();
+ y->put("/Binary", MiniPS::Qinteger(Rule::Cache::TE_Binary));
+ y->put("/ASCII", MiniPS::Qinteger(Rule::Cache::TE_ASCII));
+ y->put("/Hex", MiniPS::Qinteger(Rule::Cache::TE_Hex)); /* recommended */
+ y->put("/AHx", MiniPS::Qinteger(Rule::Cache::TE_Hex));
+ y->put("/ASCIIHex", MiniPS::Qinteger(Rule::Cache::TE_Hex));
+ y->put("/A85", MiniPS::Qinteger(Rule::Cache::TE_A85)); /* recommended */
+ y->put("/ASCII85", MiniPS::Qinteger(Rule::Cache::TE_A85));
+ y->put("/MSBfirst", MiniPS::Qinteger(Rule::Cache::TE_MSBfirst));
+ y->put("/LSBfirst", MiniPS::Qinteger(Rule::Cache::TE_LSBfirst));
+
+ y=y_Compression=new MiniPS::Dict();
+ y->put("/ ", MiniPS::Qinteger(Rule::Cache::CO_None)); /* default */
+ y->put("/None", MiniPS::Qinteger(Rule::Cache::CO_None)); /* recommended */
+ y->put("/LZW", MiniPS::Qinteger(Rule::Cache::CO_LZW)); /* recommended */
+ y->put("/ZIP", MiniPS::Qinteger(Rule::Cache::CO_ZIP)); /* recommended */
+ y->put("/Flate", MiniPS::Qinteger(Rule::Cache::CO_ZIP));
+ y->put("/Fl", MiniPS::Qinteger(Rule::Cache::CO_ZIP));
+ y->put("/RLE", MiniPS::Qinteger(Rule::Cache::CO_RLE)); /* recommended */
+ y->put("/RunLength", MiniPS::Qinteger(Rule::Cache::CO_RLE));
+ y->put("/RunLengthEncoded", MiniPS::Qinteger(Rule::Cache::CO_RLE));
+ y->put("/RL", MiniPS::Qinteger(Rule::Cache::CO_RLE));
+ y->put("/PackBits", MiniPS::Qinteger(Rule::Cache::CO_RLE));
+ y->put("/Fax", MiniPS::Qinteger(Rule::Cache::CO_Fax)); /* recommended */
+ y->put("/CCITTFax", MiniPS::Qinteger(Rule::Cache::CO_Fax));
+ y->put("/CCF", MiniPS::Qinteger(Rule::Cache::CO_Fax));
+ y->put("/DCT", MiniPS::Qinteger(Rule::Cache::CO_DCT)); /* recommended */
+ y->put("/JPEG",MiniPS::Qinteger(Rule::Cache::CO_IJG)); /* changed at Sun Jun 23 17:06:34 CEST 2002 */
+ y->put("/JPG", MiniPS::Qinteger(Rule::Cache::CO_IJG)); /* changed at Sun Jun 23 17:06:34 CEST 2002 */
+ y->put("/JFIF",MiniPS::Qinteger(Rule::Cache::CO_IJG)); /* changed at Sun Jun 23 17:06:34 CEST 2002 */
+ y->put("/IJG", MiniPS::Qinteger(Rule::Cache::CO_IJG)); /* recommended */
+ y->put("/JAI", MiniPS::Qinteger(Rule::Cache::CO_JAI)); /* recommended */
+
+ y=y_Scale=new MiniPS::Dict();
+ y->put("/ ", MiniPS::Qinteger(Rule::CacheHints::SC_None)); /* default */
+ y->put("/None", MiniPS::Qinteger(Rule::CacheHints::SC_None));
+ y->put("/OK", MiniPS::Qinteger(Rule::CacheHints::SC_OK));
+ y->put("/RotateOK",MiniPS::Qinteger(Rule::CacheHints::SC_RotateOK));
+}
+
+Image::sf_t Rule::Cache::parseSampleFormat(char const*s, slen_t slen) {
+ /* Tue Jul 2 13:48:12 CEST 2002 */
+ #if 0 /* BUGFIX for g++-3.4 (needs symbols __cxa_guard_acquire, __cxa_guard_release) */
+ static char rule_dummy=(init_dicts(),0); /* call once per process */
+ (void)rule_dummy;
+ #else
+ if (y_FileFormat==NULLP) init_dicts();
+ #endif
+ while (slen!=0 && s[0]=='/') { s++; slen--; }
+ if (slen<=0 || slen>=SampleFormat_MAXLEN) return Image::SF_max;
+ char buf[SampleFormat_MAXLEN];
+ GenBuffer::tolower_memcpy(buf, s, slen);
+ if (buf[0]>='a' && buf[0]<='z') buf[0]+='A'-'a'; /* capitalize 1st letter */
+ MiniPS::VALUE v=y_SampleFormat->get(buf, slen);
+ return (Image::sf_t) (v==MiniPS::Qundef ? Image::SF_max : MiniPS::int2ii(v));
+}
+
+char const* Rule::Cache::dumpFileFormat(ff_t FileFormat, co_t Compression) {
+ switch (FileFormat) {
+ case FF_eps: return Compression==CO_ZIP ? "PSL3" : "PSL2";
+ case FF_pdf: return Compression==CO_ZIP ? "PDF1.2" : "PDF1.0";
+ case FF_pdfb: return Compression==CO_ZIP ? "PDFB1.2" : "PDFB1.0";
+ case FF_PSL1: return "PSL1";
+ case FF_PSLC: return "PSLC";
+ case FF_PSL2: return "PSL2";
+ case FF_PSL3: return "PSL3";
+ case FF_PDFB10:return "PDFB1.0";
+ case FF_PDFB12:return "PDFB1.2";
+ case FF_PDF10: return "PDF1.0";
+ case FF_PDF12: return "PDF1.2";
+ case FF_GIF89a:return "GIF89a";
+ case FF_PNM: return "PNM";
+ case FF_PAM: return "PAM";
+ case FF_PIP: return "PIP";
+ case FF_Empty: return "Empty";
+ case FF_Meta: return "Meta";
+ case FF_JPEG: return "JPEG";
+ case FF_TIFF: return "TIFF";
+ case FF_PNG: return "PNG";
+ case FF_XPM: return "XPM";
+ case FF_BMP: return "BMP";
+ case FF_XWD: return "XWD";
+ case FF_X11: return "X11";
+ }
+ return (char const*)NULLP;
+}
+char const* Rule::Cache::dumpTransferEncoding(te_t TransferEncoding) {
+ switch (TransferEncoding) {
+ case TE_Binary: return "Binary";
+ case TE_ASCII: return "ASCII";
+ case TE_Hex: return "Hex";
+ case TE_A85: return "A85";
+ case TE_MSBfirst:return "MSBfirst";
+ case TE_LSBfirst:return "LSBfirst";
+ }
+ return (char const*)NULLP;
+}
+char const* Rule::Cache::dumpSampleFormat(Image::sf_t SampleFormat) {
+ switch (SampleFormat) {
+ case Image::SF_Opaque: return "Opaque";
+ case Image::SF_Transparent: return "Transparent";
+ case Image::SF_Gray1: return "Gray1";
+ case Image::SF_Indexed1: return "Indexed1";
+ case Image::SF_Mask: return "Mask";
+ case Image::SF_Transparent2: return "Transparent2";
+ case Image::SF_Gray2: return "Gray2";
+ case Image::SF_Indexed2: return "Indexed2";
+ case Image::SF_Transparent4: return "Transparent4";
+ case Image::SF_Rgb1: return "Rgb1";
+ case Image::SF_Gray4: return "Gray4";
+ case Image::SF_Indexed4: return "Indexed4";
+ case Image::SF_Transparent8: return "Transparent8";
+ case Image::SF_Rgb2: return "Rgb2";
+ case Image::SF_Gray8: return "Gray8";
+ case Image::SF_Indexed8: return "Indexed8";
+ case Image::SF_Rgb4: return "Rgb4";
+ case Image::SF_Rgb8: return "Rgb8";
+ case Image::SF_Asis: return "Asis";
+ case Image::SF_Bbox: return "Bbox";
+ }
+ return (char const*)NULLP;
+}
+char const* Rule::Cache::dumpCompression(co_t Compression) {
+ switch (Compression) {
+ case CO_None:return "None";
+ case CO_LZW: return "LZW";
+ case CO_ZIP: return "ZIP";
+ case CO_RLE: return "RLE";
+ case CO_Fax: return "Fax";
+ case CO_DCT: return "DCT";
+ case CO_IJG: return "IJG";
+ case CO_JAI: return "JAI";
+ }
+ return (char const*)NULLP;
+}
+
+char const* Rule::CacheHints::dumpScale(sc_t Scale) {
+ switch (Scale) {
+ case SC_None: return "None";
+ case SC_OK: return "OK";
+ case SC_RotateOK:return "RotateOK";
+ }
+ return (char const*)NULLP;
+}
+
+/* Checks and recovers Predictor. Called by scanf_dict.
+ * @return Qundef if param invalid
+ * Qinteger(1) if param==Qundef
+ * valid Qinteger otherwise
+ */
+static MiniPS::VALUE better_predictor(MiniPS::VALUE v) {
+ return v==MiniPS::Qundef ? MiniPS::Qinteger(1) /* PR_None */
+ : v==MiniPS::Qinteger(1) || v==MiniPS::Qinteger(2) ||
+ v==MiniPS::Qinteger(45) || v==MiniPS::Qinteger(55) ||
+ ((v&1)!=0 && v>=MiniPS::Qinteger(10) && v<=MiniPS::Qinteger(15)) ? v
+ : MiniPS::Qundef;
+}
+static MiniPS::VALUE better_xColors(MiniPS::VALUE v) {
+ return v==MiniPS::Qundef ? MiniPS::Qinteger(0)
+ : ((v&1)!=0 && v>=MiniPS::Qinteger(1) && v<=MiniPS::Qinteger(4)) ? v
+ : MiniPS::Qundef;
+}
+static MiniPS::VALUE better_predictorBPC(MiniPS::VALUE v) {
+ return v==MiniPS::Qundef ? MiniPS::Qinteger(0)
+ : v==MiniPS::Qinteger(1) || v==MiniPS::Qinteger(2) ||
+ v==MiniPS::Qinteger(4) || v==MiniPS::Qinteger(8) ? v
+ : MiniPS::Qundef;
+}
+static MiniPS::VALUE better_effort(MiniPS::VALUE v) {
+ return v==MiniPS::Qundef ? MiniPS::Qinteger(-1)
+ : ((v&1)!=0 && v>=MiniPS::Qinteger(-1) && v<=MiniPS::Qinteger(9)) ? v
+ : MiniPS::Qundef;
+}
+static MiniPS::VALUE better_k(MiniPS::VALUE v) {
+ return v==MiniPS::Qundef ? MiniPS::Qinteger(0)
+ : ((v&1)!=0 && v>=MiniPS::Qinteger(-2)) ? v /* -2 means: positive value marking the image height */
+ : MiniPS::Qundef;
+}
+static MiniPS::VALUE better_quality(MiniPS::VALUE v) {
+ return v==MiniPS::Qundef ? MiniPS::Qinteger(75)
+ : ((v&1)!=0 && v>=MiniPS::Qinteger(0) && v<=MiniPS::Qinteger(100)) ? v
+ : MiniPS::Qundef;
+}
+static MiniPS::VALUE better_colorTransform(MiniPS::VALUE v) {
+ return v==MiniPS::Qundef ? MiniPS::Qinteger(3)
+ : ((v&1)!=0 && v>=MiniPS::Qinteger(0) && v<=MiniPS::Qinteger(3)) ? v
+ : MiniPS::Qundef;
+}
+
+void Rule::OutputRule::fromDict(MiniPS::VALUE dict_) {
+ #if 0 /* BUGFIX for g++-3.4 (needs symbols __cxa_guard_acquire, __cxa_guard_release) */
+ static char rule_dummy=(init_dicts(),0); /* call once per process */
+ (void)rule_dummy;
+ #else
+ if (y_FileFormat==NULLP) init_dicts();
+ #endif
+ MiniPS::VALUE dummy; (void)dummy;
+ MiniPS::VALUE FileFormat, SampleFormat, WarningOK, TransferEncoding,
+ Compression, Predictor, Transparent;
+ MiniPS::VALUE PredictorColumns, PredictorColors, PredictorBPC, Effort, K,
+ RecordSize, Quality, ColorTransform, TransferCPL,
+ EncoderRows, EncoderColumns, EncoderBPL, EncoderColors, DCT, Scale;
+
+ MiniPS::scanf_dict(dict_, /*show_warnings:*/true,
+ "FileFormat", MiniPS::S_SENUM, y_FileFormat, &FileFormat,
+ "SampleFormat", MiniPS::S_SENUM, y_SampleFormat, &SampleFormat,
+ "WarningOK", MiniPS::T_BOOLEAN, MiniPS::Qtrue, &WarningOK,
+ "TransferEncoding",MiniPS::S_SENUM, y_TransferEncoding, &TransferEncoding,
+ "Compression", MiniPS::S_SENUM, y_Compression, &Compression,
+ "Predictor", MiniPS::S_FUNC, better_predictor, &Predictor,
+ "Transparent", MiniPS::S_RGBSTR, MiniPS::Qnull, &Transparent, /* force an RGB color transparent */
+ "Hints", MiniPS::T_DICT, MiniPS::Qnull, &dictHints,
+ NULLP
+ );
+ dict=(MiniPS::Dict*)dict_;
+ cache.FileFormat=(Rule::Cache::ff_t)MiniPS::int2ii(FileFormat);
+ cache.SampleFormat=(Image::sf_t)MiniPS::int2ii(SampleFormat);
+ cache.WarningOK=(Rule::Cache::ff_t)WarningOK==MiniPS::Qtrue;
+ cache.TransferEncoding=(Rule::Cache::te_t)MiniPS::int2ii(TransferEncoding);
+ cache.Compression=(Rule::Cache::co_t)MiniPS::int2ii(Compression);
+ cache.Predictor=(Rule::Cache::pr_t)MiniPS::int2ii(Predictor);
+ cache.Transparent=0x1000000UL; /* No extra transparency */
+ if (Transparent!=MiniPS::Qnull) {
+ unsigned char const*p=(unsigned char const*)(MiniPS::RSTRING(Transparent)->begin_());
+ cache.Transparent=(p[0]<<16)+(p[1]<<8)+p[2];
+ }
+ //MiniPS::dump(Predictor);
+ // fprintf(stderr,"cpred=%u\n", cache.Predictor);
+
+ if ((MiniPS::VALUE)dictHints==MiniPS::Qnull) dict->put("/Hints", (MiniPS::VALUE)(dictHints=new MiniPS::Dict()));
+ MiniPS::scanf_dict((MiniPS::VALUE)dictHints, /*show_warnings:*/true,
+ "EncoderBPL", MiniPS::S_PINTEGER,MiniPS::Qinteger(0), &EncoderBPL,
+ "EncoderColumns", MiniPS::S_PINTEGER,MiniPS::Qinteger(0), &EncoderColumns,
+ "EncoderRows", MiniPS::S_PINTEGER,MiniPS::Qinteger(0), &EncoderRows,
+ "EncoderColors", MiniPS::S_FUNC, better_xColors, &EncoderColors,
+ "PredictorColumns",MiniPS::S_PINTEGER,MiniPS::Qinteger(0), &PredictorColumns,
+ "PredictorColors", MiniPS::S_FUNC, better_xColors, &PredictorColors,
+ "PredictorBPC", MiniPS::S_FUNC, better_predictorBPC, &PredictorBPC,
+ "Effort", MiniPS::S_FUNC, better_effort, &Effort,
+ "RecordSize", MiniPS::S_UINTEGER,MiniPS::Qinteger(0), &RecordSize,
+ "K", MiniPS::S_FUNC, better_k, &K,
+ "Quality", MiniPS::S_FUNC, better_quality, &Quality,
+ "ColorTransform", MiniPS::S_FUNC, better_colorTransform, &ColorTransform,
+ "TransferCPL", MiniPS::S_PINTEGER,MiniPS::Qinteger(78), &TransferCPL,
+ "DCT", MiniPS::T_DICT, MiniPS::Qnull, &DCT,
+ "Scale", MiniPS::S_SENUM, y_Scale, &Scale,
+ "ImageDPI", MiniPS::S_NUMBER, MiniPS::Qinteger(72), &cacheHints.ImageDPI,
+ "TopMargin", MiniPS::S_NUMBER, MiniPS::Qinteger(0), &cacheHints.TopMargin,
+ "BottomMargin", MiniPS::S_NUMBER, MiniPS::Qinteger(0), &cacheHints.BottomMargin,
+ "LeftMargin", MiniPS::S_NUMBER, MiniPS::Qinteger(0), &cacheHints.LeftMargin,
+ "RightMargin", MiniPS::S_NUMBER, MiniPS::Qinteger(0), &cacheHints.RightMargin,
+ "LowerMargin", MiniPS::S_NUMBER, MiniPS::Qinteger(0), &cacheHints.LowerMargin,
+
+ "Comment", MiniPS::T_STRING, MiniPS::Qnull, &cacheHints.Comment,
+ "Title", MiniPS::T_STRING, MiniPS::Qnull, &cacheHints.Title,
+ "Subject", MiniPS::T_STRING, MiniPS::Qnull, &cacheHints.Subject,
+ "Author", MiniPS::T_STRING, MiniPS::Qnull, &cacheHints.Author,
+ "Creator", MiniPS::T_STRING, MiniPS::Qnull, &cacheHints.Creator,
+ "Producer", MiniPS::T_STRING, MiniPS::Qnull, &cacheHints.Producer,
+ "Created", MiniPS::T_STRING, MiniPS::Qnull, &cacheHints.Created,
+ "Produced", MiniPS::T_STRING, MiniPS::Qnull, &cacheHints.Produced,
+#if 0
+ /* vvv parameters for /DCTEncode. Currently ignored. Obsoleted by /DCT */
+ "Colors", MiniPS::S_ANY, MiniPS::Qnull, &dummy,
+ "HSamples", MiniPS::S_ANY, MiniPS::Qnull, &dummy,
+ "VSamples", MiniPS::S_ANY, MiniPS::Qnull, &dummy,
+ "QuantTables", MiniPS::S_ANY, MiniPS::Qnull, &dummy,
+ "QFactor", MiniPS::S_ANY, MiniPS::Qnull, &dummy,
+ "HuffTables", MiniPS::S_ANY, MiniPS::Qnull, &dummy,
+#endif
+ NULLP
+ );
+ if (DCT==MiniPS::Qnull) dict->put("/DCT", DCT=(MiniPS::VALUE)new MiniPS::Dict());
+ // cacheHints.DCT=(DCT==MiniPS::Qnull)? new MiniPS::Dict() : MiniPS::RDICT(DCT);
+ if (cache.isPS()) {
+ MiniPS::setDumpPS(cacheHints.TopMargin, true);
+ MiniPS::setDumpPS(cacheHints.BottomMargin, true);
+ MiniPS::setDumpPS(cacheHints.LeftMargin, true);
+ MiniPS::setDumpPS(cacheHints.RightMargin, true);
+ MiniPS::setDumpPS(cacheHints.LowerMargin, true);
+ }
+ cacheHints.DCT=MiniPS::RDICT(DCT);
+ cacheHints.EncoderColumns=MiniPS::int2ii(EncoderColumns);
+ cacheHints.EncoderBPL=MiniPS::int2ii(EncoderBPL);
+ cacheHints.EncoderColors=MiniPS::int2ii(EncoderColors);
+ cacheHints.EncoderRows=MiniPS::int2ii(EncoderRows);
+ cacheHints.PredictorColumns=MiniPS::int2ii(PredictorColumns);
+ cacheHints.PredictorColors=MiniPS::int2ii(PredictorColors);
+ cacheHints.PredictorBPC=MiniPS::int2ii(PredictorBPC);
+ cacheHints.Effort=MiniPS::int2ii(Effort);
+ cacheHints.RecordSize=MiniPS::int2ii(RecordSize);
+ cacheHints.K=MiniPS::int2ii(K);
+ cacheHints.Quality=MiniPS::int2ii(Quality);
+ cacheHints.ColorTransform=MiniPS::int2ii(ColorTransform);
+ cacheHints.TransferCPL=MiniPS::int2ii(TransferCPL);
+ cacheHints.Scale=(Rule::CacheHints::sc_t)MiniPS::int2ii(Scale);
+ /* fprintf(stderr, "scaled=%g\n", (char*)MiniPS::scale(ImageDPI,1)); */
+}
+
+void Rule::OutputRule::doSampleFormat(Image::SampledInfo *info, bool separatep) {
+ /* Dat: called from appliers.cpp:out_*_work(); the sample format is final */
+ bool separatep2=
+ separatep &&
+ ( cache.SampleFormat==Image::SF_Transparent2
+ || cache.SampleFormat==Image::SF_Transparent4
+ || cache.SampleFormat==Image::SF_Transparent8);
+ /* vvv simplifier added at Sat Jun 15 13:59:40 CEST 2002 */
+ if (separatep2) cache.SampleFormat=Image::SF_Transparent8;
+ if (!info->setSampleFormat(cache.SampleFormat, cache.WarningOK, /*TryOnly*/false, cache.Transparent))
+ Error::sev(Error::EERROR) << "doSampleFormat: cannot set desired SampleFormat" << (Error*)0;
+ Image::Sampled *img=info->getImg();
+ slen_t n=1;
+ if (separatep2) {
+ info->separate();
+ img=info->getImgs()[0];/*NULLP OK*/;
+ n=info->getNncols();
+ }
+ if (img!=NULLP) {
+ if (0==cacheHints.EncoderBPL) cacheHints.EncoderBPL=(slen_t)img->getWd()*img->getCpp()*img->getBpc();
+ if (0==cacheHints.EncoderColumns) cacheHints.EncoderColumns=img->getWd();
+ if (0==cacheHints.EncoderColors) cacheHints.EncoderColors=img->getCpp();
+ if (0==cacheHints.EncoderRows) cacheHints.EncoderRows=img->getHt()*n;
+ if (0==cacheHints.PredictorColumns) cacheHints.PredictorColumns=img->getWd();
+ if (0==cacheHints.PredictorColors) cacheHints.PredictorColors=img->getCpp();
+ if (0==cacheHints.PredictorBPC) cacheHints.PredictorBPC=img->getBpc();
+ if (-2==cacheHints.K) cacheHints.K=img->getHt()*n;
+ }
+}
+
+static char const*getDecode(Rule::Cache::co_t Compression) {
+ return (Compression==Rule::Cache::CO_LZW ? "/LZWDecode"
+ :Compression==Rule::Cache::CO_Fax ? "/CCITTFaxDecode"
+ :Compression==Rule::Cache::CO_ZIP ? "/FlateDecode"
+ :Compression==Rule::Cache::CO_RLE ? "/RunLengthDecode"
+ :Compression==Rule::Cache::CO_DCT ? "/DCTDecode"
+ :Compression==Rule::Cache::CO_IJG ? "/DCTDecode"
+ :Compression==Rule::Cache::CO_JAI ? "/DCTDecode"
+ :"");
+}
+
+/** For PDF BI inline images */
+static char const*getBIDecode(Rule::Cache::co_t Compression) {
+ return (Compression==Rule::Cache::CO_LZW ? "/LZW"
+ :Compression==Rule::Cache::CO_Fax ? "/CCF"
+ :Compression==Rule::Cache::CO_ZIP ? "/Fl"
+ :Compression==Rule::Cache::CO_RLE ? "/RL"
+ :Compression==Rule::Cache::CO_DCT ? "/DCT"
+ :Compression==Rule::Cache::CO_IJG ? "/DCT"
+ :Compression==Rule::Cache::CO_JAI ? "/DCT"
+ :"");
+}
+
+void Rule::OutputRule::appendDecoderSpec(GenBuffer::Writable &out) const {
+ assert(cacheHints.PredictorBPC!=0 && "doSampleFormat already called");
+ bool hps=hasPredictorSpec();
+ if (cache.isPDF()) {
+ /* Dat: also implies appendTransferSpec() -- this is true only for PDF */
+ if (!cache.isPDFB()) {
+ if (cache.Compression==cache.CO_None) {
+ if (cache.TransferEncoding==cache.TE_Hex) out << "/Filter/ASCIIHexDecode";
+ else if (cache.TransferEncoding==cache.TE_A85) out << "/Filter/ASCII85Decode";
+ } else if (cache.TransferEncoding!=cache.TE_Hex && cache.TransferEncoding!=cache.TE_A85) {
+ out << "/Filter" << getDecode(cache.Compression);
+ if (hps) { out << "/DecodeParms"; appendPredictorSpec(out); }
+ } else { /* both TransferEncoding and Compression */
+ if (cache.TransferEncoding==cache.TE_Hex) out << "/Filter[/ASCIIHexDecode";
+ else if (cache.TransferEncoding==cache.TE_A85) out << "/Filter[/ASCII85Decode";
+ else assert(0);
+ out << getDecode(cache.Compression);
+ if (hps) { out << "]/DecodeParms[null"; appendPredictorSpec(out); }
+ /* ^^^ BUGFIX at Tue Jun 4 18:50:13 CEST 2002 */
+ out << ']';
+ }
+ } else {
+ if (cache.Compression==cache.CO_None) {
+ if (cache.TransferEncoding==cache.TE_Hex) out << "/F/AHx";
+ else if (cache.TransferEncoding==cache.TE_A85) out << "/F/A85";
+ } else if (cache.TransferEncoding!=cache.TE_Hex && cache.TransferEncoding!=cache.TE_A85) {
+ out << "/F" << getBIDecode(cache.Compression);
+ if (hps) { out << "/DP"; appendPredictorSpec(out); }
+ } else { /* both TransferEncoding and Compression */
+ if (cache.TransferEncoding==cache.TE_Hex) out << "/F[/AHx";
+ else if (cache.TransferEncoding==cache.TE_A85) out << "/F[/A85";
+ else assert(0);
+ out << getBIDecode(cache.Compression);
+ if (hps) { out << "]/DP[null"; appendPredictorSpec(out); }
+ out << ']';
+ }
+ } /* IFELSE PDFB */
+ } else { /* NOT PDF */
+ if (cache.Compression!=cache.CO_None) {
+ appendPredictorSpec(out);
+ out << getDecode(cache.Compression) << " filter";
+ }
+ } /* IFELSE PDF */
+}
+
+bool Rule::OutputRule::hasPredictorSpec() const {
+ return cache.Compression==cache.CO_Fax
+ || ((cache.Compression==cache.CO_ZIP || cache.Compression==cache.CO_LZW) &&
+ cache.Predictor!=cache.PR_None);
+}
+
+void Rule::OutputRule::appendPredictorSpec(GenBuffer::Writable &out) const {
+ assert(cacheHints.PredictorBPC!=0 && "doSampleFormat already called");
+ if (cache.Compression==cache.CO_Fax)
+ out << "<</K " << cacheHints.K
+ << "/Columns " << cacheHints.EncoderBPL
+ /* ^^^ EncoderColumns -> EncoderBPL BUGFIX at Wed Jul 3 20:05:12 CEST 2002 */
+ << ">>";
+ else if ((cache.Compression==cache.CO_ZIP || cache.Compression==cache.CO_LZW) &&
+ cache.Predictor!=cache.PR_None)
+ out<< "<</BitsPerComponent " << (unsigned)cacheHints.PredictorBPC
+ << "/Columns " << cacheHints.PredictorColumns
+ << "/Colors " << (unsigned)cacheHints.PredictorColors
+ << (cache.Predictor==cache.PR_TIFF2 ? "/Predictor 2>>": "/Predictor 10>>");
+}
+void Rule::OutputRule::appendTransferSpec(GenBuffer::Writable &out) const {
+ if (cache.TransferEncoding==cache.TE_Hex) out << "/ASCIIHexDecode filter";
+ else if (cache.TransferEncoding==cache.TE_A85) out << "/ASCII85Decode filter";
+}
+
+/* --- */
+
+static Rule::Applier *first_rule=(Rule::Applier*)NULLP;
+
+void Rule::register0(Rule::Applier *anew) {
+ param_assert(anew!=NULLP);
+ anew->next=first_rule;
+ first_rule=anew;
+}
+
+unsigned Rule::printAppliers(GenBuffer::Writable &out) {
+ unsigned num=0;
+ Applier *p=first_rule;
+ while (p!=(Applier*)NULLP) {
+ if (p->check_rule!=0/*NULLP*/ && p->work!=0/*NULLP*/) { num++; out << ' ' << p->format; }
+ p=p->next;
+ }
+ return num;
+}
+
+Rule::OutputRule* Rule::buildProfile(MiniPS::VALUE Profile, bool quiet) {
+ param_assert(MiniPS::getType(Profile)==MiniPS::T_ARRAY);
+ MiniPS::Array *pary=MiniPS::RARRAY(Profile);
+ OutputRule *ret=new OutputRule[pary->getLength()+1], *or_=ret;
+ /* ^^^ just enough place; there may be BAD items which won't be stored */
+ MiniPS::VALUE *val;
+ unsigned c;
+ #if !USE_BUILTIN_LZW
+ bool lzw_warning=true;
+ #endif
+ if (quiet) Error::pushPolicy((Error::level_t)0,
+ /*printed_:*/Error::getTopPrinted()+0>Error::WARNING+0 ? Error::getTopPrinted() : Error::WARNING,
+ Error::WARNING_DEFER, (GenBuffer::Writable*)NULLP); /* Dat: WARNING_DEFER untested */
+ for (c=0, pary->getFirst(val); val!=NULLP; pary->getNext(val), c++) {
+ /* val: each OutputRule of the Profile */
+ or_->fromDict(*val);
+ or_->c=c;
+ Applier *p=first_rule;
+ // printf("building: %s...\n", p->format);
+ #if !USE_BUILTIN_LZW
+ if (or_->cache.Compression==or_->cache.CO_LZW && lzw_warning) {
+ lzw_warning=false;
+ Error::sev(Error::WARNING) << "buildProfile: please `configure --enable-lzw' for /Compression/LZW support in OutputRule #" << c << (Error*)0;
+ }
+ #endif
+ while (p!=NULLP) {
+ if (p->check_rule!=0/*NULLP*/) switch (p->check_rule(or_)) {
+ case Applier::BAD:
+ Error::sev(Error::WARNING_DEFER) << "buildProfile: ^^^ thus ignoring impossible OutputRule #" << c << (Error*)0;
+ goto end_appliers;
+ case Applier::MAYBE: case Applier::OK:
+ if (p->work!=0/*NULLP*/) { or_++; goto end_appliers; }
+ Error::sev(Error::WARNING_DEFER) << "buildProfile: ^^^ ignoring unimplemented OutputRule #" << c << (Error*)0;
+ // case p->DONT_KNOW: ;
+ }
+ p=p->next; /* continue with other Appliers; hope other than DONT_KNOW */
+ }
+ Error::sev(Error::WARNING_DEFER) << "buildProfile: ignoring, no handlers for OutputRule #" << c << (Error*)0;
+ end_appliers:
+ if (quiet) delete Error::getRecorded();
+ }
+ if (quiet) { delete Error::getRecorded(); Error::popPolicy(); }
+ if (or_==ret) Error::sev(Error::WARNING) << "buildProfile: all OutputRules in the .job file are useless" << (Error*)0;
+ or_->dict=or_->dictHints=(MiniPS::Dict*)NULLP; /* end-of-list */
+ return ret;
+}
+
+void Rule::applyProfile(GenBuffer::Writable& out, OutputRule*rule_list, Image::SampledInfo *sf) {
+ OutputRule *or_;
+ // unsigned tryc=0; /* Wed Jul 3 19:30:33 CEST 2002 */
+ Error::pushPolicy((Error::level_t)0,
+ /*printed_:*/Error::getTopPrinted()+0>Error::NOTICE+0 ? Error::getTopPrinted() : Error::NOTICE,
+ Error::NOTICE_DEFER, (GenBuffer::Writable*)NULLP);
+ Image::Sampled::rgb_t Transparent=0x1000000UL;
+ if (rule_list->dict!=NULLP) {
+ Transparent=rule_list->cache.Transparent;
+ for (or_=rule_list+1; or_->dict!=NULLP; or_++) {
+ if (Transparent!=rule_list->cache.Transparent) {
+ /* Imp: make different copies, based on different or_->cache.Transparent -- or not? */
+ Error::sev(Error::EERROR) << "applyProfile: ambiguous /Transparent" << (Error*)0;
+ }
+ }
+ }
+ /* Dat: -transparent ... makes the specified color transparent, but it cannot
+ * be used to remove transparenct
+ */
+ // printf("Transparent=0x%lx\n",Transparent);
+ for (or_=rule_list; or_->dict!=NULLP; or_++) {
+ /* ^^^ Try each OutputRule (or_) in reverse order of registration */
+ Error::sev(Error::NOTICE_DEFER) << "applyProfile: trying OutputRule #" << or_->c << (Error*)0;
+ if (sf->setSampleFormat(or_->cache.SampleFormat, or_->cache.WarningOK, /*TryOnly*/true, or_->cache.Transparent)) {
+ /* image supports the SampleFormat of OutputRule */
+ Applier *p=first_rule;
+ while (p!=NULLP) {
+ /* ^^^ Try each output Applier for the current candidate OutputRule */
+ if (p->check_rule!=0/*NULLP*/ && p->work!=0/*NULLP*/) {
+ // tryc++;
+ switch (p->work(out, or_, sf)) {
+ case Applier::BAD:
+ Error::sev(Error::WARNING) << "applyProfile: ^^^ thus cannot apply OutputRule #" << or_->c << (Error*)0;
+ goto end_appliers;
+ case Applier::OK:
+ // if (or_->c!=0) {
+ delete Error::getRecorded(); Error::popPolicy();
+ Error::sev(Error::NOTICE) << "applyProfile: applied OutputRule #" << or_->c << " using applier " << p->format << (Error*)0;
+ return;
+ /* case Applier::MAYBE: impossible */
+ // case p->DONT_KNOW: ;
+ }
+ }
+ p=p->next; /* continue with other Appliers; hope other than DONT_KNOW */
+ end_appliers: ;
+ }
+ } /* IF image supports SampleFormat */
+ }
+ Error::sev(Error::EERROR) << "applyProfile: invalid combination, no applicable OutputRule" << (Error*)0;
+}
+
+void Rule::deleteProfile(OutputRule*rule_list) {
+ /* MiniPS::* objects still remain -- the caller (reader) will delete them. */
+ delete [] rule_list;
+}
+
+/* --- */
+
+//#include <string.h>
+//static char xx[5000];
+
+void Rule::writeData(GenBuffer::Writable&, GenBuffer::Writable&outstream, Image::SampledInfo *sf) {
+ Image::Indexed **imgs=sf->getImgs();
+ slen_t rlenht;
+ if (imgs!=NULLP) {
+ unsigned i;
+ if (sf->getNncols()!=0 && 0!=(rlenht=imgs[0]->getRlen()*imgs[0]->getHt())) {
+ // fprintf(stderr,"rh=%u nc=%u\n", rlenht, sf->getNncols());
+ for (i=0;i<sf->getNncols();i++) outstream.vi_write(imgs[i]->getRowbeg(), rlenht);
+ //for (i=0;i<sf->getNncols();i++) {
+ // memset(xx, 1<<(i), sizeof(xx));
+ // outstream.vi_write(xx, rlenht);
+ //}
+ }
+ } else {
+ Image::Sampled *img=sf->getImg();
+ rlenht=img->getRlen()*img->getHt();
+ if (rlenht!=0) outstream.vi_write(img->getRowbeg(), rlenht);
+ }
+ outstream.vi_write(0,0); /* Dat: frees cp, bp, (ap) */
+}
+void Rule::writePalData(GenBuffer::Writable& outpal, GenBuffer::Writable&outstream, Image::SampledInfo *sf) {
+ Image::Sampled *img=sf->getImg();
+ slen_t wlen=img->getRowbeg()-img->getHeadp();
+ if (wlen!=0) outpal.vi_write(img->getHeadp(), wlen);
+ writeData(outpal, outstream, sf);
+ /* vvv replaced by the more generic writeData */
+ // slen_t rlenht=img->getRlen()*img->getHt();
+ // if (rlenht!=0) outstream.vi_write(img->getRowbeg(), rlenht);
+ // outstream.vi_write(0,0); /* Dat: frees cp, bp, (ap) */
+}
+
+/** Returns a divisor of v1*v2 near 4096 */
+static slen_t near_div(slen_t v1, slen_t v2) {
+ static const slen_t LOW=2048, MID=4096, HIGH=8192;
+ slen_t d, p;
+ if (v1>v2) { d=v1; v1=v2; v2=d; }
+ if (LOW<=v2 && v2<=HIGH) return v2; /* larger */
+ if (LOW<=v1 && v1<=HIGH) return v1; /* smaller */
+ if ((p=v1*v2)<=HIGH) return p; /* smaller */
+ for (d=MID;d<=HIGH;d++) if (p%d==0) return d;
+ for (d=MID-1;d>=LOW;d--) if (p%d==0) return d;
+ return v1; /* the smaller one */
+}
+
+/** Basicly out.format("%g", (double)n/255);, but we don't want to depend on
+ * floating point arithmetic of the underlying architecture.
+ */
+static void div255(GenBuffer::Writable& out, unsigned n) {
+ char tmp[7];
+ unsigned abc;
+ param_assert(n<=255);
+ tmp[0]='0'; tmp[1]='.'; tmp[3]='\0';
+ if (n%51!=0) {
+ /* Divisors of 255: 1, 3, 5, 15, 17, 51, 85, 255.
+ * 0/255 == "0" 51/255 == "0.2"
+ * 102/255 == "0.4" 153/255 == "0.6"
+ * 204/255 == "0.8" 255/255 == "1"
+ * All other k/255 are infinite as a decimal fraction.
+ * 1000 > 2*255, so 3 digits after '.' is enough.
+ */
+ assert(n<=254);
+ #if 0
+ abc=(127L+1000*n)/255;
+ tmp[2]='0'+abc/100;
+ tmp[3]='0'+(abc/10)%10;
+ tmp[4]='0'+abc%10;
+ tmp[5]='\0';
+ #else
+ abc=(127L+10000*n)/255;
+ tmp[2]='0'+abc/1000;
+ tmp[3]='0'+(abc/100)%10;
+ tmp[4]='0'+(abc/10)%10;
+ tmp[5]='0'+abc%10;
+ tmp[6]='\0';
+ #endif
+ } else if (n<153) {
+ if (n<51) tmp[1]='\0';
+ else if (n>51) tmp[2]='4';
+ else tmp[2]='2';
+ }
+ else if (n<204) tmp[2]='6';
+ else if (n>204) { tmp[0]='1'; tmp[1]='\0'; }
+ else tmp[2]='8';
+ out << tmp;
+}
+
+void Rule::writeTTE(
+ GenBuffer::Writable& out,
+ GenBuffer::Writable&outpal,
+ GenBuffer::Writable&outstream,
+ char const*template_, Rule::OutputRule*or_, Image::SampledInfo *sf, stream_writer_t stream_writer, char const*const*strings) {
+ unsigned int i, j;
+ register char const*p;
+ char *r;
+ Image::Sampled *img=sf->getImg();
+ param_assert(template_!=(const char*)NULLP);
+ p=template_;
+ bool nzp, scp;
+ SimBuffer::B scf;
+ while (1) {
+ assert(template_==p);
+ while (*p!='`' && *p!='\0') p++; /* '`' is the escape character */
+ if (p!=template_) out.vi_write(template_, p-template_);
+ if (*p++=='\0') break;
+ switch (*p++) {
+ case '\0':
+ p--; /* fall through */
+ case '`':
+ out.vi_write("`", 1); break;
+ case '#': /* number of non-transparent colors of /Indexed*, /Transparent* */
+ out << sf->getNncols(); break;
+ case 'p': /* 3*(number of non-transparent colors of /Indexed*, /Transparent*) */
+ out << (3*sf->getNncols()); break;
+ case 'P': /* number of palette bytes (including the transparent color) */
+ out << img->getRowbeg()-img->getHeadp(); break;
+ case '0': case '1': case '2': /* arbitrary, user-defined string */
+ param_assert(strings!=(char const*const*)NULLP);
+ out << strings[p[-1]-'0']; break;
+ case 'C': /* PDF /Procset entries */
+ if (or_->cache.isIndexed()) out << "/ImageI";
+ else if (or_->cache.isGray()) out << "/ImageB";
+ else out << "/ImageC"; /* SF_Rgb*, SF_Asis etc. */
+ break;
+ case 'i': /* PS image or colorimage operator */
+ out << (or_->cache.isGray() ? "image"
+ : or_->cache.SampleFormat==Image::SF_Mask || or_->cache.SampleFormat==Image::SF_Indexed1 ? "imagemask"
+ : "false 3 colorimage");
+ break;
+ case 'I': /* PS warning for usage of colorimage operator */
+ // if (!or_->cache.isGray()) out << "% PSLC required\n";
+ if (!or_->cache.isGray() && !or_->cache.isTransparentM()) out << "%%Extensions: CMYK\n";
+ break;
+#if 0
+ case "p:invalid": /* optional predictor specification */
+ { unsigned char pred=or_->cache.Predictor;
+ if (pred== 2) out << "/Predictor 2"; /* TIFF predictor */
+ else if (pred>=10) out << "/Predictor 10"; /* any PNG predictor */
+ }
+#endif
+ case 'w': /* image width, decimal */
+ out << img->getWd();
+ break;
+ case 'h': /* image height, decimal */
+ out << img->getHt();
+ break;
+ case '?': /* a divisor of rlen*height near 4096 */
+ if (sf->getImgs()!=NULLP) { /* /Transparent+ */
+ out << near_div(sf->getImgs()[0]->getRlen(), img->getHt());
+ /* Dat: `img->getHt()*sf->getNncols()' would be wrong */
+ } else {
+ out << near_div(img->getRlen(), img->getHt());
+ }
+ break;
+ case 'B': /* Clean7Bits or Binary; Sun Jun 23 18:55:35 CEST 2002 */
+ out << (or_->cache.isPDF() ? (or_->cache.isBinSB() ? "%\307\354\217\242\n" : "")
+ : (or_->cache.isBinSB() ? "Binary" : "Clean7Bit"));
+ break;
+ case 'b': /* image bpc, decimal */
+ /* added "true"|"false" for sam2p-0.39 at Sun Sep 22 17:49:25 CEST 2002 */
+ if (or_->cache.SampleFormat==Image::SF_Mask) out << "false";
+ else if (or_->cache.SampleFormat==Image::SF_Indexed1) out << "true";
+ else out << (unsigned)img->getBpc();
+ break;
+ case 'c': /* image cpp, decimal */
+ out << (unsigned)img->getCpp();
+ break;
+ case 'd': /* device-specific color-space name */
+ out << Image::Sampled::cs2devcs(img->getCs());
+ break;
+ case 't': /* closefile specification in PostScript */
+ if (or_->cache.Compression!=or_->cache.CO_None) out << " F closefile";
+ if (or_->cache.TransferEncoding!=or_->cache.TE_Binary) out << " T closefile";
+ break;
+ case 'T': /* TransferEncoding specification in PostScript */
+ or_->appendTransferSpec(out);
+ break;
+ case 'F': /* decoding filter specification in PostScript */
+ or_->appendDecoderSpec(out);
+ break;
+ case 'O': /* 0..1 /Decode values */
+ i=1;
+ emit_Decode:
+ j=img->getCpp();
+ out << "0 " << i;
+ while (j--!=1) out << " 0 " << i;
+ break;
+ case 'D': /* 0..max-1 /Decode values for indexed, 0..1 for others */
+ i=(or_->cache.isIndexed())?(1<<img->getBpc())-1:1;
+ goto emit_Decode;
+ case 'S': /* image data stream */
+ stream_writer(outpal, outstream, sf);
+ break;
+ case 'g': /* PDF 0..1 RGB triplet of the 0th palette color */
+ assert(img->getTy()==img->TY_INDEXED);
+ r=img->getHeadp();
+ goto appG;
+ case 'G': /* PDF 0..1 RGB triplet of the 1st palette color */
+ assert(img->getTy()==img->TY_INDEXED);
+ r=img->getHeadp()+3;
+ appG:
+ div255(out, (unsigned char)r[0]); out << ' ';
+ div255(out, (unsigned char)r[1]); out << ' ';
+ div255(out, (unsigned char)r[2]);
+ break;
+ case 'r': /* PS 0..1 RGB triplet of the 0th palette color */
+ assert(img->getTy()==img->TY_INDEXED);
+ r=img->getHeadp();
+ out << (unsigned)(unsigned char)r[0] << " 255 div "
+ << (unsigned)(unsigned char)r[1] << " 255 div "
+ << (unsigned)(unsigned char)r[2] << " 255 div";
+ break;
+ case 'R': /* PS code for setting up bg and fg colors for an imagemask */
+ /* formerly: PS 0..1 RGB triplet of the 1st palette color */
+ /* changed at Sun Sep 22 18:02:41 CEST 2002 */
+ if (or_->cache.SampleFormat==Image::SF_Mask || or_->cache.SampleFormat==Image::SF_Indexed1) {
+ assert(img->getTy()==img->TY_INDEXED);
+ r=img->getHeadp();
+ out << (unsigned)(unsigned char)r[0] << " 255 div " /* 0th palette color */
+ << (unsigned)(unsigned char)r[1] << " 255 div "
+ << (unsigned)(unsigned char)r[2] << " 255 div setrgbcolor\n";
+ if (or_->cache.SampleFormat==Image::SF_Indexed1) {
+ out << "0 0 moveto\n"
+ << img->getWd() << " 0 lineto\n0 "
+ << img->getHt() << " rlineto\n-"
+ << img->getWd() << " 0 rlineto\nclosepath fill\n"
+ << (unsigned)(unsigned char)r[3] << " 255 div " /* 1st palette color */
+ << (unsigned)(unsigned char)r[4] << " 255 div "
+ << (unsigned)(unsigned char)r[5] << " 255 div\nsetrgbcolor\n";
+ }
+ }
+ break;
+ case 'E': /* EPS header for unscaled PS files */
+ if (or_->cacheHints.Scale==or_->cacheHints.SC_None) out << " EPSF-3.0";
+ break;
+ case 'X': /* BoundingBox for EPS, MediaBox for PDF */
+ if (or_->cache.isPDF()) {
+ // out << "0 0 ";
+ out << "0 ";
+ goto do_bbox;
+ } else if (or_->cacheHints.Scale==or_->cacheHints.SC_None) {
+ /* It is no point to start the BoundingBox of EPS files at
+ * (LeftMargin,BottomMargin). The effect would be the same as
+ * specifying no margins at all. Our choice is better: the
+ * BoundingBox contains the image and the margins too.
+ */
+ // out << "%%BoundingBox: 0 0 ";
+ out << "%%BoundingBox: 0 ";
+ do_bbox:
+ // out << MiniPS::RVALUE(or_->cacheHints.LowerMargin) << ';'; /* SUXX: this would put `1 72 mul' */
+ // out << MiniPS::RVALUE(or_->cacheHints.BottomMargin) << ';'; /* SUXX: this would put `1 72 mul' */
+ MiniPS::dumpAdd3(out, MiniPS::Qinteger(0), MiniPS::Qinteger(0), MiniPS::Qinteger(0), or_->cacheHints.LowerMargin, or_->cacheHints.BottomMargin, 1);
+ out << ' ';
+ MiniPS::dumpAdd3(out, or_->cacheHints.ImageDPI, MiniPS::Qinteger(img->getWd()),
+ or_->cacheHints.LeftMargin, or_->cacheHints.RightMargin, MiniPS::Qinteger(0), 2);
+ out << ' ';
+ MiniPS::dumpAdd3(out, or_->cacheHints.ImageDPI, MiniPS::Qinteger(img->getHt()),
+ or_->cacheHints.TopMargin, or_->cacheHints.LowerMargin, MiniPS::Qinteger(0), 2);
+ if (!or_->cache.isPDF()) out << '\n';
+ }
+ break;
+ case 's': /* scaling to a full PostScript page or translation for PDF and EPS */
+ nzp=!(MiniPS::isZero(or_->cacheHints.LowerMargin)
+ && MiniPS::isZero(or_->cacheHints.TopMargin));
+ scp=!MiniPS::isEq(or_->cacheHints.ImageDPI, 72) &&
+ !MiniPS::isEq(or_->cacheHints.ImageDPI, -72);
+
+ if (or_->cache.isPDF()) {
+ SimBuffer::B scf;
+ if (scp) MiniPS::dumpScale(scf, or_->cacheHints.ImageDPI);
+ else scf << 'x';
+ if (nzp || scp) out << " " << scf << " 0 0 " << scf << " " << MiniPS::RVALUE(or_->cacheHints.LeftMargin)
+ << ' ' << MiniPS::RVALUE(or_->cacheHints.LowerMargin)
+ << " cm"; /* translate */
+ } else switch (or_->cacheHints.Scale) {
+ case Rule::CacheHints::SC_None:
+ if (nzp) out << '\n' << MiniPS::RVALUE(or_->cacheHints.LeftMargin)
+ << ' ' << MiniPS::RVALUE(or_->cacheHints.LowerMargin)
+ << " translate";
+ if (scp) {
+ MiniPS::dumpScale(scf, or_->cacheHints.ImageDPI);
+ out << '\n' << scf << " dup scale";
+ }
+ break;
+ case Rule::CacheHints::SC_OK:
+ /* from pshack/big.ps */
+ out <<"\n6 dict begin currentpagedevice/PageSize get dup 0 get\n " << MiniPS::RVALUE(or_->cacheHints.LeftMargin) << " sub " << MiniPS::RVALUE(or_->cacheHints.RightMargin) << " sub/w exch\n"
+ " def 1 get " << MiniPS::RVALUE(or_->cacheHints.TopMargin) << " sub " << MiniPS::RVALUE(or_->cacheHints.BottomMargin) << " sub/h exch\n"
+ " def/x " << img->getWd() << " def/y " << img->getHt() << " def " << MiniPS::RVALUE(or_->cacheHints.LeftMargin) << ' ' << MiniPS::RVALUE(or_->cacheHints.BottomMargin) << " translate x h\n"
+ " mul y w mul gt{w x 0 h y w mul x div sub 2 div}{h y w x h mul y div sub 2 div\n"
+ " 0}ifelse translate div dup scale\nend";
+ break;
+ case Rule::CacheHints::SC_RotateOK:
+ /* from pshack/big.ps */
+ out <<"\n6 dict begin currentpagedevice/PageSize get dup 0 get\n " << MiniPS::RVALUE(or_->cacheHints.LeftMargin) << " sub " << MiniPS::RVALUE(or_->cacheHints.RightMargin) << " sub/w exch\n"
+ " def 1 get " << MiniPS::RVALUE(or_->cacheHints.TopMargin) << " sub " << MiniPS::RVALUE(or_->cacheHints.BottomMargin) << " sub/h exch\n"
+ " def/x " << img->getWd() << " def/y " << img->getHt() << " def " << MiniPS::RVALUE(or_->cacheHints.LeftMargin) << ' ' << MiniPS::RVALUE(or_->cacheHints.BottomMargin) << "/b y h mul x\n"
+ " w mul gt def b{w y}{h x}ifelse div/c x h mul y w mul gt def c{w x}{h y}ifelse\n"
+ " div gt{h add translate -90 rotate b{w y h x w mul y div sub 2 div 0}{h\n"
+ " x 0 w y h mul x div sub 2 div}}{translate c{w x 0 h y w mul x div sub 2 div}{h\n"
+ " y w x h mul y div sub 2 div 0}}ifelse ifelse translate div dup scale\nend";
+ break;
+ }
+ break;
+ default:
+ Error::sev(Error::EERROR) << "writeTTE: unknown escape: " << (char)p[-1] << (Error*)0;
+ }
+ template_=p;
+ }
+}
+
+/** by pts@fazekas.hu at Mon Apr 15 22:31:03 CEST 2002 */
+void Rule::writeTTM(
+ Filter::VerbatimE &outve,
+ GenBuffer::Writable&outpal,
+ GenBuffer::Writable&outstream,
+ MiniPS::Array *chunkArray,
+ Rule::OutputRule*or_,
+ Image::SampledInfo *sf,
+ stream_writer_t stream_writer,
+ char const*const*strings) {
+ static const unsigned MAXLEN=64;
+ /* Imp: use heap instead of stack space */
+ slen_t offsets[MAXLEN+1]; /* 260 bytes stack */
+ SimBuffer::B chunks[MAXLEN]; /* <=1024 bytes stack; default constructor */
+ MiniPS::VALUE *chunk;
+ param_assert(chunkArray!=NULLP);
+ // param_assert(chunkArray->getLength()<=MAXLEN);
+ if (chunkArray->getLength()>(int)MAXLEN) Error::sev(Error::EERROR) << "writeTTM: TTM too long" << (Error*)0;
+ GenBuffer::Writable& out=outve.getOut();
+ MiniPS::ii_t i, ii;
+ for (chunkArray->getFirst(chunk), i=0; chunk!=NULLP; chunkArray->getNext(chunk), i++) {
+ if (MiniPS::getType(*chunk)==MiniPS::T_ARRAY) {
+ outve.setOut(chunks[i]);
+ writeTTM(outve, outpal, outstream, MiniPS::RARRAY(*chunk), or_, sf, stream_writer, strings);
+ }
+ }
+ for (chunkArray->getFirst(chunk), offsets[i=0]=0; chunk!=NULLP; chunkArray->getNext(chunk), i++) {
+ switch (MiniPS::getType(*chunk)) {
+ case MiniPS::T_ARRAY:
+ break;
+ case MiniPS::T_STRING: /* always null-terminated */
+ outve.setOut(chunks[i]);
+ writeTTE(outve, outpal, outstream, MiniPS::RSTRING(*chunk)->begin_(), or_, sf, stream_writer, strings);
+ break;
+ case MiniPS::T_INTEGER:
+ if (0==(ii=MiniPS::int2ii(*chunk))) Error::sev(Error::EERROR) << "writeTTM: zero is an invalid chunk" << (Error*)0;
+ if (ii>0) { /* an offset */
+ if (ii>i) Error::sev(Error::EERROR) << "writeTTM: cannot predict chunk offset" << (Error*)0;
+ if (MiniPS::T_ARRAY==MiniPS::getType(chunkArray->get(ii)))
+ chunks[i].write_num(offsets[ii], 10); /* Dat: 10: 10 digits (for PDF xref table), not base 10 */
+ else chunks[i] << offsets[ii];
+ } else { /* a length */
+ chunks[i] << chunks[-ii].getLength();
+ }
+ break;
+ default:
+ Error::sev(Error::EERROR) << "writeTTM: invalid chunk type: " << MiniPS::getTypeStr(MiniPS::getType(*chunk)) << (Error*)0;
+ }
+ offsets[i+1]=offsets[i]+chunks[i].getLength();
+ } /* NEXT */
+ outve.setOut(out);
+ for (i=0; i<chunkArray->getLength(); i++) out << chunks[i];
+ /* Imp: organize that chunks[.] gets freed earlier than this */
+} /* Rule::writeTTM() */
+
+MiniPS::Dict *Rule::Templates=(MiniPS::Dict*)NULLP;
+
+void Rule::writeTTT(
+ GenBuffer::Writable&out,
+ GenBuffer::Writable&outpal,
+ GenBuffer::Writable&outstream,
+ char const *template_key,
+ Rule::OutputRule*or_,
+ Image::SampledInfo *sf,
+ stream_writer_t stream_writer,
+ char const*const*strings) {
+ assert(Templates!=NULLP);
+ Error::sev(Error::NOTICE) << "writeTTT: using template: " << template_key << (Error*)0;
+ MiniPS::VALUE val=Templates->get(template_key, strlen(template_key));
+ assert(val!=MiniPS::Qundef);
+ switch (MiniPS::getType(val)) {
+ case MiniPS::T_STRING:
+ writeTTE(out, outpal, outstream, MiniPS::RSTRING(val)->begin_(), or_, sf, stream_writer, strings);
+ break;
+ case MiniPS::T_ARRAY:
+ /* Imp: vvv This up-cast is unsafe! */
+ writeTTM(*(Filter::VerbatimE*)&out, outpal, outstream, MiniPS::RARRAY(val), or_, sf, stream_writer, strings);
+ break;
+ default:
+ Error::sev(Error::EERROR) << "writeTTT: invalid template type: " << MiniPS::getTypeStr(MiniPS::getType(val)) << (Error*)0;
+ }
+}
+
+/* __END__ */
diff --git a/graphics/sam2p/rule.hpp b/graphics/sam2p/rule.hpp
new file mode 100644
index 0000000000..7dcf3cd4a0
--- /dev/null
+++ b/graphics/sam2p/rule.hpp
@@ -0,0 +1,319 @@
+/* rule.hpp -- Output rules
+ * by pts@fazekas.hu Fri Mar 15 15:11:38 CET 2002
+ */
+
+#ifdef __GNUC__
+#ifndef __clang__
+#pragma interface
+#endif
+#endif
+
+#ifndef RULE_HPP
+#define RULE_HPP 1
+
+#include "config2.h"
+#include "gensio.hpp"
+#include "image.hpp"
+#include "minips.hpp"
+
+/** a namespace */
+class Rule { public:
+ struct Cache {
+ bool WarningOK;
+ BEGIN_STATIC_ENUM(unsigned char,ff_t)
+ FF_default=0, /* only for one-liner */
+ FF_eps=71, /* only for one-liner, temporary */
+ FF_pdf=72, /* only for one-liner, temporary */
+ FF_pdfb=73, /* only for one-liner, temporary */
+ FF_PSL1=110,
+ FF_PSLC=115,
+ FF_PSL2=120,
+ FF_PSL3=130,
+ FF_PDFB10=90,
+ FF_PDFB12=92,
+ FF_PDF10=80,
+ FF_PDF12=82,
+ FF_GIF89a=1,
+ FF_PNM=2,
+ FF_PAM=3,
+ FF_PIP=4, /* Portable Indexed file format by pts */
+ FF_Empty=5,
+ FF_Meta=6,
+ FF_JPEG=7,
+ FF_TIFF=8,
+ FF_PNG=9,
+ FF_XPM=10,
+ FF_BMP=11,
+ FF_XWD=12,
+ FF_X11=13 /* Don't add a comma, gcc-4.8.1. can't compile it that way. */
+ END_STATIC_ENUM()
+ ff_t FileFormat;
+ Image::sf_t SampleFormat;
+ /** Used only in appliers.cpp when _check_rule() changes SampleFormat so
+ * setSampleFormat() called before _work() would set that dummy
+ * SampleFormat.
+ */
+ Image::sf_t origSampleFormat;
+ BEGIN_STATIC_ENUM(unsigned char,te_t)
+ TE_default=0, /* only for one-liner */
+ TE_Binary=1,
+ TE_ASCII=2,
+ TE_Hex=3,
+ TE_A85=4,
+ TE_MSBfirst=5,
+ TE_LSBfirst=6
+ END_STATIC_ENUM()
+ te_t TransferEncoding;
+
+ BEGIN_STATIC_ENUM(unsigned char,co_t)
+ CO_default=0, /* only for one-liner */
+ CO_None=1,
+ CO_LZW=2,
+ CO_ZIP=3,
+ CO_RLE=4,
+ CO_Fax=5,
+ CO_DCT=6,
+ CO_IJG=7,
+ CO_JAI=8,
+ CO_max=8
+ END_STATIC_ENUM()
+ co_t Compression;
+
+ BEGIN_STATIC_ENUM(unsigned char,pr_t)
+ PR_None=1,
+ PR_TIFF2=2,
+ PR_PNGNone=10, PR_PNG=10,
+ PR_PNGSub=11,
+ PR_PNGUP=12,
+ PR_PNGAverage=13,
+ PR_PNGPaeth=14,
+ PR_PNGAuto=15,
+ PR_PNGAutoMaybe=25,
+ PR_PNGAutoBadUnsigned=45,
+ PR_PNGAutoBadSigned=55
+ END_STATIC_ENUM()
+ pr_t Predictor;
+
+ Image::Sampled::rgb_t Transparent;
+
+ bool isOneBit() const;
+ bool isPDF() const;
+ bool isPDFB() const;
+ bool isPS() const;
+ bool isPSL2() const;
+ bool isPSL3() const;
+ bool hasPredictor() const;
+ bool isIndexed() const;
+ bool isTransparentM() const;
+ bool isGray() const;
+ bool isRGB() const;
+ bool isDCTE() const;
+ bool isBinSB() const;
+ /** /Compression/ZIP not OK with /PSL1, /PSLC, /PSL2, /PDF10, /PDFB10 */
+ bool isZIPOK() const;
+ // bool is8() const;
+
+ /** @param s is case insensitive, leading `/' is optional.
+ * @return SF_max if not found, or a valid SF_... constant
+ */
+ static Image::sf_t parseSampleFormat(char const*s, slen_t slen);
+ static char const* dumpFileFormat(ff_t FileFormat, co_t Compression=CO_default);
+ static char const* dumpTransferEncoding(te_t TransferEncoding);
+ static char const* dumpSampleFormat(Image::sf_t SampleFormat);
+ static char const* dumpCompression(co_t Compression);
+ };
+
+ struct CacheHints {
+ BEGIN_STATIC_ENUM(unsigned char,sc_t) /* Fri Aug 16 16:33:47 CEST 2002 */
+ SC_default=0,
+ SC_None=1,
+ SC_OK=2,
+ SC_RotateOK=3
+ END_STATIC_ENUM()
+ sc_t Scale;
+
+ /* Image dimensions for encoding filters (may be different from real
+ * image dimensions, but _really_ disrecommended).
+ * slen_t important becasuse of separate().
+ */
+ slen_t EncoderColumns, EncoderBPL, EncoderRows;
+ /** Number of color components (channels) per pixel. */
+ unsigned char EncoderColors;
+ slen_t PredictorColumns;
+ unsigned char PredictorBPC, PredictorColors;
+ unsigned ColorTransform;
+ signed Effort;
+ slen_t RecordSize;
+ slendiff_t K;
+ /* JPEG quality for the IJG encoding filter */
+ unsigned char Quality;
+ unsigned TransferCPL;
+ MiniPS::String *Comment, *Title, *Subject, *Author, *Creator, *Producer;
+ MiniPS::String *Created, *Produced;
+ MiniPS::Dict *DCT;
+ /** MiniPS::Real* or integer */
+ MiniPS::VALUE TopMargin, BottomMargin, LeftMargin, RightMargin;
+ /** MiniPS::Real* or integer. Specifies the dimension the image should
+ * be lowered below the baseline for (PostScript or PDF) output with
+ * /Scale/None. Default to 0.
+ */
+ MiniPS::VALUE LowerMargin;
+ /** 72 by default. */
+ MiniPS::VALUE ImageDPI;
+ static char const* dumpScale(sc_t Scale);
+ };
+
+ struct OutputRule {
+ Cache cache;
+ CacheHints cacheHints;
+ MiniPS::Dict* dict;
+ /* /Hints entry in dict */
+ MiniPS::Dict* dictHints;
+ /* Number of this output rule, as appeared in .job. Imp: name */
+ unsigned c;
+ inline bool isEOL() const { return dictHints==NULLP; }
+ /** In: dict, dictHints, cache and cacheHints is uninitialized. Out: they
+ * get inititalized from param. Errors might occur and error messages
+ * might get printed.
+ */
+ void fromDict(MiniPS::VALUE);
+ /** Calls info->setSampleFormat(), and sets cacheHints.PredictorColumns
+ * and some other fields if they are zero (unspecified in the .job file)
+ */
+ void doSampleFormat(Image::SampledInfo *info, bool separate=false);
+ /** Appends "" when CO_None,
+ * "<</K ... /Columns ...>>/CCITTFaxDecode filter" when CO_Fax
+ * "/...Decode filter" otherwise
+ * Calls appendPredictorSpec() if necessary.
+ * For PDF (not PS!), implies appendTransferSpec().
+ */
+ void appendDecoderSpec(GenBuffer::Writable &out) const;
+ /** Appends "" when PR_None or
+ * appends "<</BitsPerComponent.../Colors.../Columns.../Predictor 2>>" or
+ * appends "<</BitsPerComponent.../Colors.../Columns.../Predictor 10>>"
+ * appends "<</K ...>>"
+ */
+ void appendPredictorSpec(GenBuffer::Writable &out) const;
+ /** Appends "" or "/ASCII85Decode filter" or "/ASCIIHexDecode filter"
+ */
+ void appendTransferSpec(GenBuffer::Writable &out) const;
+ bool hasPredictorSpec() const;
+ };
+
+ struct Applier {
+ BEGIN_STATIC_ENUM(unsigned,cons_t)
+ DONT_KNOW=0, BAD=1, MAYBE=2, OK=3
+ END_STATIC_ENUM()
+ /** Checks the specified OutputRule for internal consistency, updates
+ * the `or->cache', emits warnings, and returns consistency status
+ * information.
+ *
+ * -- If (this) Applier doesn't know how to handle the OutputRule, returns
+ * DONT_KNOW immediately.
+ * -- If (this) Applier knows that the OutputRule is internally
+ * inconsistent or proved to be unsupported (i.e printing JPEG images
+ * on PostScript Level1 printers), regardless of the image itself, it
+ * returns BAD immediately and emits a warning about the reason.
+ * -- If (this) Applier knows that the OutputRule may or may not be
+ * processed, depending on the actual image, then MAYBE is returned.
+ * -- If (this) Applier knows that the OutputRule can be processed on
+ * any image, then OK is returned.
+ */
+ typedef cons_t(*check_rule_t)(OutputRule* or_);
+
+ /** Outputs (writes) the PostScript or PDF presentation of the image
+ * specified in param `sf' to the output stream in param `out', using
+ * the Output Rule specified in param `or'.
+ * @return DONT_KNOW if doesn't know how to handle the OutputRule;
+ * BAD if it is sure that the image cannot be written with the
+ * specified OutputRule;
+ * OK if writing was successful
+ */
+ typedef cons_t(*work_t)(GenBuffer::Writable& out, OutputRule*or_, Image::SampledInfo *sf);
+
+ /** A short, informal description of this Applier. */
+ char const*format;
+ check_rule_t check_rule;
+ /** May be NULLP if `check_rule' never returns OK or MAYBE */
+ work_t work;
+ /** Null or next Applier to probe. Filled by register0(); */
+ Applier *next;
+ };
+
+ /* Registers a new type of output Applier, i.e a new output file
+ * format/method. The new output format will be put in front of all others,
+ * and will be checked first by apply_best().
+ */
+ static void register0(Applier*);
+ /* Loads the image contained in te file `filename'. */
+
+ /** Builds the list of available profiles from the Profile element read
+ * from a .job file. To do the task, calls check_rule() of all registered (!)
+ * Appliers. Also calls OutputRule::fromDict for each profile element.
+ * All returned OutputRules have an Applier which returned OK or MAYBE.
+ * @return a dict==NULLP-terminated list of OutputRules
+ */
+ static OutputRule* buildProfile(MiniPS::VALUE Profile, bool quiet=false);
+
+ /** Applies the Profile specified in param `rule_list' to the image
+ * specified in param `sf', and writes the output to param `out'.
+ */
+ static void applyProfile(GenBuffer::Writable& out, OutputRule*rule_list, Image::SampledInfo *sf);
+
+ /** Frees memory associated with a profile returned by buildProfile() */
+ static void deleteProfile(OutputRule*);
+
+ static unsigned printAppliers(GenBuffer::Writable &out);
+
+
+ typedef void (*stream_writer_t)(GenBuffer::Writable&out, GenBuffer::Writable&outstream, Image::SampledInfo *sf);
+
+ /** Writes a PS/PDF file to `out' according to `template_': substitutes
+ * actual image (pixel) data from `sf->getImg()', and substitutes image
+ * metadata from `sf'. `outstream' should be a prepared stream (top of chain
+ * of Encode filters).
+ * See a .tte file for an example template.
+ */
+ static void writeTTE(
+ GenBuffer::Writable& out,
+ GenBuffer::Writable& outpal,
+ GenBuffer::Writable& outstream,
+ char const*template_,
+ Rule::OutputRule*or_,
+ Image::SampledInfo *sf,
+ stream_writer_t stream_writer,
+ char const*const*strings=(char**)NULLP);
+
+ /** Doesn't invoke MiniPS::delete0(chunkArray); */
+ static void writeTTM(
+ Filter::VerbatimE &outve,
+ GenBuffer::Writable&outpal,
+ GenBuffer::Writable&outstream,
+ MiniPS::Array *chunkArray,
+ Rule::OutputRule*or_,
+ Image::SampledInfo *sf,
+ stream_writer_t stream_writer,
+ char const*const*strings=(char**)NULLP);
+
+ /** Used by writeTTT() to find template specification by name */
+ static MiniPS::Dict* Templates;
+ /** @param out must be of type Filter::VerbatimE if the template is a TTM
+ * array.
+ * @param template_key a key in file bts.ttt
+ */
+ static void writeTTT(
+ GenBuffer::Writable&out,
+ GenBuffer::Writable&outpal,
+ GenBuffer::Writable&outstream,
+ char const *template_key,
+ Rule::OutputRule*or_,
+ Image::SampledInfo *sf,
+ stream_writer_t stream_writer,
+ char const*const*strings=(char**)NULLP);
+
+ static void writeData(GenBuffer::Writable& out, GenBuffer::Writable&outstream, Image::SampledInfo *sf);
+ static void writePalData(GenBuffer::Writable& out, GenBuffer::Writable&outstream, Image::SampledInfo *sf);
+
+};
+
+#endif
diff --git a/graphics/sam2p/sam2p16.ico b/graphics/sam2p/sam2p16.ico
new file mode 100644
index 0000000000..b712b32166
--- /dev/null
+++ b/graphics/sam2p/sam2p16.ico
Binary files differ
diff --git a/graphics/sam2p/sam2p32.ico b/graphics/sam2p/sam2p32.ico
new file mode 100644
index 0000000000..c5b26e2659
--- /dev/null
+++ b/graphics/sam2p/sam2p32.ico
Binary files differ
diff --git a/graphics/sam2p/sam2p_main.cpp b/graphics/sam2p/sam2p_main.cpp
new file mode 100644
index 0000000000..5b39a6c19a
--- /dev/null
+++ b/graphics/sam2p/sam2p_main.cpp
@@ -0,0 +1,1118 @@
+/* sam2p_main.cpp
+ * by pts@fazekas.hu at Fri Mar 15 16:11:03 CET 2002
+ */
+
+#include "gensi.hpp"
+#include "gensio.hpp"
+#include "image.hpp"
+#include "error.hpp"
+#include "encoder.hpp"
+#include "minips.hpp"
+#include "rule.hpp"
+#include "main.hpp"
+#include "in_jai.hpp"
+
+#ifndef SAM2P_VERSION
+#include "sam2p_version.h"
+#endif
+
+/* Sat Jul 6 16:39:19 CEST 2002
+ * empirical checkerg++ helper routines for gcc version 2.95.2 20000220 (Debian GNU/Linux)
+ * see c_lgcc.cpp for more
+ */
+#if !defined(OBJDEP) && defined(__CHECKER__) && !HAVE_PTS_C_LGCC_CPP_REQUIRED
+# include "c_lgcc.cpp"
+#endif
+
+#if 0 /*#ifdef __CHECKER__*/
+#include <stdlib.h>
+void* __builtin_vec_new(unsigned len){ return malloc(len); }
+void __builtin_vec_delete(void *p) { free(p); }
+void* __builtin_new(unsigned len){ return malloc(len); }
+void __builtin_delete(void *p) { free(p); }
+void __rtti_user() { abort(); }
+void __rtti_si() { abort(); }
+void terminate() { abort(); }
+extern "C" void __pure_virtual();
+void __pure_virtual() { abort(); }
+#endif
+
+#if OBJDEP
+# warning PROVIDES: sam2p_main
+# warning REQUIRES: gensi.o
+# warning REQUIRES: gensio.o
+# warning REQUIRES: image.o
+# warning REQUIRES: error.o
+# warning REQUIRES: encoder.o
+# warning REQUIRES: minips.o
+# warning REQUIRES: rule.o
+#endif
+
+#include <stdio.h>
+#include <string.h> /* memset() */
+
+#if OBJDEP
+# warning REQUIRES: in_tiff.o
+# warning REQUIRES: in_jpeg.o
+# warning REQUIRES: in_png.o
+# warning REQUIRES: in_jai.o
+# warning REQUIRES: in_pcx.o
+# warning REQUIRES: in_xpm.o
+# warning REQUIRES: in_lbm.o
+# warning REQUIRES: in_gif.o
+# warning REQUIRES: in_bmp.o
+# warning REQUIRES: in_pnm.o
+# warning REQUIRES: in_tga.o
+/*# warning REQUIRES: in_pdf.o Dat: no more, integrated to in_ps.o */
+# warning REQUIRES: in_ps.o
+#endif
+extern Image::Loader in_tiff_loader;
+extern Image::Loader in_jpeg_loader;
+extern Image::Loader in_png_loader;
+extern Image::Loader in_jai_loader;
+extern Image::Loader in_pcx_loader;
+extern Image::Loader in_xpm_loader;
+extern Image::Loader in_lbm_loader;
+extern Image::Loader in_gif_loader;
+extern Image::Loader in_bmp_loader;
+extern Image::Loader in_pnm_loader;
+extern Image::Loader in_tga_loader;
+extern Image::Loader in_pdf_loader;
+extern Image::Loader in_ps_loader;
+void init_loader() {
+ static bool had_init_loader=false;
+ if (had_init_loader) return;
+ Image::register0(&in_tga_loader); /* checker not sure; install early */
+ Image::register0(&in_pcx_loader);
+ Image::register0(&in_xpm_loader);
+ Image::register0(&in_lbm_loader);
+ Image::register0(&in_gif_loader);
+ Image::register0(&in_bmp_loader);
+ Image::register0(&in_pnm_loader);
+ Image::register0(&in_tiff_loader);
+ Image::register0(&in_jpeg_loader);
+ Image::register0(&in_png_loader);
+ Image::register0(&in_jai_loader);
+ Image::register0(&in_pdf_loader);
+ Image::register0(&in_ps_loader);
+ had_init_loader=true;
+}
+
+#if OBJDEP
+# warning REQUIRES: appliers.o
+#endif
+extern Rule::Applier out_pnm_applier;
+extern Rule::Applier out_jpeg_applier;
+extern Rule::Applier out_jpegjai_applier;
+extern Rule::Applier out_tiffjai_applier;
+extern Rule::Applier out_tiff_applier;
+extern Rule::Applier out_png_applier;
+extern Rule::Applier out_bmp_applier;
+extern Rule::Applier out_gif89a_applier;
+extern Rule::Applier out_xpm_applier;
+extern Rule::Applier out_l1c_applier;
+// extern Rule::Applier out_l1op_applier;
+extern Rule::Applier out_l1tr_applier;
+extern Rule::Applier out_l23_applier;
+// extern Rule::Applier out_l1fa85g_applier;
+extern Rule::Applier out_l2jbin_applier;
+// extern Rule::Applier out_p0jbin_applier;
+extern Rule::Applier out_empty_applier;
+extern Rule::Applier out_meta_applier;
+extern Rule::Applier out_xwd_applier;
+extern Rule::Applier out_x11_applier;
+void init_applier() {
+ static bool had_init_applier=false;
+ if (had_init_applier) return;
+ // Rule::register0(&out_l1op_applier);
+ Rule::register0(&out_l1tr_applier);
+ // Rule::register0(&out_l1fa85g_applier);
+ Rule::register0(&out_l2jbin_applier);
+ // Rule::register0(&out_p0jbin_applier);
+ Rule::register0(&out_l23_applier);
+ Rule::register0(&out_l1c_applier);
+ Rule::register0(&out_xpm_applier);
+ Rule::register0(&out_gif89a_applier);
+ Rule::register0(&out_pnm_applier);
+ Rule::register0(&out_jpeg_applier);
+ Rule::register0(&out_jpegjai_applier);
+ Rule::register0(&out_tiffjai_applier);
+ Rule::register0(&out_tiff_applier);
+ Rule::register0(&out_png_applier);
+ Rule::register0(&out_bmp_applier);
+ Rule::register0(&out_empty_applier);
+ Rule::register0(&out_meta_applier);
+ Rule::register0(&out_xwd_applier);
+ Rule::register0(&out_x11_applier);
+ had_init_applier=true;
+}
+
+static char bts_ttt[] =
+#include "bts2.tth"
+;
+
+/* --- One-liner mode */
+
+/** Dat: mod 16 does matter: expected # args etc. */
+static const unsigned
+ OPT_unknown=0,
+ OPT_SampleFormat=0x02,
+ OPT_LoadHints=0x12,
+ OPT_Compression=0x22,
+ OPT_TransferEncoding=0x32,
+ OPT_TransferEncodingF=0x42,
+ // OPT_Asis=0x50,
+ OPT_PSL1=0x60,
+ OPT_PSLC=0x70,
+ OPT_PSL2=0x80,
+ OPT_PSL3=0x90,
+ OPT_PS=0xA1,
+ OPT_PDF=0xB1,
+ OPT_DisplayJobFile=0xC1,
+ OPT_Hints=0xD2,
+ // OPT_InputFile=0xE2,
+ OPT_OutputFile=0xF2,
+ OPT_Scale=0x101,
+ OPT_Margins=0x112,
+ OPT_Transparent=0x122,
+ OPT_TmpRemove=0x132;
+
+/** @param s an option (lower/upper case intact), without leading `-'s
+ * @param slen length of option
+ * @return 0 if invalid/unsupported/unknown option
+ * | 16*(k+1)+0 if the option never accepts parameters
+ * | 16*(k+2)+1 if the option may or may not have a parameter
+ * | 16*(k+3)+2 if the option must have a parameter
+ */
+static unsigned sam2p_optval(char const* s, slen_t slen) {
+ if (slen==1) {
+ switch (s[0]) {
+ case 's': return OPT_SampleFormat;
+ case 'l': return OPT_LoadHints;
+ case 'h': return OPT_Hints;
+ case 't': return OPT_TransferEncoding;
+ case 'f': return OPT_TransferEncodingF;
+ case 'c': return OPT_Compression;
+ // case 'a': return OPT_Asis; /* disabled, automatic! */
+ case '1': return OPT_PSL1;
+ case '2': return OPT_PSL2;
+ case '3': return OPT_PSL3;
+ case 'j': return OPT_DisplayJobFile;
+ case 'o': case 'O': return OPT_OutputFile;
+ case 'e': return OPT_Scale;
+ case 'm': return OPT_Margins;
+ }
+ } else {
+ slen_t len=slen; /* strlen(s); */
+ if (len>=32) return OPT_unknown;
+ char buf[32];
+ GenBuffer::tolower_memcpy(buf, s, len);
+ buf[len]='\0';
+ /* printf("buf=(%s)\n", buf); */
+ if (0==strcmp(buf, "sampleformat")) return OPT_SampleFormat;
+ if (0==strcmp(buf, "loadhints")) return OPT_LoadHints;
+ if (0==strcmp(buf, "tmpremove")) return OPT_TmpRemove;
+ if (0==strcmp(buf, "transparent")) return OPT_Transparent;
+ if (0==strcmp(buf, "hints")) return OPT_Hints;
+ if (0==strcmp(buf, "ps")
+ || 0==strcmp(buf, "eps")) return OPT_PS;
+ if (0==strcmp(buf, "pdf")) return OPT_PDF;
+ if (0==strcmp(buf, "1c")) return OPT_PSLC;
+ if (0==strcmp(buf, "scale")) return OPT_Scale;
+ if (0==strcmp(buf, "hints")) return OPT_Margins;
+ }
+ return OPT_unknown;
+}
+
+static void displayJob(GenBuffer::Writable &sout, SimBuffer::Flat const& jobss) {
+ fflush(stdout); fflush(stderr);
+ #if 0
+ puts("\n\n% begin sam2p job dump");
+ fwrite(stdout, 1, jobss.getLength(), jobss);
+ puts("% end sam2p job dump\n");
+ #else
+ /* vvv Dat: sout conflicts /OutputFile(-), but it is OK here */
+ sout << "\n% begin sam2p job dump\n"
+ << jobss
+ << "%)%)%)% end sam2p job dump\n\n";
+ #endif
+ fflush(stdout); fflush(stderr);
+}
+
+static inline char const *protect_null(char const *s) {
+ return s==(char const*)NULLP ? "//" : s;
+}
+
+/** @return the value for the parameter if matches key or the first letter of
+ * key; or NULLP if no match.
+ * @param key lower case
+ */
+static char const*one_pabbr(char const*param, char const *key) {
+ return GenBuffer::nocase_strbegins(param, key) ? param+strlen(key)
+ : (param[0]==key[0] || param[0]==key[0]+'A'-'a') && param[1]==':' ? param+2
+ : (char const*)NULLP;
+}
+
+#if 0 /* cannot set badp... */
+static inline void one_setdimen2(char const*&Dimen1, char const*&Dimen2, char const*p2) {
+ if (MiniPS::Real::isDimen(p2)) Dimen1=Dimen2=p2;
+ else Error::sev(Error::ERROR_CONT) << "one_liner: dimen expected" /*<< (SimBuffer::B().appendDumpC(p2, true))*/ << (Error*)0;
+}
+#endif
+#if 0
+#define one_setdimen2(Dimen1,Dimen2,p2) do { \
+ if (MiniPS::Real::isDimen(p2)) Dimen1=Dimen2=p2; \
+ else { badmsg="one_liner: dimen expected: "; goto bad_label; } \
+} while(0)
+#endif
+
+static Filter::UngetFILED *ufd;
+static bool do_DisplayJobFile;
+static bool buildProfile_quiet=false;
+/** Creates an in-memory job file according to the command-line options.
+ * @param a argv+1
+ * @param job initially an empty string. On error, this function leaves it
+ * as-is, but on success, a valid job file is appened.
+ * @return true on syntax error
+ */
+static bool one_liner(SimBuffer::B &jobss, char const *const* a) {
+ /* Tue Jul 2 21:27:15 CEST 2002 */
+ char const *p, *pend;
+ bool no_option_term=true;
+ bool badp=false;
+ bool no_selector=true;
+ char const *badmsg;
+ // SimBuffer::B Profile /* MiniPS code */
+ SimBuffer::B Hints; /* MiniPS code */
+ /* ^^^ Imp: separate hint for each -c arg?? */
+ SimBuffer::B LoadHints;
+ bool TmpRemove_p=true;
+ Rule::Cache::pr_t Predictor=Rule::Cache::PR_None; /* Imp: separate for each Compression */
+ Rule::Cache::ff_t FileFormat=Rule::Cache::FF_default;
+ Rule::Cache::te_t TransferEncoding=Rule::Cache::TE_default;
+ do_DisplayJobFile=false;
+ bool do_stop_SampleFormat=false;
+ char const *Transparent=(char const*)NULLP; /* change 1 color to transparent unless NULL */
+ char const *OutputFile=(char const*)NULLP, *InputFile=(char const*)NULLP;
+ // SimBuffer::B tmp;
+ char const *TopMargin=(char const*)NULLP, *BottomMargin=(char const*)NULLP,
+ *LeftMargin=(char const*)NULLP, *RightMargin=(char const*)NULLP,
+ *LowerMargin=(char const*)NULLP, *ImageDPI=(char const*)NULLP;
+ bool negLowerMargin=false;
+ Rule::CacheHints::sc_t Scale=Rule::CacheHints::SC_default;
+ #define APPEND_sf(val) do { if (sfx[val]==0) { sfx[val]=1; sft[sflen++]=val; } } while (0)
+ Image::sf_t sft[Image::SF_max+1]; char sfx[Image::SF_max+1]; memset(sfx, 0, sizeof(sfx)); unsigned sflen=0;
+ #define APPEND_co(val) do { if (cox[val]==0) { cox[val]=1; cot[colen++]=val; } } while (0)
+ Rule::Cache::co_t cot[Rule::Cache::CO_max+1]; char cox[Image::SF_max+1]; memset(cox, 0, sizeof(cox)); unsigned colen=0;
+ /* ^^^ BUGFIX at 2002.12.02 */
+
+ /** OPT_* value of current option */
+ unsigned opt;
+ /** Parameter for current option. May be NULL. */
+ char const *param=""; /* pacify VC6.0 */
+ char const *p2;
+ slen_t paramlen;
+ SimBuffer::B tmpnam; /* any dir -- keep on stack frame */
+
+ buildProfile_quiet=true;
+
+ for (; (p=*a)!=(char const*)NULLP; a++) {
+ if (p[0]=='-' && p[1]=='\0') { /* `-': Filename: STDIN or STDOUT */
+ #if 1
+ goto normal_label;
+ #else
+ Error::sev(Error::ERROR_CONT) << "one_liner: `-' (stdin|stdout) not allowed as filename" << (Error*)0;
+ badp=true;
+ continue;
+ #endif
+ } else if (p[0]=='-' && p[1]=='-' && p[2]=='\0') { /* `--': No more options */
+ if (a[1]==(char const*)NULLP && InputFile!=(char const*)NULLP) { /* `--' is last argument */
+ p=InputFile; /* OutputFile:=InputFile */
+ goto normal_label;
+ }
+ no_option_term=false;
+ } else if (p[0]=='-' && no_option_term) { /* an option */
+ while (*p=='-') p++; /* short options (-p) and long options (--pdf) are equivalent */
+ pend=p; while (*pend!='\0' && *pend!=':' && *pend!='=') pend++;
+ SimBuffer::Static optss(p, pend-p);
+ if (0==(opt=sam2p_optval(p, pend-p))) {
+ badmsg="one_liner: unknown option: ";
+ bad_label:
+ Error::sev(Error::ERROR_CONT) << badmsg << (SimBuffer::B().appendDumpC(optss, true)) << (Error*)0;
+ badp=true;
+ continue;
+ }
+ if ((opt&15)==0) { /* no parameters */
+ if (*pend!='\0') { badmsg="one_liner: don't give param to option: "; goto bad_label; }
+ param=(char const*)NULLP;
+ } else if ((opt&15)==1) { /* an optional parameter */
+ if (*pend!='\0') {
+ param=pend+1; while (*pend==*param) param++;
+ } else param=(char const*)NULLP;
+ } else if ((opt&15)==2) { /* a mandatory parameter */
+ if (*pend!='\0') {
+ param=pend+1; while (*pend==*param) param++;
+ } else if ((param=*++a)==(char const*)NULLP) { badmsg="one_liner: missing param for option: "; goto bad_label; }
+ } else assert(0);
+ paramlen=param==(char const*)NULLP ? 0 : strlen(param);
+
+ /* Dat: now opt, paramlen and param are correct */
+ switch (opt) {
+ case OPT_LoadHints: LoadHints << ',' << param; break;
+ case OPT_TmpRemove: TmpRemove_p=GenBuffer::parseBool(param, paramlen); break;
+ case OPT_Transparent: Transparent=param; break; /* Imp: is this good memory management */
+ case OPT_Hints: Hints << '\n' << param; break;
+ case OPT_PSL1: FileFormat=Rule::Cache::FF_PSL1; break;
+ case OPT_PSLC: FileFormat=Rule::Cache::FF_PSLC; break;
+ case OPT_PSL2: FileFormat=Rule::Cache::FF_PSL2; break;
+ case OPT_PSL3: FileFormat=Rule::Cache::FF_PSL3; break;
+ case OPT_DisplayJobFile:
+ // fprintf(stderr, "param=(%s)\n", param);
+ if (paramlen==0 || 0==GenBuffer::nocase_strcmp(param, "job")) do_DisplayJobFile=true;
+ else if (0==GenBuffer::nocase_strcmp(param, "warn")) buildProfile_quiet=false;
+ else if (GenBuffer::nocase_strbegins(param, "warn:")) buildProfile_quiet=!GenBuffer::parseBool(param+5, paramlen-5);
+ else if (0==GenBuffer::nocase_strcmp(param, "quiet")) { buildProfile_quiet=true; Error::setTopPrinted(Error::ERROR_CONT); } /* Dat: hide warnings, info etc. */ /* at Fri Aug 26 07:54:00 CEST 2005 */
+ else if (GenBuffer::nocase_strbegins(param, "job:")) do_DisplayJobFile=GenBuffer::parseBool(param+4, paramlen-4);
+ else do_DisplayJobFile=GenBuffer::parseBool(param, paramlen); /* Imp: better error report */
+ break;
+ case OPT_Margins:
+ /* Dat:abbreviation letters are distinct: [ahxvylrtubd] */
+ if (0!=(p2=one_pabbr(param,"all:"))) { all5:
+ if (MiniPS::Real::isDimen(p2)) LeftMargin=RightMargin=TopMargin=BottomMargin=LowerMargin=p2;
+ else { err_dimexp: badmsg="one_liner: dimen expected: "; goto bad_label; }
+ }
+ else if (0!=(p2=one_pabbr(param,"horiz:"))
+ || 0!=(p2=one_pabbr(param,"x:"))) { if (MiniPS::Real::isDimen(p2)) LeftMargin=RightMargin=p2; else goto err_dimexp; }
+ else if (0!=(p2=one_pabbr(param,"vert:"))
+ || 0!=(p2=one_pabbr(param,"y:"))) { if (MiniPS::Real::isDimen(p2)) TopMargin=BottomMargin=LowerMargin=p2; else goto err_dimexp; }
+ else if (0!=(p2=one_pabbr(param,"left:"))) { if (MiniPS::Real::isDimen(p2)) LeftMargin=p2; else goto err_dimexp; }
+ else if (0!=(p2=one_pabbr(param,"right:"))) { if (MiniPS::Real::isDimen(p2)) RightMargin=p2; else goto err_dimexp; }
+ else if (0!=(p2=one_pabbr(param,"dpi:"))) { if (MiniPS::Real::isDimen(p2)) ImageDPI=p2; else goto err_dimexp; }
+ else if (0!=(p2=one_pabbr(param,"top:"))
+ || 0!=(p2=one_pabbr(param,"up:"))) { if (MiniPS::Real::isDimen(p2)) TopMargin=p2; else goto err_dimexp; }
+ else if (0!=(p2=one_pabbr(param,"bottom:"))
+ || 0!=(p2=one_pabbr(param,"down:"))) { if (MiniPS::Real::isDimen(p2)) BottomMargin=LowerMargin=p2; else goto err_dimexp; }
+ else if (0!=(p2=one_pabbr(param,"raise:"))) { if (MiniPS::Real::isDimen(p2)) LowerMargin=p2; else goto err_dimexp; }
+ else if (0!=(p2=one_pabbr(param,"lower:"))) { negLowerMargin=true; if (MiniPS::Real::isDimen(p2)) LowerMargin=p2; else goto err_dimexp; }
+ else { p2=param; goto all5; }
+ break;
+ case OPT_Scale:
+ if (paramlen==0 || 0==GenBuffer::nocase_strcmp(param, "scale")) Scale=Rule::CacheHints::SC_OK;
+ else if (0==GenBuffer::nocase_strcmp(param, "none")) Scale=Rule::CacheHints::SC_None;
+ else if (0==GenBuffer::nocase_strcmp(param, "rot")) Scale=Rule::CacheHints::SC_RotateOK;
+ else if (0==GenBuffer::nocase_strcmp(param, "rotate")) Scale=Rule::CacheHints::SC_RotateOK;
+ else Scale=(Rule::CacheHints::sc_t)(GenBuffer::parseBool(param, paramlen) ? 0+Rule::CacheHints::SC_OK : 0+Rule::CacheHints::SC_None);
+ /* ^^^ Imp: better error report */
+ /* ^^^ +0: pacify g++-3.1 */
+ break;
+ case OPT_TransferEncoding:
+ if (0==GenBuffer::nocase_strcmp(param, "bin")) TransferEncoding=Rule::Cache::TE_Binary;
+ else if (0==GenBuffer::nocase_strcmp(param, "hex")) TransferEncoding=Rule::Cache::TE_Hex;
+ else if (0==GenBuffer::nocase_strcmp(param, "a85")) TransferEncoding=Rule::Cache::TE_A85;
+ else if (0==GenBuffer::nocase_strcmp(param, "ascii"))TransferEncoding=Rule::Cache::TE_ASCII;
+ else if (0==GenBuffer::nocase_strcmp(param, "lsb1")) TransferEncoding=Rule::Cache::TE_LSBfirst;
+ else if (0==GenBuffer::nocase_strcmp(param, "msb1")) TransferEncoding=Rule::Cache::TE_MSBfirst;
+ else { inv_par: badmsg="one_liner: invalid param for option: "; goto bad_label; }
+ break;
+ case OPT_TransferEncodingF:
+ if (0==GenBuffer::nocase_strcmp(param, "lsb2msb")) TransferEncoding=Rule::Cache::TE_LSBfirst;
+ else if (0==GenBuffer::nocase_strcmp(param, "msb2lsb")) TransferEncoding=Rule::Cache::TE_MSBfirst;
+ else goto inv_par;
+ break;
+ case OPT_PS:
+ if (param==(char const*)NULLP || param[0]=='\0') FileFormat=Rule::Cache::FF_eps;
+ else if (0==GenBuffer::nocase_strcmp(param, "1")) FileFormat=Rule::Cache::FF_PSL1;
+ else if (0==GenBuffer::nocase_strcmp(param, "1c")
+ || 0==GenBuffer::nocase_strcmp(param, "c")) FileFormat=Rule::Cache::FF_PSLC;
+ else if (0==GenBuffer::nocase_strcmp(param, "2")) FileFormat=Rule::Cache::FF_PSL2;
+ else if (0==GenBuffer::nocase_strcmp(param, "3")) FileFormat=Rule::Cache::FF_PSL3;
+ else goto inv_par;
+ break;
+ case OPT_PDF:
+ if (param==(char const*)NULLP || param[0]=='\0') FileFormat=Rule::Cache::FF_pdfb;
+ else if (0==GenBuffer::nocase_strcmp(param, "b")) FileFormat=Rule::Cache::FF_pdfb; /* BI */
+ else if (0==GenBuffer::nocase_strcmp(param, "x")) FileFormat=Rule::Cache::FF_pdf; /* XObject */
+ else if (0==GenBuffer::nocase_strcmp(param, "b0")) FileFormat=Rule::Cache::FF_PDFB10;
+ else if (0==GenBuffer::nocase_strcmp(param, "b2")) FileFormat=Rule::Cache::FF_PDFB12;
+ else if (0==GenBuffer::nocase_strcmp(param, "0")) FileFormat=Rule::Cache::FF_PDF10;
+ else if (0==GenBuffer::nocase_strcmp(param, "2")) FileFormat=Rule::Cache::FF_PDF12;
+ else goto inv_par;
+ break;
+ case OPT_SampleFormat:
+ pend=param;
+ while (*pend!='\0') {
+ while (*pend==':') pend++;
+ if (do_stop_SampleFormat) goto inv_par; /* already stopped */
+ p=pend; while (*pend!='\0' && *pend!=':') pend++;
+ paramlen=pend-p;
+ if (4==paramlen && 0==memcmp(p,"stop",4)) { do_stop_SampleFormat=true; buildProfile_quiet=false; break; }
+ if (5==paramlen && 0==memcmp(p,"stopq",5)) { do_stop_SampleFormat=true; break; }
+ if (2==paramlen && 0==memcmp(p,"tr",2)) {
+ APPEND_sf(Image::SF_Transparent);
+ APPEND_sf(Image::SF_Opaque);
+ APPEND_sf(Image::SF_Mask);
+ APPEND_sf(Image::SF_Transparent2);
+ APPEND_sf(Image::SF_Transparent4);
+ APPEND_sf(Image::SF_Transparent8);
+ } else {
+ Image::sf_t sf=Rule::Cache::parseSampleFormat(p, paramlen);
+ if (sf==Image::SF_max) goto inv_par;
+ APPEND_sf(sf);
+ }
+ }
+ break;
+ case OPT_Compression:
+ assert(param!=(char const*)NULLP);
+ if (0==GenBuffer::nocase_strcmp(param, "none")) APPEND_co(Rule::Cache::CO_None);
+ else if (0==GenBuffer::nocase_strcmp(param, "lzw")) APPEND_co(Rule::Cache::CO_LZW);
+ else if (0==GenBuffer::nocase_strcmp(param, "zip")) APPEND_co(Rule::Cache::CO_ZIP);
+ else if (0==GenBuffer::nocase_strcmp(param, "rle")
+ || 0==GenBuffer::nocase_strcmp(param, "packbits")) APPEND_co(Rule::Cache::CO_RLE);
+ else if (0==GenBuffer::nocase_strcmp(param, "dct")) { APPEND_co(Rule::Cache::CO_DCT); Hints << "\n/DCT<<>>"; }
+ else if (0==GenBuffer::nocase_strcmp(param, "jpg")
+ || 0==GenBuffer::nocase_strcmp(param, "jpeg")) { APPEND_co(Rule::Cache::CO_JAI); APPEND_co(Rule::Cache::CO_IJG); }
+ else if (0==GenBuffer::nocase_strcmp(param, "ijg")) APPEND_co(Rule::Cache::CO_IJG);
+ else if (0==GenBuffer::nocase_strcmp(param, "g4")) { APPEND_co(Rule::Cache::CO_Fax); Hints << "\n/K -1"; }
+ else if (0==GenBuffer::nocase_strcmp(param, "g3")
+ || 0==GenBuffer::nocase_strcmp(param, "fax")
+ || 0==GenBuffer::nocase_strcmp(param, "g3:1d"))APPEND_co(Rule::Cache::CO_Fax);
+ else if (0==GenBuffer::nocase_strcmp(param, "g3:2d")){ APPEND_co(Rule::Cache::CO_Fax); Hints << "\n/K -2"; }
+ else if (0==GenBuffer::nocase_strcmp(param, "jai")) APPEND_co(Rule::Cache::CO_JAI);
+ else if (GenBuffer::nocase_strbegins(param, "lzw:")) {
+ SimBuffer::Static s(param+4);
+ unsigned long i; /* toInteger() is quickest on long */
+ if (s.toInteger(i)) goto inv_par;
+ APPEND_co(Rule::Cache::CO_LZW); Predictor=(Rule::Cache::pr_t)i;
+ } else if (GenBuffer::nocase_strbegins(param, "rle:")) {
+ SimBuffer::Static s(param+4);
+ unsigned long i; /* toInteger() is quickest on long */
+ if (s.toInteger(i)) goto inv_par;
+ APPEND_co(Rule::Cache::CO_RLE); Hints << "\n/RecordSize " << i;
+ } else if (GenBuffer::nocase_strbegins(param, "packbits:")) {
+ SimBuffer::Static s(param+9);
+ unsigned long i; /* toInteger() is quickest on long */
+ if (s.toInteger(i)) goto inv_par;
+ APPEND_co(Rule::Cache::CO_RLE); Hints << "\n/RecordSize " << i;
+ } else if (GenBuffer::nocase_strbegins(param, "fax:")) {
+ SimBuffer::Static s(param+4);
+ long i; /* toInteger() is quickest on long */
+ if (s.toInteger(i)) goto inv_par;
+ APPEND_co(Rule::Cache::CO_Fax); Hints << "\n/K " << i;
+ } else if (GenBuffer::nocase_strbegins(param, "dct:")) {
+ APPEND_co(Rule::Cache::CO_DCT); Hints << "\n/DCT<< " << (param+4) << " >>";
+ } else if (GenBuffer::nocase_strbegins(param, "ijg:")) {
+ SimBuffer::Static s(param+4);
+ unsigned long i; /* toInteger() is quickest on long */
+ if (s.toInteger(i)) goto inv_par;
+ APPEND_co(Rule::Cache::CO_IJG); Hints << "\n/Quality " << i;
+ } else if (GenBuffer::nocase_strbegins(param, "jpeg:")) {
+ SimBuffer::Static s(param+5);
+ unsigned long i; /* toInteger() is quickest on long */
+ if (s.toInteger(i)) goto inv_par;
+ APPEND_co(Rule::Cache::CO_JAI);
+ APPEND_co(Rule::Cache::CO_IJG); Hints << "\n/Quality " << i;
+ } else if (GenBuffer::nocase_strbegins(param, "zip:")) {
+ pend=param+4; while (*pend!='\0' && *pend!=':') pend++;
+ SimBuffer::Static s(param+4, pend-param-4);
+ unsigned long i; /* toInteger() is quickest on long */
+ if (s.toInteger(i)) goto inv_par;
+ APPEND_co(Rule::Cache::CO_ZIP); Predictor=(Rule::Cache::pr_t)i;
+ if (*pend==':') {
+ pend++; while (*pend==':') pend++;
+ SimBuffer::Static s(pend);
+ if (s.toInteger(i)) goto inv_par;
+ // Error::sev(Error::FATAL) << "SUXX)" << s << ',' << i << '.' << (Error*)0;
+ APPEND_co(Rule::Cache::CO_ZIP); Hints << "\n/Effort " << i;
+ // Error::sev(Error::FATAL) << "SUXX(" << s << ',' << Hints << '.' << (Error*)0;
+ }
+ } else goto inv_par;
+ break;
+ default: assert(0);
+ }
+ } else { /* a selector or a normal argument */
+ if (!(no_selector && no_option_term)) goto normal_label;
+ pend=p; while (*pend!='\0' && *pend!=':') pend++;
+ if (pend-p>=2 && *pend==':') { /* an ImageMagick-style FileFormat selector */
+ if (GenBuffer::nocase_strbegins(p, "PSL2:")
+ || GenBuffer::nocase_strbegins(p, "EPS2:")) FileFormat=Rule::Cache::FF_PSL2;
+ else if (GenBuffer::nocase_strbegins(p, "EPS:")) FileFormat=Rule::Cache::FF_eps;
+ else if (GenBuffer::nocase_strbegins(p, "PS2:")) { FileFormat=Rule::Cache::FF_PSL2; if (Scale==Rule::CacheHints::SC_default) Scale=Rule::CacheHints::SC_RotateOK; }
+ else if (GenBuffer::nocase_strbegins(p, "PS:")) { FileFormat=Rule::Cache::FF_eps; if (Scale==Rule::CacheHints::SC_default) Scale=Rule::CacheHints::SC_RotateOK; }
+ else if (GenBuffer::nocase_strbegins(p, "PSL1:")) FileFormat=Rule::Cache::FF_PSL1;
+ else if (GenBuffer::nocase_strbegins(p, "PSLC:")) FileFormat=Rule::Cache::FF_PSLC;
+ else if (GenBuffer::nocase_strbegins(p, "PSL3:")) FileFormat=Rule::Cache::FF_PSL3;
+ else if (GenBuffer::nocase_strbegins(p, "PDF:")
+ || GenBuffer::nocase_strbegins(p, "PDF:")) FileFormat=Rule::Cache::FF_pdfb;
+ else if (GenBuffer::nocase_strbegins(p, "PDFX:")) FileFormat=Rule::Cache::FF_pdf;
+ else if (GenBuffer::nocase_strbegins(p, "PDFB1.0:")) FileFormat=Rule::Cache::FF_PDFB10;
+ else if (GenBuffer::nocase_strbegins(p, "PDFB1.2:")) FileFormat=Rule::Cache::FF_PDFB12;
+ else if (GenBuffer::nocase_strbegins(p, "PDF1.0:")) FileFormat=Rule::Cache::FF_PDF10;
+ else if (GenBuffer::nocase_strbegins(p, "PDF1.2:")) FileFormat=Rule::Cache::FF_PDF12;
+ else if (GenBuffer::nocase_strbegins(p, "GIF89a:")
+ || GenBuffer::nocase_strbegins(p, "GIF:")) FileFormat=Rule::Cache::FF_GIF89a;
+ /* vvv do_stop_SampleFormat BUGFIX at Thu Nov 21 23:44:20 CET 2002 */
+ else if (GenBuffer::nocase_strbegins(p, "PNM:")) { FileFormat=Rule::Cache::FF_PNM; APPEND_sf(Image::SF_Gray1); APPEND_sf(Image::SF_Gray8); APPEND_sf(Image::SF_Rgb8); APPEND_sf(Image::SF_Transparent8); do_stop_SampleFormat=true; }
+ else if (GenBuffer::nocase_strbegins(p, "PBM:")) { FileFormat=Rule::Cache::FF_PNM; APPEND_sf(Image::SF_Gray1); do_stop_SampleFormat=true; }
+ else if (GenBuffer::nocase_strbegins(p, "PGM:")) { FileFormat=Rule::Cache::FF_PNM; APPEND_sf(Image::SF_Gray8); do_stop_SampleFormat=true; }
+ else if (GenBuffer::nocase_strbegins(p, "PPM:")) { FileFormat=Rule::Cache::FF_PNM; APPEND_sf(Image::SF_Rgb8); do_stop_SampleFormat=true; }
+ else if (GenBuffer::nocase_strbegins(p, "PAM:")) FileFormat=Rule::Cache::FF_PAM;
+ else if (GenBuffer::nocase_strbegins(p, "PIP:")) FileFormat=Rule::Cache::FF_PIP;
+ else if (GenBuffer::nocase_strbegins(p, "Empty:"))FileFormat=Rule::Cache::FF_Empty;
+ else if (GenBuffer::nocase_strbegins(p, "Meta:")) FileFormat=Rule::Cache::FF_Meta;
+ else if (GenBuffer::nocase_strbegins(p, "JPEG:")
+ || GenBuffer::nocase_strbegins(p, "JPG:")) FileFormat=Rule::Cache::FF_JPEG;
+ else if (GenBuffer::nocase_strbegins(p, "TIFF:")
+ || GenBuffer::nocase_strbegins(p, "TIF:")) FileFormat=Rule::Cache::FF_TIFF;
+ else if (GenBuffer::nocase_strbegins(p, "PNG:")) FileFormat=Rule::Cache::FF_PNG;
+ else if (GenBuffer::nocase_strbegins(p, "XPM:")) FileFormat=Rule::Cache::FF_XPM;
+ else if (GenBuffer::nocase_strbegins(p, "BMP:")
+ || GenBuffer::nocase_strbegins(p, "RLE:")) { FileFormat=Rule::Cache::FF_BMP; /*APPEND_co(Rule::Cache::CO_RLE);*/ }
+ else if (GenBuffer::nocase_strbegins(p, "XWD:")) FileFormat=Rule::Cache::FF_XWD;
+ else if (GenBuffer::nocase_strbegins(p, "X11:")) FileFormat=Rule::Cache::FF_X11;
+ else {
+ Error::sev(Error::ERROR_CONT) << "one_liner: invalid FileFormat selector: " << (SimBuffer::B().appendDumpC(SimBuffer::Static(p, pend-p), true)) << (Error*)0;
+ badp=true;
+ continue;
+ }
+ no_selector=false;
+ while (*pend==':') pend++;
+ if (*pend=='\0') continue; /* this arg is just a selector */
+ /* normal argument is coming */
+ p=pend;
+ }
+ normal_label:
+ if (InputFile==(char const*)NULLP) {
+ InputFile=p; /* set it even on error */
+ /* vvv since Sat Apr 19 13:37:57 CEST 2003:
+ * Possibly unseekable STDIN is handled by Filter::UngetFILED
+ */
+ #if 0
+ if (p[0]=='-' && p[1]=='\0') { /* Filename: STDIN */
+ Files::set_binary_mode(0, true);
+ if (0!=fseek(stdin, 0L, 0)) { unseekable:
+ #if 0
+ Error::sev(Error::ERROR_CONT) << "one_liner: `-' (stdin) not allowed as InputFile (stdin unseekable)" << (Error*)0;
+ badp=true; continue;
+ #endif
+ FILE *f=Files::open_tmpnam(tmpnam);
+ if (!f) { Error::sev(Error::ERROR_CONT) << "one_liner: cannot open" << " temporary file for `-' (stdin)" << (Error*)0; badp=true; continue; }
+ tmpnam.term0();
+ Files::tmpRemoveCleanup(InputFile=tmpnam());
+ char *buf=new char[4096];
+ unsigned got;
+ while (
+ (0<(got=fread(buf, 1, sizeof(buf), stdin)))
+ && got==fwrite(buf, 1, sizeof(buf), f)) {}
+ delete [] buf;
+ if (ferror(f) || 0!=fclose(f) || ferror(stdin))
+ { Error::sev(Error::ERROR_CONT) << "one_liner: cannot write" << " temporary file for `-' (stdin)" << (Error*)0; badp=true; continue; }
+ // fprintf(stderr, "if=(%s)\n", InputFile);
+ continue;
+ /* Imp: report `-' as filename on errors etc. */
+ }
+ int c=MACRO_GETC(stdin);
+ if (0!=fseek(stdin, 0L, 0)) { if (c>=0) ungetc(c, stdin); goto unseekable; } /* active test */
+ /* ungetc() is not necessary because of fseek() */
+ }
+ #endif
+ } else if (OutputFile==(char const*)NULLP) { /* Filename: STDOUT */
+ Files::set_binary_mode(1, true);
+ OutputFile=p;
+ if (FileFormat==Rule::Cache::FF_default) { /* OutputFile; determine FileFormat from extension */
+ pend=p+strlen(p);
+ while (pend!=p && *pend!='.') pend--;
+ /* ^^^ Dat: extra care later for /a/b.c/d */
+ if (pend!=p) { /* have extension */
+ assert(*pend=='.'); pend++;
+ if (0==GenBuffer::nocase_strcmp(pend, "eps")
+ || 0==GenBuffer::nocase_strcmp(pend, "epsi")
+ || 0==GenBuffer::nocase_strcmp(pend, "epsf")) FileFormat=Rule::Cache::FF_eps;
+ else if (0==GenBuffer::nocase_strcmp(pend, "ps")) { FileFormat=Rule::Cache::FF_eps; if (Scale==Rule::CacheHints::SC_default) Scale=Rule::CacheHints::SC_RotateOK; }
+ else if (0==GenBuffer::nocase_strcmp(pend, "pdf")) FileFormat=Rule::Cache::FF_pdfb;
+ else if (0==GenBuffer::nocase_strcmp(pend, "gif")) FileFormat=Rule::Cache::FF_GIF89a;
+ else if (0==GenBuffer::nocase_strcmp(pend, "pnm")) { FileFormat=Rule::Cache::FF_PNM; APPEND_sf(Image::SF_Gray1); APPEND_sf(Image::SF_Gray8); APPEND_sf(Image::SF_Rgb8); APPEND_sf(Image::SF_Transparent8); do_stop_SampleFormat=true; }
+ else if (0==GenBuffer::nocase_strcmp(pend, "pbm")) { FileFormat=Rule::Cache::FF_PNM; APPEND_sf(Image::SF_Gray1); do_stop_SampleFormat=true; }
+ else if (0==GenBuffer::nocase_strcmp(pend, "pgm")) { FileFormat=Rule::Cache::FF_PNM; APPEND_sf(Image::SF_Gray8); do_stop_SampleFormat=true; }
+ else if (0==GenBuffer::nocase_strcmp(pend, "ppm")) { FileFormat=Rule::Cache::FF_PNM; APPEND_sf(Image::SF_Rgb8); do_stop_SampleFormat=true; }
+ else if (0==GenBuffer::nocase_strcmp(pend, "pam")) FileFormat=Rule::Cache::FF_PAM;
+ else if (0==GenBuffer::nocase_strcmp(pend, "pip")) FileFormat=Rule::Cache::FF_PIP;
+ else if (0==GenBuffer::nocase_strcmp(pend, "empty"))FileFormat=Rule::Cache::FF_Empty;
+ else if (0==GenBuffer::nocase_strcmp(pend, "meta")) FileFormat=Rule::Cache::FF_Meta;
+ else if (0==GenBuffer::nocase_strcmp(pend, "jpeg")
+ || 0==GenBuffer::nocase_strcmp(pend, "jpg")) FileFormat=Rule::Cache::FF_JPEG;
+ else if (0==GenBuffer::nocase_strcmp(pend, "tiff")
+ || 0==GenBuffer::nocase_strcmp(pend, "tif")) FileFormat=Rule::Cache::FF_TIFF;
+ else if (0==GenBuffer::nocase_strcmp(pend, "png")) FileFormat=Rule::Cache::FF_PNG;
+ else if (0==GenBuffer::nocase_strcmp(pend, "xpm")) FileFormat=Rule::Cache::FF_XPM;
+ else if (0==GenBuffer::nocase_strcmp(pend, "bmp")
+ || 0==GenBuffer::nocase_strcmp(pend, "rle")) { FileFormat=Rule::Cache::FF_BMP; /*APPEND_co(Rule::Cache::CO_RLE);*/ }
+ else if (0==GenBuffer::nocase_strcmp(pend, "xwd")) FileFormat=Rule::Cache::FF_XWD;
+ // else if (0==GenBuffer::nocase_strcmp(pend, "x11")) FileFormat=Rule::Cache::FF_X11;
+ /* ^^^ .x11 extension is useless */
+ }
+ }
+ } else {
+ Error::sev(Error::ERROR_CONT) << "one_liner: got too many (>2) filenames" << (Error*)0;
+ badp=true;
+ continue;
+ }
+ } /* IF */
+ } /* NEXT */
+
+ if (InputFile==(char const*)NULLP) {
+ Error::sev(Error::ERROR_CONT) << "one_liner: InputFile unspecified" << (Error*)0;
+ badp=true;
+ }
+ if (OutputFile==(char const*)NULLP) {
+ Error::sev(Error::ERROR_CONT) << "one_liner: OutputFile unspecified" << (Error*)0;
+ badp=true;
+ }
+ if (FileFormat==Rule::Cache::FF_default) {
+ Error::sev(Error::ERROR_CONT) << "one_liner: FileFormat unspecified" << (Error*)0;
+ badp=true;
+ }
+ if (badp) return true;
+
+ int prcc = (colen==0) ? 2 : 1;
+ if (colen==0) { /* apply default if Compression is unspecified */
+ // Error::sev(Error::FATAL) << "FileFormat=" << (unsigned)FileFormat << (Error*)0;
+ switch (FileFormat) {
+ case Rule::Cache::FF_TIFF:
+ case Rule::Cache::FF_eps: case Rule::Cache::FF_PSL2:
+ case Rule::Cache::FF_PDFB10: case Rule::Cache::FF_PDF10:
+ APPEND_co(Rule::Cache::CO_JAI);
+ #if HAVE_LZW
+ APPEND_co(Rule::Cache::CO_LZW);
+ #endif
+ APPEND_co(Rule::Cache::CO_RLE);
+ APPEND_co(Rule::Cache::CO_None); break;
+ case Rule::Cache::FF_BMP:
+ case Rule::Cache::FF_PSL1: case Rule::Cache::FF_PSLC:
+ /* assert(0); */
+ APPEND_co(Rule::Cache::CO_RLE);
+ APPEND_co(Rule::Cache::CO_None); break;
+ case Rule::Cache::FF_PSL3:
+ case Rule::Cache::FF_pdfb: /* BUGFIX at Sun Sep 22 14:57:03 CEST 2002 */
+ case Rule::Cache::FF_pdf:
+ case Rule::Cache::FF_PDFB12: case Rule::Cache::FF_PDF12:
+ APPEND_co(Rule::Cache::CO_JAI);
+ APPEND_co(Rule::Cache::CO_ZIP);
+ APPEND_co(Rule::Cache::CO_None); break;
+ case Rule::Cache::FF_GIF89a:
+ APPEND_co(Rule::Cache::CO_LZW); /* _not_ /LZWEncode filter */
+ APPEND_co(Rule::Cache::CO_None); break;
+ case Rule::Cache::FF_JPEG:
+ APPEND_co(Rule::Cache::CO_JAI);
+ APPEND_co(Rule::Cache::CO_IJG); break;
+ case Rule::Cache::FF_PNG:
+ APPEND_co(Rule::Cache::CO_ZIP); break;
+ default:
+ APPEND_co(Rule::Cache::CO_None); break;
+ /* for others FileFormats: CO_None, but that is _not_ appended anyway */
+ }
+ } else {
+ if ((int)Predictor == 55 || (int)Predictor == 45) {
+ Error::sev(Error::WARNING) << "predictor: /Predictor " << (int)Predictor
+ << " is inefficient; use /Predictor 15 instead" << (Error*)0;
+ }
+ }
+ /* Dat: don't append /Compression/None if the user has specified `-c'. The
+ * user can append `-c none' manually.
+ */
+
+ if (Scale==Rule::CacheHints::SC_default) Scale=Rule::CacheHints::SC_None;
+ if (TransferEncoding==Rule::Cache::TE_default) { /* apply default if TransferEncoding is unspecified */
+ switch (FileFormat) {
+ case Rule::Cache::FF_PSL1: case Rule::Cache::FF_PSLC:
+ TransferEncoding=(Rule::Cache::te_t)(cox[Rule::Cache::CO_ZIP]!=0 ||
+ cox[Rule::Cache::CO_LZW]!=0 ? 0+Rule::Cache::TE_A85 : 0+Rule::Cache::TE_Hex); break;
+ /* ^^^ Dat: /Hex is default for /RLE */
+ case Rule::Cache::FF_eps: case Rule::Cache::FF_PSL2:
+ case Rule::Cache::FF_PSL3:
+ TransferEncoding=Rule::Cache::TE_A85; break;
+ #if 0 /* useless bugfix */
+ case Rule::Cache::FF_XPM: /* BUGFIX at Thu Jul 11 21:53:56 CEST 2002 */
+ // assert(0);
+ TransferEncoding=Rule::Cache::TE_ASCII; break;
+ #endif
+ default:
+ TransferEncoding=Rule::Cache::TE_Binary; break;
+ }
+ }
+
+ unsigned coc=colen;
+
+ /* Smart verify whether /Compression/JAI is requested. If so, and the input
+ * file is JPEG, then load it as-is. Our heuristic is that if the user
+ * allowed /Compression/JAI among others, and the input file is a baseline
+ * JPEG, then /Compression/JAI will be the best (and only) compression
+ * method.
+ */
+ bool jaip=cox[Rule::Cache::CO_JAI]!=0;
+ if (jaip) {
+ if (ufd==NULLP) ufd=new Filter::UngetFILED(InputFile, stdin,
+ Filter::UngetFILED::CM_closep|Filter::UngetFILED::CM_keep_stdinp);
+ /* vvv Imp: no error handling */
+ if (1!=jai_is_baseline_jpeg(ufd)) { jaip=false; coc--; cox[Rule::Cache::CO_JAI]=0; }
+ ufd->seek(0);
+#if 0
+ assert(ufd->vi_getcc()==255);
+ assert(ufd->vi_getcc()==0xd8);
+ assert(ufd->vi_getcc()==255+0);
+ assert(0);
+#endif
+ }
+
+ if (jaip) { /* Dat: might have changed to false */
+ APPEND_sf(Image::SF_Asis);
+ LoadHints << ",jpeg-asis,";
+ cot[0]=Rule::Cache::CO_JAI; colen=1; /* disable all other compression */
+ } else if (coc==1 && cox[Rule::Cache::CO_Fax]!=0) {
+ APPEND_sf(Image::SF_Opaque);
+ APPEND_sf(Image::SF_Transparent);
+ APPEND_sf(Image::SF_Gray1);
+ APPEND_sf(Image::SF_Indexed1);
+ APPEND_sf(Image::SF_Mask);
+ } else if (coc==1 && (cox[Rule::Cache::CO_DCT]!=0 || cox[Rule::Cache::CO_IJG]!=0)) {
+ APPEND_sf(Image::SF_Opaque);
+ APPEND_sf(Image::SF_Transparent);
+ APPEND_sf(Image::SF_Gray8);
+ APPEND_sf(Image::SF_Rgb8);
+ } else if (!do_stop_SampleFormat) {
+ /* JAI compression is automatically disabled since jaip==false */
+ /* Guess SampleFormat automatically. The order is significant, so most
+ * warnings emitted by Image::SampledInfo::setSampleFormat() are avoided.
+ */
+ APPEND_sf(Image::SF_Opaque);
+ APPEND_sf(Image::SF_Transparent);
+ APPEND_sf(Image::SF_Gray1);
+ APPEND_sf(Image::SF_Indexed1);
+ APPEND_sf(Image::SF_Mask);
+ APPEND_sf(Image::SF_Gray2);
+ APPEND_sf(Image::SF_Indexed2);
+ APPEND_sf(Image::SF_Rgb1);
+ APPEND_sf(Image::SF_Gray4);
+ APPEND_sf(Image::SF_Indexed4);
+ APPEND_sf(Image::SF_Rgb2);
+ APPEND_sf(Image::SF_Gray8);
+ APPEND_sf(Image::SF_Indexed8);
+ APPEND_sf(Image::SF_Rgb4);
+ APPEND_sf(Image::SF_Rgb8);
+ APPEND_sf(Image::SF_Transparent2); /* transparents are put last because of expensive color separation */
+ APPEND_sf(Image::SF_Transparent4);
+ APPEND_sf(Image::SF_Transparent8);
+ }
+
+ /* Append more Hints */
+ if (Scale!=Rule::CacheHints::SC_None) Hints << "\n/Scale /" << protect_null(Rule::CacheHints::dumpScale(Scale));
+ if ((char const*)NULLP!=ImageDPI) Hints << "\n/ImageDPI " << ImageDPI;
+ if ((char const*)NULLP!=LeftMargin) Hints << "\n/LeftMargin " << LeftMargin;
+ if ((char const*)NULLP!=RightMargin) Hints << "\n/RightMargin " << RightMargin;
+ if ((char const*)NULLP!=TopMargin) Hints << "\n/TopMargin " << TopMargin;
+ if ((char const*)NULLP!=BottomMargin) Hints << "\n/BottomMargin " << BottomMargin;
+ if ((char const*)NULLP!=LowerMargin) {
+ Hints << "\n/LowerMargin ";
+ if (negLowerMargin) {
+ if (LowerMargin[0]=='-') Hints << (LowerMargin+1);
+ else Hints << '-' << LowerMargin;
+ } else Hints << LowerMargin;
+ }
+
+ /* Emit job file */
+ jobss << "<<%sam2p in-memory job file, autogenerated by " << Error::banner0
+ << "\n/InputFile ";
+ jobss.appendDumpPS(SimBuffer::Static(InputFile), true);
+ jobss << "\n/OutputFile ";
+ jobss.appendDumpPS(SimBuffer::Static(OutputFile), true);
+ jobss << "\n/LoadHints ";
+ jobss.appendDumpPS(LoadHints, true);
+ jobss << "\n/TmpRemove " << (TmpRemove_p ? "true" : "false");
+ jobss << "\n/Profile[\n";
+
+ unsigned coi, sfi;
+ slen_t orc=0;
+ int prc;
+ bool is_predictor_recommended;
+ for (sfi=0;sfi<sflen;sfi++) { for (coi=0;coi<colen;coi++) {
+ // for (coi=0;coi<colen;coi++) for (sfi=0;sfi<sflen;sfi++)
+ Rule::Cache::co_t co=cot[coi];
+ Image::sf_t sf=sft[sfi];
+ if (co==Rule::Cache::CO_JAI) {
+ if (!jaip || sf!=Image::SF_Asis) continue;
+ }
+ for (prc=prcc; prc>0; --prc) {
+ /* Add an extra predictor only for LZW or ZIP, appropriate SampleFormat
+ * and if the `-c' command line option was not specified.
+ * So if the user specifies `-c zip', he won't get a predictor by
+ * default; but if he specifies no `-c', he might get a `-c:zip:15'.
+ * To get the smallest file size, he should specify `-c zip:15:9'.
+ *
+ * The value we assign to is_predictor_recommended comes from the
+ * do_filter = ... assignment in png_write_IHDR() in pngwutil.c of
+ * libpng-1.2.15 .
+ */
+ is_predictor_recommended = (
+ sf==Image::SF_Gray8 || sf==Image::SF_Rgb8);
+ if (prc>1 && ((co!=Rule::Cache::CO_LZW && co!=Rule::Cache::CO_ZIP) ||
+ !is_predictor_recommended)) continue;
+ jobss << "<<% OutputRule #" << orc++
+ << "\n /FileFormat /" << protect_null(Rule::Cache::dumpFileFormat(FileFormat, co))
+ << "\n /TransferEncoding /" << protect_null(Rule::Cache::dumpTransferEncoding(TransferEncoding))
+ << "\n /SampleFormat /" << protect_null(Rule::Cache::dumpSampleFormat(sf))
+ << "\n /Compression /" << protect_null(Rule::Cache::dumpCompression (co))
+ << "\n /Predictor " << (int)(co==Rule::Cache::CO_LZW || co==Rule::Cache::CO_ZIP ?
+ /* If no compression (or predictor) specified, try predictor 15, then 1; otherwise try the specified predictor */
+ /* +0 down there to avoid linking problems with g++ on Mac OS X 10.5.6 */
+ (prc>1 ? Rule::Cache::PR_PNGAuto+0 : Predictor != Rule::Cache::PR_PNGAutoMaybe ? Predictor : is_predictor_recommended ? Rule::Cache::PR_PNGAuto+0 : Rule::Cache::PR_None+0) : Rule::Cache::PR_None+0)
+ << "\n /Hints << " << Hints << " >>";
+ // jobss << " /Transparent (\377\377\377)\n";
+ if (Transparent!=NULL) {
+ jobss << "\n /Transparent ";
+ jobss.appendDumpPS(SimBuffer::Static(Transparent), true);
+ }
+ jobss << "\n>>\n";
+ }
+ }
+ }
+ jobss << "]>>% __EOF__\n";
+
+ /* Common keys not emited here:
+ * /TmpRemove true /Templates pop
+ * /ColorTransform pop
+ * /EncoderColumns 0 /EncoderBPL 0 /EncoderRows 0 /EncoderColors 0
+ * /PredictorColumns 0 /PredictorBPC 0 /PredictorColors 0
+ * /Transparent null
+ * /WarningOK true
+ * /Comment pop
+ * /Title pop
+ * /Subject pop
+ * /Author pop
+ * /Creator pop
+ * /Producer pop
+ * /Created pop
+ * /Produced pop
+ */
+ return false;
+ #undef APPEND_sf
+ #undef APPEND_co
+} /* one_liner() */
+
+static bool option_eq(char const *arg, char const*option) {
+ if (option[0]=='-') { option++; while (arg[0]=='-') arg++; }
+ return 0==GenBuffer::nocase_strcmp(arg, option);
+}
+
+void init_sam2p_engine(char const*argv0) {
+ Error::long_argv0=argv0==(char const*)NULLP ? "sam2p" : argv0;
+ Error::argv0=Files::only_fext(Error::long_argv0);
+ Error::tmpargv0="_sam2p_";
+ Error::banner0="sam2p " SAM2P_VERSION;
+}
+
+/* --- */
+
+/* Never returns. */
+int run_sam2p_engine(Files::FILEW &sout, Files::FILEW &serr, char const*const*argv1, bool helpp) {
+ class SerrResetter {
+ public:
+ SerrResetter(GenBuffer::Writable *old_serr_): old_serr(old_serr_) {}
+ ~SerrResetter() { Error::serr = old_serr; }
+ private:
+ GenBuffer::Writable *old_serr;
+ } serr_resetter(Error::serr);
+ Error::serr=&serr;
+
+ /* --- Parse arguments, generate/read .job file */
+
+ MiniPS::VALUE job=MiniPS::Qundef;
+ Filter::FlatD bts(bts_ttt);
+ ufd=(Filter::UngetFILED*)NULLP;
+ if (!helpp && argv1[0]!=(char const*)NULLP && argv1[1]==(char const*)NULLP) {
+ /* A single argument: must be the name of the .job file */
+ MiniPS::Parser p(argv1[0]);
+ p.addSpecRun("%bts", &bts); /* bts: Built-in TemplateS, the bts.ttt file in the sources */
+ job=p.parse1();
+ if (p.parse1(p.EOF_ALLOWED)!=MiniPS::Qundef)
+ Error::sev(Error::EERROR) << "job: the .job file should contain a single job" << (Error*)0;
+ /* ^^^ Dat: the result of the second p.parse1() doesn't get delete0(...)d */
+ } else if (helpp || argv1[0]==(char const*)NULLP) { help: /* help message */
+ sout << "Usage: " << Error::long_argv0 << " <filename.job>\n" <<
+ " " << Error::long_argv0 << " [options] <in.img> [OutputFormat:] <out.img>\n" <<
+ "Example: " << Error::long_argv0 << " test.gif EPS: test.eps\n";
+ if (helpp) Error::cexit(Error::runCleanups(0));
+ Error::sev(Error::EERROR) << "Incorrect command line" << (Error*)0;
+ } else { /* one_liner */
+ SimBuffer::B jobss;
+ if (one_liner(jobss, argv1)) goto help;
+ if (do_DisplayJobFile) displayJob(sout, jobss);
+ Filter::FlatD jobr(jobss(), jobss.getLength());
+ MiniPS::Parser p(&jobr);
+ p.addSpecRun("%bts", &bts); /* bts: Built-in TemplateS, the bts.ttt file in the sources */
+ if (MiniPS::Qerror==(job=p.parse1(p.EOF_ILLEGAL, Error::ERROR_CONT))
+ || p.parse1(p.EOF_ALLOWED)!=MiniPS::Qundef
+ ) {
+ displayJob(sout, jobss);
+ Error::sev(Error::EERROR) << "job: in-memory .job file corrupt (bug?" "?)" << (Error*)0;
+ /* ^^^ Dat: the result of the second p.parse1() doesn't get delete0(...)d */
+ }
+ }
+ Files::doSignalCleanup();
+
+ /* --- Pre-parse .job file */
+
+ /* Dat: memory storage for the MiniPS objects in the .job file are
+ * allocated by p.parse1() and freed by MiniPS::delete0(job). Other
+ * structures throughout this program hold pointers to inside `job',
+ * but storage is not copied.
+ */
+
+ MiniPS::String *InputFile, *OutputFile, *LoadHints;
+ MiniPS::Array *Profile;
+ MiniPS::VALUE TmpRemove;
+ MiniPS::scanf_dict(job, /*show_warnings:*/true,
+ "InputFile", MiniPS::T_STRING, MiniPS::Qundef, &InputFile,
+ "OutputFile", MiniPS::T_STRING, MiniPS::Qundef, &OutputFile,
+ "LoadHints", MiniPS::T_STRING, MiniPS::Qnull, &LoadHints,
+ "Templates", MiniPS::T_DICT, MiniPS::Qnull, &Rule::Templates,
+ "Profile", MiniPS::T_ARRAY, MiniPS::Qundef, &Profile,
+ "TmpRemove", MiniPS::T_BOOLEAN,MiniPS::Qtrue, &TmpRemove, /* remove temporary files upon exit? */
+ NULLP
+ );
+ // MiniPS::dump(sout, job, 1);
+ Files::tmpRemove=TmpRemove==MiniPS::Qtrue;
+ if (MiniPS::Qnull==(MiniPS::VALUE)Rule::Templates) {
+ Filter::FlatD flatd("<< (%bts) run >>");
+ MiniPS::Parser p(&flatd);
+ p.addSpecRun("%bts", &bts);
+ Rule::Templates=(MiniPS::Dict*)p.parse1();
+ MiniPS::RDICT(job)->put("/Templates", (MiniPS::VALUE)Rule::Templates); /* Takes ownership, deletes the previous value. */
+ }
+
+ /* --- Preprocess Appliers */
+
+ Rule::OutputRule *rule_list=Rule::buildProfile((MiniPS::VALUE)Profile, buildProfile_quiet);
+
+ /* --- Read/open other files */
+
+ if ((MiniPS::VALUE)LoadHints==MiniPS::Qnull) { /* smart default */
+ /* This isn't reached by default (sam2p t.png t.pdf), becuase `job'
+ * already contains /LoadHints ().
+ */
+
+ if (!rule_list[0].isEOL() && rule_list[0].cache.Compression==Rule::Cache::CO_JAI) {
+ LoadHints=new MiniPS::String("jpeg-asis",4); /* used by in_jai.cpp and in_jpeg.cpp; even TIFF/JPEG */
+ } else {
+ LoadHints=new MiniPS::String("",0);
+ }
+ MiniPS::RDICT(job)->put("/LoadHints", (MiniPS::VALUE)LoadHints); /* Takes ownership, deletes the previous value. */
+ }
+
+ /* vvv may raise tons of error messages */
+ // InputFile->term0(); /* always term0() for MiniPS::String */
+ if (ufd==NULLP) ufd=new Filter::UngetFILED(InputFile->begin_(), stdin,
+ Filter::UngetFILED::CM_closep|Filter::UngetFILED::CM_keep_stdinp);
+ // fprintf(stderr, "ufd=%p\n", ufd);
+ Image::SampledInfo info(Image::load(
+ #if 0
+ InputFile->begin_(), /* knows about stdin `-' */
+ SimBuffer::B(",",1, LoadHints->begin_(),LoadHints->getLength(), ",",1 ).term0() /* three-way concatentation */
+ #else
+ (Image::Loader::UFD*)ufd,
+ SimBuffer::B(",",1, LoadHints->begin_(),LoadHints->getLength(), ",",1 ).term0(), /* three-way concatentation */
+ /*format:*/(char const*)NULLP
+ #endif
+ ));
+ Error::sev(Error::NOTICE) << "job: read InputFile: " <<
+ FNQ2STDOK(InputFile->begin_(),InputFile->getLength()) << (Error*)0;
+ delete ufd;
+ // assert(0);
+
+ bool overwrite=false;
+ if (0==strcmp(InputFile->begin_(), OutputFile->begin_()) && 0!=strcmp("-", InputFile->begin_())) {
+ // Error::sev(Error::WARNING) << "job: InputFile == OutputFile" << (Error*)0;
+ OutputFile->replace(OutputFile->begin_(), OutputFile->getLength(), ".s2new", 6);
+ overwrite=true;
+ }
+ FILE *of=stdout;
+ if (OutputFile->getLength()!=1 || OutputFile->begin_()[0]!='-') {
+ if ((of=fopen(OutputFile->begin_(), "wb"))==(FILE*)NULLP) {
+ Error::sev(Error::EERROR) << "job: cannot rewrite OutputFile: " << FNQ2STDOK(OutputFile->begin_(),OutputFile->getLength()) << (Error*)0;
+ }
+ /*if (!overwrite)*/
+ Files::tmpRemoveCleanup(OutputFile->begin_(), &of);
+ } else Files::set_binary_mode(1, true);
+
+ /* --- Find and apply best applier */
+
+ Files::FILEW wf(of);
+ Rule::applyProfile(wf, rule_list, &info);
+
+ /* --- Done, flush files and clean up. */
+
+ fflush(of);
+ if (ferror(of)) {
+ /* FILE *backup=of; of=(FILE*)NULLP; fclose(backup); */
+ Error::sev(Error::EERROR) << "job: error writing OutputFile: " << FNQ2STDOK(OutputFile->begin_(),OutputFile->getLength()) << (Error*)0;
+ }
+ if (of!=stdout) { /* Don't interfere with tmpRemoveCleanup() */
+ FILE *backup=of; of=(FILE*)NULLP; fclose(backup);
+ }
+ if (overwrite) {
+ if (0!=rename(OutputFile->begin_(), InputFile->begin_())) {
+ // remove(OutputFile->begin_()); /* tmpRemoveCleanup() does it */
+ Error::sev(Error::EERROR) << "job: error renaming, InputFile left intact" << (Error*)0;
+ }
+ }
+ Error::sev(Error::NOTICE) << "job: written OutputFile: " << FNQ2STDOK(OutputFile->begin_(),OutputFile->getLength()) << (Error*)0;
+
+ /* Freeing memory may cause segfaults because of possibly
+ * bad code design :-(. Luckily we have already saved the output file.
+ */
+ Rule::deleteProfile(rule_list);
+ MiniPS::delete0(job); /* frees OutputFile etc. */
+
+ bool successp = Error::getTopPrinted()+0<=Error::NOTICE+0;
+ int exitCode = Error::runCleanups(0);
+ fflush(stdout); fflush(stderr);
+ if (successp && exitCode == 0)
+ fputs("Success.\n", stderr);
+ /* Don't do Error::cexit(exitCode);, it won't run destructors of
+ * stack-allocated objects, and valgrind will complain about leaking memory.
+ */
+ return exitCode;
+}
+
+/** main: process entry point for the sam2p utility. */
+int main(int, char const*const* argv) {
+ Files::FILEW sout(stdout);
+ Files::FILEW serr(stderr);
+ /* --- Initialize */
+
+ bool helpp=argv[0]==(char const*)NULLP || (argv[0]!=(char const*)NULLP && argv[1]!=(char const*)NULLP && argv[2]==(char const*)NULLP && (
+ option_eq(argv[1], "-help") ||
+ option_eq(argv[1], "-h") ||
+ option_eq(argv[1], "-?") ||
+ option_eq(argv[1], "/h") ||
+ option_eq(argv[1], "/?")));
+ bool versionp=argv[0]!=(char const*)NULLP && argv[1]!=(char const*)NULLP && argv[2]==(char const*)NULLP && (
+ option_eq(argv[1], "-version") ||
+ option_eq(argv[1], "-v"));
+ bool quietp=argv[0]!=(char const*)NULLP && argv[1]!=(char const*)NULLP &&
+ option_eq(argv[1], "-j:quiet");
+ init_sam2p_engine(argv[0]);
+
+ if (versionp) {
+ sout << "This is " << Error::banner0 << ".\n";
+ return 0;
+ }
+
+ /* Don't print diagnostics to stdout, becuse it might be the OutputFile */
+ if (!quietp) { serr << "This is " << Error::banner0 << ".\n"; }
+ init_loader();
+ if (!quietp) { serr << "Available Loaders:"; Image::printLoaders(serr); serr << ".\n"; }
+ init_applier();
+ if (!quietp) { serr << "Available Appliers:"; Rule::printAppliers(serr); serr << ".\n"; }
+
+ return run_sam2p_engine(
+ sout, serr, argv+(argv[0]!=(char const*)NULLP), helpp);
+}
diff --git a/graphics/sam2p/sam2p_pdf_scale.pl b/graphics/sam2p/sam2p_pdf_scale.pl
new file mode 100755
index 0000000000..9347e27272
--- /dev/null
+++ b/graphics/sam2p/sam2p_pdf_scale.pl
@@ -0,0 +1,110 @@
+#! /bin/sh
+eval '(exit $?0)' && eval 'PERL_BADLANG=x;PATH="$PATH:.";export PERL_BADLANG\
+ PATH;exec perl -x -S -- "$0" ${1+"$@"};#'if 0;eval 'setenv PERL_BADLANG x\
+;setenv PATH "$PATH":.;exec perl -x -S -- "$0" $argv:q;#'.q
+#!perl -w
++push@INC,'.';$0=~/(.*)/s;do(index($1,"/")<0?"./$1":$1);die$@if$@__END__+if 0
+;#Don't touch/remove lines 1--7: http://www.inf.bme.hu/~pts/Magic.Perl.Header
+#
+# sam2p_pdf_scale.pl: scale PDF created by sam2p to page size
+# by pts@fazekas.hu at Sat Jun 6 17:16:17 CEST 2009
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# TODO(pts): Rotate the image by 90 degrees if necessary.
+
+use integer;
+use strict;
+die "Usage: $0 <page-width-bp> <page-height-bp> <input.pdf> [<output.pdf>]\n".
+ "This program reads a PDF generated by sam2p, ".
+ "and scales it to page size.\n" if @ARGV != 3 and @ARGV != 4;
+die "page-width not a nonnegative number\n" if $ARGV[0] !~ m@\A[\d.]+\Z(?!\n)@;
+die "page-height not a nonnegative number\n"
+ if $ARGV[1] !~ m@\A[\d.]+\Z(?!\n)@;
+sub float2str($) {
+ no integer;
+ my $F = $_[0] + 0;
+ $F = "$F";
+ if (index($F, 'e') >= 0) {
+ $F = sprintf("%.20f", $F);
+ $F =~ s@[.]?0+\Z@@;
+ }
+ $F
+}
+#** Desired page size dimensions. Must be integers, measured in bp (inch/72).
+my $dwidth = float2str($ARGV[0]);
+my $dheight = float2str($ARGV[1]);
+my $outfn = @ARGV == 4 ? $ARGV[3] : $ARGV[2];
+my $F;
+die "cannot open input PDF: $ARGV[2]: $!\n" if !open($F, '<', $ARGV[2]);
+my $S = join('', <$F>);
+die if !close($F);
+die "sam2p PDF syntax error (no cm)\n" if $S!~m@\n((\d+) 0 0 (\d+) 0 0 cm\b)@g;
+my $cm_at = pos($S) - length($1);
+my $cm_size = length($1);
+my $iwidth = $2 + 0;
+my $iheight = $3 + 0;
+die "sam2p PDF image error (empty image)\n" if $iwidth < 0 or $iheight < 0;
+my $rest_at = rindex($S, "\nendstream\n") + 1;
+die "sam2p PDF syntax error (no endstream)\n" if $rest_at <= $cm_at;
+pos($S) = $rest_at;
+die "sam2p PDF syntax error (boxes not found)\n" if
+ $S!~m@(/MediaBox\s*\[0 0 (\d+) (\d+)\]\s*/CropBox\s*\[0 0 (\d+) (\d+)\])@g;
+my $boxes_at = pos($S) - length($1);
+my $boxes_size = length($1);
+die "sam2p PDF syntax error (image size mismatch)\n" if
+ $2 ne $iwidth or $3 ne $iheight or
+ $4 ne $iwidth or $5 ne $iheight;
+my $boxes_new =
+ "/MediaBox[0 0 $dwidth $dheight]\n/CropBox[0 0 $dwidth $dheight]";
+substr($S, $boxes_at, $boxes_size) = $boxes_new;
+my($cwidth, $cheight);
+my($xshift, $yshift);
+{ no integer;
+ my $aheight = $iheight * $dwidth / $iwidth;
+ my $bwidth = $iwidth * $dheight / $iheight;
+ if ($aheight <= $dheight) { ($cwidth, $cheight) = ($dwidth, $aheight) }
+ else { ($cwidth, $cheight) = ($bwidth, $dheight) }
+ $xshift = ($dwidth - $cwidth) / 2;
+ $yshift = ($dheight - $cheight) / 2;
+}
+my $cm_new = float2str($cwidth)." 0 0 ".float2str($cheight)." ".
+ float2str($xshift)." ".float2str($yshift)." cm";
+substr($S, $cm_at, $cm_size) = $cm_new;
+pos($S) = 0;
+if ($S =~ m@\n<</Length ((\d+)>>\nstream\nq\n)@g and pos($S) == $cm_at) {
+ substr($S, pos($S) - length($1), length($2)) =
+ sprintf("%".length($2)."d", $2 + length($cm_new) - $cm_size);
+}
+pos($S) = $boxes_at + length($boxes_new) + length($cm_new) - $cm_size;
+die "sam2p PDF syntax error (xref not found)\n" if
+ $S!~m@\sendobj\n(xref\n0 (\d+)\n0000000000 65535 f \n)@g;
+my $xref_at = pos($S) - length($1);
+my $obj_count = $2 - 1;
+my $ofss_at = pos($S);
+for (my $I = 1; $I <= $obj_count; ++$I) {
+ my $xrefe_at = $ofss_at + ($I - 1) * 20;
+ my $xrefe = substr($S, $xrefe_at, 20);
+ die "sam2p PDF syntax error (xref entry $I bad)\n" if
+ $xrefe!~m@\A(\d{10}) 00000 n \n\Z(?!\n)@;
+ my $ofs = $1 + 0;
+ $ofs += (
+ ($ofs >= $boxes_at) ? length($boxes_new) - $boxes_size +
+ length($cm_new) - $cm_size :
+ ($ofs >= $cm_at) ? length($cm_new) - $cm_size : 0);
+ substr($S, $xrefe_at, 20) = sprintf("%010d 00000 n \n", $ofs);
+}
+pos($S) = $ofss_at + $obj_count * 20;
+die "sam2p PDF syntax error (startxref not found)\n" if
+ $S!~s@\nstartxref\n(\d+)\n@\nstartxref\n$xref_at\n@;
+die "cannot open output PDF: $outfn: $!\n" if !open($F, '>', $outfn);
+die if !print($F $S);
+die if !close($F);
diff --git a/graphics/sam2p/snprintf.c b/graphics/sam2p/snprintf.c
new file mode 100644
index 0000000000..1649808f1a
--- /dev/null
+++ b/graphics/sam2p/snprintf.c
@@ -0,0 +1,996 @@
+/*
+ * snprintf.c
+ * ripped from rsync sources by pts@inf.bme.hu at Thu Mar 7 18:16:00 CET 2002
+ * ripped from reTCP sources by pts@fazekas.hu at Tue Jun 11 14:47:01 CEST 2002
+ *
+ * Why does this .c file rock?
+ *
+ * -- minimal dependencies: only <stdarg.h> is included
+ * -- minimal dependencies: not even -lm is required
+ * -- can print floating point numbers
+ * -- can print `long long' and `long double'
+ * -- C99 semantics (NULL arg for vsnprintf OK, always returns the length
+ * that would have been printed)
+ * -- provides all vsnprintf(), snprintf(), vasprintf(), asprintf()
+ */
+
+/**** pts: sam2p-specific defines ****/
+#include "snprintf.h"
+/* #include <stdarg.h> -- from snprintf.h */
+#define P_CONST PTS_const
+#ifdef NULL /* as on Mac OS/X 10.5.7 <stdlib.h> */
+# undef NULL
+#endif
+#define NULL ((void*)0)
+#ifdef __cplusplus
+# define malloc ::operator new
+#else
+# include <stdlib.h> /* malloc() */
+#endif
+#define size_t slen_t /* normally defined in <sys/types.h> */
+#define sizeret_t slen_t /* normally: int, unsigned */
+#undef HAVE_LONG_DOUBLE
+#undef HAVE_LONG_LONG
+#undef HAVE_C99_VSNPRINTF /* force local implementation */
+#undef HAVE_ASPRINTF
+#undef HAVE_VASPRINTF
+#undef TEST_SNPRINTF
+#undef DEBUG_SNPRINTF
+#define NEED_SPRINTF 1
+#define vsnprintf fixup_vsnprintf
+#define snprintf fixup_snprintf
+#define vasprintf fixup_vasprintf
+#define asprintf fixup_asprintf
+#define sprintf fixup_sprintf
+typedef slen_t ret_t;
+
+/* vvv repeat prototypes in snprintf.h */
+EXTERN_C sizeret_t fixup_vsnprintf(char *str, size_t count, P_CONST char *fmt, va_list args);
+EXTERN_C sizeret_t fixup_snprintf(char *str,size_t count,P_CONST char *fmt,...);
+EXTERN_C sizeret_t fixup_vasprintf(char **ptr, P_CONST char *format, va_list ap);
+EXTERN_C sizeret_t fixup_asprintf(char **ptr, P_CONST char *format, ...);
+EXTERN_C sizeret_t fixup_sprintf(char *ptr, P_CONST char *format, ...);
+
+/*
+ * Copyright Patrick Powell 1995
+ * This code is based on code written by Patrick Powell (papowell@astart.com)
+ * It may be used for any purpose as long as this notice remains intact
+ * on all source code distributions
+ */
+
+/**************************************************************
+ * Original:
+ * Patrick Powell Tue Apr 11 09:48:21 PDT 1995
+ * A bombproof version of doprnt (dopr) included.
+ * Sigh. This sort of thing is always nasty do deal with. Note that
+ * the version here does not include floating point...
+ *
+ * snprintf() is used instead of sprintf() as it does limit checks
+ * for string length. This covers a nasty loophole.
+ *
+ * The other functions are there to prevent NULL pointers from
+ * causing nast effects.
+ *
+ * More Recently:
+ * Brandon Long <blong@fiction.net> 9/15/96 for mutt 0.43
+ * This was ugly. It is still ugly. I opted out of floating point
+ * numbers, but the formatter understands just about everything
+ * from the normal C string format, at least as far as I can tell from
+ * the Solaris 2.5 printf(3S) man page.
+ *
+ * Brandon Long <blong@fiction.net> 10/22/97 for mutt 0.87.1
+ * Ok, added some minimal floating point support, which means this
+ * probably requires libm on most operating systems. Don't yet
+ * support the exponent (e,E) and sigfig (g,G). Also, fmtint()
+ * was pretty badly broken, it just wasn't being exercised in ways
+ * which showed it, so that's been fixed. Also, formated the code
+ * to mutt conventions, and removed dead code left over from the
+ * original. Also, there is now a builtin-test, just compile with:
+ * gcc -DTEST_SNPRINTF -o snprintf snprintf.c -lm
+ * and run snprintf for results.
+ *
+ * Thomas Roessler <roessler@guug.de> 01/27/98 for mutt 0.89i
+ * The PGP code was using unsigned hexadecimal formats.
+ * Unfortunately, unsigned formats simply didn't work.
+ *
+ * Michael Elkins <me@cs.hmc.edu> 03/05/98 for mutt 0.90.8
+ * The original code assumed that both snprintf() and vsnprintf() were
+ * missing. Some systems only have snprintf() but not vsnprintf(), so
+ * the code is now broken down under HAVE_SNPRINTF and HAVE_VSNPRINTF.
+ *
+ * Andrew Tridgell (tridge@samba.org) Oct 1998
+ * fixed handling of %.0f
+ * added test for HAVE_LONG_DOUBLE
+ *
+ * tridge@samba.org, idra@samba.org, April 2001
+ * got rid of fcvt code (twas buggy and made testing harder)
+ * added C99 semantics
+ *
+ **************************************************************/
+
+
+#if defined(HAVE_SNPRINTF) && defined(HAVE_VSNPRINTF) && defined(HAVE_C99_VSNPRINTF)
+/* only include stdio.h if we are not re-defining snprintf or vsnprintf */
+#include <stdio.h>
+ /* make the compiler happy with an empty file */
+ void dummy_snprintf(void) {}
+#else
+
+#if HAVE_LONG_DOUBLE && NEED_LONG_DOUBLE
+#define LDOUBLE long double
+#else
+#define LDOUBLE double
+#endif
+
+#if HAVE_LONG_LONG && NEED_LONG_LONG
+#define LLONG long long
+#else
+#define LLONG long
+#endif
+
+static size_t dopr(char *buffer, size_t maxlen, P_CONST char *format,
+ va_list args);
+static void fmtstr(char *buffer, size_t *currlen, size_t maxlen,
+ char *value, int flags, int min, int max);
+static void fmtint(char *buffer, size_t *currlen, size_t maxlen,
+ long value, int base, int min, int max, int flags);
+static void fmtfp(char *buffer, size_t *currlen, size_t maxlen,
+ LDOUBLE fvalue, int min, int max, int flags);
+static void dopr_outch(char *buffer, size_t *currlen, size_t maxlen, char c);
+
+/*
+ * dopr(): poor man's version of doprintf
+ */
+
+/* format read states */
+#define DP_S_DEFAULT 0
+#define DP_S_FLAGS 1
+#define DP_S_MIN 2
+#define DP_S_DOT 3
+#define DP_S_MAX 4
+#define DP_S_MOD 5
+#define DP_S_CONV 6
+#define DP_S_DONE 7
+
+/* format flags - Bits */
+#define DP_F_MINUS (1 << 0)
+#define DP_F_PLUS (1 << 1)
+#define DP_F_SPACE (1 << 2)
+#define DP_F_NUM (1 << 3)
+#define DP_F_ZERO (1 << 4)
+#define DP_F_UP (1 << 5)
+#define DP_F_UNSIGNED (1 << 6)
+
+/* Conversion Flags */
+#define DP_C_SHORT 1
+#define DP_C_LONG 2
+#define DP_C_LDOUBLE 3
+#define DP_C_LLONG 4
+
+#define char_to_int(p) ((p)- '0')
+#ifndef MAX
+#define MAX(p,q) (((p) >= (q)) ? (p) : (q))
+#endif
+
+/**** pts ****/
+#undef isdigit
+#define isdigit(c) ((unsigned char)((c)-'0')<=(unsigned char)('9'-'0'))
+
+static size_t dopr(char *buffer, size_t maxlen, P_CONST char *format, va_list args)
+{
+ char ch;
+ LLONG value;
+ LDOUBLE fvalue;
+ char *strvalue;
+ int min;
+ int max;
+ int state;
+ int flags;
+ int cflags;
+ size_t currlen;
+
+ state = DP_S_DEFAULT;
+ currlen = flags = cflags = min = 0;
+ max = -1;
+ ch = *format++;
+
+ while (state != DP_S_DONE) {
+ if (ch == '\0')
+ state = DP_S_DONE;
+
+ switch(state) {
+ case DP_S_DEFAULT:
+ if (ch == '%')
+ state = DP_S_FLAGS;
+ else
+ dopr_outch (buffer, &currlen, maxlen, ch);
+ ch = *format++;
+ break;
+ case DP_S_FLAGS:
+ switch (ch) {
+ case '-':
+ flags |= DP_F_MINUS;
+ ch = *format++;
+ break;
+ case '+':
+ flags |= DP_F_PLUS;
+ ch = *format++;
+ break;
+ case ' ':
+ flags |= DP_F_SPACE;
+ ch = *format++;
+ break;
+ case '#':
+ flags |= DP_F_NUM;
+ ch = *format++;
+ break;
+ case '0':
+ flags |= DP_F_ZERO;
+ ch = *format++;
+ break;
+ default:
+ state = DP_S_MIN;
+ break;
+ }
+ break;
+ case DP_S_MIN:
+ if (isdigit((unsigned char)ch)) {
+ min = 10*min + char_to_int (ch);
+ ch = *format++;
+ } else if (ch == '*') {
+ min = va_arg (args, int);
+ ch = *format++;
+ state = DP_S_DOT;
+ } else {
+ state = DP_S_DOT;
+ }
+ break;
+ case DP_S_DOT:
+ if (ch == '.') {
+ state = DP_S_MAX;
+ ch = *format++;
+ } else {
+ state = DP_S_MOD;
+ }
+ break;
+ case DP_S_MAX:
+ if (isdigit((unsigned char)ch)) {
+ if (max < 0)
+ max = 0;
+ max = 10*max + char_to_int (ch);
+ ch = *format++;
+ } else if (ch == '*') {
+ max = va_arg (args, int);
+ ch = *format++;
+ state = DP_S_MOD;
+ } else {
+ state = DP_S_MOD;
+ }
+ break;
+ case DP_S_MOD:
+ switch (ch) {
+ case 'h':
+ cflags = DP_C_SHORT;
+ ch = *format++;
+ break;
+ case 'l':
+ cflags = DP_C_LONG;
+ ch = *format++;
+ if (ch == 'l') { /* It's a long long */
+ cflags = DP_C_LLONG;
+ ch = *format++;
+ }
+ break;
+ case 'L':
+ cflags = DP_C_LDOUBLE;
+ ch = *format++;
+ break;
+ default:
+ break;
+ }
+ state = DP_S_CONV;
+ break;
+ case DP_S_CONV:
+ switch (ch) {
+ case 'd':
+ case 'i':
+ if (cflags == DP_C_SHORT)
+ value = va_arg (args, int);
+ else if (cflags == DP_C_LONG)
+ value = va_arg (args, long int);
+ else if (cflags == DP_C_LLONG)
+ value = va_arg (args, LLONG);
+ else
+ value = va_arg (args, int);
+ fmtint (buffer, &currlen, maxlen, value, 10, min, max, flags);
+ break;
+ case 'o':
+ flags |= DP_F_UNSIGNED;
+ if (cflags == DP_C_SHORT)
+ value = va_arg (args, unsigned int);
+ else if (cflags == DP_C_LONG)
+ value = (long)va_arg (args, unsigned long int);
+ else if (cflags == DP_C_LLONG)
+ value = (long)va_arg (args, unsigned LLONG);
+ else
+ value = (long)va_arg (args, unsigned int);
+ fmtint (buffer, &currlen, maxlen, value, 8, min, max, flags);
+ break;
+ case 'u':
+ flags |= DP_F_UNSIGNED;
+ if (cflags == DP_C_SHORT)
+ value = va_arg (args, unsigned int);
+ else if (cflags == DP_C_LONG)
+ value = (long)va_arg (args, unsigned long int);
+ else if (cflags == DP_C_LLONG)
+ value = (LLONG)va_arg (args, unsigned LLONG);
+ else
+ value = (long)va_arg (args, unsigned int);
+ fmtint (buffer, &currlen, maxlen, value, 10, min, max, flags);
+ break;
+ case 'X':
+ flags |= DP_F_UP;
+ case 'x':
+ flags |= DP_F_UNSIGNED;
+ if (cflags == DP_C_SHORT)
+ value = va_arg (args, unsigned int);
+ else if (cflags == DP_C_LONG)
+ value = (long)va_arg (args, unsigned long int);
+ else if (cflags == DP_C_LLONG)
+ value = (LLONG)va_arg (args, unsigned LLONG);
+ else
+ value = (long)va_arg (args, unsigned int);
+ fmtint (buffer, &currlen, maxlen, value, 16, min, max, flags);
+ break;
+ case 'f':
+ if (cflags == DP_C_LDOUBLE)
+ fvalue = va_arg (args, LDOUBLE);
+ else
+ fvalue = va_arg (args, double);
+ /* um, floating point? */
+ fmtfp (buffer, &currlen, maxlen, fvalue, min, max, flags);
+ break;
+ case 'E':
+ flags |= DP_F_UP;
+ case 'e':
+ if (cflags == DP_C_LDOUBLE)
+ fvalue = va_arg (args, LDOUBLE);
+ else
+ fvalue = va_arg (args, double);
+ break;
+ case 'G':
+ flags |= DP_F_UP;
+ case 'g':
+ if (cflags == DP_C_LDOUBLE)
+ fvalue = va_arg (args, LDOUBLE);
+ else
+ fvalue = va_arg (args, double);
+ break;
+ case 'c':
+ dopr_outch (buffer, &currlen, maxlen, (char)va_arg (args, int));
+ break;
+ case 's':
+ strvalue = va_arg (args, char *);
+ if (max == -1) {
+ /**** pts ****/
+ for (max = 0; strvalue[max]; ++max); /* strlen */
+ }
+ if (min > 0 && max >= 0 && min > max) max = min;
+ fmtstr (buffer, &currlen, maxlen, strvalue, flags, min, max);
+ break;
+ case 'p':
+ strvalue = (char*)(va_arg (args, void *));
+ fmtint (buffer, &currlen, maxlen, (long) strvalue, 16, min, max, flags);
+ break;
+ case 'n':
+ if (cflags == DP_C_SHORT) {
+ short int *num;
+ num = va_arg (args, short int *);
+ *num = currlen;
+ } else if (cflags == DP_C_LONG) {
+ long int *num;
+ num = va_arg (args, long int *);
+ *num = (long int)currlen;
+ } else if (cflags == DP_C_LLONG) {
+ LLONG *num;
+ num = va_arg (args, LLONG *);
+ *num = (LLONG)currlen;
+ } else {
+ int *num;
+ num = va_arg (args, int *);
+ *num = currlen;
+ }
+ break;
+ case '%':
+ dopr_outch (buffer, &currlen, maxlen, ch);
+ break;
+ case 'w':
+ /* not supported yet, treat as next char */
+ ch = *format++;
+ break;
+ default:
+ /* Unknown, skip */
+ break;
+ }
+ ch = *format++;
+ state = DP_S_DEFAULT;
+ flags = cflags = min = 0;
+ max = -1;
+ break;
+ case DP_S_DONE:
+ break;
+ default:
+ /* hmm? */
+ break; /* some picky compilers need this */
+ }
+ }
+ if (maxlen != 0) {
+ if (currlen < maxlen - 1)
+ buffer[currlen] = '\0';
+ else if (maxlen > 0)
+ buffer[maxlen - 1] = '\0';
+ }
+
+ return currlen;
+}
+
+static void fmtstr(char *buffer, size_t *currlen, size_t maxlen,
+ char *value, int flags, int min, int max)
+{
+ int padlen, strln; /* amount to pad */
+ int cnt = 0;
+
+#ifdef DEBUG_SNPRINTF
+ printf("fmtstr min=%d max=%d s=[%s]\n", min, max, value);
+#endif
+ if (value == 0) {
+ value = (char*)"<NULL>";
+ }
+
+ for (strln = 0; value[strln]; ++strln); /* strlen */
+ padlen = min - strln;
+ if (padlen < 0)
+ padlen = 0;
+ if (flags & DP_F_MINUS)
+ padlen = -padlen; /* Left Justify */
+
+ while ((padlen > 0) && (cnt < max)) {
+ dopr_outch (buffer, currlen, maxlen, ' ');
+ --padlen;
+ ++cnt;
+ }
+ while (*value && (cnt < max)) {
+ dopr_outch (buffer, currlen, maxlen, *value++);
+ ++cnt;
+ }
+ while ((padlen < 0) && (cnt < max)) {
+ dopr_outch (buffer, currlen, maxlen, ' ');
+ ++padlen;
+ ++cnt;
+ }
+}
+
+/* Have to handle DP_F_NUM (ie 0x and 0 alternates) */
+
+static void fmtint(char *buffer, size_t *currlen, size_t maxlen,
+ long value, int base, int min, int max, int flags)
+{
+ int signvalue = 0;
+ unsigned long uvalue;
+ char convert[20];
+ int place = 0;
+ int spadlen = 0; /* amount to space pad */
+ int zpadlen = 0; /* amount to zero pad */
+ int caps = 0;
+
+ if (max < 0)
+ max = 0;
+
+ uvalue = value;
+
+ if(!(flags & DP_F_UNSIGNED)) {
+ if( value < 0 ) {
+ signvalue = '-';
+ uvalue = -value;
+ } else {
+ if (flags & DP_F_PLUS) /* Do a sign (+/i) */
+ signvalue = '+';
+ else if (flags & DP_F_SPACE)
+ signvalue = ' ';
+ }
+ }
+
+ if (flags & DP_F_UP) caps = 1; /* Should characters be upper case? */
+
+ do {
+ convert[place++] =
+ (caps? "0123456789ABCDEF":"0123456789abcdef")
+ [uvalue % (unsigned)base ];
+ uvalue = (uvalue / (unsigned)base );
+ } while(uvalue && (place < 20));
+ if (place == 20) place--;
+ convert[place] = 0;
+
+ zpadlen = max - place;
+ spadlen = min - MAX (max, place) - (signvalue ? 1 : 0);
+ if (zpadlen < 0) zpadlen = 0;
+ if (spadlen < 0) spadlen = 0;
+ if (flags & DP_F_ZERO) {
+ zpadlen = MAX(zpadlen, spadlen);
+ spadlen = 0;
+ }
+ if (flags & DP_F_MINUS)
+ spadlen = -spadlen; /* Left Justifty */
+
+#ifdef DEBUG_SNPRINTF
+ printf("zpad: %d, spad: %d, min: %d, max: %d, place: %d\n",
+ zpadlen, spadlen, min, max, place);
+#endif
+
+ /* Spaces */
+ while (spadlen > 0) {
+ dopr_outch (buffer, currlen, maxlen, ' ');
+ --spadlen;
+ }
+
+ /* Sign */
+ if (signvalue)
+ dopr_outch (buffer, currlen, maxlen, (char)signvalue); /* pacify VC6.0 */
+
+ /* Zeros */
+ if (zpadlen > 0) {
+ while (zpadlen > 0) {
+ dopr_outch (buffer, currlen, maxlen, '0');
+ --zpadlen;
+ }
+ }
+
+ /* Digits */
+ while (place > 0)
+ dopr_outch (buffer, currlen, maxlen, convert[--place]);
+
+ /* Left Justified spaces */
+ while (spadlen < 0) {
+ dopr_outch (buffer, currlen, maxlen, ' ');
+ ++spadlen;
+ }
+}
+
+static LDOUBLE abs_val(LDOUBLE value)
+{
+ LDOUBLE result = value;
+
+ if (value < 0)
+ result = -value;
+
+ return result;
+}
+
+static LDOUBLE POW10(int exp)
+{
+ LDOUBLE result = 1;
+
+ while (exp) {
+ result *= 10;
+ exp--;
+ }
+
+ return result;
+}
+
+static LLONG ROUND(LDOUBLE value)
+{
+ LLONG intpart;
+
+ intpart = (LLONG)value;
+ value = value - intpart;
+ if (value >= 0.5) intpart++;
+
+ return intpart;
+}
+
+/* a replacement for modf that doesn't need the math library. Should
+ be portable, but slow */
+static double my_modf(double x0, double *iptr)
+{
+ int i;
+ long l=0;
+ double x = x0;
+ double f = 1.0;
+
+ for (i=0;i<100;i++) {
+ l = (long)x;
+ if (l <= (x+1) && l >= (x-1)) break;
+ x *= 0.1;
+ f *= 10.0;
+ }
+
+ if (i == 100) {
+ /* yikes! the number is beyond what we can handle. What do we do? */
+ (*iptr) = 0;
+ return 0;
+ }
+
+ if (i != 0) {
+ double i2;
+ double ret;
+
+ ret = my_modf(x0-l*f, &i2);
+ (*iptr) = l*f + i2;
+ return ret;
+ }
+
+ (*iptr) = l;
+ return x - (*iptr);
+}
+
+
+static void fmtfp (char *buffer, size_t *currlen, size_t maxlen,
+ LDOUBLE fvalue, int min, int max, int flags)
+{
+ int signvalue = 0;
+ double ufvalue;
+ char iconvert[311];
+ char fconvert[311];
+ int iplace = 0;
+ int fplace = 0;
+ int padlen = 0; /* amount to pad */
+ int zpadlen = 0;
+ int caps = 0;
+ int index;
+ double intpart;
+ double fracpart;
+ double temp;
+
+ /*
+ * AIX manpage says the default is 0, but Solaris says the default
+ * is 6, and sprintf on AIX defaults to 6
+ */
+ if (max < 0)
+ max = 6;
+
+ ufvalue = abs_val (fvalue);
+
+ if (fvalue < 0) {
+ signvalue = '-';
+ } else {
+ if (flags & DP_F_PLUS) { /* Do a sign (+/i) */
+ signvalue = '+';
+ } else {
+ if (flags & DP_F_SPACE)
+ signvalue = ' ';
+ }
+ }
+
+#if 0
+ if (flags & DP_F_UP) caps = 1; /* Should characters be upper case? */
+#endif
+
+#if 0
+ if (max == 0) ufvalue += 0.5; /* if max = 0 we must round */
+#endif
+
+ /*
+ * Sorry, we only support 16 digits past the decimal because of our
+ * conversion method
+ */
+ if (max > 16)
+ max = 16;
+
+ /* We "cheat" by converting the fractional part to integer by
+ * multiplying by a factor of 10
+ */
+
+ temp = ufvalue;
+ my_modf(temp, &intpart);
+
+ fracpart = ROUND((POW10(max)) * (ufvalue - intpart));
+
+ if (fracpart >= POW10(max)) {
+ intpart++;
+ fracpart -= POW10(max);
+ }
+
+
+ /* Convert integer part */
+ do {
+ temp = intpart;
+ my_modf(intpart*0.1, &intpart);
+ temp = temp*0.1;
+ index = (int) ((temp -intpart +0.05)* 10.0);
+ /* index = (int) (((double)(temp*0.1) -intpart +0.05) *10.0); */
+ /* printf ("%llf, %f, %x\n", temp, intpart, index); */
+ iconvert[iplace++] =
+ (caps? "0123456789ABCDEF":"0123456789abcdef")[index];
+ } while (intpart && (iplace < 311));
+ if (iplace == 311) iplace--;
+ iconvert[iplace] = 0;
+
+ /* Convert fractional part */
+ if (fracpart)
+ {
+ do {
+ temp = fracpart;
+ my_modf(fracpart*0.1, &fracpart);
+ temp = temp*0.1;
+ index = (int) ((temp -fracpart +0.05)* 10.0);
+ /* index = (int) ((((temp/10) -fracpart) +0.05) *10); */
+ /* printf ("%lf, %lf, %ld\n", temp, fracpart, index); */
+ fconvert[fplace++] =
+ (caps? "0123456789ABCDEF":"0123456789abcdef")[index];
+ } while(fracpart && (fplace < 311));
+ if (fplace == 311) fplace--;
+ }
+ fconvert[fplace] = 0;
+
+ /* -1 for decimal point, another -1 if we are printing a sign */
+ padlen = min - iplace - max - 1 - ((signvalue) ? 1 : 0);
+ zpadlen = max - fplace;
+ if (zpadlen < 0) zpadlen = 0;
+ if (padlen < 0)
+ padlen = 0;
+ if (flags & DP_F_MINUS)
+ padlen = -padlen; /* Left Justifty */
+
+ if ((flags & DP_F_ZERO) && (padlen > 0)) {
+ if (signvalue) {
+ dopr_outch (buffer, currlen, maxlen, (char)signvalue);
+ --padlen;
+ signvalue = 0;
+ }
+ while (padlen > 0) {
+ dopr_outch (buffer, currlen, maxlen, '0');
+ --padlen;
+ }
+ }
+ while (padlen > 0) {
+ dopr_outch (buffer, currlen, maxlen, ' ');
+ --padlen;
+ }
+ if (signvalue)
+ dopr_outch (buffer, currlen, maxlen, (char)signvalue);
+
+ while (iplace > 0)
+ dopr_outch (buffer, currlen, maxlen, iconvert[--iplace]);
+
+#ifdef DEBUG_SNPRINTF
+ printf("fmtfp: fplace=%d zpadlen=%d\n", fplace, zpadlen);
+#endif
+
+ /*
+ * Decimal point. This should probably use locale to find the correct
+ * char to print out.
+ */
+ if (max > 0) {
+ dopr_outch (buffer, currlen, maxlen, '.');
+
+ while (fplace > 0)
+ dopr_outch (buffer, currlen, maxlen, fconvert[--fplace]);
+ }
+
+ while (zpadlen > 0) {
+ dopr_outch (buffer, currlen, maxlen, '0');
+ --zpadlen;
+ }
+
+ while (padlen < 0) {
+ dopr_outch (buffer, currlen, maxlen, ' ');
+ ++padlen;
+ }
+}
+
+static void dopr_outch(char *buffer, size_t *currlen, size_t maxlen, char c)
+{
+ if (*currlen < maxlen) {
+ buffer[(*currlen)] = c;
+ }
+ (*currlen)++;
+}
+
+#if !defined(HAVE_VSNPRINTF) || !defined(HAVE_C99_VSNPRINTF)
+ sizeret_t vsnprintf (char *str, size_t count, P_CONST char *fmt, va_list args)
+{
+ return dopr(str, count, fmt, args);
+}
+#endif
+
+#if !defined(HAVE_SNPRINTF) || !defined(HAVE_C99_VSNPRINTF)
+ sizeret_t snprintf(char *str,size_t count,P_CONST char *fmt,...)
+{
+ size_t ret;
+ va_list ap;
+
+ PTS_va_start(ap, fmt);
+ ret = vsnprintf(str, count, fmt, ap);
+ va_end(ap);
+ return ret;
+}
+#endif
+
+#endif
+
+#ifndef HAVE_VASPRINTF
+ sizeret_t vasprintf(char **ptr, P_CONST char *format, va_list ap)
+{
+ size_t ret;
+
+ ret = vsnprintf((char*)NULL, 0, format, ap);
+ if (ret+1 <= 1) return ret; /* pts: bit of old unsigned trick... */
+
+ if (NULLP==(*ptr = (char *)malloc(ret+1))) return (sizeret_t)-1;
+ ret = vsnprintf(*ptr, ret+1, format, ap);
+
+ return ret;
+}
+#endif
+
+
+#ifndef HAVE_ASPRINTF
+ sizeret_t asprintf(char **ptr, P_CONST char *format, ...)
+{
+ va_list ap;
+ sizeret_t ret;
+
+ PTS_va_start(ap, format);
+ ret = vasprintf(ptr, format, ap);
+ va_end(ap);
+
+ return ret;
+}
+#endif
+
+/**** pts ****/
+#ifdef NEED_SPRINTF
+ sizeret_t sprintf(char *ptr, P_CONST char *format, ...)
+{
+ va_list ap;
+ sizeret_t ret;
+
+ PTS_va_start(ap, format);
+#if 0
+ ret = vsnprintf(NULL, 0, format, ap);
+ if (ret+1 <= 1) return ret;
+ ret = vsnprintf(ptr, ret, format, ap);
+#else
+ ret = vsnprintf(ptr, (slen_t)-1, format, ap);
+#endif
+ va_end(ap);
+
+ return ret;
+}
+#endif
+
+#ifdef TEST_SNPRINTF
+
+ sizeret_t sprintf(char *str,P_CONST char *fmt,...);
+
+ int main (void)
+{
+ char buf1[1024];
+ char buf2[1024];
+ char *fp_fmt[] = {
+ "%1.1f",
+ "%-1.5f",
+ "%1.5f",
+ "%123.9f",
+ "%10.5f",
+ "% 10.5f",
+ "%+22.9f",
+ "%+4.9f",
+ "%01.3f",
+ "%4f",
+ "%3.1f",
+ "%3.2f",
+ "%.0f",
+ "%f",
+ "-16.16f",
+ NULL
+ };
+ double fp_nums[] = { 6442452944.1234, -1.5, 134.21, 91340.2, 341.1234, 0203.9, 0.96, 0.996,
+ 0.9996, 1.996, 4.136, 0};
+ char *int_fmt[] = {
+ "%-1.5d",
+ "%1.5d",
+ "%123.9d",
+ "%5.5d",
+ "%10.5d",
+ "% 10.5d",
+ "%+22.33d",
+ "%01.3d",
+ "%4d",
+ "%d",
+ NULL
+ };
+ long int_nums[] = { -1, 134, 91340, 341, 0203, 0};
+ char *str_fmt[] = {
+ "10.5s",
+ "5.10s",
+ "10.1s",
+ "0.10s",
+ "10.0s",
+ "1.10s",
+ "%s",
+ "%.1s",
+ "%.10s",
+ "%10s",
+ NULL
+ };
+ char *str_vals[] = {"hello", "a", "", "a longer string", NULL};
+ int x, y;
+ int fail = 0;
+ int num = 0;
+
+ printf ("Testing snprintf format codes against system sprintf...\n");
+
+ for (x = 0; fp_fmt[x] ; x++) {
+ for (y = 0; fp_nums[y] != 0 ; y++) {
+ int l1 = snprintf(NULL, 0, fp_fmt[x], fp_nums[y]);
+ int l2 = snprintf(buf1, sizeof(buf1), fp_fmt[x], fp_nums[y]);
+ sprintf (buf2, fp_fmt[x], fp_nums[y]);
+ if (strcmp (buf1, buf2)) {
+ printf("snprintf doesn't match Format: %s\n\tsnprintf = [%s]\n\t sprintf = [%s]\n",
+ fp_fmt[x], buf1, buf2);
+ fail++;
+ }
+ if (l1 != l2) {
+ printf("snprintf l1 != l2 (%d %d) %s\n", l1, l2, fp_fmt[x]);
+ fail++;
+ }
+ num++;
+ }
+ }
+
+ for (x = 0; int_fmt[x] ; x++) {
+ for (y = 0; int_nums[y] != 0 ; y++) {
+ int l1 = snprintf(NULL, 0, int_fmt[x], int_nums[y]);
+ int l2 = snprintf(buf1, sizeof(buf1), int_fmt[x], int_nums[y]);
+ sprintf (buf2, int_fmt[x], int_nums[y]);
+ if (strcmp (buf1, buf2)) {
+ printf("snprintf doesn't match Format: %s\n\tsnprintf = [%s]\n\t sprintf = [%s]\n",
+ int_fmt[x], buf1, buf2);
+ fail++;
+ }
+ if (l1 != l2) {
+ printf("snprintf l1 != l2 (%d %d) %s\n", l1, l2, int_fmt[x]);
+ fail++;
+ }
+ num++;
+ }
+ }
+
+ for (x = 0; str_fmt[x] ; x++) {
+ for (y = 0; str_vals[y] != 0 ; y++) {
+ int l1 = snprintf(NULL, 0, str_fmt[x], str_vals[y]);
+ int l2 = snprintf(buf1, sizeof(buf1), str_fmt[x], str_vals[y]);
+ sprintf (buf2, str_fmt[x], str_vals[y]);
+ if (strcmp (buf1, buf2)) {
+ printf("snprintf doesn't match Format: %s\n\tsnprintf = [%s]\n\t sprintf = [%s]\n",
+ str_fmt[x], buf1, buf2);
+ fail++;
+ }
+ if (l1 != l2) {
+ printf("snprintf l1 != l2 (%d %d) %s\n", l1, l2, str_fmt[x]);
+ fail++;
+ }
+ num++;
+ }
+ }
+
+ printf ("%d tests failed out of %d.\n", fail, num);
+
+ printf("seeing how many digits we support\n");
+ {
+ double v0 = 0.12345678901234567890123456789012345678901;
+ for (x=0; x<100; x++) {
+ snprintf(buf1, sizeof(buf1), "%1.1f", v0*pow(10, x));
+ sprintf(buf2, "%1.1f", v0*pow(10, x));
+ if (strcmp(buf1, buf2)) {
+ printf("we seem to support %d digits\n", x-1);
+ break;
+ }
+ }
+ }
+
+ return 0;
+}
+#endif /* SNPRINTF_TEST */
diff --git a/graphics/sam2p/snprintf.h b/graphics/sam2p/snprintf.h
new file mode 100644
index 0000000000..7713c3154a
--- /dev/null
+++ b/graphics/sam2p/snprintf.h
@@ -0,0 +1,28 @@
+/*
+ * snprintf.h -- interface for our fixup vsnprintf() etc. functions
+ */
+
+#ifndef SNPRINTF_H
+#define SNPRINTF_H 1
+
+#ifdef __GNUC__
+#ifndef __clang__
+#pragma interface
+#endif
+#endif
+
+#include "config2.h"
+#include <stdarg.h> /* ... */
+#ifndef __cplusplus
+# define EXTERN_C extern
+#else
+# define EXTERN_C extern "C"
+#endif
+
+EXTERN_C slen_t fixup_vsnprintf(char *str, slen_t count, PTS_const char *fmt, va_list args);
+EXTERN_C slen_t fixup_snprintf(char *str,slen_t count,PTS_const char *fmt,...);
+EXTERN_C slen_t fixup_vasprintf(char **ptr, PTS_const char *format, va_list ap);
+EXTERN_C slen_t fixup_asprintf(char **ptr, PTS_const char *format, ...);
+EXTERN_C slen_t fixup_sprintf(char *ptr, PTS_const char *format, ...);
+
+#endif /* snprintf.h */
diff --git a/graphics/sam2p/test_main.cpp b/graphics/sam2p/test_main.cpp
new file mode 100644
index 0000000000..d03a8dd791
--- /dev/null
+++ b/graphics/sam2p/test_main.cpp
@@ -0,0 +1,340 @@
+/* test_main.cpp
+ * by pts@fazekas.hu at Sun Feb 24 16:24:38 CET 2002
+ */
+
+#include "gensi.hpp"
+#include "gensio.hpp"
+#include "image.hpp"
+#include "error.hpp"
+#include "encoder.hpp"
+#include "minips.hpp"
+#include "mapping.hpp"
+
+#if OBJDEP
+# warning PROVIDES: test_main
+# warning REQUIRES: gensi.o
+# warning REQUIRES: gensio.o
+# warning REQUIRES: image.o
+# warning REQUIRES: error.o
+# warning REQUIRES: encoder.o
+# warning REQUIRES: minips.o
+# warning REQUIRES: mapping.o
+#endif
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+Files::FILEW sout(stdout);
+
+#if OBJDEP
+# warning REQUIRES: in_xpm.o
+# warning REQUIRES: in_lbm.o
+# warning REQUIRES: in_gif.o
+# warning REQUIRES: in_bmp.o
+# warning REQUIRES: in_pnm.o
+# warning REQUIRES: in_tga.o
+#endif
+extern Image::Loader in_xpm_loader;
+extern Image::Loader in_lbm_loader;
+extern Image::Loader in_gif_loader;
+extern Image::Loader in_bmp_loader;
+extern Image::Loader in_pnm_loader;
+extern Image::Loader in_tga_loader;
+static void init_loader() {
+ Image::register0(&in_tga_loader); /* checker not sure; install early */
+ Image::register0(&in_xpm_loader);
+ Image::register0(&in_lbm_loader);
+ Image::register0(&in_gif_loader);
+ Image::register0(&in_bmp_loader);
+ Image::register0(&in_pnm_loader);
+ sout << "Available Loaders:";
+ Image::printLoaders(sout);
+ sout << ".\n";
+}
+
+static void test_data() {
+ int i;
+ SimBuffer::Static world("World!");
+ SimBuffer::Static("-1984").toInteger(i);
+ sout << "Hello," << ' ' << world << '\n'
+ << i << " luftballons.\n"
+ << -99U << " negatives.\n";
+ sout << (world >= "FooBar") << '\n'; /// true
+
+ { bool b=true;
+ SimBuffer::Linked sli; sli << (world>"Zorba");
+ sli.toBool(b);
+ sout << b << '\n'; /// false
+ }
+
+ SimBuffer::Linked li, lj("LJ");
+ li << "answer is: " << 42L << '\n';
+ li.prepend("The X", 4);
+ lj << "uff.";
+ lj=li;
+ lj.prepend("D.A said: ",10);
+ sout << li; /// The answer is 42
+ sout << lj; /// D.A said: The answer is 42
+
+ { Buffer b="Hello!\n"; /* <= 8 chars */
+ sout << b;
+ }
+ { Buffer b="Hello, World!\n"; /* > 8 chars */
+ sout << b;
+ }
+ { sout << "Hello,"+Buffer(" World2!\n"); }
+ { Buffer b; b.format("Hello,%cWorld %d%s", ' ', -42, "!\n"); sout << b; }
+ { Buffer b; b.format("123456789012\n"); sout << b; }
+ { Buffer b; b.format("1234567890123\n"); sout << b; }
+ { Buffer b; b.format("12345678901234\n"); sout << b; }
+ { Buffer b; b.format("123456789012345\n"); sout << b; }
+ { Buffer b; b.format("1234567890123456\n"); sout << b; }
+ { Buffer b; b.format("1234567890%u\n",123456789L); sout << b; }
+ { Buffer b("Hello, World!\n"); memcpy(b.substr_grow(7,5,3), "Bar", 3); sout << b; }
+ { Buffer b("Hello, World!\n"); memcpy(b.substr_grow(7,5,6), "FooBar", 6); sout << b; }
+ { Buffer b("Hello, World!\n"); memcpy(b.substr_grow(7,15,8), "FooBar!\n", 8); sout << b; }
+ { Buffer b("Hello, World!"); memcpy(b.substr_grow(17,15,8), "HowDYD?\n", 8); sout << b; }
+ { Buffer b="bena"; Buffer c; c=(SimBuffer::Flat)b; }
+ sout << "Done.\n";
+}
+
+#if OBJDEP
+# warning REQUIRES: image.o
+#endif
+static void test_image() {
+ // Image::Sampled *img=Image::load("at-logo.xpm");
+ // Image::Sampled *img=Image::load("pts.xpm");
+ // Image::Sampled *img=Image::load("tex5.xpm");
+ // Image::Sampled *img=Image::load("at-logo.lbm");
+ // Image::Sampled *img=Image::load("ptest.lbm");
+ // Image::Sampled *img=Image::load("chessbrd.lbm");
+ // Image::Sampled *img=Image::load("at-logo.gif");
+ // Image::Sampled *img=Image::load("ptsbanner.gif");
+ // Image::Sampled *img=Image::load("ptsbanner.bmp");
+ // Image::Sampled *img=Image::load("pts.bmp");
+ // Image::Sampled *img=Image::load("t.cpp");
+ // Image::Sampled *img=Image::load("ptsbanner.tga");
+ // Image::Sampled *img=Image::load("mixing.xpm");
+ Image::Sampled *img=Image::load("mixing0.xpm", SimBuffer::B());
+ Files::FILEW f(fopen("t.ppm","wb")); /* Imp: autoclose... */
+
+ Image::Sampled *bak=img;
+ img=img->toIndexed(); if (bak!=img) delete bak;
+ assert(img->getTy()==img->TY_INDEXED);
+ sout << "ncol0=" << PTS_dynamic_cast(Image::Indexed*,img)->getNcols() << '\n';
+ PTS_dynamic_cast(Image::Indexed*,img)->packPal();
+ sout << "ncols=" << PTS_dynamic_cast(Image::Indexed*,img)->getNcols() << '\n';
+ PTS_dynamic_cast(Image::Indexed*,img)->setBpc(0);
+ sout << "bpc=" << (int)img->getBpc() << '\n';
+ // Files::tmpRemoveCleanup("t.dump");
+ // Files::tmpRemoveCleanup("t.dump"); /* twice: OK */
+ /* Files::tmpRemoveCleanup("/bin"); */
+ Files::FILEW f2(fopen("t.dump","wb"));
+ PTS_dynamic_cast(Image::Indexed*,img)->dumpDebug(f2);
+ f2.close();
+
+ f << *img;
+ f.close();
+ // delete img;
+}
+
+static void test_encoder() {
+ // Files::tmpRemove=false; /* Imp: make this a command-line option */
+
+ { Filter::FILEE a("t.a85");
+ PSEncoder *bp=PSEncoder::newASCII85Encode(a,78);
+ // FlateEncode c(b,5);
+ // LZWEncode c(b);
+ // PipeEncode c(b,"gs -dNODISPLAY -q -c '/i(%stdin)(r)file def/o(%stdout)(w)file/LZWEncode filter def/s 4096 string def{i s readstring exch o exch writestring not{exit}if}loop o closefile quit'");
+ // GSEncode c(b,"xFlateEncode");
+ // PSEncoder *cp=PSEncoder::newLZWEncode(*bp);
+ #if 1
+ PSEncoder *cp=PSEncoder::newRunLengthEncode(*bp);
+ // delete [] cp; exit(0); /* Cannot free a GSEncode with multiple inheritance :-(( -> SegFault. virtual inheritance SUXX */
+ // PSEncoder *cp=PSEncoder::newRunLengthEncode(a);
+
+ // FILE *fin=fopen("t55","rb");
+ FILE *fin=fopen("t.dump","rb");
+ // FILE *fin=fopen("t.xin","rb");
+
+ static char mybuf[2033];
+ unsigned long sum=0;
+ while (1) {
+ unsigned size=fread(mybuf, 1, sizeof(mybuf), fin);
+ if (size<1) { fprintf(stderr,"nosiz=%u\n",size); cp->vi_write(0,0); break; }
+ fprintf(stderr, "sending size=%u ofs=%lu\n", size, sum);
+ sum+=size;
+ cp->vi_write(mybuf, size);
+ }
+ assert(feof(fin));
+ assert(!ferror(fin));
+ fprintf(stderr, "ftell=%lu\n", ftell(fin));
+ fclose(fin);
+ #else
+ img->to8();
+ //img->setBpc(0);
+ //sout << "bpc2=" << (int)img->getBpc() << '\n';
+ //Files::FILEW f2(fopen("t.dump2","wb"));
+ //PTS_dynamic_cast(Image::Indexed*,img)->dumpDebug(f2);
+ //f2.close();
+ PSEncoder *cp=PSEncoder::newDCTEncode(*bp, img->getWd(), img->getHt(), 1);
+ cp->vi_write(img->getRowbeg(), img->getWd()*img->getHt());
+ cp->vi_write(0,0);
+ #endif
+
+ delete cp;
+ delete bp;
+ }
+}
+
+static void test_predictor() {
+ /* by pts@fazekas.hu at Tue Mar 12 10:51:27 CET 2002 */
+ Image::SampledInfo info(Image::load("mixing1.xpm", SimBuffer::B()));
+ info.setSampleFormat(Image::SF_Indexed2, false, false, 0x1000000L);
+ Image::Sampled *img=info.getImg();
+
+ /* Imp: test predictors with rgb-4 */
+ unsigned char pred=11;
+ Files::FILEW f2(fopen("predictor_gen.eps","wb"));
+ f2 << "%!PS-Adobe-3.0 EPSF-3.0\n%%BoundingBox: 0 0 " << img->getWd() << ' ' << img->getHt() << "\n%%EndComments\n"
+ << "% `*image' forces grayscale :-(\nsave 99 dict begin\n"
+ "{[ /Indexed /DeviceRGB " << ((img->getRowbeg()-img->getHeadp())/3-1) << " currentfile " << (img->getRowbeg()-img->getHeadp()) << " string readstring pop ] setcolorspace\n"
+ "/f currentfile <</Predictor " << (((unsigned)pred)%30) << " /Columns " << img->getWd() << " /Colors " << (unsigned)img->getCpp() << " /BitsPerComponent " << (unsigned)img->getBpc() << ">> /FlateDecode filter def\n"
+// "/f currentfile /FlateDecode filter def\n"
+ << img->getWd() << ' ' << img->getHt() << ' ' << (unsigned)img->getBpc()
+ << "[1 0 0 -1 0 " << img->getHt() << "]f image\nf closefile}\n"
+ "%%BeginData:\nexec\n";
+ f2.vi_write(img->getHeadp(), img->getRowbeg()-img->getHeadp()); /* Write palette */
+ PSEncoder *bp=PSEncoder::newFlateEncode(f2);
+ // Encoder *cp=Encoder::newTIFFPredictor2(*bp, img->getBpc(), img->getWd(), img->getCpp());
+ // Encoder *cp=Encoder::newPNGPredictor11(*bp, img->getBpc(), img->getWd(), img->getCpp());
+ Encoder *cp=PSEncoder::newPredictor(*bp, pred, img->getBpc(), img->getWd(), img->getCpp());
+ cp->vi_write(img->getRowbeg(), img->getRlen()*img->getHt());
+ cp->vi_write(0,0);
+ f2 << "\n%%EndData\nend\nrestore showpage\n%%Trailer\n%%EOF\n";
+ f2.close();
+
+ /* destructor of info frees all memory */
+}
+
+static void test_dump() {
+ MiniPS::VALUE e=(MiniPS::VALUE)new MiniPS::Dict();
+ MiniPS::VALUE d=(MiniPS::VALUE)new MiniPS::Dict();
+ MiniPS::VALUE a=(MiniPS::VALUE)new MiniPS::Array();
+ MiniPS::RARRAY(a)->push(MiniPS::Qinteger(3));
+ MiniPS::VALUE b=(MiniPS::VALUE)new MiniPS::Array();
+ MiniPS::RARRAY(b)->push(MiniPS::Qinteger(4));
+ MiniPS::RARRAY(b)->push(MiniPS::Qinteger(5));
+ MiniPS::RARRAY(b)->push(MiniPS::Qinteger(6));
+ MiniPS::RARRAY(b)->push((MiniPS::VALUE)new MiniPS::String("Hel\téna \n\n\n\n\n\n\n",15));
+#if 0
+ MiniPS::RDICT(d)->push((MiniPS::VALUE)new MiniPS::Sname("/alma",5), MiniPS::Qinteger(42));
+ MiniPS::RDICT(d)->push((MiniPS::VALUE)new MiniPS::Sname("/korte",6), MiniPS::Qnull);
+ MiniPS::RDICT(d)->push((MiniPS::VALUE)new MiniPS::Sname("/szilva",7), MiniPS::Qtrue);
+ MiniPS::RDICT(d)->push((MiniPS::VALUE)new MiniPS::Sname("/narancs",8), MiniPS::Qfalse);
+ MiniPS::RDICT(d)->push((MiniPS::VALUE)new MiniPS::Sname("/naranc2",8), (MiniPS::VALUE)new MiniPS::Array());
+ MiniPS::RDICT(d)->push((MiniPS::VALUE)new MiniPS::Sname("/naranc3",8), a);
+ MiniPS::RDICT(d)->push((MiniPS::VALUE)new MiniPS::Sname("/naranc4",8), b);
+ MiniPS::RDICT(d)->push((MiniPS::VALUE)new MiniPS::Sname("/naranc5",8), e);
+#else
+ MiniPS::RDICT(d)->push("/alma",5, MiniPS::Qinteger(42));
+ MiniPS::RDICT(d)->push("/korte",6, MiniPS::Qnull);
+ MiniPS::RDICT(d)->push("/szilva",7, MiniPS::Qtrue);
+ MiniPS::RDICT(d)->push("/narancs",8, MiniPS::Qfalse);
+ MiniPS::RDICT(d)->push("/naranc2",8, (MiniPS::VALUE)new MiniPS::Array());
+ MiniPS::RDICT(d)->push("/naranc3",8, a);
+ MiniPS::RDICT(d)->push("/naranc4",8, b);
+ MiniPS::RDICT(d)->push("/naranc5",8, e);
+#endif
+ MiniPS::dump(sout, d);
+ MiniPS::delete0(d);
+}
+
+static void test_tokenizer() {
+ Files::FILER sin(stdin);
+ MiniPS::Tokenizer pst(sin);
+ int i;
+ while ((i=pst.yylex())!=pst.EOFF) {
+ putchar(i);
+ putchar('\n');
+ }
+}
+
+static void test_parser() {
+ { MiniPS::Parser p("-"); /* STDIN */
+ MiniPS::VALUE d=p.parse1();
+ MiniPS::dump(sout, d);
+ MiniPS::delete0(d);
+ }
+}
+
+
+static void test_hash() {
+ {Mapping::H h(6);
+ h.set("alma",4,"apple");
+ printf("alma=%s.\n", h.get("alma",4));
+ printf("korte=%s.\n", h.get("korte",5));
+ h.set("korte",5,"bear_");
+ printf("alma=%s.\n", h.get("alma",4));
+ printf("kort=%s.\n", h.get("korte",4));
+ printf("korte=%s.\n", h.get("korte",5));
+ }
+
+ /* Dat: this might take a long time to run */
+ /* Imp: srand, but that would make the test less predictable */
+ char tmp[2];
+ unsigned i, j;
+ Mapping::H h(sizeof(tmp));
+ for (i=0; i<10000000; i++) {
+ // printf("%u\n", i);
+ for (j=0; j<sizeof(tmp); ) tmp[j++]=rand();
+ if ((rand()&3)!=0) h.set(tmp, sizeof(tmp), tmp);
+ else h.deletee(tmp, sizeof(tmp));
+ // putchar('.');
+ // h.rehash();
+ }
+ printf("OK!\n");
+}
+
+static void test_decoder() {
+ SimBuffer::B sb("Hello, World!\n");
+ char const*p=sb();
+ Filter::FlatD fd(sb(), sb.getLength());
+ Filter::PipeD pd(fd, "tr A-Z a-z <%S");
+ int i;
+ while ((i=pd.vi_getcc())>=0) {
+ putchar(':');
+ putchar(i);
+ if (i!=(*p>='A' && *p<='Z'?*p+'a'-'A':*p)) abort();
+ p++;
+ }
+ pd.vi_read(0,0);
+ /* Dat: the destructors do their jobs; freeing is not necessary */
+}
+
+int main(int argc, char **argv) {
+ (void)argc;
+ (void)argv;
+
+ Error::argv0=argc>=1 ? argv[0] : "test_main"; /* Imp: update this */
+ Error::tmpargv0="test_main";
+ Files::tmpRemove=0;
+ init_loader();
+
+ test_data();
+ test_hash();
+ test_decoder();
+ // test_image(); // Needs file and more refactoring.
+ // test_encoder(); // Needs file.
+ test_dump();
+ // test_parser(); // Needs stdin.
+ // test_tokenizer(); // Needs stdin.
+ // test_predictor(); // Needs file and more refactoring.
+
+ sout << "Success (test_main).\n";
+ fflush(stdout);
+ Error::cexit(Error::runCleanups(0));
+ assert(0);
+ return 0; /*notreached*/
+}
diff --git a/graphics/sam2p/testfax_main.c b/graphics/sam2p/testfax_main.c
new file mode 100644
index 0000000000..7b07f59951
--- /dev/null
+++ b/graphics/sam2p/testfax_main.c
@@ -0,0 +1,178 @@
+/*
+ * testfax_main.c -- CCITTFax(En|De)code usage sample
+ * by pts@fazekas.hu at Sat Jul 6 20:03:35 CEST 2002
+ * Sun Jul 7 22:25:55 CEST 2002
+ *
+ * Note that this sample is incomplete since the parameters (such as /K)
+ * cannot be set from the command line.
+ */
+
+#include "pts_fax.h"
+#include <stdlib.h>
+#include <string.h>
+#include <stdio.h>
+#include <assert.h>
+
+#ifdef __GNUC__
+#ifndef __clang__
+#pragma implementation
+#endif
+#endif
+
+#if OBJDEP
+# warning PROVIDES: testfax_main
+#endif
+
+static void* gsfax_xalloc(unsigned n) {
+ void *ret;
+ if ((ret=malloc(n))==0) abort();
+ return ret;
+}
+static void gsfax_free(void *ptr) {
+ free(ptr);
+}
+static void gsfax_memset(void *s, int c, unsigned n) {
+ /*return*/ memset(s,c,n);
+}
+static void gsfax_memcpy(void *dest, const void *src, unsigned n) {
+ /*return*/ memcpy(dest, src, n);
+}
+
+
+
+#if 0
+CCITTFaxEncode:
+
+bool Uncompressed=false;
+int K=0;
+bool EndOfLine=false;
+bool EncodedByteAlign=false;
+int Columns=1728;
+int Rows=0; // Decode only
+bool EndOfBlock=true;
+bool BlackIs1=false;
+int DamagedRowsBeforeError=0; // Decode only
+bool FirstBitLowOrder=false; // GS only
+int DecodedByteAlign=1; // GS only
+bool CloseSource;
+bool CloseTarget;
+#endif
+
+/* GS expected
+ * min_left=0
+ * bits_left=32
+ *
+ */
+
+static void work(FILE *f, stream_template const*template_, stream_state *state) {
+ unsigned got, pog;
+ stream_cursor_read r;
+ stream_cursor_write w;
+ unsigned char rbuf[4096], wbuf[1000], *hard, *rlimit;
+ bool last;
+
+ #if __CHECKER__
+ memset(&r, 0, sizeof(r));
+ memset(&w, 0, sizeof(w));
+ #endif
+
+ template_->init(state);
+
+ r.ptr=rlimit=rbuf-1;
+ hard=rbuf+sizeof(rbuf)-1;
+ assert(hard-r.ptr>=(int)template_->min_in_size);
+ last=false;
+
+
+ while (1) {
+ assert(r.ptr==rbuf-1);
+ if (last==false) {
+ if (0==(got=fread(rlimit+1, 1, hard-rlimit, f))) last=true;
+ rlimit+=got;
+ }
+ /* if (r.ptr==rlimit) break; */
+ w.ptr=wbuf-1;
+ w.limit=wbuf+sizeof(wbuf)-1;
+ assert(w.limit-w.ptr>=(int)template_->min_out_size);
+ r.limit=rlimit;
+ pog=template_->process(state, &r, &w, last);
+ fprintf(stderr, "pog=%d write=%d last=%d\n", pog, w.ptr-(wbuf-1), last);
+ if ((int)pog==PTSFAX_ERRC) {
+ fprintf(stderr, "syntax error!\n");
+ abort();
+ }
+ /* assert(last || r.ptr>=rbuf); */
+ fwrite(wbuf, 1, w.ptr-(wbuf-1), stdout);
+ if (last && (pog==0 || (int)pog==PTSFAX_EOFC)) break;
+ if (r.ptr!=rbuf-1) {
+ fprintf(stderr, "limit=%d\n", rlimit-r.ptr);
+ memmove(rbuf, r.ptr+1, rlimit-r.ptr);
+ rlimit=rbuf-1+(rlimit-r.ptr);
+ r.ptr=rbuf-1;
+ }
+ }
+
+ template_->release(state);
+}
+
+int main(int argc, char **argv) {
+ FILE *f;
+
+ (void)argc;
+ (void)argv;
+/*
+-* Define a limit on the Rows parameter, close to max_int. *-
+#define cf_max_height 32000
+ if (code >= 0 &&
+ (state.K < -cf_max_height || state.K > cf_max_height ||
+ state.Columns < 0 || state.Columns > cfe_max_width ||
+ state.Rows < 0 || state.Rows > cf_max_height ||
+ state.DamagedRowsBeforeError < 0 ||
+ state.DamagedRowsBeforeError > cf_max_height ||
+ state.DecodedByteAlign < 1 || state.DecodedByteAlign > 16 ||
+ (state.DecodedByteAlign & (state.DecodedByteAlign - 1)) != 0)
+ )
+*/
+
+ f=stdin;
+ /* f=fopen("stdpre.x","rb"); */
+ /* f=fopen("216","rb"); */
+ assert(f!=0);
+
+ if (0) {
+ #if USE_BUILTIN_FAXE
+ #if OBJDEP
+ # warning REQUIRES: pts_faxe
+ #endif
+ } else if (argc==2 && 0==strcmp(argv[1], "encode")) {
+ stream_CFE_state sCFEs;
+ sCFEs.memset_=gsfax_memset;
+ sCFEs.xalloc_=gsfax_xalloc;
+ sCFEs.free_=gsfax_free;
+ sCFEs.memcpy_=gsfax_memcpy;
+ s_CFE_template.set_defaults((stream_state*)&sCFEs);
+ /* sCFEs.K=-1; ... */
+ work(f, (stream_template const*)&s_CFE_template, (stream_state*)&sCFEs);
+ #endif
+ #if USE_BUILTIN_FAXD
+ #if OBJDEP
+ # warning REQUIRES: pts_faxd
+ #endif
+ } else if (argc==2 && 0==strcmp(argv[1], "decode")) {
+ stream_CFD_state sCFDs;
+ sCFDs.memset_=gsfax_memset;
+ sCFDs.xalloc_=gsfax_xalloc;
+ sCFDs.free_=gsfax_free;
+ sCFDs.memcpy_=gsfax_memcpy;
+ s_CFD_template.set_defaults((stream_state*)&sCFDs);
+ /* sCFEs.K=-1; ... */
+ work(f, (stream_template const*)&s_CFD_template, (stream_state*)&sCFDs);
+ #endif
+ } else {
+ fprintf(stderr, "Usage: %s encode|decode <INFILE >OUTFILE\n", argv[0]);
+ return 2;
+ }
+ fclose(f);
+
+ return 0;
+}
diff --git a/graphics/sam2p/vcsam2p.cpp b/graphics/sam2p/vcsam2p.cpp
new file mode 100644
index 0000000000..a3c3ab6a2a
--- /dev/null
+++ b/graphics/sam2p/vcsam2p.cpp
@@ -0,0 +1,921 @@
+// vcsam2p.cpp : Defines the entry point for the application.
+//
+
+#include "config2.h"
+#include "image.hpp"
+#include "error.hpp"
+#include "main.hpp" /* init_loader(), init_applier() */
+#include "StdAfx.h"
+#include "resource.h"
+
+#define MAX_LOADSTRING 100
+
+extern "C" int main(int argc, char**argv);
+
+#if 0
+extern "C" int getpid(void);
+
+//#include <windows.h> /* OSVERSIONINFO etc. */
+//#include <process.h> /* _getpid() */
+static unsigned long win32_os_id(void) {
+ static OSVERSIONINFO osver;
+ static DWORD w32_platform = (DWORD)-1;
+ if (w32_platform==-1 || osver.dwPlatformId != w32_platform) {
+ memset(&osver, 0, sizeof(OSVERSIONINFO));
+ osver.dwOSVersionInfoSize = sizeof(OSVERSIONINFO);
+ GetVersionEx(&osver);
+ w32_platform = osver.dwPlatformId;
+ }
+ return (unsigned long)w32_platform;
+}
+static inline bool IsWin95(void) {
+ return (win32_os_id() == VER_PLATFORM_WIN32_WINDOWS);
+}
+
+// static int win32_getpid(void) {
+int getpid(void) {
+ int pid;
+ pid = _getpid();
+ /* Windows 9x appears to always reports a pid for threads and processes
+ * that has the high bit set. So we treat the lower 31 bits as the
+ * "real" PID for Perl's purposes. */
+ if (IsWin95() && pid < 0) pid = -pid;
+ return pid;
+}
+#endif
+
+
+// Global Variables:
+HINSTANCE hInst; // current instance
+// TCHAR szTitle[MAX_LOADSTRING]; // The title bar text
+TCHAR szWindowClass[MAX_LOADSTRING]; // The title bar text
+
+// Foward declarations of functions included in this code module:
+ATOM MyRegisterClass(HINSTANCE hInstance);
+BOOL InitInstance(HINSTANCE, int);
+LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM);
+LRESULT CALLBACK About(HWND, UINT, WPARAM, LPARAM);
+LRESULT CALLBACK dialogRun(HWND, UINT, WPARAM, LPARAM);
+
+int APIENTRY WinMain(HINSTANCE hInstance,
+ HINSTANCE /*hPrevInstance*/,
+ LPSTR /*lpCmdLine*/, // !!
+ int nCmdShow) {
+ // TODO: Place code here.
+ MSG msg;
+ HACCEL hAccelTable;
+
+ // Initialize global strings
+ // LoadString(hInstance, IDS_APP_TITLE, szTitle, MAX_LOADSTRING);
+ LoadString(hInstance, IDC_VCSAM2P, szWindowClass, MAX_LOADSTRING);
+ MyRegisterClass(hInstance);
+
+ // Perform application initialization:
+ if (!InitInstance (hInstance, nCmdShow)) {
+ return FALSE;
+ }
+
+ hAccelTable = LoadAccelerators(hInstance, (LPCTSTR)IDC_VCSAM2P);
+
+ // Main message loop:
+ while (GetMessage(&msg, NULL, 0, 0)) {
+ if (!TranslateAccelerator(msg.hwnd, hAccelTable, &msg)) {
+ TranslateMessage(&msg);
+ DispatchMessage(&msg);
+ }
+ }
+ return msg.wParam;
+}
+
+
+
+//
+// FUNCTION: MyRegisterClass()
+//
+// PURPOSE: Registers the window class.
+//
+// COMMENTS:
+//
+// This function and its usage is only necessary if you want this code
+// to be compatible with Win32 systems prior to the 'RegisterClassEx'
+// function that was added to Windows 95. It is important to call this function
+// so that the application will get 'well formed' small icons associated
+// with it.
+//
+ATOM MyRegisterClass(HINSTANCE hInstance) {
+ WNDCLASSEX wcex;
+ wcex.cbSize = sizeof(WNDCLASSEX);
+ wcex.style = 0; /*CS_HREDRAW | CS_VREDRAW;*/
+ wcex.lpfnWndProc = (WNDPROC)WndProc;
+ wcex.cbClsExtra = 0;
+ wcex.cbWndExtra = 0;
+ wcex.hInstance = hInstance;
+ wcex.hIcon = LoadIcon(hInstance, (LPCTSTR)IDI_SAM2P32);
+ wcex.hCursor = LoadCursor(NULL, IDC_ARROW);
+ wcex.hbrBackground = (HBRUSH)(COLOR_WINDOW+1);
+ wcex.lpszMenuName = (LPCSTR)IDC_VCSAM2P;
+ wcex.lpszClassName = szWindowClass;
+ wcex.hIconSm = LoadIcon(wcex.hInstance, (LPCTSTR)IDI_SAM2P16);
+ return RegisterClassEx(&wcex);
+}
+
+/* --- */
+
+/** An image that can be rendered onto a window really quickly */
+class WinFastImage {
+ HDC hmemdc;
+ HBITMAP hbitmap;
+ slen_t wd, ht;
+ public:
+ // WinFastImage::WinFastImage(slen_t wd_, slen_t ht_);
+ WinFastImage();
+ ~WinFastImage();
+ /** Constructs a WinFastImage that can be drawn fast onto hdc. */
+ WinFastImage(HDC hdc, HBITMAP hsrc);
+ /** Constructs a WinFastImage that can be drawn fast onto hwnd and all compatible HDCs. */
+ WinFastImage(HWND hwnd, HBITMAP hsrc);
+ slen_t getWd() const { return wd; }
+ slen_t getHt() const { return ht; }
+ /* @param hdc dc on which fast rendering is desired
+ * @param hsrc source bitmap containing the data
+ */
+ void set(HDC hdc, HBITMAP hsrc);
+ inline void drawTo(HDC hdc, slen_t dstX, slen_t dstY) const {
+ drawTo(hdc, dstX, dstY, wd, ht, 0, 0);
+ }
+ inline void drawTo(HDC hdc, slen_t dstX, slen_t dstY, slen_t dstWd, slen_t dstHt, slen_t srcX, slen_t srcY) const {
+ BitBlt(hdc,dstX,dstY,dstWd,dstHt,hmemdc,srcX,srcY,SRCCOPY);
+ }
+ // void drawTo(HDC hdc, slen_t dstX, slen_t dstY);
+ // void drawTo(HDC hdc, slen_t dstX, slen_t dstY, slen_t dstWd, slen_t dstHt, slen_t srcX, slen_t srcY);
+ /** MSDN says hbitmap must be a DDB, but it worked fine for me with a DIB */
+ static void getSize(HBITMAP hbitmap, slen_t &wd, slen_t &ht);
+};
+
+void WinFastImage::getSize(HBITMAP hbitmap, slen_t &wd, slen_t &ht) {
+ /* It took me 1 hour to figure this out. Not documented anywhere! */
+ BITMAPINFOHEADER h2;
+ h2.biSize=sizeof(h2);
+ h2.biBitCount=0;
+ // h2.biWidth=11; h2.biHeight=22; h2.biPlanes=1;
+ HDC hxdc=CreateDC("DISPLAY",NULL,NULL,NULL);
+ GetDIBits(hxdc, hbitmap, 0, 0, NULL, (BITMAPINFO*)&h2, DIB_RGB_COLORS);
+ wd=h2.biWidth; ht=h2.biHeight;
+ DeleteDC(hxdc);
+}
+
+WinFastImage::WinFastImage(): hmemdc(NULL), hbitmap(NULL), wd(0), ht(0) {}
+WinFastImage::WinFastImage(HDC hdc, HBITMAP hsrc): hmemdc(NULL), hbitmap(NULL) { set(hdc, hsrc); }
+WinFastImage::WinFastImage(HWND hwnd, HBITMAP hsrc): hmemdc(NULL), hbitmap(NULL) {
+ HDC hdc=GetDC(hwnd);
+ set(hdc, hsrc);
+ ReleaseDC(hwnd, hdc);
+}
+
+WinFastImage::~WinFastImage() {
+ if (hmemdc!=NULL) DeleteDC(hmemdc);
+ if (hbitmap!=NULL) DeleteObject(hbitmap);
+}
+void WinFastImage::set(HDC hdc, HBITMAP hsrc) {
+ if (hmemdc!=NULL) DeleteDC(hmemdc);
+ if (hbitmap!=NULL) DeleteObject(hbitmap);
+ /* Imp: error handling */
+ getSize(hsrc, wd, ht);
+ hmemdc=CreateCompatibleDC(hdc);
+ hbitmap=CreateCompatibleBitmap(hdc, wd, ht); /* BUGFIX at 22:07 */
+ DeleteObject(SelectObject(hmemdc, hbitmap));
+ HDC hsrcdc=CreateCompatibleDC(hmemdc);
+ SelectObject(hsrcdc, hsrc);
+ BitBlt(hmemdc,0,0,wd,ht,hsrcdc,0,0,SRCCOPY);
+ DeleteDC(hsrcdc);
+}
+
+/* --- */
+
+class CopyableImage { public:
+ virtual slen_t vi_getWd() const =0;
+ virtual slen_t vi_getHt() const =0;
+ /** Copies an row in RGB PPM8 format from (this) to `to' */
+ virtual void copyRGBRow(char *to, slen_t whichRow) const =0;
+};
+
+/** A rectangular RGB image, suitable for displaying in Win32 API */
+class WinImageRGB {
+ /** Number of bytes per scanline */
+ slen_t rlen;
+ HBITMAP hbitmap;
+ /** data[0] is blue of upper left pixel, data[1] is green, data[2] is red. Rows
+ * are aligned to 4-byte boundary
+ */
+ char *data;
+ BITMAPINFOHEADER header;
+ void init(slen_t wd_, slen_t ht_);
+ public:
+ inline WinImageRGB(slen_t wd_, slen_t ht_) { init(wd_, ht_); }
+ WinImageRGB(CopyableImage const&);
+ ~WinImageRGB();
+ inline slen_t getWd() const { return header.biWidth; }
+ inline slen_t getHt() const { return -header.biHeight; }
+ virtual inline slen_t vi_getWd() const { return header.biWidth; }
+ virtual inline slen_t vi_getHt() const { return -header.biHeight; }
+ virtual void copyRGBRow(char *to, slen_t whichRow) const;
+ inline slen_t getRlen() const { return rlen; }
+ inline char* getData() const { return data; }
+ inline HBITMAP getHbitmap() const { return hbitmap; }
+ void drawTo(HDC hdc, slen_t dstX, slen_t dstY) const;
+ void drawTo(HDC hdc, slen_t dstX, slen_t dstY, slen_t dstWd, slen_t dstHt, slen_t srcX, slen_t srcY) const;
+ /** Copies image data from an other image in the PPM8 format: ppm8_data[0]
+ * is red, ppm8_data[1] is green, pp8_data[2] is blue. Rows are aligned to
+ * byte boundary.
+ */
+ void fromPPM8(char const*ppm8_data);
+ void fill(char r, char g, char b);
+ void putPixel(slen_t x, slen_t y, char r, char g, char b);
+};
+
+void WinImageRGB::init(slen_t wd_, slen_t ht_) {
+ rlen=(wd_*3+3)&~3;
+ header.biSize=sizeof(header);
+ header.biWidth=wd_;
+ header.biHeight=0-ht_;
+ header.biPlanes=1;
+ header.biBitCount=24;
+ header.biCompression=BI_RGB;
+ header.biSizeImage=0;
+ header.biXPelsPerMeter=1000; /* returned by GetBitmapDimensionEx */
+ header.biXPelsPerMeter=1000;
+ header.biClrUsed=0;
+ header.biClrImportant=0;
+ hbitmap=CreateDIBSection(NULL, (CONST BITMAPINFO*)&header, DIB_RGB_COLORS, (void**)&data, NULL, 0);
+// slen_t xx=GetDeviceCaps(hbitmap, HORZRES);
+}
+
+WinImageRGB::WinImageRGB(CopyableImage const& other) {
+ init(other.vi_getWd(), other.vi_getHt());
+ char *buf=new char[rlen];
+ slen_t pad=(header.biWidth)&3, x, y=0, ym=header.biHeight;
+ char *p=data;
+ char const *ppm8_data;
+ while (ym++!=0) {
+ other.copyRGBRow(buf, y++); ppm8_data=buf;
+ x=header.biWidth;
+ while (x--!=0) { p[2]=*ppm8_data++; p[1]=*ppm8_data++; p[0]=*ppm8_data++; p+=3; }
+ p+=pad;
+ }
+ delete [] buf;
+}
+
+WinImageRGB::~WinImageRGB() {
+ DeleteObject(hbitmap);
+}
+
+void WinImageRGB::copyRGBRow(char *to, slen_t whichRow) const {
+ if (whichRow<0U-header.biHeight) {
+ char *p=data+rlen*whichRow, *pend=p+rlen;
+ while (p!=pend) { to[0]=p[2]; to[1]=p[1]; to[2]=p[0]; p+=3; to+=3; }
+ }
+}
+
+void WinImageRGB::drawTo(HDC hdc, slen_t dstX, slen_t dstY) const {
+ drawTo(hdc, dstX, dstY, header.biWidth, -header.biHeight, 0, 0);
+}
+
+void WinImageRGB::drawTo(HDC hdc, slen_t dstX, slen_t dstY, slen_t dstWd, slen_t dstHt, slen_t srcX, slen_t srcY) const {
+ HDC hmemdc=CreateCompatibleDC(hdc);
+ DeleteObject(SelectObject(hmemdc, hbitmap));
+ /* ^^^ set the bitmap for hmemdc that Rectangle (hmemdc etc.) will draw to, to (this) */
+
+ // slen_t xx=GetDeviceCaps(hdc, HORZRES);
+ // HPEN hpen=CreatePen(PS_SOLID, 0, RGB(255,0,0));
+ // HANDLE hold=SelectObject(hmemdc, hpen);
+ // Rectangle(hmemdc,10,10,200,100);
+ // SelectObject(hmemdc, hold);
+ // DeleteObject(hpen);
+
+ BitBlt(hdc,dstX,dstY,dstWd,dstHt,hmemdc,srcX,srcY,SRCCOPY);
+ DeleteDC(hmemdc);
+}
+
+void WinImageRGB::fromPPM8(char const* ppm8_data) {
+ /* Dat: biWidth*3 is considered when calculating pad */
+ slen_t pad=(header.biWidth)&3, x, y=header.biHeight;
+ char *p=data;
+ while (y++!=0) {
+ x=header.biWidth;
+ while (x--!=0) { p[2]=*ppm8_data++; p[1]=*ppm8_data++; p[0]=*ppm8_data++; p+=3; }
+ p+=pad;
+ }
+}
+
+void WinImageRGB::fill(char r, char g, char b) {
+ /* Dat: biWidth*3 is considered when calculating pad */
+ slen_t pad=(header.biWidth)&3, x, y=header.biHeight;
+ char *p=data;
+ while (y++!=0) {
+ x=header.biWidth;
+ while (x--!=0) { *p++=b; *p++=g; *p++=r; }
+ p+=pad;
+ }
+}
+
+void WinImageRGB::putPixel(slen_t x, slen_t y, char r, char g, char b) {
+ if (x<(slen_t)header.biWidth && y<(slen_t)-header.biHeight) {
+ char *p=data+rlen*y+x;
+ p[0]=b; p[1]=g; p[2]=r;
+ }
+}
+
+/* --- */
+
+
+/** Implements the CopyableImage interface for the sam2p Image::Sampled class. */
+class CopyableAdapter: public CopyableImage {
+ Image::Sampled const& img;
+ public:
+ inline CopyableAdapter(Image::Sampled const& img_): img(img_) {}
+ inline virtual slen_t vi_getHt() const { return img.getHt(); }
+ inline virtual slen_t vi_getWd() const { return img.getWd(); }
+ inline virtual void copyRGBRow(char *to, slen_t whichRow) const { img.copyRGBRow(to, whichRow); }
+};
+
+/* --- */
+
+/** Size of previous open image */
+static slen_t wd_last=0, ht_last=0;
+/** Size of window including decorations !! exclude decorations */
+static const unsigned wd_def=150, ht_def=90;
+static WinImageRGB *imgr=NULL;
+static WinFastImage *imgf=NULL;
+static HWND hwnd_main;
+/** Changed since last save? */
+static bool dirty=false;
+/** File loaded. NULL if no/new; begins with "* " for a dirty file, ": " for a normal file.
+ * TODO(pts): Do `delete [] filename2;' on exit, also for other global variables.
+ */
+static char *filename2=NULL;
+static bool first_paint_p=true;
+// static char szHello[MAX_LOADSTRING];
+/* OK: not resizable: WM_... */
+/* Imp: clipboard copy-paste image */
+/* !! about editbox non-grey disabled */
+/* !! open rxvt_bug.bmp wrong window size */
+/* !! test larger image than screen */
+/* !! SetWindowText() LineScroll() */
+/* !! bongeszo ne irjon felul ablakot */
+/* !! transparent images */
+/* void CHistoryEdit::AppendString(CString str)
+ { SendMessage(EM_SETSEL,0xFFFFFFFF,-1);
+ SendMessage(EM_REPLACESEL,FALSE,(LPARAM)(LPCTSTR)str);
+ }
+*/
+
+// PURPOSE: Saves instance handle and creates main window
+// In this function, we save the instance handle in a global variable and
+// create and display the main program window.
+//
+BOOL InitInstance(HINSTANCE hInstance, int nCmdShow) {
+ init_sam2p_engine("vcsam2p");
+ hInst = hInstance; // Store instance handle in our global variable
+ hwnd_main = CreateWindow(szWindowClass, Error::banner0,
+ WS_OVERLAPPED| WS_CAPTION| WS_SYSMENU| WS_MINIMIZEBOX| WS_BORDER| WS_THICKFRAME,
+ // WS_THICKFRAME: resizable (has sizing border)
+ // WS_MAXIMIZEBOX, WS_OVERLAPPEDWINDOW
+ CW_USEDEFAULT, 0, CW_USEDEFAULT, 0, NULL, NULL, hInstance, NULL);
+ if (!hwnd_main) return FALSE;
+ SetWindowPos(hwnd_main, NULL, 0, 0, wd_def, ht_def, SWP_NOCOPYBITS|SWP_NOMOVE|SWP_NOOWNERZORDER|SWP_NOZORDER);
+ #if 0
+ imgr=new WinImageRGB(226, 33);
+ if (imgr==NULL) return FALSE;
+ imgr->fill(0,0,(char)255);
+ HDC hdc_main=GetDC(hwnd_main);
+ imgf=new WinFastImage(hdc_main, imgr->getHbitmap());
+ #endif
+ ShowWindow(hwnd_main, nCmdShow);
+ // ReleaseDC(hwnd_main, hdc_main);
+ UpdateWindow(hwnd_main);
+ // imgr->fill((char)255,0,0);
+ return TRUE;
+}
+
+static void do_ask_save_as() {
+ // !! implement this
+}
+
+/** @return true iff save successful */
+static bool do_save(bool ask_save_as) {
+ /* !! implement this */
+ if (!dirty) return true;
+ if (filename2==NULL && ask_save_as) do_ask_save_as();
+ if (filename2==NULL) return false;
+ if (IDYES==MessageBox(hwnd_main, "Saving... Success?", NULL, MB_YESNO)) {
+ dirty=false;
+ return true;
+ }
+ return false;
+}
+
+static void do_save_as(void) {
+ char *old_filename2=filename2;
+ filename2=NULL;
+ do_ask_save_as();
+ if (filename2!=NULL) {
+ if (do_save(false)) { delete [] old_filename2; return; }
+ delete [] filename2;
+ }
+ filename2=old_filename2;
+}
+
+/** no@@return true iff should exit */
+static void do_exit(void) {
+ if (dirty) {
+ int i=MessageBox(hwnd_main, "Save changes before exit?", "Confirm exit",
+ MB_YESNOCANCEL|MB_ICONEXCLAMATION|MB_DEFBUTTON1);
+ if (i==IDCANCEL || (i==IDYES && !do_save(true))) return;
+ }
+ DestroyWindow(hwnd_main);
+}
+
+static void getFrameSize(HWND hwnd, LONG &wd_ret, LONG &ht_ret) {
+ RECT wr; GetWindowRect(hwnd, &wr);
+ RECT cr; GetClientRect(hwnd, &cr);
+ wd_ret=(wr.right-wr.left)-(cr.right-cr.left);
+ ht_ret=(wr.bottom-wr.top)-(cr.bottom-cr.top);
+}
+
+extern Image::Loader in_bmp_loader;
+
+struct SamArgs {
+ typedef void* (WINAPI*samfun_t)(SamArgs const*);
+};
+
+struct SamImageLoad: public SamArgs {
+ char const *filename;
+ SimBuffer::Flat *loadHints;
+};
+
+void* WINAPI do_image_load(SamImageLoad const* args) {
+ // Error::sev((Error::level_t) 2) << "a lma" << (Error*)0;
+ return Image::load(args->filename, *(args->loadHints));
+}
+
+void* do_samfun(SamArgs::samfun_t samfun, SamArgs const* args) {
+ SimBuffer::B log;
+ GenBuffer::Writable *old_serr=Error::serr;
+ Error::pushPolicy((Error::level_t)0, (Error::level_t)-99, (Error::level_t)-199, &log); // Error::serr=&log;
+ HANDLE hthread;
+ DWORD res=0, tid;
+ /* printf("Creating thread.\n"); */
+ if (NULL==(hthread=CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)samfun, (void*)args, CREATE_SUSPENDED, &tid))) {
+ log << "CreateThread() failed\n";
+ on_error:
+ Error::serr=old_serr;
+ log.term0();
+ MessageBox(hwnd_main, log(), Error::banner0, 0);
+ return NULL;
+ }
+ /* printf("Resuming thread (h=0x%x tid=0x%x).\n", hthread, tid); */
+ if (0==1+ResumeThread(hthread)) {
+ log << "ResumeThread() failed\n";
+ on_thread_error:
+ TerminateThread(hthread, 0);
+ CloseHandle(hthread);
+ goto on_error;
+ }
+ /* printf("Waiting for thread.\n"); */
+ if (WAIT_FAILED==WaitForSingleObject(hthread, INFINITE)) { log << "WaitForSingleObject() failed\n"; goto on_thread_error; }
+ if (0==GetExitCodeThread(hthread, &res)) { log << "GetExitCodeThread() failed\n"; goto on_thread_error; }
+ Error::popPolicy();
+ CloseHandle(hthread);
+ Error::serr=old_serr;
+ // !! vvv 0 == NULL, exit(1), exit(2) is
+ if (res+0U<10U) { /* log << "return(NULL);\n1\n"; */ goto on_error; }
+ /* printf("Done, thread has returned=%u\n", res); */
+ return (void*)res;
+}
+
+
+/** Load image from disk, update imgr and imgf
+ * @return true on success
+ */
+static bool do_open_image(char const* filename) {
+ // MessageBox(NULL, filename, "opening image", 0);
+ if (imgf!=NULL) {
+ if (imgr!=NULL) { delete imgr; imgr=NULL; }
+ delete imgf; imgf=NULL;
+ if (filename2!=NULL) filename2[0]='-'; /* mark file closed */
+ }
+
+ // !! free
+ // !! check for errors
+ // !! generalize
+
+ SimBuffer::B loadHints;
+ #if 0
+ Image::Loader::reader_t reader=in_bmp_loader.checker(
+ "BM\0\0\0\0" "\0\0\0\0"
+ "\0\0\0\0" "\0\0\0\0", "", opt);
+ FILE *f=fopen(filename, "rb");
+ if (f==NULL) return false;
+ Image::Sampled *img=reader((Image::filep_t)f, loadHints);
+ fclose(f);
+ #endif
+
+ init_loader();
+ SamImageLoad args;
+ args.filename=filename;
+ args.loadHints=&loadHints;
+ Image::Sampled *img=(Image::Sampled*)do_samfun((SamArgs::samfun_t)do_image_load, &args);
+ if (img==NULL) return false;
+ // Image::load(filename, loadHints);
+
+ imgr=new WinImageRGB(CopyableAdapter(*img));
+ // Image::Sampled *imgrgb=img->toRGB(8);
+ // imgr=new WinImageRGB(img->getWd(), img->getHt());
+ // imgr->fill(0,0,(char)255);
+ // imgr->fromPPM8(imgrgb->getRowbeg());
+ assert(imgr!=NULL); /* `operator new' never returns NULL */
+ // HDC hdc_main=GetDC(hwnd_main);
+ imgf=new WinFastImage(hwnd_main, imgr->getHbitmap());
+ wd_last=imgf->getWd(); ht_last=imgf->getHt();
+ // ReleaseDC(hwnd_main, hdc_main);
+
+ slen_t len=strlen(filename);
+ if (filename2!=NULL) delete [] filename2;
+ strcpy(filename2=new char[len+3], ": ");
+ strcpy(filename2+2, filename);
+ SetWindowText(hwnd_main, filename2);
+ SetWindowLong(hwnd_main, GWL_STYLE, GetWindowLong(hwnd_main, GWL_STYLE)&~WS_THICKFRAME);
+ /* ^^^ The Win32 API way to say hwnd_main.setResizable(false); :-) */
+ InvalidateRect(hwnd_main, NULL, TRUE);
+#if 0
+ LONG fr_wd, fr_ht;
+ getFrameSize(hwnd_main, fr_wd, fr_ht);
+ // !! handle minimum window size
+ SetWindowPos(hwnd_main, NULL, 0, 0, fr_wd+imgf->getWd(), fr_ht+imgf->getHt(), SWP_NOCOPYBITS|SWP_NOMOVE|SWP_NOOWNERZORDER|SWP_NOZORDER);
+ GdiFlush();
+ { /* Dat: strange, two iterations of getFrameSize + SetWindowPos is needed !! still bad */
+ getFrameSize(hwnd_main, fr_wd, fr_ht);
+ SetWindowPos(hwnd_main, NULL, 0, 0, fr_wd+imgf->getWd(), fr_ht+imgf->getHt(), SWP_NOCOPYBITS|SWP_NOMOVE|SWP_NOOWNERZORDER|SWP_NOZORDER);
+ }
+BOOL CYourWndOrDialog::ResizeClient (int nWidth, int nHeight, BOOL bRedraw) {
+ RECT rcWnd;
+ GetClientRect (&rcWnd);
+ if(nWidth != -1)
+ rcWnd.right = nWidth;
+ if(nHeight != -1)
+ rcWnd.bottom = nHeight;
+ if(!::AdjustWindowRectEx(&rcWnd,
+ GetStyle(),
+ (!(GetStyle() & WS_CHILD)
+ && GetMenu() != NULL)), GetExStyle()))
+ return FALSE;
+ UINT uFlags = SWP_NOZORDER | SWP_NOMOVE;
+ if(!bRedraw)
+ uFlags |= SWP_NOREDRAW;
+ return SetWindowPos(NULL,
+ 0, 0,
+ rcWnd.right - rcWnd.left,
+ rcWnd.bottom - rcWnd.top,
+ uFlags);
+ } // CYourWndOrDialog::ResizeClient
+#endif
+ RECT rt;
+ rt.left=0; rt.right=imgf->getWd();
+ rt.top=0; rt.bottom=imgf->getHt();
+ AdjustWindowRect(&rt, GetWindowLong(hwnd_main, GWL_STYLE), TRUE); // !! true
+ SetWindowPos(hwnd_main, NULL, 0,0, rt.right-rt.left, rt.bottom-rt.top,
+ SWP_NOCOPYBITS|SWP_NOMOVE|SWP_NOOWNERZORDER|SWP_NOZORDER);
+ return true;
+}
+
+static char const* loadImageFilter=
+ "all loadable images\0*.tiff;*.tif;*.jpeg;*.jpg;*.gif;*.png;*.pnm;*.pgm;*.ppm;*.xpm;*.lbm;*.tga;*.pcx;*.bmp\0"
+ "TIFF images\0*.tiff;*.tif\0"
+ "JPEG images\0*.jpeg;*.jpg\0"
+ "GIF images\0*.gif\0"
+ "PNG images\0*.png\0"
+ "PNM images\0*.pnm;*.pbm;*.pgm;*.ppm\0"
+ "PBM images\0*.pbm\0"
+ "PGM images\0*.pgm\0"
+ "PPM images\0*.ppm\0"
+ "XPM images\0*.xpm\0"
+ "IFF ILBM images\0*.lbm\0"
+ // "EPS figures\0*.eps\0"
+ // "PostScript documents\0*.ps\0"
+ // "PDF figures\0*.pdf\0"
+ // "XWD screen shots\0*.xwd\0"
+ // "PAM images\0*.pam\0"
+ // "Image meta information\0*.meta\0"
+ "Targa TGA images\0*.tga\0"
+ "PCX images\0*.pcx\0"
+ "Windows BMP bitmaps\0*.bmp\0"
+ "All files (*)\0*\0";
+
+static char const* saveImageFilter=
+ "all saveable images\0*.tiff;*.tif;*.jpeg;*.jpg;*.gif;*.png"
+ ";*.pnm;*.pgm;*.ppm;*.xpm;*.lbm;*.tga;*.pcx;*.bmp;*.eps;*.ps;*.pdf;*.xwd;*.pam;*.meta\0"
+ "TIFF images\0*.tiff;*.tif\0"
+ "JPEG images\0*.jpeg;*.jpg\0"
+ "GIF images\0*.gif\0"
+ "PNG images\0*.png\0"
+ "PNM images\0*.pnm;*.pbm;*.pgm;*.ppm\0"
+ "PBM images\0*.pbm\0"
+ "PGM images\0*.pgm\0"
+ "PPM images\0*.ppm\0"
+ "XPM images\0*.xpm\0"
+ "IFF ILBM images\0*.lbm\0"
+ "EPS figures\0*.eps\0"
+ "PostScript documents\0*.ps\0"
+ "PDF figures\0*.pdf\0"
+ "XWD screen shots\0*.xwd\0"
+ // "PAM images\0*.pam\0"
+ "Image meta information\0*.meta\0"
+ "Targa TGA images\0*.tga\0"
+ "PCX images\0*.pcx\0"
+ "Windows BMP bitmaps\0*.bmp\0"
+ "All files (*)\0*\0";
+
+static void do_open(void) {
+ OPENFILENAME ofn;
+ // ZeroMemory(&ofn, sizeof(ofn));
+ char szFileName[MAX_PATH];
+ szFileName[0]='\0';
+ ofn.lpstrTitle="Open image with sam2p";
+ ofn.lStructSize = sizeof(ofn); // SEE NOTE BELOW
+ ofn.hwndOwner = NULL; // hwnd;
+ ofn.lpstrFilter=loadImageFilter;
+ ofn.lpstrDefExt=NULL;
+ ofn.lpstrFile = szFileName;
+ ofn.nMaxFile = MAX_PATH;
+ ofn.Flags = OFN_EXPLORER | OFN_FILEMUSTEXIST /*|OFN_HIDEREADONLY*/
+ |OFN_EXTENSIONDIFFERENT /*|OFN_NODEREFERENCELINKS*/ |OFN_READONLY;
+ ofn.lpstrDefExt = "txt";
+ ofn.hInstance=NULL;
+ ofn.lpstrCustomFilter=NULL; // !!
+ ofn.nMaxCustFilter=0; // !!
+ ofn.nFilterIndex=0; // use Custom Filter
+ ofn.lpstrFileTitle=NULL;
+ ofn.nMaxFileTitle=0;
+ ofn.lpstrInitialDir=NULL; // use current directory
+ ofn.nFileOffset=0;
+ ofn.nFileExtension=0;
+ ofn.lCustData=NULL;
+ ofn.lpfnHook=NULL;
+ ofn.lpTemplateName=NULL;
+ // MessageBox(NULL, "hello", "world", 0);
+ if (GetOpenFileName(&ofn)) {
+ do_open_image(szFileName);
+ }
+}
+
+static void do_new(void) {
+ if (imgf!=NULL) {
+ if (filename2!=NULL) filename2[0]='-';
+ if (imgr!=NULL) { delete imgr; imgr=NULL; }
+ delete imgf; imgf=NULL;
+ #if 0
+ if (filename2!=NULL) { delete [] filename2; filename2=NULL; }
+ SetWindowText(hwnd_main, Error::banner0);
+ #endif
+ SetWindowLong(hwnd_main, GWL_STYLE, GetWindowLong(hwnd_main, GWL_STYLE)|WS_THICKFRAME);
+ /* ^^^ The Win32 API way to say hwnd_main.setResizable(true); :-) */
+ InvalidateRect(hwnd_main, NULL, TRUE);
+ // SetWindowPos(hwnd_main, NULL, 0, 0, wd_def, ht_def, SWP_NOCOPYBITS|SWP_NOMOVE|SWP_NOOWNERZORDER|SWP_NOZORDER);
+ /* ^^^ Do _not_ revert to default window size */
+ SendMessage(hwnd_main, WM_SIZE, 0, 0); /* calls updateBgText() */
+ } else if (wd_last!=0 || ht_last!=0) {
+ if (filename2!=NULL) { delete [] filename2; filename2=NULL; }
+ SetWindowText(hwnd_main, Error::banner0);
+ wd_last=0; ht_last=0;
+ SendMessage(hwnd_main, WM_SIZE, 0, 0); /* calls updateBgText() */
+ }
+}
+
+/** Rectangle to draw the background text into */
+static RECT bgRect={0,0,0,0};
+static char bgText[128];
+
+/** @param hwnd hwnd_main */
+static void updateBgText(HWND hwnd, slen_t x, slen_t y) {
+ RECT rt;
+ HDC hdc=GetDC(hwnd);
+ GetClientRect(hwnd, &rt); bgRect=rt;
+ sprintf(bgText, "%s\n%lu\327%lu", Error::banner0, x+0UL, y+0UL);
+ // DrawText(hdc, msg, strlen(msg), &rt, DT_CENTER|DT_VCENTER|DT_SINGLELINE);
+ int textht=DrawText(hdc, bgText, -1, &rt, DT_CENTER|DT_CALCRECT);
+ bgRect.top+=(bgRect.bottom-bgRect.top-textht)/2;
+ ReleaseDC(hwnd, hdc);
+}
+
+//void CDECL AfxTrace(LPCTSTR lpszFormat, ...);
+
+/** Processes messages for the main window. */
+LRESULT CALLBACK WndProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam) {
+ PAINTSTRUCT ps;
+ HDC hdc;
+ RECT *rp, rt;
+ int i;
+ switch (message) {
+ case WM_PAINT:
+ if (first_paint_p) {
+ first_paint_p=false;
+ // LoadString(hInst, IDS_HELLO, szHello, MAX_LOADSTRING);
+ }
+ hdc = BeginPaint(hwnd, &ps);
+ if (imgf==NULL) { /* no image is loaded yet */
+ DrawText(hdc, bgText, -1, &bgRect, DT_CENTER);
+ } else {
+ GetClientRect(hwnd, &rt);
+ bool xbad=0U+rt.right-rt.left>imgf->getWd(), ybad=0U+rt.bottom-rt.top>imgf->getHt();
+ if (ps.fErase && (xbad || ybad)) {
+ /* Erase only region not part of the image; to avoid flicker */
+ // HDC hdc=GetDC(hwnd);
+ // HBRUSH hbrush=(HBRUSH)GetClassLong(hwnd, GCL_HBRBACKGROUND);
+ HBRUSH hbrush=(HBRUSH)GetStockObject(WHITE_BRUSH);
+ HGDIOBJ holdbrush=SelectObject(hdc, hbrush);
+ HPEN hpen=(HPEN)GetStockObject(WHITE_PEN); /* always used */
+ HGDIOBJ holdpen=SelectObject(hdc, hpen);
+ Rectangle(hdc, imgf->getWd(), rt.top, rt.right, rt.bottom);
+ Rectangle(hdc, rt.left, imgf->getHt(), imgf->getWd(), rt.bottom);
+ SelectObject(hdc, holdpen);
+ SelectObject(hdc, holdbrush);
+ // ReleaseDC(hwnd, hdc);
+ }
+ // if (imgf==NULL) imgf=new WinFastImage(hdc, imgr->getHbitmap());
+ // rt.right-=rt.left; rt.bottom-=rt.top;
+ imgf->drawTo(hdc, rt.left, rt.top);
+ if (xbad) { /* show the borders of the image inside the window */
+ MoveToEx(hdc, rt.left+imgf->getWd(), rt.top, NULL);
+ LineTo(hdc, rt.left+imgf->getWd(), rt.bottom-1);
+ LineTo(hdc, rt.right-1, rt.top);
+ }
+ if (ybad) { /* show the borders of the image inside the window */
+ MoveToEx(hdc, rt.left, imgf->getHt()+rt.top, NULL);
+ LineTo(hdc, rt.left+imgf->getWd(), rt.bottom-1);
+ LineTo(hdc, rt.left, imgf->getHt()+rt.top);
+ }
+ }
+ EndPaint(hwnd, &ps);
+ return 0;
+ case WM_COMMAND:
+ /* int wmId=LOWORD(wParam), wmEvent=HIWORD(wParam); */
+ switch (LOWORD(wParam)) {
+ case IDM_SAVE:
+ do_save(true); return 0;
+ case IDM_SAVE_AS:
+ {
+ char *argv[]={"(progname)","pts.ppm","pts.ps",NULL};
+ int argc=3;
+ char result[30];
+ int ret=main(argc, argv);
+ // int ret=getpid();
+ sprintf(result, "main run: %d", ret);
+ MessageBox(hwnd, result, NULL, 0); /* unreached !! */
+ }
+ do_save_as(); return 0;
+ case IDM_WEBSITE:
+ /* Dat: it seems to be impossible to force the browser to open the URL
+ * in a new window (instead of overwriting the current window). There
+ * are OLE/DDE solutions for Netscape4 and Internet Explorer, but no
+ * generic solution.
+ */
+ ShellExecute(hwnd, "open", "http://www.inf.bme.hu/~pts/sam2p/", 0, 0, SW_SHOWDEFAULT);
+ return 0;
+ case IDM_ABOUT:
+ DialogBox(hInst, (LPCTSTR)IDD_ABOUTBOX, hwnd, (DLGPROC)About);
+ return 0;
+ case IDM_OPEN:
+ do_open(); return 0;
+ case IDM_NEW:
+ do_new(); return 0;
+ case IDM_PARAMETERS:
+ DialogBox(hInst, (LPCTSTR)IDD_RUN, hwnd, (DLGPROC)dialogRun);
+ return 0;
+ case IDM_EXIT:
+ do_exit(); return 0;
+ default:
+ MessageBox(hwnd,"Unimplemented.", Error::banner0, 0);
+ return 0;
+ }
+ case WM_SIZING: /* possibly override resize requests */
+ if (imgf!=NULL) { /* resize the window to perfectly fit the image */
+ rp=(RECT*)lParam;
+ // RECT wr; GetWindowRect(hwnd, &wr);
+ // RECT cr; GetClientRect(hwnd, &cr);
+ // rp->right=rp->left+imgf->getWd()+(wr.right-wr.left)-(cr.right-cr.left);
+ // rp->bottom=rp->top+imgf->getHt()+(wr.bottom-wr.top)-(cr.bottom-cr.top);
+ getFrameSize(hwnd, rp->right, rp->bottom);
+ rp->right+=rp->left+imgf->getWd();
+ rp->bottom+=rp->top+imgf->getHt();
+ return TRUE;
+ } else return FALSE;
+ case WM_ERASEBKGND:
+ if (imgf!=NULL) return FALSE;
+ break;
+ /* Dat: upon window resize, WM_SIZING, WM_SIZE, WM_ERASEBKGND and WM_PAINT is sent in this order */
+ case WM_SIZE: /* we have been resized; let's invalidate the window contents */
+ GetClientRect(hwnd, &rt);
+ if (wd_last==0 && ht_last==0) updateBgText(hwnd, rt.right-rt.left, rt.bottom-rt.top);
+ else updateBgText(hwnd, wd_last, ht_last);
+ InvalidateRect(hwnd, NULL, TRUE);
+ return 0;
+ case WM_CLOSE: /* user has clicked button X on the title bar; confirm exit first */
+ do_exit(); return 0;
+ case WM_DESTROY: /* exit already confirmed */
+ PostQuitMessage(0);
+ return 0;
+ }
+ return DefWindowProc(hwnd, message, wParam, lParam);
+}
+
+#if 0
+char *s="1111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111"
+ "1111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111"
+ "1111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111"
+ "1111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111";
+#endif
+
+// Mesage handler for about box.
+LRESULT CALLBACK About(HWND hdlg, UINT message, WPARAM wParam, LPARAM /*lParam*/) {
+ switch (message) {
+ case WM_INITDIALOG:
+ { HFONT hfont=CreateFont(10, 0, 0, 0, 700, 0, 0, 0, 0, 0, 0, 0, 0, /*"System"*/ "MS Sans Serif");
+ SendMessage(GetDlgItem(hdlg, IDC_PRODUCT), WM_SETFONT, (WPARAM)hfont, MAKELPARAM(TRUE, 0));
+ // !! DeleteObject
+ SetDlgItemText(hdlg, IDC_PRODUCT, Error::banner0);
+ SetDlgItemText(hdlg, IDC_INFO,
+"This is the Win32 GUI of sam2p.\r\n"
+" sam2p is a UNIX command line utility written in ANSI C++ that converts many "
+"raster (bitmap) image formats into Adobe PostScript or PDF files and several "
+"other formats. The images "
+"are not vectorized. sam2p gives full control to the user to specify "
+"standards-compliance, compression, and bit depths. In some cases sam2p can "
+"compress an image 100 times smaller than the PostScript output of many other "
+"common image converters. sam2p provides ZIP, RLE and LZW (de)compression "
+"filters even on Level1 devices.\r\n");
+ }
+ return TRUE;
+ case WM_COMMAND:
+ if (LOWORD(wParam) == IDOK || LOWORD(wParam) == IDCANCEL) {
+ { CHOOSEFONT cf;
+ ZeroMemory(&cf, sizeof(cf));
+ cf.lStructSize=sizeof(cf);
+ cf.rgbColors=0; /* black */
+ cf.Flags=CF_EFFECTS|CF_FORCEFONTEXIST|CF_NOSIMULATIONS|CF_NOVERTFONTS|CF_SCREENFONTS;
+ cf.hwndOwner=NULL;
+ cf.hDC=NULL;
+ ChooseFont(&cf);
+ }
+ EndDialog(hdlg, LOWORD(wParam));
+ return TRUE;
+ }
+ break;
+ }
+ return FALSE;
+}
+
+LRESULT CALLBACK dialogRun(HWND hdlg, UINT message, WPARAM wParam, LPARAM /*lParam*/) {
+ switch (message) {
+ case WM_INITDIALOG:
+ { HWND hwnd=GetDlgItem(hdlg, IDC_ELOG);
+ HFONT hfont=CreateFont(10, 0, 0, 0, 400, 0, 0, 0, 0, 0, 0, 0, 0,"Fixedsys");
+ SendMessage(hwnd, WM_SETFONT, (WPARAM)hfont, MAKELPARAM(TRUE, 0));
+ // DeleteObject(hfont); /* Imp: where to do DeleteObject()? */
+ /* PostMessage doesn't work, either */
+ unsigned i;
+ char buf[222];
+ for (i=0;i<100;i++) {
+ SendMessage(hwnd,EM_SETSEL,0U-1,0U-1);
+ sprintf(buf, "%d Hello, World! 0123456789 1111111111 222222222 333333333\r\n", i);
+ SendMessage(hwnd,EM_REPLACESEL,FALSE,(LPARAM)(LPCTSTR)buf);
+ }
+ SendMessage(hwnd,EM_SCROLLCARET,0,0);
+ InvalidateRect(hwnd,NULL,FALSE); /* no effect */
+ // !! EM_REPLACESEL doesn't make the end of the edit box text
+ }
+ return TRUE;
+ #if 0
+ case WM_ACTIVATE:
+ { // HWND hwnd=GetDlgItem(hdlg, IDC_ELOG);
+ // MessageBox(NULL,"Hello","",0);
+ //SendMessage(hwnd,EM_SETSEL,-1,2000);
+ //SendMessage(hwnd,EM_SCROLLCARET,0,0);
+ //InvalidateRect(hwnd,NULL,FALSE); /* no effect */
+ }
+ return TRUE;
+ #endif
+ case WM_COMMAND:
+ if (LOWORD(wParam) == IDOK) {
+ HWND hwnd=GetDlgItem(hdlg, IDC_ELOG);
+ SendMessage(hwnd,EM_SETSEL,0xFFFFFFFF,-1);
+ SendMessage(hwnd,EM_REPLACESEL,FALSE,(LPARAM)(LPCTSTR)"Append.");
+ break;
+ }
+ if (LOWORD(wParam) == IDOK || LOWORD(wParam) == IDCANCEL) {
+ EndDialog(hdlg, LOWORD(wParam));
+ return TRUE;
+ }
+ break;
+ }
+ return FALSE;
+}
diff --git a/graphics/sam2p/vcsam2p.dsp b/graphics/sam2p/vcsam2p.dsp
new file mode 100644
index 0000000000..2a878f468d
--- /dev/null
+++ b/graphics/sam2p/vcsam2p.dsp
@@ -0,0 +1,300 @@
+# Microsoft Developer Studio Project File - Name="vcsam2p" - Package Owner=<4>
+# Microsoft Developer Studio Generated Build File, Format Version 6.00
+# ** DO NOT EDIT **
+
+# TARGTYPE "Win32 (x86) Application" 0x0101
+
+CFG=vcsam2p - Win32 Debug
+!MESSAGE This is not a valid makefile. To build this project using NMAKE,
+!MESSAGE use the Export Makefile command and run
+!MESSAGE
+!MESSAGE NMAKE /f "vcsam2p.mak".
+!MESSAGE
+!MESSAGE You can specify a configuration when running NMAKE
+!MESSAGE by defining the macro CFG on the command line. For example:
+!MESSAGE
+!MESSAGE NMAKE /f "vcsam2p.mak" CFG="vcsam2p - Win32 Debug"
+!MESSAGE
+!MESSAGE Possible choices for configuration are:
+!MESSAGE
+!MESSAGE "vcsam2p - Win32 Release" (based on "Win32 (x86) Application")
+!MESSAGE "vcsam2p - Win32 Debug" (based on "Win32 (x86) Application")
+!MESSAGE
+
+# Begin Project
+# PROP AllowPerConfigDependencies 0
+# PROP Scc_ProjName ""
+# PROP Scc_LocalPath ""
+CPP=cl.exe
+MTL=midl.exe
+RSC=rc.exe
+
+!IF "$(CFG)" == "vcsam2p - Win32 Release"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 0
+# PROP BASE Output_Dir "Release"
+# PROP BASE Intermediate_Dir "Release"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 0
+# PROP Output_Dir "Release"
+# PROP Intermediate_Dir "Release"
+# PROP Target_Dir ""
+# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /D "_MBCS" /Yu"StdAfx.h" /FD /c
+# ADD CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /D "_MBCS" /FD /c
+# SUBTRACT CPP /YX /Yc /Yu
+# ADD BASE MTL /nologo /D "NDEBUG" /mktyplib203 /win32
+# ADD MTL /nologo /D "NDEBUG" /mktyplib203 /win32
+# ADD BASE RSC /l 0x409 /d "NDEBUG"
+# ADD RSC /l 0x409 /d "NDEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LINK32=link.exe
+# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:windows /machine:I386
+# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:windows /machine:I386
+
+!ELSEIF "$(CFG)" == "vcsam2p - Win32 Debug"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 1
+# PROP BASE Output_Dir "Debug"
+# PROP BASE Intermediate_Dir "Debug"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 1
+# PROP Output_Dir "Debug"
+# PROP Intermediate_Dir "Debug"
+# PROP Target_Dir ""
+# ADD BASE CPP /nologo /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /D "_MBCS" /Yu"StdAfx.h" /FD /GZ /c
+# ADD CPP /nologo /W4 /Gm /ZI /Od /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /D "_MBCS" /YX /FD /GZ /c
+# ADD BASE MTL /nologo /D "_DEBUG" /mktyplib203 /win32
+# ADD MTL /nologo /D "_DEBUG" /mktyplib203 /win32
+# ADD BASE RSC /l 0x409 /d "_DEBUG"
+# ADD RSC /l 0x409 /d "_DEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LINK32=link.exe
+# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:windows /debug /machine:I386 /pdbtype:sept
+# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:windows /debug /machine:I386 /pdbtype:sept
+
+!ENDIF
+
+# Begin Target
+
+# Name "vcsam2p - Win32 Release"
+# Name "vcsam2p - Win32 Debug"
+# Begin Group "Source Files"
+
+# PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat"
+# Begin Source File
+
+SOURCE=.\appliers.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=.\crc32.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\encoder.cpp
+
+!IF "$(CFG)" == "vcsam2p - Win32 Release"
+
+!ELSEIF "$(CFG)" == "vcsam2p - Win32 Debug"
+
+# ADD CPP /W4 /GX- /Od /YX"config2.h"
+
+!ENDIF
+
+# End Source File
+# Begin Source File
+
+SOURCE=.\error.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=.\gensi.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=.\gensio.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=.\image.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=.\in_bmp.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=.\in_gif.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=.\in_jai.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=.\in_jpeg.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=.\in_lbm.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=.\in_pcx.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=.\in_png.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=.\in_pnm.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=.\in_tga.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=.\in_tiff.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=.\in_xpm.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=.\mapping.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=.\minips.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=.\out_gif.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=.\pts_defl.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\pts_fax.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\pts_lzw.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\rule.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=.\sam2p_main.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=.\snprintf.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\StdAfx.cpp
+# ADD CPP /Yc"StdAfx.h"
+# End Source File
+# Begin Source File
+
+SOURCE=.\vcsam2p.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=.\vcsam2p.rc
+# End Source File
+# End Group
+# Begin Group "Header Files"
+
+# PROP Default_Filter "h;hpp;hxx;hm;inl"
+# Begin Source File
+
+SOURCE=.\at_bitmap.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\cgif.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\config.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\config2.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\crc32.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\pts_defl.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\pts_fax.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\pts_lzw.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\resource.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\snprintf.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\StdAfx.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\tmp.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\vcsam2p.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\xpmc.h
+# End Source File
+# End Group
+# Begin Group "Resource Files"
+
+# PROP Default_Filter "ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe"
+# Begin Source File
+
+SOURCE=.\small.ico
+# End Source File
+# Begin Source File
+
+SOURCE=.\vcsam2p.ico
+# End Source File
+# End Group
+# Begin Source File
+
+SOURCE=.\ReadMe.txt
+# End Source File
+# End Target
+# End Project
diff --git a/graphics/sam2p/vcsam2p.h b/graphics/sam2p/vcsam2p.h
new file mode 100644
index 0000000000..f5404b40a8
--- /dev/null
+++ b/graphics/sam2p/vcsam2p.h
@@ -0,0 +1,14 @@
+
+#if !defined(AFX_VCSAM2P_H__26C24785_06B6_11D7_846E_0004E2009304__INCLUDED_)
+#define AFX_VCSAM2P_H__26C24785_06B6_11D7_846E_0004E2009304__INCLUDED_
+
+#if _MSC_VER > 1000
+#ifndef __clang__
+#pragma once
+#endif
+#endif // _MSC_VER > 1000
+
+#include "resource.h"
+
+
+#endif // !defined(AFX_VCSAM2P_H__26C24785_06B6_11D7_846E_0004E2009304__INCLUDED_)
diff --git a/graphics/sam2p/vcsam2p.ico b/graphics/sam2p/vcsam2p.ico
new file mode 100644
index 0000000000..386883523b
--- /dev/null
+++ b/graphics/sam2p/vcsam2p.ico
Binary files differ
diff --git a/graphics/sam2p/vcsam2p.rc b/graphics/sam2p/vcsam2p.rc
new file mode 100644
index 0000000000..34f9ab3411
--- /dev/null
+++ b/graphics/sam2p/vcsam2p.rc
@@ -0,0 +1,162 @@
+//Microsoft Developer Studio generated resource script.
+//
+#include "resource.h"
+
+#define APSTUDIO_READONLY_SYMBOLS
+/////////////////////////////////////////////////////////////////////////////
+//
+// Generated from the TEXTINCLUDE 2 resource.
+//
+#define APSTUDIO_HIDDEN_SYMBOLS
+#include "windows.h"
+#undef APSTUDIO_HIDDEN_SYMBOLS
+#include "resource.h"
+
+/////////////////////////////////////////////////////////////////////////////
+#undef APSTUDIO_READONLY_SYMBOLS
+
+/////////////////////////////////////////////////////////////////////////////
+// English (U.S.) resources
+
+#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_ENU)
+#ifdef _WIN32
+LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US
+#pragma code_page(1252)
+#endif //_WIN32
+
+/////////////////////////////////////////////////////////////////////////////
+//
+// Icon
+//
+
+// Icon with lowest ID value placed first to ensure application icon
+// remains consistent on all systems.
+IDI_SAM2P16 ICON DISCARDABLE "sam2p16.ico"
+IDI_SAM2P32 ICON DISCARDABLE "sam2p32.ico"
+
+/////////////////////////////////////////////////////////////////////////////
+//
+// Menu
+//
+
+IDC_VCSAM2P MENU DISCARDABLE
+BEGIN
+ POPUP "&Image"
+ BEGIN
+ MENUITEM "&New/Close", IDM_NEW
+ MENUITEM "&Open...", IDM_OPEN
+ MENUITEM "&Save", IDM_SAVE
+ MENUITEM "Save &as...", IDM_SAVE_AS
+ MENUITEM "&Parameters...", IDM_PARAMETERS
+ MENUITEM SEPARATOR
+ MENUITEM "E&xit", IDM_EXIT
+ END
+ POPUP "&Help"
+ BEGIN
+ MENUITEM "&About sam2p...", IDM_ABOUT
+ MENUITEM "&Web site", IDM_WEBSITE
+ END
+END
+
+
+/////////////////////////////////////////////////////////////////////////////
+//
+// Accelerator
+//
+
+IDC_VCSAM2P ACCELERATORS MOVEABLE PURE
+BEGIN
+ "?", IDM_ABOUT, ASCII, ALT
+ "/", IDM_ABOUT, ASCII, ALT
+END
+
+
+/////////////////////////////////////////////////////////////////////////////
+//
+// Dialog
+//
+
+IDD_ABOUTBOX DIALOG DISCARDABLE 22, 17, 142, 76
+STYLE DS_MODALFRAME | WS_CAPTION | WS_SYSMENU
+CAPTION "About"
+FONT 8, "System"
+BEGIN
+ ICON IDI_SAM2P32,IDC_MYICON,2,3,16,16
+ LTEXT "vcsam2p Version 1.0",IDC_PRODUCT,19,5,90,8,SS_NOPREFIX
+ LTEXT "Copyright (C) 2002 pts",IDC_STATIC,1,20,139,52
+ DEFPUSHBUTTON "OK",IDOK,110,4,30,11,WS_GROUP
+END
+
+
+#ifdef APSTUDIO_INVOKED
+/////////////////////////////////////////////////////////////////////////////
+//
+// TEXTINCLUDE
+//
+
+2 TEXTINCLUDE DISCARDABLE
+BEGIN
+ "#define APSTUDIO_HIDDEN_SYMBOLS\r\n"
+ "#include ""windows.h""\r\n"
+ "#undef APSTUDIO_HIDDEN_SYMBOLS\r\n"
+ "#include ""resource.h""\r\n"
+ "\0"
+END
+
+3 TEXTINCLUDE DISCARDABLE
+BEGIN
+ "\r\n"
+ "\0"
+END
+
+1 TEXTINCLUDE DISCARDABLE
+BEGIN
+ "resource.h\0"
+END
+
+#endif // APSTUDIO_INVOKED
+
+
+/////////////////////////////////////////////////////////////////////////////
+//
+// DESIGNINFO
+//
+
+#ifdef APSTUDIO_INVOKED
+GUIDELINES DESIGNINFO DISCARDABLE
+BEGIN
+ IDD_ABOUTBOX, DIALOG
+ BEGIN
+ BOTTOMMARGIN, 75
+ END
+END
+#endif // APSTUDIO_INVOKED
+
+
+/////////////////////////////////////////////////////////////////////////////
+//
+// String Table
+//
+
+STRINGTABLE DISCARDABLE
+BEGIN
+ IDS_APP_TITLE "vcsam2p"
+ IDS_HELLO "Hello World!"
+ IDC_VCSAM2P "VCSAM2P"
+END
+
+#endif // English (U.S.) resources
+/////////////////////////////////////////////////////////////////////////////
+
+
+
+#ifndef APSTUDIO_INVOKED
+/////////////////////////////////////////////////////////////////////////////
+//
+// Generated from the TEXTINCLUDE 3 resource.
+//
+
+
+/////////////////////////////////////////////////////////////////////////////
+#endif // not APSTUDIO_INVOKED
+
diff --git a/graphics/sam2p/xpmc.h b/graphics/sam2p/xpmc.h
new file mode 100644
index 0000000000..1b965fb43c
--- /dev/null
+++ b/graphics/sam2p/xpmc.h
@@ -0,0 +1,4 @@
+#define xpmColors_mul 95
+#define xpmColors_mod 1109
+unsigned short xpmColors_ofs[]={0,0,0,1,0,0,0,0,0,0,0,0,15,0,43,0,0,0,0,0,0,0,65,0,0,0,84,0,0,0,0,0,96,0,0,0,0,0,0,0,113,0,0,0,0,0,0,0,0,0,0,129,140,151,162,173,199,210,221,232,243,0,254,0,0,0,0,268,0,0,0,0,282,0,0,0,0,0,0,0,0,0,0,0,0,0,0,296,0,310,0,0,0,0,0,0,0,0,0,0,0,0,0,329,0,0,0,0,0,0,0,0,343,352,0,0,0,0,0,0,368,0,0,0,0,0,0,0,0,0,0,0,0,0,382,0,0,0,0,0,0,0,0,0,0,0,391,402,413,424,435,446,457,468,479,490,0,0,0,0,0,0,0,0,0,501,0,516,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,525,0,0,0,0,0,0,540,0,557,0,0,0,568,0,0,576,0,0,0,0,0,0,0,0,0,0,594,0,0,0,0,0,607,0,0,0,0,0,0,0,0,0,0,0,0,0,0,623,634,645,656,667,678,689,700,711,722,0,0,733,0,0,0,743,0,0,0,0,0,0,0,0,0,0,0,0,763,0,0,0,0,771,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,785,0,0,0,794,0,0,0,0,0,0,0,0,806,816,0,0,0,0,833,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,842,853,864,875,886,897,908,919,930,941,0,952,0,0,0,0,0,966,0,0,0,0,0,0,0,0,0,980,0,0,0,0,0,0,989,0,0,1011,0,1026,0,0,0,0,0,0,0,0,0,1041,1056,0,0,1066,0,0,0,0,0,1075,1090,0,1106,0,1120,0,0,0,1134,0,0,0,0,0,1148,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1167,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1180,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1199,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1214,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1228,0,0,0,0,0,0,1241,1255,0,0,0,0,1265,1279,0,0,0,0,0,0,0,0,0,1293,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1312,0,0,0,0,0,0,0,0,0,0,0,0,0,1324,0,1333,0,1345,0,0,0,0,0,0,0,0,0,0,1359,0,0,0,1370,0,0,0,0,1387,1405,0,0,1418,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1436,0,0,0,1450,0,0,0,1461,0,0,0,0,1482,0,1497,0,0,0,0,0,0,0,1511,0,0,0,0,0,0,0,0,0,1527,0,0,0,0,0,0,0,0,0,1541,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1560,1571,1582,1593,1604,1615,1626,1637,1648,1659,0,0,0,0,0,0,0,0,0,0,0,1670,0,0,1685,0,0,0,0,0,1699,0,0,0,0,0,0,0,1710,0,0,0,0,0,0,1721,0,0,0,0,0,0,0,0,0,0,0,1739,1748,0,0,0,0,0,0,1758,0,1776,0,1788,0,0,0,0,0,0,0,0,0,1806,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1831,1857,1868,1879,1890,1901,1912,1923,1934,1945,0,0,0,0,0,0,0,1956,0,0,0,0,0,0,0,0,0,0,0,0,0,1969,0,0,0,0,0,0,0,1979,0,0,0,0,0,0,1994,0,2004,0,0,0,0,0,2015,0,0,0,0,0,0,0,0,0,0,0,0,2033,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2049,0,0,0,0,2067,2078,2089,2100,2111,2122,2133,2144,2155,2166,0,0,0,0,2177,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2190,2209,2225,0,0,0,0,0,0,0,2241,0,2256,0,0,0,0,2267,0,2286,0,2297,0,0,0,0,0,0,0,0,0,0,0,2312,0,0,0,0,0,0,0,0,0,0,0,0,2328,0,0,0,0,0,0,0,0,0,0,2340,0,0,0,2358,0,0,0,2372,2383,2394,2405,2432,2443,2464,2488,2499,2510,2521,2538,0,0,0,0,0,0,0,2558,2568,0,0,0,0,0,0,0,0,0,0,2583,0,0,0,2603,0,0,0,0,0,0,2623,0,0,0,2635,0,2649,0,0,0,2663,2673,2683,2693,2703,2713,2723,2733,2743,2753,0,0,0,0,0,0,2763,2777,0,0,0,0,2790,2809,0,0,0,0,2826,0,2841,2851,0,0,0,0,0,0,0,0,0,0,0,2862,2873,2884,2895,2906,2917,2928,2939,2950,2961,0,2972,0,0,2981,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2994,0,0,0,0,0,0,0,0,0,0,0,};
+char xpmColors_dat[]="\000LawnGreen\000|\374\000\000SlateGray\000p\200\220WhiteSmoke\000\365\365\365\000MediumForestGreen\000""2\201K\000LightSlateGray\000w\210\231\000Magenta\000\377\000\377\000DarkSeaGreen\000\217\274\217\000ForestGreen\000P\237i\000Gray60\000\231\231\231\000Gray61\000\234\234\234\000Gray62\000\236\236\236\000Gray63\000\241\241\241\000GreenYellow\000\255\377/Gray64\000\243\243\243\000Gray65\000\246\246\246\000Gray66\000\250\250\250\000Gray67\000\253\253\253\000Gray68\000\255\255\255\000Gray69\000\260\260\260\000PaleGreen\000s\336x\000chocolate\000\322i\036\000DarkKhaki\000\275\267k\000PeachPuff\000\377\332\271\000DarkOliveGreen\000UV/\000LightCyan\000\340\377\377\000Blue\000\000\000\377\000NavajoWhite\000\377\336\255\000AliceBlue\000\360\370\377\000Gold\000\332\252\000\000Gray70\000\263\263\263\000Gray71\000\265\265\265\000Gray72\000\270\270\270\000Gray73\000\272\272\272\000Gray74\000\275\275\275\000Gray75\000\277\277\277\000Gray76\000\302\302\302\000Gray77\000\304\304\304\000Gray78\000\307\307\307\000Gray79\000\311\311\311\000GhostWhite\000\370\370\377\000peru\000\315\205?\000DarkSalmon\000\351\226z\000MidnightBlue\000//d\000Salmon\000\351\226z\000Tan\000\336\270\207\000DarkSlateGray\000/OO\000moccasin\000\377\344\265\000LightYellow\000\377\377\340\000Gray80\000\314\314\314\000Gray81\000\317\317\317\000Gray82\000\321\321\321\000Gray83\000\324\324\324\000Gray84\000\326\326\326\000Gray85\000\331\331\331\000Gray86\000\333\333\333\000Gray87\000\336\336\336\000Gray88\000\340\340\340\000Gray89\000\343\343\343\000Azure\000\360\377\377\000MediumSlateBlue\000jj\215\000Red\000\377\000\000\000VioletRed\000\363>\226\000Plum\000\305H\233\000SkyBlue\000r\237\377\000linen\000\372\360\346\000AntiqueWhite\000\372\353\327\000Navy\000##u\000Gray90\000\345\345\345\000Gray91\000\350\350\350\000Gray92\000\353\353\353\000Gray93\000\355\355\355\000Gray94\000\360\360\360\000Gray95\000\362\362\362\000Gray96\000\365\365\365\000Gray97\000\367\367\367\000Gray98\000\372\372\372\000Gray99\000\374\374\374\000OliveDrab\000k\216#\000LightBlue\000\260\342\377\000None\000\003\002\001\000MediumSpringGreen\000#\216#\000BlueViolet\000\212+\342\000MediumBlue\000""22\314\000PapayaWhip\000\377\357\325\000Brown\000\245**\000Pink\000\377\265\305\000chartreuse\000\177\377\000\000SpringGreen\000A\254A\000RoyalBlue\000Ai\341\000Goldenrod\000\357\337\204\000Turquoise\000\031\314\337\000LightGoldenrod\000\356\335\202\000NavyBlue\000##u\000MediumSeaGreen\000""4wf\000PowderBlue\000\260\340\346\000LimeGreen\000\000\257\024\000honeydew\000\360\377\360\000LightPink\000\377\266\301\000ivory\000\377\377\360\000OrangeRed\000\377E\000\000SteelBlue\000Tp\252\000LightSteelBlue\000|\230\323\000Gray100\000\377\377\377\000Gray\000~~~\000DimGray\000TTT\000gainsboro\000\334\334\334\000tomato\000\377cG\000LemonChiffon\000\377\372\315\000DarkGoldenrod\000\270\206\013\000SeaGreen\000R\225\204\000DarkTurquoise\000\000\246\246\000Firebrick\000\216##\000Yellow\000\377\377\000\000MediumAquamarine\000\000\223\217\000DodgerBlue\000\036\220\377\000CadetBlue\000_\222\236\000YellowGreen\000""2\330""8\000SlateBlue\000~\210\253\000LightSlateBlue\000\204p\377\000Gray10\000\032\032\032\000Gray11\000\034\034\034\000Gray12\000\037\037\037\000Gray13\000!!!\000Gray14\000$$$\000Gray15\000&&&\000Gray16\000)))\000Gray17\000+++\000Gray18\000...\000Gray19\000""000\000DarkOrange\000\377\214\000\000LightGray\000\250\250\250\000Orange\000\377\207\000\000Sienna\000\226R-\000PaleVioletRed\000\333p\223\000snow\000\377\372\372\000Coral\000\377rV\000PaleGoldenrod\000\356\350\252\000OldLace\000\375\365\346\000PaleTurquoise\000\257\356\356\000LightGoldenrodYellow\000\372\372\322\000DeepSkyBlue\000\000\277\377Gray20\000""333\000Gray21\000""666\000Gray22\000""888\000Gray23\000;;;\000Gray24\000===\000Gray25\000@@@\000Gray26\000BBB\000Gray27\000EEE\000Gray28\000GGG\000Gray29\000JJJ\000seashell\000\377\365\356\000Black\000\000\000\000\000DarkViolet\000\224\000\323\000Wheat\000\365\336\263\000Violet\000\234>\316\000LightSeaGreen\000\040\262\252\000FloralWhite\000\377\372\360\000LavenderBlush\000\377\360\365\000Gray30\000MMM\000Gray31\000OOO\000Gray32\000RRR\000Gray33\000TTT\000Gray34\000WWW\000Gray35\000YYY\000Gray36\000\\\\\\\000Gray37\000^^^\000Gray38\000aaa\000Gray39\000ccc\000DeepPink\000\377\024\223\000Green\000\000\377\000White\000\377\377\377\000LightSalmon\000\377\240z\000Transparent\000\000\000\001\000DarkOrchid\000\213\040\213\000purple\000\240\040\360\000BlanchedAlmond\000\377\353\315\000Orchid\000\357\204\357\000LightCoral\000\360\200\200\000SaddleBrown\000\213E\023\000Thistle\000\330\277\330\000DarkSlateBlue\000""8Kf\000burlywood\000\336\270\207\000Gray40\000fff\000Gray41\000iii\000Gray42\000kkk\000MediumPurple\000\223p\333Gray43\000nnn\000Gray44\000ppp\000Maroon\000\217\000RGray45\000sss\000IndianRed\000k99Gray46\000uuu\000Gray47\000xxx\000Gray48\000zzz\000Gray49\000}}}\000MediumOrchid\000\275R\275\000MediumVioletRed\000\325\040y\000Khaki\000\263\263~\000SandyBrown\000\364\244`\000MediumGoldenrod\000\321\301f\000MediumTurquoise\000\000\322\322\000HotPink\000\377i\264\000MistyRose\000\377\344\341\000MintCream\000\365\377\372\000Gray0\000\000\000\000\000Gray1\000\003\003\003\000Gray2\000\005\005\005\000Gray3\000\010\010\010\000Gray4\000\012\012\012\000Gray5\000\015\015\015\000Gray6\000\017\017\017\000Gray7\000\022\022\022\000Gray8\000\024\024\024\000Gray9\000\027\027\027\000RosyBrown\000\274\217\217\000cornsilk\000\377\370\334\000CornflowerBlue\000\"\"\230\000LightSkyBlue\000\207\316\372\000Aquamarine\000""2\277\301\000Beige\000\365\365\334\000Bisque\000\377\344\304\000Gray50\000\177\177\177\000Gray51\000\202\202\202\000Gray52\000\205\205\205\000Gray53\000\207\207\207\000Gray54\000\212\212\212\000Gray55\000\214\214\214\000Gray56\000\217\217\217\000Gray57\000\221\221\221\000Gray58\000\224\224\224\000Gray59\000\226\226\226\000Cyan\000\000\377\377\000lavender\000\346\346\372\000DarkGreen\000\000V-";