filters

structures_private.cpp
1/* This file is part of the LibMSWrite Library
2 Copyright (C) 2001-2003 Clarence Dang <clarencedang@users.sourceforge.net>
3
4 This library is free software; you can redistribute it and/or
5 modify it under the terms of the GNU Library General Public
6 License Version 2 as published by the Free Software Foundation.
7
8 This library is distributed in the hope that it will be useful,
9 but WITHOUT ANY WARRANTY; without even the implied warranty of
10 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
11 Library General Public License Version 2 for more details.
12
13 You should have received a copy of the GNU Library General Public License
14 Version 2 along with this library; see the file COPYING.LIB. If not,
15 write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
16 * Boston, MA 02110-1301, USA.
17
18 LibMSWrite Project Website:
19 http://sourceforge.net/projects/libmswrite/
20*/
21
22/*
23 * structures_private.cpp - Process Internal Microsoft(r) Write file structures
24 * - that are hidden/abstracted away from the user
25 * This file has ugly reading/writing code that couldn't be generated.
26 * It performs some higher-level sanity checks.
27 *
28 * Don't use any of these classes as it would defeat the purpose of LibMSWrite.
29 */
30
31#include "structures_private.h"
32#include "structures.h"
33
34namespace MSWrite
35{
36 Header::Header ()
37 {
38 }
39
40 Header::~Header ()
41 {
42 }
43
44 Header &Header::operator= (const Header &rhs)
45 {
46 if (this == &rhs)
47 return *this;
48
49 HeaderGenerated::operator= (rhs);
50
51 m_numCharBytes = rhs.m_numCharBytes;
52 m_pageCharInfo = rhs.m_pageCharInfo;
53
54 return *this;
55 }
56
57 bool Header::readFromDevice (void)
58 {
59 CHECK_DEVICE;
60
61 #ifdef DEBUG_HEADER
62 m_device->debug ("\n<<<< Header::readFromDevice >>>>\n");
63 #endif
64
65 if (!m_device->seekInternal (0, SEEK_SET)) return false;
66 if (!HeaderGenerated::readFromDevice ()) return false;
67
68 #ifdef DEBUG_HEADER
69 switch (m_magic)
70 {
71 case 0xBE31: m_device->debug ("normal write file\n"); break;
72 case 0xBE32: m_device->debug ("write file with OLE\n"); break;
73 default: ErrorAndQuit (Error::InternalError, "magic test passed but failed later?");
74 }
75 #endif
76
77 m_numCharBytes = m_numCharBytesPlus128 - 128;
78
79 #ifdef DEBUG_HEADER
80 m_device->debug ("num bytes of data (text+images+OLE): ", m_numCharBytes);
81 m_device->debug ("page # start of parainfo: ", m_pageParaInfo);
82 m_device->debug ("page # footnote table: ", m_pageFootnoteTable);
83 m_device->debug ("page # pageLayout: ", m_pageSectionProperty);
84 m_device->debug ("page # sectionTable: ", m_pageSectionTable);
85 m_device->debug ("page # pageTable: ", m_pagePageTable);
86 m_device->debug ("page # fontTable: ", m_pageFontTable);
87 m_device->debug ("num pages in file: ", m_numPages);
88 #endif
89
90 /*
91 * more checks
92 */
93
94 // footnoteTables simply do not exist...
95 if (m_pageFootnoteTable != m_pageSectionProperty)
96 ErrorAndQuit (Error::InvalidFormat, "document should not have a footnoteTable\n");
97
98
99 // cannot have a sectionProperty without a sectionTable or vice-versa
100
101 // no sectionProperty?
102 if (m_pageSectionProperty == m_pagePageTable)
103 {
104 // must not have a sectionTable then
105 if (m_pageSectionTable != m_pagePageTable)
106 ErrorAndQuit (Error::InvalidFormat, "sectionTable without sectionProperty\n");
107 }
108 // have sectionProperty...
109 else
110 {
111 if (m_pageSectionTable != m_pageSectionProperty + 1)
112 ErrorAndQuit (Error::InvalidFormat, "sectionTable not immediately after sectionProperty\n");
113
114 if (m_pageSectionTable == m_pagePageTable)
115 ErrorAndQuit (Error::InvalidFormat, "sectionProperty without sectionTable\n");
116 }
117
118 // charInfo page comes immediately after the header and text
119 m_pageCharInfo = (m_numCharBytesPlus128 + 127) / 128;
120
121 #ifdef DEBUG_HEADER
122 m_device->debug ("page # start of charinfo: ", m_pageCharInfo);
123 #endif
124
125 // catches a lot of corrupted files
126 if (m_pageCharInfo > m_pageParaInfo)
127 ErrorAndQuit (Error::InvalidFormat, "charInfo page after paraInfo page\n");
128
129 return true;
130 }
131
132 bool Header::writeToDevice (void)
133 {
134 CHECK_DEVICE;
135
136 #ifdef DEBUG_HEADER
137 m_device->debug ("\n<<<< Header::writeToDevice >>>>\n");
138 #endif
139
140 m_numCharBytesPlus128 = m_numCharBytes + 128;
141
142 if (!m_device->seekInternal (0, SEEK_SET)) return false;
143 if (!HeaderGenerated::writeToDevice ()) return false;
144
145 return true;
146 }
147
148
149 SectionDescriptor::SectionDescriptor ()
150 {
151 }
152
153 SectionDescriptor::~SectionDescriptor ()
154 {
155 }
156
157 SectionDescriptor &SectionDescriptor::operator= (const SectionDescriptor &rhs)
158 {
159 if (this == &rhs)
160 return *this;
161
162 SectionDescriptorGenerated::operator= (rhs);
163
164 return *this;
165 }
166
167
168 SectionTable::SectionTable ()
169 {
170 }
171
172 SectionTable::~SectionTable ()
173 {
174 }
175
176 SectionTable &SectionTable::operator= (const SectionTable &rhs)
177 {
178 if (this == &rhs)
179 return *this;
180
181 SectionTableGenerated::operator= (rhs);
182 NeedsHeader::operator= (rhs);
183
184 return *this;
185 }
186
187 // this function really only does some sanity checking
188 // in fact, a SectionTable is quite useless in Write...
189 // ...so you actually don't have to call it :)
190 bool SectionTable::readFromDevice (void)
191 {
192 CHECK_DEVICE;
193
194 #ifdef DEBUG_PAGELAYOUT
195 m_device->debug ("\n<<<< SectionTable::readFromDevice >>>>\n");
196 #endif
197
198 int numSectionTablePages = m_header->getNumPageSectionTable ();
199
200 #ifdef DEBUG_PAGELAYOUT
201 m_device->debug ("num sectionTablePages=", numSectionTablePages);
202 #endif
203
204 // no SectionTable
205 if (numSectionTablePages == 0)
206 return true;
207 else if (numSectionTablePages > 1)
208 ErrorAndQuit (Error::InvalidFormat, "invalid #sectionTablePages\n");
209
210 // seek to the SectionTable in the file
211 if (!m_device->seekInternal (m_header->getPageSectionTable () * 128, SEEK_SET))
212 return false;
213
214 if (!SectionTableGenerated::readFromDevice ()) return false;
215
216 #ifdef DEBUG_PAGELAYOUT
217 m_device->debug ("num sectionDescriptors=", m_numSectionDescriptors);
218 for (int i = 0; i < 2; i++)
219 {
220 m_device->debug ("Dumping SED #", i);
221 m_device->debug ("\tbyte after section=", m_sed [i]->getAfterEndCharByte ());
222 m_device->debug ("\tsectionProperty location=", m_sed [i]->getSectionPropertyLocation ());
223 }
224 #endif
225
226 if (m_numSectionDescriptors != 2)
227 m_device->error (Error::Warn, "#sectionDescriptors != 2, ignoring");
228
229 // check that 1st SectionDescriptor covers all characters
230 if (m_sed [0]->getAfterEndCharByte () != m_header->getNumCharBytes ())
231 m_device->error (Error::Warn, "sectionDescriptor #1 does not cover entire document\n");
232
233 // check that 1st SectionDescriptor points to the SectionProperty
234 if (m_sed [0]->getSectionPropertyLocation () != m_header->getPageSectionProperty () * DWord (128))
235 m_device->error (Error::Warn, "sectionDescriptor #1 does not refer to correct sectionProperty, ignoring\n");
236
237 // check that 2nd SectionDescriptor covers after the end of the document
238 if (m_sed [1]->getAfterEndCharByte () != m_header->getNumCharBytes () + 1)
239 m_device->error (Error::Warn, "sectionDescriptor #2 does not cover post-document\n");
240
241 // check that 2nd SectionDescriptor is indeed a dummy
242 if (m_sed [1]->getSectionPropertyLocation () != (DWord) 0xFFFFFFFF)
243 m_device->error (Error::Warn, "sectionDescriptor #2 is not a dummy\n");
244
245 return true;
246 }
247
248 bool SectionTable::writeToDevice (const bool needed)
249 {
250 CHECK_DEVICE;
251
252 #ifdef DEBUG_PAGELAYOUT
253 m_device->debug ("\n>>>> SectionTable::writeToDevice <<<<\n");
254 #endif
255
256 m_header->setPageSectionTable (m_device->tellInternal () / 128);
257
258 // if no sectionProperty, no sectionTable
259 if (!needed)
260 return true;
261
262
263 // set that 1st SectionDescriptor covers all characters
264 m_sed [0]->setAfterEndCharByte (m_header->getNumCharBytes ());
265
266 // set that 1st SectionDescriptor points to the SectionProperty
267 m_sed [0]->setSectionPropertyLocation (m_header->getPageSectionProperty () * 128);
268
269 // set that 2nd SectionDescriptor covers after the end of the document
270 m_sed [1]->setAfterEndCharByte (m_header->getNumCharBytes () + 1);
271
272 // set that 2nd SectionDescriptor is indeed a dummy
273 m_sed [1]->setSectionPropertyLocation ((DWord) 0xFFFFFFFF);
274
275 if (!SectionTableGenerated::writeToDevice ())
276 return false;
277
278 return true;
279 }
280
281
282 FontTable::FontTable ()
283 {
284 }
285
286 FontTable::~FontTable ()
287 {
288 }
289
290 FontTable &FontTable::operator= (const FontTable &rhs)
291 {
292 if (this == &rhs)
293 return *this;
294
295 FontTableGenerated::operator= (rhs);
296 NeedsHeader::operator= (rhs);
297
298 m_fontList = rhs.m_fontList;
299
300 return *this;
301 }
302
303 bool FontTable::readFromDevice (void)
304 {
305 CHECK_DEVICE;
306
307 #ifdef DEBUG_FONT
308 m_device->debug ("\n<<<< FontTable::readFromDevice >>>>\n");
309 #endif
310
311 int numFontTablePages = m_header->getNumPageFontTable ();
312
313 // no FontTable
314 if (numFontTablePages == 0)
315 return true;
316
317 // seek to the fontTable in the file
318 if (!m_device->seekInternal (m_header->getPageFontTable () * 128, SEEK_SET))
319 return false;
320
321 if (!FontTableGenerated::readFromDevice ()) return false;
322
323 #ifdef DEBUG_FONT
324 m_device->debug ("num Fonts: ", m_numFonts);
325 #endif
326
327 bool dontAddToBack = false;
328 for (int i = 0; i < FontTableGenerated::m_numFonts; i++)
329 {
330 #ifdef DEBUG_FONT
331 m_device->debug ("Font: ", i);
332 #endif
333
334 if (!dontAddToBack)
335 {
336 if (!m_fontList.addToBack ())
337 ErrorAndQuit (Error::OutOfMemory, "could not add Font to fontList\n");
338 }
339 else
340 dontAddToBack = false;
341
342 List <Font>::Iterator it = m_fontList.begin (false);
343 Font &font = *it;
344
345 // read font
346 font.setDevice (m_device);
347 if (!font.readFromDevice ())
348 {
349 // a real error...
350 if (m_device->bad ())
351 return false;
352
353 //
354 // ... or Font::readFromDevice() signalled something
355 //
356
357 // font is on next page?
358 if (font.getNumDataBytes () == 0xFFFF)
359 {
360 #ifdef DEBUG_FONT
361 m_device->debug ("\tcurrent offset=", m_device->tellInternal ());
362 m_device->debug ("\tnext page offset=", (m_device->tellInternal () + 127) / 128 * 128);
363 #endif
364
365 // seek to next page
366 if (!m_device->seekInternal ((m_device->tellInternal () + 127) / 128 * 128, SEEK_SET))
367 return false;
368 --i; // still reading the same font
369 dontAddToBack = true; // don't need to add another font, just re-use this sentinel
370 continue;
371 }
372
373 // no more entries (should _not_ get in here)?
374 if (font.getNumDataBytes () == 0)
375 {
376 if (i != m_numFonts - 1) // actually, this check isn't required
377 m_device->error (Error::Warn, "font marked as last but is not\n");
378
379 // let's not cause problems later with uninitialised Font::m_name's
380 m_fontList.erase (it);
381
382 // better quit just in case (it is better to have fewer fonts than risk errors)
383 break;
384 }
385 }
386 } // for (int i = 0; i < m_numFonts; i++) {
387
388 return true;
389 }
390
391 bool FontTable::writeToDevice (void)
392 {
393 CHECK_DEVICE;
394
395 #ifdef DEBUG_FONT
396 m_device->debug ("\n>>>> FontTable::writeToDevice <<<<\n");
397 #endif
398
399 // indicate fontTable page in header
400 m_header->setPageFontTable (m_device->tellInternal () / 128);
401
402 FontTableGenerated::m_numFonts = m_fontList.getNumElements ();
403
404 // no fontTable
405 if (FontTableGenerated::m_numFonts == 0)
406 {
407 m_device->error (Error::Warn, "not writing fontTable\n");
408 return true;
409 }
410
411 // write numFonts
412 if (!FontTableGenerated::writeToDevice ()) return false;
413
414 int i = 0;
415 for (List <Font>::Iterator it = m_fontList.begin ();
416 it != m_fontList.end ();
417 /* don't iterate here since we might "continue" with the same font */)
418 {
419 #ifdef DEBUG_FONT
420 m_device->debug ("\twriting font #", i);
421 #endif
422
423 Font &font = *it;
424
425 // write font
426 font.setDevice (m_device);
427 if (!font.writeToDevice ())
428 {
429 // a real error...
430 if (m_device->bad ())
431 return false;
432
433 //
434 // ... or Font::readFromDevice() signalled something
435 //
436
437 // font is on next page then
438 #ifdef DEBUG_FONT
439 m_device->debug ("\tcurrent offset=", m_device->tellInternal ());
440 m_device->debug ("\tnext page offset=", (m_device->tellInternal () + 127) / 128 * 128);
441 #endif
442
443 // seek to next page
444 if (!m_device->seekInternal ((m_device->tellInternal () + 127) / 128 * 128, SEEK_SET))
445 return false;
446
447 // still writing the same font
448 continue;
449 }
450
451 // get next font to write
452 it++;
453 i++;
454 }
455
456 return true;
457 }
458
459 Font *FontTable::getFont (const DWord fontCode) const
460 {
461 // OPT: inefficient, maybe an array of pointers because we can't delete fonts anyway
462 List <Font>::Iterator it = m_fontList.begin ();
463 for (int i = 0; i < int (fontCode) && it != m_fontList.end (); i++, ++it)
464 ;
465 if (it == m_fontList.end ()) return NULL;
466 return &(*it);
467 }
468
469 DWord FontTable::findFont (const Font *want) const
470 {
471 DWord code = 0;
472
473 List <Font>::Iterator it;
474 for (it = m_fontList.begin (); it != m_fontList.end (); ++it)
475 {
476 if ((*it) == *want)
477 return code;
478
479 code++;
480 }
481
482 // couldn't find
483 return 0xFFFFFFFF;
484 }
485
486 DWord FontTable::addFont (const Font *input)
487 {
488 CHECK_DEVICE;
489
490 #ifdef DEBUG_FONT
491 m_device->debug ("\t\t\tTrying to add Font ", input->getName ());
492 #endif
493
494 DWord e = findFont (input);
495
496 // already in list
497 if (e != 0xFFFFFFFF)
498 {
499 #ifdef DEBUG_FONT
500 m_device->debug ("\t\t\t\tAlready in list, fontCode=", e);
501 #endif
502
503 // return fontCode
504 return e;
505 }
506 // new font
507 else
508 {
509 #ifdef DEBUG_FONT
510 m_device->debug ("\t\t\t\tNew font, adding to list\n");
511 #endif
512
513 if (!m_fontList.addToBack (*input))
514 ErrorAndQuit (Error::OutOfMemory, "could not allocate memory for next font element\n");
515 return m_fontList.getNumElements () - 1;
516 }
517 }
518
519
520 PagePointer::PagePointer ()
521 {
522 }
523
524 PagePointer::~PagePointer ()
525 {
526 }
527
528 PagePointer &PagePointer::operator= (const PagePointer &rhs)
529 {
530 if (this == &rhs)
531 return *this;
532
533 PagePointerGenerated::operator= (rhs);
534
535 return *this;
536 }
537
538 bool PagePointer::readFromDevice (void)
539 {
540 CHECK_DEVICE;
541
542 if (!PagePointerGenerated::readFromDevice ())
543 return false;
544
545 #ifdef DEBUG_PAGETABLE
546 m_device->debug ("\t\tpage number: ", m_pageNumber);
547 m_device->debug ("\t\tfirst char: ", m_firstCharByte);
548 #endif
549
550 return true;
551 }
552
553 bool PagePointer::writeToDevice (void)
554 {
555 CHECK_DEVICE;
556
557 if (!PagePointerGenerated::writeToDevice ())
558 return false;
559
560 return true;
561 }
562
563
564 PageTable::PageTable () : m_pageNumberStart (0xFFFF)
565 {
566 }
567
568 PageTable::~PageTable ()
569 {
570 }
571
572 PageTable &PageTable::operator= (const PageTable &rhs)
573 {
574 if (this == &rhs)
575 return *this;
576
577 PageTableGenerated::operator= (rhs);
578 NeedsHeader::operator= (rhs);
579
580 m_pagePointerList = rhs.m_pagePointerList;
581 m_pageNumberStart = rhs.m_pageNumberStart;
582
583 m_pageTableIterator = rhs.m_pageTableIterator;
584
585 return *this;
586 }
587
588 bool PageTable::readFromDevice (void)
589 {
590 CHECK_DEVICE;
591
592 #ifdef DEBUG_PAGETABLE
593 m_device->debug ("\n<<<< PageTable::readFromDevice >>>>\n");
594 #endif
595
596 #ifdef CHECK_INTERNAL
597 if (m_pageNumberStart == (Word) 0xFFFF || NeedsHeader::m_header == NULL)
598 ErrorAndQuit (Error::InternalError, "PageTable call not setup\n");
599 #endif
600
601 // no pageTable
602 if (m_header->getNumPagePageTable () == 0)
603 return true;
604
605 // seek to the pageTable in the file
606 if (!m_device->seekInternal (m_header->getPagePageTable () * 128, SEEK_SET))
607 return false;
608
609 if (!PageTableGenerated::readFromDevice ())
610 return false;
611
612 #ifdef DEBUG_PAGETABLE
613 Dump (numPagePointers);
614 Dump (zero);
615 #endif
616
617 DWord lastCharByte = (DWord) 0xFFFFFFFF;
618 Word lastPage = (Word) 0xFFFF; // do not have to init
619 for (int i = 0; i < m_numPagePointers; i++)
620 {
621 if (!m_pagePointerList.addToBack ())
622 ErrorAndQuit (Error::OutOfMemory, "could not add pagePointer to list\n");
623
624 PagePointer &pp = *m_pagePointerList.begin (false);
625
626 #ifdef DEBUG_PAGETABLE
627 m_device->debug ("\tPagePointer: ", i);
628 #endif
629
630 // read pointer
631 pp.setDevice (m_device);
632 if (!pp.readFromDevice ()) return false;
633
634 // first pointer?
635 if (i == 0)
636 {
637 if (pp.getPageNumber () != m_pageNumberStart)
638 ErrorAndQuit (Error::InvalidFormat, "pageTable & sectionProperty disagree on pageNumberStart\n");
639 }
640 else
641 {
642 // according to KOffice 1.2:
643 //
644 // "the pageTable can get really out of sync with reality
645 // if the user doesn't repaginate after deleting a few pages
646 // -- so this is just a warning, not an error"
647 //
648 if (pp.getPageNumber () != lastPage + 1)
649 m_device->error (Error::Warn, "pages don't follow each other\n");
650
651 if (pp.getFirstCharByte () <= lastCharByte)
652 ErrorAndQuit (Error::InvalidFormat, "pageTable is not going forward?\n");
653 }
654
655 // for checking, on next iteration
656 lastPage = pp.getPageNumber ();
657 lastCharByte = pp.getFirstCharByte ();
658 }
659
660 return true;
661 }
662
663 bool PageTable::writeToDevice (void)
664 {
665 CHECK_DEVICE;
666
667 #ifdef DEBUG_PAGETABLE
668 m_device->debug ("\n>>>> PageTable::writeToDevice <<<<\n");
669 #endif
670
671 m_header->setPagePageTable (m_device->tellInternal () / 128);
672
673 // LibMSWrite directly (!) adds to the list so m_numPagePointers may be out of date
674 PageTableGenerated::m_numPagePointers = m_pagePointerList.getNumElements ();
675
676 // no pageTable
677 if (m_numPagePointers == 0)
678 return true;
679
680 // write numPagePointers, zero
681 if (!PageTableGenerated::writeToDevice ())
682 return false;
683
684 int i = 0;
685 List <PagePointer>::Iterator it;
686 for (it = m_pagePointerList.begin (); it != m_pagePointerList.end (); ++it, i++)
687 {
688 PagePointer &pp = (*it);
689
690 #ifdef DEBUG_PAGETABLE
691 m_device->debug ("\tPagePointer: ", i);
692 #endif
693
694 // read page pointer
695 pp.setDevice (m_device);
696 if (!pp.writeToDevice ())
697 return false;
698 }
699
700 return true;
701 }
702
703
704 FormatPointer::FormatPointer () : m_afterEndCharByte (0)
705 {
706 }
707
708 FormatPointer::~FormatPointer ()
709 {
710 }
711
712 FormatPointer &FormatPointer::operator= (const FormatPointer &rhs)
713 {
714 if (this == &rhs)
715 return *this;
716
717 FormatPointerGenerated::operator= (rhs);
718
719 m_afterEndCharByte = rhs.m_afterEndCharByte;
720 m_formatProperty = rhs.m_formatProperty;
721
722 return *this;
723 }
724
725 bool FormatPointer::readFromDevice (void)
726 {
727 CHECK_DEVICE;
728
729 if (!FormatPointerGenerated::readFromDevice ())
730 return false;
731
732 m_afterEndCharByte = m_afterEndCharBytePlus128 - 128;
733
734 #ifdef DEBUG_FORMATINFO
735 m_device->debug ("\t\tafterEndCharByte: ", m_afterEndCharByte);
736 m_device->debug ("\t\tformatPropertyOffset: ", m_formatPropertyOffset);
737 #endif
738
739 return true;
740 }
741
742 bool FormatPointer::writeToDevice (void)
743 {
744 CHECK_DEVICE;
745
746 #ifdef DEBUG_FORMATINFO
747 m_device->debug ("\t\t\t\tafterEndCharByte: ", m_afterEndCharByte);
748 m_device->debug ("\t\t\t\tformatPropertyOffset: ", m_formatPropertyOffset);
749 #endif
750
751 m_afterEndCharBytePlus128 = m_afterEndCharByte + 128;
752
753 if (!FormatPointerGenerated::writeToDevice ())
754 return false;
755
756 return true;
757 }
758
759
760 FormatInfoPage::FormatInfoPage () : m_firstCharByte (0),
761 m_formatPointer (NULL),
762 m_formatCharProperty (NULL),
763 m_fontTable (NULL),
764 m_formatParaProperty (NULL),
765 m_leftMargin (0xFFFF), m_rightMargin (0xFFFF),
766 m_formatPointerUpto (0),
767 m_nextCharByte (0),
768 m_formatPointerPos (0), m_formatPropertyPos (123)
769 {
770 // m_type=
771 // m_lastPropertyOffset=
772 // m_numProperty=
773 }
774
775 FormatInfoPage::~FormatInfoPage ()
776 {
777 delete [] m_formatParaProperty;
778 delete [] m_formatCharProperty;
779 delete [] m_formatPointer;
780 }
781
782
783 bool FormatInfoPage::readFromDevice (void)
784 {
785 CHECK_DEVICE;
786
787 #ifdef DEBUG_FORMATINFO
788 if (m_type == ParaType)
789 m_device->debug ("FormatInfoPage::readFromDevice (ParaType)\n");
790 else // if (m_type == CharType)
791 m_device->debug ("FormatInfoPage::readFromDevice (CharType)\n");
792 #endif
793
794 if (!FormatInfoPageGenerated::readFromDevice ())
795 return false;
796
797 m_firstCharByte = FormatInfoPageGenerated::m_firstCharBytePlus128 - 128;
798
799 #ifdef DEBUG_FORMATINFO
800 m_device->debug ("number of FormatPointers on this page: ", FormatInfoPageGenerated::m_numFormatPointers);
801 m_device->debug ("byte number of first character covered by this page: ", m_firstCharByte);
802 #endif
803
804 return true;
805 }
806
807 bool FormatInfoPage::writeToDevice (void)
808 {
809 CHECK_DEVICE;
810
811 #ifdef DEBUG_FORMATINFO
812 if (m_type == ParaType)
813 m_device->debug ("FormatInfoPage::writeToDevice (ParaType)\n");
814 else // if (m_type == CharType)
815 m_device->debug ("FormatInfoPage::writeToDevice (CharType)\n");
816 #endif
817
818 FormatInfoPageGenerated::m_firstCharBytePlus128 = m_firstCharByte + 128;
819
820 #ifdef DEBUG_FORMATINFO
821 m_device->debug ("\tnumber of FormatPointers on this page: ", FormatInfoPageGenerated::m_numFormatPointers);
822 m_device->debug ("\tbyte number of first character covered by this page: ", m_firstCharByte);
823 #endif
824
825 // will call FormatInfoPageGenerated::writeToArray()...
826 // ...which will resolve to FormatInfoPage::writeToArray()...
827 // which will then call the base FormatInfoPageGenerated::writeToArray()
828 return FormatInfoPageGenerated::writeToDevice ();
829 }
830
831 bool FormatInfoPage::writeToArray (void)
832 {
833 CHECK_DEVICE;
834
835 #ifdef DEBUG_FORMATINFO
836 if (m_type == ParaType)
837 m_device->debug ("\tFormatInfoPage::writeToArray (ParaType)\n");
838 else // if (m_type == CharType)
839 m_device->debug ("\tFormatInfoPage::writeToArray (CharType)\n");
840 #endif
841
842 MemoryDevice memdev;
843
844 m_formatPointerPos = 0;
845 m_formatPropertyPos = 123;
846
847 #ifdef DEBUG_FORMATINFO
848 m_device->debug ("\t\tWriting FormatPointer[], num=", m_numFormatPointers);
849 #endif
850 for (int i = 0; i < m_numFormatPointers; i++)
851 {
852 #ifdef DEBUG_FORMATINFO
853 m_device->debug ("\t\t\tOffset=", m_formatPointerPos);
854 #endif
855 // write FormatPointer
856 memdev.setCache (m_packedStructs + m_formatPointerPos);
857 m_formatPointer [i].setDevice (&memdev);
858 if (!m_formatPointer [i].writeToDevice ()) return false;
859 memdev.setCache (NULL);
860 m_formatPointerPos += FormatPointer::s_size;
861 }
862
863 #ifdef DEBUG_FORMATINFO
864 m_device->debug ("\t\tWriting FormatProperty[], num=", m_numProperty);
865 #endif
866 for (int i = 0; i < m_numProperty; i++)
867 {
868 // write FormatProperty
869 if (m_type == ParaType)
870 {
871 FormatParaProperty *prop = &m_formatParaProperty [i];
872
873 m_formatPropertyPos -= (sizeof (Byte) + prop->getNumDataBytes ());
874 memdev.setCache (m_packedStructs + m_formatPropertyPos);
875 prop->setDevice (&memdev); // device was set to m_device to keep operator== happy in FormatInfoPage::add
876 if (!prop->writeToDevice ()) return false;
877 memdev.setCache (NULL);
878 }
879 else // if (m_type == CharType)
880 {
881 FormatCharProperty *prop = &m_formatCharProperty [i];
882
883 m_formatPropertyPos -= (sizeof (Byte) + prop->getNumDataBytes ());
884 memdev.setCache (m_packedStructs + m_formatPropertyPos);
885 prop->setDevice (&memdev); // device was set to m_device to keep operator== happy in FormatInfoPage::add
886 if (!prop->writeToDevice ()) return false;
887 memdev.setCache (NULL);
888 }
889 #ifdef DEBUG_FORMATINFO
890 m_device->debug ("\t\t\tWrote at Offset=", m_formatPropertyPos);
891 #endif
892 }
893
894 if (!FormatInfoPageGenerated::writeToArray ())
895 return false;
896
897 return true;
898 }
899
900 void *FormatInfoPage::begin (void)
901 {
902 CHECK_DEVICE;
903
904 #ifdef DEBUG_FORMATINFO
905 if (m_type == ParaType)
906 m_device->debug ("\nFormatInfoPage::begin (ParaType)\n");
907 else // if (m_type == CharType)
908 m_device->debug ("\nFormatInfoPage::begin (CharType)\n");
909 #endif
910
911 m_formatPointerUpto = 0;
912 m_nextCharByte = 0; // for consistency checking
913
914 m_lastPropertyOffset = -1;
915
916 if (!m_formatPointer)
917 {
918 m_formatPointer = new FormatPointer [1];
919
920 if (!m_formatPointer)
921 {
922 m_device->error (Error::OutOfMemory, "could not allocate memory for FormatPointer\n");
923 return NULL;
924 }
925
926 m_formatPointer->setDevice (m_device);
927 }
928
929 return this->next ();
930 }
931
932 void *FormatInfoPage::next (void)
933 {
934 void *ret;
935
936 #ifdef DEBUG_FORMATINFO
937 if (m_type == ParaType)
938 m_device->debug ("\tPara FormatPointer #", m_formatPointerUpto);
939 else // if (m_type == CharType)
940 m_device->debug ("\tChar FormatPointer #", m_formatPointerUpto);
941 #endif
942
943
944 //
945 // read Format Pointer
946 //
947
948 // check Format Pointer allocated
949 if (!m_formatPointer)
950 {
951 m_device->error (Error::InternalError, "formatPointer not initialised - call FormatInfoPage::begin() before next()\n");
952 return NULL;
953 }
954
955 // read next Format Pointer (fixed length)
956 m_device->setCache (m_packedStructs + m_formatPointerUpto * FormatPointer::s_size);
957 if (!m_formatPointer->readFromDevice ()) return NULL;
958 m_device->setCache (NULL);
959 DWord formatPointerAfterEndCharByte = m_formatPointer->getAfterEndCharByte ();
960
961 // check that it continues on from the last
962 if (formatPointerAfterEndCharByte <= m_nextCharByte)
963 m_device->error (Error::Warn, "FormatPointer afterEndCharByte does not go forward\n");
964 m_nextCharByte = formatPointerAfterEndCharByte;
965
966 // check whether it is the last one (EOF-wise)
967 if (formatPointerAfterEndCharByte >= m_header->getNumCharBytes ())
968 {
969 #ifdef DEBUG_FORMATINFO
970 m_device->debug ("\t\tThis is the last FormatPointer!\n");
971 #endif
972
973 // past EOF?
974 if (formatPointerAfterEndCharByte > m_header->getNumCharBytes ())
975 {
976 m_device->error (Error::Warn, "FormatPointer ends after EOF, forcing it to end at EOF\n");
977 m_formatPointer->setAfterEndCharByte (m_header->getNumCharBytes ());
978 m_nextCharByte = m_header->getNumCharBytes ();
979 }
980
981 // but there are still more FormatPointers left?
982 if (m_formatPointerUpto != m_numFormatPointers - 1)
983 {
984 m_device->error (Error::Warn, "FormatPointer ends at EOF but is not the last, forcing it to be the last\n");
985 m_formatPointerUpto = m_numFormatPointers - 1; // m_formatPointerUpto will get incremented at the end of this function
986 }
987 }
988
989
990 //
991 // read in corresponding Format Property
992 //
993 int currentPropertyOffset = m_formatPointer->getFormatPropertyOffset ();
994
995 bool up2date = (currentPropertyOffset == m_lastPropertyOffset);
996 if (!up2date) m_device->setCache (m_packedStructs + currentPropertyOffset);
997
998 if (m_type == CharType)
999 {
1000 if (!up2date)
1001 {
1002 // reset to defaults
1003 delete [] m_formatCharProperty;
1004 m_formatCharProperty = new FormatCharProperty [1];
1005
1006 if (!m_formatCharProperty)
1007 {
1008 m_device->error (Error::OutOfMemory, "could not allocate memory for FormatCharProperty\n");
1009 m_device->setCache (NULL);
1010 return NULL;
1011 }
1012
1013 m_formatCharProperty->setDevice (m_device);
1014 m_formatCharProperty->setFontTable (m_fontTable);
1015 if (!m_formatCharProperty->updateFont ())
1016 {
1017 m_device->setCache (NULL);
1018 return NULL;
1019 }
1020
1021 // corresponding charProperty structure exists?
1022 if (currentPropertyOffset != 0xFFFF)
1023 {
1024 if (!m_formatCharProperty->readFromDevice ())
1025 {
1026 m_device->setCache (NULL);
1027 return NULL;
1028 }
1029 }
1030 }
1031
1032 assert (m_formatCharProperty);
1033 m_formatCharProperty->setAfterEndCharByte (m_formatPointer->getAfterEndCharByte ());
1034 ret = m_formatCharProperty;
1035 }
1036 else // if (m_type == ParaType)
1037 {
1038 if (!up2date)
1039 {
1040 // reset to defaults
1041 delete [] m_formatParaProperty;
1042 m_formatParaProperty = new FormatParaProperty [1];
1043
1044 if (!m_formatParaProperty)
1045 {
1046 m_device->error (Error::OutOfMemory, "could not allocate memory for FormatParaProperty\n");
1047 m_device->setCache (NULL);
1048 return NULL;
1049 }
1050
1051 m_formatParaProperty->setDevice (m_device);
1052 m_formatParaProperty->setMargins (m_leftMargin, m_rightMargin);
1053
1054 // corresponding paraProperty structure exists?
1055 if (currentPropertyOffset != 0xFFFF)
1056 {
1057 if (!m_formatParaProperty->readFromDevice ())
1058 {
1059 m_device->setCache (NULL);
1060 return NULL;
1061 }
1062 }
1063 }
1064
1065 assert (m_formatParaProperty);
1066 m_formatParaProperty->setAfterEndCharByte (m_formatPointer->getAfterEndCharByte ());
1067 ret = m_formatParaProperty;
1068 }
1069
1070 if (!up2date) m_device->setCache (NULL);
1071 m_lastPropertyOffset = currentPropertyOffset;
1072
1073 m_formatPointerUpto++;
1074 assert (m_formatPointer);
1075 return ret;
1076 }
1077
1078 bool FormatInfoPage::end (void) const
1079 {
1080 assert (m_formatPointerUpto <= FormatInfoPageGenerated::m_numFormatPointers);
1081 return m_formatPointerUpto >= FormatInfoPageGenerated::m_numFormatPointers;
1082 }
1083
1084 bool FormatInfoPage::add (const void *property)
1085 {
1086 CHECK_DEVICE;
1087
1088 // MaxElements is true for FormatPointers since you can't have partial FormatPointers
1089 // This is also true for FormatProperties because m_numFormatPointer >= m_numProperty
1090 // so MaxElements is also the upper limit on the number of properties
1091 const int MaxElements = 123 / FormatPointer::s_size;
1092
1093 #ifdef DEBUG_FORMATINFO
1094 if (m_type == ParaType)
1095 m_device->debug (">>>> FormatInfoPage::add (ParaType) <<<<\n");
1096 else // if (m_type == CharType)
1097 m_device->debug (">>>> FormatInfoPage::add (CharType) <<<<\n");
1098
1099 Dump (formatPointerPos);
1100 Dump (formatPropertyPos);
1101 #endif
1102
1103
1104 //
1105 // Allocated memory for FormatPointers yet?
1106 //
1107
1108 if (!m_formatPointer)
1109 {
1110 #ifdef DEBUG_FORMATINFO
1111 m_device->debug ("\tFIRST CALL! Allocating memory for FormatPointer[] and FormatProperty[]\n");
1112 #endif
1113
1114 // allocate memory for FormatPointers
1115 m_formatPointer = new FormatPointer [MaxElements + 1]; // lazy memory allocation (+1 in case we can merge the last one)
1116 if (!m_formatPointer)
1117 ErrorAndQuit (Error::OutOfMemory, "could not allocate memory for formatPointer[]\n");
1118 // don't need to use m_formatPointerUpto here
1119 FormatInfoPageGenerated::m_numFormatPointers = 0;
1120
1121 // ok, better allocate memory for relevant FormatProperties
1122 if (m_type == ParaType)
1123 {
1124 assert (!m_formatParaProperty);
1125 m_formatParaProperty = new FormatParaProperty [MaxElements + 1]; // lazy memory allocation (+1 for default prop)
1126 m_formatParaProperty [MaxElements].setDevice (m_device); // we will be == this default which has to writeToArray which NeedsDevice
1127 if (!m_formatParaProperty)
1128 ErrorAndQuit (Error::OutOfMemory, "could not allocate memory for formatParaProperty[]\n");
1129 }
1130 else // if (m_type == CharType)
1131 {
1132 assert (!m_formatCharProperty);
1133 m_formatCharProperty = new FormatCharProperty [MaxElements + 1]; // lazy memory allocation (+1 for default prop)
1134 m_formatCharProperty [MaxElements].setDevice (m_device); // we will be == this default which has to writeToArray which NeedsDevice
1135 if (!m_formatCharProperty)
1136 ErrorAndQuit (Error::OutOfMemory, "could not allocate memory for formatCharProperty[]\n");
1137 }
1138
1139 m_numProperty = 0;
1140 }
1141
1142
1143 //
1144 // Setup pointers
1145 //
1146
1147 FormatParaProperty inpp;
1148 FormatCharProperty incp;
1149
1150 if (m_type == ParaType)
1151 {
1152 #ifdef DEBUG_FORMATINFO
1153 m_device->debug ("\tTrying to add ParaProperty, #numDataBytes=", ((FormatParaProperty *) property)->getNumDataBytes ());
1154 #endif
1155
1156 inpp = *((FormatParaProperty *) property);
1157 inpp.setDevice (m_device);
1158 inpp.setAfterEndCharByte (m_device->tellInternal () - 128);
1159 inpp.setMargins (m_leftMargin, m_rightMargin);
1160 if (!inpp.updateIndents ()) return false;
1161 }
1162 else // if (m_type == CharType)
1163 {
1164 #ifdef DEBUG_FORMATINFO
1165 m_device->debug ("\tTrying to add CharProperty, #numDataBytes=", ((FormatCharProperty *) property)->getNumDataBytes ());
1166 #endif
1167
1168 incp = *((FormatCharProperty *) property);
1169 incp.setDevice (m_device);
1170 incp.setAfterEndCharByte (m_device->tellInternal () - 128);
1171 incp.setFontTable (m_fontTable);
1172 if (!incp.updateFontCode ()) return false;
1173 }
1174
1175
1176 //
1177 // Attempt to add Property to current page:
1178 //
1179 // Since MS programmers tried so hard to save space, we will do the same :)
1180 // This results in having to store variable-length structures and the use of other nasty
1181 // tricks such as having multiple FormatPointers pointing to the same FormatProperty.
1182 // Details follow in code :)
1183 //
1184
1185 // In Write, character formatting blocks can extend across paragraphs
1186 // In LibMSWrite they don't (for convenience?) so here we merge FormatPointers that have been split up
1187 // This applies _only_ to _character formatting_ and is not MS' fault but rather the design of LibMSWrite.
1188 // It should _not_ be done to paragraph formatting because I don't think the user would appreciate
1189 // several paragraphs being merged into one multi-line paragraph (changing paragraph properties would
1190 // become rather difficult...)
1191 bool checkedLastFormatPointer = false;
1192 if (m_type == CharType && m_numProperty > 0 /* && m_numFormatPointers > 0 */)
1193 {
1194 #ifdef DEBUG_FORMATINFO
1195 m_device->debug ("\tIs it the same property as last? ");
1196 #endif
1197
1198 // simply extend last FormatPointer
1199 FormatCharProperty *lastProp = (FormatCharProperty *) m_formatPointer [m_numFormatPointers - 1].getFormatProperty ();
1200 if (incp == *lastProp)
1201 {
1202 #ifdef DEBUG_FORMATINFO
1203 m_device->debug ("Yes, extending FormatPointer #", m_numFormatPointers - 1);
1204 m_device->debug ("\t\tFrom ", m_formatPointer [m_numFormatPointers - 1].getAfterEndCharByte ());
1205 #endif
1206
1207 m_formatPointer [m_numFormatPointers - 1].setAfterEndCharByte (incp.getAfterEndCharByte ());
1208
1209 #ifdef DEBUG_FORMATINFO
1210 m_device->debug ("\t\tTo: ", incp.getAfterEndCharByte ());
1211 #endif
1212 return true;
1213 }
1214
1215 checkedLastFormatPointer = true;
1216 #ifdef DEBUG_FORMATINFO
1217 m_device->debug ("No\n");
1218 #endif
1219 }
1220 #ifdef DEBUG_FORMATINFO
1221 m_device->debug ("\tSame as earlier FormatPointer? ");
1222 #endif
1223
1224 // points to same property as an earlier formatPointer?
1225 for (int i = 0; i < m_numFormatPointers - (checkedLastFormatPointer ? 1 : 0); i++)
1226 {
1227 #ifdef DEBUG_FORMATINFO
1228 m_device->debug (i);
1229 m_device->debug ("? ");
1230 #endif
1231 if (m_type == ParaType)
1232 {
1233 FormatParaProperty *prop = (FormatParaProperty *) m_formatPointer [i].getFormatProperty ();
1234 if (inpp == *prop)
1235 {
1236 // try to add new formatPointer
1237 if (m_formatPointerPos + FormatPointer::s_size > m_formatPropertyPos)
1238 {
1239 #ifdef DEBUG_FORMATINFO
1240 m_device->debug ("Yes, but out of room on this page\n");
1241 #endif
1242 return false; // not enough room
1243 }
1244
1245 #ifdef DEBUG_FORMATINFO
1246 m_device->debug ("Yes, same property as ", i);
1247 #endif
1248 m_formatPointer [m_numFormatPointers].setAfterEndCharByte (inpp.getAfterEndCharByte ());
1249 m_formatPointer [m_numFormatPointers].setFormatPropertyOffset (m_formatPointer [i].getFormatPropertyOffset ());
1250 m_formatPointer [m_numFormatPointers].setFormatProperty (prop);
1251
1252 m_formatPointerPos += FormatPointer::s_size;
1253 m_numFormatPointers++;
1254 return true;
1255 }
1256 }
1257 else // if (m_type == CharType)
1258 {
1259 FormatCharProperty *prop = (FormatCharProperty *) m_formatPointer [i].getFormatProperty ();
1260 if (incp == *prop)
1261 {
1262 // try to add new formatPointer
1263 if (m_formatPointerPos + FormatPointer::s_size > m_formatPropertyPos)
1264 {
1265 #ifdef DEBUG_FORMATINFO
1266 m_device->debug ("Yes, but out of room on this page\n");
1267 #endif
1268 return false; // not enough room
1269 }
1270
1271 #ifdef DEBUG_FORMATINFO
1272 m_device->debug ("Yes, same property as ", i);
1273 #endif
1274 m_formatPointer [m_numFormatPointers].setAfterEndCharByte (incp.getAfterEndCharByte ());
1275 m_formatPointer [m_numFormatPointers].setFormatPropertyOffset (m_formatPointer [i].getFormatPropertyOffset ());
1276 m_formatPointer [m_numFormatPointers].setFormatProperty (prop);
1277
1278 m_formatPointerPos += FormatPointer::s_size;
1279 m_numFormatPointers++;
1280 return true;
1281 }
1282 }
1283 }
1284 #ifdef DEBUG_FORMATINFO
1285 m_device->debug ("No, outputting full FormatPointer & Property\n");
1286 #endif
1287
1288 // ok we can't compress, must output a full FormatPointer & FormatProperty
1289 if (m_type == ParaType)
1290 {
1291 int nextPropertyPos = m_formatPropertyPos;
1292 if (inpp.getNumDataBytes ())
1293 nextPropertyPos -= (sizeof (Byte) + inpp.getNumDataBytes ());
1294
1295 if (m_formatPointerPos + FormatPointer::s_size > nextPropertyPos)
1296 {
1297 #ifdef DEBUG_FORMATINFO
1298 m_device->debug ("\tOut of room on this page!\n");
1299 #endif
1300 return false; // not enough room
1301 }
1302
1303 m_formatPropertyPos = nextPropertyPos;
1304 if (inpp.getNumDataBytes ())
1305 m_formatParaProperty [m_numProperty] = inpp;
1306
1307 m_formatPointer [m_numFormatPointers].setAfterEndCharByte (inpp.getAfterEndCharByte ());
1308 if (inpp.getNumDataBytes ())
1309 {
1310 m_formatPointer [m_numFormatPointers].setFormatPropertyOffset (m_formatPropertyPos);
1311 m_formatPointer [m_numFormatPointers].setFormatProperty (&m_formatParaProperty [m_numProperty]);
1312 }
1313 else
1314 {
1315 m_formatPointer [m_numFormatPointers].setFormatPropertyOffset (0xFFFF/*nowhere*/);
1316 m_formatPointer [m_numFormatPointers].setFormatProperty (&m_formatParaProperty [MaxElements]/*default*/);
1317 }
1318 m_formatPointerPos += FormatPointer::s_size;
1319
1320 if (inpp.getNumDataBytes ()) m_numProperty++;
1321 m_numFormatPointers++;
1322 return true;
1323 }
1324 else // if (m_type == CharType)
1325 {
1326 int nextPropertyPos = m_formatPropertyPos;
1327 if (incp.getNumDataBytes ())
1328 nextPropertyPos -= (sizeof (Byte) + incp.getNumDataBytes ());
1329
1330 if (m_formatPointerPos + FormatPointer::s_size > nextPropertyPos)
1331 {
1332 #ifdef DEBUG_FORMATINFO
1333 m_device->debug ("\tOut of room on this page!\n");
1334 #endif
1335 return false; // not enough room
1336 }
1337
1338 m_formatPropertyPos = nextPropertyPos;
1339 if (incp.getNumDataBytes ())
1340 m_formatCharProperty [m_numProperty] = incp;
1341
1342 m_formatPointer [m_numFormatPointers].setAfterEndCharByte (incp.getAfterEndCharByte ());
1343 if (incp.getNumDataBytes ())
1344 {
1345 m_formatPointer [m_numFormatPointers].setFormatPropertyOffset (m_formatPropertyPos);
1346 m_formatPointer [m_numFormatPointers].setFormatProperty (&m_formatCharProperty [m_numProperty]);
1347 }
1348 else
1349 {
1350 m_formatPointer [m_numFormatPointers].setFormatPropertyOffset (0xFFFF/*nowhere*/);
1351 m_formatPointer [m_numFormatPointers].setFormatProperty (&m_formatCharProperty [MaxElements]/*default*/);
1352 }
1353 m_formatPointerPos += FormatPointer::s_size;
1354
1355 if (incp.getNumDataBytes ()) m_numProperty++;
1356 m_numFormatPointers++;
1357 return true;
1358 }
1359 }
1360
1361
1362 BMP_BitmapFileHeader::BMP_BitmapFileHeader ()
1363 {
1364 }
1365
1366 BMP_BitmapFileHeader::~BMP_BitmapFileHeader ()
1367 {
1368 }
1369
1370 BMP_BitmapFileHeader &BMP_BitmapFileHeader::operator= (const BMP_BitmapFileHeader &rhs)
1371 {
1372 if (this == &rhs)
1373 return *this;
1374
1375 BMP_BitmapFileHeaderGenerated::operator= (rhs);
1376
1377 return *this;
1378 }
1379
1380 bool BMP_BitmapFileHeader::readFromDevice (void)
1381 {
1382 CHECK_DEVICE;
1383
1384 #ifdef DEBUG_IMAGE
1385 m_device->debug ("\n<<<< BMP_BitmapFileHeader::readFromDevice >>>>\n");
1386 #endif
1387
1388 if (!BMP_BitmapFileHeaderGenerated::readFromDevice ())
1389 return false;
1390
1391 #ifdef DEBUG_IMAGE
1392 Dump (magic);
1393 Dump (totalBytes);
1394 Dump (zero [0]);
1395 Dump (zero [1]);
1396 Dump (actualImageOffset);
1397 #endif
1398
1399 return true;
1400 }
1401
1402 bool BMP_BitmapFileHeader::writeToDevice (void)
1403 {
1404 CHECK_DEVICE;
1405
1406 #ifdef DEBUG_IMAGE
1407 m_device->debug ("\n<<<< BMP_BitmapFileHeader::writeToDevice >>>>\n");
1408 #endif
1409
1410 if (!BMP_BitmapFileHeaderGenerated::writeToDevice ())
1411 return false;
1412
1413 return true;
1414
1415 }
1416
1417
1418 BMP_BitmapInfoHeader::BMP_BitmapInfoHeader ()
1419 {
1420 }
1421
1422 BMP_BitmapInfoHeader::~BMP_BitmapInfoHeader ()
1423 {
1424 }
1425
1426 BMP_BitmapInfoHeader &BMP_BitmapInfoHeader::operator= (const BMP_BitmapInfoHeader &rhs)
1427 {
1428 if (this == &rhs)
1429 return *this;
1430
1431 BMP_BitmapInfoHeaderGenerated::operator= (rhs);
1432
1433 return *this;
1434 }
1435
1436 bool BMP_BitmapInfoHeader::readFromDevice (void)
1437 {
1438 CHECK_DEVICE;
1439
1440 #ifdef DEBUG_IMAGE
1441 m_device->debug ("\n<<<< BMP_BitmapInfoHeader::readFromDevice >>>>\n");
1442 #endif
1443
1444 if (!BMP_BitmapInfoHeaderGenerated::readFromDevice ())
1445 return false;
1446
1447 #ifdef DEBUG_IMAGE
1448 Dump (numHeaderBytes);
1449 Dump (width);
1450 Dump (height);
1451 Dump (numPlanes);
1452 Dump (bitsPerPixel);
1453 Dump (compression);
1454 Dump (sizeImage);
1455 Dump (xPixelsPerMeter);
1456 Dump (yPixelsPerMeter);
1457 Dump (coloursUsed);
1458 Dump (coloursImportant);
1459 #endif
1460
1461 return true;
1462 }
1463
1464 bool BMP_BitmapInfoHeader::writeToDevice (void)
1465 {
1466 CHECK_DEVICE;
1467
1468 #ifdef DEBUG_IMAGE
1469 m_device->debug ("\n<<<< BMP_BitmapInfoHeader::writeToDevice >>>>\n");
1470 #endif
1471
1472 if (!BMP_BitmapInfoHeaderGenerated::writeToDevice ())
1473 return false;
1474
1475 return true;
1476 }
1477
1478
1479 BMP_BitmapColourIndex::BMP_BitmapColourIndex ()
1480 {
1481 }
1482
1483 BMP_BitmapColourIndex::~BMP_BitmapColourIndex ()
1484 {
1485 }
1486
1487 BMP_BitmapColourIndex &BMP_BitmapColourIndex::operator= (const BMP_BitmapColourIndex &rhs)
1488 {
1489 if (this == &rhs)
1490 return *this;
1491
1492 BMP_BitmapColourIndexGenerated::operator= (rhs);
1493
1494 return *this;
1495 }
1496
1497
1498 BitmapHeader::BitmapHeader ()
1499 {
1500 }
1501
1502 BitmapHeader::~BitmapHeader ()
1503 {
1504 }
1505
1506 BitmapHeader &BitmapHeader::operator= (const BitmapHeader &rhs)
1507 {
1508 if (this == &rhs)
1509 return *this;
1510
1511 BitmapHeaderGenerated::operator= (rhs);
1512
1513 return *this;
1514 }
1515
1516 bool BitmapHeader::readFromDevice (void)
1517 {
1518 CHECK_DEVICE;
1519
1520 #ifdef DEBUG_IMAGE
1521 m_device->debug ("\n<<<< BitmapHeader::readFromDevice >>>>\n");
1522 #endif
1523
1524 if (!BitmapHeaderGenerated::readFromDevice ())
1525 return false;
1526
1527 #ifdef DEBUG_IMAGE
1528 Dump (zero);
1529 Dump (width);
1530 Dump (height);
1531 Dump (widthBytes);
1532 Dump (numPlanes);
1533 Dump (bitsPerPixel);
1534 Dump (zero2);
1535 #endif
1536
1537 return true;
1538 }
1539
1540 bool BitmapHeader::writeToDevice (void)
1541 {
1542 CHECK_DEVICE;
1543
1544 #ifdef DEBUG_IMAGE
1545 m_device->debug ("\n>>>> BitmapHeader::writeToDevice <<<<\n");
1546 #endif
1547
1548 if (!BitmapHeaderGenerated::writeToDevice ())
1549 return false;
1550
1551 return true;
1552 }
1553
1554
1555 WMFHeader::WMFHeader ()
1556 {
1557 }
1558
1559 WMFHeader::~WMFHeader ()
1560 {
1561 }
1562
1563 WMFHeader &WMFHeader::operator= (const WMFHeader &rhs)
1564 {
1565 if (this == &rhs)
1566 return *this;
1567
1568 WMFHeaderGenerated::operator= (rhs);
1569
1570 return *this;
1571 }
1572
1573 bool WMFHeader::readFromDevice (void)
1574 {
1575 CHECK_DEVICE;
1576
1577 #ifdef DEBUG_IMAGE
1578 m_device->debug ("\n<<<< WMFHeader::readFromDevice >>>>\n");
1579 #endif
1580
1581 if (!WMFHeaderGenerated::readFromDevice ())
1582 return false;
1583
1584 #ifdef DEBUG_IMAGE
1585 Dump (fieldType);
1586 Dump (headerSize);
1587 Dump (winVersion);
1588 Dump (fileSize);
1589 Dump (numObjects);
1590 Dump (maxRecordSize);
1591 Dump (zero);
1592 #endif
1593
1594 return true;
1595 }
1596
1597 bool WMFHeader::writeToDevice (void)
1598 {
1599 CHECK_DEVICE;
1600
1601 #ifdef DEBUG_IMAGE
1602 m_device->debug ("\n>>>> WMFHeader::writeToDevice <<<<\n");
1603 #endif
1604
1605 #ifdef DEBUG_IMAGE
1606 Dump (fieldType);
1607 Dump (headerSize);
1608 Dump (winVersion);
1609 Dump (fileSize);
1610 Dump (numObjects);
1611 Dump (maxRecordSize);
1612 Dump (zero);
1613 #endif
1614
1615 if (!WMFHeaderGenerated::writeToDevice ())
1616 return false;
1617
1618 return true;
1619 }
1620} // namespace MSWrite {
1621
1622// end of structures_private.cpp