/* -*- 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(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: */