]> git.sesse.net Git - rdpsrv/blob - Xserver/lib/font/fontfile/dirfile.c
Support RDP5 logon packets.
[rdpsrv] / Xserver / lib / font / fontfile / dirfile.c
1 /* $XFree86: xc/lib/font/fontfile/dirfile.c,v 3.3 1997/01/27 06:56:28 dawes Exp $ */
2 #ifndef lint
3 static char *rid=
4     "$XConsortium: dirfile.c /main/12 1995/12/08 19:02:23 gildea $";
5 #endif /* lint */
6
7 /*
8
9 Copyright (c) 1991  X Consortium
10
11 Permission is hereby granted, free of charge, to any person obtaining a copy
12 of this software and associated documentation files (the "Software"), to deal
13 in the Software without restriction, including without limitation the rights
14 to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
15 copies of the Software, and to permit persons to whom the Software is
16 furnished to do so, subject to the following conditions:
17
18 The above copyright notice and this permission notice shall be included in
19 all copies or substantial portions of the Software.
20
21 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
22 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
23 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL THE
24 X CONSORTIUM BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
25 AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
26 CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
27
28 Except as contained in this notice, the name of the X Consortium shall not be
29 used in advertising or otherwise to promote the sale, use or other dealings
30 in this Software without prior written authorization from the X Consortium.
31
32 */
33
34 /*
35  * Author:  Keith Packard, MIT X Consortium
36  */
37
38 /*
39  * dirfile.c
40  *
41  * Read fonts.dir and fonts.alias files
42  */
43
44 #include "fntfilst.h"
45 #include <stdio.h>
46 #include <sys/types.h>
47 #include <sys/stat.h>
48 #include <errno.h>
49 #ifdef X_NOT_STDC_ENV
50 extern int errno;
51 #endif
52
53 static int ReadFontAlias();
54
55 int
56 FontFileReadDirectory (directory, pdir)
57     char                *directory;
58     FontDirectoryPtr    *pdir;
59 {
60     char        file_name[MAXFONTNAMELEN];
61     char        font_name[MAXFONTNAMELEN];
62     char        dir_file[MAXFONTNAMELEN];
63 #ifdef FONTDIRATTRIB
64     char        dir_path[MAXFONTNAMELEN];
65     char        *ptr;
66 #endif
67     FILE       *file;
68     int         count,
69                 i,
70                 status;
71     struct stat statb;
72
73     FontDirectoryPtr    dir = NullFontDirectory;
74
75 #ifdef FONTDIRATTRIB
76     /* Check for font directory attributes */
77 #ifndef __EMX__
78     if (ptr = strchr(directory, ':')) {
79 #else
80     /* OS/2 path might start with a drive letter, don't clip this */
81     if (ptr = strchr(directory+2, ':')) {
82 #endif
83         strncpy(dir_path, directory, ptr - directory);
84         dir_path[ptr - directory] = '\0';
85     } else {
86         strcpy(dir_path, directory);
87     }
88     strcpy(dir_file, dir_path);
89 #else
90     strcpy(dir_file, directory);
91 #endif
92     if (dir_file[strlen(dir_file) - 1] != '/')
93         strcat(dir_file, "/");
94     strcat(dir_file, FontDirFile);
95     file = fopen(dir_file, "r");
96     if (file) {
97         if (fstat (fileno(file), &statb) == -1)
98             return BadFontPath;
99         count = fscanf(file, "%d\n", &i);
100         if ((count == EOF) || (count != 1)) {
101             fclose(file);
102             return BadFontPath;
103         }
104         dir = FontFileMakeDir(directory, i);
105         if (dir == NULL) {
106             fclose(file);
107             return BadFontPath;
108         }
109         dir->dir_mtime = statb.st_mtime;
110         while ((count = fscanf(file, "%s %[^\n]\n", file_name, font_name)) != EOF) {
111 #ifdef __EMX__
112             /* strip any existing trailing CR */
113             for (i=0; i<strlen(font_name); i++) {
114                 if (font_name[i]=='\r') font_name[i] = '\0';
115             }
116 #endif
117             if (count != 2) {
118                 FontFileFreeDir (dir);
119                 fclose(file);
120                 return BadFontPath;
121             }
122             if (!FontFileAddFontFile (dir, font_name, file_name))
123             {
124                 FontFileFreeDir (dir);
125                 fclose(file);
126                 return BadFontPath;
127             }
128         }
129         fclose(file);
130     } else if (errno != ENOENT) {
131         return BadFontPath;
132     }
133 #ifdef FONTDIRATTRIB
134     status = ReadFontAlias(dir_path, FALSE, &dir);
135 #else
136     status = ReadFontAlias(directory, FALSE, &dir);
137 #endif
138     if (status != Successful) {
139         if (dir)
140             FontFileFreeDir (dir);
141         return status;
142     }
143     if (!dir) {
144         /*** TJR - dirty hack - this variable is set in
145              programs/Xserver/dix/dixfont.c when setting default font path  */
146         extern int settingDefaultFontPath;
147         if (settingDefaultFontPath) {
148             fprintf(stderr,"Font directory '%s' not found - ignoring\n",
149                     directory);
150             dir = FontFileMakeDir(directory, 0);
151         }
152
153         if (!dir)
154             return BadFontPath;
155     }
156
157     FontFileSortDir(dir);
158
159     *pdir = dir;
160     return Successful;
161 }
162
163 Bool
164 FontFileDirectoryChanged(dir)
165     FontDirectoryPtr    dir;
166 {
167     char        dir_file[MAXFONTNAMELEN];
168     struct stat statb;
169
170     strcpy (dir_file, dir->directory);
171     strcat (dir_file, FontDirFile);
172     if (stat (dir_file, &statb) == -1)
173     {
174         if (errno != ENOENT || dir->dir_mtime != 0)
175             return TRUE;
176         return FALSE;           /* doesn't exist and never did: no change */
177     }
178     if (dir->dir_mtime != statb.st_mtime)
179         return TRUE;
180     strcpy (dir_file, dir->directory);
181     strcat (dir_file, FontAliasFile);
182     if (stat (dir_file, &statb) == -1)
183     {
184         if (errno != ENOENT || dir->alias_mtime != 0)
185             return TRUE;
186         return FALSE;           /* doesn't exist and never did: no change */
187     }
188     if (dir->alias_mtime != statb.st_mtime)
189         return TRUE;
190     return FALSE;
191 }
192     
193 /*
194  * Make each of the file names an automatic alias for each of the files.
195  */
196
197 static Bool
198 AddFileNameAliases(dir)
199     FontDirectoryPtr    dir;
200 {
201     int             i;
202     char            copy[MAXFONTNAMELEN];
203     char            *fileName;
204     FontTablePtr    table;
205     FontRendererPtr renderer;
206     int             len;
207     FontNameRec     name;
208
209     table = &dir->nonScalable;
210     for (i = 0; i < table->used; i++) {
211         if (table->entries[i].type != FONT_ENTRY_BITMAP)
212             continue;
213         fileName = table->entries[i].u.bitmap.fileName;
214         renderer = FontFileMatchRenderer (fileName);
215         if (!renderer)
216             continue;
217         
218         len = strlen (fileName) - renderer->fileSuffixLen;
219         CopyISOLatin1Lowered (copy, fileName, len);
220         copy[len] = '\0';
221         name.name = copy;
222         name.length = len;
223         name.ndashes = FontFileCountDashes (copy, len);
224
225         if (!FontFileFindNameInDir(table, &name)) {
226             if (!FontFileAddFontAlias (dir, copy, table->entries[i].name.name))
227                 return FALSE;
228         }
229     }
230     return TRUE;
231 }
232
233 /*
234  * parse the font.alias file.  Format is:
235  *
236  * alias font-name
237  *
238  * To imbed white-space in an alias name, enclose it like "font name"
239  * in double quotes.  \ escapes and character, so
240  * "font name \"With Double Quotes\" \\ and \\ back-slashes"
241  * works just fine.
242  *
243  * A line beginning with a ! denotes a newline-terminated comment.
244  */
245
246 /*
247  * token types
248  */
249
250 static int  lexAlias(), lexc();
251
252 #define NAME            0
253 #define NEWLINE         1
254 #define DONE            2
255 #define EALLOC          3
256
257 static int
258 ReadFontAlias(directory, isFile, pdir)
259     char                *directory;
260     Bool                isFile;
261     FontDirectoryPtr    *pdir;
262 {
263     char                alias[MAXFONTNAMELEN];
264     char                font_name[MAXFONTNAMELEN];
265     char                alias_file[MAXFONTNAMELEN];
266     FILE                *file;
267     FontDirectoryPtr    dir;
268     int                 token;
269     char                *lexToken;
270     int                 status = Successful;
271     struct stat         statb;
272
273     dir = *pdir;
274     strcpy(alias_file, directory);
275     if (!isFile) {
276         if (directory[strlen(directory) - 1] != '/')
277             strcat(alias_file, "/");
278         strcat(alias_file, FontAliasFile);
279     }
280     file = fopen(alias_file, "r");
281     if (!file)
282         return ((errno == ENOENT) ? Successful : BadFontPath);
283     if (!dir)
284         *pdir = dir = FontFileMakeDir(directory, 10);
285     if (!dir)
286     {
287         fclose (file);
288         return AllocError;
289     }
290     if (fstat (fileno (file), &statb) == -1)
291     {
292         fclose (file);
293         return BadFontPath;
294     }
295     dir->alias_mtime = statb.st_mtime;
296     while (status == Successful) {
297         token = lexAlias(file, &lexToken);
298         switch (token) {
299         case NEWLINE:
300             break;
301         case DONE:
302             fclose(file);
303             return Successful;
304         case EALLOC:
305             status = AllocError;
306             break;
307         case NAME:
308             strcpy(alias, lexToken);
309             token = lexAlias(file, &lexToken);
310             switch (token) {
311             case NEWLINE:
312                 if (strcmp(alias, "FILE_NAMES_ALIASES"))
313                     status = BadFontPath;
314                 else if (!AddFileNameAliases(dir))
315                     status = AllocError;
316                 break;
317             case DONE:
318                 status = BadFontPath;
319                 break;
320             case EALLOC:
321                 status = AllocError;
322                 break;
323             case NAME:
324                 CopyISOLatin1Lowered((unsigned char *) alias,
325                                      (unsigned char *) alias,
326                                      strlen(alias));
327                 CopyISOLatin1Lowered((unsigned char *) font_name,
328                                      (unsigned char *) lexToken,
329                                      strlen(lexToken));
330                 if (!FontFileAddFontAlias (dir, alias, font_name))
331                     status = AllocError;
332                 break;
333             }
334         }
335     }
336     fclose(file);
337     return status;
338 }
339
340 #define QUOTE           0
341 #define WHITE           1
342 #define NORMAL          2
343 #define END             3
344 #define NL              4
345 #define BANG            5
346
347 static int  charClass;
348
349 static int
350 lexAlias(file, lexToken)
351     FILE       *file;
352     char      **lexToken;
353 {
354     int         c;
355     char       *t;
356     enum state {
357         Begin, Normal, Quoted, Comment
358     }           state;
359     int         count;
360
361     static char *tokenBuf = (char *) NULL;
362     static int  tokenSize = 0;
363
364     t = tokenBuf;
365     count = 0;
366     state = Begin;
367     for (;;) {
368         if (count == tokenSize) {
369             int         nsize;
370             char       *nbuf;
371
372             nsize = tokenSize ? (tokenSize << 1) : 64;
373             nbuf = (char *) xrealloc(tokenBuf, nsize);
374             if (!nbuf)
375                 return EALLOC;
376             tokenBuf = nbuf;
377             tokenSize = nsize;
378             t = tokenBuf + count;
379         }
380         c = lexc(file);
381         switch (charClass) {
382         case QUOTE:
383             switch (state) {
384             case Begin:
385             case Normal:
386                 state = Quoted;
387                 break;
388             case Quoted:
389                 state = Normal;
390                 break;
391             case Comment:
392                 break;
393             }
394             break;
395         case WHITE:
396             switch (state) {
397             case Begin:
398             case Comment:
399                 continue;
400             case Normal:
401                 *t = '\0';
402                 *lexToken = tokenBuf;
403                 return NAME;
404             case Quoted:
405                 break;
406             }
407             /* fall through */
408         case NORMAL:
409             switch (state) {
410             case Begin:
411                 state = Normal;
412                 break;
413             case Comment:
414                 continue;
415             }
416             *t++ = c;
417             ++count;
418             break;
419         case END:
420         case NL:
421             switch (state) {
422             case Begin:
423             case Comment:
424                 *lexToken = (char *) NULL;
425                 return charClass == END ? DONE : NEWLINE;
426             default:
427                 *t = '\0';
428                 *lexToken = tokenBuf;
429                 ungetc(c, file);
430                 return NAME;
431             }
432             break;
433         case BANG:
434             switch (state) {
435             case Begin:
436                 state = Comment;
437                 break;
438             case Comment:
439                 break;
440             default:
441                 *t++ = c;
442                 ++count;
443             }
444             break;
445         }
446     }
447 }
448
449 static int
450 lexc(file)
451     FILE       *file;
452 {
453     int         c;
454
455     c = getc(file);
456     switch (c) {
457     case EOF:
458         charClass = END;
459         break;
460     case '\\':
461         c = getc(file);
462         if (c == EOF)
463             charClass = END;
464         else
465             charClass = NORMAL;
466         break;
467     case '"':
468         charClass = QUOTE;
469         break;
470     case ' ':
471     case '\t':
472         charClass = WHITE;
473         break;
474     case '\r':
475     case '\n':
476         charClass = NL;
477         break;
478     case '!':
479         charClass = BANG;
480         break;
481     default:
482         charClass = NORMAL;
483         break;
484     }
485     return c;
486 }