/* -*- 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)
 *
 * 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 <string.h>
#include <limits>
#include "WP6FontDescriptorPacket.h"
#include "libwpd_internal.h"
#include <string>

const char *FONT_WEIGHT_STRINGS [] = {	"Bold", "bold", "Demi", "demi", "Extended", "extended",
                                        "Extra", "extra", "Headline", "headline", "Light", "light",
                                        "Medium", "medium", "Normal", "normal", "Regular", "regular",
                                        "Standaard", "standaard", "Standard", "standard"
                                     };
const char *USELESS_WP_POSTFIX = "-WP";
#define countElements(a) ((sizeof(a) / sizeof(a[0])))

WP6FontDescriptorPacket::WP6FontDescriptorPacket(librevenge::RVNGInputStream *input, WPXEncryption *encryption, int /* id */, unsigned dataOffset, unsigned dataSize) :
	WP6PrefixDataPacket(input, encryption),
	m_characterWidth(0),
	m_ascenderHeight(0),
	m_xHeight(0),
	m_descenderHeight(0),
	m_italicsAdjust(0),
	m_primaryFamilyId(0),
	m_primaryFamilyMemberId(0),
	m_scriptingSystem(0),
	m_primaryCharacterSet(0),
	m_width(0),
	m_weight(0),
	m_attributes(0),
	m_generalCharacteristics(0),
	m_classification(0),
	m_fill(0),
	m_fontType(0),
	m_fontSourceFileType(0),
	m_fontNameLength(0),
	m_fontName()
{
	_read(input, encryption, dataOffset, dataSize);
}

WP6FontDescriptorPacket::~WP6FontDescriptorPacket()
{
}

void WP6FontDescriptorPacket::_readContents(librevenge::RVNGInputStream *input, WPXEncryption *encryption)
{
	// short sized characteristics
	m_characterWidth = readU16(input, encryption);
	m_ascenderHeight = readU16(input, encryption);
	m_xHeight = readU16(input, encryption);
	m_descenderHeight = readU16(input, encryption);
	m_italicsAdjust = readU16(input, encryption);
	// byte sized characteristics
	m_primaryFamilyMemberId = readU8(input, encryption);
	m_primaryFamilyId = readU8(input, encryption);
	m_scriptingSystem = readU8(input, encryption);
	m_primaryCharacterSet = readU8(input, encryption);
	m_width = readU8(input, encryption);
	m_weight = readU8(input, encryption);
	m_attributes = readU8(input, encryption);
	m_generalCharacteristics = readU8(input, encryption);
	m_classification = readU8(input, encryption);
	m_fill = readU8(input, encryption);
	m_fontType = readU8(input, encryption);
	m_fontSourceFileType = readU8(input, encryption);

	m_fontNameLength = readU16(input, encryption);

	_readFontName(input, encryption);
}

void WP6FontDescriptorPacket::_readFontName(librevenge::RVNGInputStream *input, WPXEncryption *encryption)
{
	if (m_fontNameLength > ((std::numeric_limits<unsigned short>::max)() / 2))
		m_fontNameLength = ((std::numeric_limits<unsigned short>::max)() / 2);
	if (m_fontNameLength)
	{
		for (unsigned short i=0; i<(m_fontNameLength/2); i++)
		{
			unsigned short charWord = readU16(input, encryption);
			auto characterSet = (unsigned char)((charWord >> 8) & 0x00FF);
			auto character = (unsigned char)(charWord & 0xFF);

			if (character == 0x00 && characterSet == 0x00)
				break;

			const unsigned *chars;
			int len = extendedCharacterWP6ToUCS4(character, characterSet, &chars);

			for (int j = 0; j < len; j++)
				appendUCS4(m_fontName, chars[j]);
		}

		WPD_DEBUG_MSG(("WordPerfect: stripping font name (original: %s)\n", m_fontName.cstr()));
		std::string stringValue(m_fontName.cstr());
		std::string::size_type pos;
		for (auto &k : FONT_WEIGHT_STRINGS)
		{
			if (!stringValue.empty())
				while ((pos = stringValue.find(k)) != std::string::npos)
					stringValue.replace(pos, strlen(k),"");
		}
		// SPECIAL CASE: eliminate the -WP postfix (if it's there), which isn't spaced out from
		// the rest of the font
		if (!stringValue.empty())
			while ((pos = stringValue.find(USELESS_WP_POSTFIX)) != std::string::npos)
				stringValue.replace(pos, strlen(USELESS_WP_POSTFIX), "");
		// also consume any whitespace at the end of the font.
		if (!stringValue.empty())
			while ((pos = stringValue.find("  ")) != std::string::npos)
				stringValue.replace(pos, strlen("  "), " ");
		if (!stringValue.empty())
			while ((pos = stringValue.find(" ", stringValue.size() - 1)) != std::string::npos)
				stringValue.replace(pos, strlen(" "), "");
		if (!stringValue.empty())
			while ((pos = stringValue.find("-", stringValue.size() - 1)) != std::string::npos)
				stringValue.replace(pos, strlen("-"), "");

		m_fontName = librevenge::RVNGString(stringValue.c_str());
		WPD_DEBUG_MSG(("WordPerfect: stripping font name (final: %s)\n", m_fontName.cstr()));
	}
}
/* vim:set shiftwidth=4 softtabstop=4 noexpandtab: */
