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