/* This file is part of the LibMSWrite Library Copyright (C) 2001-2003 Clarence Dang 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 Version 2 for more details. You should have received a copy of the GNU Library General Public License Version 2 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. LibMSWrite Project Website: http://sourceforge.net/projects/libmswrite/ */ #ifndef __STRUCTURES_H__ #define __STRUCTURES_H__ #include "structures_generated.h" #include "structures_private.h" namespace MSWrite { class Format { public: static const Word Write_3_0 = 0xBE31; static const Word Write_3_1 = 0xBE32; }; class PageLayout : public PageLayoutGenerated, public NeedsHeader { private: int m_numModified; bool readFromDevice (void); friend class InternalGenerator; bool writeToDevice (void); friend class InternalParser; // the defaults of course static const Byte magic102Default = Byte (102); static const Word magic512Default = Word (512); static const Word pageHeightDefault = Word (Inch2Twip (11)); static const Word pageWidthDefault = Word (Inch2Twip (8.5)); static const Word pageNumberStartDefault = Word (1); static const Word topMarginDefault = Word (Inch2Twip (1)); static const Word textHeightDefault = Word (Inch2Twip (9)); static const Word leftMarginDefault = Word (Inch2Twip (1.25)); static const Word textWidthDefault = Word (Inch2Twip (6)); static const Word magic256Default = Word (256); static const Word headerFromTopDefault = Word (Inch2Twip (0.75)); static const Word footerFromTopDefault = Word (Inch2Twip (10.25 /*11.0 (m_pageHeight) - 0.75*/)); static const Word magic720Default = Word (720); static const Word zeroDefault = Word (0); static const Word magic1080Default = Word (1080); // no reliable default for m_unknown static const Word zero2Default = Word (0); public: PageLayout (); virtual ~PageLayout (); PageLayout &operator= (const PageLayout &rhs); bool getIsModified (void) const { return m_numModified > 0; } #define PageLayoutModify(variable,value) \ { \ if (m_##variable != value) /* don't skew m_numModified count */ \ { \ if (value == variable##Default) \ --m_numModified; \ else \ m_numModified++; \ m_##variable = value; \ } \ } Word getPageNumberStart (const bool purist = false) const { if (purist) return m_pageNumberStart; if (m_pageNumberStart == Word (0xFFFF)) return 1; else return m_pageNumberStart; } void setPageNumberStart (const Word val) { PageLayoutModify (pageNumberStart, val); } // // since these are calculated values, // there can't be corresponding set functions // (how do I know what value you want to change?) // Word getBottomMargin (void) const { return getPageHeight () - getTopMargin () - getTextHeight (); } Word getRightMargin (void) const { return getPageWidth () - getLeftMargin () - getTextWidth (); } // // get and set functions (could not generated because we want to keep a // "modified" counter) // Word getPageHeight (void) const { return m_pageHeight; } void setPageHeight (const Word val) { PageLayoutModify (pageHeight, val); } Word getPageWidth (void) const { return m_pageWidth; } void setPageWidth (const Word val) { PageLayoutModify (pageWidth, val); } Word getTopMargin (void) const { return m_topMargin; } void setTopMargin (const Word val) { PageLayoutModify (topMargin, val); } Word getTextHeight (void) const { return m_textHeight; } void setTextHeight (const Word val) { PageLayoutModify (textHeight, val); } Word getLeftMargin (void) const { return m_leftMargin; } void setLeftMargin (const Word val) { PageLayoutModify (leftMargin, val); } Word getTextWidth (void) const { return m_textWidth; } void setTextWidth (const Word val) { PageLayoutModify (textWidth, val); } Word getHeaderFromTop (void) const { return m_headerFromTop; } void setHeaderFromTop (const Word val) { PageLayoutModify (headerFromTop, val); } Word getFooterFromTop (void) const { return m_footerFromTop; } void setFooterFromTop (const Word val) { PageLayoutModify (footerFromTop, val); } }; class Font : public FontGenerated { private: Byte *m_name; friend class FontTable; bool readFromDevice (void); bool writeToDevice (void); public: enum Family { DontCare = 0x00, Roman = 0x10, Times = 0x10, Serif = 0x10, Swiss = 0x20, Helvetica = 0x20, SansSerif = 0x20, Modern = 0x30, Courier = 0x30, TypeWriter = 0x30, Script = 0x40, Decorative = 0x50, OldEnglish = 0x50 }; Font (const Byte *name = NULL, const Byte family = DontCare); virtual ~Font (); Font &operator= (const Font &rhs); Byte *getName (void) const { return m_name; } Byte *setName (const Byte *s) { #if 0 // TODO fix #ifdef CHECK_INTERNAL if (!m_device) CHECK_DEVICE_ERROR; #endif if (!s) { m_device->error (Error::InternalError, "NULL fontName passed to Font::setName\n"); return m_name = NULL; } #endif int length = strlen ((const char *) s) + 1 /* NUL */; delete [] m_name; m_name = new Byte [length]; if (!m_name) m_device->error (Error::OutOfMemory, "could not allocate memory for fontName\n"); else strcpy ((char *) m_name, (const char *) s); FontGenerated::m_numDataBytes = sizeof (m_family) + length; return m_name; } bool operator!= (const Font &rhs) { // if their m_family's are different, it's not my problem... return strcmp ((const char *) this->m_name, (const char *) rhs.m_name) != 0; } bool operator== (const Font &rhs) { // if their m_family's are different, it's not my problem... return strcmp ((const char *) this->m_name, (const char *) rhs.m_name) == 0; } private: Font (const Font &rhs); }; class FontTable; // from structures_private.h class FormatCharProperty : public FormatCharPropertyGenerated { private: DWord m_afterEndCharByte; // from the FormatPointer that points to us FontTable *m_fontTable; // pointer to fontTable (valid only during & after FormatInfoPage::(readFromDevice|add)) Font m_font; // temporarily store font until we get the fontTable Word getFontCode (void) const { return ((Word) getFontCodeLow ()) | (((Word) getFontCodeHigh ()) << 6); } void setFontCode (const Word code) { setFontCodeHigh ((code >> 6) & BitMask3); // OPT: I don't think we really need & BitMask3 setFontCodeLow (code & BitMask6); } friend class FormatInfoPage; friend class FormatInfo; friend class InternalParser; friend class InternalGenerator; bool readFromDevice (void); bool writeToDevice (void); void setFontTable (FontTable *fontTable) { m_fontTable = fontTable; } DWord getAfterEndCharByte (void) const { return m_afterEndCharByte; } void setAfterEndCharByte (const DWord b) { m_afterEndCharByte = b; } // convenience functions DWord getEndCharByte (void) const { return m_afterEndCharByte - 1; } void setEndCharByte (const DWord b) { m_afterEndCharByte = b + 1; } public: FormatCharProperty (); virtual ~FormatCharProperty (); FormatCharProperty &operator= (const FormatCharProperty &rhs); const Font *getFont (void) const { return &m_font; } void setFont (const Font *font) { m_font = *font; } // [PRIVATE] called by FormatCharProperty::readFromDevice and other places too bool updateFont (void); // [PRIVATE] called by FormatInfoPage::add bool updateFontCode (void); Byte getFontSizeHalfPoints (void) const { return m_fontSize; } void setFontSizeHalfPoints (const Byte val) { m_fontSize = val; signalHaveSetData (m_fontSize == fontSizeDefault, (2 * 8)/*offset*/ + (1 * 8)/*size*/); } // loss of accuracy but look, would you prefer it in half-points or twips instead? :) Byte getFontSize (void) const { return getFontSizeHalfPoints () / 2; } void setFontSize (const Byte val) { setFontSizeHalfPoints (val * 2); } bool getIsNormalPosition (void) const { return getPosition () == 0; } void setIsNormalPosition (void) { setPosition (0); } bool getIsSuperscript (void) const { return getPosition () >= 1 && getPosition () <= 127; } void setIsSuperscript (void) { setPosition (4); /* common value (sometimes 10, but) */ } bool getIsSubscript (void) const { return getPosition () >= 128; } void setIsSubscript (void) { setPosition (252); /* common value */ } // compares if the contents are the same (not if it points to the same place etc. etc.) bool operator== (FormatCharProperty &rhs); }; class FormatParaPropertyTabulator : public FormatParaPropertyTabulatorGenerated { private: friend class FormatParaPropertyGenerated; friend class FormatParaProperty; bool readFromDevice (void); bool writeToDevice (void); public: FormatParaPropertyTabulator (); virtual ~FormatParaPropertyTabulator (); FormatParaPropertyTabulator &operator= (const FormatParaPropertyTabulator &rhs); // you can use getType()/setType() if you really want to... bool getIsNormal (void) const { return m_type == 0; } void setIsNormal (const bool yes = true) { m_type = (yes ? 0 : 3); } bool getIsDecimal (void) const { return m_type == 3; } void setIsDecimal (const bool yes = true) { m_type = (yes ? 3 : 0); } // is this a sentinel tabulator? bool getIsDummy (void) const { return m_indent == 0; } }; class Alignment { public: static const int Left = 0; static const int Centre = 1; static const int Center = 1; static const int Right = 2; static const int Justify = 3; }; // lazy synonym class Align : public Alignment {}; class LineSpacing { public: static const int Normal = 240; static const int Single = 240; static const int OneAndAHalf = 360; static const int Double = 480; }; class FormatParaProperty : public FormatParaPropertyGenerated { private: DWord m_afterEndCharByte; // from the FormatPointer that points to us Word m_leftMargin, m_rightMargin; // needed to adjust leftIndent & rightIndent in header/footer int m_numTabulators; bool m_addedTooManyTabs; friend class FormatInfoPage; friend class FormatInfo; friend class InternalParser; friend class InternalGenerator; bool readFromDevice (void); bool writeToDevice (void); void setMargins (const Word leftMargin, const Word rightMargin) { m_leftMargin = leftMargin; m_rightMargin = rightMargin; } DWord getAfterEndCharByte (void) const { return m_afterEndCharByte; } void setAfterEndCharByte (const DWord b) { m_afterEndCharByte = b; } // convenience functions DWord getEndCharByte (void) const { return m_afterEndCharByte - 1; } void setEndCharByte (const DWord b) { m_afterEndCharByte = b + 1; } public: FormatParaProperty (); virtual ~FormatParaProperty (); FormatParaProperty &operator= (const FormatParaProperty &rhs); // convenience functions Byte getAlign (void) const { return getAlignment (); } void setAlign (const Byte val) { setAlignment (val); } Short getLeftIndentFirstLine (const bool purist = false) const { // Write _always_ ignores "First Line Indent" if it's an object if (getIsObject () && !purist) { #ifdef DEBUG_PARA if (m_leftIndentFirstLine) #ifdef CHECK_INTERNAL if (m_device) #endif m_device->debug ("user specified leftIndentFirstLine for an object=", m_leftIndentFirstLine); #ifdef CHECK_INTERNAL else CHECK_DEVICE_ERROR; #endif #endif return 0; } else return m_leftIndentFirstLine; } void setLeftIndentFirstLine (const Word val) { m_leftIndentFirstLine = val; signalHaveSetData (m_leftIndentFirstLine == leftIndentFirstLineDefault, 8 * 8/*offset*/ + 2 * 8/*size*/); } // [PRIVATE] called by FormatInfoPage::add bool updateIndents (void) { if (getIsNotNormalParagraph ()) { m_leftIndent += m_leftMargin; m_rightIndent += m_rightMargin; } return true; } bool getIsText (void) const { return !getIsObject (); } void setIsText (const bool val) { setIsObject (!val); } bool getIsNormalParagraph (void) const { return !getIsNotNormalParagraph (); } void setIsNormalParagraph (const bool val = true) { setIsNotNormalParagraph (!val); } bool getIsHeader (void) const { return getIsNotNormalParagraph () && getHeaderOrFooter () == 0; } void setIsHeader (const bool val) { setIsNormalParagraph (false); setHeaderOrFooter (val ? 0 : 1); } bool getIsFooter (void) const { return getIsNotNormalParagraph () && getHeaderOrFooter () == 1; } void setIsFooter (const bool val) { setIsNormalParagraph (false); setHeaderOrFooter (val ? 1 : 0); } Word getNumTabulator (void) const { return m_numTabulators; } const FormatParaPropertyTabulator *getTabulator (const int which) const { if (which > m_numTabulators) return NULL; return m_tab [which]; } bool addTabulator (FormatParaPropertyTabulator *fpp) { if (m_numTabulators >= 14) { // we can't return false yet because there may be no m_device // so we will return false in writeToDevice() instead m_addedTooManyTabs = true; return true; } *m_tab [m_numTabulators++] = *fpp; // OPT: could use fewer bytes if Tabulator can do so signalHaveSetData (false/*probably not default*/, (22 + m_numTabulators * FormatParaPropertyTabulator::s_size) * 8); return true; } // compares if the contents are the same (not if it points to the same place etc. etc.) bool operator== (FormatParaProperty &rhs); }; class ObjectType { public: static const int NotObject = 0; static const int Bitmap = 1, BMP = 1; static const int WindowsMetaFile = 2, WMF = 2; static const int OLE = 3; }; class Image : public ImageGenerated { private: Byte *m_externalImage; DWord m_externalImageSize; DWord m_externalImageUpto; // image dimensions in twips double m_originalWidth, m_originalHeight; double m_displayedWidth, m_displayedHeight; static int getBytesPerScanLine (const int width, const int bitsPerPixel, const int padBytes); // these read and write an image stored in .WRI format bool readFromDevice (void); friend class InternalGenerator; bool writeToDevice (void); friend class InternalParser; public: Image (); virtual ~Image (); Image &operator= (const Image &rhs); bool getIsWMF (void) const { return m_mappingMode != 0xE3; } bool getIsBMP (void) const { return m_mappingMode == 0xE3; } // 0x88 is a common value for WMFs void setIsWMF (const bool yes = true) { yes ? m_mappingMode = 0x88 : m_mappingMode = 0xE3; } void setIsBMP (const bool yes = true) { yes ? m_mappingMode = 0xE3 : m_mappingMode = 0x88; } double getOriginalWidth (void) const { return m_originalWidth; } void setOriginalWidth (const double val) { m_originalWidth = val; } double getOriginalHeight (void) const { return m_originalHeight; } void setOriginalHeight (const double val) { m_originalHeight = val; } double getDisplayedWidth (void) const { return m_displayedWidth; } void setDisplayedWidth (const double val) { m_displayedWidth = val; } double getDisplayedHeight (void) const { return m_displayedHeight; } void setDisplayedHeight (const double val) { m_displayedHeight = val; } // these read and write an image stored in an external format Byte *getExternalImage (void) const { return m_externalImage; } DWord getExternalImageSize (void) const { return m_externalImageSize; } bool setExternalImage (const Byte *data, const DWord size) { CHECK_DEVICE; if (!m_externalImage) { m_externalImage = new Byte [m_externalImageSize]; if (!m_externalImage) ErrorAndQuit (Error::OutOfMemory, "could not allocate memory for external image\n"); } if (m_externalImageUpto + size > m_externalImageSize) { Dump (externalImageUpto); m_device->debug ("\tsize: ", size); Dump (externalImageSize); ErrorAndQuit (Error::InternalError, "user overflowed setExternalImage(); attempt to write too much binary data\n"); } memcpy (m_externalImage + m_externalImageUpto, data, size); m_externalImageUpto += size; return true; } bool setExternalImageSize (const DWord externalImageSize) { m_externalImageSize = externalImageSize; m_externalImageUpto = 0; return true; } }; class OLEType { public: static const int Static = 1; static const int Embedded = 2; static const int Link = 3; }; class OLE : public OLEGenerated { private: Byte *m_externalObject; DWord m_externalObjectSize; DWord m_externalObjectUpto; // these read and write OLE stored in .WRI format bool readFromDevice (void); friend class InternalGenerator; bool writeToDevice (void); friend class InternalParser; public: OLE (); virtual ~OLE (); OLE &operator= (const OLE &rhs); Byte *getExternalObject (void) const { return m_externalObject; } DWord getExternalObjectSize (void) const { return m_externalObjectSize; } bool setExternalObject (const Byte *data, const DWord size) { CHECK_DEVICE; if (!m_externalObject) { m_externalObject = new Byte [m_externalObjectSize]; if (!m_externalObject) ErrorAndQuit (Error::OutOfMemory, "could not allocate memory for external object\n"); } if (m_externalObjectUpto + size > m_externalObjectSize) { Dump (externalObjectUpto); m_device->debug ("\tsize: ", size); Dump (externalObjectSize); ErrorAndQuit (Error::InternalError, "user overflowed setExternalObject (); attempt to write too much binary data\n"); } memcpy (m_externalObject + m_externalObjectUpto, data, size); m_externalObjectUpto += size; return true; } bool setExternalObjectSize (const DWord externalObjectSize) { m_externalObjectSize = externalObjectSize; m_externalObjectUpto = 0; return true; } }; } // namespace MSWrite { #endif // __STRUCTURES_H__ // end of structures.h