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