--- /dev/null
+/* Hello, Emacs, this is -*-C-*-
+ * $Id: mif.trm,v 1.33 2006/07/21 02:35:47 sfeam Exp $
+ */
+
+/* GNUPLOT -- mif.trm */
+
+/*[
+ * Copyright 1992, 1993, 1998, 2004
+ *
+ * Permission to use, copy, and distribute this software and its
+ * documentation for any purpose with or without fee is hereby granted,
+ * provided that the above copyright notice appear in all copies and
+ * that both that copyright notice and this permission notice appear
+ * in supporting documentation.
+ *
+ * Permission to modify the software is granted, but not the right to
+ * distribute the complete modified source code. Modifications are to
+ * be distributed as patches to the released version. Permission to
+ * distribute binaries produced by compiling modified sources is granted,
+ * provided you
+ * 1. distribute the corresponding source modifications from the
+ * released version in the form of a patch file along with the binaries,
+ * 2. add special version identification to distinguish your version
+ * in addition to the base release version number,
+ * 3. provide your name and address as the primary contact for the
+ * support of your modified version, and
+ * 4. retain our contact information in regard to use of the base
+ * software.
+ * Permission to distribute the released version of the source code along
+ * with corresponding source modifications in the form of a patch file is
+ * granted with same provisions 2 through 4 for binary distributions.
+ *
+ * This software is provided "as is" without express or implied warranty
+ * to the extent permitted by applicable law.
+]*/
+
+/*
+ * This file is included by ../term.c.
+ *
+ * This terminal driver was developed for
+ * gnuplot for unix version 3.0 (patchlevel 1)
+ * gnuplot for unix version 3.2 (patchlevel 2)
+ *
+ * This terminal driver supports:
+ * Frame Maker MIF format version 3.00
+ *
+ * Options for this terminal driver (set terminal mif [options]):
+ * colour / Draw primitives with line types >= 0 in colour (sep. 2-7)
+ * monochrome Draw primitives in black (sep. 0)
+ *
+ * polyline / Draw lines as continuous curves
+ * vectors Draw lines as collections of vectors
+ *
+ * help / ? Print short usage description on stderr
+ *
+ * Properties for this terminal driver:
+ * -Gnuplot size of worksheet: MIF_XMAX * MIF_YMAX
+ * -Unit in MIF output: cm
+ * -Plot primitives with the same pen will
+ * be grouped in the same MIF group.
+ * -Plot primitives with line types >= 0
+ * will as default be drawn in colour.
+ * -Lines are plotted as collections of
+ * vectors, or as continuous lines (default)
+ * -Plot primitives in a plot will be in a
+ * Frame in MIF. Several plot Frames will
+ * be collected in one large Frame.
+ * -Point size of MIF output characters: MIF_PSIZE
+ * -Used font for MIF output characters: Times
+ * -Supports vertical text
+ * -points and dots as characters
+ * -character formats for TextLines
+ *
+ * AUTHORS:
+ * Olof Franksson, Physics IV, KTH, S-100 44 Stockholm, Sweden
+ *
+ * NEW TERMINAL FORMAT: David C. Schooley
+
+ * COMMENTS:
+ * Send comments and/or suggestions to olof@fysik4.kth.se
+ *
+ * CHANGES:
+ * Changed to new terminal format 9/29/95 schooley@ee.gatech.edu
+ * Changed order of routine declarations. olof@fysik4.kth.se
+ * Changed mechanism for pen pattern selection. kssingvo@immd4.informatik.uni-erlangen.de
+ * Support for vertical text. kssingvo@immd4.informatik.uni-erlangen.de
+ * Fixed plot bug for "set size XS,YS", XS/YS > 1. olof@fysik4.kth.se
+ * Support colored text merritt@u.washington.edu
+ * Support box fill and pattern fill merritt@u.washington.edu
+ *
+ */
+
+#include "driver.h"
+
+#ifdef TERM_REGISTER
+register_term(mif)
+#endif
+
+
+
+#ifdef TERM_PROTO
+TERM_PUBLIC void MIF_init __PROTO((void));
+TERM_PUBLIC void MIF_graphics __PROTO((void));
+TERM_PUBLIC void MIF_text __PROTO((void));
+TERM_PUBLIC void MIF_linetype __PROTO((int linetype));
+TERM_PUBLIC void MIF_move __PROTO((unsigned int x, unsigned int y));
+TERM_PUBLIC void MIF_vector __PROTO((unsigned int x, unsigned int y));
+TERM_PUBLIC void MIF_put_text __PROTO((unsigned int x, unsigned int y, const char *str));
+TERM_PUBLIC int MIF_text_angle __PROTO((int ang));
+TERM_PUBLIC void MIF_reset __PROTO((void));
+TERM_PUBLIC void MIF_options __PROTO((void));
+TERM_PUBLIC int MIF_justify_text __PROTO((enum JUSTIFY mode));
+TERM_PUBLIC void MIF_point __PROTO((unsigned int x, unsigned int y, int number));
+TERM_PUBLIC void MIF_boxfill __PROTO((int style, unsigned int x1, unsigned int y1,
+ unsigned int width, unsigned int height));
+TERM_PUBLIC void MIF_filled_polygon __PROTO((int points, gpiPoint* corners));
+
+/** Coordinates **/
+/* The cast to float is not necessary because we are dividing by a float */
+/* On OSK the cast to a float is not allowed in a constant expression wich */
+/* is used by the declaration and initialization of mif_line */
+/* Converts gnuplot units to MIF units */
+#define GNP_TO_MIF(P) ((P) / 1000.0)
+/* Basic unit: 0.01 mm (15cm -> 15*10*100=15000) */
+#define MIF_XMAX 15000
+/* Basic unit: 0.01 mm (10cm -> 10*10*100=10000) */
+#define MIF_YMAX 10000
+
+#define MIF_XLAST (MIF_XMAX - 1)
+#define MIF_YLAST (MIF_YMAX - 1)
+
+static int insert_mif_line __PROTO((double fx, double fy));
+static int proc_group_id __PROTO((int group_id));
+static void free_mif_line __PROTO((void));
+static void put_mif_line __PROTO((void));
+static void MIF_set_font __PROTO((const char *));
+static void mif_put_point __PROTO((unsigned int x, unsigned int y, int np));
+
+#endif
+
+#ifndef TERM_PROTO_ONLY
+#ifdef TERM_BODY
+
+#ifndef cfree
+# define cfree free
+#endif
+
+static struct mif_line { /* Line point structure specification */
+ float fpos_x; /* Line point X coordinate */
+ float fpos_y; /* Y coordinate */
+ struct mif_line *next; /* Pointer to next line point */
+ struct mif_line *prev; /* Pointer to previous line point */
+} mif_line =
+{ /* Current position structure. Adjust for orign. Local for this file. */
+ GNP_TO_MIF(0),
+ GNP_TO_MIF(MIF_YLAST),
+ &mif_line,
+ &mif_line
+};
+
+/** Characters **/
+#define MIF_PSIZE 9 /* Point size of used characters */
+
+#define MIF_VCHAR (MIF_YMAX/31) /* Distance between rows (a guess) */
+#define MIF_HCHAR (MIF_XMAX/95) /* Distance between characters (a guess) */
+
+/** Scale marks **/
+#define MIF_VTIC (MIF_YMAX/150) /* Size of scale mark (vert) */
+#define MIF_HTIC (MIF_XMAX/225) /* Size of scale mark (hor) */
+
+/** Drawing properties **/
+static char mif_justify[64]; /* How to justify the used text */
+static char mif_pen[64], mif_pen_width[64], mif_separation[64]; /* How to plot */
+static char mif_textcolor[64]; /* EAM parallels separation */
+
+static int mif_text_ang = 0; /* Rotation angle of text */
+
+static int mif_fill_patterns[] = {7,12,3,0,9,8,14,13};
+#define MIF_FILL_SOLID 0
+#define MIF_FILL_NONE 15
+
+#define MIF_NPENS 16 /* Number of MIF pen types */
+static int mif_pentype = 0; /* Pen type to use. Also used to create groups for graphics */
+#define MIF_PEN_TO_GROUP(P) ( 1 + (P) ) /* Map pen type to group number. Must be >= 1 */
+
+static int mif_pattern_table[MIF_NPENS] =
+{ /* Table, which pattern should be used for drawing */
+ 0, /* border */
+ 1, /* not used */
+ 2, 3, 4, 8, 12, 13, /* other lines: functions, data, ... (5 is used for grid; 6,7 is (nearly) invisible) */
+ 5, /* grid */
+ 9, 10, 11, 12, 13, 14, 15 /* not used */
+};
+
+/** MIF groups administration **/
+#define MIF_NGROUP_ID 20
+static struct mif_group_id {
+ int group_existance;
+/* This group id should generate a MIF group */
+#define MIF_GROUP_EXISTS 1
+/* This group id should not generate a MIF group */
+#define MIF_GROUP_NOT_EXISTS 0
+
+ int group_id;
+#define MIF_INVALID_GROUP_ID 0 /* An invalid MIF group ID */
+
+} mif_group_id[MIF_NGROUP_ID]; /* List of used group ID:s and corresponding MIF groups existance */
+
+/** Semaphores **/
+static int mif_initialized = 0; /* != 0 when output is active */
+static int mif_in_frame = 0; /* != 0 when inside a plot frame */
+static int mif_frameno = -1; /* Current frame number */
+static int mif_colour = TRUE; /* == TRUE when colour should be used */
+static int mif_polyline = TRUE; /* == TRUE when lines are drawn as continuous curves */
+
+struct mpt { /* point definition structure */
+ int chr; /* character for point */
+ float x_offset, y_offset; /* offset for vertical positioning */
+ char *font; /* font */
+};
+
+static char zgnuplot[] = "ZGnuplot"; /* character formats */
+static char zgnuplotp[] = "ZGnuplotP";
+static char zgnuplotd[] = "ZGnuplotD";
+static const char *mif_font = NULL; /* actual character format */
+
+static struct mpt mpt[POINT_TYPES + 1] =
+{ /* point definition data */
+ {'.', 0.000, 0.005, zgnuplotd, /* dot */ },
+
+ {'G', 0.002, 0.084, zgnuplotp, /* diamond */ },
+ {';', 0.002, 0.084, zgnuplotp, /* plus */ },
+ {'n', 0.002, 0.084, zgnuplotp, /* box */ },
+ {'5', 0.002, 0.084, zgnuplotp, /* X */ },
+ {'s', 0.002, 0.062, zgnuplotp, /* triangle */ },
+ {'K', 0.005, 0.075, zgnuplotp, /* star */ },
+};
+
+/* diamond is offset 0, dot is offset -1 */
+static struct mpt *mif_point = &(mpt[1]);
+
+
+/** Declaration of routine/s for internal use **/
+static int insert_mif_line __PROTO((double fx, double fy));
+static int proc_group_id __PROTO((int group_id));
+
+enum MIF_id {
+ MIF_MONOCHROME, MIF_COLOR, MIF_VECTORS, MIF_POLYLINE, MIF_HELP,
+ MIF_OTHER
+};
+
+static struct gen_table MIF_opts[] =
+{
+ { "m$onochrome", MIF_MONOCHROME },
+ { "c$olor", MIF_COLOR },
+ { "c$olour", MIF_COLOR },
+ { "v$ectors", MIF_VECTORS },
+ { "p$olyline", MIF_POLYLINE },
+ { "h$elp", MIF_HELP },
+ { "?$", MIF_HELP },
+ { NULL, MIF_OTHER }
+};
+
+/** Routine/s **/
+
+/* Called when this terminal type is set in order to parse options */
+TERM_PUBLIC void
+MIF_options()
+{
+ while (!END_OF_COMMAND) {
+ switch(lookup_table(&MIF_opts[0],c_token)) {
+ /* Colour options */
+ case MIF_MONOCHROME:
+ mif_colour = FALSE;
+ c_token++;
+ break;
+ case MIF_COLOR:
+ mif_colour = TRUE;
+ c_token++;
+ break;
+ /* Curve options */
+ case MIF_VECTORS:
+ mif_polyline = FALSE;
+ c_token++;
+ break;
+ case MIF_POLYLINE:
+ mif_polyline = TRUE;
+ c_token++;
+ break;
+ /* Short help */
+ case MIF_HELP:
+ case MIF_OTHER:
+ default:
+ fprintf(stderr, "\
+Usage: set terminal mif [options]\n\
+\toptions:\n\
+\t\tcolour / Draw primitives with line types >= 0 in colour (sep. 2-7)\n\
+\t\tmonochrome Draw primitives in black (sep. 0)\n\n\
+\t\tpolyline / Draw lines as continuous curves\n\
+\t\tvectors Draw lines as collections of vectors\n\n\
+\t\thelp / ? Print short usage description on stderr\n");
+ c_token++;
+ break;
+ }
+ }
+ sprintf(term_options, "%s %s",
+ (mif_colour == TRUE) ? "colour" : "monochrome",
+ (mif_polyline == TRUE) ? "polyline" : "vectors");
+}
+
+/* Deallocate the used line structure elements */
+static void
+free_mif_line()
+{
+ struct mif_line *tline;
+
+ while (mif_line.prev != &mif_line) {
+ /* Unlink */
+ tline = mif_line.prev;
+ mif_line.prev = mif_line.prev->prev;
+ mif_line.prev->next = &mif_line;
+
+ /* Deallocate */
+ free(tline);
+ }
+
+ /* Make sure that the list will be empty */
+ mif_line.prev = &mif_line;
+ mif_line.next = &mif_line;
+}
+
+/* Draw the pending line. Change current position. */
+static void
+put_mif_line()
+{
+ int np, i;
+ struct mif_line *tline;
+
+ /* Process if inside a Frame */
+ if (mif_initialized != 0 && mif_in_frame != 0) {
+
+ /* Count the number of available points */
+ for (tline = mif_line.next, np = 1; tline != &mif_line; tline = tline->next, np++);
+
+ /* Draw line (at least two points) */
+ if (np >= 2) {
+
+ /* Line preamble */
+ fprintf(gpoutfile, "\t<PolyLine <GroupID %d> %s %s %s <Fill 15>\n",
+ MIF_PEN_TO_GROUP(mif_pentype), mif_pen, mif_pen_width, mif_separation);
+
+ /* Draw the line elements */
+ fprintf(gpoutfile, "\t\t<NumPoints %d> ", np);
+ for (i = 0, tline = &mif_line; i < np; i++, tline = tline->next) {
+ if (i % 4 == 0)
+ fputs("\n\t\t", gpoutfile);
+ fprintf(gpoutfile, "<Point %.3f %.3f> ",
+ tline->fpos_x, tline->fpos_y);
+ }
+
+ /* Line post amble */
+ fputs("\n\t>\n", gpoutfile);
+
+ /* Register the used group ID */
+ proc_group_id(MIF_PEN_TO_GROUP(mif_pentype));
+
+ /* Avoid to redraw this. The MIF system should remember it. */
+ mif_pen[0] = '\0';
+ mif_pen_width[0] = '\0';
+ mif_separation[0] = '\0';
+
+ /* Move current position to end of line */
+ mif_line.fpos_x = mif_line.prev->fpos_x;
+ mif_line.fpos_y = mif_line.prev->fpos_y;
+
+ /* Restore the line */
+ free_mif_line();
+ }
+ } /* Line processed */
+}
+
+/* Filled box support - Ethan Merritt <merritt@u.washington.edu> */
+TERM_PUBLIC void
+MIF_boxfill(int style, unsigned int x1, unsigned int y1,
+ unsigned int width, unsigned int height)
+{
+ int fill_pattern;
+
+ int fillpar = style >> 4;
+ style &= 0xf;
+ switch (style) {
+ default:
+ case FS_EMPTY: fill_pattern = 7;
+ break;
+ case FS_SOLID: fill_pattern = MIF_FILL_SOLID;
+ break;
+ case FS_PATTERN:fill_pattern = mif_fill_patterns[fillpar % 8];
+ break;
+ }
+
+ /* Object preamble */
+ fprintf(gpoutfile, "\t<Rectangle <GroupID %d> %s\n",
+ MIF_PEN_TO_GROUP(mif_pentype), mif_separation);
+
+ /* Set fill type */
+ fprintf(gpoutfile, "\t\t<Fill %d>\n", fill_pattern);
+
+ /* Draw the box */
+ fprintf(gpoutfile, "\t\t<ShapeRect %.3f %.3f %.3f %.3f>\n",
+ GNP_TO_MIF(x1), GNP_TO_MIF(MIF_YLAST - (y1+height)),
+ GNP_TO_MIF(width), GNP_TO_MIF(height));
+
+ /* End of object */
+ fputs("\n\t>\n", gpoutfile);
+
+ /* Register the used group ID */
+ proc_group_id(MIF_PEN_TO_GROUP(mif_pentype));
+
+}
+
+/* Filled polygon. Ethan Merritt <merritt@u.washington.edu> */
+TERM_PUBLIC void
+MIF_filled_polygon(int points, gpiPoint* corners)
+{
+ int i;
+
+ /* Object preamble */
+ fprintf(gpoutfile, "\t<Polygon <GroupID %d>\n",
+ MIF_PEN_TO_GROUP(mif_pentype));
+
+ /* Set fill type */
+ fprintf(gpoutfile, "\t\t<Fill %d>\n", MIF_FILL_SOLID);
+
+ /* Draw the line elements */
+ fprintf(gpoutfile, "\t\t<NumPoints %d> ", points);
+ for (i=0; i<points; i++) {
+ fprintf(gpoutfile, "<Point %.3f %.3f> ",
+ GNP_TO_MIF(corners[i].x),
+ GNP_TO_MIF(MIF_YLAST - corners[i].y));
+ }
+
+ /* End of object */
+ fputs("\n\t>\n", gpoutfile);
+
+ /* Register the used group ID */
+ proc_group_id(MIF_PEN_TO_GROUP(mif_pentype));
+
+}
+
+/* Draw a point */
+static void
+mif_put_point(unsigned int x, unsigned int y, int np)
+{
+ /* Process if inside a Frame */
+ if (mif_initialized != 0 && mif_in_frame != 0) {
+
+ /* Draw pending line */
+ if (mif_polyline == TRUE)
+ put_mif_line();
+
+ /* Adjust current position for text-graphics alignment */
+ MIF_move(x, y);
+
+ /* center text */
+ MIF_justify_text(CENTRE);
+
+ /* Draw the point */
+ fprintf(gpoutfile, "\t<TextLine <GroupID %d> %s\n",
+ MIF_PEN_TO_GROUP(mif_pentype),
+ mif_textcolor);
+
+ MIF_set_font(mif_point[np].font);
+
+ fprintf(gpoutfile, "\t\t<TLOrigin %.3f %.3f> %s <String `%c'>\n",
+ mif_line.fpos_x + mif_point[np].x_offset,
+ mif_line.fpos_y + mif_point[np].y_offset,
+ mif_justify,
+ mif_point[np].chr);
+ fputs("\t>\n", gpoutfile);
+
+ /* Register the used group ID */
+ proc_group_id(MIF_PEN_TO_GROUP(mif_pentype));
+
+ /* Avoid to redraw this. The MIF system should remember it. */
+ mif_justify[0] = '\0';
+
+ } /* Point processed */
+}
+
+
+/*
+ * draw points
+ */
+TERM_PUBLIC void
+MIF_point(unsigned int x, unsigned int y, int number)
+{
+ if (number < 0) { /* dot */
+ number = -1;
+ } else { /* point */
+ number %= POINT_TYPES;
+ }
+ mif_put_point(x, y, number);
+}
+
+
+/* Set up a MIF output file */
+TERM_PUBLIC void
+MIF_init()
+{
+ int i;
+
+ /* Process if not inside a MIF file and Frame */
+ if (mif_initialized == 0 && mif_in_frame == 0) {
+ /* Tell this terminal driver that the output is initialized and
+ * no current frames are processed */
+ mif_initialized = 1;
+ mif_in_frame = 0;
+
+ /* Reset internal position */
+ free_mif_line();
+ mif_line.fpos_x = GNP_TO_MIF(0);
+ mif_line.fpos_y = GNP_TO_MIF(MIF_YLAST);
+
+ /* Reset drawing properties strings */
+ mif_pen[0] = '\0';
+ mif_pen_width[0] = '\0';
+ mif_separation[0] = '\0';
+
+ MIF_justify_text(LEFT);
+
+ /* Reset group ID generator */
+ for (i = 0; i < MIF_NGROUP_ID; i++) {
+ mif_group_id[i].group_id = MIF_INVALID_GROUP_ID;
+ mif_group_id[i].group_existance = MIF_GROUP_NOT_EXISTS;
+ }
+
+ /* Identify ourselves */
+ /*bs show borders */
+ /* Setup a default environment to use */
+ fprintf(gpoutfile, "\
+<MIFFile 3.00> # Generated by gnuplot version %s patchlevel %s; identifies this as a MIF file\n\
+#\n\
+# show borders\n\
+<Document\n<DBordersOn Yes>\n>\n\
+# Set a default pen pattern, pen width, unit and font for subsequent objects\n\
+<Pen 0>\n\
+<Fill 15>\n\
+<PenWidth 0.5 pt>\n\
+<Separation 0>\n\
+<Units Ucm>\n\
+<FontCatalog\n\
+\t<Font <FTag `%s'><FFamily `Times'><FSize %d><FPlain Yes>>\n\
+\t<Font <FTag `%s'><FFamily `ZapfDingbats'><FSize 7.0 pt><FPlain Yes>>\n\
+\t<Font <FTag `%s'><FFamily `Symbol'><FSize 5.0 pt><FPlain Yes>>\n\
+>\n\
+#\n",
+ gnuplot_version, gnuplot_patchlevel,
+ zgnuplot, MIF_PSIZE,
+ zgnuplotp,
+ zgnuplotd);
+ } /* MIF file created */
+}
+
+/* Finish of a MIF output file */
+TERM_PUBLIC void
+MIF_reset()
+{
+ /* Process if inside a MIF file and not inside a Frame */
+ if (mif_initialized != 0 && mif_in_frame == 0) {
+ /* Finish off the MIF file */
+ fputs("\
+#\n\
+# End of MIFFile\n", gpoutfile);
+
+ /* Tell this terminal driver that the output is finished */
+ mif_initialized = 0;
+
+ /* bs: reset frame number */
+ mif_frameno = -1;
+
+ } /* MIF file finished */
+}
+
+/* Start plotting a Frame (-> graphics mode) */
+TERM_PUBLIC void
+MIF_graphics()
+{
+ int i;
+
+ /* Process if not inside a Frame */
+ if (mif_initialized != 0 && mif_in_frame == 0) {
+ /* Tell that this terminal driver is working with a plot frame */
+ mif_in_frame = 1;
+
+ /* Update frame number */
+ mif_frameno++;
+
+ /* Set current position */
+ free_mif_line();
+ mif_line.fpos_x = GNP_TO_MIF(0);
+ mif_line.fpos_y = GNP_TO_MIF(MIF_YLAST);
+
+ /* Set drawing properties */
+ mif_pen[0] = '\0';
+ mif_pen_width[0] = '\0';
+ mif_separation[0] = '\0';
+
+ MIF_justify_text(LEFT);
+
+ /* Reset group ID generator */
+ for (i = 0; i < MIF_NGROUP_ID; i++) {
+ mif_group_id[i].group_id = MIF_INVALID_GROUP_ID;
+ mif_group_id[i].group_existance = MIF_GROUP_NOT_EXISTS;
+ }
+
+ /* Frame preamble */
+ fprintf(gpoutfile, "\
+#\n\
+# Frame number %d with plot of graphics\n\
+<Frame\n\
+\t<Pen 15>\n\
+\t<Fill 15>\n\
+\t<PenWidth 0.5 pt>\n\
+\t<Separation 0>\n\
+\t<BRect 2.000 %.3f %.3f %.3f>\n\
+\t<NSOffset 0.000>\n\
+\t<BLOffset 0.000>\n",
+ mif_frameno,
+ ((float) mif_frameno) * GNP_TO_MIF(MIF_YMAX + 100),
+ GNP_TO_MIF(MIF_XMAX), GNP_TO_MIF(MIF_YMAX));
+ } /* Frame created */
+}
+
+/* Stop plotting a Frame (-> text mode) */
+TERM_PUBLIC void
+MIF_text()
+{
+ int i;
+
+ /* Process if inside a Frame */
+ if (mif_initialized != 0 && mif_in_frame != 0) {
+
+ /* Draw pending line */
+ if (mif_polyline == TRUE)
+ put_mif_line();
+
+ /* Group the used plot primitives */
+ fputs("\
+\t#\n\
+\t# Group the the objects in groups to make the chart easier to manipulate\n\
+\t# after it's imported into FrameMaker.\n", gpoutfile);
+
+ for (i = 0; i < MIF_NGROUP_ID; i++) {
+ if (mif_group_id[i].group_id != MIF_INVALID_GROUP_ID &&
+ mif_group_id[i].group_existance == MIF_GROUP_EXISTS) {
+ fprintf(gpoutfile, "\
+\t<Group\n\
+\t\t<ID %d>\n\
+\t>\n", mif_group_id[i].group_id);
+ }
+ }
+
+ /* Frame post amble */
+ fprintf(gpoutfile, "\
+>\n\
+# End of Frame number %d\n\
+#\n",
+ mif_frameno);
+
+ /* Tell that this terminal driver is not working with a plot frame */
+ mif_in_frame = 0;
+ } /* Frame finshed */
+}
+
+/* Select type of line in grapics */
+/* NOTE: actually written to output the first time a primitive
+ * is drawn AFTER this call */
+/* -2=border, -1=X/Y-axis, 0-13=lines, and 14-=mapped back */
+TERM_PUBLIC void
+MIF_linetype(int linetype)
+{
+ /* Process if inside a Frame */
+ if (mif_initialized != 0 && mif_in_frame != 0) {
+
+ /* Draw pending line */
+ if (mif_polyline == TRUE)
+ put_mif_line();
+
+ /* Translate gnuplot pen types to MIF pen types */
+ if (linetype < 0) { /* Special lines */
+ if (linetype == LT_AXIS) {
+ mif_pentype = 8 + MIF_NPENS; /* -1 */
+ if (mif_colour == TRUE)
+ sprintf(mif_separation, " <Separation 0> ");
+ } else {
+ mif_pentype = 0 + MIF_NPENS; /* -2 or less */
+ if (mif_colour == TRUE)
+ sprintf(mif_separation, " <Separation 0> ");
+ }
+ sprintf(mif_pen_width, " <PenWidth 1.0 pt> ");
+ /* EAM - set text color to black */
+ sprintf(mif_textcolor, " <Font <FSeparation 0>> ");
+ } else { /* Normal lines */
+ mif_pentype = (linetype) % MIF_NPENS; /* 0-(MIF_NPENS-1) */
+ sprintf(mif_pen_width, " <PenWidth 0.1 pt> ");
+ if (mif_colour == TRUE)
+ sprintf(mif_separation, " <Separation %d> ",
+ 2 + (mif_pentype % 6)); /* 2-7 */
+ /* EAM - set text color also */
+ if (mif_colour == TRUE)
+ sprintf(mif_textcolor, " <Font <FSeparation %d>> ",
+ 2 + (mif_pentype % 6)); /* 2-7 */
+ }
+
+ /* Set pen type */
+ sprintf(mif_pen, " <Pen %d> ",
+ mif_pattern_table[mif_pentype % MIF_NPENS]);
+
+ } /* Primitive processed */
+}
+
+/* Allow arbitrary text rotation */
+TERM_PUBLIC int
+MIF_text_angle(int ang)
+{
+ mif_text_ang = ang;
+ return (TRUE);
+}
+
+/* Justify following text lines (MIF_put_text()) relative to the
+ * insertion point
+ * NOTE: actually written to output in text primitives which are
+ * drawn AFTER this call */
+TERM_PUBLIC int
+MIF_justify_text(enum JUSTIFY mode)
+{
+ int rval = TRUE;
+
+ /* Process if inside a Frame */
+ if (mif_initialized != 0 && mif_in_frame != 0) {
+ switch (mode) {
+ case LEFT:
+ sprintf(mif_justify, " <TLAlignment Left> ");
+ break;
+ case CENTRE:
+ sprintf(mif_justify, " <TLAlignment Center> ");
+ break;
+ case RIGHT:
+ sprintf(mif_justify, " <TLAlignment Right> ");
+ break;
+ default:
+ rval = FALSE;
+ break;
+ }
+
+ }
+ /* Primitive processed */
+ else {
+ rval = FALSE;
+ }
+
+ return (rval);
+}
+
+/* Draw a vector from current position to (x, y) and change current position.
+ * NOTE: actually written to output the first time another primitive
+ * is called AFTER this call */
+TERM_PUBLIC void
+MIF_vector(unsigned int x, unsigned int y)
+{
+ /* Process if inside a Frame */
+ if (mif_initialized != 0 && mif_in_frame != 0) {
+
+ /* Setup the vector as a part of the line */
+ insert_mif_line(GNP_TO_MIF(x), GNP_TO_MIF(MIF_YLAST - (int) y));
+
+ /* Draw pending line -> vector */
+ if (mif_polyline == FALSE)
+ put_mif_line();
+
+ } /* Vector processed */
+}
+
+/* Move current position */
+TERM_PUBLIC void
+MIF_move(unsigned int x, unsigned int y)
+{
+ /* Process if inside a Frame */
+ if (mif_initialized != 0 && mif_in_frame != 0) {
+
+ /* Draw pending line */
+ if (mif_polyline == TRUE)
+ put_mif_line();
+
+ mif_line.fpos_x = GNP_TO_MIF(x);
+ mif_line.fpos_y = GNP_TO_MIF(MIF_YLAST - (int) y);
+ }
+}
+
+
+/* set font */
+static void
+MIF_set_font(const char *font)
+{
+ if (font != mif_font) {
+ fprintf(gpoutfile, "\t\t<Font\n\t\t\t<FTag `%s'>\n\t\t>\n", font);
+ mif_font = font;
+ }
+}
+
+
+/* Draw the text string str at (x, y). Adjust according to MIF_justify_text().
+ * Change current position. */
+TERM_PUBLIC void
+MIF_put_text(unsigned int x, unsigned int y, const char str[])
+{
+ /* Process if inside a Frame */
+ if (mif_initialized != 0 && mif_in_frame != 0) {
+
+ /* Draw pending line */
+ if (mif_polyline == TRUE)
+ put_mif_line();
+
+ /* Adjust current position for text-graphics alignment */
+ MIF_move(x, y - MIF_VCHAR / 5);
+
+ if (strlen(str) > 0) {
+
+ /* Draw the text */
+ fprintf(gpoutfile, "\t<TextLine <GroupID %d> %s %s %s %s\n",
+ MIF_PEN_TO_GROUP(mif_pentype), mif_pen,
+ mif_pen_width, mif_separation, mif_textcolor);
+
+ MIF_set_font(zgnuplot);
+
+ fprintf(gpoutfile, "\
+\t\t<TLOrigin %.3f %.3f> %s <Angle %d> <String `%s'>\n\
+\t>\n",
+ mif_line.fpos_x, mif_line.fpos_y, mif_justify,
+ mif_text_ang, str);
+
+ /* Register the used group ID */
+ proc_group_id(MIF_PEN_TO_GROUP(mif_pentype));
+
+ /* Avoid to redraw this. The MIF system should remember it. */
+ mif_pen[0] = '\0';
+ mif_pen_width[0] = '\0';
+ mif_separation[0] = '\0';
+
+ mif_justify[0] = '\0'; /* Independent of linetype */
+ }
+ } /* Text processed */
+}
+
+
+/* Insert one point in the line */
+static int
+insert_mif_line(double fx, double fy)
+{
+ int rval = TRUE;
+
+ if ((mif_line.prev->next = (struct mif_line *) gp_alloc(sizeof(struct mif_line),
+ "MIF driver")) != (struct mif_line *) NULL) {
+ /* Link */
+ mif_line.prev->next->next = &mif_line;
+ mif_line.prev->next->prev = mif_line.prev;
+ mif_line.prev = mif_line.prev->next;
+
+ /* Fill */
+ mif_line.prev->fpos_x = fx;
+ mif_line.prev->fpos_y = fy;
+
+ rval = TRUE;
+ } else { /* Failed to allocate */
+ /* Relink */
+ mif_line.prev->next = &mif_line;
+
+ rval = FALSE;
+ }
+
+ return (rval);
+}
+
+/* Register group ID. Update group ID existance. */
+/* Returns: 1 group_id belongs to a MIF group
+ 0 group_id does not belong to a MIF group
+ -1 not inside a Frame
+ -2 group ID list is full
+ */
+static int
+proc_group_id(int group_id)
+{
+ int i, rval = 0;
+
+ /* Process if inside a Frame */
+ if (mif_initialized != 0 && mif_in_frame != 0) {
+
+ /* Find out the group ID, or a free group ID slot index. */
+ for (i = 0; i < MIF_NGROUP_ID &&
+ mif_group_id[i].group_id != MIF_INVALID_GROUP_ID &&
+ mif_group_id[i].group_id != group_id;
+ i++) {
+ /* Don't check the group_existance variable */
+ }
+
+ if (i < MIF_NGROUP_ID) {
+ if (mif_group_id[i].group_id == MIF_INVALID_GROUP_ID) {
+ /* Register as new group ID for eventual use as MIF group */
+ mif_group_id[i].group_id = group_id;
+ mif_group_id[i].group_existance = MIF_GROUP_NOT_EXISTS;
+ } else {
+ /* If second use of this group ID -> create a new MIF group */
+ if (mif_group_id[i].group_id == group_id) {
+ mif_group_id[i].group_existance = MIF_GROUP_EXISTS;
+ /* NOTE: a group MUST have at least two members. */
+ rval = 1;
+ }
+ }
+ } else {
+ rval = -2; /* No place for this group ID in the list */
+ }
+
+ }
+ /* Group ID processed */
+ else {
+ rval = -1; /* Not inside a Frame */
+ }
+
+ /* Return MIF group status */
+ return (rval);
+}
+
+
+#endif
+
+
+#ifdef TERM_TABLE
+
+TERM_TABLE_START(mif_driver)
+ "mif", "Frame maker MIF 3.00 format",
+ MIF_XMAX, MIF_YMAX, MIF_VCHAR, MIF_HCHAR,
+ MIF_VTIC, MIF_HTIC, MIF_options, MIF_init, MIF_reset,
+ MIF_text, null_scale, MIF_graphics, MIF_move, MIF_vector,
+ MIF_linetype, MIF_put_text, MIF_text_angle,
+ MIF_justify_text, MIF_point, do_arrow, set_font_null,
+ 0, /* pointsize */
+ 0, /* flags */
+ 0, 0, /* suspend, resume */
+ MIF_boxfill,
+ 0 /* linewidth */
+#ifdef USE_MOUSE
+ , 0, 0, 0, 0, 0
+#endif
+ ,0 /* make_palette */
+ ,0 /* previous_palette */
+ ,0 /* set_color */
+ ,MIF_filled_polygon /* filled_polygon */
+TERM_TABLE_END(mif_driver)
+
+#undef LAST_TERM
+#define LAST_TERM mif_driver
+
+#endif
+#endif /* TERM_PROTO_ONLY */
+
+#ifdef TERM_HELP
+START_HELP(mif)
+"1 mif",
+"?commands set terminal mif",
+"?set terminal mif",
+"?set term mif",
+"?terminal mif",
+"?term mif",
+"?mif",
+" The `mif` terminal driver produces Frame Maker MIF format version 3.00. It",
+" plots in MIF Frames with the size 15*10 cm, and plot primitives with the same",
+" pen will be grouped in the same MIF group. Plot primitives in a `gnuplot`",
+" page will be plotted in a MIF Frame, and several MIF Frames are collected in",
+" one large MIF Frame. The MIF font used for text is \"Times\".",
+"",
+" Several options may be set in the MIF 3.00 driver.",
+"",
+" Syntax:",
+" set terminal mif {color | colour | monochrome} {polyline | vectors}",
+" {help | ?}",
+"",
+" `colour` plots lines with line types >= 0 in colour (MIF sep. 2--7) and",
+" `monochrome` plots all line types in black (MIF sep. 0).",
+" `polyline` plots curves as continuous curves and `vectors` plots curves as",
+" collections of vectors.",
+" `help` and `?` print online help on standard error output---both print a",
+" short description of the usage; `help` also lists the options.",
+"",
+" Examples:",
+" set term mif colour polylines # defaults",
+" set term mif # defaults",
+" set term mif vectors",
+" set term mif help"
+END_HELP(mif)
+#endif /* TERM_HELP */