mirror of
https://github.com/simon987/antiword.git
synced 2025-04-10 13:06:41 +00:00
306 lines
7.4 KiB
C
306 lines
7.4 KiB
C
/*
|
|
* fonts_u.c
|
|
* Copyright (C) 1999-2004 A.J. van Os; Released under GNU 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, *szAntiword, *szGlobalFile;
|
|
char szEnvironmentFile[PATH_MAX+1];
|
|
char szLocalFile[PATH_MAX+1];
|
|
|
|
szEnvironmentFile[0] = '\0';
|
|
szLocalFile[0] = '\0';
|
|
|
|
/* Try the environment version of the fontnames file */
|
|
szAntiword = szGetAntiwordDirectory();
|
|
if (szAntiword != NULL && szAntiword[0] != '\0') {
|
|
if (strlen(szAntiword) +
|
|
sizeof(FILE_SEPARATOR FONTNAMES_FILE) >=
|
|
sizeof(szEnvironmentFile)) {
|
|
werr(0,
|
|
"The name of your ANTIWORDHOME directory is too long");
|
|
return NULL;
|
|
}
|
|
sprintf(szEnvironmentFile, "%s%s",
|
|
szAntiword,
|
|
FILE_SEPARATOR FONTNAMES_FILE);
|
|
DBG_MSG(szEnvironmentFile);
|
|
|
|
pFile = fopen(szEnvironmentFile, "r");
|
|
if (pFile != NULL) {
|
|
return pFile;
|
|
}
|
|
}
|
|
|
|
/* 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) {
|
|
return pFile;
|
|
}
|
|
|
|
if (szEnvironmentFile[0] != '\0') {
|
|
werr(0, "I can not open your fontnames file.\n"
|
|
"Neither '%s' nor\n"
|
|
"'%s' nor\n"
|
|
"'%s' can be opened for reading.",
|
|
szEnvironmentFile, szLocalFile, szGlobalFile);
|
|
} else {
|
|
werr(0, "I can not open your fontnames file.\n"
|
|
"Neither '%s' nor\n"
|
|
"'%s' can be opened for reading.",
|
|
szLocalFile, szGlobalFile);
|
|
}
|
|
return NULL;
|
|
} /* 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() */
|
|
eEncoding = encoding_neutral;
|
|
bUsePlainText = TRUE;
|
|
} /* end of vCloseFont */
|
|
|
|
/*
|
|
* tOpenFont - make the specified font the current font
|
|
*
|
|
* Returns the font reference number
|
|
*/
|
|
drawfile_fontref
|
|
tOpenFont(UCHAR ucWordFontNumber, USHORT usFontStyle, USHORT usWordFontSize)
|
|
{
|
|
options_type tOptions;
|
|
const char *szOurFontname;
|
|
size_t tIndex;
|
|
int iFontnumber;
|
|
|
|
NO_DBG_MSG("tOpenFont");
|
|
NO_DBG_DEC(ucWordFontNumber);
|
|
NO_DBG_HEX(usFontStyle);
|
|
NO_DBG_DEC(usWordFontSize);
|
|
|
|
/* Keep the relevant bits */
|
|
usFontStyle &= FONT_BOLD|FONT_ITALIC;
|
|
NO_DBG_HEX(usFontStyle);
|
|
|
|
vGetOptions(&tOptions);
|
|
eEncoding = tOptions.eEncoding;
|
|
bUsePlainText = tOptions.eConversionType != conversion_draw &&
|
|
tOptions.eConversionType != conversion_ps &&
|
|
tOptions.eConversionType != conversion_pdf;
|
|
|
|
if (bUsePlainText) {
|
|
/* Plain text, no fonts */
|
|
return (drawfile_fontref)0;
|
|
}
|
|
|
|
iFontnumber = iGetFontByNumber(ucWordFontNumber, usFontStyle);
|
|
szOurFontname = szGetOurFontname(iFontnumber);
|
|
if (szOurFontname == NULL || szOurFontname[0] == '\0') {
|
|
DBG_DEC(iFontnumber);
|
|
return (drawfile_fontref)0;
|
|
}
|
|
NO_DBG_MSG(szOurFontname);
|
|
|
|
for (tIndex = 0; tIndex < elementsof(szFontnames); tIndex++) {
|
|
if (STREQ(szFontnames[tIndex], szOurFontname)) {
|
|
NO_DBG_DEC(tIndex);
|
|
return (drawfile_fontref)tIndex;
|
|
}
|
|
}
|
|
return (drawfile_fontref)0;
|
|
} /* end of tOpenFont */
|
|
|
|
/*
|
|
* tOpenTableFont - make the table font the current font
|
|
*
|
|
* Returns the font reference number
|
|
*/
|
|
drawfile_fontref
|
|
tOpenTableFont(USHORT usWordFontSize)
|
|
{
|
|
options_type tOptions;
|
|
int iWordFontnumber;
|
|
|
|
NO_DBG_MSG("tOpenTableFont");
|
|
|
|
vGetOptions(&tOptions);
|
|
eEncoding = tOptions.eEncoding;
|
|
bUsePlainText = tOptions.eConversionType != conversion_draw &&
|
|
tOptions.eConversionType != conversion_ps &&
|
|
tOptions.eConversionType != conversion_pdf;
|
|
|
|
if (bUsePlainText) {
|
|
/* Plain text, no fonts */
|
|
return (drawfile_fontref)0;
|
|
}
|
|
|
|
iWordFontnumber = iFontname2Fontnumber(TABLE_FONT, FONT_REGULAR);
|
|
if (iWordFontnumber < 0 || iWordFontnumber > (int)UCHAR_MAX) {
|
|
DBG_DEC(iWordFontnumber);
|
|
return (drawfile_fontref)0;
|
|
}
|
|
|
|
return tOpenFont((UCHAR)iWordFontnumber, FONT_REGULAR, usWordFontSize);
|
|
} /* end of tOpenTableFont */
|
|
|
|
/*
|
|
* szGetFontname - get the fontname
|
|
*/
|
|
const char *
|
|
szGetFontname(drawfile_fontref tFontRef)
|
|
{
|
|
fail((size_t)(UCHAR)tFontRef >= elementsof(szFontnames));
|
|
return szFontnames[(int)(UCHAR)tFontRef];
|
|
} /* end of szGetFontname */
|
|
|
|
/*
|
|
* lComputeStringWidth - compute the string width
|
|
*
|
|
* Note: the fontsize is specified in half-points!
|
|
* the stringlength is specified in bytes, not characters!
|
|
*
|
|
* Returns the string width in millipoints
|
|
*/
|
|
long
|
|
lComputeStringWidth(const char *szString, size_t tStringLength,
|
|
drawfile_fontref tFontRef, USHORT usFontSize)
|
|
{
|
|
USHORT *ausCharWidths;
|
|
UCHAR *pucChar;
|
|
long lRelWidth;
|
|
size_t tIndex;
|
|
int iFontRef;
|
|
|
|
fail(szString == NULL);
|
|
fail(usFontSize < MIN_FONT_SIZE || usFontSize > MAX_FONT_SIZE);
|
|
|
|
if (szString[0] == '\0' || tStringLength == 0) {
|
|
/* Empty string */
|
|
return 0;
|
|
}
|
|
|
|
if (eEncoding == encoding_utf_8) {
|
|
fail(!bUsePlainText);
|
|
return lChar2MilliPoints(
|
|
utf8_strwidth(szString, tStringLength));
|
|
}
|
|
|
|
if (bUsePlainText) {
|
|
/* No current font, use "systemfont" */
|
|
return lChar2MilliPoints(tStringLength);
|
|
}
|
|
|
|
if (eEncoding == encoding_cyrillic) {
|
|
/* FIXME: until the character tables are available */
|
|
return (tStringLength * 600L * (long)usFontSize + 1) / 2;
|
|
}
|
|
|
|
DBG_DEC_C(eEncoding != encoding_latin_1 &&
|
|
eEncoding != encoding_latin_2, eEncoding);
|
|
fail(eEncoding != encoding_latin_1 &&
|
|
eEncoding != encoding_latin_2);
|
|
|
|
/* Compute the relative string width */
|
|
iFontRef = (int)(UCHAR)tFontRef;
|
|
if (eEncoding == encoding_latin_2) {
|
|
ausCharWidths = ausCharacterWidths2[iFontRef];
|
|
} else {
|
|
ausCharWidths = ausCharacterWidths1[iFontRef];
|
|
}
|
|
lRelWidth = 0;
|
|
for (tIndex = 0, pucChar = (UCHAR *)szString;
|
|
tIndex < tStringLength;
|
|
tIndex++, pucChar++) {
|
|
lRelWidth += (long)ausCharWidths[(int)*pucChar];
|
|
}
|
|
|
|
/* Compute the absolute string width */
|
|
return (lRelWidth * (long)usFontSize + 1) / 2;
|
|
} /* end of lComputeStringWidth */
|
|
|
|
/*
|
|
* tCountColumns - count the number of columns in a string
|
|
*
|
|
* Note: the length is specified in bytes!
|
|
* A UTF-8 a character can be 0, 1 or 2 columns wide.
|
|
*
|
|
* Returns the number of columns
|
|
*/
|
|
size_t
|
|
tCountColumns(const char *szString, size_t tLength)
|
|
{
|
|
fail(szString == NULL);
|
|
|
|
if (eEncoding != encoding_utf_8) {
|
|
/* One byte, one character, one column */
|
|
return tLength;
|
|
}
|
|
return (size_t)utf8_strwidth(szString, tLength);
|
|
} /* end of tCountColumns */
|
|
|
|
/*
|
|
* tGetCharacterLength - the length of the specified character in bytes
|
|
*
|
|
* Returns the length in bytes
|
|
*/
|
|
size_t
|
|
tGetCharacterLength(const char *szString)
|
|
{
|
|
fail(szString == NULL);
|
|
|
|
if (eEncoding != encoding_utf_8) {
|
|
return 1;
|
|
}
|
|
return (size_t)utf8_chrlength(szString);
|
|
} /* end of tGetCharacterLength */
|