diff options
author | Norbert Preining <norbert@preining.info> | 2019-09-02 13:46:59 +0900 |
---|---|---|
committer | Norbert Preining <norbert@preining.info> | 2019-09-02 13:46:59 +0900 |
commit | e0c6872cf40896c7be36b11dcc744620f10adf1d (patch) | |
tree | 60335e10d2f4354b0674ec22d7b53f0f8abee672 /dviware/dvgtk/options.c |
Initial commit
Diffstat (limited to 'dviware/dvgtk/options.c')
-rw-r--r-- | dviware/dvgtk/options.c | 534 |
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 */ |