/*
 * fonts_u.c
 * Copyright (C) 1999-2001 A.J. van Os; Released under GPL
 *
 * Description:
 * Functions to deal with fonts (Unix version)
 */

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "antiword.h"
#include "fontinfo.h"

/* Don't use fonts, just plain text */
static BOOL		bUsePlainText = TRUE;
/* Which character set should be used */
static encoding_type	eEncoding = encoding_neutral;


/*
 * pOpenFontTableFile - open the Font translation file
 *
 * Returns the file pointer or NULL
 */
FILE *
pOpenFontTableFile(void)
{
	FILE		*pFile;
	const char	*szHome;
	const char	*szGlobalFile;
	char		szLocalFile[PATH_MAX+1];

	/* Try the local version of the fontnames file */
	szHome = szGetHomeDirectory();
	if (strlen(szHome) +
	    sizeof(FILE_SEPARATOR ANTIWORD_DIR FILE_SEPARATOR FONTNAMES_FILE) >=
	    sizeof(szLocalFile)) {
		werr(0, "The name of your HOME directory is too long");
		return NULL;
	}

	sprintf(szLocalFile, "%s%s",
		szHome,
		FILE_SEPARATOR ANTIWORD_DIR FILE_SEPARATOR FONTNAMES_FILE);
	DBG_MSG(szLocalFile);

	pFile = fopen(szLocalFile, "r");
	if (pFile != NULL) {
		return pFile;
	}

	/* Try the global version of the fontnames file */
	szGlobalFile = GLOBAL_ANTIWORD_DIR FILE_SEPARATOR FONTNAMES_FILE;
	DBG_MSG(szGlobalFile);
	pFile = fopen(szGlobalFile, "r");
	if (pFile == NULL) {
		werr(0, "I can not open your fontnames file for reading");
	}
	return pFile;
} /* end of pOpenFontTableFile */

/*
 * vCloseFont - close the current font, if any
 */
void
vCloseFont(void)
{
	NO_DBG_MSG("vCloseFont");
	/* For safety: to be overwritten at the next call of tOpenfont() */
	bUsePlainText = TRUE;
	eEncoding = encoding_neutral;
} /* end of vCloseFont */

/*
 * tOpenFont - make the given font the current font
 *
 * Returns the font reference number
 */
draw_fontref
tOpenFont(int iWordFontNumber, unsigned char ucFontstyle, int iWordFontsize)
{
	options_type	tOptions;
	const char	*szOurFontname;
	int	iIndex, iFontnumber;

	NO_DBG_MSG("tOpenFont");
	NO_DBG_DEC(iWordFontNumber);
	NO_DBG_HEX(ucFontstyle);
	NO_DBG_DEC(iWordFontsize);

	/* Keep the relevant bits */
	ucFontstyle &= FONT_BOLD|FONT_ITALIC;
	NO_DBG_HEX(ucFontstyle);

	vGetOptions(&tOptions);
	bUsePlainText = !tOptions.bUseOutlineFonts;
	eEncoding = tOptions.eEncoding;

	if (bUsePlainText) {
		/* No outline fonts, no postscript just plain text */
		return (draw_fontref)0;
	}

	iFontnumber = iGetFontByNumber(iWordFontNumber, ucFontstyle);
	szOurFontname = szGetOurFontname(iFontnumber);
	if (szOurFontname == NULL || szOurFontname[0] == '\0') {
		DBG_DEC(iFontnumber);
		return (draw_fontref)0;
	}
	NO_DBG_MSG(szOurFontname);

	for (iIndex = 0; iIndex < (int)elementsof(szFontnames); iIndex++) {
		if (STREQ(szFontnames[iIndex], szOurFontname)) {
			NO_DBG_DEC(iIndex);
			return (draw_fontref)iIndex;
		}
	}
	return (draw_fontref)0;
} /* end of tOpenFont */

/*
 * tOpenTableFont - make the table font the current font
 *
 * Returns the font reference number
 */
draw_fontref
tOpenTableFont(int iWordFontsize)
{
	options_type	tOptions;
	int	iWordFontnumber;

	NO_DBG_MSG("tOpenTableFont");

	vGetOptions(&tOptions);
	bUsePlainText = !tOptions.bUseOutlineFonts;
	if (bUsePlainText) {
		/* No outline fonts, no postscript just plain text */
		return (draw_fontref)0;
	}

	iWordFontnumber = iFontname2Fontnumber(TABLE_FONT, FONT_REGULAR);
	if (iWordFontnumber < 0 || iWordFontnumber > (int)UCHAR_MAX) {
		DBG_DEC(iWordFontnumber);
		return (draw_fontref)0;
	}

	return tOpenFont(iWordFontnumber, FONT_REGULAR, iWordFontsize);
} /* end of tOpenTableFont */

/*
 * szGetFontname - get the fontname
 */
const char *
szGetFontname(draw_fontref tFontRef)
{
	fail((size_t)(unsigned char)tFontRef >= elementsof(szFontnames));
	return szFontnames[(int)(unsigned char)tFontRef];
} /* end of szGetFontname */

/*
 * lComputeStringWidth - compute the string width
 *
 * Note: the fontsize is given in half-points!
 *       the stringlength is given in bytes, not characters!
 *
 * Returns the string width in millipoints
 */
long
lComputeStringWidth(char *szString, int iStringLength,
		draw_fontref tFontRef, int iFontsize)
{
	unsigned short	*ausCharWidths;
	unsigned char	*pucChar;
	long	lRelWidth;
	int	iIndex, iFontRef;

	fail(szString == NULL || iStringLength < 0);
	fail(iFontsize < MIN_FONT_SIZE || iFontsize > MAX_FONT_SIZE);

	if (szString[0] == '\0' || iStringLength <= 0) {
		/* Empty string */
		return 0;
	}

	if (eEncoding == encoding_utf8) {
		fail(!bUsePlainText);
		return lChar2MilliPoints(
				utf8_strwidth(szString, iStringLength));
	}

	if (bUsePlainText) {
		/* No current font, use "systemfont" */
		return lChar2MilliPoints(iStringLength);
	}

	fail(eEncoding != encoding_iso_8859_1 &&
		eEncoding != encoding_iso_8859_2);

	/* Compute the relative string width */
	iFontRef = (int)(unsigned char)tFontRef;
	if (eEncoding == encoding_iso_8859_2) {
		ausCharWidths = ausCharacterWidths2[iFontRef];
	} else {
		ausCharWidths = ausCharacterWidths1[iFontRef];
	}
	lRelWidth = 0;
	for (iIndex = 0, pucChar = (unsigned char *)szString;
	     iIndex < iStringLength;
	     iIndex++, pucChar++) {
		lRelWidth += (long)ausCharWidths[(int)*pucChar];
	}

	/* Compute the absolute string width */
	return (lRelWidth * iFontsize + 1) / 2;
} /* end of lComputeStringWidth */
