ciderpress/reformat/AppleWorks.h
Andy McFadden 2adbe9591f Add optional MouseText-to-ASCII conversion
The AWP5 MouseText output is okay for some things but not others.
This adds an ASCII conversion, enabled through a preference.
2017-11-13 14:24:58 -08:00

247 lines
9.7 KiB
C++

/*
* CiderPress
* Copyright (C) 2007 by faddenSoft, LLC. All Rights Reserved.
* See the file LICENSE for distribution terms.
*/
/*
* Reformat AppleWorks documents.
*/
#ifndef REFORMAT_APPLEWORKS_H
#define REFORMAT_APPLEWORKS_H
#include "ReformatBase.h"
/*
* Reformat an AppleWorks WP document into formatted text.
*/
class ReformatAWP : public ReformatText {
public:
ReformatAWP(void)
: fShowEmbeds(true),
fMouseTextToASCII(false)
{}
virtual ~ReformatAWP(void) {}
virtual void Examine(ReformatHolder* pHolder) override;
virtual int Process(const ReformatHolder* pHolder,
ReformatHolder::ReformatID id, ReformatHolder::ReformatPart part,
ReformatOutput* pOutput) override;
private:
/*
* Constants.
*/
enum {
kFileHeaderSize = 300, /* expected size of FileHeader */
kSeventyNine = 79, /* value of FileHeader.seventyNine */
kSFMinVers30 = 30, /* indicates AW 3.0 */
kTabFlagsIsRuler = 0xff, /* compare against byte 2 of text record */
kCRatEOL = 0x80, /* flag on byte 3 of the text record */
kMinTextChar = 0x20, /* values from 0x01 - 0x1f are special */
kEOFMarker = 0xff, /* two of these found at end of file */
kLineRecordText = 0x00,
kLineRecordCarriageReturn = 0xd0,
kLineRecordCommandMin = 0xd4,
kLineRecordCommandMax = 0xff,
kLineRecordCommandPageHeaderEnd = 0xd5,
kLineRecordCommandPageFooterEnd = 0xd6,
kLineRecordCommandRightJustify = 0xd7,
kLineRecordCommandPlatenWidth = 0xd8, // 10ths of an inch
kLineRecordCommandLeftMargin = 0xd9, // 10ths of an inch
kLineRecordCommandRightMargin = 0xda, // 10ths of an inch
kLineRecordCommandCharsPerInch = 0xdb,
kLineRecordCommandProportional1 = 0xdc,
kLineRecordCommandProportional2 = 0xdd,
kLineRecordCommandIndent = 0xde,
kLineRecordCommandJustify = 0xdf,
kLineRecordCommandUnjustify = 0xe0,
kLineRecordCommandCenter = 0xe1,
kLineRecordCommandPaperLength = 0xe2,
kLineRecordCommandTopMargin = 0xe3,
kLineRecordCommandBottomMargin = 0xe4,
kLineRecordCommandLinesPerInch = 0xe5,
kLineRecordCommandSingleSpace = 0xe6,
kLineRecordCommandDoubleSpace = 0xe7,
kLineRecordCommandTripleSpace = 0xe8,
kLineRecordCommandNewPage = 0xe9,
kLineRecordCommandGroupBegin = 0xea,
kLineRecordCommandGroupEnd = 0xeb,
kLineRecordCommandPageHeader = 0xec,
kLineRecordCommandPageFooter = 0xed,
kLineRecordCommandSkipLines = 0xee,
kLineRecordCommandPageNumber = 0xef,
kLineRecordCommandPauseEachPage = 0xf0,
kLineRecordCommandPauseHere = 0xf1,
kLineRecordCommandSetMarker = 0xf2,
kLineRecordCommandSetPageNumber = 0xf3,
kLineRecordCommandPageBreak = 0xf4,
kLineRecordCommandPageBreak256 = 0xf5,
kLineRecordCommandPageBreakPara = 0xf6,
kLineRecordCommandPageBreakPara256 = 0xf7,
// end of file is 0xff
kSpecialCharBoldBegin = 0x01,
kSpecialCharBoldEnd = 0x02,
kSpecialCharSuperscriptBegin = 0x03,
kSpecialCharSuperscriptEnd = 0x04,
kSpecialCharSubscriptBegin = 0x05,
kSpecialCharSubscriptEnd = 0x06,
kSpecialCharUnderlineBegin = 0x07,
kSpecialCharUnderlineEnd = 0x08,
kSpecialCharPrintPageNumber = 0x09,
kSpecialCharEnterKeyboard = 0x0a,
kSpecialCharStickySpace = 0x0b,
kSpecialCharMailMerge = 0x0c,
// reserved = 0x0d,
kSpecialCharPrintDate = 0x0e,
kSpecialCharPrintTime = 0x0f,
// Special Code N = 0x10-15
kSpecialCharTab = 0x16,
kSpecialCharTabFill = 0x17, /* tab fill char, not vis in doc */
// reserved = 0x18
kMaxSoftFailures = 8, /* give up if it looks like junk */
};
/*
* File header, mapped directly on top of the input. This structure must
* be exactly 300 bytes.
*/
typedef struct FileHeader {
uint8_t unused1[4]; /* 000 - 003: not used */
uint8_t seventyNine; /* 004 : $4f (79) */
uint8_t tabStops[80]; /* 005 - 084: tab stops, one of "=<^>.|" */
uint8_t zoomFlag; /* 085 : boolean Zoom flag */
uint8_t unused2[4]; /* 086 - 089: not used */
uint8_t paginatedFlag; /* 090 : boolean Paginated flag */
uint8_t minLeftMargin; /* 091 : minimum "unseen" left margin */
uint8_t mailMergeFlag; /* 092 : boolean - file has merge cmds */
uint8_t unused3[83]; /* 093 - 175: not used, reserved */
uint8_t multiRulerFlag; /* 176 : (3.0) boolean Multiple Rulers */
uint8_t tabRulers[6]; /* 177 - 182: (3.0) used internally */
uint8_t sfMinVers; /* 183 : (3.0) min version of AW req */
uint8_t unused4[66]; /* 184 - 249: reserved */
uint8_t unused5[50]; /* 250 - 299: available */
} FileHeader;
/*
* Current state of the document.
*/
typedef struct DocState {
long softFailures;
long line;
/* not using these yet */
int leftMargin;
} DocState;
void InitDocState(void);
int ProcessLineRecord(uint8_t lineRecData, uint8_t lineRecCode,
const uint8_t** pSrcPtr, long* pLength);
int HandleTextRecord(uint8_t lineRecData,
const uint8_t** pSrcPtr, long* pLength);
FileHeader fFileHeader;
DocState fDocState;
bool fShowEmbeds;
bool fMouseTextToASCII;
};
/*
* Reformat an AppleWorks DB document into CSV.
*/
class ReformatADB : public ReformatText {
public:
ReformatADB(void) {}
virtual ~ReformatADB(void) {}
virtual void Examine(ReformatHolder* pHolder) override;
virtual int Process(const ReformatHolder* pHolder,
ReformatHolder::ReformatID id, ReformatHolder::ReformatPart part,
ReformatOutput* pOutput) override;
private:
enum {
kOffsetToFirstCatHeader = 357,
kMinHeaderLen = 379,
kReportRecordLen = 600,
kCatNameLen = 20,
kCatHeaderLen = 22,
};
};
/*
* Reformat an AppleWorks SS document into CSV.
*/
class ReformatASP : public ReformatText {
public:
ReformatASP(void) { fCurrentRow = fCurrentCol = 1; }
virtual ~ReformatASP(void) {}
virtual void Examine(ReformatHolder* pHolder) override;
virtual int Process(const ReformatHolder* pHolder,
ReformatHolder::ReformatID id, ReformatHolder::ReformatPart part,
ReformatOutput* pOutput) override;
private:
enum {
kFileHeaderSize = 300,
kPropCount = 8,
kSANELen = 8,
};
/*
* File header, mapped directly on top of the input. This structure must
* be exactly 300 bytes.
*/
typedef struct FileHeader {
uint8_t unused1[4]; /* 000-003: not used */
uint8_t colWidth[127]; /* 004-130: column width for each column */
uint8_t recalcOrder; /* 131 : recalc order ('R' or 'C') */
uint8_t recalcFreq; /* 132 : recalc frequency ('A' or 'M') */
uint8_t lastRowRef[2]; /* 133-134: last row referenced */
uint8_t lastColRef; /* 135 : last column referenced */
uint8_t numWindows; /* 136 : '1'/'S'/'T' */
uint8_t windowSync; /* 137 : if two windows, are sync'ed? */
uint8_t winInfo1[24]; /* 138-161: struct with info for 1st window */
uint8_t winInfo2[24]; /* 162-185: struct with info for 2nd window */
uint8_t unused2[27]; /* 186-212: not used */
uint8_t cellProt; /* 213 : cell protection on/off */
uint8_t unused3; /* 214 : not used */
uint8_t platenWidth; /* 215 : platen width */
uint8_t leftMargin; /* 216 : left margin, in 1/10th inches */
uint8_t rightMargin; /* 217 : right margin */
uint8_t cpi; /* 218 : characters per inch */
uint8_t paperLength; /* 219 : paper length, 1/10th inches */
uint8_t topMargin; /* 220 : top margin */
uint8_t bottomMargin; /* 221 : bottom margin */
uint8_t lpi; /* 222 : lines per inch (6 or 8) */
uint8_t spacing; /* 223 : 'S'ingle, 'D'ouble, or 'T'riple */
uint8_t printerCodes[14];/*224-237: "special codes" for printer */
uint8_t printDash; /* 238 : print dash when entry is blank */
uint8_t reportHeader; /* 239 : print report header */
uint8_t zoomed; /* 240 : zoomed to show formulas */
uint8_t reserved1; /* 241 : used internally (v2.1) */
uint8_t ssMinVers; /* 242 : holds 0 for AW2.x, 0x1e for AW3.x */
uint8_t reserved2[7]; /* 243-249: reserved */
uint8_t available[50]; /* 250-299: available for non-AW app use */
} FileHeader;
int fCurrentRow, fCurrentCol;
char fPrintColBuf[3];
int ProcessRow(int rowNum, const uint8_t** pSrcPtr,
long* pLength);
void ProcessCell(const uint8_t* srcPtr, long cellLength);
void PrintToken(const uint8_t** pSrcPtr, long* pLength);
const char* PrintCol(int col);
double ConvertSANEDouble(const uint8_t* srcPtr);
};
#endif /*REFORMAT_APPLEWORKS_H*/