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