Sync usage with man page.
[netbsd-mini2440.git] / gnu / dist / groff / src / utils / xtotroff / xtotroff.c
blob801b5a7602455d2a3be0c734a6b38396c8004de7
1 /* $NetBSD$ */
3 /*
4 * xtotroff
6 * convert X font metrics into troff font metrics
7 */
9 #ifdef HAVE_CONFIG_H
10 #include <config.h>
11 #endif
13 #include <X11/Xlib.h>
14 #include <stdio.h>
15 #include <ctype.h>
16 #include <unistd.h>
17 #include <stdlib.h>
18 #include <string.h>
19 #include <fcntl.h>
20 #include <limits.h>
22 #define __GETOPT_PREFIX groff_
23 #include <getopt.h>
25 #include "XFontName.h"
26 #include "DviChar.h"
28 #define charWidth(fi,c) \
29 ((fi)->per_char[(c) - (fi)->min_char_or_byte2].width)
30 #define charHeight(fi,c) \
31 ((fi)->per_char[(c) - (fi)->min_char_or_byte2].ascent)
32 #define charDepth(fi,c) \
33 ((fi)->per_char[(c) - (fi)->min_char_or_byte2].descent)
34 #define charLBearing(fi,c) \
35 ((fi)->per_char[(c) - (fi)->min_char_or_byte2].lbearing)
36 #define charRBearing(fi,c) \
37 ((fi)->per_char[(c) - (fi)->min_char_or_byte2].rbearing)
39 extern const char *Version_string;
40 static char *program_name;
42 Display *dpy;
43 unsigned resolution = 75;
44 unsigned point_size = 10;
46 int charExists(XFontStruct * fi, int c)
48 XCharStruct *p;
50 /* `c' is always >= 0 */
51 if ((unsigned int) c < fi->min_char_or_byte2
52 || (unsigned int) c > fi->max_char_or_byte2)
53 return 0;
54 p = fi->per_char + (c - fi->min_char_or_byte2);
55 return p->lbearing != 0 || p->rbearing != 0 || p->width != 0
56 || p->ascent != 0 || p->descent != 0 || p->attributes != 0;
59 /* Canonicalize the font name by replacing scalable parts by *s. */
61 static int CanonicalizeFontName(char *font_name, char *canon_font_name)
63 unsigned int attributes;
64 XFontName parsed;
66 if (!XParseFontName(font_name, &parsed, &attributes)) {
67 fprintf(stderr, "not a standard name: %s\n", font_name);
68 return 0;
71 attributes &= ~(FontNamePixelSize | FontNameAverageWidth
72 | FontNamePointSize
73 | FontNameResolutionX | FontNameResolutionY);
74 XFormatFontName(&parsed, attributes, canon_font_name);
75 return 1;
78 static int
79 FontNamesAmbiguous(const char *font_name, char **names, int count)
81 char name1[2048], name2[2048];
82 int i;
84 if (count == 1)
85 return 0;
87 for (i = 0; i < count; i++) {
88 if (!CanonicalizeFontName(names[i], i == 0 ? name1 : name2)) {
89 fprintf(stderr, "bad font name: %s\n", names[i]);
90 return 1;
92 if (i > 0 && strcmp(name1, name2) != 0) {
93 fprintf(stderr, "ambiguous font name: %s\n", font_name);
94 fprintf(stderr, " matches %s\n", names[0]);
95 fprintf(stderr, " and %s\n", names[i]);
96 return 1;
99 return 0;
102 static int MapFont(char *font_name, const char *troff_name)
104 XFontStruct *fi;
105 int count;
106 char **names;
107 FILE *out;
108 unsigned int c;
109 unsigned int attributes;
110 XFontName parsed;
111 int j, k;
112 DviCharNameMap *char_map;
113 char encoding[256];
114 char *s;
115 int wid;
116 char name_string[2048];
118 if (!XParseFontName(font_name, &parsed, &attributes)) {
119 fprintf(stderr, "not a standard name: %s\n", font_name);
120 return 0;
123 attributes &= ~(FontNamePixelSize | FontNameAverageWidth);
124 attributes |= FontNameResolutionX;
125 attributes |= FontNameResolutionY;
126 attributes |= FontNamePointSize;
127 parsed.ResolutionX = resolution;
128 parsed.ResolutionY = resolution;
129 parsed.PointSize = point_size * 10;
130 XFormatFontName(&parsed, attributes, name_string);
132 names = XListFonts(dpy, name_string, 100000, &count);
133 if (count < 1) {
134 fprintf(stderr, "bad font name: %s\n", font_name);
135 return 0;
138 if (FontNamesAmbiguous(font_name, names, count))
139 return 0;
141 XParseFontName(names[0], &parsed, &attributes);
142 sprintf(encoding, "%s-%s", parsed.CharSetRegistry,
143 parsed.CharSetEncoding);
144 for (s = encoding; *s; s++)
145 if (isupper(*s))
146 *s = tolower(*s);
147 char_map = DviFindMap(encoding);
148 if (!char_map) {
149 fprintf(stderr, "not a standard encoding: %s\n", encoding);
150 return 0;
153 fi = XLoadQueryFont(dpy, names[0]);
154 if (!fi) {
155 fprintf(stderr, "font does not exist: %s\n", names[0]);
156 return 0;
159 printf("%s -> %s\n", names[0], troff_name);
161 { /* Avoid race while opening file */
162 int fd;
163 (void) unlink(troff_name);
164 fd = open(troff_name, O_WRONLY | O_CREAT | O_EXCL, 0600);
165 out = fdopen(fd, "w");
168 if (!out) {
169 perror(troff_name);
170 return 0;
172 fprintf(out, "name %s\n", troff_name);
173 if (!strcmp(char_map->encoding, "adobe-fontspecific"))
174 fprintf(out, "special\n");
175 if (charExists(fi, ' ')) {
176 int w = charWidth(fi, ' ');
177 if (w > 0)
178 fprintf(out, "spacewidth %d\n", w);
180 fprintf(out, "charset\n");
181 for (c = fi->min_char_or_byte2; c <= fi->max_char_or_byte2; c++) {
182 const char *name = DviCharName(char_map, c, 0);
183 if (charExists(fi, c)) {
184 int param[5];
186 wid = charWidth(fi, c);
188 fprintf(out, "%s\t%d", name ? name : "---", wid);
189 param[0] = charHeight(fi, c);
190 param[1] = charDepth(fi, c);
191 param[2] = 0; /* charRBearing (fi, c) - wid */
192 param[3] = 0; /* charLBearing (fi, c) */
193 param[4] = 0; /* XXX */
194 for (j = 0; j < 5; j++)
195 if (param[j] < 0)
196 param[j] = 0;
197 for (j = 4; j >= 0; j--)
198 if (param[j] != 0)
199 break;
200 for (k = 0; k <= j; k++)
201 fprintf(out, ",%d", param[k]);
202 fprintf(out, "\t0\t0%o\n", c);
204 if (name) {
205 for (k = 1; DviCharName(char_map, c, k); k++) {
206 fprintf(out, "%s\t\"\n", DviCharName(char_map, c, k));
211 XUnloadFont(dpy, fi->fid);
212 fclose(out);
213 return 1;
216 static void usage(FILE *stream)
218 fprintf(stream,
219 "usage: %s [-r resolution] [-s pointsize] FontMap\n",
220 program_name);
223 int main(int argc, char **argv)
225 char troff_name[1024];
226 char font_name[1024];
227 char line[1024];
228 char *a, *b, c;
229 FILE *map;
230 int opt;
231 static const struct option long_options[] = {
232 { "help", no_argument, 0, CHAR_MAX + 1 },
233 { "version", no_argument, 0, 'v' },
234 { NULL, 0, 0, 0 }
237 program_name = argv[0];
239 while ((opt = getopt_long(argc, argv, "gr:s:v", long_options,
240 NULL)) != EOF) {
241 switch (opt) {
242 case 'g':
243 /* unused; just for compatibility */
244 break;
245 case 'r':
246 sscanf(optarg, "%u", &resolution);
247 break;
248 case 's':
249 sscanf(optarg, "%u", &point_size);
250 break;
251 case 'v':
252 printf("xtotroff (groff) version %s\n", Version_string);
253 exit(0);
254 break;
255 case CHAR_MAX + 1: /* --help */
256 usage(stdout);
257 exit(0);
258 break;
259 case '?':
260 usage(stderr);
261 exit(1);
262 break;
265 if (argc - optind != 1) {
266 usage(stderr);
267 exit(1);
270 dpy = XOpenDisplay(0);
271 if (!dpy) {
272 fprintf(stderr, "Can't connect to the X server.\n");
273 fprintf(stderr,
274 "Make sure the DISPLAY environment variable is set correctly.\n");
275 exit(1);
278 map = fopen(argv[optind], "r");
279 if (map == NULL) {
280 perror(argv[optind]);
281 exit(1);
284 while (fgets(line, sizeof(line), map)) {
285 for (a = line, b = troff_name; *a; a++, b++) {
286 c = (*b = *a);
287 if (c == ' ' || c == '\t')
288 break;
290 *b = '\0';
291 while (*a && (*a == ' ' || *a == '\t'))
292 ++a;
293 for (b = font_name; *a; a++, b++)
294 if ((*b = *a) == '\n')
295 break;
296 *b = '\0';
297 if (!MapFont(font_name, troff_name))
298 exit(1);
300 exit(0);