Annotation of OpenXM_contrib/gnuplot/term/mif.trm, Revision 1.1.1.2
1.1 maekawa 1: /*
1.1.1.2 ! maekawa 2: * $Id: mif.trm,v 1.11 1999/01/12 14:04:11 lhecking Exp $
1.1 maekawa 3: */
4: /* GNUPLOT -- mif.trm */
5:
6: /*[
7: * Copyright 1992, 1993, 1998
8: *
9: * Permission to use, copy, and distribute this software and its
10: * documentation for any purpose with or without fee is hereby granted,
11: * provided that the above copyright notice appear in all copies and
12: * that both that copyright notice and this permission notice appear
13: * in supporting documentation.
14: *
15: * Permission to modify the software is granted, but not the right to
16: * distribute the complete modified source code. Modifications are to
17: * be distributed as patches to the released version. Permission to
18: * distribute binaries produced by compiling modified sources is granted,
19: * provided you
20: * 1. distribute the corresponding source modifications from the
21: * released version in the form of a patch file along with the binaries,
22: * 2. add special version identification to distinguish your version
23: * in addition to the base release version number,
24: * 3. provide your name and address as the primary contact for the
25: * support of your modified version, and
26: * 4. retain our contact information in regard to use of the base
27: * software.
28: * Permission to distribute the released version of the source code along
29: * with corresponding source modifications in the form of a patch file is
30: * granted with same provisions 2 through 4 for binary distributions.
31: *
32: * This software is provided "as is" without express or implied warranty
33: * to the extent permitted by applicable law.
34: ]*/
35:
36: /*
37: * This file is included by ../term.c.
38: *
39: * This terminal driver was developed for
40: * gnuplot for unix version 3.0 (patchlevel 1)
41: * gnuplot for unix version 3.2 (patchlevel 2)
42: *
43: * This terminal driver supports:
44: * Frame Maker MIF format version 3.00
45: *
46: * Options for this terminal driver (set terminal mif [options]):
47: * colour / Draw primitives with line types >= 0 in colour (sep. 2-7)
48: * monochrome Draw primitives in black (sep. 0)
49: *
50: * polyline / Draw lines as continous curves
51: * vectors Draw lines as collections of vectors
52: *
53: * help / ? Print short usage description on stderr
54: *
55: * Properties for this terminal driver:
56: * -Gnuplot size of worksheet: MIF_XMAX * MIF_YMAX
57: * -Unit in MIF output: cm
58: * -Plot primitives with the same pen will
59: * be grouped in the same MIF group.
60: * -Plot primitives with line types >= 0
61: * will as default be drawn in colour.
62: * -Lines are plotted as collections of
63: * vectors, or as continous lines (default)
64: * -Plot primitives in a plot will be in a
65: * Frame in MIF. Several plot Frames will
66: * be collected in one large Frame.
67: * -Point size of MIF output characters: MIF_PSIZE
68: * -Used font for MIF output characters: Times
69: * -Supports vertical text
70: * -points and dots as characters
71: * -character formats for TextLines
72: *
73: * AUTHORS:
74: * Olof Franksson, Physics IV, KTH, S-100 44 Stockholm, Sweden
75: *
76: * NEW TERMINAL FORMAT: David C. Schooley
77:
78: * COMMENTS:
79: * Send comments and/or suggestions to olof@fysik4.kth.se
80: *
81: * CHANGES:
82: * Changed to new terminal format 9/29/95 schooley@ee.gatech.edu
83: * Changed order of routine declarations. olof@fysik4.kth.se
84: * Changed mechanism for pen pattern selection. kssingvo@immd4.informatik.uni-erlangen.de
85: * Support for vertical text. kssingvo@immd4.informatik.uni-erlangen.de
86: * Fixed plot bug for "set size XS,YS", XS/YS > 1. olof@fysik4.kth.se
87: *
88: */
89:
90: #include "driver.h"
91:
92: #ifdef TERM_REGISTER
93: register_term(mif)
94: #endif
95:
96:
97:
98: #ifdef TERM_PROTO
99: TERM_PUBLIC void MIF_init __PROTO((void));
100: TERM_PUBLIC void MIF_graphics __PROTO((void));
101: TERM_PUBLIC void MIF_text __PROTO((void));
102: TERM_PUBLIC void MIF_linetype __PROTO((int linetype));
103: TERM_PUBLIC void MIF_move __PROTO((unsigned int x, unsigned int y));
104: TERM_PUBLIC void MIF_vector __PROTO((unsigned int x, unsigned int y));
105: TERM_PUBLIC void MIF_put_text __PROTO((unsigned int x, unsigned int y, char *str));
106: TERM_PUBLIC int MIF_text_angle __PROTO((int ang));
107: TERM_PUBLIC void MIF_reset __PROTO((void));
108: TERM_PUBLIC void MIF_options __PROTO((void));
109: TERM_PUBLIC int MIF_justify_text __PROTO((enum JUSTIFY mode));
110: TERM_PUBLIC void MIF_point __PROTO((unsigned int x, unsigned int y, int number));
111:
112: /** Coordinates **/
113: /* The cast to float is not necessary because we are dividing by a float */
114: /* On OSK the cast to a float is not allowed in a constant expression wich */
115: /* is used by the declaration and initialization of mif_line */
116: /* Converts gnuplot units to MIF units */
117: #define GNP_TO_MIF(P) ((P) / 1000.0)
118: /* Basic unit: 0.01 mm (15cm -> 15*10*100=15000) */
119: #define MIF_XMAX 15000
120: /* Basic unit: 0.01 mm (10cm -> 10*10*100=10000) */
121: #define MIF_YMAX 10000
122:
123: #define MIF_XLAST (MIF_XMAX - 1)
124: #define MIF_YLAST (MIF_YMAX - 1)
125:
126: static int insert_mif_line __PROTO((double fx, double fy));
127: static int proc_group_id __PROTO((int group_id));
128: static void free_mif_line __PROTO((void));
129: static void put_mif_line __PROTO((void));
130: static void MIF_set_font __PROTO((char *));
131: static void mif_put_point __PROTO((unsigned int x, unsigned int y, int np));
132:
133: #ifndef cfree
134: # define cfree free
135: #endif
136:
137: /* Declared in ../setshow.c */
138: extern char term_options[];
139:
140: /* From version.c */
141: extern char version[];
142: extern char patchlevel[];
143:
144: static struct mif_line { /* Line point structure specification */
145: float fpos_x; /* Line point X coordinate */
146: float fpos_y; /* Y coordinate */
147: struct mif_line *next; /* Pointer to next line point */
148: struct mif_line *prev; /* Pointer to previous line point */
149: } mif_line =
150: { /* Current position structure. Adjust for orign. Local for this file. */
151: GNP_TO_MIF(0),
152: GNP_TO_MIF(MIF_YLAST),
153: &mif_line,
154: &mif_line
155: };
156:
157: /** Characters **/
158: #define MIF_PSIZE 9 /* Point size of used characters */
159:
160: #define MIF_VCHAR (MIF_YMAX/31) /* Distance between rows (a guess) */
161: #define MIF_HCHAR (MIF_XMAX/95) /* Distance between characters (a guess) */
162:
163: /** Scale marks **/
164: #define MIF_VTIC (MIF_YMAX/150) /* Size of scale mark (vert) */
165: #define MIF_HTIC (MIF_XMAX/225) /* Size of scale mark (hor) */
166:
167: /** Drawing properties **/
168: static char mif_justify[64]; /* How to justify the used text */
169: static char mif_pen[64], mif_pen_width[64], mif_separation[64]; /* How to plot */
170:
171: #define MIF_TEXT_HOR 0
172: #define MIF_TEXT_VER 1
173: static int mif_text_ang = MIF_TEXT_HOR; /* Rotation angle of text */
174:
175: #define MIF_NPENS 16 /* Number of MIF pen types */
176: static int mif_pentype = 0; /* Pen type to use. Also used to create groups for graphics */
177: #define MIF_PEN_TO_GROUP(P) ( 1 + (P) ) /* Map pen type to group number. Must be >= 1 */
178:
179: static int mif_pattern_table[MIF_NPENS] =
180: { /* Table, which pattern should be used for drawing */
181: 0, /* border */
182: 1, /* not used */
183: 2, 3, 4, 8, 12, 13, /* other lines: functions, data, ... (5 is used for grid; 6,7 is (nearly) invisible) */
184: 5, /* grid */
185: 9, 10, 11, 12, 13, 14, 15 /* not used */
186: };
187:
188: /** MIF groups administration **/
189: #define MIF_NGROUP_ID 20
190: static struct mif_group_id {
191: int group_existance;
192: /* This group id should generate a MIF group */
193: #define MIF_GROUP_EXISTS 1
194: /* This group id should not generate a MIF group */
195: #define MIF_GROUP_NOT_EXISTS 0
196:
197: int group_id;
198: #define MIF_INVALID_GROUP_ID 0 /* An invalid MIF group ID */
199:
200: } mif_group_id[MIF_NGROUP_ID]; /* List of used group ID:s and corresponding MIF groups existance */
201:
202: /** Semaphores **/
203: static int mif_initialized = 0; /* != 0 when output is active */
204: static int mif_in_frame = 0; /* != 0 when inside a plot frame */
205: static int mif_frameno = -1; /* Current frame number */
206: static int mif_colour = TRUE; /* == TRUE when colour should be used */
207: static int mif_polyline = TRUE; /* == TRUE when lines are drawn as continous curves */
208:
209: struct mpt { /* point definition structure */
210: int chr; /* character for point */
211: float x_offset, y_offset; /* offset for vertical positioning */
212: char *font; /* font */
213: };
214:
215: char zgnuplot[] = "ZGnuplot"; /* character formats */
216: char zgnuplotp[] = "ZGnuplotP";
217: char zgnuplotd[] = "ZGnuplotD";
218: char *mif_font = NULL; /* actual character format */
219:
220: struct mpt mpt[POINT_TYPES + 1] =
221: { /* point definition data */
222: {'.', 0.000, 0.005, zgnuplotd, /* dot */ },
223:
224: {'G', 0.002, 0.084, zgnuplotp, /* diamond */ },
225: {';', 0.002, 0.084, zgnuplotp, /* plus */ },
226: {'n', 0.002, 0.084, zgnuplotp, /* box */ },
227: {'5', 0.002, 0.084, zgnuplotp, /* X */ },
228: {'s', 0.002, 0.062, zgnuplotp, /* triangle */ },
229: {'K', 0.005, 0.075, zgnuplotp, /* star */ },
230: };
231:
232: /* diamond is offset 0, dot is offset -1 */
233: struct mpt *mif_point = &(mpt[1]);
234:
235: #endif
236:
237:
238: #ifndef TERM_PROTO_ONLY
239: #ifdef TERM_BODY
240:
241:
242: /** Declaration of routine/s for internal use **/
243: static int insert_mif_line __PROTO((double fx, double fy));
244: static int proc_group_id __PROTO((int group_id));
245:
246: /** Routine/s **/
247:
248: /* Called when this terminal type is set in order to parse options */
249: TERM_PUBLIC void MIF_options()
250: {
251: if (!END_OF_COMMAND) {
252: /* Colour options */
253: if (!END_OF_COMMAND && almost_equals(c_token, "m$onochrome")) { /* Compare up to $ */
254: mif_colour = FALSE;
255: c_token++;
256: }
257: if (!END_OF_COMMAND && (almost_equals(c_token, "c$olor")
258: || almost_equals(c_token, "c$olour"))) { /* Compare up to $ */
259: mif_colour = TRUE;
260: c_token++;
261: }
262: /* Curve options */
263: if (!END_OF_COMMAND && almost_equals(c_token, "v$ectors")) { /* Compare up to $ */
264: mif_polyline = FALSE;
265: c_token++;
266: }
267: if (!END_OF_COMMAND && almost_equals(c_token, "p$olyline")) { /* Compare up to $ */
268: mif_polyline = TRUE;
269: c_token++;
270: }
271: /* Short help */
272: if (!END_OF_COMMAND &&
273: (almost_equals(c_token, "h$elp") ||
274: almost_equals(c_token, "?$"))) { /* Compare up to $ */
275: fprintf(stderr, "\
276: Usage: set terminal mif [options]\n\
277: \toptions:\n\
278: \t\tcolour / Draw primitives with line types >= 0 in colour (sep. 2-7)\n\
279: \t\tmonochrome Draw primitives in black (sep. 0)\n\n\
280: \t\tpolyline / Draw lines as continous curves\n\
281: \t\tvectors Draw lines as collections of vectors\n\n\
282: \t\thelp / ? Print short usage description on stderr\n");
283:
284: c_token++;
285: }
286: }
287: sprintf(term_options, "%s %s", (mif_colour == TRUE) ? "colour" : "monochrome",
288: (mif_polyline == TRUE) ? "polyline" : "vectors");
289: }
290:
291: /* Deallocate the used line structure elements */
292: static void free_mif_line()
293: {
294: struct mif_line *tline;
295:
296: while (mif_line.prev != &mif_line) {
297: /* Unlink */
298: tline = mif_line.prev;
299: mif_line.prev = mif_line.prev->prev;
300: mif_line.prev->next = &mif_line;
301:
302: /* Deallocate */
303: free(tline);
304: }
305:
306: /* Make sure that the list will be empty */
307: mif_line.prev = &mif_line;
308: mif_line.next = &mif_line;
309: }
310:
311: /* Draw the pending line. Change current position. */
312: static void put_mif_line()
313: {
314: int np, i;
315: struct mif_line *tline;
316:
317: /* Process if inside a Frame */
318: if (mif_initialized != 0 && mif_in_frame != 0) {
319:
320: /* Count the number of available points */
321: for (tline = mif_line.next, np = 1; tline != &mif_line; tline = tline->next, np++);
322:
323: /* Draw line (at least two points) */
324: if (np >= 2) {
325:
326: /* Line preamble */
327: fprintf(gpoutfile, "\t<PolyLine <GroupID %d> %s %s %s\n",
328: MIF_PEN_TO_GROUP(mif_pentype), mif_pen, mif_pen_width, mif_separation);
329:
330: /* Draw the line elements */
331: fprintf(gpoutfile, "\t\t<NumPoints %d> ", np);
332: for (i = 0, tline = &mif_line; i < np; i++, tline = tline->next) {
333: if (i % 4 == 0)
334: fputs("\n\t\t", gpoutfile);
335: fprintf(gpoutfile, "<Point %.3f %.3f> ",
336: tline->fpos_x, tline->fpos_y);
337: }
338:
339: /* Line post amble */
340: fputs("\n\t>\n", gpoutfile);
341:
342: /* Register the used group ID */
343: proc_group_id(MIF_PEN_TO_GROUP(mif_pentype));
344:
345: /* Avoid to redraw this. The MIF system should remember it. */
346: mif_pen[0] = '\0';
347: mif_pen_width[0] = '\0';
348: mif_separation[0] = '\0';
349:
350: /* Move current position to end of line */
351: mif_line.fpos_x = mif_line.prev->fpos_x;
352: mif_line.fpos_y = mif_line.prev->fpos_y;
353:
354: /* Restore the line */
355: free_mif_line();
356: }
357: } /* Line processed */
358: }
359:
360:
361: /* Draw a point */
362: static void mif_put_point(x, y, np)
363: unsigned int x, y;
364: int np;
365: {
366: /* Process if inside a Frame */
367: if (mif_initialized != 0 && mif_in_frame != 0) {
368:
369: /* Draw pending line */
370: if (mif_polyline == TRUE)
371: put_mif_line();
372:
373: /* Adjust current position for text-graphics alignment */
374: MIF_move(x, y);
375:
376: /* center text */
377: MIF_justify_text(CENTRE);
378:
379: /* Draw the point */
380: fprintf(gpoutfile, "\t<TextLine <GroupID %d>\n",
381: MIF_PEN_TO_GROUP(mif_pentype));
382:
383: MIF_set_font(mif_point[np].font);
384:
385: fprintf(gpoutfile, "\t\t<TLOrigin %.3f %.3f> %s <String `%c'>\n",
386: mif_line.fpos_x + mif_point[np].x_offset,
387: mif_line.fpos_y + mif_point[np].y_offset,
388: mif_justify,
389: mif_point[np].chr);
390: fputs("\t>\n", gpoutfile);
391:
392: /* Register the used group ID */
393: proc_group_id(MIF_PEN_TO_GROUP(mif_pentype));
394:
395: /* Avoid to redraw this. The MIF system should remember it. */
396: mif_justify[0] = '\0';
397:
398: } /* Point processed */
399: }
400:
401:
402: /*
403: * draw points
404: */
405: TERM_PUBLIC void MIF_point(x, y, number)
406: unsigned int x, y;
407: int number;
408: {
409: if (number < 0) { /* dot */
410: number = -1;
411: } else { /* point */
412: number %= POINT_TYPES;
413: }
414: mif_put_point(x, y, number);
415: }
416:
417:
418: /* Set up a MIF output file */
419: TERM_PUBLIC void MIF_init()
420: {
421: int i;
422:
423: /* Process if not inside a MIF file and Frame */
424: if (mif_initialized == 0 && mif_in_frame == 0) {
425: /* Tell this terminal driver that the output is initialized and no current frames are processed */
426: mif_initialized = 1;
427: mif_in_frame = 0;
428:
429: /* Reset internal position */
430: free_mif_line();
431: mif_line.fpos_x = GNP_TO_MIF(0);
432: mif_line.fpos_y = GNP_TO_MIF(MIF_YLAST);
433:
434: /* Reset drawing properties strings */
435: mif_pen[0] = '\0';
436: mif_pen_width[0] = '\0';
437: mif_separation[0] = '\0';
438:
439: MIF_justify_text(LEFT);
440:
441: /* Reset group ID generator */
442: for (i = 0; i < MIF_NGROUP_ID; i++) {
443: mif_group_id[i].group_id = MIF_INVALID_GROUP_ID;
444: mif_group_id[i].group_existance = MIF_GROUP_NOT_EXISTS;
445: }
446:
447: /* Identify ourselves */
448: /*bs show borders */
449: /* Setup a default environment to use */
450: fprintf(gpoutfile, "\
451: <MIFFile 3.00> # Generated by gnuplot version %s patchlevel %s; identifies this as a MIF file\n\
452: #\n\
453: # show borders\n\
454: <Document\n<DBordersOn Yes>\n>\n\
455: # Set a default pen pattern, pen width, unit and font for subsequent objects\n\
456: <Pen 0>\n\
457: <Fill 15>\n\
458: <PenWidth 0.5 pt>\n\
459: <Separation 0>\n\
460: <Units Ucm>\n\
461: <FontCatalog\n\
462: \t<Font <FTag `%s'><FFamily `Times'><FSize %d><FPlain Yes>>\n\
463: \t<Font <FTag `%s'><FFamily `ZapfDingbats'><FSize 7.0 pt><FPlain Yes>>\n\
464: \t<Font <FTag `%s'><FFamily `Symbol'><FSize 5.0 pt><FPlain Yes>>\n\
465: >\n\
466: #\n",
467: version, patchlevel,
468: zgnuplot, MIF_PSIZE,
469: zgnuplotp,
470: zgnuplotd);
471: } /* MIF file created */
472: }
473:
474: /* Finish of a MIF output file */
475: TERM_PUBLIC void MIF_reset()
476: {
477: /* Process if inside a MIF file and not inside a Frame */
478: if (mif_initialized != 0 && mif_in_frame == 0) {
479: /* Finish off the MIF file */
480: fputs("\
481: #\n\
482: # End of MIFFile\n", gpoutfile);
483:
484: /* Tell this terminal driver that the output is finished */
485: mif_initialized = 0;
486:
487: /* bs: reset frame number */
488: mif_frameno = -1;
489:
490: } /* MIF file finished */
491: }
492:
493: /* Start plotting a Frame (-> graphics mode) */
494: TERM_PUBLIC void MIF_graphics()
495: {
496: int i;
497:
498: /* Process if not inside a Frame */
499: if (mif_initialized != 0 && mif_in_frame == 0) {
500: /* Tell that this terminal driver is working with a plot frame */
501: mif_in_frame = 1;
502:
503: /* Update frame number */
504: mif_frameno++;
505:
506: /* Set current position */
507: free_mif_line();
508: mif_line.fpos_x = GNP_TO_MIF(0);
509: mif_line.fpos_y = GNP_TO_MIF(MIF_YLAST);
510:
511: /* Set drawing properties */
512: mif_pen[0] = '\0';
513: mif_pen_width[0] = '\0';
514: mif_separation[0] = '\0';
515:
516: MIF_justify_text(LEFT);
517:
518: /* Reset group ID generator */
519: for (i = 0; i < MIF_NGROUP_ID; i++) {
520: mif_group_id[i].group_id = MIF_INVALID_GROUP_ID;
521: mif_group_id[i].group_existance = MIF_GROUP_NOT_EXISTS;
522: }
523:
524: /* Frame preamble */
525: fprintf(gpoutfile, "\
526: #\n\
527: # Frame number %d with plot of graphics\n\
528: <Frame\n\
529: \t<Pen 15>\n\
530: \t<Fill 15>\n\
531: \t<PenWidth 0.5 pt>\n\
532: \t<Separation 0>\n\
533: \t<BRect 2.000 %.3f %.3f %.3f>\n\
534: \t<NSOffset 0.000>\n\
535: \t<BLOffset 0.000>\n",
536: mif_frameno,
537: ((float) mif_frameno) * GNP_TO_MIF(MIF_YMAX + 100),
538: GNP_TO_MIF(MIF_XMAX), GNP_TO_MIF(MIF_YMAX));
539: } /* Frame created */
540: }
541:
542: /* Stop plotting a Frame (-> text mode) */
543: TERM_PUBLIC void MIF_text()
544: {
545: int i;
546:
547: /* Process if inside a Frame */
548: if (mif_initialized != 0 && mif_in_frame != 0) {
549:
550: /* Draw pending line */
551: if (mif_polyline == TRUE)
552: put_mif_line();
553:
554: /* Group the used plot primitives */
555: fputs("\
556: \t#\n\
557: \t# Group the the objects in groups to make the chart easier to manipulate\n\
558: \t# after it's imported into FrameMaker.\n", gpoutfile);
559:
560: for (i = 0; i < MIF_NGROUP_ID; i++) {
561: if (mif_group_id[i].group_id != MIF_INVALID_GROUP_ID &&
562: mif_group_id[i].group_existance == MIF_GROUP_EXISTS) {
563: fprintf(gpoutfile, "\
564: \t<Group\n\
565: \t\t<ID %d>\n\
566: \t>\n", mif_group_id[i].group_id);
567: }
568: }
569:
570: /* Frame post amble */
571: fprintf(gpoutfile, "\
572: >\n\
573: # End of Frame number %d\n\
574: #\n",
575: mif_frameno);
576:
577: /* Tell that this terminal driver is not working with a plot frame */
578: mif_in_frame = 0;
579: } /* Frame finshed */
580: }
581:
582: /* Select type of line in grapics */
583: /* NOTE: actually written to output the first time a primitive
584: * is drawn AFTER this call */
585: TERM_PUBLIC void MIF_linetype(linetype)
586: /* -2=border, -1=X/Y-axis, 0-13=lines, and 14-=mapped back */
587: int linetype;
588: {
589: /* Process if inside a Frame */
590: if (mif_initialized != 0 && mif_in_frame != 0) {
591:
592: /* Draw pending line */
593: if (mif_polyline == TRUE)
594: put_mif_line();
595:
596: /* Translate gnuplot pen types to MIF pen types */
597: if (linetype < 0) { /* Special lines */
598: if (linetype == -1) {
599: mif_pentype = 8 + MIF_NPENS; /* -1 */
600: if (mif_colour == TRUE)
601: sprintf(mif_separation, " <Separation 0> ");
602: } else {
603: mif_pentype = 0 + MIF_NPENS; /* -2 or less */
604: if (mif_colour == TRUE)
605: sprintf(mif_separation, " <Separation 0> ");
606: }
607: sprintf(mif_pen_width, " <PenWidth 1.0 pt> ");
608: } else { /* Normal lines */
609: mif_pentype = (linetype) % MIF_NPENS; /* 0-(MIF_NPENS-1) */
610: sprintf(mif_pen_width, " <PenWidth 0.1 pt> ");
611: if (mif_colour == TRUE)
612: sprintf(mif_separation, " <Separation %d> ", 2 + (mif_pentype % 6)); /* 2-7 */
613: }
614:
615: /* Set pen type */
616: sprintf(mif_pen, " <Pen %d> ", mif_pattern_table[mif_pentype % MIF_NPENS]);
617:
618: } /* Primitive processed */
619: }
620:
621: /* Draw the text horisontally or vertically (90 degrees counterclockwise) */
622: TERM_PUBLIC int MIF_text_angle(ang)
623: int ang;
624: {
625: if (ang != 0)
626: mif_text_ang = MIF_TEXT_VER;
627: else
628: mif_text_ang = MIF_TEXT_HOR;
629:
630: return (TRUE);
631: }
632:
633: /* Justify following text lines (MIF_put_text()) relative to the insertion point */
634: TERM_PUBLIC int MIF_justify_text(mode)
635: /* NOTE: actually written to output in text primitives which are
636: * drawn AFTER this call */
637: enum JUSTIFY mode;
638: {
639: int rval = TRUE;
640:
641: /* Process if inside a Frame */
642: if (mif_initialized != 0 && mif_in_frame != 0) {
643: switch (mode) {
644: case LEFT:
645: sprintf(mif_justify, " <TLAlignment Left> ");
646: break;
647: case CENTRE:
648: sprintf(mif_justify, " <TLAlignment Center> ");
649: break;
650: case RIGHT:
651: sprintf(mif_justify, " <TLAlignment Right> ");
652: break;
653: default:
654: rval = FALSE;
655: break;
656: }
657:
658: }
659: /* Primitive processed */
660: else {
661: rval = FALSE;
662: }
663:
664: return (rval);
665: }
666:
667: /* Draw a vector from current position to (x, y) and change current position. */
668: /* NOTE: actually written to output the first time another primitive
669: * is called AFTER this call */
670: TERM_PUBLIC void MIF_vector(x, y)
671: unsigned int x, y;
672: {
673: /* Process if inside a Frame */
674: if (mif_initialized != 0 && mif_in_frame != 0) {
675:
676: /* Setup the vector as a part of the line */
677: insert_mif_line(GNP_TO_MIF(x), GNP_TO_MIF(MIF_YLAST - (int) y));
678:
679: /* Draw pending line -> vector */
680: if (mif_polyline == FALSE)
681: put_mif_line();
682:
683: } /* Vector processed */
684: }
685:
686: /* Move current position */
687: TERM_PUBLIC void MIF_move(x, y)
688: unsigned int x, y;
689: {
690: /* Process if inside a Frame */
691: if (mif_initialized != 0 && mif_in_frame != 0) {
692:
693: /* Draw pending line */
694: if (mif_polyline == TRUE)
695: put_mif_line();
696:
697: mif_line.fpos_x = GNP_TO_MIF(x);
698: mif_line.fpos_y = GNP_TO_MIF(MIF_YLAST - (int) y);
699: }
700: }
701:
702:
703: /* set font */
704: static void MIF_set_font(font)
705: char *font;
706: {
707: if (font != mif_font) {
708: fprintf(gpoutfile, "\t\t<Font\n\t\t\t<FTag `%s'>\n\t\t>\n", font);
709: mif_font = font;
710: }
711: }
712:
713:
714: /* Draw the text string str at (x, y). Adjust according to MIF_justify_text().
715: * Change current position. */
716: TERM_PUBLIC void MIF_put_text(x, y, str)
717: unsigned int x, y;
718: char str[];
719: {
720: /* Process if inside a Frame */
721: if (mif_initialized != 0 && mif_in_frame != 0) {
722:
723: /* Draw pending line */
724: if (mif_polyline == TRUE)
725: put_mif_line();
726:
727: /* Adjust current position for text-graphics alignment */
728: MIF_move(x, y - MIF_VCHAR / 5);
729:
730: if (strlen(str) > 0) {
731:
732: /* Draw the text */
733: fprintf(gpoutfile, "\t<TextLine <GroupID %d> %s %s %s\n",
734: MIF_PEN_TO_GROUP(mif_pentype), mif_pen,
735: mif_pen_width, mif_separation);
736:
737: MIF_set_font(zgnuplot);
738:
739: fprintf(gpoutfile, "\
740: \t\t<TLOrigin %.3f %.3f> %s %s <String `%s'>\n\
741: \t>\n",
742: mif_line.fpos_x, mif_line.fpos_y, mif_justify,
743: (mif_text_ang == MIF_TEXT_VER) ? "<Angle 90>" : "",
744: str);
745:
746: /* Register the used group ID */
747: proc_group_id(MIF_PEN_TO_GROUP(mif_pentype));
748:
749: /* Avoid to redraw this. The MIF system should remember it. */
750: mif_pen[0] = '\0';
751: mif_pen_width[0] = '\0';
752: mif_separation[0] = '\0';
753:
754: mif_justify[0] = '\0'; /* Independent of linetype */
755: }
756: } /* Text processed */
757: }
758:
759:
760: /* Insert one point in the line */
761: static int insert_mif_line(fx, fy)
762: double fx, fy;
763: {
764: int rval = TRUE;
765:
766: if ((mif_line.prev->next = (struct mif_line *) gp_alloc(sizeof(struct mif_line),
767: "MIF driver")) != (struct mif_line *) NULL) {
768: /* Link */
769: mif_line.prev->next->next = &mif_line;
770: mif_line.prev->next->prev = mif_line.prev;
771: mif_line.prev = mif_line.prev->next;
772:
773: /* Fill */
774: mif_line.prev->fpos_x = fx;
775: mif_line.prev->fpos_y = fy;
776:
777: rval = TRUE;
778: } else { /* Failed to allocate */
779: /* Relink */
780: mif_line.prev->next = &mif_line;
781:
782: rval = FALSE;
783: }
784:
785: return (rval);
786: }
787:
788: /* Register group ID. Update group ID existance. */
789: /* Returns: 1 group_id belongs to a MIF group
790: 0 group_id does not belong to a MIF group
791: -1 not inside a Frame
792: -2 group ID list is full
793: */
794: static int proc_group_id(group_id)
795: int group_id;
796: {
797: int i, rval = 0;
798:
799: /* Process if inside a Frame */
800: if (mif_initialized != 0 && mif_in_frame != 0) {
801:
802: /* Find out the group ID, or a free group ID slot index. */
803: for (i = 0; i < MIF_NGROUP_ID &&
804: mif_group_id[i].group_id != MIF_INVALID_GROUP_ID &&
805: mif_group_id[i].group_id != group_id;
806: i++) {
807: /* Don't check the group_existance variable */
808: }
809:
810: if (i < MIF_NGROUP_ID) {
811: if (mif_group_id[i].group_id == MIF_INVALID_GROUP_ID) {
812: /* Register as new group ID for eventual use as MIF group */
813: mif_group_id[i].group_id = group_id;
814: mif_group_id[i].group_existance = MIF_GROUP_NOT_EXISTS;
815: } else {
816: /* If second use of this group ID -> create a new MIF group */
817: if (mif_group_id[i].group_id == group_id) {
818: mif_group_id[i].group_existance = MIF_GROUP_EXISTS;
819: /* NOTE: a group MUST have at least two members. */
820: rval = 1;
821: }
822: }
823: } else {
824: rval = -2; /* No place for this group ID in the list */
825: }
826:
827: }
828: /* Group ID processed */
829: else {
830: rval = -1; /* Not inside a Frame */
831: }
832:
833: /* Return MIF group status */
834: return (rval);
835: }
836:
837:
838: #endif
839:
840:
841: #ifdef TERM_TABLE
842:
843: TERM_TABLE_START(mif_driver)
844: "mif", "Frame maker MIF 3.00 format",
845: MIF_XMAX, MIF_YMAX, MIF_VCHAR, MIF_HCHAR,
846: MIF_VTIC, MIF_HTIC, MIF_options, MIF_init, MIF_reset,
847: MIF_text, null_scale, MIF_graphics, MIF_move, MIF_vector,
848: MIF_linetype, MIF_put_text, MIF_text_angle,
849: MIF_justify_text, MIF_point, do_arrow, set_font_null
850: TERM_TABLE_END(mif_driver)
851:
852: #undef LAST_TERM
853: #define LAST_TERM mif_driver
854:
855: #endif
856: #endif /* TERM_PROTO_ONLY */
857:
858: #ifdef TERM_HELP
859: START_HELP(mif)
860: "1 mif",
861: "?commands set terminal mif",
862: "?set terminal mif",
863: "?set term mif",
864: "?terminal mif",
865: "?term mif",
866: "?mif",
867: " The `mif` terminal driver produces Frame Maker MIF format version 3.00. It",
868: " plots in MIF Frames with the size 15*10 cm, and plot primitives with the same",
869: " pen will be grouped in the same MIF group. Plot primitives in a `gnuplot`",
870: " page will be plotted in a MIF Frame, and several MIF Frames are collected in",
871: " one large MIF Frame. The MIF font used for text is \"Times\".",
872: "",
873: " Several options may be set in the MIF 3.00 driver.",
874: "",
875: " Syntax:",
876: " set terminal mif {colour | monochrome} {polyline | vectors}",
877: " {help | ?}",
878: "",
879: " `colour` plots lines with line types >= 0 in colour (MIF sep. 2--7) and",
880: " `monochrome` plots all line types in black (MIF sep. 0).",
881: " `polyline` plots curves as continuous curves and `vectors` plots curves as",
882: " collections of vectors.",
883: " `help` and `?` print online help on standard error output---both print a",
884: " short description of the usage; `help` also lists the options;",
885: "",
886: " Examples:",
887: " set term mif colour polylines # defaults",
888: " set term mif # defaults",
889: " set term mif vectors",
890: " set term mif help"
891: END_HELP(mif)
892: #endif /* TERM_HELP */
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>