Merge from vendor branch CVS:
[dragonfly.git] / contrib / groff / src / xditview / xtotroff.c
1 /*
2  * xtotroff
3  *
4  * convert X font metrics into troff font metrics
5  */
6
7 #include        <X11/Xlib.h>
8 #include        <stdio.h>
9 #include        <ctype.h>
10 #include        <unistd.h>
11 #include        <stdlib.h>
12 #include        <fcntl.h>
13 #include        "XFontName.h"
14 #include        "DviChar.h"
15
16 #ifdef X_NOT_STDC_ENV
17 char *malloc();
18 #else 
19 #include <stdlib.h>
20 #endif
21
22 #define charWidth(fi,c) ((fi)->per_char[(c) - (fi)->min_char_or_byte2].width)
23 #define charHeight(fi,c)        ((fi)->per_char[(c) - (fi)->min_char_or_byte2].ascent)
24 #define charDepth(fi,c) ((fi)->per_char[(c) - (fi)->min_char_or_byte2].descent)
25 #define charLBearing(fi,c)      ((fi)->per_char[(c) - (fi)->min_char_or_byte2].lbearing)
26 #define charRBearing(fi,c)      ((fi)->per_char[(c) - (fi)->min_char_or_byte2].rbearing)
27
28 Display         *dpy;
29 int             groff_flag = 0;
30 unsigned        resolution = 75;
31 unsigned        point_size = 10;
32
33 int charExists (fi, c)
34         XFontStruct     *fi;
35         int             c;
36 {
37         XCharStruct *p;
38
39         if (c < fi->min_char_or_byte2 || c > fi->max_char_or_byte2)
40                 return 0;
41         p = fi->per_char + (c - fi->min_char_or_byte2);
42         return (p->lbearing != 0 || p->rbearing != 0 || p->width != 0
43                 || p->ascent != 0 || p->descent != 0 || p->attributes != 0);
44 }
45
46 /* Canonicalize the font name by replacing scalable parts by *s. */
47
48 CanonicalizeFontName (font_name, canon_font_name)
49         char *font_name, *canon_font_name;
50 {
51         unsigned int    attributes;
52         XFontName       parsed;
53
54         if (!XParseFontName(font_name, &parsed, &attributes)) {
55                 fprintf (stderr, "not a standard name: %s\n", font_name);
56                 return 0;
57         }
58
59         attributes &= ~(FontNamePixelSize|FontNameAverageWidth
60                         |FontNamePointSize
61                         |FontNameResolutionX|FontNameResolutionY);
62         XFormatFontName(&parsed, attributes, canon_font_name);
63         return 1;
64 }
65
66 int FontNamesAmbiguous(font_name, names, count)
67 char *font_name;
68 char **names;
69 int count;
70 {
71         char name1[2048], name2[2048];
72         int i;
73
74         if (count == 1)
75                 return 0;
76
77         for (i = 0; i < count; i++) {
78                 if (!CanonicalizeFontName(names[i], i == 0 ? name1 : name2)) {
79                         fprintf(stderr, "bad font name: %s\n", names[i]);
80                         return 1;
81                 }
82                 if (i > 0 && strcmp(name1, name2) != 0) {
83                         fprintf(stderr, "ambiguous font name: %s\n", font_name);
84                         fprintf(stderr, "  matches %s\n", names[0]);
85                         fprintf(stderr, "  and %s\n", names[i]);
86                         return 1;
87                 }
88
89         }
90         return 0;
91 }
92
93 MapFont (font_name, troff_name)
94         char    *font_name;
95         char    *troff_name;
96 {
97         XFontStruct     *fi;
98         int             count;
99         char            **names;
100         FILE            *out;
101         int             c;
102         unsigned int    attributes;
103         XFontName       parsed;
104         int             j, k;
105         DviCharNameMap  *char_map;
106         char            encoding[256];
107         char            *s;
108         int             wid;
109         char            name_string[2048];
110
111         if (!XParseFontName(font_name, &parsed, &attributes)) {
112                 fprintf (stderr, "not a standard name: %s\n", font_name);
113                 return 0;
114         }
115
116         attributes &= ~(FontNamePixelSize|FontNameAverageWidth);
117         attributes |= FontNameResolutionX;
118         attributes |= FontNameResolutionY;
119         attributes |= FontNamePointSize;
120         parsed.ResolutionX = resolution;
121         parsed.ResolutionY = resolution;
122         parsed.PointSize = point_size*10;
123         XFormatFontName(&parsed, attributes, name_string);
124
125         names = XListFonts (dpy, name_string, 100000, &count);
126         if (count < 1) {
127                 fprintf (stderr, "bad font name: %s\n", font_name);
128                 return 0;
129         }
130
131         if (FontNamesAmbiguous(font_name, names, count))
132                 return 0;
133
134         XParseFontName(names[0], &parsed, &attributes);
135         sprintf (encoding, "%s-%s", parsed.CharSetRegistry,
136                                     parsed.CharSetEncoding);
137         for (s = encoding; *s; s++)
138                 if (isupper (*s))
139                         *s = tolower (*s);
140         char_map = DviFindMap (encoding);
141         if (!char_map) {
142                 fprintf (stderr, "not a standard encoding: %s\n", encoding);
143                 return 0;
144         }
145
146         fi = XLoadQueryFont (dpy, names[0]);
147         if (!fi) {
148                 fprintf (stderr, "font does not exist: %s\n", names[0]);
149                 return 0;
150         }
151                 
152         printf ("%s -> %s\n", names[0], troff_name);
153
154         { /* Avoid race while opening file */
155                 int fd;
156                 (void) unlink (troff_name);
157                 fd = open (troff_name, O_WRONLY | O_CREAT | O_EXCL, 0600);
158                 out = fdopen (fd, "w");
159         }
160
161         if (!out) {
162                 perror (troff_name);
163                 return 0;
164         }
165         fprintf (out, "name %s\n", troff_name);
166         if (!strcmp (char_map->encoding, "adobe-fontspecific"))
167                 fprintf (out, "special\n");
168         if (charExists (fi, ' ')) {
169                 int w = charWidth (fi, ' ');
170                 if (w > 0)
171                         fprintf (out, "spacewidth %d\n", w);
172         }
173         fprintf (out, "charset\n");
174         for (c = fi->min_char_or_byte2; c <= fi->max_char_or_byte2; c++) {
175                 char *name = DviCharName (char_map,c,0);
176                 if (charExists (fi, c) && (groff_flag || name)) {
177
178                         wid = charWidth (fi, c);
179
180                         fprintf (out, "%s\t%d",
181                                         name ? name : "---",
182                                         wid);
183                         if (groff_flag) {
184                                 int     param[5];
185                                 param[0] = charHeight (fi, c);
186                                 param[1] = charDepth (fi, c);
187                                 param[2] = 0 /* charRBearing (fi, c) - wid */;
188                                 param[3] = 0 /* charLBearing (fi, c) */;
189                                 param[4] = 0; /* XXX */
190                                 for (j = 0; j < 5; j++)
191                                         if (param[j] < 0)
192                                                 param[j] = 0;
193                                 for (j = 4; j >= 0; j--)
194                                         if (param[j] != 0)
195                                                 break;
196                                 for (k = 0; k <= j; k++)
197                                         fprintf (out, ",%d", param[k]);
198                         }
199                         fprintf (out, "\t0\t0%o\n", c);
200                         
201                         if (name) {
202                                 for (k = 1; DviCharName(char_map,c,k); k++) {
203                                         fprintf (out, "%s\t\"\n",
204                                                  DviCharName (char_map,c,k));
205                                 }
206                         }
207                 }
208         }
209         XUnloadFont (dpy, fi->fid);
210         fclose (out);
211         return 1;
212 }
213
214 static usage(prog)
215         char    *prog;
216 {
217         fprintf (stderr,
218                  "usage: %s [-g] [-r resolution] [-s pointsize] FontMap\n",
219                  prog);
220         exit (1);
221 }
222
223
224 /* For use by DviChar.c */
225
226 char *xmalloc(n)
227 int n;
228 {
229         char *p = malloc(n);
230         if (!p) {
231                 fprintf(stderr, "Out of memory\n");
232                 exit(1);
233         }
234         return p;
235 }
236
237 main (argc, argv)
238         char    **argv;
239 {
240         char    troff_name[1024];
241         char    font_name[1024];
242         char    line[1024];
243         char    *a, *b, c;
244         int     position;
245         FILE    *map;
246         int     opt;
247         extern int optind;
248         extern char *optarg;
249
250         while ((opt = getopt(argc, argv, "gr:s:")) != EOF) {
251                 switch (opt) {
252                 case 'g':
253                         groff_flag = 1;
254                         break;
255                 case 'r':
256                         sscanf(optarg, "%u", &resolution);
257                         break;
258                 case 's':
259                         sscanf(optarg, "%u", &point_size);
260                         break;
261                 default:
262                         usage(argv[0]);
263                 }
264         }
265         if (argc - optind != 1)
266                 usage(argv[0]);
267
268         dpy = XOpenDisplay (0);
269         if (!dpy) {
270                 fprintf (stderr, "Can't connect to the X server.\n");
271                 fprintf (stderr, "Make sure the DISPLAY environment variable is set correctly.\n");
272                 exit (1);
273         }
274         position = 1;
275
276         map = fopen (argv[optind], "r");
277         if (map == NULL) {
278                 perror (argv[optind]);
279                 exit (1);
280         }
281
282         while (fgets (line, sizeof (line), map)) {
283                 for (a=line,b=troff_name; *a; a++,b++) {
284                         c = (*b = *a);
285                         if (c == ' ' || c == '\t')
286                                 break;
287                 }
288                 *b = '\0';
289                 while (*a && (*a == ' ' || *a == '\t'))
290                         ++a;
291                 for (b=font_name; *a; a++,b++)
292                         if ((*b = *a) == '\n')
293                                 break;
294                 *b = '\0';
295                 if (!MapFont (font_name, troff_name))
296                         exit (1);
297                 ++position;
298         }
299         exit (0);
300 }
301
302 /*
303 Local Variables:
304 c-indent-level: 8
305 c-continued-statement-offset: 8
306 c-brace-offset: -8
307 c-argdecl-indent: 8
308 c-label-offset: -8
309 c-tab-always-indent: nil
310 End:
311 */