Merge from vendor branch NTPD:
[dragonfly.git] / contrib / groff / src / xditview / font.c
1 /*
2  * font.c
3  *
4  * map dvi fonts to X fonts
5  */
6
7 #include <X11/Xos.h>
8 #include <X11/IntrinsicP.h>
9 #include <X11/StringDefs.h>
10 #include <stdio.h>
11 #include <ctype.h>
12 #include "DviP.h"
13 #include "XFontName.h"
14
15 static DisposeFontSizes();
16
17 static char *
18 savestr (s)
19         char    *s;
20 {
21         char    *n;
22
23         if (!s)
24                 return 0;
25         n = XtMalloc (strlen (s) + 1);
26         if (n)
27                 strcpy (n, s);
28         return n;
29 }
30
31 static DviFontList *
32 LookupFontByPosition (dw, position)
33         DviWidget       dw;
34         int             position;
35 {
36         DviFontList     *f;
37
38         for (f = dw->dvi.fonts; f; f = f->next)
39                 if (f->dvi_number == position)
40                         break;
41         return f;
42 }
43
44 int
45 MaxFontPosition (dw)
46         DviWidget dw;
47 {
48         DviFontList     *f;
49         int n = -1;
50
51         for (f = dw->dvi.fonts; f; f = f->next)
52                 if (f->dvi_number > n)
53                         n = f->dvi_number;
54         return n;
55 }
56
57 static DviFontSizeList *
58 LookupFontSizeBySize (dw, f, size)
59         DviWidget       dw;
60         DviFontList     *f;
61         int             size;
62 {
63         DviFontSizeList *fs, *best = 0, *smallest = 0;
64         int             bestsize = 0;
65         XFontName       fontName;
66         unsigned int    fontNameAttributes;
67         char            fontNameString[2048];
68         int             decipointsize;
69         
70         if (f->scalable) {
71                 decipointsize = (10*size)/dw->dvi.sizescale;
72                 for (best = f->sizes; best; best = best->next)
73                         if (best->size == decipointsize)
74                                 return best;
75                 best = (DviFontSizeList *) XtMalloc(sizeof *best);
76                 best->next = f->sizes;
77                 best->size = decipointsize;
78                 f->sizes = best;
79                 XParseFontName (f->x_name, &fontName, &fontNameAttributes);
80                 fontNameAttributes &= ~(FontNamePixelSize|FontNameAverageWidth);
81                 fontNameAttributes |= FontNameResolutionX;
82                 fontNameAttributes |= FontNameResolutionY;
83                 fontNameAttributes |= FontNamePointSize;
84                 fontName.ResolutionX = dw->dvi.display_resolution;
85                 fontName.ResolutionY = dw->dvi.display_resolution;
86                 fontName.PointSize = decipointsize;
87                 XFormatFontName (&fontName, fontNameAttributes, fontNameString);
88                 best->x_name = savestr (fontNameString);
89                 best->doesnt_exist = 0;
90                 best->font = 0;
91                 return best;
92         }
93         for (fs = f->sizes; fs; fs=fs->next) {
94                 if (dw->dvi.sizescale*fs->size <= 10*size
95                     && fs->size >= bestsize) {
96                         best = fs;
97                         bestsize = fs->size;
98                 }
99                 if (smallest == 0 || fs->size < smallest->size)
100                         smallest = fs;
101         }
102         return best ? best : smallest;
103 }
104
105 static char *
106 SkipFontNameElement (n)
107         char    *n;
108 {
109         while (*n != '-')
110                 if (!*++n)
111                         return 0;
112         return n+1;
113 }
114
115 # define SizePosition           8
116 # define EncodingPosition       13
117
118 static
119 ConvertFontNameToSize (n)
120         char    *n;
121 {
122         int     i, size;
123
124         for (i = 0; i < SizePosition; i++) {
125                 n = SkipFontNameElement (n);
126                 if (!n)
127                         return -1;
128         }
129         size = atoi (n);
130         return size;
131 }
132
133 static char *
134 ConvertFontNameToEncoding (n)
135         char    *n;
136 {
137         int i;
138         for (i = 0; i < EncodingPosition; i++) {
139                 n = SkipFontNameElement (n);
140                 if (!n)
141                         return 0;
142         }
143         return n;
144 }
145
146 DviFontSizeList *
147 InstallFontSizes (dw, x_name, scalablep)
148         DviWidget       dw;
149         char            *x_name;
150         Boolean         *scalablep;
151 {
152         char    fontNameString[2048];
153         char    **fonts;
154         int     i, count;
155         int     size;
156         DviFontSizeList *sizes, *new;
157         XFontName       fontName;
158         unsigned int    fontNameAttributes;
159
160         *scalablep = FALSE;
161         if (!XParseFontName (x_name, &fontName, &fontNameAttributes))
162                 return 0;
163         fontNameAttributes &= ~(FontNamePixelSize|FontNamePointSize
164                                 |FontNameAverageWidth);
165         fontNameAttributes |= FontNameResolutionX;
166         fontNameAttributes |= FontNameResolutionY;
167         fontName.ResolutionX = dw->dvi.display_resolution;
168         fontName.ResolutionY = dw->dvi.display_resolution;
169         XFormatFontName (&fontName, fontNameAttributes, fontNameString);
170         fonts = XListFonts (XtDisplay (dw), fontNameString, 10000000, &count);
171         sizes = 0;
172         for (i = 0; i < count; i++) {
173                 size = ConvertFontNameToSize (fonts[i]);
174                 if (size == 0) {
175                         DisposeFontSizes (dw, sizes);
176                         sizes = 0;
177                         *scalablep = TRUE;
178                         break;
179                 }
180                 if (size != -1) {
181                         new = (DviFontSizeList *) XtMalloc (sizeof *new);
182                         new->next = sizes;
183                         new->size = size;
184                         new->x_name = savestr (fonts[i]);
185                         new->doesnt_exist = 0;
186                         new->font = 0;
187                         sizes = new;
188                 }
189         }
190         XFreeFontNames (fonts);
191         return sizes;
192 }
193
194 static
195 DisposeFontSizes (dw, fs)
196         DviWidget       dw;
197         DviFontSizeList *fs;
198 {
199         DviFontSizeList *next;
200
201         for (; fs; fs=next) {
202                 next = fs->next;
203                 if (fs->x_name)
204                         XtFree (fs->x_name);
205                 if (fs->font && fs->font != dw->dvi.default_font) {
206                         XUnloadFont (XtDisplay (dw), fs->font->fid);
207                         XFree ((char *)fs->font);
208                 }
209                 XtFree ((char *) fs);
210         }
211 }
212
213 static DviFontList *
214 InstallFont (dw, position, dvi_name, x_name)
215         DviWidget       dw;
216         int             position;
217         char            *dvi_name;
218         char            *x_name;
219 {
220         DviFontList     *f;
221         char            *encoding;
222
223         if ((f = LookupFontByPosition (dw, position)) != NULL) {
224                 /*
225                  * ignore gratuitous font loading
226                  */
227                 if (!strcmp (f->dvi_name, dvi_name) &&
228                     !strcmp (f->x_name, x_name))
229                         return f;
230
231                 DisposeFontSizes (dw, f->sizes);
232                 if (f->dvi_name)
233                         XtFree (f->dvi_name);
234                 if (f->x_name)
235                         XtFree (f->x_name);
236                 f->device_font = 0;
237         } else {
238                 f = (DviFontList *) XtMalloc (sizeof (*f));
239                 f->next = dw->dvi.fonts;
240                 dw->dvi.fonts = f;
241         }
242         f->initialized = FALSE;
243         f->dvi_name = savestr (dvi_name);
244         f->device_font = device_find_font (dw->dvi.device, dvi_name);
245         f->x_name = savestr (x_name);
246         f->dvi_number = position;
247         f->sizes = 0;
248         f->scalable = FALSE;
249         if (f->x_name) {
250                 encoding = ConvertFontNameToEncoding (f->x_name);
251                 f->char_map = DviFindMap (encoding);
252         } else
253                 f->char_map = 0;
254         /* 
255          * force requery of fonts
256          */
257         dw->dvi.font = 0;
258         dw->dvi.font_number = -1;
259         dw->dvi.cache.font = 0;
260         dw->dvi.cache.font_number = -1;
261         dw->dvi.device_font = 0;
262         dw->dvi.device_font_number = -1;
263         return f;
264 }
265
266 ForgetFonts (dw)
267         DviWidget dw;
268 {
269         DviFontList *f = dw->dvi.fonts;
270         
271         while (f) {
272                 DviFontList *tem = f;
273
274                 if (f->sizes)
275                         DisposeFontSizes (dw, f->sizes);
276                 if (f->dvi_name)
277                         XtFree (f->dvi_name);
278                 if (f->x_name)
279                         XtFree (f->x_name);
280                 f = f->next;
281                 XtFree ((char *) tem);
282         }
283         
284         /* 
285          * force requery of fonts
286          */
287         dw->dvi.font = 0;
288         dw->dvi.font_number = -1;
289         dw->dvi.cache.font = 0;
290         dw->dvi.cache.font_number = -1;
291         dw->dvi.device_font = 0;
292         dw->dvi.device_font_number = -1;
293         dw->dvi.fonts = 0;
294 }
295
296
297 static char *
298 MapDviNameToXName (dw, dvi_name)
299         DviWidget       dw;
300         char            *dvi_name;
301 {
302         DviFontMap      *fm;
303         
304         for (fm = dw->dvi.font_map; fm; fm=fm->next)
305                 if (!strcmp (fm->dvi_name, dvi_name))
306                         return fm->x_name;
307         return 0;
308 }
309
310 #if 0
311 static char *
312 MapXNameToDviName (dw, x_name)
313         DviWidget       dw;
314         char            *x_name;
315 {
316         DviFontMap      *fm;
317         
318         for (fm = dw->dvi.font_map; fm; fm=fm->next)
319                 if (!strcmp (fm->x_name, x_name))
320                         return fm->dvi_name;
321         return 0;
322 }
323 #endif
324
325 ParseFontMap (dw)
326         DviWidget       dw;
327 {
328         char            dvi_name[1024];
329         char            x_name[2048];
330         char            *m, *s;
331         DviFontMap      *fm, *new;
332
333         if (dw->dvi.font_map)
334                 DestroyFontMap (dw->dvi.font_map);
335         fm = 0;
336         m = dw->dvi.font_map_string;
337         while (*m) {
338                 s = m;
339                 while (*m && !isspace (*m))
340                         ++m;
341                 strncpy (dvi_name, s, m-s);
342                 dvi_name[m-s] = '\0';
343                 while (isspace (*m))
344                         ++m;
345                 s = m;
346                 while (*m && *m != '\n')
347                         ++m;
348                 strncpy (x_name, s, m-s);
349                 x_name[m-s] = '\0';
350                 new = (DviFontMap *) XtMalloc (sizeof *new);
351                 new->x_name = savestr (x_name);
352                 new->dvi_name = savestr (dvi_name);
353                 new->next = fm;
354                 fm = new;
355                 ++m;
356         }
357         dw->dvi.font_map = fm;
358 }
359
360 DestroyFontMap (font_map)
361         DviFontMap      *font_map;
362 {
363         DviFontMap      *next;
364
365         for (; font_map; font_map = next) {
366                 next = font_map->next;
367                 if (font_map->x_name)
368                         XtFree (font_map->x_name);
369                 if (font_map->dvi_name)
370                         XtFree (font_map->dvi_name);
371                 XtFree ((char *) font_map);
372         }
373 }
374
375 /* ARGSUSED */
376
377 SetFontPosition (dw, position, dvi_name, extra)
378         DviWidget       dw;
379         int             position;
380         char            *dvi_name;
381         char            *extra; /* unused */
382 {
383         char    *x_name;
384
385         x_name = MapDviNameToXName (dw, dvi_name);
386         if (x_name)
387                 (void) InstallFont (dw, position, dvi_name, x_name);
388 }
389
390 XFontStruct *
391 QueryFont (dw, position, size)
392         DviWidget       dw;
393         int             position;
394         int             size;
395 {
396         DviFontList     *f;
397         DviFontSizeList *fs;
398
399         f = LookupFontByPosition (dw, position);
400         if (!f)
401                 return dw->dvi.default_font;
402         if (!f->initialized) {
403                 f->sizes = InstallFontSizes (dw, f->x_name, &f->scalable);
404                 f->initialized = TRUE;
405         }
406         fs = LookupFontSizeBySize (dw, f, size);
407         if (!fs)
408                 return dw->dvi.default_font;
409         if (!fs->font) {
410                 if (fs->x_name)
411                         fs->font = XLoadQueryFont (XtDisplay (dw), fs->x_name);
412                 if (!fs->font)
413                         fs->font = dw->dvi.default_font;
414         }
415         return fs->font;
416 }
417
418 DeviceFont *
419 QueryDeviceFont (dw, position)
420         DviWidget       dw;
421         int             position;
422 {
423         DviFontList     *f;
424
425         f = LookupFontByPosition (dw, position);
426         if (!f)
427                 return 0;
428         return f->device_font;
429 }
430
431 DviCharNameMap *
432 QueryFontMap (dw, position)
433         DviWidget       dw;
434         int             position;
435 {
436         DviFontList     *f;
437
438         f = LookupFontByPosition (dw, position);
439         if (f)
440             return f->char_map;
441         else
442             return 0;
443 }
444
445 #if 0
446 LoadFont (dw, position, size)
447         DviWidget       dw;
448         int             position;
449         int             size;
450 {
451         XFontStruct     *font;
452
453         font = QueryFont (dw, position, size);
454         dw->dvi.font_number = position;
455         dw->dvi.font_size = size;
456         dw->dvi.font = font;
457         XSetFont (XtDisplay (dw), dw->dvi.normal_GC, font->fid);
458         return;
459 }
460 #endif
461
462 /*
463 Local Variables:
464 c-indent-level: 8
465 c-continued-statement-offset: 8
466 c-brace-offset: -8
467 c-argdecl-indent: 8
468 c-label-offset: -8
469 c-tab-always-indent: nil
470 End:
471 */