diff options
author | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-15 19:44:05 +0000 |
---|---|---|
committer | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-15 19:44:05 +0000 |
commit | d318611dd6f23fcfedd50e9b9e24620b102ba96a (patch) | |
tree | 8b9eef82ca40fdd5a8deeabf07572074c236095d /src/utils/addftinfo/addftinfo.cpp | |
parent | Initial commit. (diff) | |
download | groff-f22bf21391d2b916c7303c565592ae6e99efbb58.tar.xz groff-f22bf21391d2b916c7303c565592ae6e99efbb58.zip |
Adding upstream version 1.23.0.upstream/1.23.0upstream
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'src/utils/addftinfo/addftinfo.cpp')
-rw-r--r-- | src/utils/addftinfo/addftinfo.cpp | 237 |
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 ¶m, 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: |