/* 13:30 GMT +10 Thu 16 June 1994 - gt@ee.latrobe.edu.au */ /* fig2mfpic 0.024 in ANSI C and traditional C */ /* Geoffrey Tobin's attempt at a "fig2mfpic" for mfpic 0.2.5, based on Anthony Starks's Fig2MF 0.04 of Wed 28 Oct 1992, Anthony's letter of Fri 11 Sep 1992, and Uwe Bonnes's investigations for Uwe's transfig driver for mfpic 0.2.5. Note: Fig 2.1 is the native (I/O) language of X11 `xfig' GUI drawing program. (An older version of Fig was used in Sunview's `fig'.) Some other programs, e.g. the unix version of gnuplot, can output Fig 2.1 code. */ /* fig2mfpic -- convert Fig 2.1 to mfpic 0.2.5 TeX macros * * Anthony J. Starks and Geoffrey R.D. Tobin * ajs@msdrl.com ecsgrt@luxor.latrobe.edu.au * ajs@merck.com gt@ee.latrobe.edu.au * * Uwe Bonnes * bon@lte.e-technik.u-erlangen.de * * Scaling in inches, * default [x-y]scale is 1/80 inch, which is one Fig unit. * MFpic uses pt, not in, so fig2mfpic must convert. * Pen switching is local. * Supports 3-point arcs. * Token support for text. * Supports interpolated splines. * Output units: in, pt, bp, mm, cm, sp, Fig units. * Many input files. * Output to stdout. * Splines have floating point numbers as coordinates (Fig 2.1 spec). * ANSI C or traditional C. * Count objects, starting from 1. * Log file kept of all error messages. * In polyline, expect EPS line before points line. * For ANSI C, display source file, date and time of compilation. * Fig Object Type information supplied in TeX comments. */ #include #include #include #include /* Fig 2.1 signature */ #define FIG_SIG "#FIG 2.1" /* A technique for handling both Standard and traditional C compilers, */ /* borrowed from the Free Software Foundation */ #ifdef __STDC__ #define __(X) X #define Void void #define VOID void #else #define __(X) () #define Void int #define VOID #endif char * type_name __((int code)); char * diagnostic __((void)); Void put_msg __((char * msg)); Void Lwrite __((char * msg)); Void Lflush __((void)); double xs __((double x)); double ys __((double y)); double xt __((double x)); double yt __((double y)); int parse __((char * s)); Void give_help __((void)); int process __((char * filename)); int ellipse __((FILE * figfp)); int polyline __((FILE * figfp)); int spline __((FILE * figfp)); int read_pts __((FILE * figfp)); int controls __((int npts, FILE * figfp)); int text __((FILE * figfp)); int arc __((FILE * figfp)); int compound __((FILE * figfp)); char * subtype_name __((int obj, int subobj)); Void define_polydash __((void)); Void finit __((void)); Void cinit __((void)); Void cfin __((void)); Void ffin __((void)); int get_line __((FILE * figfp)); int next_src_line __((FILE * figfp)); Void display_line __((void)); int get_int __((char ** bufpa, int * ya)); int get_double __((FILE * figfp, char ** bufpa, double * ya)); int buffer_empty __((char * bp)); #ifndef TRUE # define TRUE 1 # define FALSE 0 #endif #define SUCCESS 0 #define FAILURE 1 #define MIN(a,b) ((a) < (b) ? (a) : (b)) #define MAX(a,b) ((a) > (b) ? (a) : (b)) #define OUTPUT printf /* write a log file? */ int do_log = FALSE; /* log file pointer */ FILE * logfp = (FILE *) NULL; /* error message */ #define MESSAGE_SLEN 255 typedef char MsgType[MESSAGE_SLEN+1]; MsgType Message; /* filling gradation - is "1.2" a `magic' number? */ #define dofill() 1.2-((double)area_fill/(double)FILL_BLACK) /* pen size */ #define do_pen(x) ((x-1)*PEN_INCR)+DEF_PEN #define VERSION "0.024" #define MFPIC_VERSION "0.2.5" #define GRAPHBASE_VERSION "0.2 fig 2a" #define O_ELLIPSE 1 #define O_POLYLINE 2 #define O_SPLINE 3 #define O_TEXT 4 #define O_ARC 5 #define O_COMPOUND 6 #define O_END_COMPOUND (-6) /* Area fill */ #define UNFILLED 0 #define FILL_BLACK 21 #define N_ELLIPSE 19 #define N_POLYLINE 12 #define N_SPLINE 11 #define N_TEXT 14 #define N_ARC 20 #define N_COMPOUND 4 /* default pen size in pt */ #define DEF_PEN 0.5 #define PEN_INCR 0.1 /* DEFAULT mfpic drawing macros TeX file */ #define DEF_DFILE "mfpic.tex" /* DEFAULT output MetaFont file : interpreted by mfpic as "figleaf.mf" */ #define DEF_MF_OFILE "figleaf" /* DEFAULT output log file */ #define DEF_LOG_FILE "fig2mfpic.log" #define BUF_SIZE 1024 char buf[BUF_SIZE]; /* Number of TeX points (pt) in an inch (in) */ #define PT_PER_INCH 72.27 /* Number of actual drawing units per pt */ #define PIXEL (PT_PER_INCH / ppi) /* Number of default (Fig) drawing units per inch */ #define DEF_PPI 80.0 /* Default maxy value (in Y drawing units) */ #define DEF_MAXY 640.0 /* Pi, from Abramowitz and Stegun */ #define PI 3.141592653589793238462643 /* radian in degrees, from Abramowitz and Stegun */ #define RADIAN 57.295779513082320876798155 /* degree in radians, from Abramowitz and Stegun */ #define DEGREE 0.017453292519943295769237 /* First output character's code */ #define FIRST_CHAR 33 /* "fig2mfpic" program options */ #define None 0 #define Real 1 #define Integer 2 #define String 3 #define Help 4 #define Unit 5 #define Boolean 6 typedef struct { char *keyword; /* option's keyword */ int type; /* data type of option's value */ Void *value; /* generic pointer to option's value */ char *description; /* description of keyword & value for option */ } Options; /* maximum allowed number of output characters */ #define MAXNCHAR 256 /* number of characters output so far */ int nchar = 0; /* current line number, in current input file */ int linenum = 0; /* number of objects counted so far */ int nobjs = -1; /* object type */ int obj_type = -1; /* object subtype */ int obj_subtype = -1; /* whether object types have been listed during this run */ int listed_types = FALSE; /* pixels [input units] per inch */ /* 1 Fig unit = 1 inch / ppi */ double ppi = DEF_PPI; /* coordinate system = orientation of Y axis */ #define Y_UP 1 #define Y_DOWN 2 int coord_sys = Y_DOWN; /* usual with Fig */ /* I prefer input and output units to coincide */ double oupi = DEF_PPI; /* output units per inch */ double ioc = 1.0; /* input to output unit conversion factor */ /* calculated bounding box of a picture */ double bxl, bxu, byl, byu; int bbbegun = 0; /* no lower bound yet for BB for current picture */ /* options */ int help; /* help flag */ int debug; /* debug flag */ int char_code = 33; /* initial char code */ double mfpen; /* global pen width (pt) */ char * o_unit="Fig"; /* output unit (default is 1 Fig unit) */ double xscale = 1.0; /* 1 X drawing unit = xscale * output unit */ double yscale = 1.0; double xl; /* character bounds, in X and Y drawing units */ double yl; double xu; double yu; double maxy; /* maximum Y value (Y drawing units) */ char * mf_ofile=""; /* output MF file name */ char *draw_macros=""; /* mfpic drawing macros TeX file name */ char *log_file=""; /* log file name */ char *progname=""; /* command line name of this program */ char *curfigfile=""; /* current input file */ Options opts[] = { {"-?", Help, &help, "Help request"}, {"-d", Boolean, &debug, "List input file, with line numbers"}, {"-code", Integer, &char_code, "First character's code : not effective"}, {"-pen", Real, &mfpen, "Default pen width (pt)"}, {"-u", Unit, &o_unit, "Output unit name"}, {"-xscale", Real, &xscale, "X unit (in output units)"}, {"-yscale", Real, &yscale, "Y unit (in output units)"}, {"-xneg", Real, &xl, "Most negative X value (X units)"}, {"-xpos", Real, &xu, "Most positive X value (X units)"}, {"-yneg", Real, &yl, "Most negative Y value (Y units)"}, {"-ypos", Real, &yu, "Most positive Y value (Y units)"}, {"-top", Real, &maxy, "Top of drawing (Y units)"}, {"-mf", String, &mf_ofile, "Output METAFONT file"}, {"-tex", String, &draw_macros, "mfpic TeX drawing macros file"}, {"-log", String, &log_file, "fig2mfpic log file"}, {NULL, None, NULL, ""} }; /* opts[] */ /* FUNCTIONS */ /* return name of object type from given code */ char * type_name #ifdef __STDC__ (int code) #else (code) int code; #endif { char * name = "unknown"; switch (code) { case O_ELLIPSE: name = "ellipse"; break; case O_POLYLINE: name = "polyline"; break; case O_SPLINE: name = "spline"; break; case O_TEXT: name = "text"; break; case O_ARC: name = "arc"; break; case O_COMPOUND: name = "compound"; break; case O_END_COMPOUND: name = "end compound"; break; default: name = "unknown"; break; } return (name); } /* type_name */ char * diagnostic (VOID) { extern char *curfigfile; extern int nobjs; extern int obj_type; extern int linenum; extern MsgType Message; char * Diagnostic = Message; sprintf (Diagnostic, " : file \"%s\", object # %d, type %s (%d %d), at line %d\n", curfigfile, nobjs+1, subtype_name (obj_type, obj_subtype), obj_type, obj_subtype, linenum); return (Diagnostic); } /* diagnostic */ /* write a diagnostic message to stderr and to logfp */ Void put_msg #ifdef __STDC__ (char * msg) #else (msg) char * msg; #endif { if (!debug) /* avoid double display */ { display_line(); } Lwrite ("! "); Lwrite (msg); Lwrite (diagnostic()); Lflush (); } /* put_msg */ /* write to stderr and to logfp */ Void Lwrite (char * msg) { extern int do_log; fprintf (stderr, "%s", msg); if (do_log) { fprintf (logfp, "%s", msg); } } /* Lwrite */ /* flush both stderr and logfp */ Void Lflush (void) { fflush (stderr); if (do_log) { fflush (logfp); } } /* Lflush */ double xs #ifdef __STDC__ (double xr) #else (xr) double xr; #endif { return (ioc * xr); } /* xs */ double ys #ifdef __STDC__ (double yr) #else (yr) double yr; #endif { return (ioc * yr); } /* ys */ double xt #ifdef __STDC__ (double x) #else (x) double x; #endif { return (ioc * x); } /* xt */ double yt #ifdef __STDC__ (double y) #else (y) double y; #endif { return (ioc * (maxy-y)); } /* yt */ int main #ifdef __STDC__ (int argc, char * argv[]) #else (argc, argv) int argc; char * argv[]; #endif { progname = argv[0]; /* this program */ curfigfile = "Standard Input"; /* current input file */ linenum=0; /* no line read yet */ /* initial values of options */ help=0; /* no help */ char_code=FIRST_CHAR; /* first character has char code FIRST_CHAR */ mfpen=DEF_PEN; /* pen diameter (pt) */ o_unit = "Fig"; xscale=1.0; /* drawing units (in output units) */ yscale=1.0; xl=0.0; /* xl, xu, yl, yu : size of picture in drawing units */ xu=DEF_MAXY; yl=0.0; yu=DEF_MAXY; maxy=DEF_MAXY; mf_ofile=DEF_MF_OFILE; /* use default MF drawing macros */ draw_macros=DEF_DFILE; /* use default TeX drawing macros */ log_file=DEF_LOG_FILE; /* write to default log file */ if ((logfp = fopen (log_file, "w")) == (FILE *) NULL) { do_log = FALSE; } else { do_log = TRUE; } if (argc < 2) /* no cmdline arguments, so give help */ give_help(); else /* treat each argument as an option or an input filename */ { int i; for (i=1; i < argc; i++) parse (argv[i]); } ffin(); /* close mfpic output, if there was any */ return (SUCCESS); } /* main */ int parse #ifdef __STDC__ (char * s) #else (s) char * s; #endif { int optnum; char *strchr(); double atof(); int atoi(); for (optnum=0; opts[optnum].keyword != NULL; optnum++) { if (strncmp (s, opts[optnum].keyword, strlen (opts[optnum].keyword)) == 0) { switch (opts[optnum].type) { case None: break; case Real: * (double *) opts[optnum].value = atof (strchr (s, '=')+1); break; case Integer: * (int *) opts[optnum].value = atoi (strchr (s, '=')+1); break; case String: * (char * *) opts[optnum].value = strchr (s, '=')+1; break; case Help: give_help(); break; case Unit: { char * unit = strchr (s, '=')+1; * (char * *) opts[optnum].value = unit; check_unit (unit); } break; case Boolean: /* FALSE by default */ * (int *) opts[optnum].value = TRUE; break; } return (optnum); } } /* this command line argument is not a known option */ /* so assume it's a filename */ process (s); return (optnum); } /* parse */ Void give_help (VOID) { char * typename = "unknown type"; int i; MsgType Advice; sprintf (Advice, "usage: %s ", progname); Lwrite (Advice); Lwrite ("[infile] [... infile] [> outfile]"); Lwrite ("\n"); Lflush (); for (i=0; opts[i].keyword != NULL; i++) { switch (opts[i].type) { case Real: typename = "real"; break; case Integer: typename = "integer"; break; case String: typename = "string"; break; default: typename = "none"; break; } Lwrite (" "); switch (opts[i].type) { case None: case Help: case Boolean: sprintf (Advice, "[%s]", opts[i].keyword); Lwrite (Advice); break; default: sprintf (Advice, "[%s=<%s>]", opts[i].keyword, typename); Lwrite (Advice); break; } Lwrite (" "); sprintf (Advice, "%s", opts[i].description); Lwrite (Advice); Lwrite ("\n"); Lflush (); } Lwrite ("If an \"infile\" is \"-\", then standard input is read.\n"); Lwrite ("The mfpic TeX drawing file goes to standard output.\n"); Lwrite ("Messages, such as this, go to standard error.\n"); Lflush (); } /* give_help */ typedef struct { char * name; /* name of unit */ double value; /* value of 1 inch / 1 unit, i.e. the number of units per inch */ } Units; Units units[] = { {"in", 1.0}, {"pt", 72.27}, {"bp", 72.0}, {"mm", 25.4}, {"cm", 2.54}, {"sp", 72.27 * 65536}, {"Fig", 80.0}, {NULL, 0.0}, }; /* units[] */ int check_unit #ifdef __STDC__ (char * unit) #else (unit) char * unit; #endif { extern MsgType Message; int unum; for (unum=0; units[unum].name != NULL; unum++) { if (strncmp (unit, units[unum].name, strlen (units[unum].name)) == 0) { oupi = units[unum].value; return (unum); } } sprintf (Message, "\"%s\" is an unknown unit!\n", unit); Lwrite (Message); Lflush (); return (unum); } /* check_unit */ int process #ifdef __STDC__ (char * filename) #else (filename) char * filename; #endif { extern MsgType Message; extern int listed_types; FILE * figfp; if (filename[0] == '-') { curfigfile = "Standard Input"; figfp = stdin; } else { curfigfile=filename; if ((figfp = fopen (filename, "r")) == NULL) { sprintf (Message, "%s: cannot open the input file \"%s\"\n", progname, filename); Lwrite (Message); Lflush (); return (FAILURE); } } linenum = 0; /* The very first line in a Fig file must be a particular comment */ get_line (figfp); /* Fig and version identification comment, and its length */ if (strncmp (buf, FIG_SIG, strlen (FIG_SIG)) != 0) { put_msg ("Not a Fig 2.1 signature"); sprintf (Message, "Expected first line to be \"%s\"\n", FIG_SIG); Lwrite (Message); Lflush (); return (FAILURE); } next_src_line (figfp); if (sscanf (buf, "%lf%d\n", &ppi, &coord_sys) != 2) { put_msg ("ppi or coord_sys missing or not in \"real integer\" format"); return (FAILURE); } /* For Fig 2.1, ppi = DEF_PPI = 80.0 pixels per inch, */ /* and the coord_sys = Y_DOWN = 2, meaning origin at top left */ ioc = oupi / ppi; /* current number of output units per input unit */ { /* First input Fig file */ static int once = 0; if (once == 0) { finit(); /* start of the (sole) TeX output file */ once = 1; } } cinit(); /* One MF character per Fig picture */ for (nobjs = 0; next_src_line (figfp) > 0; ++ nobjs) { /* object type */ if (sscanf (buf, "%d", &obj_type) != 1) { put_msg ("Incorrect object type code (need integer)"); return (FAILURE); } if (obj_type == O_COMPOUND || obj_type == O_END_COMPOUND) { OUTPUT ("%% %d : %s (%d)\n", nobjs+1, type_name (obj_type), obj_type); } else { /* object subtype */ if (sscanf (buf, "%*d %d", &obj_subtype) != 1) { put_msg ("Incorrect object subtype code (need integer)"); return (FAILURE); } OUTPUT ("%% %d : %s (%d %d)\n", nobjs+1, subtype_name (obj_type, obj_subtype), obj_type, obj_subtype); } switch (obj_type) { case O_ELLIPSE: ellipse (figfp); break; case O_POLYLINE: polyline (figfp); break; case O_SPLINE: spline (figfp); break; case O_TEXT: text (figfp); break; case O_ARC: arc (figfp); break; case O_COMPOUND: compound (figfp); break; case O_END_COMPOUND: end_compound (figfp); break; default: sprintf (Message, "Object omitted"); put_msg (Message); if (!listed_types) { Lwrite ("Known object types are:\n"); sprintf (Message, " ellipse (%d)\n", O_ELLIPSE); Lwrite (Message); sprintf (Message, " polyline (%d)\n", O_POLYLINE); Lwrite (Message); sprintf (Message, " spline (%d)\n", O_SPLINE); Lwrite (Message); sprintf (Message, " text (%d)\n", O_TEXT); Lwrite (Message); sprintf (Message, " arc (%d)\n", O_ARC); Lwrite (Message); sprintf (Message, " compound (%d)\n", O_COMPOUND); Lwrite (Message); sprintf (Message, " end_compound (%d)\n", O_END_COMPOUND); Lwrite (Message); Lflush (); listed_types = TRUE; } break; } } cfin(); if (figfp != stdin) fclose (figfp); return (SUCCESS); } /* process */ /* Line styles */ #define SOLID_LINE 0 #define DASH_LINE 1 #define DOTTED_LINE 2 /* Dimension of a dot in dotted line style (pt) */ #define DOT_SIZE 1.0 /* Ellipse objects */ /* Ellipse or circle, described by radius (radii) or diameter(s) */ /* Subtypes: */ #define T_ELLIPSE_BY_RAD 1 #define T_ELLIPSE_BY_DIA 2 #define T_CIRCLE_BY_RAD 3 #define T_CIRCLE_BY_DIA 4 int ellipse #ifdef __STDC__ (FILE * figfp) #else (figfp) FILE * figfp; #endif { int n; int type, subtype, line_style, line_thickness, /* pixels */ color, depth, pen, /* unused in Fig */ area_fill; /* 0: not filled, 1 : white, ..., 21: black */ double style_val; /* pixels; for dash lines, length of on/off dashes */ /* for dot lines, gap b/w dots */ int dir; double angle; int cx, /* cx, cy : centre */ cy, rx, /* rx, ry : radii */ ry, sx, /* sx, sy, ex, ey : ellipse's bounding box */ sy, ex, ey; n = sscanf (buf, "%d%d%d%d%d%d%d%d%lf%d%lf%d%d%d%d%d%d%d%d", &type, &subtype, &line_style, &line_thickness, &color, &depth, &pen, &area_fill, &style_val, &dir, &angle, &cx, &cy, &rx, &ry, &sx, &sy, &ex, &ey); if (n != N_ELLIPSE) { put_msg ("Malformed circle or ellipse"); return n; } { int fx, fy; if (subtype == T_CIRCLE_BY_RAD || subtype == T_ELLIPSE_BY_RAD) { fx = 2 * cx - ex; fy = 2 * cy - ey; } else { fx = sx; fy = sy; } if (bbbegun) { bxl = MIN (bxl, ex); bxl = MIN (bxl, fx); bxu = MAX (bxu, ex); bxu = MAX (bxu, fx); byl = MIN (byl, ey); byl = MIN (byl, fy); byu = MAX (byu, ey); byu = MAX (byu, fy); } else { bxl = MIN (ex, fx); bxu = MAX (ex, fx); byl = MIN (ey, fy); byu = MAX (ey, fy); bbbegun = 1; } } if (line_thickness > 1) OUTPUT (" \\pen{%.2lfpt}\n", do_pen (line_thickness)); if (subtype == T_CIRCLE_BY_RAD || subtype == T_CIRCLE_BY_DIA) { if (area_fill == FILL_BLACK) OUTPUT (" \\cdisk"); else if (area_fill < FILL_BLACK && area_fill > UNFILLED) { OUTPUT (" \\shadespace=%lfpt\n", dofill()); OUTPUT (" \\circshade"); } else OUTPUT (" \\circle"); OUTPUT ("{(%lf,%lf),%lf}\n", xt(cx), yt(cy), xs(rx)); } else if (subtype == T_ELLIPSE_BY_RAD || subtype == T_ELLIPSE_BY_DIA) { if (area_fill == FILL_BLACK) OUTPUT (" \rotatededisk"); else if (area_fill < FILL_BLACK && area_fill > UNFILLED) { OUTPUT (" \\shadespace=%lfpt\n", dofill()); OUTPUT (" \\rotatedellshade"); } else OUTPUT (" \\rotatedellipse"); OUTPUT ("{(%lf,%lf),%lf,%lf,%lf}\n", xt(cx), yt(cy), xs(rx), ys(ry), angle * RADIAN); } if (line_thickness > 1) OUTPUT (" \\pen{%.2lfpt}\n", mfpen); return n; } /* ellipse */ /* Polyline objects */ /* Subtypes: */ /* Many of these remain unimplemented in fig2mfpic */ #define T_POLYLINE 1 #define T_BOX 2 #define T_POLYGON 3 #define T_ARC_BOX 4 #define T_EPS_BOX 5 #define EPS_UPRIGHT 0 #define EPS_FLIPPED 1 /* Maximum length of name of EPSF file */ #define EPSF_SLEN 100 int polyline #ifdef __STDC__ (FILE * figfp) #else (figfp) FILE * figfp; #endif { int npts_read; int n; int type, subtype, line_style, line_thickness, color, depth, pen, area_fill; double style_val; int radius, /* for rounded corners of boxes */ fa, /* Forward arrow : not yet interpreted in fig2mfpic */ ba, /* Backward arrow : not yet interpreted in fig2mfpic */ at, as, eflag; double athick, awidth, aht; char epsfile[EPSF_SLEN+1]; npts_read = 0; n = sscanf (buf, "%d%d%d%d%d%d%d%d%lf%d%d%d", &type, &subtype, &line_style, &line_thickness, &color, &depth, &pen, &area_fill, &style_val, &radius, &fa, &ba); if (n != N_POLYLINE) { put_msg ("Malformed polyline"); return npts_read; } if (fa) { next_src_line (figfp); sscanf (buf, "%d%d%lf%lf%lf\n", &at, &as, &athick, &awidth, &aht); } if (ba) { next_src_line (figfp); sscanf (buf, "%d%d%lf%lf%lf\n", &at, &as, &athick, &awidth, &aht); } if (line_thickness > 1) OUTPUT (" \\pen{%.2lfpt}%%\n", do_pen (line_thickness)); /* filling or shading */ if (area_fill == FILL_BLACK) /* fill with black */ { OUTPUT (" \\polyfill"); } else if (area_fill < FILL_BLACK && area_fill > UNFILLED) /* shade */ { OUTPUT (" \\shadespace=%lfpt%%\n", dofill()); OUTPUT (" \\polyshade"); } else /* no fill or shade */ { if (line_style == SOLID_LINE) OUTPUT (" \\polyline"); else if (line_style == DASH_LINE) { OUTPUT (" \\dashlen=%lfpt%%\n", style_val); OUTPUT (" \\dashspace=%lfpt%%\n", style_val); OUTPUT (" \\polydash"); } else /* DOTTED_LINE */ { OUTPUT (" \\dashlen=%lfpt%%\n", DOT_SIZE); OUTPUT (" \\dashspace=%lfpt%%\n", style_val); OUTPUT (" \\polydash"); } } /* eps line is before points line, according to transfig source */ if (subtype == T_EPS_BOX) { next_src_line (figfp); sscanf (buf, "%d%s", &eflag, epsfile); } OUTPUT ("{%%\n"); npts_read = read_pts (figfp); OUTPUT ("}\n"); if (line_thickness > 1) OUTPUT (" \\pen{%.2lfpt}%%\n", mfpen); return npts_read; } /* polyline */ /* Spline objects */ /* Subtypes: */ /* Normal splines (`B-splines') are here incorrectly implemented */ #define T_OPEN_NORMAL 0 #define T_CLOSED_NORMAL 1 #define T_OPEN_INTERPOLATED 2 #define T_CLOSED_INTERPOLATED 3 int spline #ifdef __STDC__ (FILE * figfp) #else (figfp) FILE * figfp; #endif { int n; int npts_read; int type, line_style, subtype, line_thickness, color, depth, pen, area_fill, fa, ba, at, as; double style_val, athick, awidth, aht; npts_read = 0; n = sscanf (buf, "%d%d%d%d%d%d%d%d%lf%d%d", &type, &subtype, &line_style, &line_thickness, &color, &depth, &pen, &area_fill, &style_val, &fa, &ba); if (n != N_SPLINE) { put_msg ("Malformed spline"); return npts_read; } if (fa) { next_src_line (figfp); sscanf (buf, "%d%d%lf%lf%lf\n", &at, &as, &athick, &awidth, &aht); } if (ba) { next_src_line (figfp); sscanf (buf, "%d%d%lf%lf%lf\n", &at, &as, &athick, &awidth, &aht); } if (line_thickness > 1) OUTPUT (" \\pen{%.2lfpt}%%\n", do_pen (line_thickness)); if (subtype == T_OPEN_NORMAL || subtype == T_CLOSED_NORMAL) /* B-spline - very roughly */ { if (subtype == T_OPEN_NORMAL) /* open B-spline */ { OUTPUT (" \\curve"); } else if (subtype == T_CLOSED_NORMAL) /* closed B-spline */ { if (area_fill == FILL_BLACK) /* fill with black */ { OUTPUT (" \\cyclefill"); } else if (area_fill < FILL_BLACK && area_fill > UNFILLED) /* shade */ { OUTPUT (" \\shadespace=%lfpt%%\n", dofill()); OUTPUT (" \\cycleshade"); } else /* neither fill nor shade */ { OUTPUT (" \\cyclic"); } } /* control points - wrongly treated for B-spline */ OUTPUT ("{%%\n"); npts_read = read_pts (figfp); OUTPUT ("}\n"); } else if (subtype == T_OPEN_INTERPOLATED || subtype == T_CLOSED_INTERPOLATED) { OUTPUT (" \\mfcmd {%%\n"); if (subtype == T_OPEN_INTERPOLATED) /* open I-spline */ { OUTPUT (" ispline (false)"); } else if (subtype == T_CLOSED_INTERPOLATED) /* closed I-spline */ { if (area_fill == FILL_BLACK) /* fill with black */ { OUTPUT (" isplineshade (0)"); } else if (area_fill < FILL_BLACK && area_fill > UNFILLED) /* shade */ { OUTPUT (" isplineshade (%lfpt)", dofill()); } else /* neither fill nor shade */ { OUTPUT (" ispline (true)"); } } /* interpolation ("key") points */ OUTPUT (" ( \n"); npts_read = read_pts (figfp); OUTPUT (" ) \n"); /* control points */ OUTPUT (" ( \n"); npts_read = controls (npts_read, figfp); OUTPUT (" ) \n"); OUTPUT (" }\n"); /* end "\mfcmd" */ } if (line_thickness > 1) OUTPUT (" \\pen{%.2lfpt}\n", mfpen); return npts_read; } /* spline */ /* Sentinel signalling end of coordinate pair list */ #define END_COORD 9999 int read_pts #ifdef __STDC__ (FILE * figfp) #else (figfp) FILE * figfp; #endif { extern MsgType Message; char * bufp = buf; /* pointer to current buffer position */ int more = 1; /* any more coordinates? */ int npts_read = 0; /* number of coordinate pairs */ /* Read key points line from Fig file into buffer */ next_src_line (figfp); while (more) { int x, y; int n; /* read X and Y coordinates of a point */ if (!get_int (&bufp, &x)) { put_msg ("Missing X coordinate (expect an integer),"); sprintf (Message, " point %d anticipated,\n", npts_read+1); Lwrite (Message); sprintf (Message, " coord. after byte %ld in line.\n", bufp - buf); Lwrite (Message); Lflush (); more = 0; } else if (!get_int (&bufp, &y)) { put_msg ("Missing Y coordinate (expect an integer),"); sprintf (Message, " amidst point %d,\n", npts_read+1); Lwrite (Message); sprintf (Message, " coord. after byte %ld in line.\n", bufp - buf); Lwrite (Message); Lflush (); more = 0; } else if (x == END_COORD) { if (y != END_COORD) { sprintf (Message, "final Y coordinate is not %d", END_COORD); put_msg (Message); } more = 0; } else { if (bbbegun) { bxl = MIN (bxl, x); bxu = MAX (bxu, x); byl = MIN (byl, y); byu = MAX (byu, y); } else { bxl = bxu = x; byl = byu = y; bbbegun = 1; } /* write key point coordinates to TeX file */ if (npts_read > 0) OUTPUT (",\n"); OUTPUT (" (%lf, %lf)", xt(x), yt(y)); ++ npts_read; more = 1; } } if (npts_read < 1) { put_msg ("No key points"); } return npts_read; } /* read_pts */ int buffer_empty #ifdef __STDC__ (char * bp) #else int (bp) char * bp; #endif { int empty = FALSE; if (bp == NULL) empty = TRUE; else { while (*bp != '\0' && isspace (*bp)) ++ bp; empty = (*bp == '\0'); } return empty; } /* buffer_empty */ int controls #ifdef __STDC__ (int npts, FILE * figfp) #else (npts, figfp) int npts; FILE * figfp; #endif /* npts = number of ordinary points */ { extern MsgType Message; int ncontrols = 0; /* number of control points, should be 2*npts. */ int more = TRUE; /* any more coordinates? */ int i; char * bufp = buf; /* pointer to current buffer position */ /* Read control points line from Fig file into buffer */ next_src_line (figfp); for (i=0; more && i < npts; i++) { double lx, ly, rx, ry; /* control points are floating point */ int n; /* read X and Y coordinates of left and right control points */ if (!get_double (figfp, &bufp, &lx)) { put_msg ("Missing Left control X coordinate (expect a number),"); sprintf (Message, " for point %d, ", i+1); Lwrite (Message); sprintf (Message, "coord. after byte %ld in line.\n", bufp - buf); Lwrite (Message); Lflush (); more = FALSE; } else if (!get_double (figfp, &bufp, &ly)) { put_msg ("Missing Left control Y coordinate (expect a number),"); sprintf (Message, " for point %d, ", i+1); Lwrite (Message); sprintf (Message, "coord. after byte %ld in line.\n", bufp - buf); Lwrite (Message); Lflush (); more = FALSE; } else if (!get_double (figfp, &bufp, &rx)) { put_msg ("Missing Right control X coordinate (expect a number),"); sprintf (Message, " for point %d, ", i+1); Lwrite (Message); sprintf (Message, "coord. after byte %ld in line.\n", bufp - buf); Lwrite (Message); Lflush (); more = FALSE; } else if (!get_double (figfp, &bufp, &ry)) { put_msg ("Missing Right control Y coordinate (expect a number),"); sprintf (Message, " for point %d, ", i+1); Lwrite (Message); sprintf (Message, "coord. after byte %ld in line.\n", bufp - buf); Lwrite (Message); Lflush (); more = FALSE; } else { if (bbbegun) { bxl = MIN (bxl, lx); bxl = MIN (bxl, rx); bxu = MAX (bxu, lx); bxu = MAX (bxu, rx); byl = MIN (byl, ly); byl = MIN (byl, ry); byu = MAX (byu, ly); byu = MAX (byu, ry); } else { bxl = MIN (lx, rx); bxu = MAX (lx, rx); byl = MIN (ly, ry); byu = MAX (ly, ry); bbbegun = 1; } /* write control point coordinates to TeX file */ if (ncontrols > 0) OUTPUT (",\n"); OUTPUT (" (%lf, %lf), (%lf, %lf)", xt(lx), yt(ly), xt(rx), yt(ry)); ++ ncontrols; more = TRUE; } /* (outer) fi */ } /* end (for) loop */ if (ncontrols < 1) { put_msg ("No control points"); } return ncontrols; } /* controls */ /* Text objects */ /* Maximum length of text */ #define TEXT_SLEN 80 /* text justification (text subtypes) */ #define T_LEFT_JUSTIFIED 0 #define T_CENTER_JUSTIFIED 1 #define T_RIGHT_JUSTIFIED 2 /* (orthogonal) properties of text, stored as separate bits in text_flags */ #define NO_TEXT 0 #define RIGID_TEXT 1 #define SPECIAL_TEXT 2 #define PSFONT_TEXT 4 #define HIDDEN_TEXT 8 /* default font values */ #define DEFAULT_FONT_0 0 #define DEFAULT_FONT_1 (-1) /* general fonts */ /* `modern' means `sans serif' */ #define ROMAN 1 #define BOLD 2 #define ITALICS 3 #define MODERN 4 #define TYPEWRITER 5 /* PostScript fonts (the common 35) */ #define TR 1 #define TI 2 #define TB 3 #define TBI 4 #define AG 5 #define AGBO 6 #define AGD 7 #define AGDO 8 #define BKL 9 #define BKLI 10 #define BKD 11 #define BKDI 12 #define COUR 13 #define COURO 14 #define COURB 15 #define COURBI 16 #define HV 17 #define HVO 18 #define HVB 19 #define HVBO 20 #define HVN 21 #define HVNO 22 #define HVNB 23 #define HVNBO 24 #define NCR 25 #define NCI 26 #define NCB 27 #define NCBI 28 #define PLR 29 #define PLI 30 #define PLB 31 #define PLBI 32 #define SYMBOL 33 #define ZCMI 34 #define ZDING 35 int text #ifdef __STDC__ (FILE * figfp) #else (figfp) FILE * figfp; #endif { extern MsgType Message; int type, subtype, font; double font_size; int pen, color, depth; double angle; int text_flags; double ht, len; int x, y; char text[TEXT_SLEN+1]; /* alignment of text (baseline left is the default) */ char * orient = "bl"; /* Full name of font requested in the Fig file */ char * font_name = "DEFAULT FONT"; /* TeX font used to simulate font requested in the Fig file */ char * tex_font = "\\tt"; /* _estimated_ text bounding box */ int txl, txu, tyl, tyu; int n; /* eat whitespace before text string */ n = sscanf (buf, "%d%d%d%lf%d%d%d%lf%d%lf%lf%d%d %[^\1]", &type, &subtype, &font, &font_size, &pen, &color, &depth, &angle, &text_flags, &ht, &len, &x, &y, text); if (n != N_TEXT) { put_msg ("Bad Text"); return (0); /* Like a zero length string - a doubtful value? */ } switch (subtype) { case T_LEFT_JUSTIFIED: orient = "bl"; txl = x; break; case T_CENTER_JUSTIFIED: orient = "bc"; txl = x - len/2; break; default: sprintf (Message, "\"%d\" is an unknown text justification\n", subtype); put_msg (Message); /* default to right justification */ case T_RIGHT_JUSTIFIED: orient = "br"; txl = x - len; break; break; } if (text_flags & PSFONT_TEXT) { /* PostScript fonts */ switch (font) { case DEFAULT_FONT_0: case DEFAULT_FONT_1: font_name = "DEFAULT PostScript"; tex_font = "\\tt"; break; case TR: font_name = "Times-Roman"; tex_font = "\\rm"; break; case TI: font_name = "Times-Italic"; tex_font = "\\it"; break; case TB: font_name = "Times-Bold"; tex_font = "\\bf"; break; case TBI: font_name = "Times-Bold-Italic"; tex_font = "\\it"; break; case AG: font_name = "AvantGarde"; tex_font = "\\rm"; break; case AGBO: font_name = "AvantGarde-BookOblique"; tex_font = "\\sl"; break; case AGD: font_name = "AvantGarde-Demi"; tex_font = "\\bf"; break; case AGDO: font_name = "AvantGarde-DemiOblique"; tex_font = "\\sl"; break; case BKL: font_name = "Bookman-Light"; tex_font = "\\rm"; break; case BKLI: font_name = "Bookman-LightItalic"; tex_font = "\\it"; break; case BKD: font_name = "Bookman-Demi"; tex_font = "\\bf"; break; case BKDI: font_name = "Bookman-DemiItalic"; tex_font = "\\it"; break; case COUR: font_name = "Courier"; tex_font = "\\tt"; break; case COURO: font_name = "Courier-Oblique"; tex_font = "\\tt"; break; case COURB: font_name = "Courier-Bold"; tex_font = "\\tt"; break; case COURBI: font_name = "Courier-BoldItalic"; tex_font = "\\tt"; break; case HV: font_name = "Helvetica"; tex_font = "\\sf"; break; case HVO: font_name = "Helvetica-Oblique"; tex_font = "\\sf"; break; case HVB: font_name = "Helvetica-Bold"; tex_font = "\\sf"; break; case HVBO: font_name = "Helvetica-BoldOblique"; tex_font = "\\sf"; break; case HVN: font_name = "Helvetica-Narrow"; tex_font = "\\sf"; break; case HVNO: font_name = "Helvetica-Narrow-Oblique"; tex_font = "\\sf"; break; case HVNB: font_name = "Helvetica-Narrow-Bold"; tex_font = "\\sf"; break; case HVNBO: font_name = "Helvetica-Narrow-BoldOblique"; tex_font = "\\sf"; break; case NCR: font_name = "NewCenturySchlbk-Roman"; tex_font = "\\rm"; break; case NCI: font_name = "NewCenturySchlbk-Italic"; tex_font = "\\it"; break; case NCB: font_name = "NewCenturySchlbk-Bold"; tex_font = "\\bf"; break; case NCBI: font_name = "NewCenturySchlbk-BoldItalic"; tex_font = "\\it"; break; case PLR: font_name = "Palatino-Roman"; tex_font = "\\rm"; break; case PLI: font_name = "Palatino-Italic"; tex_font = "\\it"; break; case PLB: font_name = "Palatino-Bold"; tex_font = "\\bf"; break; case PLBI: font_name = "Palatino-BoldItalic"; tex_font = "\\it"; break; case SYMBOL: /* wrong characters, but what to do? */ font_name = "Symbol"; tex_font = "\\tt"; break; case ZCMI: /* wrong characters, but what to do? */ font_name = "ZapfChancery-MediumItalic"; tex_font = "\\tt"; break; case ZDING: /* wrong characters, but what to do? */ font_name = "ZapfDingbats"; tex_font = "\\tt"; break; default: /* fall back to typewriter type */ font_name = "INVALID PostScript"; tex_font = "\\tt"; break; } } else { /* general fonts */ switch (font) { case DEFAULT_FONT_0: case DEFAULT_FONT_1: font_name = "DEFAULT Fig"; tex_font = "\\tt"; break; case ROMAN: font_name = "Roman"; tex_font = "\\rm"; break; case BOLD: font_name = "Bold"; tex_font = "\\bf"; break; case ITALICS: font_name = "Italics"; tex_font = "\\it"; break; case MODERN: font_name = "Modern (sans serif)"; tex_font = "\\sf"; break; case TYPEWRITER: font_name = "Typewriter"; tex_font = "\\tt"; break; default: /* fall back to typewriter type */ font_name = "INVALID Fig"; tex_font = "\\tt"; break; } } /* completion of calculation of _estimated_ text bounding box */ txu = txl + len; tyl = y; tyu = tyl + ht; /* _estimated_ Bounding Box for picture, including this text */ if (bbbegun) { bxl = MIN (bxl, txl); bxu = MAX (bxu, txu); byl = MIN (byl, tyl); byu = MAX (byu, tyu); } else { bxl = txl; bxu = txu; byl = tyl; byu = tyu; bbbegun = 1; } OUTPUT ("%% - %s font at %.3lf pt\n", font_name, font_size); /* mfpic label */ OUTPUT (" \\label[%s]{%lf}{%lf}{%s %s}\n", orient, xt(x), yt(y), tex_font, text); return (strlen (text)); } /* text */ /* Arc objects */ /* The only arc subtype in Fig 2.1 is a three-point arc */ #define T_3_POINT_ARC 1 int arc #ifdef __STDC__ (FILE * figfp) #else (figfp) FILE * figfp; #endif { int n; int type, subtype, line_style, line_thickness, color, depth, pen, fill; double style_val; int dir, fa, ba; double cx, cy; int x1, y1, x2, y2, x3, y3; n = sscanf (buf, "%d%d%d%d%d%d%d%d%lf%d%d%d%lf%lf%d%d%d%d%d%d", &type, &subtype, &line_style, &line_thickness, &color, &depth, &pen, &fill, &style_val, &dir, &fa, &ba, &cx, &cy, &x1, &y1, &x2, &y2, &x3, &y3); if (fa) next_src_line (figfp); if (ba) next_src_line (figfp); if (n != N_ARC) { put_msg ("Malformed arc"); return n; } /* arc bounding box */ { int cxl, cxu, cyl, cyu; int axl, axu, ayl, ayu; int dx1 = x1 - cx; int dy1 = y1 - cy; double r = hypot (dx1, dy1); double cos1 = dx1 / r; double sin1 = dy1 / r; double cos3 = (x3 - cx) / r; double sin3 = (y3 - cy) / r; int ir = (int) ceil (r); /* left, right, bottom and top of circle of which arc is part */ cxl = cx - ir; cxu = cx + ir; cyl = cy - ir; cyu = cy + ir; /* ! temporary, crude estimate, based on including whole circle */ axl = cxl; axu = cxu; ayl = cyl; ayu = cyu; if (bbbegun) { bxl = MIN (bxl, axl); bxu = MAX (bxu, axu); byl = MIN (byl, ayl); byu = MAX (byu, ayu); } else { bxl = axl; bxu = axu; byl = ayl; byu = ayu; bbbegun = 1; } } if (line_thickness > 1) OUTPUT (" \\pen{%.2lfpt}\n", do_pen (line_thickness)); OUTPUT (" \\mfcmd {arcthree((%lf,%lf), (%lf,%lf), (%lf,%lf))} \n", xt(x1), yt(y1), xt(x2), yt(y2), xt(x3), yt(y3)); if (line_thickness > 1) OUTPUT (" \\pen{%.2lfpt}\n", mfpen); return n; } /* arc */ /* Compound objects */ /* Write a TeX comment, and, if necessary, extend the bounding box */ int compound #ifdef __STDC__ (FILE * figfp) #else (figfp) FILE * figfp; #endif { int cxl, cxu, cyl, cyu; int n; n = sscanf (buf, "%d%d%d%d", &cxl, &cxu, &cyl, &cyu); if (n != N_COMPOUND) { put_msg ("Malformed compound"); return n; } OUTPUT ("%% Compound.\n"); if (bbbegun) { bxl = MIN (bxl, cxl); bxu = MAX (bxu, cxu); byl = MIN (byl, cyl); byu = MAX (byu, cyu); } else { bxl = cxl; bxu = cxu; byl = cyl; byu = cyu; bbbegun = 1; } return n; } /* compound */ /* End compound objects */ /* Only write a comment */ int end_compound #ifdef __STDC__ (FILE * figfp) #else (figfp) FILE * figfp; #endif { OUTPUT ("%% End Compound.\n"); } /* end_compound */ /* return name of object subtype from given type and subtype codes */ char * subtype_name #ifdef __STDC__ (int type, int subtype) #else (type, subtype) int type, subtype; #endif { char * sub_name = "unknown"; switch (type) { case O_ELLIPSE: switch (subtype) { case T_ELLIPSE_BY_RAD: sub_name = "ellipse by radius"; break; case T_ELLIPSE_BY_DIA: sub_name = "ellipse by diameter"; break; case T_CIRCLE_BY_RAD: sub_name = "circle by radius"; break; case T_CIRCLE_BY_DIA: sub_name = "circle by diameter"; break; default: sub_name = "unknown ellipse"; break; } break; case O_POLYLINE: switch (subtype) { case T_POLYLINE: sub_name = "polyline"; break; case T_BOX: sub_name = "box"; break; case T_POLYGON: sub_name = "polygon"; break; case T_ARC_BOX: sub_name = "arc box"; break; case T_EPS_BOX: sub_name = "EPS box"; break; default: sub_name = "unknown polyline"; break; } break; case O_SPLINE: switch (subtype) { case T_OPEN_NORMAL: sub_name = "open normal spline (open B-spline)"; break; case T_CLOSED_NORMAL: sub_name = "closed normal spline (closed B-spline)"; break; case T_OPEN_INTERPOLATED: sub_name = "open interpolated spline"; break; case T_CLOSED_INTERPOLATED: sub_name = "open interpolated spline"; break; default: sub_name = "unknown spline"; break; } break; case O_TEXT: switch (subtype) { case T_LEFT_JUSTIFIED: sub_name = "left justified text"; break; case T_CENTER_JUSTIFIED: sub_name = "center justified text"; break; case T_RIGHT_JUSTIFIED: sub_name = "right justified text"; break; default: sub_name = "unknown text justification"; break; } break; case O_ARC: switch (subtype) { case T_3_POINT_ARC: sub_name = "three-point arc"; break; default: sub_name = "unknown arc"; break; } break; case O_COMPOUND: sub_name = "compound"; break; case O_END_COMPOUND: sub_name = "end compound"; break; default: sub_name = "unknown"; break; } return (sub_name); } /* subtype_name */ static int curchar = FIRST_CHAR; /* assignment here is not important */ Void finit (VOID) { curchar = char_code; OUTPUT ("%%\n"); OUTPUT ("%% gt fig2mfpic version %s for mfpic %s and graphbase %s\n", VERSION, MFPIC_VERSION, GRAPHBASE_VERSION); OUTPUT ("%% compiled as %s", progname); #ifdef __STDC__ OUTPUT (" from file %s on %s %s", __FILE__, __DATE__, __TIME__); #endif OUTPUT ("\n"); OUTPUT ("%% --- Preamble\n"); OUTPUT ("%%\n"); /* test whether drawing macros (eg, "mfpic.tex") have been input */ OUTPUT ("\\ifx\\opengraphsfile\\undefined\n"); /* if they have not, assume output is intended as a stand-alone TeX file */ OUTPUT (" \\def\\endfigtomfpic{\\par\\vfill\\supereject\\end}"); OUTPUT (" %% like bye, but not outer.\n"); OUTPUT (" \\message{You didn't input the drawing macros,"); OUTPUT (" so, Gw, I will.}\n"); OUTPUT (" \\message{NB: I'll exit after closegraphsfile.}\n"); OUTPUT ("%%\n"); /* input drawing macros now */ OUTPUT (" \\input %s\n", draw_macros); OUTPUT ("%%\n"); /* of course, the assumption might be wrong */ /* but if the drawing macros were previously input */ OUTPUT ("\\else\n"); /* then this is an "encapsulated TeX" :-) file */ OUTPUT (" \\let\\endfigtomfpic=\\relax\n"); OUTPUT ("\\fi\n"); OUTPUT ("\\def\\polyline{\\polycurve}\n"); OUTPUT ("%%\n"); OUTPUT ("\\opengraphsfile{%s}\n", mf_ofile); define_polydash(); } /* finit */ /* Augment the TeX and MF drawing macros with a dash polyline */ Void define_polydash (VOID) { #define BAD_KLUGE #ifdef BAD_KLUGE /* ! temporary partial attempt */ OUTPUT ("\\def\\polydash{\\dottedline}\n"); #else OUTPUT ("\\def\\polydash{%%\n"); OUTPUT (" \\mfcmd{%%\n"); /* ! need something substantial here */ OUTPUT (" \n"); OUTPUT (" }%%\n"); OUTPUT ("}%%\n"); #endif } /* define_polydash */ /* input picture <-> output character */ Void cinit (VOID) { if (nchar < MAXNCHAR) { bbbegun = 0; /* no bounding box estimate yet, for this picture */ /* comment : current input file, and corresponding output character */ OUTPUT ("%%\n%% \"%s\" (char %d)\n%%\n", curfigfile, curchar); /* X, Y drawing units (pt), picture bounding box (drawing units) */ OUTPUT ("\\mfpic[%.4lf][%.4lf]{%.4lf}{%.4lf}{%.4lf}{%.4lf}\n", xscale / oupi * PT_PER_INCH, yscale / oupi * PT_PER_INCH, xl, xu, yl, yu); } } /* cinit */ #define DSWAP(x,y) {double temp = x; x = y; y = temp;} Void cfin (VOID) { OUTPUT ("\\endmfpic\n"); /* bounding box comment, to replace estimate in cinit() */ if (bbbegun) { double pxl, pxu, pyl, pyu; int xsgn = (xscale / oupi * PT_PER_INCH < 0.0 ? -1 : 1); int ysgn = (yscale / oupi * PT_PER_INCH < 0.0 ? -1 : 1); pxl = xt(bxl); pxu = xt(bxu); pyl = yt(byl); pyu = yt(byu); if (xsgn * pxl > xsgn * pxu) DSWAP (pxl, pxu); if (ysgn * pyl > ysgn * pyu) DSWAP (pyl, pyu); OUTPUT ("%% Bounding box is now estimated to be:\n"); OUTPUT ("%% \\mfpic[%.4lf][%.4lf]{%.4lf}{%.4lf}{%.4lf}{%.4lf}\n", xscale / oupi * PT_PER_INCH, yscale / oupi * PT_PER_INCH, pxl, pxu, pyl, pyu); } OUTPUT ("%%\n%% end \"%s\" (char %d)\n%%\n", curfigfile, curchar); ++ nchar; ++ curchar; } /* cfin */ Void ffin (VOID) { if (nchar > 0) { OUTPUT ("\\closegraphsfile\n"); OUTPUT ("\\endfigtomfpic\n"); } } /* ffin */ int get_line #ifdef __STDC__ (FILE * figfp) #else (figfp) FILE * figfp; #endif { /* Read next line of Fig file figfp, including linefeed, */ /* into buffer of at most BUF_SIZE characters. */ int retval; if (fgets (buf, BUF_SIZE, figfp) == NULL) { /* No line */ retval = FALSE; } else { /* Count all lines */ ++ linenum; if (debug) { display_line(); } retval = TRUE; } return retval; } /* get_line */ int next_src_line #ifdef __STDC__ (FILE * figfp) #else (figfp) FILE * figfp; #endif { /* Read next non-empty, non-comment line of Fig file figfp, if any */ int flag = 0; while (!flag) { if (!get_line (figfp)) flag = -1; /* No more lines */ else if (*buf != '\n' && *buf != '#') flag = 1; /* Good! A non-empty, non-comment line */ /* _Skip_ empty and comment lines */ } return flag; /* 1 or -1 */ } /* next_src_line */ Void display_line (VOID) { MsgType LineNum; sprintf (LineNum, "Line %d: ", linenum); Lwrite (LineNum); Lwrite (buf); Lflush (); } /* display_line */ int get_int #ifdef __STDC__ (char ** bufpa, int * ya) #else (bufpa, ya) char ** bufpa; int * ya; #endif /* bufpa = Address of (a buffer pointer : I/O). */ /* ya = Address of (a int : O). */ { /* Skip leading blanks of *bufpa, then try to read a decimal */ /* integer from it into ya, advancing bufpa while successful. */ /* Return TRUE if an integer is found, FALSE otherwise. */ /*............................................................. */ /* It's hard to believe that traditional K&R has no convenient */ /* library function for this extremely common task. */ /* OR something like fscanf, that uses a data structure to keep */ /* track of its current position, and has a variety of formats. */ /*............................................................. */ int found = FALSE; if (bufpa == NULL || *bufpa == NULL || ya == NULL) { put_msg ("About to dereference a NULL pointer"); found = FALSE; } else { char * start = *bufpa; *ya = (int) strtol (start, bufpa, 10); if (*bufpa != start) found = TRUE; } return (found); } /* get_int */ int get_double #ifdef __STDC__ (FILE * figfp, char ** bufpa, double * ya) #else (figfp, bufpa, ya) FILE * figfp; char ** bufpa; double * ya; #endif /* figfp = Address of (a FILE buffer : I/O). */ /* bufpa = Address of (a buffer pointer : I/O). */ /* ya = Address of (a double : O). */ { /* Skip leading blanks of *bufpa, then try to read a floating */ /* point number from it into ya, advancing bufpa while successful. */ /* Return TRUE if a number is found, FALSE otherwise. */ int found = FALSE; if (bufpa == NULL || *bufpa == NULL || ya == NULL) { put_msg ("About to dereference a NULL pointer"); found = FALSE; } else { char * start; while (buffer_empty (*bufpa)) { next_src_line (figfp); *bufpa = buf; } start = *bufpa; *ya = strtod (start, bufpa); if (*bufpa != start) found = TRUE; } return (found); } /* get_double */ /* end of fig2mfpic of Wed 8 Jun 1994 */