/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4 -*- */
/* libwpd
* Version: MPL 2.0 / LGPLv2.1+
*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
*
* Major Contributor(s):
* Copyright (C) 2002 William Lachance (wrlach@gmail.com)
* Copyright (C) 2002 Marc Maurer (uwog@uwog.net)
* Copyright (C) 2004 Fridrich Strba (fridrich.strba@bluewin.ch)
*
* For minor contributions see the git repository.
*
* Alternatively, the contents of this file may be used under the terms
* of the GNU Lesser General Public License Version 2.1 or later
* (LGPLv2.1+), in which case the provisions of the LGPLv2.1+ are
* applicable instead of those above.
*
* For further information visit http://libwpd.sourceforge.net
*/
/* "This product is not manufactured, approved, or supported by
* Corel Corporation or Corel Corporation Limited."
*/
#include "WP6CharacterGroup.h"
#include "WP6FileStructure.h"
#include "WP6Listener.h"
#include "libwpd_internal.h"
#include "WP6CommentAnnotationPacket.h"
#include "WP6FontDescriptorPacket.h"
/*************************************************************************
* WP6CharacterGroup_SetAlignmentCharacterSubGroup
*************************************************************************/
WP6CharacterGroup_SetAlignmentCharacterSubGroup::WP6CharacterGroup_SetAlignmentCharacterSubGroup(librevenge::RVNGInputStream *input, WPXEncryption *encryption) :
m_character(0),
m_characterSet(0)
{
unsigned short charWord = readU16(input, encryption);
m_characterSet = (unsigned char)((charWord >> 8) & 0x00FF);
m_character = (unsigned char)(charWord & 0x00FF);
}
void WP6CharacterGroup_SetAlignmentCharacterSubGroup::parse(WP6Listener *listener, const unsigned char /* numPrefixIDs */,
unsigned short const * /* prefixIDs */) const
{
const unsigned *chars;
extendedCharacterWP6ToUCS4(m_character, m_characterSet, &chars);
WPD_DEBUG_MSG(("WordPerfect: Parsing Set Alignment Character (alignment character: 0x%.4x)\n", chars[0]));
listener->setAlignmentCharacter(chars[0]);
}
/*************************************************************************
* WP6CharacterGroup_ColorSubGroup
*************************************************************************/
WP6CharacterGroup_ColorSubGroup::WP6CharacterGroup_ColorSubGroup(librevenge::RVNGInputStream *input, WPXEncryption *encryption) :
m_red(0), m_green(0), m_blue(0)
{
m_red = readU8(input, encryption);
m_green = readU8(input, encryption);
m_blue = readU8(input, encryption);
WPD_DEBUG_MSG(("WordPerfect: Character Group Color subgroup info (red: %i, green: %i, blue: %i)\n", m_red, m_green, m_blue));
}
void WP6CharacterGroup_ColorSubGroup::parse(WP6Listener *listener, const unsigned char /* numPrefixIDs */, unsigned short const * /* prefixIDs */) const
{
listener->characterColorChange(m_red, m_green, m_blue);
}
/*************************************************************************
* WP6CharacterGroup_CharacterShadingChangeSubGroup
*************************************************************************/
WP6CharacterGroup_CharacterShadingChangeSubGroup::WP6CharacterGroup_CharacterShadingChangeSubGroup(librevenge::RVNGInputStream *input, WPXEncryption *encryption) :
m_shading(0)
{
m_shading = readU8(input, encryption);
WPD_DEBUG_MSG(("WordPerfect: Character Group Character Shading Change subgroup info (shading: %i)\n", m_shading));
}
void WP6CharacterGroup_CharacterShadingChangeSubGroup::parse(WP6Listener *listener, const unsigned char /* numPrefixIDs */,
unsigned short const * /* prefixIDs */) const
{
listener->characterShadingChange(m_shading);
}
/*************************************************************************
* WP6CharacterGroup_FontFaceChangeSubGroups
*************************************************************************/
WP6CharacterGroup_FontFaceChangeSubGroup::WP6CharacterGroup_FontFaceChangeSubGroup(librevenge::RVNGInputStream *input, WPXEncryption *encryption, unsigned short sizeDeletable) :
m_oldMatchedPointSize(0), m_hash(0), m_matchedFontIndex(0), m_matchedFontPointSize(0), m_packet()
{
m_oldMatchedPointSize = readU16(input, encryption);
m_hash = readU16(input, encryption);
m_matchedFontIndex = readU16(input, encryption);
m_matchedFontPointSize = readU16(input, encryption);
WPD_DEBUG_MSG(("WordPerfect: Character Group Font Face Change subgroup info (old matched point size: %i, hash: %i, matched font index: %i, matched font point size: %i)\n", m_oldMatchedPointSize, m_hash, m_matchedFontIndex, m_matchedFontPointSize));
if (sizeDeletable > 24)
{
m_packet.reset(new WP6FontDescriptorPacket(input, encryption, 0, (unsigned)input->tell(), sizeDeletable));
WPD_DEBUG_MSG(("WordPerfect: Character Group Font Face Change subgroup info (font name: %s)\n", m_packet->getFontName().cstr()));
}
}
WP6CharacterGroup_FontFaceChangeSubGroup::~WP6CharacterGroup_FontFaceChangeSubGroup()
{
}
void WP6CharacterGroup_FontFaceChangeSubGroup::parse(WP6Listener *listener, const unsigned char /* numPrefixIDs */, unsigned short const *prefixIDs) const
{
WPD_DEBUG_MSG(("WordPerfect: FontFaceChangeSubGroup parsing\n"));
if (!prefixIDs)
return;
listener->fontChange(m_matchedFontPointSize, prefixIDs[0], m_packet ? m_packet->getFontName() : librevenge::RVNGString());
}
/*************************************************************************
* WP6CharacterGroup_FontSizeChangeSubGroups
*************************************************************************/
WP6CharacterGroup_FontSizeChangeSubGroup::WP6CharacterGroup_FontSizeChangeSubGroup(librevenge::RVNGInputStream *input, WPXEncryption *encryption) :
m_desiredFontPointSize(0)
{
m_desiredFontPointSize = readU16(input, encryption);
WPD_DEBUG_MSG(("WordPerfect: Character Group Font Size Change subgroup info (desired font point size: %i\n", m_desiredFontPointSize));
}
void WP6CharacterGroup_FontSizeChangeSubGroup::parse(WP6Listener *listener, const unsigned char /* numPrefixIDs */, unsigned short const *prefixIDs) const
{
WPD_DEBUG_MSG(("WordPerfect: FontSizeChangeSubGroup parsing\n"));
if (!prefixIDs)
return;
listener->fontChange(m_desiredFontPointSize, prefixIDs[0], librevenge::RVNGString());
}
/*************************************************************************
* WP6CharacterGroup_SetDotLeaderCharactersSubGroup
*************************************************************************/
WP6CharacterGroup_SetDotLeaderCharactersSubGroup::WP6CharacterGroup_SetDotLeaderCharactersSubGroup(librevenge::RVNGInputStream *input, WPXEncryption *encryption) :
m_character(0),
m_characterSet(0),
m_numberOfSpaces(0)
{
unsigned short charWord = readU16(input, encryption);
m_characterSet = (unsigned char)((charWord >> 8) & 0x00FF);
m_character = (unsigned char)(charWord & 0x00FF);
m_numberOfSpaces = readU8(input, encryption);
}
void WP6CharacterGroup_SetDotLeaderCharactersSubGroup::parse(WP6Listener *listener, const unsigned char /* numPrefixIDs */,
unsigned short const * /* prefixIDs */) const
{
const unsigned *chars;
extendedCharacterWP6ToUCS4(m_character, m_characterSet, &chars);
WPD_DEBUG_MSG(("WordPerfect: Parsing Set Dot Leader Characters (leader character: 0x%.4x), (number of spaces: %i)\n",
chars[0], m_numberOfSpaces));
listener->setLeaderCharacter(chars[0], m_numberOfSpaces);
}
/*************************************************************************
* WP6CharacterGroup_ParagraphNumberOnSubGroup
*************************************************************************/
WP6CharacterGroup_ParagraphNumberOnSubGroup::WP6CharacterGroup_ParagraphNumberOnSubGroup(librevenge::RVNGInputStream *input, WPXEncryption *encryption) :
m_outlineHash(0), m_level(0), m_flag(0)
{
m_outlineHash = readU16(input, encryption);
m_level = readU8(input, encryption);
if (m_level > WP6_NUM_LIST_LEVELS)
m_level = WP6_NUM_LIST_LEVELS - 1;
m_flag = readU8(input, encryption);
}
void WP6CharacterGroup_ParagraphNumberOnSubGroup::parse(WP6Listener *listener, const unsigned char /* numPrefixIDs */,
unsigned short const * /* prefixIDs */) const
{
listener->paragraphNumberOn(m_outlineHash, m_level, m_flag);
}
/*************************************************************************
* WP6CharacterGroup_TableDefinitionOnSubGroup
*************************************************************************/
WP6CharacterGroup_TableDefinitionOnSubGroup::WP6CharacterGroup_TableDefinitionOnSubGroup(librevenge::RVNGInputStream *input, WPXEncryption *encryption) :
m_flags(0), m_position(0), m_leftOffset(0)
{
m_flags = readU8(input, encryption);
m_position = readU8(input, encryption);
m_leftOffset = readU16(input, encryption);
// TODO: add the remaining table properties here
}
void WP6CharacterGroup_TableDefinitionOnSubGroup::parse(WP6Listener *listener, const unsigned char /* numPrefixIDs */,
unsigned short const * /* prefixIDs */) const
{
listener->defineTable(m_position, m_leftOffset);
}
/*************************************************************************
* WP6CharacterGroup_TableDefinitionOffSubGroup
*************************************************************************/
WP6CharacterGroup_TableDefinitionOffSubGroup::WP6CharacterGroup_TableDefinitionOffSubGroup(librevenge::RVNGInputStream * /* input */, WPXEncryption * /* encryption */)
{
}
void WP6CharacterGroup_TableDefinitionOffSubGroup::parse(WP6Listener *listener, const unsigned char /* numPrefixIDs */,
unsigned short const * /* prefixIDs */) const
{
// the table is degined now; start the table
listener->startTable();
}
/*************************************************************************
* WP6CharacterGroup_TableColumnSubGroup
*************************************************************************/
WP6CharacterGroup_TableColumnSubGroup::WP6CharacterGroup_TableColumnSubGroup(librevenge::RVNGInputStream *input, WPXEncryption *encryption) :
m_flags(0), m_width(0), m_leftGutter(0), m_rightGutter(0),
m_attributes(0), m_alignment(0), m_absPosFromRight(0), m_numberType(0),
m_currencyIndex(0)
{
m_flags = readU8(input, encryption);
m_width = readU16(input, encryption);
m_leftGutter = readU16(input, encryption);
m_rightGutter = readU16(input, encryption);
m_attributes = (readU32(input, encryption) & 0x0003FFFF);
m_alignment = (readU8(input, encryption) & 0x07);
m_absPosFromRight = readU16(input, encryption);
m_numberType = readU16(input, encryption);
m_currencyIndex = readU8(input, encryption);
}
void WP6CharacterGroup_TableColumnSubGroup::parse(WP6Listener *listener, const unsigned char /* numPrefixIDs */, unsigned short const * /* prefixIDs */) const
{
listener->addTableColumnDefinition(m_width, m_leftGutter, m_rightGutter, m_attributes, m_alignment);
}
/*************************************************************************
* WP6CharacterGroup_CommentSubGroup
*************************************************************************/
WP6CharacterGroup_CommentSubGroup::WP6CharacterGroup_CommentSubGroup(librevenge::RVNGInputStream * /* input */, WPXEncryption * /* encryption */)
{
}
void WP6CharacterGroup_CommentSubGroup::parse(WP6Listener *listener, const unsigned char numPrefixIDs,
unsigned short const *prefixIDs) const
{
unsigned short textPID = 0;
for (unsigned char i=0; i<numPrefixIDs; i++)
{
if (const WP6CommentAnnotationPacket *caPacket = dynamic_cast<const WP6CommentAnnotationPacket *>(listener->getPrefixDataPacket(prefixIDs[i])))
{
textPID = caPacket->getTextPID();
break;
}
}
if (textPID)
listener->commentAnnotation(textPID);
}
/*************************************************************************
* WP6CharacterGroup
*************************************************************************/
WP6CharacterGroup::WP6CharacterGroup(librevenge::RVNGInputStream *input, WPXEncryption *encryption) :
WP6VariableLengthGroup(),
m_subGroupData(nullptr)
{
_read(input, encryption);
}
WP6CharacterGroup::~WP6CharacterGroup()
{
delete m_subGroupData;
}
void WP6CharacterGroup::_readContents(librevenge::RVNGInputStream *input, WPXEncryption *encryption)
{
// this group can contain different kinds of data, thus we need to read
// the contents accordingly
switch (getSubGroup())
{
case WP6_CHARACTER_GROUP_FONT_FACE_CHANGE:
m_subGroupData = new WP6CharacterGroup_FontFaceChangeSubGroup(input, encryption, getSizeDeletable());
break;
case WP6_CHARACTER_GROUP_FONT_SIZE_CHANGE:
m_subGroupData = new WP6CharacterGroup_FontSizeChangeSubGroup(input, encryption);
break;
case WP6_CHARACTER_GROUP_SET_ALIGNMENT_CHARACTER:
m_subGroupData = new WP6CharacterGroup_SetAlignmentCharacterSubGroup(input, encryption);
break;
case WP6_CHARACTER_GROUP_COLOR:
m_subGroupData = new WP6CharacterGroup_ColorSubGroup(input, encryption);
break;
case WP6_CHARACTER_GROUP_CHARACTER_SHADING_CHANGE:
m_subGroupData = new WP6CharacterGroup_CharacterShadingChangeSubGroup(input, encryption);
break;
case WP6_CHARACTER_GROUP_SET_DOT_LEADER_CHARACTERS:
m_subGroupData = new WP6CharacterGroup_SetDotLeaderCharactersSubGroup(input, encryption);
break;
case WP6_CHARACTER_GROUP_PARAGRAPH_NUMBER_ON:
m_subGroupData = new WP6CharacterGroup_ParagraphNumberOnSubGroup(input, encryption);
break;
case WP6_CHARACTER_GROUP_TABLE_DEFINITION_ON:
m_subGroupData = new WP6CharacterGroup_TableDefinitionOnSubGroup(input, encryption);
break;
case WP6_CHARACTER_GROUP_TABLE_DEFINITION_OFF:
m_subGroupData = new WP6CharacterGroup_TableDefinitionOffSubGroup(input, encryption);
break;
case WP6_CHARACTER_GROUP_TABLE_COLUMN:
m_subGroupData = new WP6CharacterGroup_TableColumnSubGroup(input, encryption);
break;
case WP6_CHARACTER_GROUP_COMMENT:
m_subGroupData = new WP6CharacterGroup_CommentSubGroup(input, encryption);
break;
default:
break;
}
}
void WP6CharacterGroup::parse(WP6Listener *listener)
{
WPD_DEBUG_MSG(("WordPerfect: handling a Character group\n"));
switch (getSubGroup())
{
case WP6_CHARACTER_GROUP_FONT_FACE_CHANGE:
case WP6_CHARACTER_GROUP_FONT_SIZE_CHANGE:
case WP6_CHARACTER_GROUP_SET_ALIGNMENT_CHARACTER:
case WP6_CHARACTER_GROUP_COLOR:
case WP6_CHARACTER_GROUP_CHARACTER_SHADING_CHANGE:
case WP6_CHARACTER_GROUP_SET_DOT_LEADER_CHARACTERS:
case WP6_CHARACTER_GROUP_PARAGRAPH_NUMBER_ON:
case WP6_CHARACTER_GROUP_COMMENT:
m_subGroupData->parse(listener, getNumPrefixIDs(), getPrefixIDs());
break;
case WP6_CHARACTER_GROUP_PARAGRAPH_NUMBER_OFF:
listener->paragraphNumberOff();
break;
case WP6_CHARACTER_GROUP_TABLE_DEFINITION_ON:
WPD_DEBUG_MSG(("WordPerfect: TABLE Definition ON\n"));
m_subGroupData->parse(listener, getNumPrefixIDs(), getPrefixIDs());
break;
case WP6_CHARACTER_GROUP_TABLE_DEFINITION_OFF:
WPD_DEBUG_MSG(("WordPerfect: TABLE Definition OFF\n"));
m_subGroupData->parse(listener, getNumPrefixIDs(), getPrefixIDs());
break;
case WP6_CHARACTER_GROUP_TABLE_COLUMN:
WPD_DEBUG_MSG(("WordPerfect: Table Column\n"));
m_subGroupData->parse(listener, getNumPrefixIDs(), getPrefixIDs());
break;
default: // something else we don't support yet
break;
}
}
/* vim:set shiftwidth=4 softtabstop=4 noexpandtab: */