summaryrefslogtreecommitdiff
path: root/dviware/dvgtk/options.c
diff options
context:
space:
mode:
Diffstat (limited to 'dviware/dvgtk/options.c')
-rw-r--r--dviware/dvgtk/options.c534
1 files changed, 534 insertions, 0 deletions
diff --git a/dviware/dvgtk/options.c b/dviware/dvgtk/options.c
new file mode 100644
index 0000000000..3d660c73af
--- /dev/null
+++ b/dviware/dvgtk/options.c
@@ -0,0 +1,534 @@
+/* options.c - command line arguments processing
+ $Id: options.c,v 0.2 1997/03/28 03:17:12 tjchol01 Exp $
+ Authors: Andrew Trevorrow, Ian Dall, Geoffrey Tobin, Tomasz J. Cholewo
+ */
+
+#include "dvgt.h"
+#include "screenio.h"
+#include "options.h"
+#include "defaults.h"
+
+/* Variables Exported, via "options.h" */
+
+/* X and Y resolutions, in dpi */
+double xres, yres;
+
+/* Magnification */
+int mag;
+
+/* The next four are in paper pixels, and calculated. */
+int hoffset, voffset;
+int paperwd, paperht;
+
+String dummy_pk, dummy_tfm;
+String vdu;
+
+/* DVI file's name */
+string DVIname;
+
+
+typedef struct
+ {
+ units unit;
+ char *name;
+ double per_inch;
+ }
+Dan; /* `Dimension and name' */
+
+static
+Dan dans[] = /* `dimensions and names series' */
+{
+ {ic, "in", 1.0},
+ {cm, "cm", 2.54},
+ {mm, "mm", 25.4},
+ {bp, "bp", 72.0},
+ {pc, "pc", 72.27 / 12},
+ {pt, "pt", 72.27},
+ {sp, "sp", 72.27 * 65536},
+ {px, "px", 300.0} /* "px"'s per_inch value is not used, */
+}; /* but Qume, Laserwriter, etc, are 300 dpi */
+
+static
+size_t ldans = sizeof (dans) / sizeof (Dan); /* length of dans[] */
+
+static int Inint PARAMS ((double f));
+
+/*--------------------------------------------------------------------*/
+/* Auxiliary routines */
+/*--------------------------------------------------------------------*/
+
+/* Copy at most n characters from ct to s; set s[n] = NUL character. */
+/* This ASSUMES that s has memory >= n+1 characters. */
+
+char *
+strMcpy (char *s, const char *ct, size_t n)
+{
+ strncpy (s, ct, n);
+ s[n] = '\0';
+ return s;
+}
+/* strMcpy */
+
+/*--------------------------------------------------------------------*/
+
+/* Copy at most maxstring characters from ct to s; */
+/* set s[maxstring] = NUL character. */
+
+char *
+stringcopy (String s, const char *ct)
+{
+ strncpy (s, ct, maxstring);
+ s[maxstring] = '\0';
+ return (char *) &s;
+}
+/* stringcopy */
+/*--------------------------------------------------------------------*/
+static int
+Inint (double f)
+{
+ return ((int) (f + 0.5));
+}
+/* Inint */
+/*--------------------------------------------------------------------*/
+static void
+ToCardinal (const char *option, const char *value, int *n)
+{
+ /* If value represents a positive integer, then return via n. */
+
+ int check;
+ double r;
+
+ check = sscanf (value, "%lf", &r);
+ *n = Inint (r); /* round value to nearest integer */
+
+ /* check can be 1 or EOF if ok! */
+ if ((check == 1 || check == EOF) && *n > 0)
+ return;
+
+ FATAL2 ("Bad `%s' value: %s. Specify a positive integer.", option, value);
+}
+/* ToCardinal */
+
+/*--------------------------------------------------------------------*/
+
+static void
+ToRes (const char *option, const char *value, double *xr, double *yr)
+{
+ /* X and Y resolutions, specified in dots per inch. */
+
+ int check;
+
+ check = sscanf (value, "%lf,%lf", xr, yr);
+ if (check == 2 && *xr > 0 && *yr > 0)
+ {
+ return;
+ }
+ else
+ {
+ check = sscanf (value, "%lf", xr);
+ if (check == 1 && *xr > 0)
+ {
+ *yr = *xr;
+ return;
+ }
+ }
+
+ FATAL2 ("Bad `%s' value(s): %s.\n"
+ "Resolutions must be positive reals,\n"
+ "specified as `-r xres' or `-r xres,yres'\n"
+ "in dots per inch.", option, value);
+}
+/* ToRes */
+
+/*--------------------------------------------------------------------*/
+
+static units
+Name2Unit (const char *uname)
+{
+ units unit = ic;
+ char Luname[3]; /* Lower case unit name */
+ int j;
+
+#define ToLower(x) (isupper(x) ? tolower(x) : (x))
+
+ Luname[0] = ToLower (uname[0]);
+ Luname[1] = ToLower (uname[1]);
+ Luname[2] = '\0';
+
+ for (j = 0; j < ldans && strcmp (Luname, dans[j].name); j++); /* Search for the name of the unit. */
+
+ if (j < ldans)
+ unit = dans[j].unit;
+ else
+ {
+ MesgString ("Bad unit name `");
+ MesgString (uname);
+ MesgString ("'");
+ MesgLine ();
+
+ MesgString ("Last two letters should be one of ");
+ for (j = 0; j < ldans; j++)
+ {
+ MesgString (" `");
+ MesgString (dans[j].name);
+ MesgString ("'");
+ }
+ MesgChar ('.');
+ MesgLine ();
+
+ MesgString ("Using inch.");
+ MesgLine ();
+ unit = ic;
+ }
+ return unit;
+}
+/* Name2Unit */
+
+/*--------------------------------------------------------------------*/
+
+static void
+ToDimen (const char *option, const char *value, double *r, units *un)
+{
+ /* A valid dimension consists of an integer or real number followed
+ by a two-letter unit: see dans[] above.
+ If value represents a valid dimension,
+ return number part in r, and units part in un.
+ */
+
+ int check;
+ String nun; /* name of unit - ample space in a string for it */
+
+ check = sscanf (value, "%lf%2s", r, nun);
+ if (check == 2)
+ {
+ /* extract unit's code from its name */
+ *un = Name2Unit (nun);
+ }
+ else if (check == 1)
+ {
+ MesgString ("No dimension given, using inch.");
+ MesgLine ();
+ *un = ic;
+ }
+ else
+ { /* check < 1 */
+ FATAL2 ("Bad `%s' value: %s.\nSpecify a dimensioned quantity.",
+ option, value);
+ }
+}
+/* ToDimen */
+
+/*--------------------------------------------------------------------*/
+
+static void
+ToPosDimen (const char *option, const char *value, double *r, units *un)
+{
+ /* A valid +ve dimension consists of a positive integer or real number
+ followed by a two-letter unit: see dans[] above.
+ If value represents a valid dimension,
+ return numeric part in r, and units part in un.
+ */
+
+ ToDimen (option, value, r, un);
+
+ if (*r <= 0)
+ {
+ FATAL2 ("Bad `%s' value: %s.\nSpecify a positive dimension.",
+ option, value);
+ }
+}
+/* ToPosDimen */
+
+/*--------------------------------------------------------------------*/
+
+static int
+DimenPixels (double r, units u, double res)
+{
+ /* Return given dimension as nearest whole number of pixels, */
+ /* given the appropriate (eg, X or Y direction's) resolution in dpi. */
+
+ int Result;
+
+ int i;
+
+ if (u == px)
+ Result = Inint (r);
+ else
+ {
+ for (i = 0; i < ldans && u != dans[i].unit; i++); /* search for unit */
+
+ if (i < ldans)
+ Result = Inint (r / dans[i].per_inch * res);
+ else
+ {
+ MesgString ("Unimplemented unit, treating as inch.");
+ MesgLine ();
+ Result = Inint (r * res);
+ }
+ }
+ return Result;
+}
+/* DimenPixels */
+/*--------------------------------------------------------------------*/
+void
+WriteCardinal (char *name, int value)
+{
+ String outstring;
+
+ sprintf (outstring, "%s= %d", name, value);
+ MesgString (outstring);
+ MesgLine ();
+}
+/* WriteCardinal */
+/*--------------------------------------------------------------------*/
+
+void
+WriteReal (char *name, double value)
+{
+ String outstring;
+
+ sprintf (outstring, "%s= %f", name, value);
+ MesgString (outstring);
+ MesgLine ();
+}
+
+/* WriteReal */
+
+/*--------------------------------------------------------------------*/
+
+/* GT - TO BE FINISHED - Write... FUNCTIONS BELOW, TOO! */
+/* Might be better to use a pair of arrays, or array of pairs */
+/* That is, data-driven may be more flexible. */
+
+void
+NameUnit (units un, String nun)
+/* Interface: un (I), *nun (O). */
+{
+ int i;
+
+ for (i = 0; i < ldans && un != dans[i].unit; i++); /* Search for unit un. */
+
+ if (i < ldans)
+ stringcopy (nun, dans[i].name);
+ else
+ {
+ MesgString ("Unknown unit! Assuming inch.");
+ MesgLine ();
+
+ stringcopy (nun, "in");
+ }
+}
+/* NameUnit */
+
+/*--------------------------------------------------------------------*/
+
+void
+WriteDimen (char *varname, double r, units un)
+{
+ String outstring, nun;
+
+ NameUnit (un, nun);
+ /* !! gt - this line is unsafe, as outstring may overflow! */
+ sprintf (outstring, "%s= %f %s", varname, r, nun);
+ MesgString (outstring);
+ MesgLine ();
+}
+
+/* WriteDimen */
+
+/*--------------------------------------------------------------------*/
+
+void
+WriteName (char *varname, char *svalue)
+{
+ String outstring;
+
+ sprintf (outstring, "%s= %s", varname, svalue);
+ MesgString (outstring);
+ MesgLine ();
+}
+
+/* WriteName */
+
+/*--------------------------------------------------------------------*/
+
+double
+Unit2Value (units unit)
+{
+ double per_inch = 1.0; /* 1 unit per inch */
+ int j;
+
+ for (j = 0; (j < ldans) && (unit != dans[j].unit); j++); /* Search for the unit. */
+
+ if (j < ldans)
+ per_inch = dans[j].per_inch;
+ else
+ {
+ FATAL1 ("Bad unit, enumeration value = %d", unit);
+ }
+ return per_inch;
+}
+/* Unit2Value */
+
+/*--------------------------------------------------------------------*/
+
+int
+InitOptions (int argc, char **argv)
+{
+ /* Get DVI file, and any options, from the command line.
+ If an option appears more than once, then we return the last value.
+
+ Actually, proceed in three steps, in increasing priority:
+ (1) Initialise to default values, as set in "defaults.h".
+ (2) If the appropriate environment variable is set, use that.
+ (3) If the appropriate command line option is set, use that.
+ */
+
+ char *env; /* environment variable */
+ units def_unit = ic; /* default unit is inch */
+ units hoffu, voffu, xu, yu;
+ double hoffr, voffr, xr, yr;
+ boolean landscape;
+ int c;
+
+
+ /*
+ (1) DEFAULTS.
+ initialize option values with defaults; note that the dv script can
+ set up different defaults [- quoth Andrew Trevorrow, I presume]
+ - gt observes - no "dv" script provided with DVItoVDU version 3.0!
+ */
+
+ /* "dpi" means "dots per inch" */
+ /* printer's X and Y resolutions in dpi */
+ xres = (double) DEF_XRES;
+ yres = (double) DEF_YRES;
+
+ /* Page Offsets from Paper edges */
+ hoffu = def_unit;
+ voffu = def_unit;
+ hoffr = 0.0; /* no margin shifting, so 1" left and top margins */
+ voffr = 0.0;
+
+ mag = 0; /* use DVI file's intrinsic magnification */
+
+ /*
+ (2) ENVIRONMENT VARIABLES.
+ */
+
+ /* Resolution, in dots per inch */
+ /* If DV_RES is set in the environment, then try to use that. */
+ /* If two real values are in DV_RES, copy them to xres and yres. */
+ /* If only one is in DV_RES, copy it to both xres and yres. */
+ /* If none is, then ignore DV_RES. */
+
+ if ((env = getenv ("DV_RES")) != (char *) NULL)
+ ToRes (" -r", env, &xres, &yres);
+
+#if 0
+ if (!(env = getenv ("DV_TERM")))
+ env = getenv ("TERM");
+ stringcopy (vdu, !env ? "" : env);
+#else
+ stringcopy (vdu, "tek4010");
+#endif
+
+ /* Paper Width */
+ ToPosDimen ("", !(env = getenv ("DV_PAPERWD")) ? DEF_PAPERWD : env,
+ &xr, &xu);
+
+ /* Paper Height */
+ ToPosDimen ("", !(env = getenv ("DV_PAPERHT")) ? DEF_PAPERHT : env,
+ &yr, &yu);
+
+ /* fall-back PK font */
+ stringcopy (dummy_pk, !(env = getenv ("DV_DUMMY_PK")) ? DEF_DUMMY_PK : env);
+ /* fall-back TFM metric */
+ stringcopy (dummy_tfm, !(env = getenv ("DV_DUMMY_TFM")) ? DEF_DUMMY_TFM : env);
+ /* portrait or landscape page dimensions? */
+ landscape = false; /* portrait: don't swap -x and -y values */
+
+ /*
+ (3) COMMAND LINE OPTIONS.
+ */
+
+ while ((c = getopt (argc, argv, "H:V:d:e:k:lm:r:t:x:y:")) != -1)
+ {
+ switch (c)
+ {
+ case 0: /* flags already processed */
+ break;
+
+ case 'H':
+ ToDimen (" -H", optarg, &hoffr, &hoffu);
+ break;
+ case 'V':
+ ToDimen (" -V", optarg, &voffr, &voffu);
+ break;
+ case 'd':
+ stringcopy (dummy_pk, optarg);
+ break;
+ case 'e': /* gt - not very mnemonic, I know */
+ stringcopy (dummy_tfm, optarg);
+ break;
+ case 'k':
+ kpathsea_debug |= atoi (optarg);
+ break;
+ case 'l':
+ landscape = true;
+ break;
+ case 'm':
+ ToCardinal (" -m", optarg, &mag);
+ case 'r':
+ /* gt - resolutions should allow non-integer dpi */
+ /* - this is because there are such output devices */
+ /* - for example, metric printers. */
+ /* Get resolutions, specified in dots per inch */
+ ToRes (" -r", optarg, &xres, &yres);
+ break;
+ case 'v':
+ stringcopy (vdu, optarg);
+ break;
+ case 'x':
+ ToPosDimen (" -x", optarg, &xr, &xu);
+ break;
+ case 'y':
+ ToPosDimen (" -y", optarg, &yr, &yu);
+ break;
+ case '?': /* error message in getopt */
+ FATAL ("Exiting");
+ default:
+ FATAL ("Fatal error in getopt");
+ } /* switch */
+ }
+
+ argv += optind - 1;
+ argc -= optind - 1;
+
+ if (argc < 2)
+ {
+ return 0;
+ }
+
+ /* bad DVIname will be detected upon open in main module */
+ DVIname = extend_filename (argv[1], "dvi");
+
+ /* set h/voffset and paperwd/ht only after resolutions have been decided */
+ hoffset = DimenPixels (hoffr, hoffu, xres);
+ voffset = DimenPixels (voffr, voffu, yres);
+
+ paperwd = DimenPixels (xr, xu, xres);
+ paperht = DimenPixels (yr, yu, yres);
+
+ if (landscape)
+ { /* swap paperwd and paperht */
+ int temp = paperwd;
+ paperwd = paperht;
+ paperht = temp;
+ }
+ return 1;
+}
+
+/* InitOptions */
+
+/* end options.c */