summaryrefslogtreecommitdiffstats
path: root/conduits/docconduit/makedoc9.cc
diff options
context:
space:
mode:
Diffstat (limited to 'conduits/docconduit/makedoc9.cc')
-rw-r--r--conduits/docconduit/makedoc9.cc405
1 files changed, 405 insertions, 0 deletions
diff --git a/conduits/docconduit/makedoc9.cc b/conduits/docconduit/makedoc9.cc
new file mode 100644
index 0000000..1f1c56f
--- /dev/null
+++ b/conduits/docconduit/makedoc9.cc
@@ -0,0 +1,405 @@
+// based on: MakeDoc, version 2
+// I only took the tBuf class from there and adapted it.
+//
+// Compresses text files into a format that is ready to export to a Pilot
+// and work with Rick Bram's PilotDOC reader.
+// Copyright (C) Reinhold Kainhofer, 2002
+// Copyrigth (C) Pat Beirne, 2000
+//
+// Original file (makedoc9.cpp) copyright by:
+// Copyright (C) Pat Beirne, 2000.
+// Distributable under the GNU General Public License Version 2 or later.
+//
+// ver 0.6 enforce 31 char limit on database names
+// ver 0.7 change header and record0 to structs
+// ver 2.0 added category control on the command line
+// changed extensions from .prc to .pdb
+
+/*
+** 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 in a file called COPYING; if not, write to
+** the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
+** MA 02110-1301, USA.
+*/
+
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include <iostream>
+
+
+#include "makedoc9.h"
+
+
+
+//
+// Issue()
+//
+// action: handle the details of writing a single
+// character to the compressed stream
+//
+unsigned
+ tBuf::Issue(byte src, int &bSpace)
+{
+ unsigned int iDest = len;
+ byte *dest = buf;
+
+ // TODO: which of the if parts should really be included???
+#if 0
+ // modified version of issue
+ // just issue the char
+ if (src >= 0x80 || src <= 8)
+ dest[iDest++] = 1;
+ dest[iDest++] = src;
+
+#else
+ // if there is an outstanding space char, see if
+ // we can squeeze it in with an ASCII char
+ if (bSpace)
+ {
+ if (src >= 0x40 && src <= 0x7F)
+ dest[iDest++] = src ^ 0x80;
+ else
+ {
+ // couldn't squeeze it in, so issue the space char by itself
+ // most chars go out simple, except the range 1...8,0x80...0xFF
+ dest[iDest++] = ' ';
+ if (src < 0x80 && (src == 0 || src > 8))
+ dest[iDest++] = src;
+ else
+ dest[iDest++] = 1, dest[iDest++] = src;
+ }
+ // knock down the space flag
+ bSpace = 0;
+ }
+ else
+ {
+ // check for a space char
+ if (src == ' ')
+ bSpace = 1;
+ else
+ {
+ if (src < 0x80 && (src == 0 || src > 8))
+ dest[iDest++] = src;
+ else
+ dest[iDest++] = 1, dest[iDest++] = src;
+
+ }
+ }
+#endif
+ len = iDest;
+ return iDest;
+}
+
+//
+// Compress
+//
+// params: none
+//
+// action: takes the given buffer,
+// and compresses
+// the original data down into a second buffer
+//
+// comment: This version make heavy use of walking pointers.
+//
+unsigned tBuf::Compress()
+{
+ if (!buf)
+ return 0;
+ if (isCompressed) {
+// cout<<"Buffer is already compressed!"<<endl;
+ return len;
+// } else {
+// cout<<" Compressing buffer!!!"<<endl;
+ }
+
+ unsigned int i;
+
+ // run through the input buffer
+ byte *pBuffer; // points to the input buffer
+ byte *pHit; // points to a walking test hit; works upwards on successive matches
+ byte *pPrevHit; // previous value of pHit; also, start of next test
+ byte *pTestHead; // current test string
+ byte *pTestTail; // current walking pointer; one past the current test buffer
+ byte *pEnd; // 1 past the end of the input buffer
+
+ pHit = pPrevHit = pTestHead = pBuffer = buf;
+ pTestTail = pTestHead + 1;
+ pEnd = buf + len; // should point to a 0!
+
+ // make a dest buffer and reassign the local buffer
+ buf = new byte[6000];
+ len = 0; // used to walk through the output buffer
+
+ // loop, absorbing one more char from the input buffer on each pass
+ for (; pTestHead != pEnd; pTestTail++)
+ {
+ // if we already have 10 char match, don't bother scanning again for the 11th (wasted time)
+ if (pTestTail - pTestHead != (1 << COUNT_BITS) + 3)
+ {
+ // scan in the previous data for a match
+ // terminate the test string (and the matcher string, as well!) in a 0
+ byte tmp = *pTestTail;
+
+ *pTestTail = 0;
+ pHit = (byte *) strstr((const char *) pPrevHit,
+ (const char *) pTestHead);
+ *pTestTail = tmp; // restore the char
+ }
+
+ // on a mismatch or end of buffer, issued codes
+ if (pHit == pTestHead
+ || pTestTail - pTestHead > (1 << COUNT_BITS) + 2
+ || pTestTail == pEnd)
+ {
+ // issue the codes
+ // first, check for short runs
+ if (pTestTail - pTestHead < 4)
+ {
+ if (pTestHead[0] > 0x7F || pTestHead[0] <= 8)
+ buf[len++] = 1;
+ buf[len++] = pTestHead[0];
+ pTestHead++;
+ }
+ // for longer runs, issue a run-code
+ else
+ {
+ unsigned int dist = pTestHead - pPrevHit;
+ unsigned int compound =
+ (dist << COUNT_BITS) + pTestTail - pTestHead - 4;
+
+//if (dist>=(1<<DISP_BITS)) printf("\n!! error dist overflow");
+//if (pTestTail-pTestHead-4>7) printf("\n!! error len overflow");
+
+ buf[len++] = 0x80 + (compound >> 8);
+ buf[len++] = compound & 0xFF;
+//printf("\nissuing code for sequence len %d <%c%c%c>",pTestTail-pTestHead-1,pTestHead[0],pTestHead[1],pTestHead[2]);
+//printf("\n <%x%x>",pOut[-2],pOut[-1]);
+ // and start again
+ pTestHead = pTestTail - 1;
+ }
+ // start the search again
+ pPrevHit = pBuffer;
+ // within range
+ if (pTestHead - pPrevHit > ((1 << DISP_BITS) - 1))
+ pPrevHit = pTestHead - ((1 << DISP_BITS) - 1);
+ }
+ // got a match
+ else
+ {
+ pPrevHit = pHit;
+ }
+ // when we get to the end of the buffer, don't inc past the end
+ // this forces the residue chars out one at a time
+ if (pTestTail == pEnd)
+ pTestTail--;
+ }
+
+
+ // final scan to merge consecutive high chars together
+ // and merge space chars
+ unsigned int k;
+
+ for (i = k = 0; i < len; i++, k++)
+ {
+ buf[k] = buf[i];
+ // skip the run-length codes
+ if (buf[k] >= 0x80 && buf[k] < 0xC0)
+ buf[++k] = buf[++i];
+ // if we hit a high char marker, look ahead for another
+ // and merge multiples together
+ else if (buf[k] == 1)
+ {
+ buf[k + 1] = buf[i + 1];
+ while (i + 2 < len && buf[i + 2] == 1 && buf[k] < 8)
+ {
+ buf[k]++;
+ buf[k + buf[k]] = buf[i + 3];
+ i += 2;
+ }
+ k += buf[k];
+ i++;
+ }
+ else if (buf[k] == ' ' && i < len - 1 && buf[i + 1] <= 0x7F
+ && buf[i + 1] >= 0x40)
+ buf[k] = 0x80 | buf[++i];
+ }
+
+ // delete original buffer
+ delete[]pBuffer;
+ len = k;
+
+ isCompressed = true;
+ return k;
+}
+
+/*
+ Decompress
+
+ params: none
+
+ action: make a new buffer
+ run through the source data
+ check the 4 cases:
+ 0,9...7F represent self
+ 1...8 escape n chars
+ 80...bf reference earlier run
+ c0...ff space+ASCII
+
+*/
+unsigned tBuf::Decompress()
+{
+ if (!buf)
+ return 0;
+ if (!isCompressed) {
+// cout<<"Buffer already uncompressed. Doing nothing"<<endl;
+ return len;
+// } else {
+// cout<<"Decompressing buffer"<<endl;
+ }
+
+ // we "know" that all decompresses fit within 4096, right?
+ byte *pOut = new byte[6000];
+ byte *in_buf = buf;
+ byte *out_buf = pOut;
+
+ unsigned int i, j;
+
+ for (j = i = 0; j < len;)
+ {
+ unsigned int c;
+
+ // take a char from the input buffer
+ c = in_buf[j++];
+
+ // separate the char into zones: 0, 1...8, 9...0x7F, 0x80...0xBF, 0xC0...0xFF
+
+ // codes 1...8 mean copy that many bytes; for accented chars & binary
+ if (c > 0 && c < 9)
+ while (c--)
+ out_buf[i++] = in_buf[j++];
+
+ // codes 0, 9...0x7F represent themselves
+ else if (c < 0x80)
+ out_buf[i++] = c;
+
+ // codes 0xC0...0xFF represent "space + ascii char"
+ else if (c >= 0xC0)
+ out_buf[i++] = ' ', out_buf[i++] = c ^ 0x80;
+
+ // codes 0x80...0xBf represent sequences
+ else
+ {
+ int m, n;
+
+ c <<= 8;
+ c += in_buf[j++];
+ m = (c & 0x3FFF) >> COUNT_BITS;
+ n = c & ((1 << COUNT_BITS) - 1);
+ n += 3;
+ while (n--)
+ {
+ out_buf[i] = out_buf[i - m];
+ i++;
+ }
+ }
+ }
+ out_buf[i++]='\0';
+ out_buf[i++]='\0';
+ delete[]buf;
+ buf = pOut;
+ len = i;
+
+ isCompressed = false;
+ return i;
+}
+
+unsigned tBuf::DuplicateCR()
+{
+ if (!buf)
+ return 0;
+ byte *pBuf = new byte[2 * len];
+
+ unsigned int k, j;
+
+ for (j = k = 0; j < len; j++, k++)
+ {
+ pBuf[k] = buf[j];
+ if (pBuf[k] == 0x0A)
+ pBuf[k++] = 0x0D, pBuf[k] = 0x0A;
+ }
+ delete[]buf;
+ buf = pBuf;
+ len = k;
+ return k;
+}
+
+
+
+// this nasty little beast removes really low ASCII and 0's
+// and handles the CR problem
+//
+// if a cr appears before a lf, then remove the cr
+// if a cr appears in isolation, change to a lf
+unsigned tBuf::RemoveBinary()
+{
+ if (!buf)
+ return 0;
+ byte *in_buf = buf;
+ byte *out_buf = new byte[len];
+
+ unsigned int k, j;
+
+ for (j = k = 0; j < len; j++, k++)
+ {
+ // copy each byte
+ out_buf[k] = in_buf[j];
+
+ // throw away really low ASCII
+ if (( /*out_buf[k]>=0 && */ out_buf[k] < 9))
+ k--;
+
+ // for CR
+ if (out_buf[k] == 0x0D)
+ {
+ // if next is LF, then drop it
+ if (j < len - 1 && in_buf[j + 1] == 0x0A)
+ k--;
+ else // turn it into a LF
+ out_buf[k] = 0x0A;
+ }
+ }
+ delete[]buf;
+ buf = out_buf;
+ len = k;
+ return k;
+}
+
+void tBuf::setText(const byte * text, unsigned txtlen, bool txtcomp)
+{
+ if (buf)
+ delete[]buf;
+ buf = 0L;
+
+ if (txtlen <= 0)
+ txtlen = strlen((const char *) text);
+ len = txtlen;
+ buf = new byte[len];
+
+ memcpy(buf, text, len*sizeof(char));
+// strncpy((char *) buf, (const char *) text, len);
+ isCompressed = txtcomp;
+// cout<<"Setting text, compressed="<<txtcomp<<endl;
+}