summaryrefslogtreecommitdiffstats
path: root/kfax
diff options
context:
space:
mode:
authortoma <toma@283d02a7-25f6-0310-bc7c-ecb5cbfe19da>2009-11-25 17:56:58 +0000
committertoma <toma@283d02a7-25f6-0310-bc7c-ecb5cbfe19da>2009-11-25 17:56:58 +0000
commit47d455dd55be855e4cc691c32f687f723d9247ee (patch)
tree52e236aaa2576bdb3840ebede26619692fed6d7d /kfax
downloadtdegraphics-47d455dd55be855e4cc691c32f687f723d9247ee.tar.gz
tdegraphics-47d455dd55be855e4cc691c32f687f723d9247ee.zip
Copy the KDE 3.5 branch to branches/trinity for new KDE 3.5 features.
BUG:215923 git-svn-id: svn://anonsvn.kde.org/home/kde/branches/trinity/kdegraphics@1054174 283d02a7-25f6-0310-bc7c-ecb5cbfe19da
Diffstat (limited to 'kfax')
-rw-r--r--kfax/AUTHORS3
-rw-r--r--kfax/ChangeLog28
-rw-r--r--kfax/Makefile.am32
-rw-r--r--kfax/NOTES49
-rw-r--r--kfax/README34
-rw-r--r--kfax/TODO2
-rw-r--r--kfax/examples/README22
-rw-r--r--kfax/examples/README.kdeapps12
-rw-r--r--kfax/examples/kde.g3bin0 -> 55571 bytes
-rw-r--r--kfax/examples/nasty.tiffbin0 -> 92354 bytes
-rw-r--r--kfax/faxexpand.cpp732
-rw-r--r--kfax/faxexpand.h160
-rw-r--r--kfax/faxinit.cpp337
-rw-r--r--kfax/faxinput.cpp479
-rw-r--r--kfax/hi16-app-kfax.pngbin0 -> 787 bytes
-rw-r--r--kfax/hi22-app-kfax.pngbin0 -> 1241 bytes
-rw-r--r--kfax/hi32-app-kfax.pngbin0 -> 1928 bytes
-rw-r--r--kfax/hi48-app-kfax.pngbin0 -> 3352 bytes
-rw-r--r--kfax/hisc-app-kfax.svgzbin0 -> 11876 bytes
-rw-r--r--kfax/kfax.cpp1695
-rw-r--r--kfax/kfax.desktop86
-rw-r--r--kfax/kfax.h159
-rw-r--r--kfax/kfax.tifbin0 -> 74703 bytes
-rw-r--r--kfax/kfax_printsettings.cpp98
-rw-r--r--kfax/kfax_printsettings.h47
-rw-r--r--kfax/kfaxlogo.xpm134
-rw-r--r--kfax/kfaxui.rc28
-rw-r--r--kfax/options.cpp374
-rw-r--r--kfax/options.h112
-rw-r--r--kfax/version.h1
-rw-r--r--kfax/viewfax.cpp770
-rw-r--r--kfax/viewfax.h27
32 files changed, 5421 insertions, 0 deletions
diff --git a/kfax/AUTHORS b/kfax/AUTHORS
new file mode 100644
index 00000000..88b4ef2b
--- /dev/null
+++ b/kfax/AUTHORS
@@ -0,0 +1,3 @@
+Bernd Johannes Wuebben
diff --git a/kfax/ChangeLog b/kfax/ChangeLog
new file mode 100644
index 00000000..39accef4
--- /dev/null
+++ b/kfax/ChangeLog
@@ -0,0 +1,28 @@
+1999-03-03 Harri Porten <[email protected]>
+
+ * viewfax.cpp: prefix getopt declarations with 'extern'. Bug reported
+ by Oliver Oster <[email protected]>
+
+1999-02-08 Harri Porten <[email protected]>
+
+ * fixed segfault caused by infinite recursion in kfaxerror()
+
+Sun May 3 16:48:13 1998 Bernd Johannes Wuebben <[email protected]>
+
+ * fixed print dialog
+ adjusted layout for i18n
+
+Sun Oct 5 22:17:09 1997 Bernd Johannes Wuebben <[email protected]>
+
+ * added support for printing all fax formats at all printer page
+ sizes.
+
+Sun Aug 3 09:55:52 1997 Bernd Johannes Wuebben <[email protected]>
+
+ * Made kfax work with the new KToolBar etc.
+
+Thu Jul 24 20:44:33 1997 Bernd Johannes Wuebben <[email protected]>
+
+ * made the necessary changes so that kfax will compile with
+ the new libs.
+
diff --git a/kfax/Makefile.am b/kfax/Makefile.am
new file mode 100644
index 00000000..fd3e478c
--- /dev/null
+++ b/kfax/Makefile.am
@@ -0,0 +1,32 @@
+AM_LDFLAGS = $(all_libraries) $(KDE_RPATH)
+LDADD = $(LIB_KFILE) $(LIB_KDEPRINT) -lm
+INCLUDES = $(all_includes)
+
+####### Files
+noinst_HEADERS = kfax.h faxexpand.h options.h
+
+kfax_SOURCES = options.cpp kfax.cpp faxexpand.cpp faxinit.cpp faxinput.cpp \
+ viewfax.cpp kfax_printsettings.cpp
+
+METASOURCES = AUTO
+
+bin_PROGRAMS = kfax
+
+xdg_apps_DATA = kfax.desktop
+
+picsdir = $(kde_datadir)/kfax/pics
+pics_DATA = kfax.tif kfaxlogo.xpm
+
+rcdir = $(kde_datadir)/kfax
+rc_DATA = kfaxui.rc
+
+KDE_ICON = kfax
+
+EXTRA_DIST = $(xdg_apps_DATA) $(pics_DATA)
+
+messages: rc.cpp
+ $(XGETTEXT) $(kfax_SOURCES) -o $(podir)/kfax.pot
+
+####### Explicit dependencies
+
+
diff --git a/kfax/NOTES b/kfax/NOTES
new file mode 100644
index 00000000..9a3c70b6
--- /dev/null
+++ b/kfax/NOTES
@@ -0,0 +1,49 @@
+
+Drag and Drop
+Net Drag and Drop
+
+kfax can display all fax output modes of ghostscript:
+raw: fag3 faxg32d faxg4
+tiff: tiffg3 tiffg32d tiffg4
+
+By default raw fax files are interpreted as g3 files. If you want
+to display faxg3-2d and faxg4 files you have to specifiy this on
+the command line and in the case of raw g4 files also specify
+the height in scan lines of the fax if it differs from the
+default 2155.
+
+A raw file will have no pagignation information and will be displayed
+as a whole in the fax window.
+tiff files contain pagination information can be paged through in the
+fax window
+
+kfax can not display image file formats which are not related to
+faxing, such as an arbitrary tiff or gif file.
+
+
+How to create fax file that sendfax /mgetty can accept and send:
+gs -sDEVICE=faxg3 -sOutputFile=/tmp/fax.g3.%d yourdocument.ps
+
+Assume that you ps document yourdocumnet.ps contains three pages,
+this will produce fax.g3.1 fax.g3.2 fax.g3.3
+
+
+HylaFAX:
+http://info-sys.home.vix.com/flexfax/toc.html
+
+sendfax/mgetty:
+http://www.leo.org/~doering/mgetty/
+
+cat fax.g3 | g32pbm | pnmtops -noturn > output.ps
+
+
+
+How to print raw " no tiff " g3 fax data:
+
+
+
+fax2tiff -M viewfax.g3 -o viewfax.tiff
+(M for: Treat input data as having bits filled from most
+ significant bit (MSB) to most least bit (LSB))
+This is what I need on my intel machine, I would presume this
+might be different on a Sun station.
diff --git a/kfax/README b/kfax/README
new file mode 100644
index 00000000..23d3c6c2
--- /dev/null
+++ b/kfax/README
@@ -0,0 +1,34 @@
+KFax 0.3
+
+Added printing for g32 and g4, so that kfax can now print all fax formats.
+Added support for all pages sizes.
+
+Bernd
+
+
+I am please to release KFax 0.2, the first public release of
+KFax - a fax file viewer for the KDE project.
+
+Please peruse the accompanying html documentation for more information
+about KFax
+
+Help wanted:
+============
+
+Much of my work was done "in vitro". Now it is time to go out into
+the wilderness and test KFax:
+
+I need people to send me faxes from all sorts of programs and machines
+in order to thoroughly test KFax and develop further ideas as to what needs
+to be implemented. If you own a fax modem or a fax machine and you would
+like to help, please write to me by email. I will then give you my phone
+number and we will agree on which fax program I will used for reception.
+You can then send me a fax from your favorite program or machine, stating
+what machine/program you used, from where you sent the fax, what
+the size of the fax is, the number of pages you transmitted etc.
+This would be very helpful. Thanks for your coorporation.
+
+thanks,
+Bernd Wuebben
diff --git a/kfax/TODO b/kfax/TODO
new file mode 100644
index 00000000..2e9d8464
--- /dev/null
+++ b/kfax/TODO
@@ -0,0 +1,2 @@
+o Page Marking
+o Printing of only the Marked pages
diff --git a/kfax/examples/README b/kfax/examples/README
new file mode 100644
index 00000000..74631fe6
--- /dev/null
+++ b/kfax/examples/README
@@ -0,0 +1,22 @@
+If you have the kdeapps distributions, please also read README.kdeapps
+thanks,
+Bernd
+
+This directory contains a number of fax files which you can use to
+test and play with KFax:
+
+kde.g3 a group 3 raw fax file
+kde.g32d a group 3, 2-dim raw fax file
+kde.g4 a group 4 raw fax file
+
+Note: the g32d and g4 raw fax files will not display correctly
+ unless you change the default raw fax file format on the
+ Fax Options dialog.
+
+kdefaq.tiff.g3 a tiff group 3 encoded fax file
+kdefaq.tiff.g32d a tiff group 3, 2-dim, encoded fax file
+kdefaq.tiff.g4 a tiff group 4 encoded fax file
+
+Note that the tiff file format is the superiour format. Each
+of the above tiff fax files contains several pages.
+
diff --git a/kfax/examples/README.kdeapps b/kfax/examples/README.kdeapps
new file mode 100644
index 00000000..6664690a
--- /dev/null
+++ b/kfax/examples/README.kdeapps
@@ -0,0 +1,12 @@
+Note from the kdeapps maintainer:
+
+This directory used to contain several example fax files. Some of which are
+raw fax files others tiff fax files. Since I need to keep the kdeapps
+distributions small in size, I removed them with the permission of the author.
+You will still find all example files in the original kfax distribution
+at:
+
+ftp.kde.org//pub/kde/apps/graphics/
+
+Stephan Kulow <[email protected]>
+
diff --git a/kfax/examples/kde.g3 b/kfax/examples/kde.g3
new file mode 100644
index 00000000..a419e9af
--- /dev/null
+++ b/kfax/examples/kde.g3
Binary files differ
diff --git a/kfax/examples/nasty.tiff b/kfax/examples/nasty.tiff
new file mode 100644
index 00000000..e9edd50c
--- /dev/null
+++ b/kfax/examples/nasty.tiff
Binary files differ
diff --git a/kfax/faxexpand.cpp b/kfax/faxexpand.cpp
new file mode 100644
index 00000000..93f1bc85
--- /dev/null
+++ b/kfax/faxexpand.cpp
@@ -0,0 +1,732 @@
+/* Expand one page of fax data
+ Copyright (C) 1990, 1995 Frank D. Cringle.
+
+This file is part of viewfax - g3/g4 fax processing software.
+
+viewfax is free software; you can redistribute it and/or modify it
+under the terms of the GNU General Public License as published by the
+Free Software Foundation; either version 2 of the License, or (at your
+option) any later version.
+
+This program is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <sys/types.h>
+#include "faxexpand.h"
+
+//Uncomment this for verbose debug output
+//#define DEBUG_FAX
+
+/* Note that NeedBits() only works for n <= 16 */
+#define NeedBits(n) do { \
+ if (BitsAvail < (n)) { \
+ BitAcc |= *sp++ << BitsAvail; \
+ BitsAvail += 16; \
+ } \
+} while (0)
+#define GetBits(n) (BitAcc & ((1<<(n))-1))
+#define ClrBits(n) do { \
+ BitAcc >>= (n); \
+ BitsAvail -= (n); \
+} while (0)
+
+#ifdef DEBUG_FAX
+#define DEBUG_SHOW putchar(BitAcc & (1 << t) ? '1' : '0')
+#define LOOKUP(wid,tab) do { \
+ int t; \
+ NeedBits(wid); \
+ TabEnt = tab + GetBits(wid); \
+ printf("%08lX/%d: %s%5d\t", BitAcc, BitsAvail, \
+ StateNames[TabEnt->State], TabEnt->Param); \
+ for (t = 0; t < TabEnt->Width; t++) \
+ DEBUG_SHOW; \
+ putchar('\n'); \
+ fflush(stdout); \
+ ClrBits(TabEnt->Width); \
+} while (0)
+
+#define SETVAL(x) do { \
+ *pa++ = RunLength + (x); \
+ printf("SETVAL: %d\t%d\n", RunLength + (x), a0); \
+ a0 += x; \
+ RunLength = 0; \
+} while (0)
+
+char *StateNames[] = {
+ "Null ",
+ "Pass ",
+ "Horiz ",
+ "V0 ",
+ "VR ",
+ "VL ",
+ "Ext ",
+ "TermW ",
+ "TermB ",
+ "MakeUpW",
+ "MakeUpB",
+ "MakeUp ",
+ "EOL ",
+};
+
+#else
+#define LOOKUP(wid,tab) do { \
+ NeedBits(wid); \
+ TabEnt = tab + GetBits(wid); \
+ ClrBits(TabEnt->Width); \
+} while (0)
+
+#define SETVAL(x) do { \
+ *pa++ = RunLength + (x); \
+ a0 += x; \
+ RunLength = 0; \
+} while (0)
+#endif
+
+#define dumpruns(runs) do { \
+ printf("-------------------- %d\n", LineNum); \
+ for (pa = runs, a0 = 0; a0 < lastx; a0 += *pa++) \
+ printf("%4d %d\n", a0, *pa); \
+} while (0)
+
+#define EndOfData(pn) (sp >= pn->data + pn->length/sizeof(*pn->data))
+
+/* This macro handles coding errors in G3 data.
+ We redefine it below for the G4 case */
+#define SKIP_EOL do { \
+ while (!EndOfData(pn)) { \
+ NeedBits(11); \
+ if (GetBits(11) == 0) \
+ break; \
+ ClrBits(1); \
+ } \
+ ClrBits(11); \
+ goto EOL; \
+} while (0)
+#define eol2lab EOL2:
+
+/* the line expanders are written as macros so that they can be reused
+ (twice each) but still have direct access to the local variables of
+ the "calling" function */
+#define expand1d() do { \
+ while (a0 < lastx) { \
+ int done = 0; \
+ while (!done) { /* white first */ \
+ LOOKUP(12, WhiteTable); \
+ switch (TabEnt->State) { \
+ case S_EOL: \
+ EOLcnt = 1; \
+ goto EOL; \
+ case S_TermW: \
+ SETVAL(TabEnt->Param); \
+ done = 1; \
+ break; \
+ case S_MakeUpW: \
+ case S_MakeUp: \
+ a0 += TabEnt->Param; \
+ RunLength += TabEnt->Param; \
+ break; \
+ case S_Ext: \
+ unexpected("Extension code", LineNum); \
+ SKIP_EOL; \
+ break; \
+ default: \
+ unexpected("WhiteTable", LineNum); \
+ SKIP_EOL; \
+ break; \
+ } \
+ } \
+ done = a0 >= lastx; \
+ while (!done) { /* then black */ \
+ LOOKUP(13, BlackTable); \
+ switch (TabEnt->State) { \
+ case S_EOL: \
+ EOLcnt = 1; \
+ goto EOL; \
+ case S_TermB: \
+ SETVAL(TabEnt->Param); \
+ done = 1; \
+ break; \
+ case S_MakeUpB: \
+ case S_MakeUp: \
+ a0 += TabEnt->Param; \
+ RunLength += TabEnt->Param; \
+ break; \
+ case S_Ext: \
+ unexpected("Extension code", LineNum); \
+ SKIP_EOL; \
+ break; \
+ default: \
+ unexpected("BlackTable", LineNum); \
+ SKIP_EOL; \
+ break; \
+ } \
+ } \
+ } \
+ EOL: ; \
+} while (0)
+
+#define CHECK_b1 do { \
+ if (pa != thisrun) while (b1 <= a0 && b1 < lastx) { \
+ b1 += pb[0] + pb[1]; \
+ pb += 2; \
+ } \
+} while (0)
+
+#define expand2d(eolab) do { \
+ while (a0 < lastx) { \
+ LOOKUP(7, MainTable); \
+ switch (TabEnt->State) { \
+ case S_Pass: \
+ CHECK_b1; \
+ b1 += *pb++; \
+ RunLength += b1 - a0; \
+ a0 = b1; \
+ b1 += *pb++; \
+ break; \
+ case S_Horiz: \
+ if ((pa-run0)&1) { \
+ int done = 0; \
+ while (!done) { /* black first */ \
+ LOOKUP(13, BlackTable); \
+ switch (TabEnt->State) { \
+ case S_TermB: \
+ SETVAL(TabEnt->Param); \
+ done = 1; \
+ break; \
+ case S_MakeUpB: \
+ case S_MakeUp: \
+ a0 += TabEnt->Param; \
+ RunLength += TabEnt->Param; \
+ break; \
+ default: \
+ unexpected("BlackTable", LineNum); \
+ SKIP_EOL; \
+ break; \
+ } \
+ } \
+ done = 0; \
+ while (!done) { /* then white */ \
+ LOOKUP(12, WhiteTable); \
+ switch (TabEnt->State) { \
+ case S_TermW: \
+ SETVAL(TabEnt->Param); \
+ done = 1; \
+ break; \
+ case S_MakeUpW: \
+ case S_MakeUp: \
+ a0 += TabEnt->Param; \
+ RunLength += TabEnt->Param; \
+ break; \
+ default: \
+ unexpected("WhiteTable", LineNum); \
+ SKIP_EOL; \
+ break; \
+ } \
+ } \
+ } \
+ else { \
+ int done = 0; \
+ while (!done) { /* white first */ \
+ LOOKUP(12, WhiteTable); \
+ switch (TabEnt->State) { \
+ case S_TermW: \
+ SETVAL(TabEnt->Param); \
+ done = 1; \
+ break; \
+ case S_MakeUpW: \
+ case S_MakeUp: \
+ a0 += TabEnt->Param; \
+ RunLength += TabEnt->Param; \
+ break; \
+ default: \
+ unexpected("WhiteTable", LineNum); \
+ SKIP_EOL; \
+ break; \
+ } \
+ } \
+ done = 0; \
+ while (!done) { /* then black */ \
+ LOOKUP(13, BlackTable); \
+ switch (TabEnt->State) { \
+ case S_TermB: \
+ SETVAL(TabEnt->Param); \
+ done = 1; \
+ break; \
+ case S_MakeUpB: \
+ case S_MakeUp: \
+ a0 += TabEnt->Param; \
+ RunLength += TabEnt->Param; \
+ break; \
+ default: \
+ unexpected("BlackTable", LineNum); \
+ SKIP_EOL; \
+ break; \
+ } \
+ } \
+ } \
+ CHECK_b1; \
+ break; \
+ case S_V0: \
+ CHECK_b1; \
+ SETVAL(b1 - a0); \
+ b1 += *pb++; \
+ break; \
+ case S_VR: \
+ CHECK_b1; \
+ SETVAL(b1 - a0 + TabEnt->Param); \
+ b1 += *pb++; \
+ break; \
+ case S_VL: \
+ CHECK_b1; \
+ SETVAL(b1 - a0 - TabEnt->Param); \
+ b1 -= *--pb; \
+ break; \
+ case S_Ext: \
+ *pa++ = lastx - a0; \
+ if (verbose) \
+ fprintf(stderr, "Line %d: extension code\n", LineNum); \
+ SKIP_EOL; \
+ break; \
+ case S_EOL: \
+ *pa++ = lastx - a0; \
+ NeedBits(4); \
+ if (GetBits(4) && verbose) /* already seen 7 zeros */ \
+ fprintf(stderr, "Line %d: Bad EOL\n", LineNum); \
+ ClrBits(4); \
+ EOLcnt = 1; \
+ goto eolab; \
+ break; \
+ default: \
+ unexpected("MainTable", LineNum); \
+ SKIP_EOL; \
+ break; \
+ } \
+ } \
+ if (RunLength) { \
+ if (RunLength + a0 < lastx) { \
+ /* expect a final V0 */ \
+ NeedBits(1); \
+ if (!GetBits(1)) { \
+ unexpected("MainTable", LineNum); \
+ SKIP_EOL; \
+ } \
+ ClrBits(1); \
+ } \
+ SETVAL(0); \
+ } \
+ eol2lab ; \
+} while (0)
+
+static void
+unexpected(const char *what, int LineNum)
+{
+ if (verbose)
+ fprintf(stderr, "Line %d: Unexpected state in %s\n",
+ LineNum, what);
+}
+
+/* Expand tiff modified huffman data (g3-1d without EOLs) */
+void
+MHexpand(struct pagenode *pn, drawfunc df)
+{
+ int a0; /* reference element */
+ int lastx = pn->width; /* copy line width to register */
+ t32bits BitAcc; /* bit accumulator */
+ int BitsAvail; /* # valid bits in BitAcc */
+ int RunLength; /* Length of current run */
+ t16bits *sp; /* pointer into compressed data */
+ pixnum *pa; /* pointer into new line */
+ int EOLcnt; /* number of consecutive EOLs */
+ int LineNum; /* line number */
+ pixnum *runs; /* list of run lengths */
+ struct tabent *TabEnt;
+
+ sp = pn->data;
+ BitAcc = 0;
+ BitsAvail = 0;
+ lastx = pn->width;
+ runs = (pixnum *) xmalloc(lastx * sizeof(pixnum));
+ for (LineNum = 0; LineNum < pn->rowsperstrip; ) {
+#ifdef DEBUG_FAX
+ printf("\nBitAcc=%08lX, BitsAvail = %d\n", BitAcc, BitsAvail);
+ printf("-------------------- %d\n", LineNum);
+ fflush(stdout);
+#endif
+ RunLength = 0;
+ pa = runs;
+ a0 = 0;
+ EOLcnt = 0;
+ if (BitsAvail & 7) /* skip to byte boundary */
+ ClrBits(BitsAvail & 7);
+ expand1d();
+ if (RunLength)
+ SETVAL(0);
+ if (a0 != lastx) {
+ if (verbose)
+ fprintf(stderr, "Line %d: length is %d (expected %d)\n", LineNum, a0, lastx);
+ while (a0 > lastx)
+ a0 -= *--pa;
+ if (a0 < lastx) {
+ if ((pa - runs) & 1)
+ SETVAL(0);
+ SETVAL(lastx - a0);
+ }
+ }
+ (*df)(runs, LineNum++, pn);
+ }
+ free(runs);
+}
+
+/* Expand group-3 1-dimensional data */
+void
+g31expand(struct pagenode *pn, drawfunc df)
+{
+ int a0; /* reference element */
+ int lastx = pn->width; /* copy line width to register */
+ t32bits BitAcc; /* bit accumulator */
+ int BitsAvail; /* # valid bits in BitAcc */
+ int RunLength; /* Length of current run */
+ t16bits *sp; /* pointer into compressed data */
+ pixnum *pa; /* pointer into new line */
+ int EOLcnt; /* number of consecutive EOLs */
+ int LineNum; /* line number */
+ pixnum *runs; /* list of run lengths */
+ struct tabent *TabEnt;
+
+ sp = pn->data;
+ BitAcc = 0;
+ BitsAvail = 0;
+ lastx = pn->width;
+ runs = (pixnum *) xmalloc(lastx * sizeof(pixnum));
+ EOLcnt = 0;
+ for (LineNum = 0; LineNum < pn->rowsperstrip; ) {
+#ifdef DEBUG_FAX
+ printf("\nBitAcc=%08lX, BitsAvail = %d\n", BitAcc, BitsAvail);
+ printf("-------------------- %d\n", LineNum);
+ fflush(stdout);
+#endif
+ if (EOLcnt == 0)
+ while (!EndOfData(pn)) {
+ /* skip over garbage after a coding error */
+ NeedBits(11);
+ if (GetBits(11) == 0)
+ break;
+ ClrBits(1);
+ }
+ for (EOLcnt = 1; !EndOfData(pn); EOLcnt++) {
+ /* we have seen 11 zeros, which implies EOL,
+ skip possible fill bits too */
+ while (1) {
+ NeedBits(8);
+ if (GetBits(8))
+ break;
+ ClrBits(8);
+ }
+ while (GetBits(1) == 0)
+ ClrBits(1);
+ ClrBits(1); /* the eol flag */
+ NeedBits(11);
+ if (GetBits(11))
+ break;
+ ClrBits(11);
+ }
+ if (EOLcnt > 1 && EOLcnt != 6 && verbose)
+ fprintf(stderr, "Line %d: bad RTC (%d EOLs)\n", LineNum, EOLcnt);
+ if (EOLcnt >= 6 || EndOfData(pn)) {
+ free(runs);
+ return;
+ }
+ RunLength = 0;
+ pa = runs;
+ a0 = 0;
+ EOLcnt = 0;
+ expand1d();
+ if (RunLength)
+ SETVAL(0);
+ if (a0 != lastx) {
+ if (verbose)
+ fprintf(stderr, "Line %d: length is %d (expected %d)\n", LineNum, a0, lastx);
+ while (a0 > lastx)
+ a0 -= *--pa;
+ if (a0 < lastx) {
+ if ((pa - runs) & 1)
+ SETVAL(0);
+ SETVAL(lastx - a0);
+ }
+ }
+ (*df)(runs, LineNum++, pn);
+ }
+ free(runs);
+}
+
+/* Expand group-3 2-dimensional data */
+void
+g32expand(struct pagenode *pn, drawfunc df)
+{
+ int RunLength; /* Length of current run */
+ int a0; /* reference element */
+ int b1; /* next change on previous line */
+ int lastx = pn->width; /* copy line width to register */
+ pixnum *run0, *run1; /* run length arrays */
+ pixnum *thisrun, *pa, *pb; /* pointers into runs */
+ t16bits *sp; /* pointer into compressed data */
+ t32bits BitAcc; /* bit accumulator */
+ int BitsAvail; /* # valid bits in BitAcc */
+ int EOLcnt; /* number of consecutive EOLs */
+ int refline = 0; /* 1D encoded reference line */
+ int LineNum; /* line number */
+ struct tabent *TabEnt;
+
+ sp = pn->data;
+ BitAcc = 0;
+ BitsAvail = 0;
+ /* allocate space for 2 runlength arrays */
+ run0 = (pixnum *) xmalloc(2 * ((lastx+5)&~1) * sizeof(pixnum));
+ run1 = run0 + ((lastx+5)&~1);
+ run1[0] = lastx;
+ run1[1] = 0;
+ EOLcnt = 0;
+ for (LineNum = 0; LineNum < pn->rowsperstrip; ) {
+#ifdef DEBUG_FAX
+ printf("\nBitAcc=%08lX, BitsAvail = %d\n", BitAcc, BitsAvail);
+ printf("-------------------- %d\n", LineNum);
+ fflush(stdout);
+#endif
+ if (EOLcnt == 0)
+ while (!EndOfData(pn)) {
+ /* skip over garbage after a coding error */
+ NeedBits(11);
+ if (GetBits(11) == 0)
+ break;
+ ClrBits(1);
+ }
+ for (EOLcnt = 1; !EndOfData(pn); EOLcnt++) {
+ /* we have seen 11 zeros, which implies EOL,
+ skip possible fill bits too */
+ while (1) {
+ NeedBits(8);
+ if (GetBits(8))
+ break;
+ ClrBits(8);
+ }
+ while (GetBits(1) == 0)
+ ClrBits(1);
+ ClrBits(1); /* the eol flag */
+ NeedBits(12);
+ refline = GetBits(1); /* 1D / 2D flag */
+ ClrBits(1);
+ if (GetBits(11))
+ break;
+ ClrBits(11);
+ }
+ if (EOLcnt > 1 && EOLcnt != 6 && verbose)
+ fprintf(stderr, "Line %d: bad RTC (%d EOLs)\n", LineNum, EOLcnt);
+ if (EOLcnt >= 6 || EndOfData(pn)) {
+ free(run0);
+ return;
+ }
+ if (LineNum == 0 && refline == 0 && verbose)
+ fprintf(stderr, "First line is 2-D encoded\n");
+ RunLength = 0;
+ if (LineNum & 1) {
+ pa = run1;
+ pb = run0;
+ }
+ else {
+ pa = run0;
+ pb = run1;
+ }
+ thisrun = pa;
+ EOLcnt = 0;
+ a0 = 0;
+ b1 = *pb++;
+
+ if (refline) {
+ expand1d();
+ }
+ else {
+ expand2d(EOL2);
+ }
+ if (RunLength)
+ SETVAL(0);
+ if (a0 != lastx) {
+ if (verbose)
+ fprintf(stderr, "Line %d: length is %d (expected %d)\n", LineNum, a0, lastx);
+ while (a0 > lastx)
+ a0 -= *--pa;
+ if (a0 < lastx) {
+ if ((pa - run0) & 1)
+ SETVAL(0);
+ SETVAL(lastx - a0);
+ }
+ }
+ SETVAL(0); /* imaginary change at end of line for reference */
+ (*df)(thisrun, LineNum++, pn);
+ }
+ free(run0);
+}
+
+/* Redefine the "skip to eol" macro. We cannot recover from coding
+ errors in G4 data */
+#undef SKIP_EOL
+#undef eol2lab
+#define SKIP_EOL do { \
+ if (verbose) \
+ fprintf(stderr, "Line %d: G4 coding error\n", LineNum); \
+ free(run0); \
+ return; \
+} while (0)
+#define eol2lab
+
+/* Expand group-4 data */
+void
+g4expand(struct pagenode *pn, drawfunc df)
+{
+ int RunLength; /* Length of current run */
+ int a0; /* reference element */
+ int b1; /* next change on previous line */
+ int lastx = pn->width; /* copy line width to register */
+ pixnum *run0, *run1; /* run length arrays */
+ pixnum *thisrun, *pa, *pb; /* pointers into runs */
+ t16bits *sp; /* pointer into compressed data */
+ t32bits BitAcc; /* bit accumulator */
+ int BitsAvail; /* # valid bits in BitAcc */
+ int LineNum; /* line number */
+ int EOLcnt;
+ struct tabent *TabEnt;
+
+ sp = pn->data;
+ BitAcc = 0;
+ BitsAvail = 0;
+ /* allocate space for 2 runlength arrays */
+ run0 = (pixnum *) xmalloc(2 * ((lastx+5)&~1) * sizeof(pixnum));
+ run1 = run0 + ((lastx+5)&~1);
+ run1[0] = lastx; /* initial reference line */
+ run1[1] = 0;
+
+ for (LineNum = 0; LineNum < pn->rowsperstrip; ) {
+#ifdef DEBUG_FAX
+ printf("\nBitAcc=%08lX, BitsAvail = %d\n", BitAcc, BitsAvail);
+ printf("-------------------- %d\n", LineNum);
+ fflush(stdout);
+#endif
+ RunLength = 0;
+ if (LineNum & 1) {
+ pa = run1;
+ pb = run0;
+ }
+ else {
+ pa = run0;
+ pb = run1;
+ }
+ thisrun = pa;
+ a0 = 0;
+ b1 = *pb++;
+ expand2d(EOFB);
+ if (a0 < lastx) {
+ if ((pa - run0) & 1)
+ SETVAL(0);
+ SETVAL(lastx - a0);
+ }
+ SETVAL(0); /* imaginary change at end of line for reference */
+ (*df)(thisrun, LineNum++, pn);
+ continue;
+ EOFB:
+ NeedBits(13);
+ if (GetBits(13) != 0x1001 && verbose)
+ fputs("Bad RTC\n", stderr);
+ break;
+ }
+ free(run0);
+}
+
+static unsigned char zerotab[256] = {
+ 0x88, 0x07, 0x16, 0x06, 0x25, 0x05, 0x15, 0x05,
+ 0x34, 0x04, 0x14, 0x04, 0x24, 0x04, 0x14, 0x04,
+ 0x43, 0x03, 0x13, 0x03, 0x23, 0x03, 0x13, 0x03,
+ 0x33, 0x03, 0x13, 0x03, 0x23, 0x03, 0x13, 0x03,
+ 0x52, 0x02, 0x12, 0x02, 0x22, 0x02, 0x12, 0x02,
+ 0x32, 0x02, 0x12, 0x02, 0x22, 0x02, 0x12, 0x02,
+ 0x42, 0x02, 0x12, 0x02, 0x22, 0x02, 0x12, 0x02,
+ 0x32, 0x02, 0x12, 0x02, 0x22, 0x02, 0x12, 0x02,
+ 0x61, 0x01, 0x11, 0x01, 0x21, 0x01, 0x11, 0x01,
+ 0x31, 0x01, 0x11, 0x01, 0x21, 0x01, 0x11, 0x01,
+ 0x41, 0x01, 0x11, 0x01, 0x21, 0x01, 0x11, 0x01,
+ 0x31, 0x01, 0x11, 0x01, 0x21, 0x01, 0x11, 0x01,
+ 0x51, 0x01, 0x11, 0x01, 0x21, 0x01, 0x11, 0x01,
+ 0x31, 0x01, 0x11, 0x01, 0x21, 0x01, 0x11, 0x01,
+ 0x41, 0x01, 0x11, 0x01, 0x21, 0x01, 0x11, 0x01,
+ 0x31, 0x01, 0x11, 0x01, 0x21, 0x01, 0x11, 0x01,
+ 0x70, 0x00, 0x10, 0x00, 0x20, 0x00, 0x10, 0x00,
+ 0x30, 0x00, 0x10, 0x00, 0x20, 0x00, 0x10, 0x00,
+ 0x40, 0x00, 0x10, 0x00, 0x20, 0x00, 0x10, 0x00,
+ 0x30, 0x00, 0x10, 0x00, 0x20, 0x00, 0x10, 0x00,
+ 0x50, 0x00, 0x10, 0x00, 0x20, 0x00, 0x10, 0x00,
+ 0x30, 0x00, 0x10, 0x00, 0x20, 0x00, 0x10, 0x00,
+ 0x40, 0x00, 0x10, 0x00, 0x20, 0x00, 0x10, 0x00,
+ 0x30, 0x00, 0x10, 0x00, 0x20, 0x00, 0x10, 0x00,
+ 0x60, 0x00, 0x10, 0x00, 0x20, 0x00, 0x10, 0x00,
+ 0x30, 0x00, 0x10, 0x00, 0x20, 0x00, 0x10, 0x00,
+ 0x40, 0x00, 0x10, 0x00, 0x20, 0x00, 0x10, 0x00,
+ 0x30, 0x00, 0x10, 0x00, 0x20, 0x00, 0x10, 0x00,
+ 0x50, 0x00, 0x10, 0x00, 0x20, 0x00, 0x10, 0x00,
+ 0x30, 0x00, 0x10, 0x00, 0x20, 0x00, 0x10, 0x00,
+ 0x40, 0x00, 0x10, 0x00, 0x20, 0x00, 0x10, 0x00,
+ 0x30, 0x00, 0x10, 0x00, 0x20, 0x00, 0x10, 0x00
+};
+
+#define check(v) do { \
+ prezeros = zerotab[v]; \
+ postzeros = prezeros & 15; \
+ prezeros >>= 4; \
+ if (prezeros == 8) { \
+ zeros += 8; \
+ continue; \
+ } \
+ if (zeros + prezeros < 11) { \
+ empty = 0; \
+ zeros = postzeros; \
+ continue; \
+ } \
+ zeros = postzeros; \
+ if (empty) \
+ EOLcnt++; \
+ lines++; \
+ empty = 1; \
+} while (0)
+
+/* count fax lines */
+int
+G3count(struct pagenode *pn, int twoD)
+{
+ t16bits *p = pn->data;
+ t16bits *end = p + pn->length/sizeof(*p);
+ int lines = 0; /* lines seen so far */
+ int zeros = 0; /* number of consecutive zero bits seen */
+ int EOLcnt = 0; /* number of consecutive EOLs seen */
+ int empty = 1; /* empty line */
+ int prezeros, postzeros;
+
+ while (p < end && EOLcnt < 6) {
+ t16bits bits = *p++;
+ check(bits&255);
+ if (twoD && (prezeros + postzeros == 7)) {
+ if (postzeros || ((bits & 0x100) == 0))
+ zeros--;
+ }
+ check(bits>>8);
+ if (twoD && (prezeros + postzeros == 7)) {
+ if (postzeros || ((p < end) && ((*p & 1) == 0)))
+ zeros--;
+ }
+ }
+ return lines - EOLcnt; /* don't count trailing EOLs */
+}
diff --git a/kfax/faxexpand.h b/kfax/faxexpand.h
new file mode 100644
index 00000000..a1be736f
--- /dev/null
+++ b/kfax/faxexpand.h
@@ -0,0 +1,160 @@
+/* Include file for fax routines
+ Copyright (C) 1990, 1995 Frank D. Cringle.
+
+This file is part of viewfax - g3/g4 fax processing software.
+
+viewfax is free software; you can redistribute it and/or modify it
+under the terms of the GNU General Public License as published by the
+Free Software Foundation; either version 2 of the License, or (at your
+option) any later version.
+
+This program is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */
+
+#ifndef _faxexpand_h_
+#define _faxexpand_h_
+
+#include <limits.h>
+
+#if ULONG_MAX == 4294967295UL
+typedef unsigned long t32bits;
+#elif UINT_MAX == 4294967295UL
+typedef unsigned int t32bits;
+#else
+#error need a 32-bit unsigned type
+/* if you expirence the above error, and live to tell about it,
+ add an #elif case for your architecture
+ and tell [email protected] , [email protected] about it */
+#endif
+
+#if USHRT_MAX == 65535
+typedef unsigned short t16bits;
+#elif UINT_MAX == 65535
+typedef unsigned int t16bits;
+#else
+#error need a 16-bit unsigned type
+/* if you experience the above error, and live to tell about it,
+ add an #elif case for your architecture
+ and tell [email protected] about it */
+#endif
+typedef t16bits pixnum;
+
+struct pagenode;
+
+/* drawfunc() points to a function which processes a line of the
+ expanded image described as a list of run lengths.
+ run is the base of an array of lengths, starting with a
+ (possibly empty) white run for line number linenum.
+ pn points to the page descriptor */
+typedef void (*drawfunc)(pixnum *run, int linenum, struct pagenode *pn);
+
+struct strip { /* tiff strip descriptor */
+ off_t offset; /* offset in file */
+ off_t size; /* size of this strip */
+};
+
+
+/* defines for the pagenode member: type */
+#define FAX_TIFF 1
+#define FAX_RAW 2
+
+struct pagenode { /* compressed page descriptor */
+ struct pagenode *prev, *next; /* list links */
+ char *name; /* basename of file */
+ char *pathname; /* full name of file */
+ int nstrips; /* number of strips */
+ int rowsperstrip; /* number of rows per strip */
+ int stripnum; /* current strip while expanding */
+ struct strip *strips; /* array of strips containing fax data in file */
+ t16bits *data; /* in-memory copy of strip */
+ size_t length; /* length of data */
+ pixnum width; /* width of page in pixels */
+ pixnum height; /* height of page in lines */
+ int inverse; /* black <=> white */
+ int lsbfirst; /* bit order is lsb first */
+ int type; /* Bernd: tiff vs no tiff*/
+ int orient; /* orientation - upsidedown, landscape, mirrored */
+ int vres; /* vertical resolution: 1 = fine */
+ int dpiX,dpiY; /* DPI horz/vert */
+ void (*expander)(struct pagenode *, drawfunc);
+ void *extra; /* used for Ximage */
+};
+extern struct pagenode *firstpage, *lastpage, *thispage,* auxpage;
+extern struct pagenode defaultpage;
+
+/* page orientation flags */
+#define TURN_U 1
+#define TURN_L 2
+#define TURN_M 4
+
+extern const char *ProgName;
+
+/* fsm state codes */
+#define S_Null 0
+#define S_Pass 1
+#define S_Horiz 2
+#define S_V0 3
+#define S_VR 4
+#define S_VL 5
+#define S_Ext 6
+#define S_TermW 7
+#define S_TermB 8
+#define S_MakeUpW 9
+#define S_MakeUpB 10
+#define S_MakeUp 11
+#define S_EOL 12
+
+/* state table entry */
+struct tabent {
+ unsigned char State;
+ unsigned char Width; /* width of code in bits */
+ pixnum Param; /* run length */
+};
+
+extern struct tabent MainTable[]; /* 2-D state table */
+extern struct tabent WhiteTable[]; /* White run lengths */
+extern struct tabent BlackTable[]; /* Black run lengths */
+
+extern int verbose;
+
+void MHexpand(struct pagenode *pn, drawfunc df);
+void g31expand(struct pagenode *pn, drawfunc df);
+void g32expand(struct pagenode *pn, drawfunc df);
+void g4expand(struct pagenode *pn, drawfunc df);
+
+unsigned char * getstrip(struct pagenode *pn, int strip);
+struct pagenode *notefile(const char *name);
+int notetiff(const char *name);
+
+/* initialise code tables */
+extern void faxinit(void);
+/* count lines in image */
+extern int G3count(struct pagenode *pn, int twoD);
+
+/* get memory or abort if none available */
+extern char *xmalloc(unsigned int size);
+
+#ifdef __linux__
+#define _HAVE_USLEEP
+#endif
+
+#if defined(BSD) || defined(__FreeBSD__) || defined(_BSD_SOURCE)
+#define _HAVE_USLEEP
+#ifndef rindex
+#define rindex strrchr
+#endif
+#ifndef bcmp
+#define memcmp bcmp
+#endif
+#define memclr(p,n) bzero(p,n)
+#else /* not BSD */
+#define memclr(p,n) memset(p,0,n)
+#endif
+
+#endif
diff --git a/kfax/faxinit.cpp b/kfax/faxinit.cpp
new file mode 100644
index 00000000..62ee0569
--- /dev/null
+++ b/kfax/faxinit.cpp
@@ -0,0 +1,337 @@
+/* Initialise fax decoder tables
+ Copyright (C) 1990, 1995 Frank D. Cringle.
+
+This file is part of viewfax - g3/g4 fax processing software.
+
+viewfax is free software; you can redistribute it and/or modify it
+under the terms of the GNU General Public License as published by the
+Free Software Foundation; either version 2 of the License, or (at your
+option) any later version.
+
+This program is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */
+
+#include <sys/types.h>
+#include "faxexpand.h"
+
+struct tabent MainTable[128];
+struct tabent WhiteTable[4096];
+struct tabent BlackTable[8192];
+
+struct proto {
+ t16bits code; /* right justified, lsb-first, zero filled */
+ t16bits val; /* (pixel count)<<4 + code width */
+};
+
+static struct proto Pass[] = {
+{ 0x0008, 4 },
+{ 0, 0 }
+};
+
+static struct proto Horiz[] = {
+{ 0x0004, 3 },
+{ 0, 0 }
+};
+
+static struct proto V0[] = {
+{ 0x0001, 1 },
+{ 0, 0 }
+};
+
+static struct proto VR[] = {
+{ 0x0006, (1<<4)+3 },
+{ 0x0030, (2<<4)+6 },
+{ 0x0060, (3<<4)+7 },
+{ 0, 0 }
+};
+
+static struct proto VL[] = {
+{ 0x0002, (1<<4)+3 },
+{ 0x0010, (2<<4)+6 },
+{ 0x0020, (3<<4)+7 },
+{ 0, 0 }
+};
+
+static struct proto ExtV[] = {
+{ 0x0040, 7 },
+{ 0, 0 }
+};
+
+static struct proto EOLV[] = {
+{ 0x0000, 7 },
+{ 0, 0 }
+};
+
+static struct proto MakeUpW[] = {
+{ 0x001b, 1029 },
+{ 0x0009, 2053 },
+{ 0x003a, 3078 },
+{ 0x0076, 4103 },
+{ 0x006c, 5128 },
+{ 0x00ec, 6152 },
+{ 0x0026, 7176 },
+{ 0x00a6, 8200 },
+{ 0x0016, 9224 },
+{ 0x00e6, 10248 },
+{ 0x0066, 11273 },
+{ 0x0166, 12297 },
+{ 0x0096, 13321 },
+{ 0x0196, 14345 },
+{ 0x0056, 15369 },
+{ 0x0156, 16393 },
+{ 0x00d6, 17417 },
+{ 0x01d6, 18441 },
+{ 0x0036, 19465 },
+{ 0x0136, 20489 },
+{ 0x00b6, 21513 },
+{ 0x01b6, 22537 },
+{ 0x0032, 23561 },
+{ 0x0132, 24585 },
+{ 0x00b2, 25609 },
+{ 0x0006, 26630 },
+{ 0x01b2, 27657 },
+{ 0, 0 }
+};
+
+static struct proto MakeUpB[] = {
+{ 0x03c0, 1034 },
+{ 0x0130, 2060 },
+{ 0x0930, 3084 },
+{ 0x0da0, 4108 },
+{ 0x0cc0, 5132 },
+{ 0x02c0, 6156 },
+{ 0x0ac0, 7180 },
+{ 0x06c0, 8205 },
+{ 0x16c0, 9229 },
+{ 0x0a40, 10253 },
+{ 0x1a40, 11277 },
+{ 0x0640, 12301 },
+{ 0x1640, 13325 },
+{ 0x09c0, 14349 },
+{ 0x19c0, 15373 },
+{ 0x05c0, 16397 },
+{ 0x15c0, 17421 },
+{ 0x0dc0, 18445 },
+{ 0x1dc0, 19469 },
+{ 0x0940, 20493 },
+{ 0x1940, 21517 },
+{ 0x0540, 22541 },
+{ 0x1540, 23565 },
+{ 0x0b40, 24589 },
+{ 0x1b40, 25613 },
+{ 0x04c0, 26637 },
+{ 0x14c0, 27661 },
+{ 0, 0 }
+};
+
+static struct proto MakeUp[] = {
+{ 0x0080, 28683 },
+{ 0x0180, 29707 },
+{ 0x0580, 30731 },
+{ 0x0480, 31756 },
+{ 0x0c80, 32780 },
+{ 0x0280, 33804 },
+{ 0x0a80, 34828 },
+{ 0x0680, 35852 },
+{ 0x0e80, 36876 },
+{ 0x0380, 37900 },
+{ 0x0b80, 38924 },
+{ 0x0780, 39948 },
+{ 0x0f80, 40972 },
+{ 0, 0 }
+};
+
+static struct proto TermW[] = {
+{ 0x00ac, 8 },
+{ 0x0038, 22 },
+{ 0x000e, 36 },
+{ 0x0001, 52 },
+{ 0x000d, 68 },
+{ 0x0003, 84 },
+{ 0x0007, 100 },
+{ 0x000f, 116 },
+{ 0x0019, 133 },
+{ 0x0005, 149 },
+{ 0x001c, 165 },
+{ 0x0002, 181 },
+{ 0x0004, 198 },
+{ 0x0030, 214 },
+{ 0x000b, 230 },
+{ 0x002b, 246 },
+{ 0x0015, 262 },
+{ 0x0035, 278 },
+{ 0x0072, 295 },
+{ 0x0018, 311 },
+{ 0x0008, 327 },
+{ 0x0074, 343 },
+{ 0x0060, 359 },
+{ 0x0010, 375 },
+{ 0x000a, 391 },
+{ 0x006a, 407 },
+{ 0x0064, 423 },
+{ 0x0012, 439 },
+{ 0x000c, 455 },
+{ 0x0040, 472 },
+{ 0x00c0, 488 },
+{ 0x0058, 504 },
+{ 0x00d8, 520 },
+{ 0x0048, 536 },
+{ 0x00c8, 552 },
+{ 0x0028, 568 },
+{ 0x00a8, 584 },
+{ 0x0068, 600 },
+{ 0x00e8, 616 },
+{ 0x0014, 632 },
+{ 0x0094, 648 },
+{ 0x0054, 664 },
+{ 0x00d4, 680 },
+{ 0x0034, 696 },
+{ 0x00b4, 712 },
+{ 0x0020, 728 },
+{ 0x00a0, 744 },
+{ 0x0050, 760 },
+{ 0x00d0, 776 },
+{ 0x004a, 792 },
+{ 0x00ca, 808 },
+{ 0x002a, 824 },
+{ 0x00aa, 840 },
+{ 0x0024, 856 },
+{ 0x00a4, 872 },
+{ 0x001a, 888 },
+{ 0x009a, 904 },
+{ 0x005a, 920 },
+{ 0x00da, 936 },
+{ 0x0052, 952 },
+{ 0x00d2, 968 },
+{ 0x004c, 984 },
+{ 0x00cc, 1000 },
+{ 0x002c, 1016 },
+{ 0, 0 }
+};
+
+static struct proto TermB[] = {
+{ 0x03b0, 10 },
+{ 0x0002, 19 },
+{ 0x0003, 34 },
+{ 0x0001, 50 },
+{ 0x0006, 67 },
+{ 0x000c, 84 },
+{ 0x0004, 100 },
+{ 0x0018, 117 },
+{ 0x0028, 134 },
+{ 0x0008, 150 },
+{ 0x0010, 167 },
+{ 0x0050, 183 },
+{ 0x0070, 199 },
+{ 0x0020, 216 },
+{ 0x00e0, 232 },
+{ 0x0030, 249 },
+{ 0x03a0, 266 },
+{ 0x0060, 282 },
+{ 0x0040, 298 },
+{ 0x0730, 315 },
+{ 0x00b0, 331 },
+{ 0x01b0, 347 },
+{ 0x0760, 363 },
+{ 0x00a0, 379 },
+{ 0x0740, 395 },
+{ 0x00c0, 411 },
+{ 0x0530, 428 },
+{ 0x0d30, 444 },
+{ 0x0330, 460 },
+{ 0x0b30, 476 },
+{ 0x0160, 492 },
+{ 0x0960, 508 },
+{ 0x0560, 524 },
+{ 0x0d60, 540 },
+{ 0x04b0, 556 },
+{ 0x0cb0, 572 },
+{ 0x02b0, 588 },
+{ 0x0ab0, 604 },
+{ 0x06b0, 620 },
+{ 0x0eb0, 636 },
+{ 0x0360, 652 },
+{ 0x0b60, 668 },
+{ 0x05b0, 684 },
+{ 0x0db0, 700 },
+{ 0x02a0, 716 },
+{ 0x0aa0, 732 },
+{ 0x06a0, 748 },
+{ 0x0ea0, 764 },
+{ 0x0260, 780 },
+{ 0x0a60, 796 },
+{ 0x04a0, 812 },
+{ 0x0ca0, 828 },
+{ 0x0240, 844 },
+{ 0x0ec0, 860 },
+{ 0x01c0, 876 },
+{ 0x0e40, 892 },
+{ 0x0140, 908 },
+{ 0x01a0, 924 },
+{ 0x09a0, 940 },
+{ 0x0d40, 956 },
+{ 0x0340, 972 },
+{ 0x05a0, 988 },
+{ 0x0660, 1004 },
+{ 0x0e60, 1020 },
+{ 0, 0 }
+};
+
+static struct proto ExtH[] = {
+{ 0x0100, 9 },
+{ 0, 0 }
+};
+
+static struct proto EOLH[] = {
+{ 0x0000, 11 },
+{ 0, 0 }
+};
+
+static void
+FillTable(struct tabent *T, int Size, struct proto *P, int State)
+{
+ int limit = 1 << Size;
+
+ while (P->val) {
+ int width = P->val & 15;
+ int param = P->val >> 4;
+ int incr = 1 << width;
+ int code;
+ for (code = P->code; code < limit; code += incr) {
+ struct tabent *E = T+code;
+ E->State = State;
+ E->Width = width;
+ E->Param = param;
+ }
+ P++;
+ }
+}
+
+/* initialise the huffman code tables */
+void
+faxinit(void)
+{
+ FillTable(MainTable, 7, Pass, S_Pass);
+ FillTable(MainTable, 7, Horiz, S_Horiz);
+ FillTable(MainTable, 7, V0, S_V0);
+ FillTable(MainTable, 7, VR, S_VR);
+ FillTable(MainTable, 7, VL, S_VL);
+ FillTable(MainTable, 7, ExtV, S_Ext);
+ FillTable(MainTable, 7, EOLV, S_EOL);
+ FillTable(WhiteTable, 12, MakeUpW, S_MakeUpW);
+ FillTable(WhiteTable, 12, MakeUp, S_MakeUp);
+ FillTable(WhiteTable, 12, TermW, S_TermW);
+ FillTable(WhiteTable, 12, ExtH, S_Ext);
+ FillTable(WhiteTable, 12, EOLH, S_EOL);
+ FillTable(BlackTable, 13, MakeUpB, S_MakeUpB);
+ FillTable(BlackTable, 13, MakeUp, S_MakeUp);
+ FillTable(BlackTable, 13, TermB, S_TermB);
+ FillTable(BlackTable, 13, ExtH, S_Ext);
+ FillTable(BlackTable, 13, EOLH, S_EOL);
+}
diff --git a/kfax/faxinput.cpp b/kfax/faxinput.cpp
new file mode 100644
index 00000000..8ca7fe85
--- /dev/null
+++ b/kfax/faxinput.cpp
@@ -0,0 +1,479 @@
+/* Fax file input processing
+ Copyright (C) 1990, 1995 Frank D. Cringle.
+
+This file is part of viewfax - g3/g4 fax processing software.
+
+viewfax is free software; you can redistribute it and/or modify it
+under the terms of the GNU General Public License as published by the
+Free Software Foundation; either version 2 of the License, or (at your
+option) any later version.
+
+This program is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <unistd.h>
+#include <errno.h>
+#include <string.h>
+#include <sys/stat.h>
+#include <sys/time.h>
+#include <fcntl.h>
+#include "faxexpand.h"
+#include <qstring.h>
+#include <qfile.h>
+#include <kapplication.h>
+#include <klocale.h>
+#include <kdebug.h>
+
+void statusbarupdate(char* name,int width,int height,char* res);
+extern void kfaxerror(const QString& title, const QString& error);
+
+#define FAXMAGIC "\000PC Research, Inc\000\000\000\000\000\000"
+
+/* Enter an argument in the linked list of pages */
+struct pagenode *
+notefile(const char *name, int type)
+{
+ struct pagenode *newnode = (struct pagenode *) xmalloc(sizeof *newnode);
+
+ *newnode = defaultpage;
+ if (firstpage == NULL){
+ firstpage = newnode;
+ auxpage = firstpage;
+ }
+ newnode->prev = lastpage;
+ newnode->next = NULL;
+ if (lastpage != NULL)
+ lastpage->next = newnode;
+ lastpage = newnode;
+
+ // kdDebug() << "Adding new node " << newnode << endl;
+
+ newnode->pathname = (char*) malloc (strlen(name) +1);
+ if(!newnode->pathname){
+ kfaxerror(i18n("Sorry"),i18n("Out of memory\n"));
+ exit(1);
+ }
+
+ strcpy(newnode->pathname,name);
+
+ newnode->type = type;
+
+
+ if ((newnode->name = strrchr(newnode->pathname, '/')) != NULL)
+ newnode->name++;
+ else
+ newnode->name = newnode->pathname;
+
+ if (newnode->width == 0)
+ newnode->width = 1728;
+ if (newnode->vres < 0)
+ newnode->vres = !(newnode->name[0] == 'f' && newnode->name[1] == 'n');
+ newnode->extra = NULL;
+
+ return newnode;
+}
+
+static t32bits
+get4(unsigned char *p, int endian)
+{
+ return endian ? (p[0]<<24)|(p[1]<<16)|(p[2]<<8)|p[3] :
+ p[0]|(p[1]<<8)|(p[2]<<16)|(p[3]<<24);
+}
+
+static int
+get2(unsigned char *p, int endian)
+{
+ return endian ? (p[0]<<8)|p[1] : p[0]|(p[1]<<8);
+}
+
+/* generate pagenodes for the images in a tiff file */
+int
+notetiff(const char *name)
+{
+
+ FILE *tf;
+ unsigned char header[8];
+ static const char littleTIFF[5] = "\x49\x49\x2a\x00";
+ static const char bigTIFF[5] = "\x4d\x4d\x00\x2a";
+ int endian;
+ t32bits IFDoff;
+ struct pagenode *pn = NULL;
+ QString str;
+
+
+ if ((tf = fopen(name, "r")) == NULL) {
+ QString mesg = i18n("Unable to open:\n%1\n").arg(QFile::decodeName(name));
+ kfaxerror(i18n("Sorry"), mesg);
+ return 0;
+ }
+
+ if (fread(header, 8, 1, tf) == 0) {
+ nottiff:
+ fclose(tf);
+ (void) notefile(name,FAX_RAW);
+ return 0;
+ }
+ if (memcmp(header, &littleTIFF, 4) == 0)
+ endian = 0;
+ else if (memcmp(header, &bigTIFF, 4) == 0)
+ endian = 1;
+ else
+ goto nottiff;
+ IFDoff = get4(header+4, endian);
+ if (IFDoff & 1)
+ goto nottiff;
+ do { /* for each page */
+ unsigned char buf[8];
+ unsigned char *dir = NULL , *dp = NULL;
+ int ndirent;
+ pixnum iwidth = defaultpage.width ? defaultpage.width : 1728;
+ pixnum iheight = defaultpage.height ? defaultpage.height : 2339;
+ int inverse = defaultpage.inverse;
+ int lsbfirst = 0;
+ int t4opt = 0, comp = 0;
+ int orient = defaultpage.orient;
+ double yres = defaultpage.vres ? 196.0 : 98.0;
+ struct strip *strips = NULL;
+ unsigned long rowsperstrip = 0;
+ t32bits nstrips = 1;
+
+ if (fseek(tf, IFDoff, SEEK_SET) < 0) {
+ realbad:
+ str = i18n("Invalid tiff file:\n%1\n").arg(QFile::decodeName(name));
+ kfaxerror(i18n("Sorry"),str);
+ bad:
+ if (strips)
+ free(strips);
+ if (dir)
+ free(dir);
+ fclose(tf);
+ return 1;
+ }
+ if (fread(buf, 2, 1, tf) == 0)
+ goto realbad;
+ ndirent = get2(buf, endian);
+ dir = (unsigned char *) xmalloc(12*ndirent+4);
+ if (fread(dir, 12*ndirent+4, 1, tf) == 0)
+ goto realbad;
+ for (dp = dir; ndirent; ndirent--, dp += 12) {
+ /* for each directory entry */
+ int tag, ftype;
+ t32bits count, value = 0;
+ tag = get2(dp, endian);
+ ftype = get2(dp+2, endian);
+ count = get4(dp+4, endian);
+ switch(ftype) { /* value is offset to list if count*size > 4 */
+ case 3: /* short */
+ value = get2(dp+8, endian);
+ break;
+ case 4: /* long */
+ value = get4(dp+8, endian);
+ break;
+ case 5: /* offset to rational */
+ value = get4(dp+8, endian);
+ break;
+ }
+ switch(tag) {
+ case 256: /* ImageWidth */
+ iwidth = value;
+ break;
+ case 257: /* ImageLength */
+ iheight = value;
+ break;
+ case 259: /* Compression */
+ comp = value;
+ break;
+ case 262: /* PhotometricInterpretation */
+ inverse ^= (value == 1);
+ break;
+ case 266: /* FillOrder */
+ lsbfirst = (value == 2);
+ break;
+ case 273: /* StripOffsets */
+ nstrips = count;
+ strips = (struct strip *) xmalloc(count * sizeof *strips);
+ if (count == 1 || (count == 2 && ftype == 3)) {
+ strips[0].offset = value;
+ if (count == 2)
+ strips[1].offset = get2(dp+10, endian);
+ break;
+ }
+ if (fseek(tf, value, SEEK_SET) < 0)
+ goto realbad;
+ for (count = 0; count < nstrips; count++) {
+ if (fread(buf, (ftype == 3) ? 2 : 4, 1, tf) == 0)
+ goto realbad;
+ strips[count].offset = (ftype == 3) ?
+ get2(buf, endian) : get4(buf, endian);
+ }
+ break;
+ case 274: /* Orientation */
+ switch(value) {
+ default: /* row0 at top, col0 at left */
+ orient = 0;
+ break;
+ case 2: /* row0 at top, col0 at right */
+ orient = TURN_M;
+ break;
+ case 3: /* row0 at bottom, col0 at right */
+ orient = TURN_U;
+ break;
+ case 4: /* row0 at bottom, col0 at left */
+ orient = TURN_U|TURN_M;
+ break;
+ case 5: /* row0 at left, col0 at top */
+ orient = TURN_M|TURN_L;
+ break;
+ case 6: /* row0 at right, col0 at top */
+ orient = TURN_U|TURN_L;
+ break;
+ case 7: /* row0 at right, col0 at bottom */
+ orient = TURN_U|TURN_M|TURN_L;
+ break;
+ case 8: /* row0 at left, col0 at bottom */
+ orient = TURN_L;
+ break;
+ }
+ break;
+ case 278: /* RowsPerStrip */
+ rowsperstrip = value;
+ break;
+ case 279: /* StripByteCounts */
+ if (count != nstrips) {
+ str = i18n("In file %1\nStripsPerImage tag 273=%2,tag279=%3\n")
+ .arg(QFile::decodeName(name)).arg(nstrips).arg(count);
+ kfaxerror(i18n("Message"),str);
+ goto realbad;
+ }
+ if (count == 1 || (count == 2 && ftype == 3)) {
+ strips[0].size = value;
+ if (count == 2)
+ strips[1].size = get2(dp+10, endian);
+ break;
+ }
+ if (fseek(tf, value, SEEK_SET) < 0)
+ goto realbad;
+ for (count = 0; count < nstrips; count++) {
+ if (fread(buf, (ftype == 3) ? 2 : 4, 1, tf) == 0)
+ goto realbad;
+ strips[count].size = (ftype == 3) ?
+ get2(buf, endian) : get4(buf, endian);
+ }
+ break;
+ case 283: /* YResolution */
+ if (fseek(tf, value, SEEK_SET) < 0 ||
+ fread(buf, 8, 1, tf) == 0)
+ goto realbad;
+ yres = get4(buf, endian) / get4(buf+4, endian);
+ break;
+ case 292: /* T4Options */
+ t4opt = value;
+ break;
+ case 293: /* T6Options */
+ /* later */
+ break;
+ case 296: /* ResolutionUnit */
+ if (value == 3)
+ yres *= 2.54;
+ break;
+ }
+ }
+ IFDoff = get4(dp, endian);
+ free(dir);
+ dir = NULL;
+ if (comp == 5) {
+ // compression type 5 is LZW compression
+ kfaxerror(i18n("Sorry"),i18n("Due to patent reasons KFax can not handle LZW (Lempel-Ziv & Welch) "
+ "compressed Fax files.\n"));
+ goto bad;
+ }
+ if (comp < 2 || comp > 4) {
+ kfaxerror(i18n("Sorry"),i18n("This version can only handle Fax files\n"));
+ goto bad;
+ }
+ pn = notefile(name,FAX_TIFF);
+ pn->nstrips = nstrips;
+ pn->rowsperstrip = nstrips > 1 ? rowsperstrip : iheight;
+ pn->strips = strips;
+ pn->width = iwidth;
+ pn->height = iheight;
+ pn->inverse = inverse;
+ pn->lsbfirst = lsbfirst;
+ pn->orient = orient;
+ pn->vres = (yres > 150); /* arbitrary threshold for fine resolution */
+ if (comp == 2)
+ pn->expander = MHexpand;
+ else if (comp == 3)
+ pn->expander = (t4opt & 1) ? g32expand : g31expand;
+ else
+ pn->expander = g4expand;
+ } while (IFDoff);
+ fclose(tf);
+ return 1;
+}
+
+/* report error and remove bad file from the list */
+static void
+badfile(struct pagenode *pn)
+{
+ struct pagenode *p;
+
+ if (errno)
+ perror(pn->pathname);
+ if (pn == firstpage) {
+ if (pn->next == NULL){
+ kfaxerror(i18n("Sorry"),i18n("Bad Fax File"));
+ return;
+ }
+ else{
+ firstpage = thispage = firstpage->next;
+ firstpage->prev = NULL;
+ }
+ }
+ else
+ for (p = firstpage; p; p = p->next)
+ if (p->next == pn) {
+ thispage = p;
+ p->next = pn->next;
+ if (pn->next)
+ pn->next->prev = p;
+ break;
+ }
+ if (pn) free(pn);
+ pn = NULL;
+}
+
+/* rearrange input bits into t16bits lsb-first chunks */
+static void
+normalize(struct pagenode *pn, int revbits, int swapbytes, size_t length)
+{
+ t32bits *p = (t32bits *) pn->data;
+
+ switch ((revbits<<1)|swapbytes) {
+ case 0:
+ break;
+ case 1:
+ for ( ; length; length -= 4) {
+ t32bits t = *p;
+ *p++ = ((t & 0xff00ff00) >> 8) | ((t & 0x00ff00ff) << 8);
+ }
+ break;
+ case 2:
+ for ( ; length; length -= 4) {
+ t32bits t = *p;
+ t = ((t & 0xf0f0f0f0) >> 4) | ((t & 0x0f0f0f0f) << 4);
+ t = ((t & 0xcccccccc) >> 2) | ((t & 0x33333333) << 2);
+ *p++ = ((t & 0xaaaaaaaa) >> 1) | ((t & 0x55555555) << 1);
+ }
+ break;
+ case 3:
+ for ( ; length; length -= 4) {
+ t32bits t = *p;
+ t = ((t & 0xff00ff00) >> 8) | ((t & 0x00ff00ff) << 8);
+ t = ((t & 0xf0f0f0f0) >> 4) | ((t & 0x0f0f0f0f) << 4);
+ t = ((t & 0xcccccccc) >> 2) | ((t & 0x33333333) << 2);
+ *p++ = ((t & 0xaaaaaaaa) >> 1) | ((t & 0x55555555) << 1);
+ }
+ }
+}
+
+
+/* get compressed data into memory */
+unsigned char *
+getstrip(struct pagenode *pn, int strip)
+{
+ int fd;
+ size_t offset, roundup;
+ struct stat sbuf;
+ unsigned char *Data;
+ union { t16bits s; unsigned char b[2]; } so;
+ QString str;
+
+#define ShortOrder so.b[1]
+
+ so.s = 1;
+ if ((fd = open(pn->pathname, O_RDONLY, 0)) < 0) {
+ badfile(pn);
+ return NULL;
+ }
+
+ if (pn->strips == NULL) {
+ if (fstat(fd, &sbuf) != 0) {
+ close(fd);
+ badfile(pn);
+ return NULL;
+ }
+ offset = 0;
+ pn->length = sbuf.st_size;
+ }
+ else if (strip < pn->nstrips) {
+ offset = pn->strips[strip].offset;
+ pn->length = pn->strips[strip].size;
+ }
+ else {
+ str = i18n("Trying to expand too many strips\n%1%n").arg(QFile::decodeName(pn->pathname));
+ kfaxerror(i18n("Warning"),str);
+ return NULL;
+ }
+
+ /* round size to full boundary plus t32bits */
+ roundup = (pn->length + 7) & ~3;
+
+ Data = (unsigned char *) xmalloc(roundup);
+ /* clear the last 2 t32bits, to force the expander to terminate
+ even if the file ends in the middle of a fax line */
+ *((t32bits *) Data + roundup/4 - 2) = 0;
+ *((t32bits *) Data + roundup/4 - 1) = 0;
+
+ /* we expect to get it in one gulp... */
+ if (lseek(fd, offset, SEEK_SET) < 0 ||
+ (uint) read(fd, Data, pn->length) != pn->length) {
+ badfile(pn);
+ free(Data);
+ close(fd);
+ return NULL;
+ }
+ close(fd);
+
+ pn->data = (t16bits *) Data;
+ if (pn->strips == NULL && memcmp(Data, FAXMAGIC, sizeof(FAXMAGIC)) == 0) {
+ /* handle ghostscript / PC Research fax file */
+ if (Data[24] != 1 || Data[25] != 0){
+ str = i18n("Only the first page of the PC Research multipage file\n%1\nwill be shown\n")
+ .arg(QFile::decodeName(pn->pathname));
+ kfaxerror(i18n("Message"),str);
+ }
+ pn->length -= 64;
+ pn->vres = Data[29];
+ pn->data += 32;
+ roundup -= 64;
+ }
+
+ normalize(pn, !pn->lsbfirst, ShortOrder, roundup);
+ if (pn->height == 0)
+ pn->height = G3count(pn, pn->expander == g32expand);
+ if (pn->height == 0) {
+
+ str = i18n("No fax found in file:\n%1\n").arg(QFile::decodeName(pn->pathname));
+ kfaxerror(i18n("Sorry"),str);
+ errno = 0;
+ badfile(pn);
+ free(Data);
+ return NULL;
+ }
+ if (pn->strips == NULL)
+ pn->rowsperstrip = pn->height;
+ if (verbose && strip == 0)
+ kdWarning() << pn->name << "\n\twidth = " << pn->width << "\n\theight = "
+ << pn->height << "\n\tresolution = " << (pn->vres ? "fine" : "normal") << endl;
+// statusbarupdate(pn->name,pn->width,pn->height,pn->vres ? "fine" : "normal");
+ return Data;
+}
diff --git a/kfax/hi16-app-kfax.png b/kfax/hi16-app-kfax.png
new file mode 100644
index 00000000..bb676f8b
--- /dev/null
+++ b/kfax/hi16-app-kfax.png
Binary files differ
diff --git a/kfax/hi22-app-kfax.png b/kfax/hi22-app-kfax.png
new file mode 100644
index 00000000..90fc64b0
--- /dev/null
+++ b/kfax/hi22-app-kfax.png
Binary files differ
diff --git a/kfax/hi32-app-kfax.png b/kfax/hi32-app-kfax.png
new file mode 100644
index 00000000..7330eb41
--- /dev/null
+++ b/kfax/hi32-app-kfax.png
Binary files differ
diff --git a/kfax/hi48-app-kfax.png b/kfax/hi48-app-kfax.png
new file mode 100644
index 00000000..3f58c369
--- /dev/null
+++ b/kfax/hi48-app-kfax.png
Binary files differ
diff --git a/kfax/hisc-app-kfax.svgz b/kfax/hisc-app-kfax.svgz
new file mode 100644
index 00000000..f46fd440
--- /dev/null
+++ b/kfax/hisc-app-kfax.svgz
Binary files differ
diff --git a/kfax/kfax.cpp b/kfax/kfax.cpp
new file mode 100644
index 00000000..02661325
--- /dev/null
+++ b/kfax/kfax.cpp
@@ -0,0 +1,1695 @@
+ /*
+
+ $Id$
+
+ Copyright (C) 1997 Bernd Johannes Wuebben
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+
+ */
+
+#ifdef KDE_USE_FINAL
+/* NewImage() in viewfax.cpp needs to fiddle with the Display structure */
+#define XLIB_ILLEGAL_ACCESS
+#endif
+
+#include <stdlib.h>
+#include <signal.h>
+#include <time.h>
+#include <unistd.h>
+
+#include <qfile.h>
+#include <qstrlist.h>
+#include <qtimer.h>
+#include <qpopupmenu.h>
+#include <qpainter.h>
+#include <qpaintdevicemetrics.h>
+#include <qbitmap.h>
+
+#include <klocale.h>
+#include <kaboutdata.h>
+#include <kstandarddirs.h>
+#include <kiconloader.h>
+#include <kfiledialog.h>
+#include <kfilemetainfo.h>
+#include <kstdaccel.h>
+#include <kconfig.h>
+#include <kmenubar.h>
+#include <kmessagebox.h>
+#include <kcmdlineargs.h>
+#include <kio/netaccess.h>
+#include <knotifyclient.h>
+#include <ktempfile.h>
+#include <kstdaction.h>
+#include <kdebug.h>
+#include <kurldrag.h>
+#include <kstatusbar.h>
+#include <kaction.h>
+#include <kprocess.h>
+#include <kprinter.h>
+#include <kio/job.h>
+#include <kdebug.h>
+
+#include "faxexpand.h"
+#include "kfax.h"
+#include "version.h"
+#include "viewfax.h"
+#include "options.h"
+#include "kfax_printsettings.h"
+
+#include <X11/X.h>
+#include <X11/Xlib.h>
+#include <X11/Xutil.h>
+#include <X11/Xatom.h>
+#include <X11/keysym.h>
+#include <X11/keysymdef.h>
+#include <X11/cursorfont.h>
+
+// StatusBar field IDs
+#define ID_LINE_COLUMN 1
+#define ID_INS_OVR 2
+#define ID_GENERAL 3
+#define ID_FNAME 4
+#define ID_TYPE 5
+#define ID_PAGE_NO 6
+
+
+TopLevel *toplevel;
+
+extern int GetImage(struct pagenode *pn);
+
+void TurnFollowing(int How, struct pagenode *pn);
+void handle_X_event(XEvent event);
+void ShowLoop(void);
+void SetupDisplay();
+void mysighandler(int sig);
+void setFaxDefaults();
+
+void parse(char* buf, char** args);
+
+extern void g31expand(struct pagenode *pn, drawfunc df);
+extern void g32expand(struct pagenode *pn, drawfunc df);
+extern void g4expand(struct pagenode *pn, drawfunc df);
+
+#define PATIENCE 100000
+
+static char KFAX_FILETYPES[] = "image/fax-g3 image/tiff";
+
+int ExpectConfNotify = 1;
+
+GC PaintGC;
+Cursor WorkCursor;
+Cursor ReadyCursor;
+Cursor MoveCursor;
+Cursor LRCursor;
+Cursor UDCursor;
+
+extern Time Lasttime;
+extern bool have_cmd_opt;
+extern struct pagenode *viewpage;
+
+extern XImage *FlipImage(XImage *xi);
+extern XImage *MirrorImage(XImage *xi);
+extern XImage *RotImage(XImage *Image);
+extern XImage *ZoomImage(XImage *Big);
+extern void FreeImage(XImage *Image);
+
+extern XImage *Image, *Images[MAXZOOM];
+
+int xpos, ox; /* x, old x, offset x, new xpos*/
+int ypos, oy; /* y, old y, offset y, new y */
+int offx, offy;
+int nx, ny;
+
+int oz, Resize, Refresh; /* old zoom, window size changed,
+ needs updating */
+int PaneWidth, PaneHeight; /* current size of our window */
+int AbsX, AbsY; /* absolute position of centre of window */
+
+Display* qtdisplay;
+
+int startingup;
+Window qtwin; // the qt window
+Window Win;
+int qwindow_height;
+int qwindow_width;
+bool have_no_fax = TRUE;
+bool display_is_setup = FALSE;
+struct optionsinfo fop; // contains the fax options
+
+extern struct pagenode *firstpage, *lastpage, *thispage;
+extern struct pagenode* auxpage;
+
+extern struct pagenode defaultpage;
+
+bool buttondown;
+
+bool MyApp::x11EventFilter( XEvent * ev)
+{
+ if (KApplication::x11EventFilter(ev))
+ return TRUE;
+
+ if (ev->type == ButtonRelease){
+ /* this is so that the cursor goes back to normal on leaving the fax window
+ and that the fax won't be moved when I reenter after I release the mouse*/
+
+ if (buttondown == true){
+ buttondown = false;
+ XDefineCursor(qtdisplay, Win, ReadyCursor);
+ XFlush(qtdisplay);
+ }
+ }
+ if ( ev->xany.window == qtwin ||
+ ev->xany.window == Win){
+
+ if(startingup || have_no_fax)
+ return FALSE;
+
+ toplevel->handle_X_event(*ev);
+ ev->xany.window = qtwin;
+
+ }
+
+ return FALSE;
+
+}
+
+TopLevel::TopLevel (QWidget *, const char *name)
+ : KMainWindow (0, name)
+{
+ setMinimumSize (100, 100);
+
+ buttondown = false;
+
+ setupMenuBar();
+ setupStatusBar();
+ updateActions();
+
+ resize(550,400);
+ setupGUI();
+
+ readSettings();
+
+ faxqtwin = new QFrame(this);
+
+ qtwin = faxqtwin->winId();
+ faxqtwin->setFrameStyle(QFrame::Panel | QFrame::Sunken);
+
+ // Create a Vertical scroll bar
+
+ vsb = new QScrollBar( QScrollBar::Vertical,faxqtwin,"scrollBar" );
+ vsb->hide();
+ connect( vsb, SIGNAL(valueChanged(int)), SLOT(scrollVert(int)) );
+
+ // Create a Horizontal scroll bar
+
+ hsb = new QScrollBar( QScrollBar::Horizontal,faxqtwin,"scrollBar" );
+ connect( hsb, SIGNAL(valueChanged(int)), SLOT(scrollHorz(int)) );
+ hsb->hide();
+
+ setCentralWidget(faxqtwin);
+
+ setAcceptDrops(true);
+
+ show();
+}
+
+
+TopLevel::~TopLevel()
+{
+}
+
+void TopLevel::setupMenuBar()
+{
+ // File menu
+ KStdAction::open( this, SLOT( faxOpen() ), actionCollection() );
+ actRecent = KStdAction::openRecent( this, SLOT( faxOpen( const KURL & ) ),
+ actionCollection() );
+ actSave = KStdAction::save( this, SLOT( faxSave() ), actionCollection() );
+ actSaveAs = KStdAction::saveAs( this, SLOT( faxSaveAs() ),
+ actionCollection() );
+ actPrint = KStdAction::print( this, SLOT( print() ), actionCollection() );
+ KStdAction::quit( this, SLOT( close() ), actionCollection() );
+ actAdd = new KAction( i18n( "A&dd..." ), "filenew", KShortcut(), this,
+ SLOT( faxAdd() ), actionCollection(), "file_add_fax" );
+
+ actRecent->setMaxItems( 5 );
+
+ // View Menu
+ actSize = KStdAction::actualSize( this, SLOT( actualSize() ),
+ actionCollection() );
+ actZoomIn = KStdAction::zoomIn( this, SLOT( zoomin() ), actionCollection() );
+ actZoomOut = KStdAction::zoomOut( this, SLOT( zoomout() ),
+ actionCollection() );
+
+ actRotate = new KAction( i18n( "&Rotate Page" ), "rotate", KShortcut(), this,
+ SLOT( rotatePage() ), actionCollection(), "view_rotate" );
+ actMirror = new KAction( i18n( "Mirror Page" ), KShortcut(), this,
+ SLOT( mirrorPage() ), actionCollection(), "view_mirror" );
+ actFlip = new KAction( i18n( "&Flip Page" ), KShortcut(), this,
+ SLOT( flipPage() ), actionCollection(), "view_flip" );
+
+ // Go menu
+ actNext = KStdAction::next( this, SLOT( nextPage() ), actionCollection() );
+ actPrev = KStdAction::prior( this, SLOT( prevPage() ), actionCollection() );
+ actFirst = KStdAction::firstPage( this, SLOT( firstPage() ),
+ actionCollection() );
+ actLast = KStdAction::lastPage( this, SLOT( lastPage() ),
+ actionCollection() );
+
+ // Settings menu
+ KStdAction::preferences( this, SLOT( faxoptions() ), actionCollection() );
+}
+
+void TopLevel::setupStatusBar()
+{
+ statusbar = statusBar();
+
+ statusbar->insertFixedItem(i18n("w: 00000 h: 00000"), ID_INS_OVR);
+ statusbar->insertFixedItem(i18n("Res: XXXXX"), ID_GENERAL);
+ statusbar->insertFixedItem(i18n("Type: XXXXXXX"), ID_TYPE);
+ statusbar->insertFixedItem(i18n("Page: XX of XX"), ID_PAGE_NO);
+ statusbar->insertItem(QString::null, ID_FNAME, 1);
+ statusbar->setItemAlignment( ID_FNAME, AlignLeft );
+
+ statusbar->changeItem(QString::null, ID_INS_OVR);
+ statusbar->changeItem(QString::null, ID_GENERAL);
+ statusbar->changeItem(QString::null, ID_TYPE);
+ statusbar->changeItem(QString::null, ID_PAGE_NO);
+ statusbar->changeItem(QString::null, ID_FNAME);
+}
+
+void TopLevel::readSettings()
+{
+ config = kapp->config();
+
+ applyMainWindowSettings( config, "MainWindowSettings" );
+
+ actRecent->loadEntries( config );
+
+ config->setGroup("General Options");
+
+ config->setGroup("Fax Options");
+
+ fop.width = config->readNumEntry("width", 1728);
+ fop.resauto = config->readNumEntry("resauto", 1);
+ fop.geomauto = config->readNumEntry("geomauto", 1);
+ fop.height = config->readNumEntry("height", 2339);
+ fop.fine = config->readNumEntry("resolution", 1);
+ fop.flip = config->readNumEntry("flip", 0);
+ fop.invert = config->readNumEntry("invert", 0);
+ fop.lsbfirst = config->readNumEntry("lsb", 0);
+ fop.raw = config->readNumEntry("raw", 3);
+
+ setFaxDefaults();
+}
+
+void TopLevel::updateActions()
+{
+ actAdd->setEnabled( thispage );
+ actSave->setEnabled( thispage );
+ actSaveAs->setEnabled( thispage );
+ actPrint->setEnabled( thispage );
+
+ actRotate->setEnabled( thispage );
+ actFlip->setEnabled( thispage );
+ actMirror->setEnabled( thispage );
+
+ updateGoActions();
+ updateZoomActions();
+}
+
+void TopLevel::updateGoActions()
+{
+ actNext->setEnabled( thispage && thispage->next );
+ actPrev->setEnabled( thispage && thispage->prev );
+ actFirst->setEnabled( thispage && thispage->prev );
+ actLast->setEnabled( thispage && thispage->next );
+}
+
+void TopLevel::updateZoomActions()
+{
+ actSize->setEnabled( Image && oz > 0 );
+ actZoomIn->setEnabled( Image && oz > 0 );
+ actZoomOut->setEnabled( Image && oz < MAXZOOM-1 && Image->width >= 256 );
+}
+
+bool TopLevel::queryClose()
+{
+ saveMainWindowSettings( config, "MainWindowSettings" );
+ actRecent->saveEntries( config );
+
+ return true;
+}
+
+void TopLevel::writeSettings()
+{
+ config = kapp->config();
+
+ config->setGroup("General Options");
+
+ config->setGroup("Fax Options");
+
+ config->writeEntry("resauto",fop.resauto);
+ config->writeEntry("geomauto",fop.geomauto);
+ config->writeEntry("width",fop.width);
+ config->writeEntry("height",fop.height);
+ config->writeEntry("resolution",fop.fine);
+ config->writeEntry("flip",fop.flip);
+ config->writeEntry("invert",fop.invert);
+ config->writeEntry("lsb",fop.lsbfirst);
+ config->writeEntry("raw",fop.raw);
+
+ config->sync();
+}
+
+void TopLevel::faxOpen()
+{
+ KURL url = KFileDialog::getOpenURL(QString::null, KFAX_FILETYPES);
+
+ faxOpen( url );
+
+ actRecent->addURL( fileURL );
+}
+
+void TopLevel::faxOpen( const KURL & url )
+{
+ if (!url.isValid())
+ return;
+
+ faxClose();
+ faxAdd( url );
+
+ fileURL = url;
+
+ updateActions();
+}
+
+void TopLevel::faxAdd()
+{
+ KURL url = KFileDialog::getOpenURL(QString::null, KFAX_FILETYPES);
+
+ faxAdd( url );
+
+ actRecent->addURL( fileURL );
+}
+
+void TopLevel::faxAdd( const KURL & url )
+{
+ if (!url.isValid())
+ return;
+
+ openNetFile(url);
+
+ updateGoActions();
+}
+
+void TopLevel::faxSave()
+{
+ saveNetFile(fileURL);
+}
+
+void TopLevel::faxSaveAs()
+{
+ fileURL = KFileDialog::getSaveURL(QString::null, KFAX_FILETYPES);
+
+ if (fileURL.isEmpty())
+ return;
+
+ faxSave();
+
+ actRecent->addURL( fileURL );
+}
+
+
+static void freeImages()
+{
+ int i;
+ for (i = 1; i < MAXZOOM; i++) {
+ if (Images[i])
+ FreeImage(Images[i]);
+ Images[i] = NULL;
+ }
+}
+
+static XImage *generateZoomImages(int maxzoom)
+{
+ int i;
+ for (i = 1; i < MAXZOOM; i++){
+ if (!Images[i-1])
+ continue;
+ Image = Images[i] = ZoomImage(Images[i-1]);
+ if(Image == NULL){// out of memory
+ Image = Images[i -1];
+ break;
+ }
+ }
+
+ i = maxzoom;
+ while (!Images[i])
+ i--;
+ return Images[i];
+}
+
+
+void TopLevel::zoom( int factor )
+{
+ if(!thispage || !Image || !faxqtwin || !display_is_setup)
+ return;
+
+ Resize = Refresh = 1;
+
+ Image = generateZoomImages(factor);
+
+ PaneWidth = Image->width;
+ PaneHeight = Image->height;
+
+ resizeView();
+ putImage();
+
+ uiUpdate();
+
+ updateZoomActions();
+}
+
+void TopLevel::zoomin()
+{
+ if ( oz > 0 )
+ {
+ oz--;
+ zoom( oz );
+ }
+}
+
+void TopLevel::zoomout()
+{
+ if (oz < MAXZOOM && Image->width >= 256)
+ {
+ ++oz;
+ zoom( oz );
+ }
+}
+
+void TopLevel::actualSize()
+{
+ oz = 0;
+ zoom( oz );
+}
+
+void loadfile(QString filename)
+{
+ // Typical FAX resolutions are:
+ // Standard: 203 dpi x 98 dpi
+ // Fine: 203 dpi x 196 lpi
+ // Super Fine: 203 dpi y 392 lpi, or
+ // 406 dpi x 392 lpi
+ QSize dpi(203,196);
+
+ KFileMetaInfo metaInfo(filename);
+ if (metaInfo.isValid() && metaInfo.item("Resolution").isValid())
+ {
+ QSize s = metaInfo.item("Resolution").value().toSize();
+ if (s.width() >= 100 && s.height() >= 100)
+ dpi = s;
+ }
+
+ (void) notetiff(QFile::encodeName(filename));
+
+ struct pagenode *pn;
+ for(pn = firstpage; pn; pn = pn->next)
+ if (!pn->dpiX) {
+ pn->dpiX = dpi.width();
+ pn->dpiY = dpi.height();
+ }
+}
+
+void TopLevel::openadd(QString filename)
+{
+ auxpage = lastpage;
+
+ loadfile(filename);
+
+ if( firstpage != lastpage )
+ {
+ if(auxpage->next)
+ auxpage = auxpage->next;
+ }
+
+ // auxpage should now point to the first pagenode which was created for
+ // the newly added fax file.
+ have_no_fax = false;
+ thispage = auxpage;
+ newPage();
+ resizeView();
+ putImage();
+}
+
+void TopLevel::resizeEvent(QResizeEvent *e)
+{
+ KMainWindow::resizeEvent(e);
+
+ resizeView();
+}
+
+void TopLevel::wheelEvent( QWheelEvent *e )
+{
+ e->accept();
+
+ if ( e->state() & ShiftButton )
+ {
+ if ( e->delta() < 0 )
+ zoomin();
+ else
+ zoomout();
+ }
+ else
+ {
+ int offset = QApplication::wheelScrollLines()*vsb->lineStep();
+ if ( e->state() & ControlButton )
+ offset = vsb->pageStep();
+ offset = -e->delta()*offset/120;
+ vsb->setValue( vsb->value() + offset );
+ }
+}
+
+void TopLevel::resizeView()
+{
+ if(!faxqtwin || !display_is_setup)
+ return;
+
+//printf("In resizeView() entered\n");
+
+ qwindow_width = faxqtwin->width();
+ qwindow_height = faxqtwin->height();
+
+ if( hsb->isVisible())
+ qwindow_height -= 16;
+
+ if( vsb->isVisible())
+ qwindow_width -= 16;
+
+ if(Image){
+ PaneWidth = Image->width;
+ PaneHeight = Image->height;
+ }
+
+ // printf("faxw %d qtw %d\n", PaneWidth , faxqtwin->width());
+
+ if( (PaneHeight > qwindow_height ) &&
+ (PaneWidth > qwindow_width)){
+
+ vsb->setGeometry(faxqtwin->width() - 16,0,16,faxqtwin->height()-16);
+ hsb->setGeometry(0,faxqtwin->height() - 16 ,faxqtwin->width()-16,16);
+
+ qwindow_width = faxqtwin->width() -16;
+ qwindow_height = faxqtwin->height()-16;
+
+
+ vsb->raise();
+ vsb->show();
+ hsb->show();
+ }
+ else{
+
+ if( PaneHeight > qwindow_height){
+ vsb->setGeometry(faxqtwin->width() - 16,0,16,faxqtwin->height());
+
+
+ qwindow_width = faxqtwin->width() -16 ;
+ qwindow_height = faxqtwin->height();
+
+
+ vsb->show();
+ hsb->hide();
+ hsb->raise();
+ }
+ else
+ vsb->hide();
+
+ if( PaneWidth > qwindow_width ){
+ hsb->setGeometry(0,faxqtwin->height() - 16 ,faxqtwin->width(),16);
+ hsb->show();
+ hsb->raise();
+ vsb->hide();
+ qwindow_width = faxqtwin->width() ;
+ qwindow_height = faxqtwin->height() -16;
+
+ }
+ else
+ hsb->hide();
+
+ }
+
+ if(Image){
+ hsb->setRange(0,QMAX(0,Image->width - qwindow_width));
+ hsb->setSteps(5,qwindow_width/2);
+ // printf("hsb range: %d\n",QMAX(0,Image->width - qwindow_width));
+ vsb->setRange(0,QMAX(0,Image->height - qwindow_height));
+ vsb->setSteps(5,qwindow_height/2);
+ // printf("vsb range: %d\n",QMAX(0,Image->height - qwindow_height));
+ // printf("vsb QMIN %d vdb QMAX %d\n",vsb->QMINValue(),vsb->QMAXValue());
+ }
+
+
+ Resize = 1;
+ uiUpdate();
+
+}
+
+bool TopLevel::loadAllPages( int &numpages, int &currentpage )
+{
+ struct pagenode *pn;
+
+ numpages = 0;
+ currentpage = 1;
+
+ for(pn = firstpage; pn; pn = pn->next) {
+ ++numpages;
+ if (pn == thispage)
+ currentpage = numpages;
+ if (!Pimage(pn)) {
+ int k = -1;
+ while((k != 0) && (k != 3) && (k != 1))
+ k = GetImage(pn); // fetch image if it is not available yet.
+ }
+ }
+ return (numpages != 0);
+}
+
+void TopLevel::print(){
+ if(!thispage || !firstpage) {
+ return KMessageBox::sorry(this, i18n("There is no document active."));
+ }
+
+ int pages, currentpage;
+ loadAllPages(pages, currentpage);
+
+ KPrinter printer(true, QPrinter::HighResolution);
+ printer.setFullPage( true );
+ printer.setUsePrinterResolution( true );
+ printer.setCreator( i18n("KFax") + " " KFAXVERSION );
+ printer.setDocName( QString("%1 - %2").arg(firstpage->name).arg(i18n("KFax")));
+ printer.setDocFileName( firstpage->name );
+ printer.setPageSelection( KPrinter::ApplicationSide );
+ printer.setMinMax( 1, pages );
+ printer.setCurrentPage( currentpage );
+ printer.addDialogPage(new KFAXPrintSettings());
+ if ( !printer.setup( this ) )
+ return;
+
+ QPainter painter;
+ painter.begin( &printer );
+ printIt(printer, painter);
+ painter.end();
+}
+
+
+void TopLevel::printIt( KPrinter &printer, QPainter &painter )
+{
+ QPaintDeviceMetrics dm(painter.device());
+
+ QApplication::setOverrideCursor( waitCursor );
+ kapp->processEvents();
+
+ const bool fullpage = printer.option(APP_KFAX_SCALE_FULLPAGE) == "true";
+ const bool center_h = printer.option(APP_KFAX_CENTER_HORZ) == "true";
+ const bool center_v = printer.option(APP_KFAX_CENTER_VERT) == "true";
+
+ int currentpage = 0;
+ bool first_page_printed = false;
+ struct pagenode *pn;
+ for(pn = firstpage; pn; pn = pn->next) {
+
+ ++currentpage;
+ // should this page be printed ?
+ if (printer.pageList().findIndex(currentpage) < 0)
+ continue;
+
+ XImage *Image = Pimage(pn);
+ if (!Image)
+ continue;
+
+ // byte-swapping the image
+ QByteArray bytes( Image->height*Image->bytes_per_line );
+ for (int y=Image->height-1; y>=0; --y) {
+ Q_UINT32 offset = y*Image->bytes_per_line;
+ Q_UINT32 *source = (Q_UINT32 *) (Image->data + offset);
+ Q_UINT32 *dest = (Q_UINT32 *) (bytes.data() + offset);
+ for (int x=(Image->bytes_per_line/4)-1; x>=0; --x) {
+ Q_UINT32 dv = 0, sv = *source;
+ for (int bit=32; bit>0; --bit) {
+ dv <<= 1;
+ dv |= sv&1;
+ sv >>= 1;
+ }
+ *dest = dv;
+ ++dest;
+ ++source;
+ }
+ }
+
+ QImage image( (uchar *)bytes.data(), Image->bytes_per_line*8, Image->height, 1, NULL, 2, QImage::LittleEndian);
+
+ if (first_page_printed)
+ printer.newPage();
+ first_page_printed = true;
+
+ const QSize printersize( dm.width(), dm.height() );
+ kdDebug() << "Printersize = " << printersize << endl;
+ // print Image in original size if possible, else scale it.
+
+ const QSize size( // logical size of the image
+ Image->width * dm.logicalDpiX() / pn->dpiX,
+ Image->height * dm.logicalDpiY() / pn->dpiY
+ );
+
+ kdDebug() << "Org image size = " << Image->width << "x" << Image->height
+ << " logical picture res = " << pn->dpiX << "x" << pn->dpiY << endl;
+ kdDebug() << "New image size = " << size
+ << " logical printer res = " << dm.logicalDpiX() << "x" << dm.logicalDpiY() << endl;
+
+ uint top, left, bottom, right;
+ if (fullpage)
+ top = left = bottom = right = 0;
+ else
+ printer.margins( &top, &left, &bottom, &right );
+ kdDebug() << "Margins = " << top << " " << left << " " << bottom << " " << right << endl;
+
+ const QSize maxSize( printersize.width()-left-right, printersize.height()-top-bottom );
+ QSize scaledImageSize = size;
+ if (size.width() > maxSize.width() || size.height() > maxSize.height() ) {
+ // Image does not fit - scale it and print centered
+ scaledImageSize.scale( maxSize, QSize::ScaleMin );
+ kdDebug() << "Image does not fit - scaling to " << maxSize << endl;
+ } else {
+ // Image does fit - print it in original size, but centered
+ scaledImageSize.scale( size, QSize::ScaleMin );
+ kdDebug() << "Image does fit - scaling to " << size << endl;
+ }
+ kdDebug() << "Final image size " << scaledImageSize << endl;
+ int x,y;
+ if (center_h)
+ x = (maxSize.width()-scaledImageSize.width())/2 + left;
+ else
+ x = left;
+ if (center_v)
+ y = (maxSize.height()-scaledImageSize.height())/2 + top;
+ else
+ y = top;
+ painter.drawImage( QRect(x,y,scaledImageSize.width(), scaledImageSize.height()), image );
+
+ }
+
+ QApplication::restoreOverrideCursor();
+}
+
+void TopLevel::saveNetFile( const KURL& dest)
+{
+ if ( !dest.isValid() )
+ {
+ KMessageBox::sorry(this, i18n("Malformed URL"));
+ return;
+ }
+
+ statusbar->message( i18n( "Saving..." ) );
+
+ KURL source = KURL::fromPathOrURL(thispage->pathname);
+ bool ok = KIO::NetAccess::file_copy( source, dest, -1, true, false, this);
+
+ statusbar->clear();
+
+ if (!ok)
+ KMessageBox::error(this, i18n("Failure in 'copy file()'\n"
+ "Could not save file!"));
+}
+
+void TopLevel::openNetFile( const KURL &u)
+{
+ if ( !u.isValid() )
+ {
+ KMessageBox::error(this, i18n("Malformed URL"));
+ return;
+ }
+
+ if ( u.isLocalFile() )
+ {
+ QString string = i18n("Loading '%1'").arg(u.path());
+ statusbar->message(string);
+ openadd( u.path());
+ statusbar->clear();
+ }
+ else
+ {
+ statusbar->message(i18n("Downloading..."));
+ QString tmpFile = QString::null;
+ if ( KIO::NetAccess::download( u, tmpFile, this ) )
+ {
+ openadd( tmpFile );
+ setCaption( u.prettyURL() );
+ }
+ statusbar->clear();
+ KIO::NetAccess::removeTempFile( tmpFile );
+ }
+}
+
+void TopLevel::dragEnterEvent( QDragEnterEvent * event)
+{
+ event->accept(KURLDrag::canDecode(event));
+}
+
+void TopLevel::dropEvent( QDropEvent * event)
+{
+
+ KURL::List list;
+
+ if (KURLDrag::decode(event, list) && !list.isEmpty())
+ {
+ // Load the first file in this window
+ const KURL &url = list.first();
+ openNetFile( url );
+ }
+}
+
+void SetupDisplay(){
+
+ if(display_is_setup){
+ return;
+ }
+
+ display_is_setup = TRUE;
+
+ xpos = ypos = ox = oy = 0;
+ ExpectConfNotify = 1;
+
+ /* XSizeHints size_hints;*/
+
+ Win = XCreateSimpleWindow(qtdisplay,qtwin,1,1,
+ 1,1,
+ 0,
+ BlackPixel(qtdisplay,XDefaultScreen(qtdisplay)),
+ WhitePixel(qtdisplay,XDefaultScreen(qtdisplay)));
+
+ PaintGC = XCreateGC(qtdisplay, Win, 0L, (XGCValues *) NULL);
+ XSetForeground(qtdisplay, PaintGC, BlackPixel(qtdisplay, XDefaultScreen(qtdisplay) ));
+ XSetBackground(qtdisplay, PaintGC, WhitePixel(qtdisplay, XDefaultScreen(qtdisplay) ));
+ XSetFunction(qtdisplay, PaintGC, GXcopy);
+ WorkCursor = XCreateFontCursor(qtdisplay, XC_watch);
+ //ReadyCursor = XCreateFontCursor(qtdisplay, XC_plus);
+ ReadyCursor = XCreateFontCursor(qtdisplay, XC_hand2);
+ MoveCursor = XCreateFontCursor(qtdisplay, XC_fleur);
+ LRCursor = XCreateFontCursor(qtdisplay, XC_sb_h_double_arrow);
+ UDCursor = XCreateFontCursor(qtdisplay, XC_sb_v_double_arrow);
+
+ XSelectInput(qtdisplay, Win, Button2MotionMask | ButtonPressMask |
+ ButtonReleaseMask | ExposureMask | KeyPressMask |
+ SubstructureNotifyMask | LeaveWindowMask | OwnerGrabButtonMask |
+ StructureNotifyMask);
+
+ XMapRaised(qtdisplay, Win);
+
+ XDefineCursor(qtdisplay, Win, ReadyCursor);
+ XFlush(qtdisplay);
+
+ memset(Images, 0, sizeof(Images));
+
+ // Start at half the Size
+ oz = 1;
+}
+
+void TopLevel::handle_X_event(XEvent Event)
+{
+ if(!thispage || !Image || !faxqtwin || !display_is_setup)
+ return;
+
+ bool putimage = false; // Do we actually have to write the image to the scree?
+
+ do {
+ switch(Event.type) {
+ case MappingNotify:
+ XRefreshKeyboardMapping((XMappingEvent *)(&Event));
+ break;
+
+ case LeaveNotify:
+ /* buttondown = false;
+ XDefineCursor(qtdisplay, Win, ReadyCursor);
+ XFlush(qtdisplay);*/
+ break;
+ case Expose:
+ {
+
+ if(Event.xexpose.count != 0)
+ break;
+
+ if(!Image)
+ break;
+
+ putimage = TRUE;
+ }
+ break;
+
+ case KeyPress:
+ if (ExpectConfNotify &&
+ (Event.xkey.time < (Lasttime + PATIENCE)))
+ break;
+ Lasttime = Event.xkey.time;
+ ExpectConfNotify = 0;
+ switch(XKeycodeToKeysym(qtdisplay, Event.xkey.keycode, 0)) {
+ case XK_m:
+ mirrorPage();
+ if (Event.xkey.state & ShiftMask)
+ TurnFollowing(TURN_M, thispage->next);
+ break;
+ case XK_o:
+ zoomout();
+ break;
+
+ case XK_i:
+ zoomin();
+ break;
+
+ case XK_Up:
+ ypos-= qwindow_height / 3;
+ putimage = TRUE;
+ break;
+ case XK_Down:
+ ypos+= qwindow_height / 3;
+ putimage = TRUE;
+ break;
+ case XK_Left:
+ xpos-= qwindow_width / 4;
+ putimage = TRUE;
+ break;
+ case XK_Right:
+ xpos+= qwindow_width / 4;
+ putimage = TRUE;
+ break;
+ case XK_Home:
+ case XK_R7:
+ if (Event.xkey.state & ShiftMask) {
+ thispage = firstpage;
+ newPage();
+ resizeView();
+ putImage();
+ break;
+ }
+ xpos= 0;
+ ypos= 0;
+ putImage();
+ break;
+ case XK_End:
+ case XK_R13:
+ if (Event.xkey.state & ShiftMask) {
+ thispage = lastpage;
+ newPage();
+ resizeView();
+ putImage();
+ break;
+ }
+ xpos= Image->width;
+ ypos= Image->height;
+ putImage();
+ break;
+ case XK_l:
+ case XK_r:
+ rotatePage();
+ if (Event.xkey.state & ShiftMask)
+ TurnFollowing(TURN_L, thispage->next);
+ break;
+ case XK_p:
+ case XK_minus:
+ case XK_Prior:
+ case XK_R9:
+ case XK_BackSpace:
+ prevPage();
+ break;
+ case XK_n:
+ case XK_plus:
+ case XK_space:
+ case XK_Next:
+ case XK_R15:
+ nextPage();
+ break;
+ case XK_u:
+ flipPage();
+ if (Event.xkey.state & ShiftMask)
+ TurnFollowing(TURN_U, thispage->next);
+ break;
+
+ case XK_q:
+ if (viewpage) {
+ thispage = viewpage;
+ viewpage = NULL;
+ newPage();
+ resizeView();
+ putImage();
+ }
+
+ }
+
+ break;
+
+ case ButtonPress:
+
+ if (ExpectConfNotify && (Event.xbutton.time < (Lasttime + PATIENCE)))
+ break;
+
+ Lasttime = Event.xbutton.time;
+ ExpectConfNotify = 0;
+
+
+ switch (Event.xbutton.button) {
+
+ case Button1:
+ buttondown = true;
+
+ switch (((Image->width > qwindow_width)<<1) |
+ (Image->height > qwindow_height)) {
+ case 0:
+ break;
+ case 1:
+ XDefineCursor(qtdisplay, Win, UDCursor);
+ break;
+ case 2:
+ XDefineCursor(qtdisplay, Win, LRCursor);
+ break;
+ case 3:
+ XDefineCursor(qtdisplay, Win, MoveCursor);
+ }
+
+ XFlush(qtdisplay);
+ offx = Event.xbutton.x;
+ offy = Event.xbutton.y;
+ break;
+
+ }
+
+ break;
+
+ case MotionNotify:
+ if(!buttondown)
+ break;
+ do {
+
+ nx = Event.xmotion.x;
+ ny = Event.xmotion.y;
+
+
+ } while (XCheckTypedEvent(qtdisplay, MotionNotify, &Event));
+
+
+ xpos+= offx - nx;
+ ypos+= offy - ny;
+
+ offx = nx;
+ offy = ny;
+
+ putimage = TRUE;
+
+ break;
+
+ case ButtonRelease:
+
+ if (Event.xbutton.button == Button1) {
+
+ buttondown = false;
+ XDefineCursor(qtdisplay, Win, ReadyCursor);
+ XFlush(qtdisplay);
+ }
+
+ }
+
+ } while (XCheckWindowEvent(qtdisplay, Win, KeyPressMask|ButtonPressMask, &Event));
+
+ if(putimage == TRUE) {
+ Refresh = Resize = 1;
+ putImage();
+ }
+}
+
+void TopLevel::rotatePage()
+{
+ if(!thispage || !Image || !faxqtwin || !display_is_setup)
+ return;
+
+ XDefineCursor(qtdisplay, Win, WorkCursor);
+ XFlush(qtdisplay);
+
+ XImage *newrotimage = RotImage(Images[0]);
+
+ XDefineCursor(qtdisplay, Win, ReadyCursor);
+
+ if(newrotimage == NULL){ // out of memory
+ return;
+ }
+
+ thispage->extra = Images[0] = newrotimage;
+ thispage->orient ^= TURN_L;
+
+ freeImages();
+ Image = generateZoomImages(oz);
+
+ { int t = xpos ; xpos= ypos; ypos= t; }
+
+ Refresh = Resize = 1;
+
+ putImage();
+}
+
+void TopLevel::flipPage()
+{
+ if(!thispage || !Image || !faxqtwin || !display_is_setup)
+ return;
+
+ XDefineCursor(qtdisplay, Win, WorkCursor);
+ XFlush(qtdisplay);
+
+ XImage *newflipimage = FlipImage(Images[0]);
+
+ XDefineCursor(qtdisplay, Win, ReadyCursor);
+
+ if(newflipimage == NULL){ // out of memory
+ return;
+ }
+
+ thispage->extra = Images[0] = newflipimage;
+ thispage->orient ^= TURN_U;
+
+ freeImages();
+ Image = generateZoomImages(oz);
+
+ Refresh = Resize = 1;
+ putImage();
+}
+
+void TopLevel::mirrorPage()
+{
+ if(!thispage || !Image || !faxqtwin || !display_is_setup)
+ return;
+
+ XDefineCursor(qtdisplay, Win, WorkCursor);
+ XFlush(qtdisplay);
+
+ XImage *newmirror = MirrorImage(Images[0]);
+
+ XDefineCursor(qtdisplay, Win, ReadyCursor);
+
+ if(newmirror == NULL){ // out of memory
+ return;
+ }
+ thispage->extra = Images[0] = newmirror;
+ thispage->orient ^= TURN_M;
+
+ freeImages();
+ Image = generateZoomImages(oz);
+
+ Refresh = Resize = 1;
+ putImage();
+}
+
+void TopLevel::scrollHorz(int){
+
+ if(!Image)
+ return;
+
+ // printf("hsb value: %d\n",hsb->value());
+ xpos= hsb->value() + qwindow_width/2;
+
+ Refresh = 1;
+ putImage();
+}
+
+void TopLevel::scrollVert(int ){
+
+ if(!Image)
+ return;
+
+ // printf("vsb value: %d\n",vsb->value());
+ ypos= vsb->value() + qwindow_height/2;
+
+ Refresh = 1;
+ putImage();
+}
+
+void TopLevel::lastPage()
+{
+ if(!thispage)
+ return;
+
+ if ( thispage->next )
+ {
+ while(thispage->next != NULL)
+ thispage = thispage->next;
+
+ newPage();
+ resizeView();
+ putImage();
+ }
+
+ updateGoActions();
+}
+
+void TopLevel::firstPage()
+{
+ if(!thispage)
+ return;
+
+ if ( thispage->prev )
+ {
+ while(thispage->prev != NULL)
+ thispage = thispage->prev;
+
+ newPage();
+ resizeView();
+ putImage();
+ }
+
+ updateGoActions();
+}
+
+void TopLevel::nextPage()
+{
+ if(!thispage)
+ return;
+
+ if (thispage->next)
+ {
+ thispage = thispage->next;
+
+ newPage();
+ resizeView();
+ putImage();
+ }
+
+ updateGoActions();
+}
+
+void TopLevel::prevPage()
+{
+ if(!thispage)
+ return;
+
+ if (thispage->prev)
+ {
+ thispage = thispage->prev;
+
+ newPage();
+ resizeView();
+ putImage();
+ }
+
+ updateGoActions();
+}
+
+void TopLevel::newPage(){
+
+ if(!display_is_setup)
+ SetupDisplay();
+
+ XDefineCursor(qtdisplay, Win, WorkCursor);
+ XFlush(qtdisplay);
+
+ freeImages();
+
+ int k = -1;
+
+ if(!thispage) {
+ XDefineCursor(qtdisplay, Win, ReadyCursor);
+ return;
+ }
+
+ if (Pimage(thispage) == NULL){
+
+ while((k != 0) && (k != 3) && (k !=1))
+ k = GetImage(thispage);
+
+ }
+
+ if (k == 3 ){
+
+ XDefineCursor(qtdisplay, Win, ReadyCursor);
+ FreeFax();
+ /* KMessageBox::sorry(i18n("Bad fax file k=3"));*/
+ return;
+ }
+
+ if (k == 0 ){
+
+ XDefineCursor(qtdisplay, Win, ReadyCursor);
+ FreeFax();
+ /* KMessageBox::sorry(i18n("Bad fax file k=0"));*/
+ return;
+ }
+
+ Image = Images[0] = Pimage(thispage);
+
+ setCaption(QFile::decodeName(thispage->name));
+
+ Image = generateZoomImages(oz);
+
+ PaneWidth = Image->width;
+ PaneHeight = Image->height;
+ Refresh = 1;
+
+ XDefineCursor(qtdisplay, Win, ReadyCursor);
+ uiUpdate();
+
+}
+
+
+void TopLevel::faxClose()
+{
+ FreeFax();
+
+ setCaption(i18n("KFax"));
+ // TODO replace this with unmapping the window.
+ if(display_is_setup)
+ XResizeWindow(qtdisplay,Win,1,1); // we want a clear gray background.
+
+ resizeView();
+ vsb->hide();
+ hsb->hide();
+
+ fileURL = QString::null;
+
+ updateActions();
+}
+
+void TopLevel::FreeFax()
+{
+ if(display_is_setup)
+ XClearWindow(qtdisplay, Win);
+
+ freeImages();
+
+ pagenode *pn;
+ for (pn = firstpage; pn; pn = pn->next){
+ if(Pimage(pn)){
+ FreeImage(Pimage(pn));
+ pn->extra = NULL;
+ }
+ }
+
+ Image = NULL;
+
+ for (pn = firstpage; pn; pn = pn->next){
+ if(pn->pathname){
+ free(pn->pathname);
+ }
+ }
+
+
+ if(firstpage){
+ for(pn = firstpage->next; pn; pn = pn->next){
+ if(pn->prev){
+ free(pn->prev);
+ }
+ }
+ }
+
+ if(lastpage)
+ free(lastpage);
+
+ firstpage = lastpage = viewpage = thispage = auxpage = NULL;
+
+ uiUpdate();
+}
+
+void TopLevel::uiUpdate(){
+
+ if(thispage){
+
+ struct pagenode *pn ;
+ int pages = 0;
+ int currentpage = 0;
+
+ for(pn = firstpage; pn ; pn = pn->next){
+ pages ++;
+ if (thispage == pn)
+ currentpage = pages;
+ }
+
+ QString pagestr = i18n("Page: %1 of %2").arg(currentpage).arg(pages);
+
+ statusbar->changeItem(pagestr, ID_PAGE_NO);
+
+ if(Image){
+ QString wh = i18n("W: %1 H: %2").arg(Image->width).arg(Image->height);
+ statusbar->changeItem(wh, ID_INS_OVR);
+ }
+
+ QString resolution = i18n("Res: %1").arg(thispage->vres?i18n("Fine"):i18n("Normal"));
+ // TODO: resolution += QString("%1x%2").arg(thispage->dpiX).arg(thispage->dpiY);
+ statusbar->changeItem(resolution, ID_GENERAL);
+
+ statusbar->changeItem(thispage->name, ID_FNAME);
+
+ QString typestring;
+
+ if(thispage->type == FAX_TIFF){
+ typestring = i18n("Type: Tiff ");
+ }
+ else if ( thispage->type == FAX_RAW){
+ typestring = i18n("Type: Raw ");
+ }
+
+ if ( thispage->expander == g31expand )
+ typestring += "G3";
+
+ if ( thispage->expander == g32expand )
+ typestring += "G3 2D";
+
+ if ( thispage->expander == g4expand )
+ typestring += "G4";
+
+ statusbar->changeItem(typestring,ID_TYPE);
+ updateActions();
+ }
+}
+
+void kfaxerror(const QString& title, const QString& error){
+ KMessageBox::error(toplevel, error, title);
+}
+
+void TopLevel::putImage()
+{
+
+ // TODO do I really need to set Refresh or Resize to 1 , is there
+ // really still someonce calling this with out haveing set Refresh or Resize to 1?
+
+ if ( !Image || !display_is_setup || !thispage )
+ return;
+
+ if ( qwindow_width > Image->width){
+ xpos= Image->width/2;
+ }
+ else{
+ if(xpos< qwindow_width/2){
+ xpos = qwindow_width/2;
+ }
+ else{
+ if(xpos> Image->width - qwindow_width/2){
+ xpos= Image->width - qwindow_width/2;
+ }
+
+ }
+ }
+
+ if ( qwindow_height > Image->height){
+ ypos= Image->height/2;
+ }
+ else{
+ if(ypos< qwindow_height/2){
+ ypos = qwindow_height/2;
+ }
+ else{
+ if(ypos> Image->height - qwindow_height/2){
+ ypos= Image->height - qwindow_height/2;
+ }
+
+ }
+ }
+
+ if (xpos!= ox || ypos!= oy || Refresh || Resize){
+
+ /* In the following we use qwindow_height -1 etc since the main view
+ has a sunken frame and I need to offset by 1 pixel to the right and
+ one pixel down so that I don't paint my fax into the border of the frame*/
+
+ XResizeWindow(qtdisplay,Win,QMIN(qwindow_width -1,Image->width ),
+ QMIN(qwindow_height -1,Image->height ));
+
+ XPutImage(qtdisplay, Win, PaintGC, Image,
+ QMAX(xpos - qwindow_width/2,0), QMAX(ypos - qwindow_height/2,0),
+ 0, 0, QMIN(qwindow_width -1,Image->width) ,
+ QMIN(qwindow_height -1,Image->height) );
+
+ vsb->setValue(QMAX(ypos - qwindow_height/2,0));
+ hsb->setValue(QMAX(xpos - qwindow_width/2,0));
+
+ XFlush(qtdisplay);
+ }
+
+ ox = xpos;
+ oy = ypos;
+
+ Resize = Refresh = 0;
+
+}
+
+void TopLevel::faxoptions(){
+
+ OptionsDialog * opd = new OptionsDialog(this, "options");
+ opd->setWidgets(&fop);
+
+ if(opd->exec()){
+
+ struct optionsinfo *newops;
+ newops = opd->getInfo();
+
+ fop.resauto = newops->resauto;
+ fop.geomauto = newops->geomauto;
+ fop.width = newops->width;
+ fop.height = newops->height;
+ fop.fine = newops->fine;
+ fop.landscape= newops->landscape;
+ fop.flip = newops->flip;
+ fop.invert = newops->invert;
+ fop.lsbfirst = newops->lsbfirst;
+ fop.raw = newops->raw;
+
+ setFaxDefaults();
+
+ writeSettings();
+ }
+
+ delete opd;
+}
+
+void setFaxDefaults(){
+
+ // fop is called in readSettings, so this can't be
+ // called after a TopLevel::readSettings()
+
+ if(have_cmd_opt ) // we have commad line options all kfaxrc defaults are
+ return; // overridden
+
+ if(fop.resauto == 1)
+ defaultpage.vres = -1;
+ else
+ defaultpage.vres = fop.fine;
+
+ if(fop.geomauto == 1){
+ defaultpage.width = defaultpage.height = 0;
+ }
+ else{
+ defaultpage.width = fop.width;
+ defaultpage.height = fop.height;
+ }
+
+ if(fop.landscape)
+ defaultpage.orient |= TURN_L;
+
+ if(fop.flip)
+ defaultpage.orient |= TURN_U;
+
+ defaultpage.inverse = fop.invert;
+ defaultpage.lsbfirst = fop.lsbfirst;
+
+ switch (fop.raw) {
+ case 2: defaultpage.expander = g32expand;
+ break;
+ case 4: defaultpage.expander = g4expand;
+ break;
+ default:defaultpage.expander = g31expand;
+ }
+
+}
+
+static const char description[] =
+ I18N_NOOP("KDE G3/G4 Fax Viewer");
+
+static KCmdLineOptions options[] =
+{
+ {"f", 0, 0 },
+ {"fine", I18N_NOOP( "Fine resolution" ), 0 },
+ {"n", 0, 0 },
+ {"normal", I18N_NOOP( "Normal resolution" ), 0 },
+ {"height", I18N_NOOP( "Height (number of fax lines)" ), 0 },
+ {"w", 0, 0 },
+ {"width", I18N_NOOP( "Width (dots per fax line)" ), 0 },
+ {"l", 0, 0 },
+ {"landscape", I18N_NOOP( "Turn image 90 degrees (landscape mode)" ), 0 },
+ {"u", 0, 0 },
+ {"upsidedown", I18N_NOOP( "Turn image upside down" ), 0 },
+ {"i", 0, 0 },
+ {"invert", I18N_NOOP( "Invert black and white" ), 0 },
+ {"m", 0, 0 },
+ {"mem <bytes>", I18N_NOOP( "Limit memory use to 'bytes'" ), "8M" },
+ {"r", 0, 0 },
+ {"reverse", I18N_NOOP( "Fax data is packed lsb first" ), 0 },
+ {"2" , I18N_NOOP( "Raw files are g3-2d" ), 0 },
+ {"4", I18N_NOOP( "Raw files are g4" ), 0 },
+ {"+file(s)", I18N_NOOP( "Fax file(s) to show" ), 0 },
+ KCmdLineLastOption
+};
+
+int main (int argc, char **argv)
+{
+ KAboutData aboutData( "kfax", I18N_NOOP("KFax"),
+ KFAXVERSION, description, KAboutData::License_GPL,
+ "(c) 1997-98 Bernd Johannes Wuebben");
+ aboutData.addAuthor( "Bernd Johannes Wuebben", 0, "[email protected]" );
+ aboutData.addCredit( "Nadeem Hasan", I18N_NOOP( "UI Rewrite, lots of code "
+ "cleanups and fixes" ), "[email protected]" );
+ aboutData.addCredit( "Helge Deller", I18N_NOOP( "Printing Rewrite, lots of code "
+ "cleanups and fixes"), "[email protected]" );
+
+ KCmdLineArgs::init(argc, argv, &aboutData);
+ KCmdLineArgs::addCmdLineOptions( options );
+
+ MyApp a;
+
+ qtdisplay = qt_xdisplay();
+
+ viewfaxmain();
+
+ toplevel = new TopLevel();
+ toplevel->show();
+
+ startingup = 1;
+ a.processEvents();
+ a.flushX();
+
+ startingup = 0;
+
+ faxinit();
+ if(!have_no_fax){
+
+ thispage = firstpage;
+
+ toplevel->newPage();
+ toplevel->resizeView();
+ //TODO : I don't think I need this putImage();
+ toplevel->putImage();
+ }
+
+ toplevel->uiUpdate();
+
+ return a.exec ();
+}
+
+
+#include "kfax.moc"
diff --git a/kfax/kfax.desktop b/kfax/kfax.desktop
new file mode 100644
index 00000000..eefd8b87
--- /dev/null
+++ b/kfax/kfax.desktop
@@ -0,0 +1,86 @@
+[Desktop Entry]
+MimeType=image/fax-g3;image/tiff;
+GenericName=Fax Viewer
+GenericName[af]=Faks Aansig
+GenericName[ar]=عارض الفاكس
+GenericName[bg]=Преглед на факсове
+GenericName[br]=Gweler faks
+GenericName[bs]=Preglednik faxova
+GenericName[ca]=Visualitzador de fax
+GenericName[cs]=Prohlížeč faxů
+GenericName[cy]=Gwelydd Ffacs
+GenericName[da]=Fax-fremviser
+GenericName[de]=Faxbetrachter
+GenericName[el]=Προβολέας φαξ
+GenericName[eo]=Faksrigardilo
+GenericName[es]=Visor de faxes
+GenericName[et]=Fakside vaataja
+GenericName[eu]=Fax ikustailua
+GenericName[fa]=مشاهده‌گر دورنگار
+GenericName[fi]=Faksinäytin
+GenericName[fr]=Afficheur de fax
+GenericName[gl]=Visor de fax
+GenericName[he]=מציג פקסים
+GenericName[hi]=फ़ैक्स प्रदर्शक
+GenericName[hr]=Preglednik faksova
+GenericName[hu]=Faxnézegető
+GenericName[is]=Fax sjá
+GenericName[it]=Visore di fax
+GenericName[ja]=ファクスビューア
+GenericName[kk]=Факсты қарау
+GenericName[km]=កម្មវិធី​មើល​ទូរសារ
+GenericName[lt]=Faksų žiūriklis
+GenericName[lv]=Faksu Skatītājs
+GenericName[ms]=Pemapar Faks
+GenericName[nb]=Faksfremviser
+GenericName[nds]=Faxkieker
+GenericName[ne]=फ्याक्स द्रष्टा
+GenericName[nl]=Faxweergaveprogramma
+GenericName[nn]=Faksvisar
+GenericName[pa]=ਫੈਕਸ ਦਰਸ਼ਕ
+GenericName[pl]=Przeglądarka faksów
+GenericName[pt]=Visualizador de Faxes
+GenericName[pt_BR]=Visualizador de Faxes
+GenericName[ro]=Vizualizor FAX
+GenericName[ru]=Просмотр факсов
+GenericName[se]=Fáksačájeheaddji
+GenericName[sk]=Prehliadač faxov
+GenericName[sl]=Pregledovalnik faksov
+GenericName[sr]=Приказивач факсова
+GenericName[sr@Latn]=Prikazivač faksova
+GenericName[sv]=Faxvisare
+GenericName[ta]=ஃபாக்ஸ் காட்சி
+GenericName[tg]=Хондани факс
+GenericName[th]=เครื่องมือแสดงโทรสารของ KDE
+GenericName[tr]=Faks Görüntüleyici
+GenericName[uk]=Переглядач факсів
+GenericName[uz]=Faks koʻruvchi
+GenericName[uz@cyrillic]=Факс кўрувчи
+GenericName[ven]=Muvhoni wa Fekisi
+GenericName[wa]=Håyneu di facs
+GenericName[xh]=Umboniseli Wefax
+GenericName[zh_CN]=传真查看器
+GenericName[zh_HK]=傳真檢視器
+GenericName[zh_TW]=傳真檢視器
+GenericName[zu]=Umbonisi wefax
+Name=KFax
+Name[af]=K-faks
+Name[ar]=برنامج KFax
+Name[cy]=KFfacs
+Name[eo]=Faksrigardilo
+Name[hi]=के-फ़ैक्स
+Name[lv]=KFakss
+Name[ne]=केडीई फ्याक्स
+Name[sv]=Kfax
+Name[ta]=கேஃபாக்ஸ்
+Name[ven]=Fekisi ya K
+Name[wa]=KFacs
+Name[zh_TW]=KFax 傳真檢視器
+Exec=kfax %f -caption "%c" %i %m
+Icon=kfax
+Path=
+Type=Application
+Terminal=false
+X-KDE-StartupNotify=true
+X-DCOP-ServiceType=Multi
+Categories=Qt;KDE;Graphics;X-KDE-More;
diff --git a/kfax/kfax.h b/kfax/kfax.h
new file mode 100644
index 00000000..506a1452
--- /dev/null
+++ b/kfax/kfax.h
@@ -0,0 +1,159 @@
+ /*
+
+ $Id$
+
+ Requires the Qt widget libraries, available at no cost at
+ http://www.troll.no
+
+ Copyright (C) 1997 Bernd Johannes Wuebben
+
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+
+ */
+
+#ifndef _KFAX_H_
+#define _KFAX_H_
+
+#include <kapplication.h>
+#include <kmainwindow.h>
+#include <qptrlist.h>
+#include <kurl.h>
+
+#define Pimage(p) ((XImage *)(p)->extra)
+
+class QPopupMenu;
+class KConfig;
+class KStatusBar;
+class KAction;
+class KRecentFilesAction;
+class KPrinter;
+class QPainter;
+class QScrollBar;
+
+typedef KToolBar::BarPosition BarPosition;
+
+class MyApp:public KApplication {
+public:
+ virtual bool x11EventFilter( XEvent * );
+};
+
+class TopLevel : public KMainWindow
+{
+ Q_OBJECT
+
+
+public:
+
+ TopLevel( QWidget *parent=0, const char *name=0 );
+ ~TopLevel();
+
+ void openNetFile( const KURL& _url);
+ void saveNetFile( const KURL& _url );
+
+ static QPtrList<TopLevel> windowList;
+ QPopupMenu *right_mouse_button, *colors;
+
+ void handle_X_event(XEvent Event);
+ void putImage();
+
+protected:
+
+ void resizeEvent( QResizeEvent * );
+ void wheelEvent( QWheelEvent * );
+ void dragEnterEvent( QDragEnterEvent * event );
+ void dropEvent( QDropEvent * event );
+
+ void updateActions();
+ void updateGoActions();
+ void updateZoomActions();
+
+ void zoom( int );
+
+ void readSettings();
+ void writeSettings();
+ void setupActions();
+ void setupMenuBar();
+ void setupToolBar();
+ void setupEditWidget();
+ void setupStatusBar();
+
+ bool queryClose();
+
+private:
+
+ QFrame *faxqtwin;
+
+ int indentID;
+ QColor forecolor;
+ QColor backcolor;
+
+ KURL fileURL;
+ KStatusBar *statusbar;
+
+ KRecentFilesAction *actRecent;
+ KAction *actAdd, *actSave, *actSaveAs, *actPrint;
+ KAction *actSize, *actZoomIn, *actZoomOut, *actRotate, *actMirror;
+ KAction *actFlip, *actNext, *actPrev, *actFirst, *actLast;
+
+ int open_mode;
+
+ KConfig *config;
+
+ QScrollBar *hsb;
+ QScrollBar *vsb;
+ QFrame* mainpane;
+
+ void printIt( KPrinter &printer, QPainter &painter );
+ bool loadAllPages( int &numpages, int &currentpage );
+
+public slots:
+
+ void faxOpen( const KURL & );
+ void faxOpen();
+ void faxAdd();
+ void faxAdd( const KURL & );
+ void faxClose();
+ void print();
+ void zoomin();
+ void zoomout();
+ void actualSize();
+ void resizeView();
+ void faxSave();
+ void faxSaveAs();
+
+ void faxoptions();
+ void rotatePage();
+ void mirrorPage();
+ void flipPage();
+ void nextPage();
+ void prevPage();
+ void newPage();
+ void firstPage();
+ void lastPage();
+ void uiUpdate();
+
+ void openadd(QString filename);
+ void FreeFax();
+ void scrollHorz(int);
+ void scrollVert(int);
+};
+
+void kfaxerror(const QString&, const QString&);
+void loadfile(QString filename);
+
+#endif // _KFAX_H_
+
diff --git a/kfax/kfax.tif b/kfax/kfax.tif
new file mode 100644
index 00000000..85eec6bb
--- /dev/null
+++ b/kfax/kfax.tif
Binary files differ
diff --git a/kfax/kfax_printsettings.cpp b/kfax/kfax_printsettings.cpp
new file mode 100644
index 00000000..02aa4050
--- /dev/null
+++ b/kfax/kfax_printsettings.cpp
@@ -0,0 +1,98 @@
+/*
+ * This file is part of the KDE libraries
+ * Copyright (c) 2005 Helge Deller <[email protected]>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License version 2 as published by the Free Software Foundation.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public License
+ * along with this library; see the file COPYING.LIB. If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ **/
+
+#include "kfax_printsettings.h"
+
+#include <klocale.h>
+#include <qcheckbox.h>
+#include <qlayout.h>
+#include <qwhatsthis.h>
+
+KFAXPrintSettings::KFAXPrintSettings(QWidget *parent, const char *name)
+: KPrintDialogPage(parent, name)
+{
+ QString whatsThisScaleFullPage = i18n( "<qt>"
+ "<p><strong>'Ignore Paper Margins'</strong></p>"
+ "<p>"
+ "If this checkbox is enabled, the paper margins will be ignored "
+ "and the fax will be printed on the full paper size."
+ "</p>"
+ "<p>"
+ "If this checkbox is disabled, KFax will respect the standard paper "
+ "margins and print the fax inside this printable area."
+ "</p>"
+ " </qt>" );
+ QString whatsThisCenterHorz = i18n( "<qt>"
+ "<p><strong>'Horizontal centered'</strong></p>"
+ "<p>"
+ "If this checkbox is enabled, the fax will be centered horizontally "
+ "on the page."
+ "</p>"
+ "<p>"
+ "If this checkbox is disabled, the fax will be printed at the left "
+ "side of the page."
+ "</p>"
+ " </qt>" );
+ QString whatsThisCenterVert = i18n( "<qt>"
+ "<p><strong>'Vertical centered'</strong></p>"
+ "<p>"
+ "If this checkbox is enabled, the fax will be centered vertically "
+ "on the page."
+ "</p>"
+ "<p>"
+ "If this checkbox is disabled, the fax will be printed at the top "
+ "of the page."
+ "</p>"
+ " </qt>" );
+
+ setTitle(i18n("&Layout"));
+
+ m_scaleFullPage = new QCheckBox(i18n("Ignore paper margins"), this);
+ QWhatsThis::add(m_scaleFullPage, whatsThisScaleFullPage);
+ m_center_horz = new QCheckBox(i18n("Horizontal centered"), this);
+ QWhatsThis::add(m_center_horz, whatsThisCenterHorz);
+ m_center_vert = new QCheckBox(i18n("Vertical centered"), this);
+ QWhatsThis::add(m_center_vert, whatsThisCenterVert);
+
+ QVBoxLayout *l0 = new QVBoxLayout(this, 0, 10);
+ l0->addWidget(m_scaleFullPage);
+ l0->addWidget(m_center_horz);
+ l0->addWidget(m_center_vert);
+ l0->addStretch(1);
+}
+
+KFAXPrintSettings::~KFAXPrintSettings()
+{
+}
+
+void KFAXPrintSettings::getOptions(QMap<QString,QString>& opts, bool /*incldef*/)
+{
+ opts[APP_KFAX_SCALE_FULLPAGE] = (m_scaleFullPage->isChecked() ? "true" : "false");
+ opts[APP_KFAX_CENTER_HORZ] = (m_center_horz->isChecked() ? "true" : "false");
+ opts[APP_KFAX_CENTER_VERT] = (m_center_vert->isChecked() ? "true" : "false");
+}
+
+void KFAXPrintSettings::setOptions(const QMap<QString,QString>& opts)
+{
+ m_scaleFullPage->setChecked(opts[APP_KFAX_SCALE_FULLPAGE] == "true");
+ m_center_horz->setChecked(opts[APP_KFAX_CENTER_HORZ] != "false");
+ m_center_vert->setChecked(opts[APP_KFAX_CENTER_VERT] == "true");
+}
+
+#include "kfax_printsettings.moc"
diff --git a/kfax/kfax_printsettings.h b/kfax/kfax_printsettings.h
new file mode 100644
index 00000000..e43e3530
--- /dev/null
+++ b/kfax/kfax_printsettings.h
@@ -0,0 +1,47 @@
+/*
+ * This file is part of the KDE libraries
+ * Copyright (c) 2005 Helge Deller <[email protected]>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License version 2 as published by the Free Software Foundation.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public License
+ * along with this library; see the file COPYING.LIB. If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ **/
+
+#ifndef KFAX_PRINTSETTINGS_H
+#define KFAX_PRINTSETTINGS_H
+
+#include <kdeprint/kprintdialogpage.h>
+
+class QCheckBox;
+
+#define APP_KFAX_SCALE_FULLPAGE "app-kfax-scalefullpage"
+#define APP_KFAX_CENTER_HORZ "app-kfax-center-horz"
+#define APP_KFAX_CENTER_VERT "app-kfax-center-vert"
+
+class KFAXPrintSettings : public KPrintDialogPage
+{
+ Q_OBJECT
+public:
+ KFAXPrintSettings(QWidget *parent = 0, const char *name = 0);
+ ~KFAXPrintSettings();
+
+ void getOptions(QMap<QString,QString>& opts, bool incldef = false);
+ void setOptions(const QMap<QString,QString>& opts);
+
+private:
+ QCheckBox *m_scaleFullPage;
+ QCheckBox *m_center_horz;
+ QCheckBox *m_center_vert;
+};
+
+#endif
diff --git a/kfax/kfaxlogo.xpm b/kfax/kfaxlogo.xpm
new file mode 100644
index 00000000..8adb7087
--- /dev/null
+++ b/kfax/kfaxlogo.xpm
@@ -0,0 +1,134 @@
+/* XPM */
+static char *magick[] = {
+/* columns rows colors chars-per-pixel */
+"90 120 8 1",
+" c #ffffff",
+". c #595959",
+"X c #808080",
+"o c #c0c0c0",
+"O c #000000",
+"+ c #dfdfdf",
+"@ c #303030",
+"# c #a0a0a4",
+/* pixels */
+" ",
+" ",
+" ",
+" ",
+" ",
+" ",
+" ",
+" ",
+" ",
+" ",
+" ",
+" ",
+" ",
+" ",
+" ",
+" ",
+" ",
+" ",
+" ",
+" ",
+" ",
+" ",
+" ",
+" ",
+" ",
+" ",
+" ",
+" ",
+" ",
+" ",
+" ",
+" ",
+" ",
+" ",
+" ",
+" ",
+" ",
+" ",
+" ",
+" ",
+" ",
+" ",
+" ",
+" .....X ...... o....o ",
+" OOOOO. oOOOOOX +@OOOOOO@+ ",
+" OOOOO. .OOOO@ +@OOOOOOOO@+ ",
+" OOOOO. XOOOOO# @OOOOOOOOOO# ",
+" OOOOO. @OOOO@ #OOOOOOOOO@+ ",
+" OOOOO. XOOOOOo .OOOOO.@O. o...X+ o..... ..... ",
+" OOOOO.+@OOOO. OOOOO. o #.OOOOOO. #OOOOO OOOOO ",
+" OOOOO..OOOOO+ OOOOO. #OOOOOOOOO@+ #OOOOO OOOOO ",
+" OOOOO@OOOOO. OOOOO. +OOOOOOOOOOO. #OOOOO OOOOO ",
+" OOOOO@OOOOO# [email protected] @OOOOOOOOOOOOo OOOOO++OOOOO ",
+" OOOOO.@OOOO. OOOOOOO# OOOOOO..OOOOO. .OOOO@@OOOO. ",
+" OOOOO.#OOOOOo OOOOOOO# #OOOOO# @OOOOO +.OOOOOOOO@+ ",
+" OOOOO. OOOOO@ OOOOOOO# #OOOO. #OOOOO .OOOOOOOO. ",
+" OOOOO. .OOOOOo OOOOOOO# oOOOO@ #OOOOO .OOOO@@OOOO. ",
+" OOOOO. +OOOOO@ OOOOO.#+ OOOOO@###OOOOO OOOOO++OOOO@ ",
+" OOOOO. @OOOOOo OOOOO. .OOOOOOO#OOOOO oOOOOO OOOOO ",
+" OOOOO. #OOOOO@ OOOOO. +@OOOOOO#OOOOO #OOOOO OOOOO ",
+" OOOOO. @OOOOOoOOOOO. o@OOOOO#OOOOO #OOOOO OOOOO ",
+" OOOOO. .OOOOO.OOOOO. +@OOOO#OOOOO #OOOOO OOOOO ",
+" #####o +####o######o o#.. ##### +##### ##### ",
+" ",
+" ",
+" ",
+" ",
+" ",
+" ",
+" ",
+" ",
+" ",
+" ",
+" ",
+" ",
+" ",
+" ",
+" ",
+" ",
+" ",
+" ",
+" ",
+" ",
+" ",
+" ",
+" ",
+" ",
+" ",
+" ",
+" ",
+" ",
+" ",
+" ",
+" ",
+" ",
+" ",
+" ",
+" ",
+" ",
+" ",
+" ",
+" ",
+" ",
+" ",
+" ",
+" ",
+" ",
+" ",
+" ",
+" ",
+" ",
+" ",
+" ",
+" ",
+" ",
+" ",
+" ",
+" ",
+" ",
+" "
+};
diff --git a/kfax/kfaxui.rc b/kfax/kfaxui.rc
new file mode 100644
index 00000000..35daf9f3
--- /dev/null
+++ b/kfax/kfaxui.rc
@@ -0,0 +1,28 @@
+<!DOCTYPE kpartgui>
+<kpartgui version="2" name="kfax">
+<MenuBar>
+ <Menu name="file"><text>&amp;File</text>
+ <Action name="file_add_fax" append="open_merge"/>
+ </Menu>
+ <Menu name="view"><text>&amp;View</text>
+ <Action name="view_rotate"/>
+ <Action name="view_mirror"/>
+ <Action name="view_flip"/>
+ </Menu>
+</MenuBar>
+ <ToolBar noMerge="1" name="mainToolBar" >
+ <text>Main Toolbar</text>
+ <Action name="file_open" />
+ <Action name="file_save" />
+ <Action name="file_print" />
+ <Separator name="separator_2" />
+ <Action name="go_previous" />
+ <Action name="go_next" />
+ <Separator name="separator_1" />
+ <Action name="go_first" />
+ <Action name="go_last" />
+ <Separator name="separator_0" />
+ <Action name="view_zoom_in" />
+ <Action name="view_zoom_out" />
+ </ToolBar>
+</kpartgui>
diff --git a/kfax/options.cpp b/kfax/options.cpp
new file mode 100644
index 00000000..b8bf8067
--- /dev/null
+++ b/kfax/options.cpp
@@ -0,0 +1,374 @@
+/*
+ $Id$
+
+ Requires the Qt widget libraries, available at no cost at
+ http://www.troll.no
+
+ Copyright (C) 1996 Bernd Johannes Wuebben
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+
+
+
+*/
+
+#include <stdio.h>
+
+#include <qlayout.h>
+#include <klocale.h>
+#include <knuminput.h>
+#include <qdir.h>
+#include <qprinter.h>
+#include <qframe.h>
+#include <qbuttongroup.h>
+#include <qcheckbox.h>
+#include <qcombobox.h>
+#include <qgroupbox.h>
+#include <qlabel.h>
+#include <qlineedit.h>
+#include <qlistbox.h>
+#include <qpushbutton.h>
+#include <qradiobutton.h>
+#include <qscrollbar.h>
+#include <qtooltip.h>
+
+#include "kfax.h"
+#include "options.h"
+
+OptionsDialog::OptionsDialog( QWidget *parent, const char *name)
+ : KDialogBase( parent, name, true, i18n("Configure"), Ok|Cancel)
+{
+ QWidget *mainWidget = new QWidget(this);
+ setMainWidget(mainWidget);
+
+ QVBoxLayout *mainLayout = new QVBoxLayout(mainWidget, 0, spacingHint());
+
+ bg = new QGroupBox(mainWidget,"bg");
+ bg->setColumnLayout( 0, Qt::Horizontal );
+ mainLayout->addWidget( bg );
+
+ QVBoxLayout *vbl = new QVBoxLayout(bg->layout());
+
+ QHBoxLayout *hbl1 = new QHBoxLayout();
+
+ vbl->addLayout( hbl1 );
+
+ displaylabel = new QLabel(i18n("Display options:"), bg,"displaylabel");
+ displaylabel->setFixedSize( displaylabel->sizeHint() );
+ hbl1->addWidget( displaylabel );
+
+ landscape = new QCheckBox(i18n("Landscape"), bg,"Landscape");
+ landscape->setFixedSize( landscape->sizeHint() );
+ hbl1->addSpacing( 10 );
+ hbl1->addWidget( landscape );
+
+ flip = new QCheckBox(i18n("Upside down"), bg,"upsidedown");
+ flip->setFixedSize( flip->sizeHint() );
+ hbl1->addSpacing( 10 );
+ hbl1->addWidget( flip );
+
+ invert = new QCheckBox(i18n("Invert"), bg,"invert");
+ invert->setFixedSize( invert->sizeHint() );
+ hbl1->addSpacing( 10 );
+ hbl1->addWidget( invert );
+
+ vbl->addSpacing( 20 );
+
+ QHBoxLayout *hbl8 = new QHBoxLayout();
+ vbl->addLayout( hbl8 );
+ hbl8->addSpacing( 10 );
+
+ resgroup = new QButtonGroup(bg,"resgroup");
+ resgroup->setFrameStyle(QFrame::NoFrame);
+ hbl8->addWidget( resgroup );
+
+ QHBoxLayout *hbl2 = new QHBoxLayout(resgroup);
+
+ reslabel = new QLabel(i18n("Raw fax resolution:"),resgroup,"relabel");
+ hbl2->addWidget( reslabel );
+
+ resauto = new QRadioButton(i18n("Auto"),resgroup,"resauto");
+ hbl2->addSpacing( 20 );
+ hbl2->addWidget( resauto );
+
+ fine = new QRadioButton(i18n("Fine"),resgroup,"fine");
+ hbl2->addSpacing( 30 );
+ hbl2->addWidget( fine );
+
+ normal = new QRadioButton(i18n("Normal"),resgroup,"normal");
+ hbl2->addSpacing( 30 );
+ hbl2->addWidget( normal );
+
+ vbl->addSpacing( 20 );
+
+ QHBoxLayout *hbl3 = new QHBoxLayout();
+ vbl->addLayout( hbl3 );
+
+ lsblabel = new QLabel(i18n("Raw fax data are:"), bg,"lsblabel");
+ hbl3->addSpacing( 10 );
+ hbl3->addWidget( lsblabel );
+
+ lsb = new QCheckBox(i18n("LS-Bit first"), bg,"lsbitfirst");
+ hbl3->addSpacing( 10 );
+ hbl3->addWidget( lsb );
+
+ vbl->addSpacing( 15 );
+
+ QHBoxLayout *hbl9 = new QHBoxLayout();
+ vbl->addLayout( hbl9 );
+ hbl9->addSpacing( 10 );
+
+ rawgroup = new QButtonGroup(bg,"rawgroup");
+ hbl9->addWidget( rawgroup );
+
+ QHBoxLayout *hbl4 = new QHBoxLayout( rawgroup );
+
+ rawgroup->setFrameStyle(QFrame::NoFrame);
+
+ rawlabel = new QLabel(i18n("Raw fax format:"),rawgroup,"rawlabel");
+ rawlabel->setFixedSize( rawlabel->sizeHint() );
+ hbl4->addWidget( rawlabel );
+
+ g3 = new QRadioButton("G3",rawgroup,"g3");
+ connect(g3,SIGNAL(clicked()), this, SLOT(g3toggled()));
+ hbl4->addSpacing( 20 );
+ hbl4->addWidget( g3 );
+
+ g32d = new QRadioButton("G32d",rawgroup,"g32d");
+ connect(g32d,SIGNAL(clicked()), this,SLOT(g32toggled()));
+ hbl4->addSpacing( 30 );
+ hbl4->addWidget( g32d );
+
+ g4 = new QRadioButton("G4",rawgroup,"g4");
+ connect(g4,SIGNAL(clicked()), this, SLOT(g4toggled()));
+ hbl4->addSpacing( 30 );
+ hbl4->addWidget( g4 );
+
+ vbl->addSpacing( 20 );
+
+ QHBoxLayout *hbl5 = new QHBoxLayout();
+ vbl->addLayout( hbl5 );
+
+ widthlabel = new QLabel(i18n("Raw fax width:"),bg,"widthlabel");
+ hbl5->addSpacing( 10 );
+ hbl5->addWidget( widthlabel );
+
+ widthedit = new KIntNumInput(1, bg);
+ widthedit->setRange(1, 10000, 1, false);
+ hbl5->addWidget( widthedit );
+
+ heightlabel = new QLabel(i18n("Height:"),bg,"heightlabel");
+ hbl5->addSpacing( 10 );
+ hbl5->addWidget( heightlabel );
+
+ heightedit = new KIntNumInput(1, bg);
+ heightedit->setRange(0, 100000, 1, false);
+ hbl5->addWidget( heightedit );
+
+ geomauto = new QCheckBox(i18n("Auto"),bg,"geomauto");
+ connect(geomauto,SIGNAL(clicked()),this,SLOT(geomtoggled()));
+ hbl5->addSpacing( 10 );
+ hbl5->addWidget( geomauto );
+}
+
+
+struct optionsinfo * OptionsDialog::getInfo(){
+
+ if(resauto->isChecked())
+ oi.resauto = 1;
+
+ if(fine->isChecked())
+ oi.fine = 1;
+ else
+ oi.fine = 0;
+
+ if(landscape->isChecked())
+ oi.landscape = 1;
+ else
+ oi.landscape = 0;
+
+ if(flip->isChecked())
+ oi.flip = 1;
+ else
+ oi.flip = 0;
+
+ if(invert->isChecked())
+ oi.invert = 1;
+ else
+ oi.invert = 0;
+
+ if(lsb->isChecked())
+ oi.lsbfirst = 1;
+ else
+ oi.lsbfirst = 0;
+
+ if(geomauto->isChecked())
+ oi.geomauto = 1;
+
+
+ if(g3->isChecked()){
+ oi.raw = 3;
+ }
+
+ if(g32d->isChecked()){
+ oi.raw = 2;
+ oi.geomauto = 0;
+
+ }
+
+ if(g4->isChecked()){
+ oi.raw = 4;
+ oi.geomauto = 0;
+ }
+
+ oi.height = heightedit->value();
+ oi.width = widthedit->value();
+
+
+
+ return &oi;
+
+}
+
+void OptionsDialog::setWidgets(struct optionsinfo* newoi ){
+
+ if(!newoi)
+ return;
+
+ if(newoi->resauto == 1){
+ resauto->setChecked(newoi->resauto);
+ fine->setChecked(!newoi->resauto);
+ normal->setChecked(!newoi->resauto);
+ }
+ else{
+ if(newoi->fine == 1){
+ resauto->setChecked(FALSE);
+ fine->setChecked(TRUE);
+ normal->setChecked(FALSE);
+ }
+ else{
+ resauto->setChecked(FALSE);
+ fine->setChecked(FALSE);
+ normal->setChecked(TRUE);
+ }
+ }
+
+ if(newoi->landscape == 1)
+ landscape->setChecked(TRUE);
+ else
+ landscape->setChecked(FALSE);
+
+ if(newoi->flip == 1)
+ flip->setChecked(TRUE);
+ else
+ flip->setChecked(FALSE);
+
+ if(newoi->invert == 1)
+ invert->setChecked(TRUE);
+ else
+ invert->setChecked(FALSE);
+
+ if(newoi->lsbfirst == 1)
+ lsb->setChecked(TRUE);
+ else
+ lsb->setChecked(FALSE);
+
+ if(newoi->raw == 3){
+ geomauto->setEnabled(TRUE);
+ g3->setChecked(TRUE);
+ }
+
+ if(newoi->raw == 2){
+ geomauto->setEnabled(FALSE);
+ g32d->setChecked(TRUE);
+ }
+
+ if(newoi->raw == 4){
+ geomauto->setEnabled(FALSE);
+ g4->setChecked(TRUE);
+ }
+ widthedit->setValue(newoi->width);
+ heightedit->setValue(newoi->height);
+
+ // auto height and width can only work with g3 faxes
+ if(newoi->geomauto == 1 && newoi->raw != 4 && newoi->raw != 2){
+ geomauto->setChecked(TRUE);
+ widthedit->setEnabled(FALSE);
+ heightedit->setEnabled(FALSE);
+ }
+ else{
+ geomauto->setChecked(FALSE);
+ widthedit->setEnabled(TRUE);
+ heightedit->setEnabled(TRUE);
+
+ }
+
+}
+
+
+void OptionsDialog::g32toggled(){
+
+ geomauto->setChecked(FALSE);
+ geomauto->setEnabled(FALSE);
+ widthedit->setEnabled(TRUE);
+ heightedit->setEnabled(TRUE);
+
+}
+
+void OptionsDialog::g4toggled(){
+
+ geomauto->setChecked(FALSE);
+ geomauto->setEnabled(FALSE);
+ widthedit->setEnabled(TRUE);
+ heightedit->setEnabled(TRUE);
+
+
+}
+
+
+void OptionsDialog::g3toggled(){
+
+ geomauto->setEnabled(TRUE);
+ geomauto->setChecked(TRUE);
+ widthedit->setEnabled(FALSE);
+ heightedit->setEnabled(FALSE);
+
+
+}
+
+void OptionsDialog::geomtoggled(){
+
+ if(geomauto->isChecked()){
+
+ widthedit->setEnabled(FALSE);
+ heightedit->setEnabled(FALSE);
+
+ }
+ else{
+
+ widthedit->setEnabled(TRUE);
+ heightedit->setEnabled(TRUE);
+
+ }
+
+}
+
+void OptionsDialog::slotHelp(){
+ kapp->invokeHelp();
+}
+
+
+#include "options.moc"
diff --git a/kfax/options.h b/kfax/options.h
new file mode 100644
index 00000000..fa9c61c9
--- /dev/null
+++ b/kfax/options.h
@@ -0,0 +1,112 @@
+/*
+ $Id$
+
+
+ Copyright (C) 1996 Bernd Johannes Wuebben
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+
+
+
+*/
+
+
+#ifndef _OPTIONS_DIALOG_H_
+#define _OPTIONS_DIALOG_H_
+
+#include <qapplication.h>
+#include <qfiledialog.h>
+#include <kdialogbase.h>
+#include <qstring.h>
+
+class QGroupBox;
+class QLabel;
+class QButtonGroup;
+class QRadioButton;
+class QCheckBox;
+class QRadioButton;
+
+
+struct optionsinfo {
+ int geomauto;
+ int resauto;
+ int width ;
+ int height;
+ int fine;
+ int landscape;
+ int flip;
+ int invert;
+ int lsbfirst;
+ int raw;
+};
+
+class KIntNumInput;
+
+class OptionsDialog : public KDialogBase {
+
+ Q_OBJECT
+
+public:
+ OptionsDialog( QWidget *parent = 0, const char *name = 0);
+
+ struct optionsinfo* getInfo();
+ void setWidgets(struct optionsinfo *oi);
+
+signals:
+
+public slots:
+ void slotHelp();
+ void geomtoggled();
+ void g32toggled();
+ void g4toggled();
+ void g3toggled();
+
+private:
+
+ QGroupBox *bg;
+ QLabel *reslabel;
+ QButtonGroup *resgroup;
+ QRadioButton *fine;
+ QRadioButton *resauto;
+ QRadioButton *normal;
+ QLabel *displaylabel;
+ QButtonGroup *displaygroup;
+ QCheckBox *landscape;
+ QCheckBox *geomauto;
+ QCheckBox *flip;
+ QCheckBox *invert;
+
+ QButtonGroup *lsbgroup;
+ QLabel *lsblabel;
+ QCheckBox *lsb;
+ QButtonGroup *rawgroup;
+ QRadioButton *g3;
+ QRadioButton *g32d;
+ QRadioButton *g4;
+
+ QLabel *rawlabel;
+
+ QLabel *widthlabel;
+ QLabel *heightlabel;
+ KIntNumInput *widthedit;
+ KIntNumInput *heightedit;
+
+ struct optionsinfo oi;
+
+};
+
+
+#endif
diff --git a/kfax/version.h b/kfax/version.h
new file mode 100644
index 00000000..ca6653cf
--- /dev/null
+++ b/kfax/version.h
@@ -0,0 +1 @@
+#define KFAXVERSION "3.3.6"
diff --git a/kfax/viewfax.cpp b/kfax/viewfax.cpp
new file mode 100644
index 00000000..fe1e4246
--- /dev/null
+++ b/kfax/viewfax.cpp
@@ -0,0 +1,770 @@
+/*
+
+ KFax -- A G3/G4 Fax Viewer
+
+ Copyrigh (C) 1997 Bernd Johannes Wuebben
+
+ Based on:
+
+ viewfax - g3/g4 fax processing software.
+ Copyright (C) 1990, 1995 Frank D. Cringle.
+
+ This file is part of viewfax - g3/g4 fax processing software.
+
+ viewfax is free software; you can redistribute it and/or modify it
+ under the terms of the GNU General Public License as published by the
+ Free Software Foundation; either version 2 of the License, or (at your
+ option) any later version.
+
+ This program is distributed in the hope that it will be useful, but
+ WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+
+*/
+
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <sys/time.h>
+#include <unistd.h>
+
+#include <qglobal.h>
+#include <qdir.h>
+#include <qfile.h>
+#include <qevent.h>
+#include <qprinter.h>
+#include <qstring.h>
+
+#include <kcmdlineargs.h>
+#include <klocale.h>
+
+#include "kfax.h"
+#include "faxexpand.h"
+#include "version.h"
+#include "viewfax.h"
+
+/* NewImage() needs to fiddle with the Display structure */
+#define XLIB_ILLEGAL_ACCESS
+#include <X11/Xlib.h>
+#include <X11/Xutil.h>
+#include <X11/Xatom.h>
+#include <X11/keysym.h>
+#include <X11/keysymdef.h>
+#include <X11/cursorfont.h>
+
+
+#define VIEWFAXVERSION "2.3"
+
+
+/* If moving the image around with the middle mouse button is jerky or
+ slow, try defining USE_MOTIONHINT. It may help (it may also make
+ things worse - it depends on the server implementation) */
+#undef USE_MOTIONHINT
+
+
+
+/* access the 'extra' field in a pagenode */
+
+#define Pimage(p) ((XImage *)(p)->extra)
+
+
+/* forward declarations */
+
+XImage *FlipImage(XImage *xi);
+XImage *MirrorImage(XImage *xi);
+XImage *NewImage(int w, int h, char *data, int bit_order);
+XImage *RotImage(XImage *Image);
+XImage *ZoomImage(XImage *Big);
+
+void FreeImage(XImage *Image);
+
+static int release(int quit);
+
+
+/* X variables */
+
+extern Cursor WorkCursor;
+extern Cursor ReadyCursor;
+extern Cursor MoveCursor;
+extern Cursor LRCursor;
+extern Cursor UDCursor;
+
+extern bool have_no_fax;
+extern Display* qtdisplay ;
+extern Window qtwin;
+extern Window Win;
+extern int qwindow_width;
+extern int qwindow_height;
+
+struct pagenode *firstpage, *lastpage, *thispage, *helppage, *auxpage;
+struct pagenode defaultpage;
+
+Display *Disp;
+
+int Default_Screen;
+int verbose = 0;
+
+int abell = 1; /* audio bell */
+int vbell = 0; /* visual bell */
+bool have_cmd_opt = FALSE;
+
+size_t Memused = 0; /* image memory usage */
+static size_t Memlimit = 8*1024*1024; /* try not to exceed */
+
+#undef min
+#undef max
+#define min(a,b) ((a)<(b)?(a):(b))
+#define max(a,b) ((a)>(b)?(a):(b))
+
+#ifndef EXIT_FAILURE
+#define EXIT_FAILURE 1
+#endif
+
+/* OK, OK - this is a dreadful hack. But it adequately distinguishes
+ modern big- and little- endian hosts. We only need this to set the
+ byte order in XImage structures */
+
+static union { t32bits i; unsigned char b[4]; } bo;
+#define ByteOrder bo.b[3]
+
+static char Banner[] =
+"KFax version " KFAXVERSION "\tCopyright (C) 1997, Bernd Johannes Wuebben\n";
+
+/*"KFax is based on:\n"
+"viewfax " VERSION ":\t\tCopyright (c) 1990, 1995 Frank D. Cringle.\n"
+"libtiff v 3.4beta:\tCopyright (c) 1988 - 1955 Sam Leffler\n"
+" \tCopyright (c) 1991 - 1995 Silicon Graphics, Inc.\n\n"
+"KFax comes with ABSOLUTELY NO WARRANTY; for details see the\n"
+"file \"COPYING\" in the distribution directory.\n";*/
+
+XEvent Event;
+XImage *Image, *Images[MAXZOOM];
+XSizeHints size_hints;
+
+Time Lasttime = 0;
+
+struct pagenode *viewpage = 0;
+
+int viewfaxmain()
+{
+ int banner = 0;
+ int have_height = 0;
+
+ bo.i = 1;
+ defaultpage.vres = -1;
+ have_no_fax = TRUE;
+
+ /* TODO Do I need to know this: */
+ defaultpage.expander = g31expand;
+
+ KCmdLineArgs *args = KCmdLineArgs::parsedArgs();
+
+ if (args->isSet("height"))
+ {
+ have_height = 1;
+ defaultpage.height = args->getOption("height").toInt();
+ }
+
+ if (args->isSet("2"))
+ {
+ defaultpage.expander = g32expand;
+ if(!have_height)
+ defaultpage.height = 2339;
+ }
+
+ if (args->isSet("4"))
+ {
+ defaultpage.expander = g4expand;
+ if(!have_height)
+ defaultpage.height = 2155;
+ }
+
+ if (args->isSet("invert"))
+ {
+ defaultpage.inverse = 1;
+ }
+
+ if (args->isSet("landscape"))
+ {
+ defaultpage.orient |= TURN_L;
+ }
+
+ if (args->isSet("fine"))
+ {
+ defaultpage.vres = 1;
+ }
+
+ if (!args->isSet("rmal")) // "normal" is interpreted as "no"+"rmal" :-)
+ {
+ defaultpage.vres = 0;
+ }
+
+ if (args->isSet("reverse"))
+ {
+ defaultpage.lsbfirst = 1;
+ }
+
+ if (args->isSet("upsidedown"))
+ {
+ defaultpage.orient |= TURN_U;
+ }
+
+ if (args->isSet("width"))
+ {
+ defaultpage.width = args->getOption("width").toInt();
+ }
+
+ QCString mem = args->getOption("mem");
+ Memlimit = atoi(mem.data());
+ switch(mem[mem.length()-1]) {
+ case 'M':
+ case 'm':
+ Memlimit *= 1024;
+ case 'K':
+ case 'k':
+ Memlimit *= 1024;
+ }
+
+ if (defaultpage.expander == g4expand && defaultpage.height == 0) {
+ KCmdLineArgs::usage("--height value is required to interpret raw g4 faxes\n");
+ }
+
+ firstpage = lastpage = thispage = helppage = auxpage = 0;
+
+ for (int i = 0; i < args->count(); i++){
+ loadfile(QFile::decodeName(args->arg(i)));
+ }
+ args->clear();
+
+ if (banner ) {
+ fputs(Banner, stderr);
+ exit(1);
+ }
+
+ have_no_fax = (firstpage == 0);
+
+ Disp = qtdisplay;
+ Default_Screen = XDefaultScreen(qtdisplay);
+
+ return 1;
+}
+
+
+/* Change orientation of all following pages */
+void TurnFollowing(int How, struct pagenode *pn)
+{
+ while (pn) {
+ if (Pimage(pn)) {
+ FreeImage(Pimage(pn));
+ pn->extra = 0;
+ }
+ pn->orient ^= How;
+ pn = pn->next;
+ }
+}
+
+static void
+drawline(pixnum *run, int LineNum, struct pagenode *pn)
+{
+ t32bits *p, *p1; /* p - current line, p1 - low-res duplicate */
+ pixnum *r; /* pointer to run-lengths */
+ t32bits pix; /* current pixel value */
+ t32bits acc; /* pixel accumulator */
+ int nacc; /* number of valid bits in acc */
+ int tot; /* total pixels in line */
+ int n;
+
+ LineNum += pn->stripnum * pn->rowsperstrip;
+ if (LineNum >= pn->height) {
+ if (verbose && LineNum == pn->height)
+ fputs("Height exceeded\n", stderr);
+ return;
+ }
+
+ p = (t32bits *) (Pimage(pn)->data + LineNum*(2-pn->vres)*Pimage(pn)->bytes_per_line);
+ p1 =(t32bits *)( pn->vres ? 0 : p + Pimage(pn)->bytes_per_line/sizeof(*p));
+ r = run;
+ acc = 0;
+ nacc = 0;
+ pix = pn->inverse ? ~0 : 0;
+ tot = 0;
+ while (tot < pn->width) {
+ n = *r++;
+ tot += n;
+ /* Watch out for buffer overruns, e.g. when n == 65535. */
+ if (tot > pn->width)
+ break;
+ if (pix)
+ acc |= (~(t32bits)0 >> nacc);
+ else if (nacc)
+ acc &= (~(t32bits)0 << (32 - nacc));
+ else
+ acc = 0;
+ if (nacc + n < 32) {
+ nacc += n;
+ pix = ~pix;
+ continue;
+ }
+ *p++ = acc;
+ if (p1)
+ *p1++ = acc;
+ n -= 32 - nacc;
+ while (n >= 32) {
+ n -= 32;
+ *p++ = pix;
+ if (p1)
+ *p1++ = pix;
+ }
+ acc = pix;
+ nacc = n;
+ pix = ~pix;
+ }
+ if (nacc) {
+ *p++ = acc;
+ if (p1)
+ *p1++ = acc;
+ }
+}
+
+static int
+GetPartImage(struct pagenode *pn, int n)
+{
+ unsigned char *Data = getstrip(pn, n);
+
+ if (Data == 0)
+ return 3;
+ pn->stripnum = n;
+ (*pn->expander)(pn, drawline);
+ free(Data);
+ return 1;
+}
+
+int GetImage(struct pagenode *pn){
+ int i;
+
+ if (pn->strips == 0) {
+
+ /*printf("RAW fax file\n");*/
+
+ /* raw file; maybe we don't have the height yet */
+ unsigned char *Data = getstrip(pn, 0);
+ if (Data == 0){
+
+ return 0;
+ }
+ pn->extra = NewImage(pn->width, pn->vres ?
+ pn->height : 2*pn->height, 0, 1);
+
+//printf("height = %d\n",pn->height);
+//printf("setting height to %d\n", pn->vres ? pn->height : 2*pn->height);
+
+ if(pn->extra == 0)
+ return 0;
+
+ (*pn->expander)(pn, drawline);
+ }
+ else {
+ /* multi-strip tiff */
+ /*printf("MULTI STRIP TIFF fax file\n");*/
+
+ pn->extra = NewImage(pn->width, pn->vres ?
+ pn->height : 2*pn->height, 0, 1);
+
+ if(pn->extra == 0)
+ return 0;
+ pn->stripnum = 0;
+ for (i = 0; i < pn->nstrips; i++){
+
+ int k =GetPartImage(pn, i);
+
+ if ( k == 3 ){
+ FreeImage(Pimage(pn));
+ return k;
+ }
+
+ }
+ }
+ if (pn->orient & TURN_U)
+ pn->extra = FlipImage(Pimage(pn));
+ if (pn->orient & TURN_M)
+ pn->extra = MirrorImage(Pimage(pn));
+ if (pn->orient & TURN_L)
+ pn->extra = RotImage(Pimage(pn));
+ if (verbose) printf("\tmemused = %d\n", Memused);
+
+/*
+if(pn->extra)
+ printf("pn->extra !=0 %s\n",pn->name);
+else
+ printf("pn->extra ==0 %s\n",pn->name);
+ */
+
+ return 1;
+}
+
+
+
+/* run this region through perl to generate the zoom table:
+$lim = 1;
+@c = ("0", "1", "1", "2");
+print "static unsigned char Z[] = {\n";
+for ($i = 0; $i < 16; $i++) {
+ for ($j = 0; $j < 16; $j++) {
+ $b1 = ($c[$j&3]+$c[$i&3]) > $lim;
+ $b2 = ($c[($j>>2)&3]+$c[($i>>2)&3]) > $lim;
+ printf " %X,", ($b2 << 1) | $b1;
+ }
+ print "\n";
+}
+print "};\n";
+*/
+
+static unsigned char Z[] = {
+ 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 2, 2, 2, 3,
+ 0, 1, 1, 1, 0, 1, 1, 1, 0, 1, 1, 1, 2, 3, 3, 3,
+ 0, 1, 1, 1, 0, 1, 1, 1, 0, 1, 1, 1, 2, 3, 3, 3,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 3, 3, 3, 3,
+ 0, 0, 0, 1, 2, 2, 2, 3, 2, 2, 2, 3, 2, 2, 2, 3,
+ 0, 1, 1, 1, 2, 3, 3, 3, 2, 3, 3, 3, 2, 3, 3, 3,
+ 0, 1, 1, 1, 2, 3, 3, 3, 2, 3, 3, 3, 2, 3, 3, 3,
+ 1, 1, 1, 1, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
+ 0, 0, 0, 1, 2, 2, 2, 3, 2, 2, 2, 3, 2, 2, 2, 3,
+ 0, 1, 1, 1, 2, 3, 3, 3, 2, 3, 3, 3, 2, 3, 3, 3,
+ 0, 1, 1, 1, 2, 3, 3, 3, 2, 3, 3, 3, 2, 3, 3, 3,
+ 1, 1, 1, 1, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
+ 2, 2, 2, 3, 2, 2, 2, 3, 2, 2, 2, 3, 2, 2, 2, 3,
+ 2, 3, 3, 3, 2, 3, 3, 3, 2, 3, 3, 3, 2, 3, 3, 3,
+ 2, 3, 3, 3, 2, 3, 3, 3, 2, 3, 3, 3, 2, 3, 3, 3,
+ 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
+};
+
+#define nib(n,w) (((w)>>((n)<<2))&15)
+#define zak(a,b) Z[(a<<4)|b]
+
+/* 2 -> 1 zoom, 4 pixels -> 1 pixel
+ if #pixels <= $lim (see above), new pixel is white,
+ else black.
+*/
+
+XImage *ZoomImage(XImage *Big){
+
+ XImage *Small;
+ int w, h;
+ int i, j;
+
+ XDefineCursor(Disp, Win, WorkCursor);
+ XFlush(Disp);
+ w = (Big->width+1) / 2;
+ h = (Big->height+1) / 2;
+ Small = NewImage(w, h, 0, Big->bitmap_bit_order);
+ if(Small == 0)
+ return 0;
+
+ Small->xoffset = (Big->xoffset+1)/2;
+ for (i = 0; i < Big->height; i += 2) {
+ t32bits *pb0 = (t32bits *) (Big->data + i * Big->bytes_per_line);
+ t32bits *pb1 = pb0 + ((i == Big->height-1) ? 0 : Big->bytes_per_line/4);
+ t32bits *ps = (t32bits *) (Small->data + i * Small->bytes_per_line / 2);
+ for (j = 0; j < Big->bytes_per_line/8; j++) {
+ t32bits r1, r2;
+ t32bits t0 = *pb0++;
+ t32bits t1 = *pb1++;
+ r1 = (zak(nib(7,t0),nib(7,t1))<<14) |
+ (zak(nib(6,t0),nib(6,t1))<<12) |
+ (zak(nib(5,t0),nib(5,t1))<<10) |
+ (zak(nib(4,t0),nib(4,t1))<<8) |
+ (zak(nib(3,t0),nib(3,t1))<<6) |
+ (zak(nib(2,t0),nib(2,t1))<<4) |
+ (zak(nib(1,t0),nib(1,t1))<<2) |
+ (zak(nib(0,t0),nib(0,t1)));
+ t0 = *pb0++;
+ t1 = *pb1++;
+ r2 = (zak(nib(7,t0),nib(7,t1))<<14) |
+ (zak(nib(6,t0),nib(6,t1))<<12) |
+ (zak(nib(5,t0),nib(5,t1))<<10) |
+ (zak(nib(4,t0),nib(4,t1))<<8) |
+ (zak(nib(3,t0),nib(3,t1))<<6) |
+ (zak(nib(2,t0),nib(2,t1))<<4) |
+ (zak(nib(1,t0),nib(1,t1))<<2) |
+ (zak(nib(0,t0),nib(0,t1)));
+ *ps++ = (Big->bitmap_bit_order) ?
+ (r1<<16)|r2 : (r2<<16)|r1;
+ }
+ for ( ; j < Small->bytes_per_line/4; j++) {
+ t32bits r1;
+ t32bits t0 = *pb0++;
+ t32bits t1 = *pb1++;
+ r1 = (zak(nib(7,t0),nib(7,t1))<<14) |
+ (zak(nib(6,t0),nib(6,t1))<<12) |
+ (zak(nib(5,t0),nib(5,t1))<<10) |
+ (zak(nib(4,t0),nib(4,t1))<<8) |
+ (zak(nib(3,t0),nib(3,t1))<<6) |
+ (zak(nib(2,t0),nib(2,t1))<<4) |
+ (zak(nib(1,t0),nib(1,t1))<<2) |
+ (zak(nib(0,t0),nib(0,t1)));
+ *ps++ = (Big->bitmap_bit_order) ?
+ (r1<<16) : r1;
+ }
+ }
+ XDefineCursor(Disp, Win, ReadyCursor);
+ return Small;
+}
+
+XImage *FlipImage(XImage *Image){
+
+ XImage *New = NewImage(Image->width, Image->height,
+ Image->data, !Image->bitmap_bit_order);
+ if(New == 0)
+ return 0;
+
+ t32bits *p1 = (t32bits *) Image->data;
+ t32bits *p2 = (t32bits *) (Image->data + Image->height *
+ Image->bytes_per_line - 4);
+
+ /* the first shall be last ... */
+ while (p1 < p2) {
+ t32bits t = *p1;
+ *p1++ = *p2;
+ *p2-- = t;
+ }
+
+ /* let Xlib twiddle the bits */
+ New->xoffset = 32 - (Image->width & 31) - Image->xoffset;
+ New->xoffset &= 31;
+
+ Image->data = 0;
+ FreeImage(Image);
+ return New;
+}
+
+XImage *MirrorImage(XImage *Image){
+
+ int i;
+ XImage *New = NewImage(Image->width, Image->height,
+ Image->data, !Image->bitmap_bit_order);
+ if(New == 0)
+ return 0;
+
+ /* reverse order of 32-bit words in each line */
+ for (i = 0; i < Image->height; i++) {
+ t32bits *p1 = (t32bits *) (Image->data + Image->bytes_per_line * i);
+ t32bits *p2 = p1 + Image->bytes_per_line/4 - 1;
+ while (p1 < p2) {
+ t32bits t = *p1;
+ *p1++ = *p2;
+ *p2-- = t;
+ }
+ }
+
+ /* let Xlib twiddle the bits */
+ New->xoffset = 32 - (Image->width & 31) - Image->xoffset;
+ New->xoffset &= 31;
+
+ Image->data = 0;
+ FreeImage(Image);
+ return New;
+}
+
+XImage *RotImage(XImage *Image){
+
+ XImage *New;
+ int w = Image->height;
+ int h = Image->width;
+ int i, j, k, shift;
+ int order = Image->bitmap_bit_order;
+ int offs = h+Image->xoffset-1;
+
+ New = NewImage(w, h, 0, 1);
+ if (New == 0)
+ return 0;
+
+ k = (32 - Image->xoffset) & 3;
+ for (i = h - 1; i && k; i--, k--) {
+ t32bits *sp = (t32bits *) Image->data + (offs-i)/32;
+ t32bits *dp = (t32bits *) (New->data+i*New->bytes_per_line);
+ t32bits d0 =0;
+ shift = (offs-i)&31;
+ if (order) shift = 31-shift;
+ for (j = 0; j < w; j++) {
+ t32bits t = *sp;
+ sp += Image->bytes_per_line/4;
+ d0 |= ((t >> shift) & 1);
+ if ((j & 31) == 31)
+ *dp++ = d0;
+ d0 <<= 1;;
+ }
+ if (j & 31)
+ *dp++ = d0<<(31-j);
+ }
+ for ( ; i >= 3; i-=4) {
+ t32bits *sp = (t32bits *) Image->data + (offs-i)/32;
+ t32bits *dp0 = (t32bits *) (New->data+i*New->bytes_per_line);
+ t32bits *dp1 = dp0 - New->bytes_per_line/4;
+ t32bits *dp2 = dp1 - New->bytes_per_line/4;
+ t32bits *dp3 = dp2 - New->bytes_per_line/4;
+ t32bits d0=0 , d1=0, d2 =0, d3 =0;
+ shift = (offs-i)&31;
+ if (order) shift = 28-shift;
+ for (j = 0; j < w; j++) {
+ t32bits t = *sp >> shift;
+ sp += Image->bytes_per_line/4;
+ d0 |= t & 1; t >>= 1;
+ d1 |= t & 1; t >>= 1;
+ d2 |= t & 1; t >>= 1;
+ d3 |= t & 1; t >>= 1;
+ if ((j & 31) == 31) {
+ if (order) {
+ *dp0++ = d3;
+ *dp1++ = d2;
+ *dp2++ = d1;
+ *dp3++ = d0;
+ }
+ else {
+ *dp0++ = d0;
+ *dp1++ = d1;
+ *dp2++ = d2;
+ *dp3++ = d3;
+ }
+ }
+ d0 <<= 1; d1 <<= 1; d2 <<= 1; d3 <<= 1;
+ }
+ if (j & 31) {
+ if (order) {
+ *dp0++ = d3<<(31-j);
+ *dp1++ = d2<<(31-j);
+ *dp2++ = d1<<(31-j);
+ *dp3++ = d0<<(31-j);
+ }
+ else {
+ *dp0++ = d0<<(31-j);
+ *dp1++ = d1<<(31-j);
+ *dp2++ = d2<<(31-j);
+ *dp3++ = d3<<(31-j);
+ }
+ }
+ }
+ for (; i >= 0; i--) {
+ t32bits *sp = (t32bits *) Image->data + (offs-i)/32;
+ t32bits *dp = (t32bits *) (New->data+i*New->bytes_per_line);
+ t32bits d0=0;
+ shift = (offs-i)&31;
+ if (order) shift = 31-shift;
+ for (j = 0; j < w; j++) {
+ t32bits t = *sp;
+ sp += Image->bytes_per_line/4;
+ d0 |= ((t >> shift) & 1);
+ if ((j & 31) == 31)
+ *dp++ = d0;
+ d0 <<= 1;;
+ }
+ if (j & 31)
+ *dp++ = d0<<(31-j);
+ }
+ FreeImage(Image);
+ return New;
+}
+
+/* release some non-essential memory or abort */
+#define Try(n) \
+ if (n && n != thispage && n->extra) { \
+ FreeImage((XImage*)n->extra); \
+ n->extra = 0; \
+ return 1; \
+ }
+
+static int
+release(int quit)
+{
+ (void) quit;
+
+ struct pagenode *pn;
+
+ if (thispage) {
+ /* first consider "uninteresting" pages */
+ for (pn = firstpage->next; pn; pn = pn->next)
+ if (pn->extra && pn != thispage && pn != thispage->prev &&
+ pn != thispage->next && pn != lastpage) {
+ FreeImage(Pimage(pn));
+ pn->extra = 0;
+ return 1;
+ }
+ Try(lastpage);
+ Try(firstpage);
+ Try(thispage->prev);
+ Try(thispage->next);
+ }
+
+ return 0;
+
+}
+
+XImage *NewImage(int w, int h, char *data, int bit_order){
+
+ XImage *newimage;
+ /* This idea is taken from xwud/xpr. Use a fake display with the
+ desired bit/byte order to get the image routines initialised
+ correctly */
+ Display fake;
+
+ fake = *Disp;
+ if (data == 0)
+ data = xmalloc(((w + 31) & ~31) * h / 8);
+ fake.byte_order = ByteOrder;
+ fake.bitmap_unit = 32;
+ fake.bitmap_bit_order = bit_order;
+
+ int returncode = -1;
+ while ((newimage = XCreateImage(&fake, DefaultVisual(Disp, Default_Screen),
+ 1, XYBitmap, 0, data, w, h, 32, 0)) == 0 ){
+
+ returncode = release(1);
+ if (returncode == 0)
+ break;
+ }
+
+ if (returncode == 0){
+ kfaxerror("Sorry","Can not allocate Memory for a new Fax Image\n");
+ return 0;
+ }
+
+ Memused += newimage->bytes_per_line * newimage->height;
+ /*printf("allocating %d bytes for %ld\n",
+ newimage->bytes_per_line * newimage->height,
+ newimage);*/
+
+
+ return newimage;
+}
+
+void FreeImage(XImage *Image){
+
+ if (Image->data){
+ Memused -= Image->bytes_per_line * Image->height;
+/*printf("deallocating %d bytes for %ld\n",
+ Image->bytes_per_line * Image->height,
+ Image);*/
+ }
+ XDestroyImage(Image);
+}
+
+#ifndef xmalloc
+char *
+xmalloc(unsigned int size)
+{
+ char *p;
+
+ while (Memused + size > Memlimit && release(0))
+ ;
+ while ((p = (char*) malloc(size)) == 0)
+ (void) release(1);
+ return p;
+}
+#endif
diff --git a/kfax/viewfax.h b/kfax/viewfax.h
new file mode 100644
index 00000000..92ffbd70
--- /dev/null
+++ b/kfax/viewfax.h
@@ -0,0 +1,27 @@
+/*
+ This file is part of KFAX
+ Copyright (c) 1999 Waldo Bastian <[email protected]>
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License version 2 as published by the Free Software Foundation.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ Boston, MA 02110-1301, USA.
+*/
+
+#ifndef _VIEWFAX_H_
+#define _VIEWFAX_H_
+
+#define MAXZOOM 4
+
+int viewfaxmain();
+
+#endif