26
26
#include "WP3Listener.h"
27
#include "WP3FileStructure.h"
28
#include "WPXFileStructure.h"
29
#include "libwpd_internal.h"
30
#include "WP3SubDocument.h"
32
_WP3ParsingState::_WP3ParsingState():
38
m_noteReference.clear();
41
_WP3ParsingState::~_WP3ParsingState()
44
m_noteReference.clear();
45
DELETEP(m_cellFillColor);
48
WP3Listener::WP3Listener(std::vector<WPXPageSpan *> *pageList, WPXHLListenerImpl *listenerImpl) :
49
WPXListener(pageList, listenerImpl),
50
m_parseState(new WP3ParsingState)
54
WP3Listener::~WP3Listener()
60
/****************************************
61
public 'HLListenerImpl' functions
62
*****************************************/
64
void WP3Listener::insertCharacter(const uint16_t character)
68
if (!m_ps->m_isSpanOpened)
70
appendUCS4(m_parseState->m_textBuffer, (uint32_t)character);
74
void WP3Listener::insertTab(const uint8_t tabType, const float tabPosition)
78
if (!m_ps->m_isSpanOpened)
82
m_listenerImpl->insertTab();
86
void WP3Listener::insertEOL()
90
if (m_ps->m_isTableOpened)
92
if (!m_ps->m_isTableRowOpened)
95
if (!m_ps->m_isTableCellOpened)
101
if (!m_ps->m_isParagraphOpened && !m_ps->m_isListElementOpened)
103
if (m_ps->m_isParagraphOpened)
105
if (m_ps->m_isListElementOpened)
111
void WP3Listener::endDocument()
117
m_listenerImpl->endDocument();
120
void WP3Listener::defineTable(const uint8_t position, const uint16_t leftOffset)
124
switch (position & 0x07)
127
m_ps->m_tableDefinition.m_positionBits = WPX_TABLE_POSITION_ALIGN_WITH_LEFT_MARGIN;
130
m_ps->m_tableDefinition.m_positionBits = WPX_TABLE_POSITION_ALIGN_WITH_RIGHT_MARGIN;
133
m_ps->m_tableDefinition.m_positionBits = WPX_TABLE_POSITION_CENTER_BETWEEN_MARGINS;
136
m_ps->m_tableDefinition.m_positionBits = WPX_TABLE_POSITION_FULL;
139
m_ps->m_tableDefinition.m_positionBits = WPX_TABLE_POSITION_ABSOLUTE_FROM_LEFT_MARGIN;
145
// Note: WordPerfect has an offset from the left edge of the page. We translate it to the offset from the left margin
146
m_ps->m_tableDefinition.m_leftOffset = (float)((double)leftOffset / (double)WPX_NUM_WPUS_PER_INCH) - m_ps->m_paragraphMarginLeft;
148
// remove all the old column information
149
m_ps->m_tableDefinition.columns.clear();
150
m_ps->m_tableDefinition.columnsProperties.clear();
151
m_ps->m_numRowsToSkip.clear();
155
void WP3Listener::addTableColumnDefinition(const uint32_t width, const uint32_t leftGutter, const uint32_t rightGutter, const uint32_t attributes, const uint8_t alignment)
159
// define the new column
160
WPXColumnDefinition colDef;
161
colDef.m_width = (float)((double)width / (double)WPX_NUM_WPUS_PER_INCH);
162
colDef.m_leftGutter = (float)((double)width / (double)WPX_NUM_WPUS_PER_INCH);
163
colDef.m_rightGutter = (float)((double)width / (double)WPX_NUM_WPUS_PER_INCH);
165
// add the new column definition to our table definition
166
m_ps->m_tableDefinition.columns.push_back(colDef);
168
WPXColumnProperties colProp;
169
colProp.m_attributes = attributes;
170
colProp.m_alignment = alignment;
172
m_ps->m_tableDefinition.columnsProperties.push_back(colProp);
174
// initialize the variable that tells us how many columns to skip
175
m_ps->m_numRowsToSkip.push_back(0);
179
void WP3Listener::startTable()
183
// save the justification information. We will need it after the table ends.
184
m_ps->m_paragraphJustificationBeforeTable = m_ps->m_paragraphJustification;
185
if (m_ps->m_sectionAttributesChanged && !m_ps->m_isTableOpened)
187
m_ps->m_sectionAttributesChanged = false;
188
if (!m_ps->m_isTableOpened && !m_ps->m_isSectionOpened)
194
void WP3Listener::insertRow()
197
_openTableRow(0, true, false);
200
void WP3Listener::insertCell()
204
if (m_ps->m_currentTableRow < 0) // cell without a row, invalid
205
throw ParseException();
207
RGBSColor tmpCellBorderColor(0x00, 0x00, 0x00, 0x64);
208
_openTableCell((uint8_t)m_parseState->m_colSpan, (uint8_t)m_parseState->m_rowSpan, 0x00000000,
209
m_parseState->m_cellFillColor, NULL, &tmpCellBorderColor, TOP);
210
DELETEP(m_parseState->m_cellFillColor);
212
m_ps->m_isCellWithoutParagraph = true;
213
m_ps->m_cellAttributeBits = 0x00000000;
217
void WP3Listener::closeCell()
223
m_parseState->m_rowSpan = 1;
224
m_parseState->m_colSpan = 1;
228
void WP3Listener::closeRow()
238
void WP3Listener::setTableCellSpan(const uint16_t colSpan, const uint16_t rowSpan)
242
m_parseState->m_colSpan=colSpan;
243
m_parseState->m_rowSpan=rowSpan;
247
void WP3Listener::setTableCellFillColor(const RGBSColor * cellFillColor)
251
if (m_parseState->m_cellFillColor)
252
DELETEP(m_parseState->m_cellFillColor);
253
m_parseState->m_cellFillColor = new RGBSColor(*cellFillColor);
257
void WP3Listener::endTable()
263
// restore the justification that was there before the table.
264
m_ps->m_paragraphJustification = m_ps->m_paragraphJustificationBeforeTable;
269
/****************************************
270
public 'parser' functions
271
*****************************************/
273
void WP3Listener::attributeChange(const bool isOn, const uint8_t attribute)
279
uint32_t textAttributeBit = 0;
281
// FIXME: handle all the possible attribute bits
284
case WP3_ATTRIBUTE_BOLD:
285
textAttributeBit = WPX_BOLD_BIT;
287
case WP3_ATTRIBUTE_ITALICS:
288
textAttributeBit = WPX_ITALICS_BIT;
290
case WP3_ATTRIBUTE_UNDERLINE:
291
textAttributeBit = WPX_UNDERLINE_BIT;
293
case WP3_ATTRIBUTE_OUTLINE:
294
textAttributeBit = WPX_OUTLINE_BIT;
296
case WP3_ATTRIBUTE_SHADOW:
297
textAttributeBit = WPX_SHADOW_BIT;
299
case WP3_ATTRIBUTE_REDLINE:
300
textAttributeBit = WPX_REDLINE_BIT;
302
case WP3_ATTRIBUTE_STRIKE_OUT:
303
textAttributeBit = WPX_STRIKEOUT_BIT;
305
case WP3_ATTRIBUTE_SUBSCRIPT:
306
textAttributeBit = WPX_SUBSCRIPT_BIT;
308
case WP3_ATTRIBUTE_SUPERSCRIPT:
309
textAttributeBit = WPX_SUPERSCRIPT_BIT;
311
case WP3_ATTRIBUTE_DOUBLE_UNDERLINE:
312
textAttributeBit = WPX_DOUBLE_UNDERLINE_BIT;
314
case WP3_ATTRIBUTE_EXTRA_LARGE:
315
textAttributeBit = WPX_EXTRA_LARGE_BIT;
317
case WP3_ATTRIBUTE_VERY_LARGE:
318
textAttributeBit = WPX_VERY_LARGE_BIT;
320
case WP3_ATTRIBUTE_LARGE:
321
textAttributeBit = WPX_LARGE_BIT;
323
case WP3_ATTRIBUTE_SMALL_PRINT:
324
textAttributeBit = WPX_SMALL_PRINT_BIT;
326
case WP3_ATTRIBUTE_FINE_PRINT:
327
textAttributeBit = WPX_FINE_PRINT_BIT;
329
case WP3_ATTRIBUTE_SMALL_CAPS:
330
textAttributeBit = WPX_SMALL_CAPS_BIT;
335
m_ps->m_textAttributeBits |= textAttributeBit;
337
m_ps->m_textAttributeBits ^= textAttributeBit;
341
void WP3Listener::undoChange(const uint8_t undoType, const uint16_t undoLevel)
343
if (undoType == 0x00) // begin invalid text
345
else if (undoType == 0x01) // end invalid text
349
void WP3Listener::marginChange(const uint8_t side, const uint16_t margin)
353
float marginInch = (float)((double)margin/ (double)WPX_NUM_WPUS_PER_INCH);
358
m_ps->m_leftMarginByPageMarginChange = marginInch - m_ps->m_pageMarginLeft;
359
m_ps->m_paragraphMarginLeft = m_ps->m_leftMarginByPageMarginChange
360
+ m_ps->m_leftMarginByParagraphMarginChange
361
+ m_ps->m_leftMarginByTabs;
364
m_ps->m_rightMarginByPageMarginChange = marginInch - m_ps->m_pageMarginRight;
365
m_ps->m_paragraphMarginRight = m_ps->m_rightMarginByPageMarginChange
366
+ m_ps->m_rightMarginByParagraphMarginChange
367
+ m_ps->m_rightMarginByTabs;
370
m_ps->m_listReferencePosition = m_ps->m_paragraphMarginLeft + m_ps->m_paragraphTextIndent;
374
void WP3Listener::justificationChange(const uint8_t justification)
378
// could be done simply by:
379
// m_ps->m_paragraphJustification = justification;
380
switch (justification)
383
m_ps->m_paragraphJustification = WPX_PARAGRAPH_JUSTIFICATION_LEFT;
386
m_ps->m_paragraphJustification = WPX_PARAGRAPH_JUSTIFICATION_CENTER;
389
m_ps->m_paragraphJustification = WPX_PARAGRAPH_JUSTIFICATION_RIGHT;
392
m_ps->m_paragraphJustification = WPX_PARAGRAPH_JUSTIFICATION_FULL;
395
m_ps->m_paragraphJustification = WPX_PARAGRAPH_JUSTIFICATION_FULL_ALL_LINES;
398
m_ps->m_paragraphJustification = WPX_PARAGRAPH_JUSTIFICATION_DECIMAL_ALIGNED;
404
void WP3Listener::indentFirstLineChange(const int16_t offset)
408
float offsetInch = (float)((double)offset / (double)WPX_NUM_WPUS_PER_INCH);
409
m_ps->m_textIndentByParagraphIndentChange = offsetInch;
410
// This is necessary in case we have Indent First Line and Hard Back Tab
411
// in the same time. The Hard Back Tab applies to the current paragraph
412
// only. Indent First Line applies untill an new Indent First Line code.
413
m_ps->m_paragraphTextIndent = m_ps->m_textIndentByParagraphIndentChange
414
+ m_ps->m_textIndentByTabs;
415
m_ps->m_listReferencePosition = m_ps->m_paragraphMarginLeft + m_ps->m_paragraphTextIndent;
419
void WP3Listener::columnChange(const WPXTextColumnType columnType, const uint8_t numColumns, const std::vector<float> &columnWidth,
420
const std::vector<bool> &isFixedWidth)
424
// In WP, the last column ends with a hard column break code.
425
// In this case, we do not really want to insert any column break
426
m_ps->m_isParagraphColumnBreak = false;
427
m_ps->m_isTextColumnWithoutParagraph = false;
429
float remainingSpace = m_ps->m_pageFormWidth - m_ps->m_pageMarginLeft - m_ps->m_pageMarginRight
430
- m_ps->m_leftMarginByPageMarginChange - m_ps->m_rightMarginByPageMarginChange;
431
// determine the space that is to be divided between columns whose width is expressed in percentage of remaining space
432
std::vector<WPXColumnDefinition> tmpColumnDefinition;
433
tmpColumnDefinition.clear();
437
for (i=0; i<columnWidth.size(); i++)
440
remainingSpace -= columnWidth[i];
442
WPXColumnDefinition tmpColumn;
443
for (i=0; i<numColumns; i++)
446
tmpColumn.m_leftGutter = 0.0f;
447
else if (isFixedWidth[2*i-1])
448
tmpColumn.m_leftGutter = 0.5f * columnWidth[2*i-1];
450
tmpColumn.m_leftGutter = 0.5f * remainingSpace * columnWidth[2*i-1];
452
if (i >= (numColumns - 1))
453
tmpColumn.m_rightGutter = 0.0f;
454
else if (isFixedWidth[2*i+1])
455
tmpColumn.m_rightGutter = 0.5f * columnWidth[2*i+1];
457
tmpColumn.m_rightGutter = 0.5f * remainingSpace * columnWidth[2*i+1];
459
if (isFixedWidth[2*i])
460
tmpColumn.m_width = columnWidth[2*i];
462
tmpColumn.m_width = remainingSpace * columnWidth[2*i];
464
tmpColumn.m_width += tmpColumn.m_leftGutter + tmpColumn.m_rightGutter;
466
tmpColumnDefinition.push_back(tmpColumn);
470
if (!m_ps->m_inSubDocument && !m_ps->m_isTableOpened)
473
m_ps->m_sectionAttributesChanged = true;
474
m_ps->m_numColumns = numColumns;
475
m_ps->m_textColumns = tmpColumnDefinition;
476
m_ps->m_isTextColumnWithoutParagraph = true;
481
void WP3Listener::setTextColor(const RGBSColor *fontColor)
487
*(m_ps->m_fontColor) = *fontColor;
491
void WP3Listener::setTextFont(const std::string fontName)
497
m_ps->m_fontName->sprintf("%s", fontName.c_str());
501
void WP3Listener::setFontSize(const uint16_t fontSize)
507
m_ps->m_fontSize=float(fontSize);
511
void WP3Listener::insertNoteReference(const std::string noteReference)
515
m_parseState->m_noteReference.sprintf("%s", noteReference.c_str());
519
void WP3Listener::insertNote(const WPXNoteType noteType, const WP3SubDocument *subDocument)
524
m_ps->m_isNote = true;
525
WPXNumberingType numberingType = _extractWPXNumberingTypeFromBuf(m_parseState->m_noteReference, ARABIC);
526
int number = _extractDisplayReferenceNumberFromBuf(m_parseState->m_noteReference, numberingType);
527
m_parseState->m_noteReference.clear();
529
WPXPropertyList propList;
530
propList.insert("libwpd:number", number);
532
if (noteType == FOOTNOTE)
533
m_listenerImpl->openFootnote(propList);
535
m_listenerImpl->openEndnote(propList);
537
handleSubDocument(subDocument, false, m_parseState->m_tableList, 0);
539
if (noteType == FOOTNOTE)
540
m_listenerImpl->closeFootnote();
542
m_listenerImpl->closeEndnote();
543
m_ps->m_isNote = false;
547
void WP3Listener::_handleSubDocument(const WPXSubDocument *subDocument, const bool isHeaderFooter, WPXTableList tableList, int nextTableIndice)
549
// save our old parsing state on our "stack"
550
WP3ParsingState *oldParseState = m_parseState;
552
m_parseState = new WP3ParsingState();
555
subDocument->parse(this);
559
// Close the sub-document properly
560
if (m_ps->m_isParagraphOpened)
562
if (m_ps->m_isListElementOpened)
565
m_ps->m_currentListLevel = 0;
572
// restore our old parsing state
574
m_parseState = oldParseState;
577
void WP3Listener::_openParagraph()
580
if (m_ps->m_isTableOpened)
582
if (!m_ps->m_isTableRowOpened)
585
if (!m_ps->m_isTableCellOpened)
591
WPXListener::_openParagraph();
594
/****************************************
596
*****************************************/
598
void WP3Listener::_flushText()
600
if (m_parseState->m_textBuffer.len())
601
m_listenerImpl->insertText(m_parseState->m_textBuffer);
602
m_parseState->m_textBuffer.clear();
28
WP3Listener::WP3Listener(std::list<WPXPageSpan> &pageList, WPXHLListenerImpl *listenerImpl)