summaryrefslogtreecommitdiff
path: root/fontconvert/main.c
diff options
context:
space:
mode:
Diffstat (limited to 'fontconvert/main.c')
-rw-r--r--fontconvert/main.c747
1 files changed, 747 insertions, 0 deletions
diff --git a/fontconvert/main.c b/fontconvert/main.c
new file mode 100644
index 0000000..a50b311
--- /dev/null
+++ b/fontconvert/main.c
@@ -0,0 +1,747 @@
+/* fontconvert -- various operations on a bitmap font.
+
+Copyright (C) 1992 Free Software Foundation, Inc.
+
+This program 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 2, or (at your option)
+any later version.
+
+This program 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, write to the Free Software
+Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
+
+#include "config.h"
+
+#include "charspec.h"
+#include "cmdline.h"
+#include "encoding.h"
+#include "font.h"
+#include "libfile.h"
+#include "list.h"
+#include "report.h"
+
+#include "filter.h"
+#include "output-epsf.h"
+#include "output-gf.h"
+#include "output-tfm.h"
+#include "random.h"
+
+
+/* How much to adjust the baseline of output characters by. We rely on
+ this being initialized to all zeros by C. (-baseline-adjust) */
+int baseline_adjust[MAX_CHARCODE + 1];
+
+/* If `column_split[N]' is non-NULL, we break character N into new
+ characters at each of the columns specified. We depend on this being
+ initialized to all zeros. (-column-split) */
+int *column_split[MAX_CHARCODE + 1];
+
+/* The names of fonts to be concatenated onto the main font in the
+ output. (-concat) */
+list_type fontname_list;
+
+/* The resolution of the font we will read, in pixels per inch. We
+ don't deal with nonsquare pixels. (-dpi) */
+string dpi = "300";
+
+/* The design size which will affect both the GF and TFM output, unless
+ the tfm-header `designsize' option overrides it. (-designsize)
+ `design_size_ratio' is the ratio of the input design size to the
+ output design size. */
+real design_size = 0.0;
+static real design_size_ratio;
+
+/* The name of the encoding file specified by the user, and the
+ structure we parse it into. (-encoding) */
+static encoding_info_type *encoding_info = NULL;
+
+/* If `omit[n]' is true for an element N, we throw away that character
+ in that output. (-omit) */
+static boolean omit[MAX_CHARCODE + 1];
+
+/* An explicitly specified output filename. (-output-file) */
+const_string output_name = NULL;
+
+/* Says which characters we should process. This is independent of the
+ ordering in the font file. (-range) */
+int starting_char = 0;
+int ending_char = MAX_CHARCODE;
+
+/* The variable `translate' maps character codes in the input font to
+ character codes in the output; by default, maps everything to
+ themselves. (-remap) */
+charcode_type translate[MAX_CHARCODE + 1];
+
+/* Says whether to output an EPS file for each character. (-epsf) */
+boolean wants_epsf = false;
+
+/* Says whether to output a GF file. (-gf) */
+boolean wants_gf = false;
+
+/* Says whether to output the font as plain text. (-text) */
+boolean wants_text = false;
+
+/* Says whether to output a TFM file. (-tfm) */
+boolean wants_tfm = false;
+
+
+
+static void append_concat_list (list_type *, string);
+static bitmap_type column_extract (bitmap_type, unsigned, unsigned);
+static void do_char (char_info_type);
+static void do_split_char (char_info_type, int[]);
+static string read_command_line (int, string []);
+static void scan_baseline_adjust (string);
+static void scan_column_split (string);
+static void scan_omit_list (string);
+static void scan_remap_list (string);
+
+/* Fontconvert provides a grabbag of operations: almost every
+ manipulation on bitmap fonts we found useful we threw here. */
+
+int
+main (int argc, string argv[])
+{
+ int code;
+ bitmap_font_type f;
+ string *first_element;
+ string font_name;
+ unsigned this_font;
+ unsigned char_count = 0;
+
+ /* Use Kpathsea path searching. */
+ kpse_set_progname (argv[0]);
+
+ /* Initialize the character code translation array before parsing the
+ command line, since we probably will not be told to remap every
+ character. */
+ for (code = 0; code <= MAX_CHARCODE; code++)
+ translate[code] = code;
+
+ /* Initialize the list of fonts to do to have one empty element at the
+ beginning, which we will fill in with the main font name. */
+ fontname_list = list_init ();
+ first_element = LIST_TAPPEND (&fontname_list, string);
+
+ /* Read all the arguments. */
+ font_name = read_command_line (argc, argv);
+
+ /* Put the main font name in the list. */
+ *first_element = font_name;
+
+ /* If no output name was specified on the command line, use the root
+ part of the input name. We've already removed the suffix in
+ `read_command_line'. */
+ if (output_name == NULL)
+ output_name = basename (font_name);
+
+ if (wants_gf && wants_tfm && find_suffix (output_name) != NULL)
+ FATAL ("The GF and TFM output files' suffixes can't be the same");
+
+ /* Open the main font specially, since we need to know some basic
+ information for most of the output formats. We don't need to close
+ it again, as opening a font twice does no harm. */
+ f = get_bitmap_font (font_name, atou (dpi));
+
+ if (wants_epsf)
+ epsf_start_output (output_name);
+ if (wants_gf)
+ gf_start_output (font_name, output_name, dpi,
+ BITMAP_FONT_COMMENT (f));
+ if (wants_tfm)
+ tfm_start_output (font_name, output_name, design_size,
+ BITMAP_FONT_DESIGN_SIZE (f));
+
+
+ /* Have to do this after `tfm_start_output', as it needs to know if
+ design_size is set or not. */
+ if (design_size == 0.0)
+ design_size = BITMAP_FONT_DESIGN_SIZE (f);
+
+ design_size_ratio = BITMAP_FONT_DESIGN_SIZE (f) / design_size;
+
+ /* Go through each input font. */
+ for (this_font = 0; this_font < LIST_SIZE (fontname_list); this_font++)
+ {
+ string font_name = *(string *) LIST_ELT (fontname_list, this_font);
+ f = get_bitmap_font (font_name, atou (dpi));
+
+ if (wants_tfm)
+ tfm_start_font (font_name);
+
+ REPORT1 ("(%s", BITMAP_FONT_FILENAME (f));
+
+ /* The main loop: convert each character. */
+ for (code = starting_char; code <= ending_char; code++)
+ {
+ char_info_type *c = get_char (font_name, code);
+
+ if (c == NULL) continue;
+
+ REPORT2 ("%c[%u", ++char_count % 8 ? ' ' : '\n', code);
+
+ if (omit[code])
+ REPORT (" omit");
+ else
+ {
+ /* If this character isn't supposed to split, just output it.
+ Otherwise, output each of the pieces after splitting. */
+ if (column_split[code] == NULL)
+ do_char (*c);
+ else
+ do_split_char (*c, column_split[code]);
+ }
+
+ REPORT ("]");
+ }
+
+ close_font (font_name);
+ REPORT (")\n");
+ }
+
+ if (wants_epsf)
+ epsf_finish_output ();
+
+ /* We must finish the TFM output before GF, because `gf_finish_output'
+ might want to open a TFM file -- and we can only have one TFM file
+ open at a time. (Because we haven't rewritten the TFM library.) */
+ if (wants_tfm)
+ tfm_finish_output ();
+
+ if (wants_gf)
+ gf_finish_output (design_size, atof (dpi));
+
+ return 0;
+}
+
+/* Output the character in whatever forms have been requested. */
+
+static void
+do_char (char_info_type c)
+{
+ static boolean char_done_p[MAX_CHARCODE + 1];
+
+ charcode_type original_code = CHARCODE (c);
+
+ /* Do the character code translation. */
+ charcode_type code = CHARCODE (c) = translate[original_code];
+
+ if (char_done_p[code])
+ {
+ WARNING1 ("Character %d already output", CHARCODE (c));
+ return;
+ }
+
+ char_done_p[code] = true;
+
+ if (filter_passes > 0)
+ filter_bitmap (CHAR_BITMAP (c));
+
+ if (random_max > 0.0)
+ {
+ bounding_box_type adjust_bb;
+ randomize_bitmap (&CHAR_BITMAP (c), &adjust_bb);
+ CHAR_MIN_ROW (c) -= MIN_ROW (adjust_bb);
+ CHAR_MAX_ROW (c) += MAX_ROW (adjust_bb);
+ CHAR_MIN_COL (c) -= MIN_COL (adjust_bb);
+ CHAR_MAX_COL (c) += MAX_COL (adjust_bb);
+ }
+
+ /* If the `baseline_adjust' value is positive, the baseline should
+ move up, i.e., we subtract from the height and add to the depth.
+ But since the depth is represented as the minimum row, which can be
+ negative, we must subtract from it to make it ``larger''. */
+ CHAR_MIN_ROW (c) -= baseline_adjust[code];
+ CHAR_MAX_ROW (c) -= baseline_adjust[code];
+
+ /* Text output is already implemented in the library. */
+ if (wants_text)
+ {
+ puts ("\f");
+ print_char (stdout, c);
+ }
+
+ if (wants_epsf)
+ epsf_output_char (c);
+
+ if (wants_gf)
+ gf_output_char (c, design_size_ratio);
+
+ if (wants_tfm)
+ tfm_output_char (c, atof (dpi));
+
+ if (original_code != code)
+ REPORT1 ("->%u", code);
+
+ /* Free the space here, instead of in the caller, since we may
+ change the bitmap. */
+ free_bitmap (&CHAR_BITMAP (c));
+}
+
+
+/* Output the character C in pieces, the division points being the
+ columns in SPLIT. */
+
+static void
+do_split_char (char_info_type c, int split[])
+{
+ unsigned last_col = 0;
+ unsigned n_split = 0;
+
+ REPORT (" (");
+
+ /* We exit the loop after splitting the last character. */
+ while (true)
+ {
+ int diff;
+ char_info_type split_char = c;
+ int this_col = *split++;
+ unsigned split_col = this_col != -1
+ ? this_col : BITMAP_WIDTH (CHAR_BITMAP (c));
+
+ /* Change the character code of this piece. */
+ CHARCODE (split_char) += n_split;
+
+ REPORT1 ("%u", CHARCODE (split_char));
+
+ /* Take the chunk from the big bitmap. */
+ CHAR_BITMAP (split_char)
+ = column_extract (CHAR_BITMAP (c), last_col, split_col);
+
+ /* Move the right column over. */
+ diff = BITMAP_WIDTH (CHAR_BITMAP (c))
+ - BITMAP_WIDTH (CHAR_BITMAP (split_char));
+ CHAR_MAX_COL (split_char) -= diff;
+ CHAR_SET_WIDTH (split_char) -= diff;
+
+ /* Output it. */
+ do_char (split_char);
+
+ /* Exit the loop if we just output the last piece. */
+ if (this_col == -1)
+ break;
+
+ n_split++;
+ last_col = this_col;
+ REPORT (",");
+ }
+
+ REPORT (")");
+ free_bitmap (&CHAR_BITMAP (c));
+}
+
+/* Return the part of the bitmap SOURCE that lies between the columns
+ START and FINISH - 1, inclusive. */
+
+static bitmap_type
+column_extract (bitmap_type source, unsigned start, unsigned finish)
+{
+ unsigned this_row;
+ dimensions_type d = { BITMAP_HEIGHT (source), finish - start };
+ bitmap_type answer = new_bitmap (d);
+
+ /* Move to the given starting column. */
+ BITMAP_BITS (source) += start;
+
+ for (this_row = 0; this_row < BITMAP_HEIGHT (source); this_row++)
+ {
+ one_byte *answer_row = BITMAP_ROW (answer, this_row);
+
+ memcpy (answer_row, BITMAP_BITS (source), BITMAP_WIDTH (answer));
+ BITMAP_BITS (source) += BITMAP_WIDTH (source);
+ }
+
+ return answer;
+}
+
+/* Reading the options. */
+
+/* This is defined in version.c. */
+extern string version_string;
+
+#define USAGE "Options:
+<font_name> should be a filename, possibly with a resolution, e.g.,
+ `cmr10' or `cmr10.300'.\n" \
+ GETOPT_USAGE \
+"baseline-adjust <char1>:<integer1>,<char2>:<integer2>,...: move the baseline
+ of each <char> by the corresponding <integer>. A positive number
+ moves the baseline up, a negative one down.
+column-split <char>@<column1>,...,<columnN>: split the character with
+ code <char> (before remapping) before each of the <column>s, producing n
+ new characters, with codes <char>, <char> + 1, ..., <char> + n, whose
+ bitmaps go from 0 to <column1> - 1 (inclusive), then <column1> to
+ <column2> - 1, ..., from <columnN> to the bitmap width.
+ Give the <column>s in bitmap coordinates, i.e., starting at zero.
+ To split more than one character, give this option for each.
+concat <font_name>,<font_name>,...: concatenate the main input font with
+ the given <font_name>s; if a character code exists in more than one
+ font, it's the first occurrence that counts.
+designsize <real>: use this as the design size for both the GF and TFM
+ output files, if any, unless overridden by `designsize' in the
+ `tfm-header' option.
+dpi <unsigned>: use a resolution of <unsigned>; default is 300.
+encoding <filename>: read encoding information for the character specs
+ from `<filename>.enc'; there is no default. Must come before any
+ options which use character specs.
+epsf: output each character as an Encapsulated PostScript file named
+ <font_name>-<code>.eps, where <code> is the character code in decimal.
+filter-passes <unsigned>: do the filtering this many times on each
+ character; default is 0.
+filter-size <unsigned>: half the size of the filter cell, i.e., a side
+ is this number * 2 + 1; default is 1.
+filter-threshold <real>: if the average of the pixels in the filter cell
+ is greater than this, change the pixel; default is .5.
+fontdimens <fontdimen>:<real>,<fontdimen>:<real>,...: assign each <real>
+ to the corresponding <fontdimen> when outputting a TFM file. A
+ <fontdimen> can be either one of the standard names (in either upper
+ or lowercase), or a number between 1 and 30. Each <real> is taken to
+ be in points (except in the case of the <fontdimen> `slant' (parameter
+ 1), which is a dimensionless number).
+gf: write a GF file to `<font_name>.<dpi>gf'. If this would overwrite the
+ input file, write to `x<font_name>.<dpi>gf' instead.
+help: print this message.
+omit <char1>,<char2>,...: omit the characters with the given codes or names
+ (before remapping) from the output.
+output-file <filename>: use <filename> as the output filename if it has
+ a suffix, and as the base of the output files if it doesn't. It
+ cannot have a suffix if using the `epsf' option, or both the `gf' and the
+ `tfm' option. Default is the base part of the input font name.
+random <real>: move each pixel a (uniformly) random distance between
+ -<real> and <real> in both x and y; default is 0.
+random-threshold <real>: if randomizing, do not move pixels with
+ probability <real>; default is 0.2.
+range <char1>-<char2>: only process characters between <char1> and
+ <char2> in the input font, inclusive.
+remap <char1>:<char2>,<char1>:<char2>,...: for each pair, make the input
+ character with code <char1> have code <char2> in the output.
+text: output the font to stdout as plain text, using `*'s and ` 's.
+tfm: write a TFM file to `<font_name>.tfm'. If this would overwrite the
+ input file, write to `x<font_name>.tfm' instead.
+tfm-header: <header-item>:<value>,<header-item>:<value>,...: assign each
+ <value> to the corresponding <header-item> when outputting a TFM file.
+ A <header-item> is one of `checksum', `designsize' or `codingscheme',
+ with casefolding. `checksum' requires an unsigned integer,
+ `designsize' a real, with 1.0 <= designsize < 2048, and `codingscheme'
+ a string of length less than 40 containing no parens or commas.
+verbose: print brief progress reports on stdout.
+version: print the version number of this program.
+"
+
+/* We return the name of the font to process. */
+
+static string
+read_command_line (int argc, string argv[])
+{
+ int g; /* `getopt' return code. */
+ int option_index;
+ boolean explicit_dpi = false;
+ boolean printed_version = false;
+ struct option long_options[]
+ = { { "baseline-adjust", 1, 0, 0 },
+ { "column-split", 1, 0, 0 },
+ { "concat", 1, 0, 0 },
+ { "designsize", 1, 0, 0 },
+ { "dpi", 1, (int *) &explicit_dpi, 1 },
+ { "encoding", 1, 0, 0 },
+ { "epsf", 0, (int *) &wants_epsf, 1 },
+ { "filter-passes", 1, 0, 0 },
+ { "filter-size", 1, 0, 0 },
+ { "filter-threshold", 1, 0, 0 },
+ { "fontdimens", 1, 0, 0 },
+ { "gf", 0, (int *) &wants_gf, 1 },
+ { "help", 0, 0, 0 },
+ { "omit", 1, 0, 0 },
+ { "output-file", 1, 0, 0 },
+ { "random", 1, 0, 0 },
+ { "random-threshold", 1, 0, 0 },
+ { "range", 1, 0, 0 },
+ { "remap", 1, 0, 0 },
+ { "text", 0, (int *) &wants_text, 1 },
+ { "tfm", 0, (int *) &wants_tfm, 1 },
+ { "tfm-header", 1, 0, 0 },
+ { "verbose", 0, (int *) &verbose, 1 },
+ { "version", 0, (int *) &printed_version, 1 },
+ { 0, 0, 0, 0 } };
+
+ while (true)
+ {
+ g = getopt_long_only (argc, argv, "", long_options, &option_index);
+
+ if (g == EOF)
+ break;
+
+ if (g == '?')
+ exit (1); /* Unknown option. */
+
+ assert (g == 0); /* We have no short option names. */
+
+ if (ARGUMENT_IS ("baseline-adjust"))
+ scan_baseline_adjust (optarg);
+
+ else if (ARGUMENT_IS ("column-split"))
+ scan_column_split (optarg);
+
+ else if (ARGUMENT_IS ("concat"))
+ append_concat_list (&fontname_list, optarg);
+
+ else if (ARGUMENT_IS ("designsize"))
+ {
+ design_size = atof (optarg);
+ TFM_CHECK_DESIGN_SIZE (design_size);
+ }
+
+ else if (ARGUMENT_IS ("dpi"))
+ dpi = optarg;
+
+ else if (ARGUMENT_IS ("encoding"))
+ {
+ if (encoding_info == NULL)
+ encoding_info = XTALLOC1 (encoding_info_type);
+ *encoding_info = read_encoding_file (optarg);
+ }
+
+ else if (ARGUMENT_IS ("filter-passes"))
+ filter_passes = atou (optarg);
+
+ else if (ARGUMENT_IS ("filter-size"))
+ filter_size = atou (optarg);
+
+ else if (ARGUMENT_IS ("filter-threshold"))
+ {
+ filter_threshold = atof (optarg);
+ if (filter_threshold <= 0.0)
+ FATAL1 ("The filter threshold should be positive, not %f",
+ filter_threshold);
+ }
+
+ else if (ARGUMENT_IS ("fontdimens"))
+ fontdimens = optarg;
+
+ else if (ARGUMENT_IS ("help"))
+ {
+ fprintf (stderr, "Usage: %s [options] <font_name>.\n", argv[0]);
+ fprintf (stderr, USAGE);
+ exit (0);
+ }
+
+ else if (ARGUMENT_IS ("omit"))
+ scan_omit_list (optarg);
+
+ else if (ARGUMENT_IS ("output-file"))
+ output_name = optarg;
+
+ else if (ARGUMENT_IS ("range"))
+ GET_RANGE (optarg, starting_char, ending_char);
+
+ else if (ARGUMENT_IS ("random"))
+ random_max = atof (optarg);
+
+ else if (ARGUMENT_IS ("random-threshold"))
+ random_threshold = atof (optarg);
+
+ else if (ARGUMENT_IS ("remap"))
+ scan_remap_list (optarg);
+
+ else if (ARGUMENT_IS ("text"))
+ report_file = stderr;
+
+ else if (ARGUMENT_IS ("tfm-header"))
+ tfm_header = optarg;
+
+ else if (ARGUMENT_IS ("version"))
+ printf ("%s.\n", version_string);
+
+ /* Else it was just a flag; getopt has already done the assignment. */
+ }
+
+ FINISH_COMMAND_LINE ();
+}
+
+/* The string S specifies baseline adjustments for individual
+ characters: `<charcode>:<adjustment>,...'. We set the element
+ <charcode> of the global array `baseline_adjust' to the <adjustment>. */
+
+static void
+scan_baseline_adjust (string s)
+{
+ string spec;
+
+ for (spec = strtok (s, ARG_SEP); spec != NULL; spec = strtok (NULL, ARG_SEP))
+ {
+ string code;
+ string adjust = strchr (spec, ':');
+
+ if (adjust == NULL)
+ FATAL1 ("Baseline adjustments look like `<code>:<integer>', not `%s'",
+ spec);
+
+ code = substring (spec, 0, adjust - spec - 1);
+
+ baseline_adjust[xparse_charspec (code, encoding_info)]
+ = atoi (adjust + 1);
+ }
+}
+
+
+/* The string S says how to split a single character into multiple
+ characters: `<charcode>@<column1>,...<columnN>'. We set the element
+ <charcode> of the global array `column_split' to the list of the
+ integers. */
+
+static void
+scan_column_split (string s)
+{
+ string code;
+ string column_list = strchr (s, '@');
+
+ if (column_list == NULL)
+ FATAL1 ("Column splits look like `<code>@<column>,<column>,...', not `%s'",
+ s);
+
+ code = substring (s, 0, column_list - s - 1);
+
+ column_split[xparse_charspec (code, encoding_info)]
+ = scan_unsigned_list (column_list + 1);
+}
+
+
+/* The string S is a list of font names, separated by commas. We append
+ each onto CONCAT_LIST. */
+
+static void
+append_concat_list (list_type *concat_list, string s)
+{
+ string name;
+
+ /* The main routine must initialize CONCAT_LIST before we are called. */
+ assert (concat_list != NULL && LIST_SIZE (*concat_list) > 0);
+
+ for (name = strtok (s, ARG_SEP); name != NULL; name = strtok (NULL, ARG_SEP))
+ {
+ string *new = LIST_TAPPEND (concat_list, string);
+ *new = name;
+ }
+}
+
+
+/* The string L is a list of character codes separated by commas; we
+ omit those characters in the output. Here, we parse the list and set
+ elements of the global array `omit' according to what we find. */
+
+static void
+scan_omit_list (string l)
+{
+ string map;
+
+ for (map = strtok (l, ARG_SEP); map != NULL; map = strtok (NULL, ARG_SEP))
+ {
+ charcode_type code = xparse_charspec (map, encoding_info);
+ omit[code] = true;
+ }
+}
+
+
+/* The string L is a list of remappings to apply, in the form
+ <code1>:<code2>,<code1>:<code2>,... where <code1> is a character
+ code in the original font, and <code2> is the character code to write
+ it as. No checking for remappings to or from the same character is
+ done here.
+
+ We set elements of the global array `translate' according to what we
+ find. */
+
+static void
+scan_remap_list (string l)
+{
+ string map; /* A single remapping. */
+
+ for (map = strtok (l, ARG_SEP); map != NULL; map = strtok (NULL, ARG_SEP))
+ {
+ one_byte original, target;
+ string original_str, target_str;
+ unsigned length = strlen (map);
+
+ /* Ignore empty mappings, as in `a:b,,c:d'. */
+ if (length == 0)
+ continue;
+
+ else if (length < 3)
+ {
+ WARNING1 ("Mapping `%s' too short to be valid", map);
+ continue;
+ }
+
+ else if (*map == ':')
+ { /* Must have form `::<code>'. */
+ original_str = ":";
+ if (*(map + 1) != ':')
+ {
+ WARNING1 ("Mapping `%s' doesn't have form `<code>:<code>'", map);
+ continue;
+ }
+ target_str = map + 2;
+ }
+
+ else if (*(map + length - 1) == ':')
+ { /* Must have form `<code>::'. */
+ target_str = ":";
+ if (*(map + length - 2) != ':')
+ {
+ WARNING1 ("Mapping `%s' doesn't have form `<code>:<code>'", map);
+ continue;
+ }
+ original_str = substring (map, 0, length - 3);
+ }
+
+ else
+ { /* Must have form `<code>:<code>'. */
+ target_str = strchr (map, ':');
+ if (target_str == NULL)
+ {
+ WARNING1 ("Mapping `%s' doesn't have form `<code>:<code>'", map);
+ continue;
+ }
+ target_str++;
+ original_str = substring (map, 0, target_str - 2 - map);
+ }
+
+ original = xparse_charspec (original_str, encoding_info);
+ target = xparse_charspec (target_str, encoding_info);
+ translate[original] = target;
+ }
+}
+
+
+
+/* xx use the macro instead */
+/*string
+finish_command_line()
+{
+ do
+ {
+ if (printed_version && optind == argc) exit (0);
+
+ if (optind + 1 == argc && *argv[optind] != 0)
+ {
+ FIND_CMDLINE_DPI ();
+ return MAYBE_REMOVE_SUFFIX (argv[optind]);
+ }
+ else
+ {
+ fprintf (stderr, "Usage: %s [options] <font_name>.\n", argv[0]);
+ fprintf (stderr, "(%s.)\n", optind == argc ? "Missing <font_name>"
+ : "Too many <font_name>s");
+ fputs ("For more information, use ``-help''.\n", stderr);
+ exit (1);
+ }
+ return NULL;
+ }
+ while (0)
+}
+*/