freebsd-skq/contrib/groff/xditview/xtotroff.c
2000-01-12 09:51:43 +00:00

304 lines
6.5 KiB
C

/*
* xtotroff
*
* convert X font metrics into troff font metrics
*/
#include <X11/Xlib.h>
#include <stdio.h>
#include <ctype.h>
#include "XFontName.h"
#include "DviChar.h"
#ifdef X_NOT_STDC_ENV
char *malloc();
#else
#include <stdlib.h>
#endif
#define charWidth(fi,c) ((fi)->per_char[(c) - (fi)->min_char_or_byte2].width)
#define charHeight(fi,c) ((fi)->per_char[(c) - (fi)->min_char_or_byte2].ascent)
#define charDepth(fi,c) ((fi)->per_char[(c) - (fi)->min_char_or_byte2].descent)
#define charLBearing(fi,c) ((fi)->per_char[(c) - (fi)->min_char_or_byte2].lbearing)
#define charRBearing(fi,c) ((fi)->per_char[(c) - (fi)->min_char_or_byte2].rbearing)
Display *dpy;
int groff_flag = 0;
unsigned resolution = 75;
unsigned point_size = 10;
int charExists (fi, c)
XFontStruct *fi;
int c;
{
XCharStruct *p;
if (c < fi->min_char_or_byte2 || c > fi->max_char_or_byte2)
return 0;
p = fi->per_char + (c - fi->min_char_or_byte2);
return (p->lbearing != 0 || p->rbearing != 0 || p->width != 0
|| p->ascent != 0 || p->descent != 0 || p->attributes != 0);
}
/* Canonicalize the font name by replacing scalable parts by *s. */
CanonicalizeFontName (font_name, canon_font_name)
char *font_name, *canon_font_name;
{
unsigned int attributes;
XFontName parsed;
if (!XParseFontName(font_name, &parsed, &attributes)) {
fprintf (stderr, "not a standard name: %s\n", font_name);
return 0;
}
attributes &= ~(FontNamePixelSize|FontNameAverageWidth
|FontNamePointSize
|FontNameResolutionX|FontNameResolutionY);
XFormatFontName(&parsed, attributes, canon_font_name);
return 1;
}
int FontNamesAmbiguous(font_name, names, count)
char *font_name;
char **names;
int count;
{
char name1[2048], name2[2048];
int i;
if (count == 1)
return 0;
for (i = 0; i < count; i++) {
if (!CanonicalizeFontName(names[i], i == 0 ? name1 : name2)) {
fprintf(stderr, "bad font name: %s\n", names[i]);
return 1;
}
if (i > 0 && strcmp(name1, name2) != 0) {
fprintf(stderr, "ambiguous font name: %s\n", font_name);
fprintf(stderr, " matches %s\n", names[0]);
fprintf(stderr, " and %s\n", names[i]);
return 1;
}
}
return 0;
}
MapFont (font_name, troff_name)
char *font_name;
char *troff_name;
{
XFontStruct *fi;
int count;
char **names;
FILE *out;
int c;
unsigned int attributes;
XFontName parsed;
int j, k;
DviCharNameMap *char_map;
char encoding[256];
char *s;
int wid;
char name_string[2048];
if (!XParseFontName(font_name, &parsed, &attributes)) {
fprintf (stderr, "not a standard name: %s\n", font_name);
return 0;
}
attributes &= ~(FontNamePixelSize|FontNameAverageWidth);
attributes |= FontNameResolutionX;
attributes |= FontNameResolutionY;
attributes |= FontNamePointSize;
parsed.ResolutionX = resolution;
parsed.ResolutionY = resolution;
parsed.PointSize = point_size*10;
XFormatFontName(&parsed, attributes, name_string);
names = XListFonts (dpy, name_string, 100000, &count);
if (count < 1) {
fprintf (stderr, "bad font name: %s\n", font_name);
return 0;
}
if (FontNamesAmbiguous(font_name, names, count))
return 0;
XParseFontName(names[0], &parsed, &attributes);
sprintf (encoding, "%s-%s", parsed.CharSetRegistry,
parsed.CharSetEncoding);
for (s = encoding; *s; s++)
if (isupper (*s))
*s = tolower (*s);
char_map = DviFindMap (encoding);
if (!char_map) {
fprintf (stderr, "not a standard encoding: %s\n", encoding);
return 0;
}
fi = XLoadQueryFont (dpy, names[0]);
if (!fi) {
fprintf (stderr, "font does not exist: %s\n", names[0]);
return 0;
}
printf ("%s -> %s\n", names[0], troff_name);
(void) unlink (troff_name);
out = fopen (troff_name, "w");
if (!out) {
perror (troff_name);
return 0;
}
fprintf (out, "name %s\n", troff_name);
if (!strcmp (char_map->encoding, "adobe-fontspecific"))
fprintf (out, "special\n");
if (charExists (fi, ' ')) {
int w = charWidth (fi, ' ');
if (w > 0)
fprintf (out, "spacewidth %d\n", w);
}
fprintf (out, "charset\n");
for (c = fi->min_char_or_byte2; c <= fi->max_char_or_byte2; c++) {
char *name = DviCharName (char_map,c,0);
if (charExists (fi, c) && (groff_flag || name)) {
wid = charWidth (fi, c);
fprintf (out, "%s\t%d",
name ? name : "---",
wid);
if (groff_flag) {
int param[5];
param[0] = charHeight (fi, c);
param[1] = charDepth (fi, c);
param[2] = 0 /* charRBearing (fi, c) - wid */;
param[3] = 0 /* charLBearing (fi, c) */;
param[4] = 0; /* XXX */
for (j = 0; j < 5; j++)
if (param[j] < 0)
param[j] = 0;
for (j = 4; j >= 0; j--)
if (param[j] != 0)
break;
for (k = 0; k <= j; k++)
fprintf (out, ",%d", param[k]);
}
fprintf (out, "\t0\t0%o\n", c);
if (name) {
for (k = 1; DviCharName(char_map,c,k); k++) {
fprintf (out, "%s\t\"\n",
DviCharName (char_map,c,k));
}
}
}
}
XUnloadFont (dpy, fi->fid);
fclose (out);
return 1;
}
static usage(prog)
char *prog;
{
fprintf (stderr,
"usage: %s [-g] [-r resolution] [-s pointsize] FontMap\n",
prog);
exit (1);
}
/* For use by DviChar.c */
char *xmalloc(n)
int n;
{
char *p = malloc(n);
if (!p) {
fprintf(stderr, "Out of memory\n");
exit(1);
}
return p;
}
main (argc, argv)
char **argv;
{
char troff_name[1024];
char font_name[1024];
char line[1024];
char *a, *b, c;
int position;
FILE *map;
int opt;
extern int optind;
extern char *optarg;
while ((opt = getopt(argc, argv, "gr:s:")) != EOF) {
switch (opt) {
case 'g':
groff_flag = 1;
break;
case 'r':
sscanf(optarg, "%u", &resolution);
break;
case 's':
sscanf(optarg, "%u", &point_size);
break;
default:
usage(argv[0]);
}
}
if (argc - optind != 1)
usage(argv[0]);
dpy = XOpenDisplay (0);
if (!dpy) {
fprintf (stderr, "Can't connect to the X server.\n");
fprintf (stderr, "Make sure the DISPLAY environment variable is set correctly.\n");
exit (1);
}
position = 1;
map = fopen (argv[optind], "r");
if (map == NULL) {
perror (argv[optind]);
exit (1);
}
while (fgets (line, sizeof (line), map)) {
for (a=line,b=troff_name; *a; a++,b++) {
c = (*b = *a);
if (c == ' ' || c == '\t')
break;
}
*b = '\0';
while (*a && (*a == ' ' || *a == '\t'))
++a;
for (b=font_name; *a; a++,b++)
if ((*b = *a) == '\n')
break;
*b = '\0';
if (!MapFont (font_name, troff_name))
exit (1);
++position;
}
exit (0);
}
/*
Local Variables:
c-indent-level: 8
c-continued-statement-offset: 8
c-brace-offset: -8
c-argdecl-indent: 8
c-label-offset: -8
c-tab-always-indent: nil
End:
*/