xref: /plan9/sys/src/cmd/aux/antiword/fonts_u.c (revision 25b329d522281a8cdd35da0dcc08c3fc621059a9)
1f5736e95SDavid du Colombier /*
2f5736e95SDavid du Colombier  * fonts_u.c
3*25b329d5SDavid du Colombier  * Copyright (C) 1999-2004 A.J. van Os; Released under GNU GPL
4f5736e95SDavid du Colombier  *
5f5736e95SDavid du Colombier  * Description:
6f5736e95SDavid du Colombier  * Functions to deal with fonts (Unix version)
7f5736e95SDavid du Colombier  */
8f5736e95SDavid du Colombier 
9f5736e95SDavid du Colombier #include <stdio.h>
10f5736e95SDavid du Colombier #include <stdlib.h>
11f5736e95SDavid du Colombier #include <string.h>
12f5736e95SDavid du Colombier #include "antiword.h"
13f5736e95SDavid du Colombier #include "fontinfo.h"
14f5736e95SDavid du Colombier 
15f5736e95SDavid du Colombier /* Don't use fonts, just plain text */
16f5736e95SDavid du Colombier static BOOL		bUsePlainText = TRUE;
17f5736e95SDavid du Colombier /* Which character set should be used */
18f5736e95SDavid du Colombier static encoding_type	eEncoding = encoding_neutral;
19f5736e95SDavid du Colombier 
20f5736e95SDavid du Colombier 
21f5736e95SDavid du Colombier /*
22f5736e95SDavid du Colombier  * pOpenFontTableFile - open the Font translation file
23f5736e95SDavid du Colombier  *
24f5736e95SDavid du Colombier  * Returns the file pointer or NULL
25f5736e95SDavid du Colombier  */
26f5736e95SDavid du Colombier FILE *
pOpenFontTableFile(void)27f5736e95SDavid du Colombier pOpenFontTableFile(void)
28f5736e95SDavid du Colombier {
29f5736e95SDavid du Colombier 	FILE		*pFile;
30*25b329d5SDavid du Colombier 	const char	*szHome, *szAntiword, *szGlobalFile;
31f5736e95SDavid du Colombier 	char		szEnvironmentFile[PATH_MAX+1];
32f5736e95SDavid du Colombier 	char		szLocalFile[PATH_MAX+1];
33f5736e95SDavid du Colombier 
34*25b329d5SDavid du Colombier 	szEnvironmentFile[0] = '\0';
35*25b329d5SDavid du Colombier 	szLocalFile[0] = '\0';
36*25b329d5SDavid du Colombier 
37f5736e95SDavid du Colombier 	/* Try the environment version of the fontnames file */
38f5736e95SDavid du Colombier 	szAntiword = szGetAntiwordDirectory();
39f5736e95SDavid du Colombier 	if (szAntiword != NULL && szAntiword[0] != '\0') {
40f5736e95SDavid du Colombier 		if (strlen(szAntiword) +
41f5736e95SDavid du Colombier 		    sizeof(FILE_SEPARATOR FONTNAMES_FILE) >=
42f5736e95SDavid du Colombier 		    sizeof(szEnvironmentFile)) {
43f5736e95SDavid du Colombier 			werr(0,
44f5736e95SDavid du Colombier 			"The name of your ANTIWORDHOME directory is too long");
45f5736e95SDavid du Colombier 			return NULL;
46f5736e95SDavid du Colombier 		}
47f5736e95SDavid du Colombier 		sprintf(szEnvironmentFile, "%s%s",
48f5736e95SDavid du Colombier 			szAntiword,
49f5736e95SDavid du Colombier 			FILE_SEPARATOR FONTNAMES_FILE);
50f5736e95SDavid du Colombier 		DBG_MSG(szEnvironmentFile);
51f5736e95SDavid du Colombier 
52*25b329d5SDavid du Colombier 		pFile = fopen(szEnvironmentFile, "r");
53f5736e95SDavid du Colombier 		if (pFile != NULL) {
54f5736e95SDavid du Colombier 			return pFile;
55f5736e95SDavid du Colombier 		}
56f5736e95SDavid du Colombier 	}
57f5736e95SDavid du Colombier 
58f5736e95SDavid du Colombier 	/* Try the local version of the fontnames file */
59f5736e95SDavid du Colombier 	szHome = szGetHomeDirectory();
60f5736e95SDavid du Colombier 	if (strlen(szHome) +
61f5736e95SDavid du Colombier 	    sizeof(FILE_SEPARATOR ANTIWORD_DIR FILE_SEPARATOR FONTNAMES_FILE) >=
62f5736e95SDavid du Colombier 	    sizeof(szLocalFile)) {
63f5736e95SDavid du Colombier 		werr(0, "The name of your HOME directory is too long");
64f5736e95SDavid du Colombier 		return NULL;
65f5736e95SDavid du Colombier 	}
66f5736e95SDavid du Colombier 
67f5736e95SDavid du Colombier 	sprintf(szLocalFile, "%s%s",
68f5736e95SDavid du Colombier 		szHome,
69f5736e95SDavid du Colombier 		FILE_SEPARATOR ANTIWORD_DIR FILE_SEPARATOR FONTNAMES_FILE);
70f5736e95SDavid du Colombier 	DBG_MSG(szLocalFile);
71f5736e95SDavid du Colombier 
72f5736e95SDavid du Colombier 	pFile = fopen(szLocalFile, "r");
73f5736e95SDavid du Colombier 	if (pFile != NULL) {
74f5736e95SDavid du Colombier 		return pFile;
75f5736e95SDavid du Colombier 	}
76f5736e95SDavid du Colombier 
77f5736e95SDavid du Colombier 	/* Try the global version of the fontnames file */
78f5736e95SDavid du Colombier 	szGlobalFile = GLOBAL_ANTIWORD_DIR FILE_SEPARATOR FONTNAMES_FILE;
79f5736e95SDavid du Colombier 	DBG_MSG(szGlobalFile);
80f5736e95SDavid du Colombier 
81f5736e95SDavid du Colombier 	pFile = fopen(szGlobalFile, "r");
82f5736e95SDavid du Colombier 	if (pFile != NULL) {
83f5736e95SDavid du Colombier 		return pFile;
84f5736e95SDavid du Colombier 	}
85f5736e95SDavid du Colombier 
86*25b329d5SDavid du Colombier 	if (szEnvironmentFile[0] != '\0') {
87*25b329d5SDavid du Colombier 		werr(0, "I can not open your fontnames file.\n"
88*25b329d5SDavid du Colombier 			"Neither '%s' nor\n"
89*25b329d5SDavid du Colombier 			"'%s' nor\n"
90*25b329d5SDavid du Colombier 			"'%s' can be opened for reading.",
91*25b329d5SDavid du Colombier 			szEnvironmentFile, szLocalFile, szGlobalFile);
92*25b329d5SDavid du Colombier 	} else {
93f5736e95SDavid du Colombier 		werr(0, "I can not open your fontnames file.\n"
94f5736e95SDavid du Colombier 			"Neither '%s' nor\n"
95f5736e95SDavid du Colombier 			"'%s' can be opened for reading.",
96f5736e95SDavid du Colombier 			szLocalFile, szGlobalFile);
97*25b329d5SDavid du Colombier 	}
98f5736e95SDavid du Colombier 	return NULL;
99f5736e95SDavid du Colombier } /* end of pOpenFontTableFile */
100f5736e95SDavid du Colombier 
101f5736e95SDavid du Colombier /*
102f5736e95SDavid du Colombier  * vCloseFont - close the current font, if any
103f5736e95SDavid du Colombier  */
104f5736e95SDavid du Colombier void
vCloseFont(void)105f5736e95SDavid du Colombier vCloseFont(void)
106f5736e95SDavid du Colombier {
107f5736e95SDavid du Colombier 	NO_DBG_MSG("vCloseFont");
108f5736e95SDavid du Colombier 	/* For safety: to be overwritten at the next call of tOpenfont() */
109f5736e95SDavid du Colombier 	eEncoding = encoding_neutral;
110*25b329d5SDavid du Colombier 	bUsePlainText = TRUE;
111f5736e95SDavid du Colombier } /* end of vCloseFont */
112f5736e95SDavid du Colombier 
113f5736e95SDavid du Colombier /*
114f5736e95SDavid du Colombier  * tOpenFont - make the specified font the current font
115f5736e95SDavid du Colombier  *
116f5736e95SDavid du Colombier  * Returns the font reference number
117f5736e95SDavid du Colombier  */
118*25b329d5SDavid du Colombier drawfile_fontref
tOpenFont(UCHAR ucWordFontNumber,USHORT usFontStyle,USHORT usWordFontSize)119f5736e95SDavid du Colombier tOpenFont(UCHAR ucWordFontNumber, USHORT usFontStyle, USHORT usWordFontSize)
120f5736e95SDavid du Colombier {
121f5736e95SDavid du Colombier 	options_type	tOptions;
122f5736e95SDavid du Colombier 	const char	*szOurFontname;
123*25b329d5SDavid du Colombier 	size_t	tIndex;
124*25b329d5SDavid du Colombier 	int	iFontnumber;
125f5736e95SDavid du Colombier 
126f5736e95SDavid du Colombier 	NO_DBG_MSG("tOpenFont");
127f5736e95SDavid du Colombier 	NO_DBG_DEC(ucWordFontNumber);
128f5736e95SDavid du Colombier 	NO_DBG_HEX(usFontStyle);
129f5736e95SDavid du Colombier 	NO_DBG_DEC(usWordFontSize);
130f5736e95SDavid du Colombier 
131f5736e95SDavid du Colombier 	/* Keep the relevant bits */
132f5736e95SDavid du Colombier 	usFontStyle &= FONT_BOLD|FONT_ITALIC;
133f5736e95SDavid du Colombier 	NO_DBG_HEX(usFontStyle);
134f5736e95SDavid du Colombier 
135f5736e95SDavid du Colombier 	vGetOptions(&tOptions);
136f5736e95SDavid du Colombier 	eEncoding = tOptions.eEncoding;
137*25b329d5SDavid du Colombier 	bUsePlainText = tOptions.eConversionType != conversion_draw &&
138*25b329d5SDavid du Colombier 			tOptions.eConversionType != conversion_ps &&
139*25b329d5SDavid du Colombier 			tOptions.eConversionType != conversion_pdf;
140f5736e95SDavid du Colombier 
141f5736e95SDavid du Colombier 	if (bUsePlainText) {
142f5736e95SDavid du Colombier 		/* Plain text, no fonts */
143*25b329d5SDavid du Colombier 		return (drawfile_fontref)0;
144f5736e95SDavid du Colombier 	}
145f5736e95SDavid du Colombier 
146f5736e95SDavid du Colombier 	iFontnumber = iGetFontByNumber(ucWordFontNumber, usFontStyle);
147f5736e95SDavid du Colombier 	szOurFontname = szGetOurFontname(iFontnumber);
148f5736e95SDavid du Colombier 	if (szOurFontname == NULL || szOurFontname[0] == '\0') {
149f5736e95SDavid du Colombier 		DBG_DEC(iFontnumber);
150*25b329d5SDavid du Colombier 		return (drawfile_fontref)0;
151f5736e95SDavid du Colombier 	}
152f5736e95SDavid du Colombier 	NO_DBG_MSG(szOurFontname);
153f5736e95SDavid du Colombier 
154*25b329d5SDavid du Colombier 	for (tIndex = 0; tIndex < elementsof(szFontnames); tIndex++) {
155*25b329d5SDavid du Colombier 		if (STREQ(szFontnames[tIndex], szOurFontname)) {
156*25b329d5SDavid du Colombier 			NO_DBG_DEC(tIndex);
157*25b329d5SDavid du Colombier 			return (drawfile_fontref)tIndex;
158f5736e95SDavid du Colombier 		}
159f5736e95SDavid du Colombier 	}
160*25b329d5SDavid du Colombier 	return (drawfile_fontref)0;
161f5736e95SDavid du Colombier } /* end of tOpenFont */
162f5736e95SDavid du Colombier 
163f5736e95SDavid du Colombier /*
164f5736e95SDavid du Colombier  * tOpenTableFont - make the table font the current font
165f5736e95SDavid du Colombier  *
166f5736e95SDavid du Colombier  * Returns the font reference number
167f5736e95SDavid du Colombier  */
168*25b329d5SDavid du Colombier drawfile_fontref
tOpenTableFont(USHORT usWordFontSize)169f5736e95SDavid du Colombier tOpenTableFont(USHORT usWordFontSize)
170f5736e95SDavid du Colombier {
171f5736e95SDavid du Colombier 	options_type	tOptions;
172f5736e95SDavid du Colombier 	int	iWordFontnumber;
173f5736e95SDavid du Colombier 
174f5736e95SDavid du Colombier 	NO_DBG_MSG("tOpenTableFont");
175f5736e95SDavid du Colombier 
176f5736e95SDavid du Colombier 	vGetOptions(&tOptions);
177f5736e95SDavid du Colombier 	eEncoding = tOptions.eEncoding;
178*25b329d5SDavid du Colombier 	bUsePlainText = tOptions.eConversionType != conversion_draw &&
179*25b329d5SDavid du Colombier 			tOptions.eConversionType != conversion_ps &&
180*25b329d5SDavid du Colombier 			tOptions.eConversionType != conversion_pdf;
181f5736e95SDavid du Colombier 
182f5736e95SDavid du Colombier 	if (bUsePlainText) {
183f5736e95SDavid du Colombier 		/* Plain text, no fonts */
184*25b329d5SDavid du Colombier 		return (drawfile_fontref)0;
185f5736e95SDavid du Colombier 	}
186f5736e95SDavid du Colombier 
187f5736e95SDavid du Colombier 	iWordFontnumber = iFontname2Fontnumber(TABLE_FONT, FONT_REGULAR);
188f5736e95SDavid du Colombier 	if (iWordFontnumber < 0 || iWordFontnumber > (int)UCHAR_MAX) {
189f5736e95SDavid du Colombier 		DBG_DEC(iWordFontnumber);
190*25b329d5SDavid du Colombier 		return (drawfile_fontref)0;
191f5736e95SDavid du Colombier 	}
192f5736e95SDavid du Colombier 
193f5736e95SDavid du Colombier 	return tOpenFont((UCHAR)iWordFontnumber, FONT_REGULAR, usWordFontSize);
194f5736e95SDavid du Colombier } /* end of tOpenTableFont */
195f5736e95SDavid du Colombier 
196f5736e95SDavid du Colombier /*
197f5736e95SDavid du Colombier  * szGetFontname - get the fontname
198f5736e95SDavid du Colombier  */
199f5736e95SDavid du Colombier const char *
szGetFontname(drawfile_fontref tFontRef)200*25b329d5SDavid du Colombier szGetFontname(drawfile_fontref tFontRef)
201f5736e95SDavid du Colombier {
202f5736e95SDavid du Colombier 	fail((size_t)(UCHAR)tFontRef >= elementsof(szFontnames));
203f5736e95SDavid du Colombier 	return szFontnames[(int)(UCHAR)tFontRef];
204f5736e95SDavid du Colombier } /* end of szGetFontname */
205f5736e95SDavid du Colombier 
206f5736e95SDavid du Colombier /*
207f5736e95SDavid du Colombier  * lComputeStringWidth - compute the string width
208f5736e95SDavid du Colombier  *
209f5736e95SDavid du Colombier  * Note: the fontsize is specified in half-points!
210f5736e95SDavid du Colombier  *       the stringlength is specified in bytes, not characters!
211f5736e95SDavid du Colombier  *
212f5736e95SDavid du Colombier  * Returns the string width in millipoints
213f5736e95SDavid du Colombier  */
214f5736e95SDavid du Colombier long
lComputeStringWidth(const char * szString,size_t tStringLength,drawfile_fontref tFontRef,USHORT usFontSize)215f5736e95SDavid du Colombier lComputeStringWidth(const char *szString, size_t tStringLength,
216*25b329d5SDavid du Colombier 	drawfile_fontref tFontRef, USHORT usFontSize)
217f5736e95SDavid du Colombier {
218f5736e95SDavid du Colombier 	USHORT	*ausCharWidths;
219f5736e95SDavid du Colombier 	UCHAR	*pucChar;
220f5736e95SDavid du Colombier 	long	lRelWidth;
221f5736e95SDavid du Colombier 	size_t	tIndex;
222f5736e95SDavid du Colombier 	int	iFontRef;
223f5736e95SDavid du Colombier 
224f5736e95SDavid du Colombier 	fail(szString == NULL);
225f5736e95SDavid du Colombier 	fail(usFontSize < MIN_FONT_SIZE || usFontSize > MAX_FONT_SIZE);
226f5736e95SDavid du Colombier 
227f5736e95SDavid du Colombier 	if (szString[0] == '\0' || tStringLength == 0) {
228f5736e95SDavid du Colombier 		/* Empty string */
229f5736e95SDavid du Colombier 		return 0;
230f5736e95SDavid du Colombier 	}
231f5736e95SDavid du Colombier 
232*25b329d5SDavid du Colombier 	if (eEncoding == encoding_utf_8) {
233f5736e95SDavid du Colombier 		fail(!bUsePlainText);
234f5736e95SDavid du Colombier 		return lChar2MilliPoints(
235f5736e95SDavid du Colombier 			utf8_strwidth(szString, tStringLength));
236f5736e95SDavid du Colombier 	}
237f5736e95SDavid du Colombier 
238f5736e95SDavid du Colombier 	if (bUsePlainText) {
239f5736e95SDavid du Colombier 		/* No current font, use "systemfont" */
240f5736e95SDavid du Colombier 		return lChar2MilliPoints(tStringLength);
241f5736e95SDavid du Colombier 	}
242f5736e95SDavid du Colombier 
243*25b329d5SDavid du Colombier 	if (eEncoding == encoding_cyrillic) {
244*25b329d5SDavid du Colombier 		/* FIXME: until the character tables are available */
245*25b329d5SDavid du Colombier 		return (tStringLength * 600L * (long)usFontSize + 1) / 2;
246*25b329d5SDavid du Colombier 	}
247*25b329d5SDavid du Colombier 
248*25b329d5SDavid du Colombier 	DBG_DEC_C(eEncoding != encoding_latin_1 &&
249*25b329d5SDavid du Colombier 		eEncoding != encoding_latin_2, eEncoding);
250*25b329d5SDavid du Colombier 	fail(eEncoding != encoding_latin_1 &&
251*25b329d5SDavid du Colombier 		eEncoding != encoding_latin_2);
252f5736e95SDavid du Colombier 
253f5736e95SDavid du Colombier 	/* Compute the relative string width */
254f5736e95SDavid du Colombier 	iFontRef = (int)(UCHAR)tFontRef;
255*25b329d5SDavid du Colombier 	if (eEncoding == encoding_latin_2) {
256f5736e95SDavid du Colombier 		ausCharWidths = ausCharacterWidths2[iFontRef];
257f5736e95SDavid du Colombier 	} else {
258f5736e95SDavid du Colombier 		ausCharWidths = ausCharacterWidths1[iFontRef];
259f5736e95SDavid du Colombier 	}
260f5736e95SDavid du Colombier 	lRelWidth = 0;
261f5736e95SDavid du Colombier 	for (tIndex = 0, pucChar = (UCHAR *)szString;
262f5736e95SDavid du Colombier 	     tIndex < tStringLength;
263f5736e95SDavid du Colombier 	     tIndex++, pucChar++) {
264f5736e95SDavid du Colombier 		lRelWidth += (long)ausCharWidths[(int)*pucChar];
265f5736e95SDavid du Colombier 	}
266f5736e95SDavid du Colombier 
267f5736e95SDavid du Colombier 	/* Compute the absolute string width */
268*25b329d5SDavid du Colombier 	return (lRelWidth * (long)usFontSize + 1) / 2;
269f5736e95SDavid du Colombier } /* end of lComputeStringWidth */
270f5736e95SDavid du Colombier 
271f5736e95SDavid du Colombier /*
272f5736e95SDavid du Colombier  * tCountColumns - count the number of columns in a string
273f5736e95SDavid du Colombier  *
274f5736e95SDavid du Colombier  * Note: the length is specified in bytes!
275f5736e95SDavid du Colombier  *       A UTF-8 a character can be 0, 1 or 2 columns wide.
276f5736e95SDavid du Colombier  *
277f5736e95SDavid du Colombier  * Returns the number of columns
278f5736e95SDavid du Colombier  */
279f5736e95SDavid du Colombier size_t
tCountColumns(const char * szString,size_t tLength)280f5736e95SDavid du Colombier tCountColumns(const char *szString, size_t tLength)
281f5736e95SDavid du Colombier {
282f5736e95SDavid du Colombier 	fail(szString == NULL);
283f5736e95SDavid du Colombier 
284*25b329d5SDavid du Colombier 	if (eEncoding != encoding_utf_8) {
285f5736e95SDavid du Colombier 		/* One byte, one character, one column */
286f5736e95SDavid du Colombier 		return tLength;
287f5736e95SDavid du Colombier 	}
288f5736e95SDavid du Colombier 	return (size_t)utf8_strwidth(szString, tLength);
289f5736e95SDavid du Colombier } /* end of tCountColumns */
290f5736e95SDavid du Colombier 
291f5736e95SDavid du Colombier /*
292f5736e95SDavid du Colombier  * tGetCharacterLength - the length of the specified character in bytes
293f5736e95SDavid du Colombier  *
294f5736e95SDavid du Colombier  * Returns the length in bytes
295f5736e95SDavid du Colombier  */
296f5736e95SDavid du Colombier size_t
tGetCharacterLength(const char * szString)297f5736e95SDavid du Colombier tGetCharacterLength(const char *szString)
298f5736e95SDavid du Colombier {
299f5736e95SDavid du Colombier 	fail(szString == NULL);
300f5736e95SDavid du Colombier 
301*25b329d5SDavid du Colombier 	if (eEncoding != encoding_utf_8) {
302f5736e95SDavid du Colombier 		return 1;
303f5736e95SDavid du Colombier 	}
304f5736e95SDavid du Colombier 	return (size_t)utf8_chrlength(szString);
305f5736e95SDavid du Colombier } /* end of tGetCharacterLength */
306