comparison lib/fontset.c @ 0:92745d501b9a

initial import from kinput2-v3.1
author Yoshiki Yazawa <yaz@honeyplanet.jp>
date Mon, 08 Mar 2010 04:44:30 +0900
parents
children
comparison
equal deleted inserted replaced
-1:000000000000 0:92745d501b9a
1 #ifndef lint
2 static char *rcsid = "$Id: fontset.c,v 1.9 1994/06/02 04:59:23 ishisone Rel $";
3 #endif
4 /*
5 * Copyright (c) 1991 Software Research Associates, Inc.
6 *
7 * Permission to use, copy, modify, and distribute this software and its
8 * documentation for any purpose and without fee is hereby granted, provided
9 * that the above copyright notice appear in all copies and that both that
10 * copyright notice and this permission notice appear in supporting
11 * documentation, and that the name of Software Research Associates not be
12 * used in advertising or publicity pertaining to distribution of the
13 * software without specific, written prior permission. Software Research
14 * Associates makes no representations about the suitability of this software
15 * for any purpose. It is provided "as is" without express or implied
16 * warranty.
17 *
18 * Author: Makoto Ishisone, Software Research Associates, Inc., Japan
19 *
20 * a FontSet handler for kinput2.
21 */
22
23 #include <X11/Intrinsic.h>
24 #include <X11/Xatom.h>
25 #include <X11/Xmu/CharSet.h>
26 #include "CachedAtom.h"
27 #include "CachedFont.h"
28 #include "KIFontSet.h"
29
30 #define DEBUG_VAR debug_fontset
31 #include "DebugPrint.h"
32
33 typedef struct {
34 String name;
35 String xlfdname;
36 } FSFontName;
37
38 static char noname[] = "no";
39
40 static int match();
41 static Cardinal parseFontSet();
42 static Boolean tryCharSet();
43 static XFontStruct *csSuppliedMatchFont();
44 static XFontStruct *exactMatchFont();
45 static XFontStruct *csReplacedMatchFont();
46 static String getXLFDName();
47
48
49 /*- match: returns 1 if the specified string matches the pattern -*/
50 static int
51 match(s, p)
52 register char *s; /* string */
53 register char *p; /* pattern */
54 {
55 register int tmp;
56
57 while ((tmp = *p++) != '\0') {
58 switch (tmp) {
59 case '?':
60 if (*s++ == '\0') return 0;
61 continue;
62 case '*':
63 while ((tmp = match(s, p)) == 0) {
64 if (*s++ == '\0') return -1;
65 }
66 return tmp;
67 default:
68 if (*s++ != tmp) return 0;
69 continue;
70 }
71 }
72 return (*s == '\0');
73 }
74
75 /*- countCommas: count number of commas in the string -*/
76 static Cardinal
77 countCommas(s)
78 String s;
79 {
80 int n = 0;
81
82 while (*s != '\0') {
83 if (*s++ == ',') n++;
84 }
85 return n;
86 }
87
88 /*- parseFontSet: separate each font in a font name list -*/
89 static Cardinal
90 parseFontSet(spec, basenames)
91 String spec; /* IN */
92 FSFontName *basenames; /* OUT */
93 {
94 register char *p, *q;
95 Cardinal nnames;
96 int c;
97
98 nnames = 0;
99 p = spec;
100 for (;;) {
101 /* skip leading blanks */
102 while ((c = *p) != '\0' && (c == ' ' || c == '\t' || c == '\n')) p++;
103 if (c == '\0') break;
104
105 basenames[nnames++].name = p;
106
107 /* find comma or NUL char */
108 for (q = p; (c = *q) != '\0' && c != ','; q++) ;
109
110 /* omit trailing blanks */
111 p = q - 1;
112 while ((c = *p) == ' ' || c == '\t' || c == '\n') *p-- = '\0';
113
114 if (*q == '\0') break;
115 *q = '\0';
116 p = q + 1;
117 }
118
119 #ifdef DEBUG
120 if (DDEBUG_CONDITION(10)) {
121 if (nnames == 0) {
122 printf("\tparse error\n");
123 } else {
124 int i;
125 printf("\t%d elements\n", nnames);
126 for (i = 0; i < nnames; i++) printf("\t\t%s\n", basenames[i].name);
127 }
128 }
129 #endif
130
131 return nnames;
132 }
133
134 /*- tryCharSet: apply specified function to the fontnames for getting appropriate font for given character set -*/
135 static Boolean
136 tryCharSet(dpy, cset, extfont, namelist, numlist, func)
137 Display *dpy;
138 KICharSet *cset;
139 KICharSetFont *extfont;
140 FSFontName *namelist;
141 Cardinal numlist;
142 XFontStruct *(*func)();
143 {
144 KICharSetSpec *specs;
145 Cardinal i;
146 XFontStruct *font;
147
148 for (i = 0, specs = cset->specs; i < cset->num_specs; i++, specs++) {
149 font = (*func)(dpy, specs->pattern, namelist, numlist);
150 if (font != NULL) {
151 extfont->charset = specs->pattern;
152 extfont->cldata = specs->cldata;
153 extfont->font = font;
154 return True;
155 }
156 }
157 return False;
158 }
159
160 static XFontStruct *
161 exactMatchFont(dpy, csetstr, namelist, numlist)
162 Display *dpy;
163 String csetstr;
164 FSFontName *namelist;
165 Cardinal numlist;
166 {
167 XFontStruct *font;
168
169 while (numlist-- > 0) {
170 String name = (namelist++)->name;
171 String p;
172 int namelen;
173 int hyphen;
174
175 if (*name != '-' && *name != '+') continue; /* not an XLFD name */
176
177 namelen = strlen(name);
178 for (p = name + namelen - 1, hyphen = 0; p > name; p--) {
179 if (*p == '-') hyphen++;
180 if (hyphen == 2) goto found;
181 }
182 continue; /* doesn't contain charset part */
183
184 found:
185 p++; /* now p points the charset part of the fontname */
186 if (match(p, csetstr) > 0 &&
187 (font = CachedLoadQueryFontByName(dpy, name)) != NULL) {
188 TRACE(("\tmatched in exactMatchFont()\n"));
189 TRACE(("\t\tcset=%s, font=%s\n", csetstr, name));
190 return font;
191 }
192 }
193 return NULL;
194 }
195
196 static XFontStruct *
197 csSuppliedMatchFont(dpy, csetstr, namelist, numlist)
198 Display *dpy;
199 String csetstr;
200 FSFontName *namelist;
201 Cardinal numlist;
202 {
203 XFontStruct *font;
204
205 while (numlist-- > 0) {
206 String name = (namelist++)->name;
207 char namebuf[512];
208
209 if (*name != '-' && *name != '+') continue; /* not an XLFD name */
210
211 (void)strcpy(namebuf, name);
212 (void)strcat(namebuf, "-");
213 (void)strcat(namebuf, csetstr);
214
215 if ((font = CachedLoadQueryFontByName(dpy, namebuf)) != NULL) {
216 TRACE(("\tmatched in csSuppliedMatchFont()\n"));
217 TRACE(("\t\tcset=%s, font=%s\n", csetstr, namebuf));
218 return font;
219 }
220 }
221 return NULL;
222 }
223
224 static XFontStruct *
225 csReplacedMatchFont(dpy, csetstr, namelist, numlist)
226 Display *dpy;
227 String csetstr;
228 FSFontName *namelist;
229 Cardinal numlist;
230 {
231 XFontStruct *font;
232
233 while (numlist-- > 0) {
234 String name = namelist->name;
235 char namebuf[512];
236 String p;
237 int namelen;
238 int hyphen;
239
240 if (*name != '-' && *name != '+') { /* non XLFD name */
241 if (namelist->xlfdname == NULL ||
242 (namelist->xlfdname == noname &&
243 (namelist->xlfdname = getXLFDName(dpy, name)) == NULL)) {
244 /* this font doesn't have XLFD name */
245 namelist++;
246 continue;
247 }
248 name = namelist->xlfdname;
249 }
250 namelist++;
251
252 (void)strcpy(namebuf, name);
253 namelen = strlen(namebuf);
254
255 /* find charset part of the font name */
256 for (p = namebuf + namelen - 1, hyphen = 0; p > namebuf; p--) {
257 if (*p == '-') hyphen++;
258 if (hyphen == 2) goto found;
259 }
260 continue; /* doesn't contain charset part */
261
262 found:
263 p++; /* now p points the charset part of the fontname */
264
265 /* replace charset part */
266 (void)strcpy(p, csetstr);
267
268 if ((font = CachedLoadQueryFontByName(dpy, namebuf)) != NULL) {
269 TRACE(("\tmatched in csReplacedMatchFont()\n"));
270 TRACE(("\t\tcset=%s, font=%s\n", csetstr, namebuf));
271 return font;
272 }
273 }
274 return NULL;
275 }
276
277 /*- getXLFDName: obtain XLFD font name from a non XLFD font name -*/
278 static String
279 getXLFDName(dpy, nonxlfdname)
280 Display *dpy;
281 String nonxlfdname;
282 {
283 XFontStruct *font;
284 Atom fontprop;
285 String name;
286
287 TRACE(("getXLFDName(%s)\n", nonxlfdname));
288 font = CachedLoadQueryFontByName(dpy, nonxlfdname);
289 if (font == NULL) {
290 DPRINT(("getXLFDName(%s):CachedLoadQueryFontByName() failed\n",
291 nonxlfdname));
292 return NULL;
293 }
294 if (!XGetFontProperty(font, XA_FONT, (unsigned long *)&fontprop)) {
295 /* can't get 'FONT' property. so XLFD name cannot be obtained */
296 DPRINT(("getXLFDName(%s): can't get FONT property\n",
297 nonxlfdname));
298 CachedFreeFont(dpy, font);
299 return NULL;
300 }
301
302 CachedFreeFont(dpy, font);
303 name = CachedGetAtomName(dpy, fontprop);
304 TRACE(("\tgot %s\n", name));
305 return (*name == '-' || *name == '+') ? name : NULL;
306 }
307
308
309 /*
310 * public functions
311 */
312
313 int
314 ExtractFontsFromFontSet(dpy, fontset, charsets, exfonts, numcsets)
315 Display *dpy;
316 String fontset;
317 KICharSet *charsets;
318 KICharSetFont *exfonts;
319 Cardinal numcsets;
320 {
321 Cardinal nfonts;
322 String fsp;
323 char fsbuf[1024];
324 FSFontName *fnp;
325 FSFontName fnbuf[20];
326 int nfound;
327 int i;
328
329 TRACE(("ExtractFontsFromFontSet(fontset=%s)\n", fontset));
330 for (i = 0; i < numcsets; i++) {
331 exfonts[i].font = NULL;
332 exfonts[i].charset = NULL;
333 exfonts[i].cldata = NULL;
334 }
335
336 if (strlen(fontset) >= sizeof(fsbuf)) {
337 fsp = XtMalloc((unsigned int)(strlen(fontset) + 1));
338 } else {
339 fsp = fsbuf;
340 }
341 XmuCopyISOLatin1Lowered(fsp, fontset);
342
343 if ((nfonts = countCommas(fsp) + 1) >= XtNumber(fnbuf)) {
344 fnp = (FSFontName *)XtMalloc(nfonts * sizeof(FSFontName));
345 } else {
346 fnp = fnbuf;
347 }
348 for (i = 0; i < nfonts; i++) fnp[i].xlfdname = noname;
349
350 if ((nfonts = parseFontSet(fsp, fnp)) == 0) {
351 if (fsp != fsbuf) XtFree(fsp);
352 if (fnp != fnbuf) XtFree((char *)fnp);
353 return 0;
354 }
355
356 nfound = 0;
357 for (i = 0; i < numcsets; i++) {
358 KICharSet *cp = charsets + i;
359 KICharSetFont *fp = exfonts + i;
360
361 TRACE(("\tfor charset #%d\n", i));
362 if (tryCharSet(dpy, cp, fp, fnp, nfonts, exactMatchFont) ||
363 tryCharSet(dpy, cp, fp, fnp, nfonts, csSuppliedMatchFont) ||
364 tryCharSet(dpy, cp, fp, fnp, nfonts, csReplacedMatchFont)) {
365 nfound++;
366 }
367 }
368 if (fsp != fsbuf) XtFree(fsp);
369 if (fnp != fnbuf) XtFree((char *)fnp);
370
371 return nfound;
372 }