summaryrefslogtreecommitdiffstats
path: root/src/utils/addftinfo/addftinfo.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/utils/addftinfo/addftinfo.cpp')
-rw-r--r--src/utils/addftinfo/addftinfo.cpp237
1 files changed, 237 insertions, 0 deletions
diff --git a/src/utils/addftinfo/addftinfo.cpp b/src/utils/addftinfo/addftinfo.cpp
new file mode 100644
index 0000000..6f4facf
--- /dev/null
+++ b/src/utils/addftinfo/addftinfo.cpp
@@ -0,0 +1,237 @@
+/* Copyright (C) 1989-2020 Free Software Foundation, Inc.
+ Written by James Clark (jjc@jclark.com)
+
+This file is part of groff.
+
+groff is free software; you can redistribute it and/or modify it under
+the terms of the GNU General Public License as published by the Free
+Software Foundation, either version 3 of the License, or
+(at your option) any later version.
+
+groff is distributed in the hope that it will be useful, but WITHOUT ANY
+WARRANTY; without even the implied warranty of MERCHANTABILITY or
+FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program. If not, see <http://www.gnu.org/licenses/>. */
+
+#include "lib.h"
+
+#include <ctype.h>
+#include <stdlib.h>
+#include <errno.h>
+#include "errarg.h"
+#include "error.h"
+#include "stringclass.h"
+#include "cset.h"
+#include "guess.h"
+
+extern "C" const char *Version_string;
+
+static void usage(FILE *stream);
+static void usage();
+static void usage(const char *problem);
+static void version();
+static void convert_font(const font_params &, FILE *, FILE *);
+
+typedef int font_params::*param_t;
+
+static struct {
+ const char *name;
+ param_t par;
+} param_table[] = {
+ { "asc-height", &font_params::asc_height },
+ { "body-depth", &font_params::body_depth },
+ { "body-height", &font_params::body_height },
+ { "cap-height", &font_params::cap_height },
+ { "comma-depth", &font_params::comma_depth },
+ { "desc-depth", &font_params::desc_depth },
+ { "fig-height", &font_params::fig_height },
+ { "x-height", &font_params::x_height },
+};
+
+// These are all in thousandths of an em.
+// These values are correct for PostScript Times Roman.
+
+#define DEFAULT_X_HEIGHT 448
+#define DEFAULT_FIG_HEIGHT 676
+#define DEFAULT_ASC_HEIGHT 682
+#define DEFAULT_BODY_HEIGHT 676
+#define DEFAULT_CAP_HEIGHT 662
+#define DEFAULT_COMMA_DEPTH 143
+#define DEFAULT_DESC_DEPTH 217
+#define DEFAULT_BODY_DEPTH 177
+
+int main(int argc, char **argv)
+{
+ program_name = argv[0];
+ int i;
+ for (i = 1; i < argc; i++) {
+ if (!strcmp(argv[i], "-v") || !strcmp(argv[i],"--version"))
+ version();
+ if (!strcmp(argv[i],"--help")) {
+ usage(stdout);
+ exit(0);
+ }
+ }
+ if (argc < 4)
+ usage("insufficient arguments");
+ /* The next couple of usage() calls cannot provide a meaningful
+ diagnostic because we don't know whether sscanf() failed on a
+ required parameter or an option. A refactor could fix this. */
+ int resolution;
+ if (sscanf(argv[argc-3], "%d", &resolution) != 1)
+ usage();
+ if (resolution <= 0)
+ fatal("resolution must be positive");
+ int unitwidth;
+ if (sscanf(argv[argc-2], "%d", &unitwidth) != 1)
+ usage();
+ if (unitwidth <= 0)
+ fatal("unit width must be positive");
+ font_params param;
+ const char *font = argv[argc-1];
+ param.italic = (font[0] != '\0' && strchr(font, '\0')[-1] == 'I');
+ param.em = (resolution*unitwidth)/72;
+ param.x_height = DEFAULT_X_HEIGHT;
+ param.fig_height = DEFAULT_FIG_HEIGHT;
+ param.asc_height = DEFAULT_ASC_HEIGHT;
+ param.body_height = DEFAULT_BODY_HEIGHT;
+ param.cap_height = DEFAULT_CAP_HEIGHT;
+ param.comma_depth = DEFAULT_COMMA_DEPTH;
+ param.desc_depth = DEFAULT_DESC_DEPTH;
+ param.body_depth = DEFAULT_BODY_DEPTH;
+ for (i = 1; i < argc && argv[i][0] == '-'; i++) {
+ if (argv[i][1] == '-' && argv[i][2] == '\0') {
+ i++;
+ break;
+ }
+ if (i + 1 >= argc)
+ usage("option requires argument");
+ size_t j;
+ for (j = 0;; j++) {
+ if (j >= sizeof(param_table)/sizeof(param_table[0]))
+ fatal("parameter '%1' not recognized", argv[i] + 1);
+ if (strcmp(param_table[j].name, argv[i] + 1) == 0)
+ break;
+ }
+ if (sscanf(argv[i+1], "%d", &(param.*(param_table[j].par))) != 1)
+ fatal("invalid option argument '%1'", argv[i+1]);
+ i++;
+ }
+ if (argc - i != 3)
+ usage("insufficient arguments");
+ errno = 0;
+ FILE *infp = fopen(font, "r");
+ if (infp == 0)
+ fatal("can't open '%1': %2", font, strerror(errno));
+ convert_font(param, infp, stdout);
+ return 0;
+}
+
+static void usage(FILE *stream)
+{
+ fprintf(stream, "usage: %s", program_name);
+ size_t len = sizeof(param_table)/sizeof(param_table[0]);
+ for (size_t i = 0; i < len; i++)
+ fprintf(stream, " [-%s n]", param_table[i].name);
+ fputs(" resolution unit-width font\n", stream);
+ fprintf(stream, "usage: %s {-v | --version}\n"
+ "usage: %s --help\n", program_name, program_name);
+}
+
+static void usage()
+{
+ usage(stderr);
+ exit(1);
+}
+
+static void usage(const char *problem)
+{
+ error("%1", problem);
+ usage();
+}
+
+static void version()
+{
+ printf("GNU addftinfo (groff) version %s\n", Version_string);
+ exit(0);
+}
+
+static int get_line(FILE *fp, string *p)
+{
+ int c;
+ p->clear();
+ while ((c = getc(fp)) != EOF) {
+ *p += char(c);
+ if (c == '\n')
+ break;
+ }
+ return p->length() > 0;
+}
+
+static void convert_font(const font_params &param, FILE *infp,
+ FILE *outfp)
+{
+ string s;
+ while (get_line(infp, &s)) {
+ put_string(s, outfp);
+ if (s.length() >= 8
+ && strncmp(&s[0], "charset", 7))
+ break;
+ }
+ while (get_line(infp, &s)) {
+ s += '\0';
+ string name;
+ const char *p = s.contents();
+ while (csspace(*p))
+ p++;
+ while (*p != '\0' && !csspace(*p))
+ name += *p++;
+ while (csspace(*p))
+ p++;
+ for (const char *q = s.contents(); q < p; q++)
+ putc(*q, outfp);
+ char *next;
+ char_metric metric;
+ metric.width = (int)strtol(p, &next, 10);
+ if (next != p) {
+ printf("%d", metric.width);
+ p = next;
+ metric.type = (int)strtol(p, &next, 10);
+ if (next != p) {
+ name += '\0';
+ guess(name.contents(), param, &metric);
+ if (metric.sk == 0) {
+ if (metric.left_ic == 0) {
+ if (metric.ic == 0) {
+ if (metric.depth == 0) {
+ if (metric.height != 0)
+ printf(",%d", metric.height);
+ }
+ else
+ printf(",%d,%d", metric.height, metric.depth);
+ }
+ else
+ printf(",%d,%d,%d", metric.height, metric.depth,
+ metric.ic);
+ }
+ else
+ printf(",%d,%d,%d,%d", metric.height, metric.depth,
+ metric.ic, metric.left_ic);
+ }
+ else
+ printf(",%d,%d,%d,%d,%d", metric.height, metric.depth,
+ metric.ic, metric.left_ic, metric.sk);
+ }
+ }
+ fputs(p, outfp);
+ }
+}
+
+// Local Variables:
+// fill-column: 72
+// mode: C++
+// End:
+// vim: set cindent noexpandtab shiftwidth=2 textwidth=72: