You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
koffice/filters/kword/mswrite/structures.h

631 lines
18 KiB

/* This file is part of the LibMSWrite Library
Copyright (C) 2001-2003 Clarence Dang <clarencedang@users.sourceforge.net>
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