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