1/************************************************************************
2Copyright 1989 by Digital Equipment Corporation, Maynard, Massachusetts.
3
4                        All Rights Reserved
5
6Permission to use, copy, modify, and distribute this software and its
7documentation for any purpose and without fee is hereby granted,
8provided that the above copyright notice appear in all copies and that
9both that copyright notice and this permission notice appear in
10supporting documentation, and that the name of Digital not be
11used in advertising or publicity pertaining to distribution of the
12software without specific, written prior permission.
13
14DIGITAL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING
15ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL
16DIGITAL BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR
17ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
18WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
19ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
20SOFTWARE.
21
22************************************************************************/
23
24/*
25
26Copyright 1994, 1998  The Open Group
27
28Permission to use, copy, modify, distribute, and sell this software and its
29documentation for any purpose is hereby granted without fee, provided that
30the above copyright notice appear in all copies and that both that
31copyright notice and this permission notice appear in supporting
32documentation.
33
34The above copyright notice and this permission notice shall be included
35in all copies or substantial portions of the Software.
36
37THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
38OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
39MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
40IN NO EVENT SHALL THE OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR
41OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
42ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
43OTHER DEALINGS IN THE SOFTWARE.
44
45Except as contained in this notice, the name of The Open Group shall
46not be used in advertising or otherwise to promote the sale, use or
47other dealings in this Software without prior written authorization
48from The Open Group.
49
50*/
51
52#ifdef HAVE_CONFIG_H
53#include <config.h>
54#endif
55
56#include <ctype.h>
57#include <stdio.h>
58#include <stdarg.h>
59
60#include "fntfilst.h"
61#include <X11/fonts/fontstruct.h>
62/* use bitmap structure */
63#include "bitmap.h"
64#include "bdfint.h"
65
66int bdfFileLineNum;
67
68/***====================================================================***/
69
70void
71bdfError(const char *message, ...)
72{
73    va_list args;
74
75    va_start(args, message);
76    fprintf(stderr, "BDF Error on line %d: ", bdfFileLineNum);
77    vfprintf(stderr, message, args);
78    va_end(args);
79}
80
81/***====================================================================***/
82
83void
84bdfWarning(const char *message, ...)
85{
86    va_list args;
87
88    va_start(args, message);
89    fprintf(stderr, "BDF Warning on line %d: ", bdfFileLineNum);
90    vfprintf(stderr, message, args);
91    va_end(args);
92}
93
94/*
95 * read the next (non-comment) line and keep a count for error messages.
96 * Returns buf, or NULL if EOF.
97 */
98
99unsigned char *
100bdfGetLine(FontFilePtr file, unsigned char *buf, int len)
101{
102    for (;;) {
103        int c;
104        unsigned char *b = buf;
105
106        while ((c = FontFileGetc(file)) != FontFileEOF) {
107            if (c == '\r')
108                continue;
109            if (c == '\n') {
110                bdfFileLineNum++;
111                break;
112            }
113            if (b - buf >= (len - 1))
114                break;
115            *b++ = c;
116        }
117        *b = '\0';
118        if (c == FontFileEOF)
119            return NULL;
120        if (b != buf && !bdfIsPrefix(buf, "COMMENT"))
121            break;
122    }
123    return buf;
124}
125
126/***====================================================================***/
127
128Atom
129bdfForceMakeAtom(const char *str, int *size)
130{
131    register int len = strlen(str);
132    Atom the_atom;
133
134    if (size != NULL)
135        *size += len + 1;
136    the_atom = MakeAtom(str, len, TRUE);
137    if (the_atom == None)
138        bdfError("Atom allocation failed\n");
139    return the_atom;
140}
141
142/***====================================================================***/
143
144/*
145 * Handle quoted strings.
146 */
147
148Atom
149bdfGetPropertyValue(char *s)
150{
151    register char *p, *pp;
152    char *orig_s = s;
153    Atom atom;
154
155    /* strip leading white space */
156    while (*s && (*s == ' ' || *s == '\t'))
157        s++;
158    if (*s == 0) {
159        return bdfForceMakeAtom(s, NULL);
160    }
161    if (*s != '"') {
162        /* no white space in value */
163        for (pp = s; *pp; pp++)
164            if (*pp == ' ' || *pp == '\t' || *pp == '\015' || *pp == '\n') {
165                *pp = 0;
166                break;
167            }
168        return bdfForceMakeAtom(s, NULL);
169    }
170    /* quoted string: strip outer quotes and undouble inner quotes */
171    s++;
172    pp = p = malloc(strlen(s) + 1);
173    if (pp == NULL) {
174        bdfError("Couldn't allocate property value string (%d)\n",
175                 (int) strlen(s) + 1);
176        return None;
177    }
178    while (*s) {
179        if (*s == '"') {
180            if (*(s + 1) != '"') {
181                *p++ = 0;
182                atom = bdfForceMakeAtom(pp, NULL);
183                free(pp);
184                return atom;
185            }
186            else {
187                s++;
188            }
189        }
190        *p++ = *s++;
191    }
192    free(pp);
193    bdfError("unterminated quoted string property: %s\n", orig_s);
194    return None;
195}
196
197/***====================================================================***/
198
199/*
200 * return TRUE if string is a valid integer
201 */
202int
203bdfIsInteger(char *str)
204{
205    char c;
206
207    c = *str++;
208    if (!(isdigit((unsigned char) c) || c == '-' || c == '+'))
209        return (FALSE);
210
211    while ((c = *str++))
212        if (!isdigit((unsigned char) c))
213            return (FALSE);
214
215    return (TRUE);
216}
217
218/***====================================================================***/
219
220/*
221 * make a byte from the first two hex characters in glyph picture
222 */
223
224unsigned char
225bdfHexByte(unsigned char *s)
226{
227    unsigned char b = 0;
228
229    for (int i = 2; i; i--) {
230        char c = *s++;
231
232        if ((c >= '0') && (c <= '9'))
233            b = (b << 4) + (c - '0');
234        else if ((c >= 'A') && (c <= 'F'))
235            b = (b << 4) + 10 + (c - 'A');
236        else if ((c >= 'a') && (c <= 'f'))
237            b = (b << 4) + 10 + (c - 'a');
238        else
239            bdfError("bad hex char '%c'", c);
240    }
241    return b;
242}
243
244/***====================================================================***/
245
246/*
247 * check for known special property values
248 */
249
250static const char *SpecialAtoms[] = {
251    "FONT_ASCENT",
252#define BDF_FONT_ASCENT	0
253    "FONT_DESCENT",
254#define BDF_FONT_DESCENT 1
255    "DEFAULT_CHAR",
256#define BDF_DEFAULT_CHAR 2
257    "POINT_SIZE",
258#define BDF_POINT_SIZE 3
259    "RESOLUTION",
260#define BDF_RESOLUTION 4
261    "X_HEIGHT",
262#define BDF_X_HEIGHT 5
263    "WEIGHT",
264#define BDF_WEIGHT 6
265    "QUAD_WIDTH",
266#define BDF_QUAD_WIDTH 7
267    "FONT",
268#define BDF_FONT 8
269    "RESOLUTION_X",
270#define BDF_RESOLUTION_X 9
271    "RESOLUTION_Y",
272#define BDF_RESOLUTION_Y 10
273    0,
274};
275
276Bool
277bdfSpecialProperty(FontPtr pFont, FontPropPtr prop,
278                   char isString, bdfFileState *bdfState)
279{
280    const char **special;
281    const char *name;
282
283    name = NameForAtom(prop->name);
284    for (special = SpecialAtoms; *special; special++)
285        if (!strcmp(name, *special))
286            break;
287
288    switch (special - SpecialAtoms) {
289    case BDF_FONT_ASCENT:
290        if (!isString) {
291            pFont->info.fontAscent = prop->value;
292            bdfState->haveFontAscent = TRUE;
293        }
294        return TRUE;
295    case BDF_FONT_DESCENT:
296        if (!isString) {
297            pFont->info.fontDescent = prop->value;
298            bdfState->haveFontDescent = TRUE;
299        }
300        return TRUE;
301    case BDF_DEFAULT_CHAR:
302        if (!isString) {
303            pFont->info.defaultCh = prop->value;
304            bdfState->haveDefaultCh = TRUE;
305        }
306        return TRUE;
307    case BDF_POINT_SIZE:
308        bdfState->pointSizeProp = prop;
309        return FALSE;
310    case BDF_RESOLUTION:
311        bdfState->resolutionProp = prop;
312        return FALSE;
313    case BDF_X_HEIGHT:
314        bdfState->xHeightProp = prop;
315        return FALSE;
316    case BDF_WEIGHT:
317        bdfState->weightProp = prop;
318        return FALSE;
319    case BDF_QUAD_WIDTH:
320        bdfState->quadWidthProp = prop;
321        return FALSE;
322    case BDF_FONT:
323        bdfState->fontProp = prop;
324        return FALSE;
325    case BDF_RESOLUTION_X:
326        bdfState->resolutionXProp = prop;
327        return FALSE;
328    case BDF_RESOLUTION_Y:
329        bdfState->resolutionYProp = prop;
330        return FALSE;
331    default:
332        return FALSE;
333    }
334}
335