Add GNU LGPL headers to all .c .C and .h files
[oweals/cde.git] / cde / programs / dtlogin / fontpath.c
1 /*
2  * CDE - Common Desktop Environment
3  *
4  * Copyright (c) 1993-2012, The Open Group. All rights reserved.
5  *
6  * These libraries and programs are free software; you can
7  * redistribute them and/or modify them under the terms of the GNU
8  * Lesser General Public License as published by the Free Software
9  * Foundation; either version 2 of the License, or (at your option)
10  * any later version.
11  *
12  * These libraries and programs are distributed in the hope that
13  * they will be useful, but WITHOUT ANY WARRANTY; without even the
14  * implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
15  * PURPOSE. See the GNU Lesser General Public License for more
16  * details.
17  *
18  * You should have received a copy of the GNU Lesser General Public
19  * License along with these librararies and programs; if not, write
20  * to the Free Software Foundation, Inc., 51 Franklin Street, Fifth
21  * Floor, Boston, MA 02110-1301 USA
22  */
23 /* $XConsortium: fontpath.c /main/4 1995/10/27 16:13:29 rswiston $ */
24 /*                                                                      *
25  * (c) Copyright 1993, 1994 Hewlett-Packard Company                     *
26  * (c) Copyright 1993, 1994 International Business Machines Corp.       *
27  * (c) Copyright 1993, 1994 Sun Microsystems, Inc.                      *
28  * (c) Copyright 1993, 1994 Novell, Inc.                                *
29  */
30 /*
31 **  fontpath.c - font path modification routines
32 **
33 **  $fontpath.c,v 1.1 93/06/24 14:52:10 bill Exp $
34 **
35 **  Copyright 1993 Hewlett-Packard Company
36 */
37
38 # include "dm.h"
39 # include <signal.h>
40 # include <X11/Xatom.h>
41 # include <setjmp.h>
42 # include <utmp.h>
43 # include "vgproto.h"
44
45 /* 
46 **  Prototypes
47 */
48
49
50 int ApplyFontPathMods( struct display *d, Display *dpy );
51 void GetSysParms( char **tzpp, char **fhpp, char **ftpp );
52 static int PathInPList(char *path, char **fplist, int listlen);
53 static int PathInZList(char *path, char *fplist, int listlen);
54 static int SeparateParts( char **path );
55
56
57 static
58 DebugFontPath(char *note, char **path, int nelems)
59 {
60     int i;
61     Debug("  %s: %d elements\n",note,nelems);
62     for (i=0; i<nelems; i++)
63         Debug("    %s\n",path[i]);
64 }
65
66 static int 
67 ErrorHandler(Display *dpy, XErrorEvent *event)
68 {
69     XmuPrintDefaultErrorMessage(dpy, event, stderr);
70     return 0; /* nonfatal */
71 }
72
73 /* ________________________________________________________________
74 **|                                                                |
75 **| ApplyFontPathMods(d) -                                         |
76 **|                                                                |
77 **|     If new font path mods are mandated, fabricate and apply    |
78 **|     an appropriate new complete X server font path.            |
79 **|                                                                |
80 **| Specify: d = pointer to display structure                      |
81 **|                                                                |
82 **| Returns: nothing                                               |
83 **|________________________________________________________________|
84 */
85
86 int 
87 ApplyFontPathMods( struct display *d, Display *dpy )
88 {
89     FILE *fin;
90     char *s,*t;
91     char *fph = NULL;
92     char *fpt = NULL;
93     char **fontPath,**newList;
94     int numHeads = 0;
95     int numTails = 0;
96     int i,j,k,numPaths;
97
98     Debug("ApplyFontPathMods() for %s\n",d->name);
99
100     if (d->displayType.location == Foreign) {
101         Debug("  Foreign display\n");
102         return;
103     }
104
105     if (!(fontPath=XGetFontPath(dpy, &numPaths))) {
106         Debug("  Can't get font path\n");
107         return;
108     }
109
110     /*
111     **  Font path mods can come from (in priority order):
112     **
113     **    1. FONT_PATH_HEAD/TAIL definitions in /etc/src.sh
114     **    2. fontPathHead/Tail resources
115     */
116
117     GetSysParms(0,&fph,&fpt);
118
119     if (fph)          { s = "sys parm file"; }
120     else if (fpHead)  { s = "resource"; fph = strdup(fpHead); }
121     if (fph && !*fph) { free(fph); fph = NULL; }
122     if (fph)          Debug("  +fp (%s) %s\n",s,fph);
123
124     if (fpt)          { s = "sys parm file"; }
125     else if (fpTail)  { s = "resource"; fpt = strdup(fpTail); }
126     if (fpt && !*fpt) { free(fpt); fpt = NULL; }
127     if (fpt)          Debug("  fp+ (%s) %s\n",s,fpt);
128
129     /* 
130     **  Break up fph and fpt into constituent parts and 
131     **  then reconstruct the complete, modified font path.
132     **  During reconstruction we also eliminate redundancies.
133     */
134
135     numHeads = SeparateParts(&fph);
136     numTails = SeparateParts(&fpt);
137     if (numHeads || numTails) {
138         newList = (char **) malloc((numHeads+numPaths+numTails)
139             * sizeof(char *));
140         if (newList) {
141             for (s=fph, i=j=0; j<numHeads; j++) {
142                 if (!PathInPList(s,newList,i))
143                     newList[i++] = s;
144                 while (*s) s++; s++;
145             }
146             for (j=0; j<numPaths; j++) {
147                 if (!PathInPList(fontPath[j],newList,i) &&
148                     !PathInZList(fontPath[j],fpt,numTails)) {
149                     newList[i++] = fontPath[j];
150                 }
151             }
152             for (s=fpt, j=0; j<numTails; j++) {
153                 if (!PathInPList(s,newList,i))
154                     newList[i++] = s;   
155                 while (*s) s++; s++;
156             }
157             if (debugLevel > 0)
158                 DebugFontPath("Request (XSetFontPath)",newList,i);
159
160             /*
161             **  Tell X server to set new font path now.  Log failure,
162             **  but don't let it be fatal.  (Note that caller should
163             **  reset error handler to elsewhere when we return.)
164             */
165
166             (void)XSetErrorHandler(ErrorHandler);
167             XSetFontPath(dpy, newList, i);
168             XSync(dpy, True);
169             free(newList);
170             if (debugLevel > 0) {
171                 newList = XGetFontPath(dpy, &i);
172                 DebugFontPath("Confirm (XGetFontPath)",newList,i);
173                 XFreeFontPath(newList);
174             }
175         }
176     }
177
178     if (fph) free(fph);
179     if (fpt) free(fpt);
180     XFreeFontPath(fontPath);
181 }
182
183 /* ___________________________________________________________________
184 **|                                                                   |
185 **| PathInPList(path,fplist,listlen) -                                |
186 **|                                                                   |
187 **|     Determine if a specific fontpath element is in a list,        |
188 **|     taking into account that identical elements may be formed     |
189 **|     differently (with multiple embedded and trailing slashes).    |
190 **|                                                                   |
191 **| Specify: (char *)path = the single element to be tested           |
192 **|          (char **)fplist = list of ptrs to asciz elements         |
193 **|          (int)listlen = number of pointers in the list            |
194 **|                                                                   |
195 **| Returns: TRUE if element is in the list                           |
196 **|___________________________________________________________________|
197 */
198
199 static int
200 PathInPList(char *path, char **fplist, int listlen)
201 {
202     char *s,*t;
203     while (listlen-- > 0) {
204         for (s=path, t=fplist[listlen]; *s && (*s == *t); ) {
205             t++; while (*t == '/') t++;
206             s++; while (*s == '/') s++;
207         }
208         if (!*s && !*t) return 1;
209     }
210     return 0;    
211 }
212
213 /* ___________________________________________________________________
214 **|                                                                   |
215 **| PathInZList(path,fplist,listlen) -                                |
216 **|                                                                   |
217 **|     Determine if a specific fontpath element is in a list,        |
218 **|     taking into account that identical elements may be formed     |
219 **|     differently (with multiple embedded and trailing slashes).    |
220 **|                                                                   |
221 **| Specify: (char *)path = the single element to be tested           |
222 **|          (char *)fplist = list of concatenated asciz elements     |
223 **|          (int)listlen = number of elements in the list            |
224 **|                                                                   |
225 **| Returns: TRUE if element is in the list                           |
226 **|___________________________________________________________________|
227 */
228
229 static int
230 PathInZList(char *path, char *fplist, int listlen)
231 {
232     char *s,*t;
233     for (t=fplist; listlen > 0; listlen--) {
234         for (s=path; *s && (*s == *t); ) {
235             t++; while (*t == '/') t++;
236             s++; while (*s == '/') s++;
237         }
238         if (!*s && !*t) return 1;
239         while (*t) t++; t++;
240     }
241     return 0;    
242 }
243
244 /* ________________________________________________________________
245 **|                                                                |
246 **| SeparateParts(path)                                            |
247 **|                                                                |
248 **|     Break a comma-delimited asciz path string into its         |
249 **|     separate asciz constituent parts.                          |
250 **|                                                                |
251 **| Specify: path = ptr to asciz path string (e.g., "as,df,jk")    |
252 **|                                                                |
253 **| Returns: number of constituent parts, with path string         |
254 **|          converted into as many sequential asciz strings       |
255 **|          (e.g., "as\0df\0jk").                                 |
256 **|________________________________________________________________|
257 */
258
259 static int
260 SeparateParts( char **path )
261 {
262     char *t,*s;
263     int nparts = 0;
264     if (path && *path)
265         for (s=*path; t=strtok(s,","); s=NULL, nparts++);
266     return nparts;
267 }
268
269 /* ___________________________________________________________________
270 **|                                                                   |
271 **| GetSysParms(tzpp,fhpp,ftpp) -                                     |
272 **|                                                                   |
273 **|     Extract TZ, FONT_PATH_HEAD, and FONT_PATH_TAIL definitions    |
274 **|     from the sys parms file (typically /etc/src.sh).              |
275 **|                                                                   |
276 **| Specify: (char **)tzpp = where to put ptr to TZ string            |
277 **|          (char **)fhpp = where to put ptr to FONT_PATH_HEAD       |
278 **|          (char **)ftpp = where to put ptr to FONT_PATH_TAIL       |
279 **|                                                                   |
280 **|     Specify a NULL (char **) for any undesired strings.           |
281 **|                                                                   |
282 **| Returns: Appropriate pointers to malloc'ed strings (NULL pointer  |
283 **|          if a string is neither requested nor defined).           |
284 **|___________________________________________________________________|
285 */
286
287 void
288 GetSysParms( char **tzpp, char **fhpp, char **ftpp )
289 {
290     FILE *fin;
291     char *s,*t,buf[256];
292
293     if (tzpp) *tzpp = NULL;
294     if (fhpp) *fhpp = NULL;
295     if (ftpp) *ftpp = NULL;
296     if ((*sysParmsFile != '/') || !(fin=fopen(sysParmsFile,"r"))) {
297         Debug("(GetSysParms) Can't open sys parms file\n");
298         return;
299     }
300     Debug("(GetSysParms) Reading sys parms file\n");
301     while (fgets(buf,255,fin)) {
302         for (t=buf; *t && *t<=' '; t++); /* t -> EOS or nonblank */
303         if (!*t || *t=='#') continue;    /* ignore comment lines */
304         while (*t && *t!='\n') t++;      /* t -> EOS or newline  */
305         if (*t) *t = '\0';               /* discard newline char */
306         if (tzpp && !*tzpp)
307             if ((s=strstr(buf,"TZ=")) && (t=strtok(s+3,"; \t")))
308                 *tzpp = (char *) strdup(t);
309         if (fhpp && !*fhpp)
310             if ((s=strstr(buf,"FONT_PATH_HEAD=")) && (t=strtok(s+15,"; \t")))
311                 *fhpp = (char *) strdup(t);
312         if (ftpp && !*ftpp)
313             if ((s=strstr(buf,"FONT_PATH_TAIL=")) && (t=strtok(s+15,"; \t")))
314                 *ftpp = (char *) strdup(t);
315     }
316     fclose(fin);
317 }    
318