filters

structures_private.cpp

00001 /* This file is part of the LibMSWrite Library
00002    Copyright (C) 2001-2003 Clarence Dang <clarencedang@users.sourceforge.net>
00003 
00004    This library is free software; you can redistribute it and/or
00005    modify it under the terms of the GNU Library General Public
00006    License Version 2 as published by the Free Software Foundation.
00007 
00008    This library is distributed in the hope that it will be useful,
00009    but WITHOUT ANY WARRANTY; without even the implied warranty of
00010    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00011    Library General Public License Version 2 for more details.
00012 
00013    You should have received a copy of the GNU Library General Public License
00014    Version 2 along with this library; see the file COPYING.LIB.  If not,
00015    write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
00016  * Boston, MA 02110-1301, USA.
00017 
00018    LibMSWrite Project Website:
00019    http://sourceforge.net/projects/libmswrite/
00020 */
00021 
00022 /*
00023  * structures_private.cpp - Process Internal Microsoft(r) Write file structures
00024  *                        - that are hidden/abstracted away from the user
00025  * This file has ugly reading/writing code that couldn't be generated.
00026  * It performs some higher-level sanity checks.
00027  *
00028  * Don't use any of these classes as it would defeat the purpose of LibMSWrite.
00029  */
00030 
00031 #include "structures_private.h"
00032 #include "structures.h"
00033 
00034 namespace MSWrite
00035 {
00036     Header::Header ()
00037     {
00038     }
00039 
00040     Header::~Header ()
00041     {
00042     }
00043 
00044     Header &Header::operator= (const Header &rhs)
00045     {
00046         if (this == &rhs)
00047             return *this;
00048 
00049         HeaderGenerated::operator= (rhs);
00050 
00051         m_numCharBytes = rhs.m_numCharBytes;
00052         m_pageCharInfo = rhs.m_pageCharInfo;
00053 
00054         return *this;
00055     }
00056 
00057     bool Header::readFromDevice (void)
00058     {
00059     CHECK_DEVICE;
00060 
00061     #ifdef DEBUG_HEADER
00062         m_device->debug ("\n<<<< Header::readFromDevice >>>>\n");
00063     #endif
00064 
00065         if (!m_device->seekInternal (0, SEEK_SET)) return false;
00066         if (!HeaderGenerated::readFromDevice ()) return false;
00067 
00068     #ifdef DEBUG_HEADER
00069         switch (m_magic)
00070         {
00071         case 0xBE31:    m_device->debug ("normal write file\n");    break;
00072         case 0xBE32:    m_device->debug ("write file with OLE\n");  break;
00073         default:    ErrorAndQuit (Error::InternalError, "magic test passed but failed later?");
00074         }
00075     #endif
00076 
00077         m_numCharBytes = m_numCharBytesPlus128 - 128;
00078 
00079     #ifdef DEBUG_HEADER
00080         m_device->debug ("num bytes of data (text+images+OLE): ", m_numCharBytes);
00081         m_device->debug ("page # start of parainfo: ", m_pageParaInfo);
00082         m_device->debug ("page # footnote table: ", m_pageFootnoteTable);
00083         m_device->debug ("page # pageLayout: ", m_pageSectionProperty);
00084         m_device->debug ("page # sectionTable: ", m_pageSectionTable);
00085         m_device->debug ("page # pageTable: ", m_pagePageTable);
00086         m_device->debug ("page # fontTable: ", m_pageFontTable);
00087         m_device->debug ("num pages in file: ", m_numPages);
00088     #endif
00089 
00090         /*
00091          * more checks
00092          */
00093 
00094         // footnoteTables simply do not exist...
00095         if (m_pageFootnoteTable != m_pageSectionProperty)
00096             ErrorAndQuit (Error::InvalidFormat, "document should not have a footnoteTable\n");
00097 
00098 
00099         // cannot have a sectionProperty without a sectionTable or vice-versa
00100 
00101         // no sectionProperty?
00102         if (m_pageSectionProperty == m_pagePageTable)
00103         {
00104             // must not have a sectionTable then
00105             if (m_pageSectionTable != m_pagePageTable)
00106                 ErrorAndQuit (Error::InvalidFormat, "sectionTable without sectionProperty\n");
00107         }
00108         // have sectionProperty...
00109         else
00110         {
00111             if (m_pageSectionTable != m_pageSectionProperty + 1)
00112                 ErrorAndQuit (Error::InvalidFormat, "sectionTable not immediately after sectionProperty\n");
00113 
00114             if (m_pageSectionTable == m_pagePageTable)
00115                 ErrorAndQuit (Error::InvalidFormat, "sectionProperty without sectionTable\n");
00116         }
00117 
00118         // charInfo page comes immediately after the header and text
00119         m_pageCharInfo = (m_numCharBytesPlus128 + 127) / 128;
00120 
00121     #ifdef DEBUG_HEADER
00122         m_device->debug ("page # start of charinfo: ", m_pageCharInfo);
00123     #endif
00124 
00125         // catches a lot of corrupted files
00126         if (m_pageCharInfo > m_pageParaInfo)
00127             ErrorAndQuit (Error::InvalidFormat, "charInfo page after paraInfo page\n");
00128 
00129         return true;
00130     }
00131 
00132     bool Header::writeToDevice (void)
00133     {
00134     CHECK_DEVICE;
00135 
00136     #ifdef DEBUG_HEADER
00137         m_device->debug ("\n<<<< Header::writeToDevice >>>>\n");
00138     #endif
00139 
00140         m_numCharBytesPlus128 = m_numCharBytes + 128;
00141 
00142         if (!m_device->seekInternal (0, SEEK_SET)) return false;
00143         if (!HeaderGenerated::writeToDevice ()) return false;
00144 
00145         return true;
00146     }
00147 
00148 
00149     SectionDescriptor::SectionDescriptor ()
00150     {
00151     }
00152 
00153     SectionDescriptor::~SectionDescriptor ()
00154     {
00155     }
00156 
00157     SectionDescriptor &SectionDescriptor::operator= (const SectionDescriptor &rhs)
00158     {
00159         if (this == &rhs)
00160             return *this;
00161 
00162         SectionDescriptorGenerated::operator= (rhs);
00163 
00164         return *this;
00165     }
00166 
00167 
00168     SectionTable::SectionTable ()
00169     {
00170     }
00171 
00172     SectionTable::~SectionTable ()
00173     {
00174     }
00175 
00176     SectionTable &SectionTable::operator= (const SectionTable &rhs)
00177     {
00178         if (this == &rhs)
00179             return *this;
00180 
00181         SectionTableGenerated::operator= (rhs);
00182         NeedsHeader::operator= (rhs);
00183 
00184         return *this;
00185     }
00186 
00187     // this function really only does some sanity checking
00188     // in fact, a SectionTable is quite useless in Write...
00189     // ...so you actually don't have to call it :)
00190     bool SectionTable::readFromDevice (void)
00191     {
00192     CHECK_DEVICE;
00193 
00194     #ifdef DEBUG_PAGELAYOUT
00195         m_device->debug ("\n<<<< SectionTable::readFromDevice >>>>\n");
00196     #endif
00197 
00198         int numSectionTablePages = m_header->getNumPageSectionTable ();
00199 
00200     #ifdef DEBUG_PAGELAYOUT
00201         m_device->debug ("num sectionTablePages=", numSectionTablePages);
00202     #endif
00203 
00204         // no SectionTable
00205         if (numSectionTablePages == 0)
00206             return true;
00207         else if (numSectionTablePages > 1)
00208             ErrorAndQuit (Error::InvalidFormat, "invalid #sectionTablePages\n");
00209 
00210         // seek to the SectionTable in the file
00211         if (!m_device->seekInternal (m_header->getPageSectionTable () * 128, SEEK_SET))
00212             return false;
00213 
00214         if (!SectionTableGenerated::readFromDevice ()) return false;
00215 
00216     #ifdef DEBUG_PAGELAYOUT
00217         m_device->debug ("num sectionDescriptors=", m_numSectionDescriptors);
00218         for (int i = 0; i < 2; i++)
00219         {
00220             m_device->debug ("Dumping SED #", i);
00221                 m_device->debug ("\tbyte after section=", m_sed [i]->getAfterEndCharByte ());
00222                 m_device->debug ("\tsectionProperty location=", m_sed [i]->getSectionPropertyLocation ());
00223         }
00224     #endif
00225 
00226         if (m_numSectionDescriptors != 2)
00227             m_device->error (Error::Warn, "#sectionDescriptors != 2, ignoring");
00228 
00229         // check that 1st SectionDescriptor covers all characters
00230         if (m_sed [0]->getAfterEndCharByte () != m_header->getNumCharBytes ())
00231             m_device->error (Error::Warn, "sectionDescriptor #1 does not cover entire document\n");
00232 
00233         // check that 1st SectionDescriptor points to the SectionProperty
00234         if (m_sed [0]->getSectionPropertyLocation () != m_header->getPageSectionProperty () * DWord (128))
00235             m_device->error (Error::Warn, "sectionDescriptor #1 does not refer to correct sectionProperty, ignoring\n");
00236 
00237         // check that 2nd SectionDescriptor covers after the end of the document
00238         if (m_sed [1]->getAfterEndCharByte () != m_header->getNumCharBytes () + 1)
00239             m_device->error (Error::Warn, "sectionDescriptor #2 does not cover post-document\n");
00240 
00241         // check that 2nd SectionDescriptor is indeed a dummy
00242         if (m_sed [1]->getSectionPropertyLocation () != (DWord) 0xFFFFFFFF)
00243             m_device->error (Error::Warn, "sectionDescriptor #2 is not a dummy\n");
00244 
00245         return true;
00246     }
00247 
00248     bool SectionTable::writeToDevice (const bool needed)
00249     {
00250     CHECK_DEVICE;
00251 
00252     #ifdef DEBUG_PAGELAYOUT
00253         m_device->debug ("\n>>>> SectionTable::writeToDevice <<<<\n");
00254     #endif
00255 
00256         m_header->setPageSectionTable (m_device->tellInternal () / 128);
00257 
00258         // if no sectionProperty, no sectionTable
00259         if (!needed)
00260             return true;
00261 
00262 
00263         // set that 1st SectionDescriptor covers all characters
00264         m_sed [0]->setAfterEndCharByte (m_header->getNumCharBytes ());
00265 
00266         // set that 1st SectionDescriptor points to the SectionProperty
00267         m_sed [0]->setSectionPropertyLocation (m_header->getPageSectionProperty () * 128);
00268 
00269         // set that 2nd SectionDescriptor covers after the end of the document
00270         m_sed [1]->setAfterEndCharByte (m_header->getNumCharBytes () + 1);
00271 
00272         // set that 2nd SectionDescriptor is indeed a dummy
00273         m_sed [1]->setSectionPropertyLocation ((DWord) 0xFFFFFFFF);
00274 
00275         if (!SectionTableGenerated::writeToDevice ())
00276             return false;
00277 
00278         return true;
00279     }
00280 
00281 
00282     FontTable::FontTable ()
00283     {
00284     }
00285 
00286     FontTable::~FontTable ()
00287     {
00288     }
00289 
00290     FontTable &FontTable::operator= (const FontTable &rhs)
00291     {
00292         if (this == &rhs)
00293             return *this;
00294 
00295         FontTableGenerated::operator= (rhs);
00296         NeedsHeader::operator= (rhs);
00297 
00298         m_fontList = rhs.m_fontList;
00299 
00300         return *this;
00301     }
00302 
00303     bool FontTable::readFromDevice (void)
00304     {
00305     CHECK_DEVICE;
00306 
00307     #ifdef DEBUG_FONT
00308         m_device->debug ("\n<<<< FontTable::readFromDevice >>>>\n");
00309     #endif
00310 
00311         int numFontTablePages = m_header->getNumPageFontTable ();
00312 
00313         // no FontTable
00314         if (numFontTablePages == 0)
00315             return true;
00316 
00317         // seek to the fontTable in the file
00318         if (!m_device->seekInternal (m_header->getPageFontTable () * 128, SEEK_SET))
00319             return false;
00320 
00321         if (!FontTableGenerated::readFromDevice ()) return false;
00322 
00323     #ifdef DEBUG_FONT
00324         m_device->debug ("num Fonts: ", m_numFonts);
00325     #endif
00326 
00327         bool dontAddToBack = false;
00328         for (int i = 0; i < FontTableGenerated::m_numFonts; i++)
00329         {
00330         #ifdef DEBUG_FONT
00331             m_device->debug ("Font: ", i);
00332         #endif
00333 
00334             if (!dontAddToBack)
00335             {
00336                 if (!m_fontList.addToBack ())
00337                     ErrorAndQuit (Error::OutOfMemory, "could not add Font to fontList\n");
00338             }
00339             else
00340                 dontAddToBack = false;
00341 
00342             List <Font>::Iterator it = m_fontList.begin (false);
00343             Font &font = *it;
00344 
00345             // read font
00346             font.setDevice (m_device);
00347             if (!font.readFromDevice ())
00348             {
00349                 // a real error...
00350                 if (m_device->bad ())
00351                     return false;
00352 
00353                 //
00354                 // ... or Font::readFromDevice() signalled something
00355                 //
00356 
00357                 // font is on next page?
00358                 if (font.getNumDataBytes () == 0xFFFF)
00359                 {
00360                 #ifdef DEBUG_FONT
00361                     m_device->debug ("\tcurrent offset=", m_device->tellInternal ());
00362                     m_device->debug ("\tnext page offset=", (m_device->tellInternal () + 127) / 128 * 128);
00363                 #endif
00364 
00365                     // seek to next page
00366                     if (!m_device->seekInternal ((m_device->tellInternal () + 127) / 128 * 128, SEEK_SET))
00367                         return false;
00368                     --i;    // still reading the same font
00369                     dontAddToBack = true;   // don't need to add another font, just re-use this sentinel
00370                     continue;
00371                 }
00372 
00373                 // no more entries (should _not_ get in here)?
00374                 if (font.getNumDataBytes () == 0)
00375                 {
00376                     if (i != m_numFonts - 1)    // actually, this check isn't required
00377                         m_device->error (Error::Warn, "font marked as last but is not\n");
00378 
00379                     // let's not cause problems later with uninitialised Font::m_name's
00380                     m_fontList.erase (it);
00381 
00382                     // better quit just in case (it is better to have fewer fonts than risk errors)
00383                     break;
00384                 }
00385             }
00386         }   // for (int i = 0; i < m_numFonts; i++) {
00387 
00388         return true;
00389     }
00390 
00391     bool FontTable::writeToDevice (void)
00392     {
00393     CHECK_DEVICE;
00394 
00395     #ifdef DEBUG_FONT
00396         m_device->debug ("\n>>>> FontTable::writeToDevice <<<<\n");
00397     #endif
00398 
00399         // indicate fontTable page in header
00400         m_header->setPageFontTable (m_device->tellInternal () / 128);
00401 
00402         FontTableGenerated::m_numFonts = m_fontList.getNumElements ();
00403 
00404         // no fontTable
00405         if (FontTableGenerated::m_numFonts == 0)
00406         {
00407             m_device->error (Error::Warn, "not writing fontTable\n");
00408             return true;
00409         }
00410 
00411         // write numFonts
00412         if (!FontTableGenerated::writeToDevice ()) return false;
00413 
00414         int i = 0;
00415         for (List <Font>::Iterator it = m_fontList.begin ();
00416                 it != m_fontList.end ();
00417                 /* don't iterate here since we might "continue" with the same font */)
00418         {
00419         #ifdef DEBUG_FONT
00420             m_device->debug ("\twriting font #", i);
00421         #endif
00422 
00423             Font &font = *it;
00424 
00425             // write font
00426             font.setDevice (m_device);
00427             if (!font.writeToDevice ())
00428             {
00429                 // a real error...
00430                 if (m_device->bad ())
00431                     return false;
00432 
00433                 //
00434                 // ... or Font::readFromDevice() signalled something
00435                 //
00436 
00437                 // font is on next page then
00438             #ifdef DEBUG_FONT
00439                 m_device->debug ("\tcurrent offset=", m_device->tellInternal ());
00440                 m_device->debug ("\tnext page offset=", (m_device->tellInternal () + 127) / 128 * 128);
00441             #endif
00442 
00443                 // seek to next page
00444                 if (!m_device->seekInternal ((m_device->tellInternal () + 127) / 128 * 128, SEEK_SET))
00445                     return false;
00446 
00447                 // still writing the same font
00448                 continue;
00449             }
00450 
00451             // get next font to write
00452             it++;
00453             i++;
00454         }
00455 
00456         return true;
00457     }
00458 
00459     Font *FontTable::getFont (const DWord fontCode) const
00460     {
00461         // OPT: inefficient, maybe an array of pointers because we can't delete fonts anyway
00462         List <Font>::Iterator it = m_fontList.begin ();
00463         for (int i = 0; i < int (fontCode) && it != m_fontList.end (); i++, ++it)
00464             ;
00465         if (it == m_fontList.end ()) return NULL;
00466         return &(*it);
00467     }
00468 
00469     DWord FontTable::findFont (const Font *want) const
00470     {
00471         DWord code = 0;
00472 
00473         List <Font>::Iterator it;
00474         for (it = m_fontList.begin (); it != m_fontList.end (); ++it)
00475         {
00476             if ((*it) == *want)
00477                 return code;
00478 
00479             code++;
00480         }
00481 
00482         // couldn't find
00483         return 0xFFFFFFFF;
00484     }
00485 
00486     DWord FontTable::addFont (const Font *input)
00487     {
00488     CHECK_DEVICE;
00489 
00490     #ifdef DEBUG_FONT
00491         m_device->debug ("\t\t\tTrying to add Font ", input->getName ());
00492     #endif
00493 
00494         DWord e = findFont (input);
00495 
00496         // already in list
00497         if (e != 0xFFFFFFFF)
00498         {
00499         #ifdef DEBUG_FONT
00500             m_device->debug ("\t\t\t\tAlready in list, fontCode=", e);
00501         #endif
00502 
00503             // return fontCode
00504             return e;
00505         }
00506         // new font
00507         else
00508         {
00509         #ifdef DEBUG_FONT
00510             m_device->debug ("\t\t\t\tNew font, adding to list\n");
00511         #endif
00512 
00513             if (!m_fontList.addToBack (*input))
00514                 ErrorAndQuit (Error::OutOfMemory, "could not allocate memory for next font element\n");
00515             return m_fontList.getNumElements () - 1;
00516         }
00517     }
00518 
00519 
00520     PagePointer::PagePointer ()
00521     {
00522     }
00523 
00524     PagePointer::~PagePointer ()
00525     {
00526     }
00527 
00528     PagePointer &PagePointer::operator= (const PagePointer &rhs)
00529     {
00530         if (this == &rhs)
00531             return *this;
00532 
00533         PagePointerGenerated::operator= (rhs);
00534 
00535         return *this;
00536     }
00537 
00538     bool PagePointer::readFromDevice (void)
00539     {
00540     CHECK_DEVICE;
00541 
00542         if (!PagePointerGenerated::readFromDevice ())
00543             return false;
00544 
00545     #ifdef DEBUG_PAGETABLE
00546         m_device->debug ("\t\tpage number: ", m_pageNumber);
00547         m_device->debug ("\t\tfirst char: ", m_firstCharByte);
00548     #endif
00549 
00550         return true;
00551     }
00552 
00553     bool PagePointer::writeToDevice (void)
00554     {
00555     CHECK_DEVICE;
00556 
00557         if (!PagePointerGenerated::writeToDevice ())
00558             return false;
00559 
00560         return true;
00561     }
00562 
00563 
00564     PageTable::PageTable () : m_pageNumberStart (0xFFFF)
00565     {
00566     }
00567 
00568     PageTable::~PageTable ()
00569     {
00570     }
00571 
00572     PageTable &PageTable::operator= (const PageTable &rhs)
00573     {
00574         if (this == &rhs)
00575             return *this;
00576 
00577         PageTableGenerated::operator= (rhs);
00578         NeedsHeader::operator= (rhs);
00579 
00580         m_pagePointerList = rhs.m_pagePointerList;
00581         m_pageNumberStart = rhs.m_pageNumberStart;
00582 
00583         m_pageTableIterator = rhs.m_pageTableIterator;
00584 
00585         return *this;
00586     }
00587 
00588     bool PageTable::readFromDevice (void)
00589     {
00590     CHECK_DEVICE;
00591 
00592     #ifdef DEBUG_PAGETABLE
00593         m_device->debug ("\n<<<< PageTable::readFromDevice >>>>\n");
00594     #endif
00595 
00596     #ifdef CHECK_INTERNAL
00597         if (m_pageNumberStart == (Word) 0xFFFF || NeedsHeader::m_header == NULL)
00598             ErrorAndQuit (Error::InternalError, "PageTable call not setup\n");
00599     #endif
00600 
00601         // no pageTable
00602         if (m_header->getNumPagePageTable () == 0)
00603             return true;
00604 
00605         // seek to the pageTable in the file
00606         if (!m_device->seekInternal (m_header->getPagePageTable () * 128, SEEK_SET))
00607             return false;
00608 
00609         if (!PageTableGenerated::readFromDevice ())
00610             return false;
00611 
00612     #ifdef DEBUG_PAGETABLE
00613         Dump (numPagePointers);
00614         Dump (zero);
00615     #endif
00616 
00617         DWord lastCharByte = (DWord) 0xFFFFFFFF;
00618         Word lastPage = (Word) 0xFFFF;  // do not have to init
00619         for (int i = 0; i < m_numPagePointers; i++)
00620         {
00621             if (!m_pagePointerList.addToBack ())
00622                 ErrorAndQuit (Error::OutOfMemory, "could not add pagePointer to list\n");
00623 
00624             PagePointer &pp = *m_pagePointerList.begin (false);
00625 
00626         #ifdef DEBUG_PAGETABLE
00627             m_device->debug ("\tPagePointer: ", i);
00628         #endif
00629 
00630             // read pointer
00631             pp.setDevice (m_device);
00632             if (!pp.readFromDevice ()) return false;
00633 
00634             // first pointer?
00635             if (i == 0)
00636             {
00637                 if (pp.getPageNumber () != m_pageNumberStart)
00638                     ErrorAndQuit (Error::InvalidFormat, "pageTable & sectionProperty disagree on pageNumberStart\n");
00639             }
00640             else
00641             {
00642                 // according to KOffice 1.2:
00643                 //
00644                 // "the pageTable can get really out of sync with reality
00645                 //  if the user doesn't repaginate after deleting a few pages
00646                 //  -- so this is just a warning, not an error"
00647                 //
00648                 if (pp.getPageNumber () != lastPage + 1)
00649                     m_device->error (Error::Warn, "pages don't follow each other\n");
00650 
00651                 if (pp.getFirstCharByte () <= lastCharByte)
00652                     ErrorAndQuit (Error::InvalidFormat, "pageTable is not going forward?\n");
00653             }
00654 
00655             // for checking, on next iteration
00656             lastPage = pp.getPageNumber ();
00657             lastCharByte = pp.getFirstCharByte ();
00658         }
00659 
00660         return true;
00661     }
00662 
00663     bool PageTable::writeToDevice (void)
00664     {
00665     CHECK_DEVICE;
00666 
00667     #ifdef DEBUG_PAGETABLE
00668         m_device->debug ("\n>>>> PageTable::writeToDevice <<<<\n");
00669     #endif
00670 
00671         m_header->setPagePageTable (m_device->tellInternal () / 128);
00672 
00673         // LibMSWrite directly (!) adds to the list so m_numPagePointers may be out of date
00674         PageTableGenerated::m_numPagePointers = m_pagePointerList.getNumElements ();
00675 
00676         // no pageTable
00677         if (m_numPagePointers == 0)
00678             return true;
00679 
00680         // write numPagePointers, zero
00681         if (!PageTableGenerated::writeToDevice ())
00682             return false;
00683 
00684         int i = 0;
00685         List <PagePointer>::Iterator it;
00686         for (it = m_pagePointerList.begin (); it != m_pagePointerList.end (); ++it, i++)
00687         {
00688             PagePointer &pp = (*it);
00689 
00690         #ifdef DEBUG_PAGETABLE
00691             m_device->debug ("\tPagePointer: ", i);
00692         #endif
00693 
00694             // read page pointer
00695             pp.setDevice (m_device);
00696             if (!pp.writeToDevice ())
00697                 return false;
00698         }
00699 
00700         return true;
00701     }
00702 
00703 
00704     FormatPointer::FormatPointer () : m_afterEndCharByte (0)
00705     {
00706     }
00707 
00708     FormatPointer::~FormatPointer ()
00709     {
00710     }
00711 
00712     FormatPointer &FormatPointer::operator= (const FormatPointer &rhs)
00713     {
00714         if (this == &rhs)
00715             return *this;
00716 
00717         FormatPointerGenerated::operator= (rhs);
00718 
00719         m_afterEndCharByte = rhs.m_afterEndCharByte;
00720         m_formatProperty = rhs.m_formatProperty;
00721 
00722         return *this;
00723     }
00724 
00725     bool FormatPointer::readFromDevice (void)
00726     {
00727     CHECK_DEVICE;
00728 
00729         if (!FormatPointerGenerated::readFromDevice ())
00730             return false;
00731 
00732         m_afterEndCharByte = m_afterEndCharBytePlus128 - 128;
00733 
00734     #ifdef DEBUG_FORMATINFO
00735         m_device->debug ("\t\tafterEndCharByte: ", m_afterEndCharByte);
00736         m_device->debug ("\t\tformatPropertyOffset: ", m_formatPropertyOffset);
00737     #endif
00738 
00739         return true;
00740     }
00741 
00742     bool FormatPointer::writeToDevice (void)
00743     {
00744     CHECK_DEVICE;
00745 
00746     #ifdef DEBUG_FORMATINFO
00747         m_device->debug ("\t\t\t\tafterEndCharByte: ", m_afterEndCharByte);
00748         m_device->debug ("\t\t\t\tformatPropertyOffset: ", m_formatPropertyOffset);
00749     #endif
00750 
00751         m_afterEndCharBytePlus128 = m_afterEndCharByte + 128;
00752 
00753         if (!FormatPointerGenerated::writeToDevice ())
00754             return false;
00755 
00756         return true;
00757     }
00758 
00759 
00760     FormatInfoPage::FormatInfoPage () : m_firstCharByte (0),
00761                                                     m_formatPointer (NULL),
00762                                                     m_formatCharProperty (NULL),
00763                                                         m_fontTable (NULL),
00764                                                     m_formatParaProperty (NULL),
00765                                                         m_leftMargin (0xFFFF), m_rightMargin (0xFFFF),
00766                                                     m_formatPointerUpto (0),
00767                                                     m_nextCharByte (0),
00768                                                     m_formatPointerPos (0), m_formatPropertyPos (123)
00769     {
00770         // m_type=
00771         // m_lastPropertyOffset=
00772         // m_numProperty=
00773     }
00774 
00775     FormatInfoPage::~FormatInfoPage ()
00776     {
00777         delete [] m_formatParaProperty;
00778         delete [] m_formatCharProperty;
00779         delete [] m_formatPointer;
00780     }
00781 
00782 
00783     bool FormatInfoPage::readFromDevice (void)
00784     {
00785     CHECK_DEVICE;
00786 
00787     #ifdef DEBUG_FORMATINFO
00788         if (m_type == ParaType)
00789             m_device->debug ("FormatInfoPage::readFromDevice (ParaType)\n");
00790         else    // if (m_type == CharType)
00791             m_device->debug ("FormatInfoPage::readFromDevice (CharType)\n");
00792     #endif
00793 
00794         if (!FormatInfoPageGenerated::readFromDevice ())
00795             return false;
00796 
00797         m_firstCharByte = FormatInfoPageGenerated::m_firstCharBytePlus128 - 128;
00798 
00799     #ifdef DEBUG_FORMATINFO
00800         m_device->debug ("number of FormatPointers on this page: ", FormatInfoPageGenerated::m_numFormatPointers);
00801         m_device->debug ("byte number of first character covered by this page: ", m_firstCharByte);
00802     #endif
00803 
00804         return true;
00805     }
00806 
00807     bool FormatInfoPage::writeToDevice (void)
00808     {
00809     CHECK_DEVICE;
00810 
00811     #ifdef DEBUG_FORMATINFO
00812         if (m_type == ParaType)
00813             m_device->debug ("FormatInfoPage::writeToDevice (ParaType)\n");
00814         else    // if (m_type == CharType)
00815             m_device->debug ("FormatInfoPage::writeToDevice (CharType)\n");
00816     #endif
00817 
00818         FormatInfoPageGenerated::m_firstCharBytePlus128 = m_firstCharByte + 128;
00819 
00820     #ifdef DEBUG_FORMATINFO
00821         m_device->debug ("\tnumber of FormatPointers on this page: ", FormatInfoPageGenerated::m_numFormatPointers);
00822         m_device->debug ("\tbyte number of first character covered by this page: ", m_firstCharByte);
00823     #endif
00824 
00825         // will call FormatInfoPageGenerated::writeToArray()...
00826         // ...which will resolve to FormatInfoPage::writeToArray()...
00827         // which will then call the base FormatInfoPageGenerated::writeToArray()
00828         return FormatInfoPageGenerated::writeToDevice ();
00829     }
00830 
00831     bool FormatInfoPage::writeToArray (void)
00832     {
00833     CHECK_DEVICE;
00834 
00835     #ifdef DEBUG_FORMATINFO
00836         if (m_type == ParaType)
00837             m_device->debug ("\tFormatInfoPage::writeToArray (ParaType)\n");
00838         else    // if (m_type == CharType)
00839             m_device->debug ("\tFormatInfoPage::writeToArray (CharType)\n");
00840     #endif
00841 
00842         MemoryDevice memdev;
00843 
00844         m_formatPointerPos = 0;
00845         m_formatPropertyPos = 123;
00846 
00847     #ifdef DEBUG_FORMATINFO
00848         m_device->debug ("\t\tWriting FormatPointer[], num=", m_numFormatPointers);
00849     #endif
00850         for (int i = 0; i < m_numFormatPointers; i++)
00851         {
00852         #ifdef DEBUG_FORMATINFO
00853             m_device->debug ("\t\t\tOffset=", m_formatPointerPos);
00854         #endif
00855             // write FormatPointer
00856             memdev.setCache (m_packedStructs + m_formatPointerPos);
00857                 m_formatPointer [i].setDevice (&memdev);
00858                 if (!m_formatPointer [i].writeToDevice ()) return false;
00859             memdev.setCache (NULL);
00860             m_formatPointerPos += FormatPointer::s_size;
00861         }
00862 
00863     #ifdef DEBUG_FORMATINFO
00864         m_device->debug ("\t\tWriting FormatProperty[], num=", m_numProperty);
00865     #endif
00866         for (int i = 0; i < m_numProperty; i++)
00867         {
00868             // write FormatProperty
00869             if (m_type == ParaType)
00870             {
00871                 FormatParaProperty *prop = &m_formatParaProperty [i];
00872 
00873                 m_formatPropertyPos -= (sizeof (Byte) + prop->getNumDataBytes ());
00874                 memdev.setCache (m_packedStructs + m_formatPropertyPos);
00875                     prop->setDevice (&memdev);  // device was set to m_device to keep operator== happy in FormatInfoPage::add
00876                     if (!prop->writeToDevice ()) return false;
00877                 memdev.setCache (NULL);
00878             }
00879             else    // if (m_type == CharType)
00880             {
00881                 FormatCharProperty *prop = &m_formatCharProperty [i];
00882 
00883                 m_formatPropertyPos -= (sizeof (Byte) + prop->getNumDataBytes ());
00884                 memdev.setCache (m_packedStructs + m_formatPropertyPos);
00885                     prop->setDevice (&memdev);  // device was set to m_device to keep operator== happy in FormatInfoPage::add
00886                     if (!prop->writeToDevice ()) return false;
00887                 memdev.setCache (NULL);
00888             }
00889             #ifdef DEBUG_FORMATINFO
00890                 m_device->debug ("\t\t\tWrote at Offset=", m_formatPropertyPos);
00891             #endif
00892         }
00893 
00894         if (!FormatInfoPageGenerated::writeToArray ())
00895             return false;
00896 
00897         return true;
00898     }
00899 
00900     void *FormatInfoPage::begin (void)
00901     {
00902     CHECK_DEVICE;
00903 
00904     #ifdef DEBUG_FORMATINFO
00905         if (m_type == ParaType)
00906             m_device->debug ("\nFormatInfoPage::begin (ParaType)\n");
00907         else    // if (m_type == CharType)
00908             m_device->debug ("\nFormatInfoPage::begin (CharType)\n");
00909     #endif
00910 
00911         m_formatPointerUpto = 0;
00912         m_nextCharByte = 0; // for consistency checking
00913 
00914         m_lastPropertyOffset = -1;
00915 
00916         if (!m_formatPointer)
00917         {
00918             m_formatPointer = new FormatPointer [1];
00919 
00920             if (!m_formatPointer)
00921             {
00922                 m_device->error (Error::OutOfMemory, "could not allocate memory for FormatPointer\n");
00923                 return NULL;
00924             }
00925 
00926             m_formatPointer->setDevice (m_device);
00927         }
00928 
00929         return this->next ();
00930     }
00931 
00932     void *FormatInfoPage::next (void)
00933     {
00934         void *ret;
00935 
00936     #ifdef DEBUG_FORMATINFO
00937         if (m_type == ParaType)
00938             m_device->debug ("\tPara FormatPointer #", m_formatPointerUpto);
00939         else    // if (m_type == CharType)
00940             m_device->debug ("\tChar FormatPointer #", m_formatPointerUpto);
00941     #endif
00942 
00943 
00944         //
00945         // read Format Pointer
00946         //
00947 
00948         // check Format Pointer allocated
00949         if (!m_formatPointer)
00950         {
00951             m_device->error (Error::InternalError, "formatPointer not initialised - call FormatInfoPage::begin() before next()\n");
00952             return NULL;
00953         }
00954 
00955         // read next Format Pointer (fixed length)
00956         m_device->setCache (m_packedStructs + m_formatPointerUpto * FormatPointer::s_size);
00957         if (!m_formatPointer->readFromDevice ()) return NULL;
00958         m_device->setCache (NULL);
00959         DWord formatPointerAfterEndCharByte = m_formatPointer->getAfterEndCharByte ();
00960 
00961         // check that it continues on from the last
00962         if (formatPointerAfterEndCharByte <= m_nextCharByte)
00963             m_device->error (Error::Warn, "FormatPointer afterEndCharByte does not go forward\n");
00964         m_nextCharByte = formatPointerAfterEndCharByte;
00965 
00966         // check whether it is the last one (EOF-wise)
00967         if (formatPointerAfterEndCharByte >= m_header->getNumCharBytes ())
00968         {
00969         #ifdef DEBUG_FORMATINFO
00970             m_device->debug ("\t\tThis is the last FormatPointer!\n");
00971         #endif
00972 
00973             // past EOF?
00974             if (formatPointerAfterEndCharByte > m_header->getNumCharBytes ())
00975             {
00976                 m_device->error (Error::Warn, "FormatPointer ends after EOF, forcing it to end at EOF\n");
00977                 m_formatPointer->setAfterEndCharByte (m_header->getNumCharBytes ());
00978                 m_nextCharByte = m_header->getNumCharBytes ();
00979             }
00980 
00981             // but there are still more FormatPointers left?
00982             if (m_formatPointerUpto != m_numFormatPointers - 1)
00983             {
00984                 m_device->error (Error::Warn, "FormatPointer ends at EOF but is not the last, forcing it to be the last\n");
00985                 m_formatPointerUpto = m_numFormatPointers - 1;  // m_formatPointerUpto will get incremented at the end of this function
00986             }
00987         }
00988 
00989 
00990         //
00991         // read in corresponding Format Property
00992         //
00993         int currentPropertyOffset = m_formatPointer->getFormatPropertyOffset ();
00994 
00995         bool up2date = (currentPropertyOffset == m_lastPropertyOffset);
00996         if (!up2date) m_device->setCache (m_packedStructs + currentPropertyOffset);
00997 
00998         if (m_type == CharType)
00999         {
01000             if (!up2date)
01001             {
01002                 // reset to defaults
01003                 delete [] m_formatCharProperty;
01004                 m_formatCharProperty = new FormatCharProperty [1];
01005 
01006                 if (!m_formatCharProperty)
01007                 {
01008                     m_device->error (Error::OutOfMemory, "could not allocate memory for FormatCharProperty\n");
01009                     m_device->setCache (NULL);
01010                     return NULL;
01011                 }
01012 
01013                 m_formatCharProperty->setDevice (m_device);
01014                 m_formatCharProperty->setFontTable (m_fontTable);
01015                 if (!m_formatCharProperty->updateFont ())
01016                 {
01017                     m_device->setCache (NULL);
01018                     return NULL;
01019                 }
01020 
01021                 // corresponding charProperty structure exists?
01022                 if (currentPropertyOffset != 0xFFFF)
01023                 {
01024                     if (!m_formatCharProperty->readFromDevice ())
01025                     {
01026                         m_device->setCache (NULL);
01027                         return NULL;
01028                     }
01029                 }
01030             }
01031 
01032             assert (m_formatCharProperty);
01033             m_formatCharProperty->setAfterEndCharByte (m_formatPointer->getAfterEndCharByte ());
01034             ret = m_formatCharProperty;
01035         }
01036         else    // if (m_type == ParaType)
01037         {
01038             if (!up2date)
01039             {
01040                 // reset to defaults
01041                 delete [] m_formatParaProperty;
01042                 m_formatParaProperty = new FormatParaProperty [1];
01043 
01044                 if (!m_formatParaProperty)
01045                 {
01046                     m_device->error (Error::OutOfMemory, "could not allocate memory for FormatParaProperty\n");
01047                     m_device->setCache (NULL);
01048                     return NULL;
01049                 }
01050 
01051                 m_formatParaProperty->setDevice (m_device);
01052                 m_formatParaProperty->setMargins (m_leftMargin, m_rightMargin);
01053 
01054                 // corresponding paraProperty structure exists?
01055                 if (currentPropertyOffset != 0xFFFF)
01056                 {
01057                     if (!m_formatParaProperty->readFromDevice ())
01058                     {
01059                         m_device->setCache (NULL);
01060                         return NULL;
01061                     }
01062                 }
01063             }
01064 
01065             assert (m_formatParaProperty);
01066             m_formatParaProperty->setAfterEndCharByte (m_formatPointer->getAfterEndCharByte ());
01067             ret = m_formatParaProperty;
01068         }
01069 
01070         if (!up2date) m_device->setCache (NULL);
01071         m_lastPropertyOffset = currentPropertyOffset;
01072 
01073         m_formatPointerUpto++;
01074         assert (m_formatPointer);
01075         return ret;
01076     }
01077 
01078     bool FormatInfoPage::end (void) const
01079     {
01080         assert (m_formatPointerUpto <= FormatInfoPageGenerated::m_numFormatPointers);
01081         return m_formatPointerUpto >= FormatInfoPageGenerated::m_numFormatPointers;
01082     }
01083 
01084     bool FormatInfoPage::add (const void *property)
01085     {
01086     CHECK_DEVICE;
01087 
01088         // MaxElements is true for FormatPointers since you can't have partial FormatPointers
01089         //  This is also true for FormatProperties because m_numFormatPointer >= m_numProperty
01090         //  so MaxElements is also the upper limit on the number of properties
01091         const int MaxElements = 123 / FormatPointer::s_size;
01092 
01093     #ifdef DEBUG_FORMATINFO
01094         if (m_type == ParaType)
01095             m_device->debug (">>>> FormatInfoPage::add (ParaType) <<<<\n");
01096         else    // if (m_type == CharType)
01097             m_device->debug (">>>> FormatInfoPage::add (CharType) <<<<\n");
01098 
01099         Dump (formatPointerPos);
01100         Dump (formatPropertyPos);
01101     #endif
01102 
01103 
01104         //
01105         // Allocated memory for FormatPointers yet?
01106         //
01107 
01108         if (!m_formatPointer)
01109         {
01110         #ifdef DEBUG_FORMATINFO
01111             m_device->debug ("\tFIRST CALL!  Allocating memory for FormatPointer[] and FormatProperty[]\n");
01112         #endif
01113 
01114             // allocate memory for FormatPointers
01115             m_formatPointer = new FormatPointer [MaxElements + 1];  // lazy memory allocation (+1 in case we can merge the last one)
01116             if (!m_formatPointer)
01117                 ErrorAndQuit (Error::OutOfMemory, "could not allocate memory for formatPointer[]\n");
01118             // don't need to use m_formatPointerUpto here
01119             FormatInfoPageGenerated::m_numFormatPointers = 0;
01120 
01121             // ok, better allocate memory for relevant FormatProperties
01122             if (m_type == ParaType)
01123             {
01124                 assert (!m_formatParaProperty);
01125                 m_formatParaProperty = new FormatParaProperty [MaxElements + 1];    // lazy memory allocation (+1 for default prop)
01126                 m_formatParaProperty [MaxElements].setDevice (m_device);    // we will be == this default which has to writeToArray which NeedsDevice
01127                 if (!m_formatParaProperty)
01128                     ErrorAndQuit (Error::OutOfMemory, "could not allocate memory for formatParaProperty[]\n");
01129             }
01130             else    // if (m_type == CharType)
01131             {
01132                 assert (!m_formatCharProperty);
01133                 m_formatCharProperty = new FormatCharProperty [MaxElements + 1];    // lazy memory allocation (+1 for default prop)
01134                 m_formatCharProperty [MaxElements].setDevice (m_device);    // we will be == this default which has to writeToArray which NeedsDevice
01135                 if (!m_formatCharProperty)
01136                         ErrorAndQuit (Error::OutOfMemory, "could not allocate memory for formatCharProperty[]\n");
01137             }
01138 
01139             m_numProperty = 0;
01140         }
01141 
01142 
01143         //
01144         // Setup pointers
01145         //
01146 
01147         FormatParaProperty inpp;
01148         FormatCharProperty incp;
01149 
01150         if (m_type == ParaType)
01151         {
01152         #ifdef DEBUG_FORMATINFO
01153             m_device->debug ("\tTrying to add ParaProperty, #numDataBytes=", ((FormatParaProperty *) property)->getNumDataBytes ());
01154         #endif
01155 
01156             inpp = *((FormatParaProperty *) property);
01157             inpp.setDevice (m_device);
01158             inpp.setAfterEndCharByte (m_device->tellInternal () - 128);
01159             inpp.setMargins (m_leftMargin, m_rightMargin);
01160             if (!inpp.updateIndents ()) return false;
01161         }
01162         else    // if (m_type == CharType)
01163         {
01164         #ifdef DEBUG_FORMATINFO
01165             m_device->debug ("\tTrying to add CharProperty, #numDataBytes=", ((FormatCharProperty *) property)->getNumDataBytes ());
01166         #endif
01167 
01168             incp = *((FormatCharProperty *) property);
01169             incp.setDevice (m_device);
01170             incp.setAfterEndCharByte (m_device->tellInternal () - 128);
01171             incp.setFontTable (m_fontTable);
01172             if (!incp.updateFontCode ()) return false;
01173         }
01174 
01175 
01176         //
01177         // Attempt to add Property to current page:
01178         //
01179         // Since MS programmers tried so hard to save space, we will do the same :)
01180         // This results in having to store variable-length structures and the use of other nasty
01181         // tricks such as having multiple FormatPointers pointing to the same FormatProperty.
01182         // Details follow in code :)
01183         //
01184 
01185         // In Write, character formatting blocks can extend across paragraphs
01186         // In LibMSWrite they don't (for convenience?) so here we merge FormatPointers that have been split up
01187         // This applies _only_ to _character formatting_ and is not MS' fault but rather the design of LibMSWrite.
01188         // It should _not_ be done to paragraph formatting because I don't think the user would appreciate
01189         // several paragraphs being merged into one multi-line paragraph (changing paragraph properties would
01190         // become rather difficult...)
01191         bool checkedLastFormatPointer = false;
01192         if (m_type == CharType && m_numProperty > 0 /* && m_numFormatPointers > 0 */)
01193         {
01194         #ifdef DEBUG_FORMATINFO
01195             m_device->debug ("\tIs it the same property as last? ");
01196         #endif
01197 
01198             // simply extend last FormatPointer
01199             FormatCharProperty *lastProp = (FormatCharProperty *) m_formatPointer [m_numFormatPointers - 1].getFormatProperty ();
01200             if (incp == *lastProp)
01201             {
01202             #ifdef DEBUG_FORMATINFO
01203                 m_device->debug ("Yes, extending FormatPointer #", m_numFormatPointers - 1);
01204                 m_device->debug ("\t\tFrom ", m_formatPointer [m_numFormatPointers - 1].getAfterEndCharByte ());
01205             #endif
01206 
01207                 m_formatPointer [m_numFormatPointers - 1].setAfterEndCharByte (incp.getAfterEndCharByte ());
01208 
01209             #ifdef DEBUG_FORMATINFO
01210                 m_device->debug ("\t\tTo: ", incp.getAfterEndCharByte ());
01211             #endif
01212                 return true;
01213             }
01214 
01215             checkedLastFormatPointer = true;
01216         #ifdef DEBUG_FORMATINFO
01217             m_device->debug ("No\n");
01218         #endif
01219         }
01220         #ifdef DEBUG_FORMATINFO
01221             m_device->debug ("\tSame as earlier FormatPointer? ");
01222         #endif
01223 
01224         // points to same property as an earlier formatPointer?
01225         for (int i = 0; i < m_numFormatPointers - (checkedLastFormatPointer ? 1 : 0); i++)
01226         {
01227         #ifdef DEBUG_FORMATINFO
01228             m_device->debug (i);
01229             m_device->debug ("? ");
01230         #endif
01231             if (m_type == ParaType)
01232             {
01233                 FormatParaProperty *prop = (FormatParaProperty *) m_formatPointer [i].getFormatProperty ();
01234                 if (inpp == *prop)
01235                 {
01236                     // try to add new formatPointer
01237                     if (m_formatPointerPos + FormatPointer::s_size > m_formatPropertyPos)
01238                     {
01239                     #ifdef DEBUG_FORMATINFO
01240                         m_device->debug ("Yes, but out of room on this page\n");
01241                     #endif
01242                         return false;   // not enough room
01243                     }
01244 
01245                 #ifdef DEBUG_FORMATINFO
01246                     m_device->debug ("Yes, same property as ", i);
01247                 #endif
01248                     m_formatPointer [m_numFormatPointers].setAfterEndCharByte (inpp.getAfterEndCharByte ());
01249                     m_formatPointer [m_numFormatPointers].setFormatPropertyOffset (m_formatPointer [i].getFormatPropertyOffset ());
01250                     m_formatPointer [m_numFormatPointers].setFormatProperty (prop);
01251 
01252                     m_formatPointerPos += FormatPointer::s_size;
01253                     m_numFormatPointers++;
01254                     return true;
01255                 }
01256             }
01257             else    // if (m_type == CharType)
01258             {
01259                 FormatCharProperty *prop = (FormatCharProperty *) m_formatPointer [i].getFormatProperty ();
01260                 if (incp == *prop)
01261                 {
01262                     // try to add new formatPointer
01263                     if (m_formatPointerPos + FormatPointer::s_size > m_formatPropertyPos)
01264                     {
01265                     #ifdef DEBUG_FORMATINFO
01266                         m_device->debug ("Yes, but out of room on this page\n");
01267                     #endif
01268                         return false;   // not enough room
01269                     }
01270 
01271                 #ifdef DEBUG_FORMATINFO
01272                     m_device->debug ("Yes, same property as ", i);
01273                 #endif
01274                     m_formatPointer [m_numFormatPointers].setAfterEndCharByte (incp.getAfterEndCharByte ());
01275                     m_formatPointer [m_numFormatPointers].setFormatPropertyOffset (m_formatPointer [i].getFormatPropertyOffset ());
01276                     m_formatPointer [m_numFormatPointers].setFormatProperty (prop);
01277 
01278                     m_formatPointerPos += FormatPointer::s_size;
01279                     m_numFormatPointers++;
01280                     return true;
01281                 }
01282             }
01283         }
01284         #ifdef DEBUG_FORMATINFO
01285             m_device->debug ("No, outputting full FormatPointer & Property\n");
01286         #endif
01287 
01288         // ok we can't compress, must output a full FormatPointer & FormatProperty
01289         if (m_type == ParaType)
01290         {
01291             int nextPropertyPos = m_formatPropertyPos;
01292             if (inpp.getNumDataBytes ())
01293                 nextPropertyPos -= (sizeof (Byte) + inpp.getNumDataBytes ());
01294 
01295             if (m_formatPointerPos + FormatPointer::s_size > nextPropertyPos)
01296             {
01297             #ifdef DEBUG_FORMATINFO
01298                 m_device->debug ("\tOut of room on this page!\n");
01299             #endif
01300                 return false;   // not enough room
01301             }
01302 
01303             m_formatPropertyPos = nextPropertyPos;
01304             if (inpp.getNumDataBytes ())
01305                 m_formatParaProperty [m_numProperty] = inpp;
01306 
01307             m_formatPointer [m_numFormatPointers].setAfterEndCharByte (inpp.getAfterEndCharByte ());
01308             if (inpp.getNumDataBytes ())
01309             {
01310                 m_formatPointer [m_numFormatPointers].setFormatPropertyOffset (m_formatPropertyPos);
01311                 m_formatPointer [m_numFormatPointers].setFormatProperty (&m_formatParaProperty [m_numProperty]);
01312             }
01313             else
01314             {
01315                 m_formatPointer [m_numFormatPointers].setFormatPropertyOffset (0xFFFF/*nowhere*/);
01316                 m_formatPointer [m_numFormatPointers].setFormatProperty (&m_formatParaProperty [MaxElements]/*default*/);
01317             }
01318             m_formatPointerPos += FormatPointer::s_size;
01319 
01320             if (inpp.getNumDataBytes ()) m_numProperty++;
01321             m_numFormatPointers++;
01322             return true;
01323         }
01324         else    // if (m_type == CharType)
01325         {
01326             int nextPropertyPos = m_formatPropertyPos;
01327             if (incp.getNumDataBytes ())
01328                 nextPropertyPos -= (sizeof (Byte) + incp.getNumDataBytes ());
01329 
01330             if (m_formatPointerPos + FormatPointer::s_size > nextPropertyPos)
01331             {
01332             #ifdef DEBUG_FORMATINFO
01333                 m_device->debug ("\tOut of room on this page!\n");
01334             #endif
01335                 return false;   // not enough room
01336             }
01337 
01338             m_formatPropertyPos = nextPropertyPos;
01339             if (incp.getNumDataBytes ())
01340                 m_formatCharProperty [m_numProperty] = incp;
01341 
01342             m_formatPointer [m_numFormatPointers].setAfterEndCharByte (incp.getAfterEndCharByte ());
01343             if (incp.getNumDataBytes ())
01344             {
01345                 m_formatPointer [m_numFormatPointers].setFormatPropertyOffset (m_formatPropertyPos);
01346                 m_formatPointer [m_numFormatPointers].setFormatProperty (&m_formatCharProperty [m_numProperty]);
01347             }
01348             else
01349             {
01350                 m_formatPointer [m_numFormatPointers].setFormatPropertyOffset (0xFFFF/*nowhere*/);
01351                 m_formatPointer [m_numFormatPointers].setFormatProperty (&m_formatCharProperty [MaxElements]/*default*/);
01352             }
01353             m_formatPointerPos += FormatPointer::s_size;
01354 
01355             if (incp.getNumDataBytes ()) m_numProperty++;
01356             m_numFormatPointers++;
01357             return true;
01358         }
01359     }
01360 
01361 
01362     BMP_BitmapFileHeader::BMP_BitmapFileHeader ()
01363     {
01364     }
01365 
01366     BMP_BitmapFileHeader::~BMP_BitmapFileHeader ()
01367     {
01368     }
01369 
01370     BMP_BitmapFileHeader &BMP_BitmapFileHeader::operator= (const BMP_BitmapFileHeader &rhs)
01371     {
01372         if (this == &rhs)
01373             return *this;
01374 
01375         BMP_BitmapFileHeaderGenerated::operator= (rhs);
01376 
01377         return *this;
01378     }
01379 
01380     bool BMP_BitmapFileHeader::readFromDevice (void)
01381     {
01382     CHECK_DEVICE;
01383 
01384     #ifdef DEBUG_IMAGE
01385         m_device->debug ("\n<<<< BMP_BitmapFileHeader::readFromDevice >>>>\n");
01386     #endif
01387 
01388         if (!BMP_BitmapFileHeaderGenerated::readFromDevice ())
01389             return false;
01390 
01391     #ifdef DEBUG_IMAGE
01392         Dump (magic);
01393         Dump (totalBytes);
01394         Dump (zero [0]);
01395         Dump (zero [1]);
01396         Dump (actualImageOffset);
01397     #endif
01398 
01399         return true;
01400     }
01401 
01402     bool BMP_BitmapFileHeader::writeToDevice (void)
01403     {
01404     CHECK_DEVICE;
01405 
01406     #ifdef DEBUG_IMAGE
01407         m_device->debug ("\n<<<< BMP_BitmapFileHeader::writeToDevice >>>>\n");
01408     #endif
01409 
01410         if (!BMP_BitmapFileHeaderGenerated::writeToDevice ())
01411             return false;
01412 
01413         return true;
01414 
01415     }
01416 
01417 
01418     BMP_BitmapInfoHeader::BMP_BitmapInfoHeader ()
01419     {
01420     }
01421 
01422     BMP_BitmapInfoHeader::~BMP_BitmapInfoHeader ()
01423     {
01424     }
01425 
01426     BMP_BitmapInfoHeader &BMP_BitmapInfoHeader::operator= (const BMP_BitmapInfoHeader &rhs)
01427     {
01428         if (this == &rhs)
01429             return *this;
01430 
01431         BMP_BitmapInfoHeaderGenerated::operator= (rhs);
01432 
01433         return *this;
01434     }
01435 
01436     bool BMP_BitmapInfoHeader::readFromDevice (void)
01437     {
01438     CHECK_DEVICE;
01439 
01440     #ifdef DEBUG_IMAGE
01441         m_device->debug ("\n<<<< BMP_BitmapInfoHeader::readFromDevice >>>>\n");
01442     #endif
01443 
01444         if (!BMP_BitmapInfoHeaderGenerated::readFromDevice ())
01445             return false;
01446 
01447     #ifdef DEBUG_IMAGE
01448         Dump (numHeaderBytes);
01449         Dump (width);
01450         Dump (height);
01451         Dump (numPlanes);
01452         Dump (bitsPerPixel);
01453         Dump (compression);
01454         Dump (sizeImage);
01455         Dump (xPixelsPerMeter);
01456         Dump (yPixelsPerMeter);
01457         Dump (coloursUsed);
01458         Dump (coloursImportant);
01459     #endif
01460 
01461         return true;
01462     }
01463 
01464     bool BMP_BitmapInfoHeader::writeToDevice (void)
01465     {
01466     CHECK_DEVICE;
01467 
01468     #ifdef DEBUG_IMAGE
01469         m_device->debug ("\n<<<< BMP_BitmapInfoHeader::writeToDevice >>>>\n");
01470     #endif
01471 
01472         if (!BMP_BitmapInfoHeaderGenerated::writeToDevice ())
01473             return false;
01474 
01475         return true;
01476     }
01477 
01478 
01479     BMP_BitmapColourIndex::BMP_BitmapColourIndex ()
01480     {
01481     }
01482 
01483     BMP_BitmapColourIndex::~BMP_BitmapColourIndex ()
01484     {
01485     }
01486 
01487     BMP_BitmapColourIndex &BMP_BitmapColourIndex::operator= (const BMP_BitmapColourIndex &rhs)
01488     {
01489         if (this == &rhs)
01490             return *this;
01491 
01492         BMP_BitmapColourIndexGenerated::operator= (rhs);
01493 
01494         return *this;
01495     }
01496 
01497 
01498     BitmapHeader::BitmapHeader ()
01499     {
01500     }
01501 
01502     BitmapHeader::~BitmapHeader ()
01503     {
01504     }
01505 
01506     BitmapHeader &BitmapHeader::operator= (const BitmapHeader &rhs)
01507     {
01508         if (this == &rhs)
01509             return *this;
01510 
01511         BitmapHeaderGenerated::operator= (rhs);
01512 
01513         return *this;
01514     }
01515 
01516     bool BitmapHeader::readFromDevice (void)
01517     {
01518     CHECK_DEVICE;
01519 
01520     #ifdef DEBUG_IMAGE
01521         m_device->debug ("\n<<<< BitmapHeader::readFromDevice >>>>\n");
01522     #endif
01523 
01524         if (!BitmapHeaderGenerated::readFromDevice ())
01525             return false;
01526 
01527     #ifdef DEBUG_IMAGE
01528         Dump (zero);
01529         Dump (width);
01530         Dump (height);
01531         Dump (widthBytes);
01532         Dump (numPlanes);
01533         Dump (bitsPerPixel);
01534         Dump (zero2);
01535     #endif
01536 
01537         return true;
01538     }
01539 
01540     bool BitmapHeader::writeToDevice (void)
01541     {
01542     CHECK_DEVICE;
01543 
01544     #ifdef DEBUG_IMAGE
01545         m_device->debug ("\n>>>> BitmapHeader::writeToDevice <<<<\n");
01546     #endif
01547 
01548         if (!BitmapHeaderGenerated::writeToDevice ())
01549             return false;
01550 
01551         return true;
01552     }
01553 
01554 
01555     WMFHeader::WMFHeader ()
01556     {
01557     }
01558 
01559     WMFHeader::~WMFHeader ()
01560     {
01561     }
01562 
01563     WMFHeader &WMFHeader::operator= (const WMFHeader &rhs)
01564     {
01565         if (this == &rhs)
01566             return *this;
01567 
01568         WMFHeaderGenerated::operator= (rhs);
01569 
01570         return *this;
01571     }
01572 
01573     bool WMFHeader::readFromDevice (void)
01574     {
01575     CHECK_DEVICE;
01576 
01577     #ifdef DEBUG_IMAGE
01578         m_device->debug ("\n<<<< WMFHeader::readFromDevice >>>>\n");
01579     #endif
01580 
01581         if (!WMFHeaderGenerated::readFromDevice ())
01582             return false;
01583 
01584     #ifdef DEBUG_IMAGE
01585         Dump (fieldType);
01586         Dump (headerSize);
01587         Dump (winVersion);
01588         Dump (fileSize);
01589         Dump (numObjects);
01590         Dump (maxRecordSize);
01591         Dump (zero);
01592     #endif
01593 
01594         return true;
01595     }
01596 
01597     bool WMFHeader::writeToDevice (void)
01598     {
01599     CHECK_DEVICE;
01600 
01601     #ifdef DEBUG_IMAGE
01602         m_device->debug ("\n>>>> WMFHeader::writeToDevice <<<<\n");
01603     #endif
01604 
01605     #ifdef DEBUG_IMAGE
01606         Dump (fieldType);
01607         Dump (headerSize);
01608         Dump (winVersion);
01609         Dump (fileSize);
01610         Dump (numObjects);
01611         Dump (maxRecordSize);
01612         Dump (zero);
01613     #endif
01614 
01615         if (!WMFHeaderGenerated::writeToDevice ())
01616             return false;
01617 
01618         return true;
01619     }
01620 }   // namespace MSWrite    {
01621 
01622 // end of structures_private.cpp
KDE Home | KDE Accessibility Home | Description of Access Keys