1/*	$NetBSD$	*/
2
3// -*- C++ -*-
4/* Copyright (C) 1989-1992, 2000, 2001 Free Software Foundation, Inc.
5     Written by James Clark (jjc@jclark.com)
6
7This file is part of groff.
8
9groff is free software; you can redistribute it and/or modify it under
10the terms of the GNU General Public License as published by the Free
11Software Foundation; either version 2, or (at your option) any later
12version.
13
14groff is distributed in the hope that it will be useful, but WITHOUT ANY
15WARRANTY; without even the implied warranty of MERCHANTABILITY or
16FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
17for more details.
18
19You should have received a copy of the GNU General Public License along
20with groff; see the file COPYING.  If not, write to the Free Software
21Foundation, 51 Franklin St - Fifth Floor, Boston, MA 02110-1301, USA. */
22
23#include "lib.h"
24
25#include <ctype.h>
26#include <assert.h>
27#include <stdlib.h>
28#include <errno.h>
29#include "errarg.h"
30#include "error.h"
31#include "stringclass.h"
32#include "cset.h"
33#include "guess.h"
34
35extern "C" const char *Version_string;
36
37static void usage(FILE *stream);
38static void usage();
39static void version();
40static void convert_font(const font_params &, FILE *, FILE *);
41
42typedef int font_params::*param_t;
43
44static struct {
45  const char *name;
46  param_t par;
47} param_table[] = {
48  { "x-height", &font_params::x_height },
49  { "fig-height", &font_params::fig_height },
50  { "asc-height", &font_params::asc_height },
51  { "body-height", &font_params::body_height },
52  { "cap-height", &font_params::cap_height },
53  { "comma-depth", &font_params::comma_depth },
54  { "desc-depth", &font_params::desc_depth },
55  { "body-depth", &font_params::body_depth },
56};
57
58// These are all in thousandths of an em.
59// These values are correct for PostScript Times Roman.
60
61#define DEFAULT_X_HEIGHT 448
62#define DEFAULT_FIG_HEIGHT 676
63#define DEFAULT_ASC_HEIGHT 682
64#define DEFAULT_BODY_HEIGHT 676
65#define DEFAULT_CAP_HEIGHT 662
66#define DEFAULT_COMMA_DEPTH 143
67#define DEFAULT_DESC_DEPTH 217
68#define DEFAULT_BODY_DEPTH 177
69
70int main(int argc, char **argv)
71{
72  program_name = argv[0];
73  int i;
74  for (i = 1; i < argc; i++) {
75    if (!strcmp(argv[i], "-v") || !strcmp(argv[i],"--version"))
76      version();
77    if (!strcmp(argv[i],"--help")) {
78      usage(stdout);
79      exit(0);
80    }
81  }
82  if (argc < 4)
83    usage();
84  int resolution;
85  if (sscanf(argv[argc-3], "%d", &resolution) != 1)
86    usage();
87  if (resolution <= 0)
88    fatal("resolution must be > 0");
89  int unitwidth;
90  if (sscanf(argv[argc-2], "%d", &unitwidth) != 1)
91    usage();
92  if (unitwidth <= 0)
93    fatal("unitwidth must be > 0");
94  font_params param;
95  const char *font = argv[argc-1];
96  param.italic = (font[0] != '\0' && strchr(font, '\0')[-1] == 'I');
97  param.em = (resolution*unitwidth)/72;
98  param.x_height = DEFAULT_X_HEIGHT;
99  param.fig_height = DEFAULT_FIG_HEIGHT;
100  param.asc_height = DEFAULT_ASC_HEIGHT;
101  param.body_height = DEFAULT_BODY_HEIGHT;
102  param.cap_height = DEFAULT_CAP_HEIGHT;
103  param.comma_depth = DEFAULT_COMMA_DEPTH;
104  param.desc_depth = DEFAULT_DESC_DEPTH;
105  param.body_depth = DEFAULT_BODY_DEPTH;
106  for (i = 1; i < argc && argv[i][0] == '-'; i++) {
107    if (argv[i][1] == '-' && argv[i][2] == '\0') {
108      i++;
109      break;
110    }
111    if (i + 1 >= argc)
112      usage();
113    size_t j;
114    for (j = 0;; j++) {
115      if (j >= sizeof(param_table)/sizeof(param_table[0]))
116	fatal("parameter `%1' not recognized", argv[i] + 1);
117      if (strcmp(param_table[j].name, argv[i] + 1) == 0)
118	break;
119    }
120    if (sscanf(argv[i+1], "%d", &(param.*(param_table[j].par))) != 1)
121      fatal("invalid argument `%1'", argv[i+1]);
122    i++;
123  }
124  if (argc - i != 3)
125    usage();
126  errno = 0;
127  FILE *infp = fopen(font, "r");
128  if (infp == 0)
129    fatal("can't open `%1': %2", font, strerror(errno));
130  convert_font(param, infp, stdout);
131  return 0;
132}
133
134static void usage(FILE *stream)
135{
136  fprintf(stream, "usage: %s [-v] [-param value] ... "
137		  "resolution unitwidth font\n",
138	  program_name);
139}
140static void usage()
141{
142  usage(stderr);
143  exit(1);
144}
145
146static void version()
147{
148  printf("GNU addftinfo (groff) version %s\n", Version_string);
149  exit(0);
150}
151
152static int get_line(FILE *fp, string *p)
153{
154  int c;
155  p->clear();
156  while ((c = getc(fp)) != EOF) {
157    *p += char(c);
158    if (c == '\n')
159      break;
160  }
161  return p->length() > 0;
162}
163
164static void convert_font(const font_params &param, FILE *infp, FILE *outfp)
165{
166  string s;
167  while (get_line(infp, &s)) {
168    put_string(s, outfp);
169    if (s.length() >= 8
170	&& strncmp(&s[0], "charset", 7))
171      break;
172  }
173  while (get_line(infp, &s)) {
174    s += '\0';
175    string name;
176    const char *p = s.contents();
177    while (csspace(*p))
178      p++;
179    while (*p != '\0' && !csspace(*p))
180      name += *p++;
181    while (csspace(*p))
182      p++;
183    for (const char *q = s.contents(); q < p; q++)
184      putc(*q, outfp);
185    char *next;
186    char_metric metric;
187    metric.width = (int)strtol(p, &next, 10);
188    if (next != p) {
189      printf("%d", metric.width);
190      p = next;
191      metric.type = (int)strtol(p, &next, 10);
192      if (next != p) {
193	name += '\0';
194	guess(name.contents(), param, &metric);
195	if (metric.sk == 0) {
196	  if (metric.left_ic == 0) {
197	    if (metric.ic == 0) {
198	      if (metric.depth == 0) {
199		if (metric.height != 0)
200		  printf(",%d", metric.height);
201	      }
202	      else
203		printf(",%d,%d", metric.height, metric.depth);
204	    }
205	    else
206	      printf(",%d,%d,%d", metric.height, metric.depth, metric.ic);
207	  }
208	  else
209	    printf(",%d,%d,%d,%d", metric.height, metric.depth, metric.ic,
210		   metric.left_ic);
211	}
212	else
213	  printf(",%d,%d,%d,%d,%d", metric.height, metric.depth, metric.ic,
214		 metric.left_ic, metric.sk);
215      }
216    }
217    fputs(p, outfp);
218  }
219}
220
221