Initial release of Maemo 5 port of gnuplot
[gnuplot] / term / rgip.trm
1 /* Hello, Emacs, this is -*-C-*-
2  * $Id: rgip.trm,v 1.17 2006/07/21 02:35:48 sfeam Exp $
3  */
4
5 /* GNUPLOT - rgip.trm Uniplex graphics metafile */
6
7 /*[
8  * Copyright 1990 - 1993, 1998, 2004
9  *
10  * Permission to use, copy, and distribute this software and its
11  * documentation for any purpose with or without fee is hereby granted,
12  * provided that the above copyright notice appear in all copies and
13  * that both that copyright notice and this permission notice appear
14  * in supporting documentation.
15  *
16  * Permission to modify the software is granted, but not the right to
17  * distribute the complete modified source code.  Modifications are to
18  * be distributed as patches to the released version.  Permission to
19  * distribute binaries produced by compiling modified sources is granted,
20  * provided you
21  *   1. distribute the corresponding source modifications from the
22  *    released version in the form of a patch file along with the binaries,
23  *   2. add special version identification to distinguish your version
24  *    in addition to the base release version number,
25  *   3. provide your name and address as the primary contact for the
26  *    support of your modified version, and
27  *   4. retain our contact information in regard to use of the base
28  *    software.
29  * Permission to distribute the released version of the source code along
30  * with corresponding source modifications in the form of a patch file is
31  * granted with same provisions 2 through 4 for binary distributions.
32  *
33  * This software is provided "as is" without express or implied warranty
34  * to the extent permitted by applicable law.
35 ]*/
36
37 /*
38  * This file is included by ../term.c.
39  *
40  * This terminal driver supports:
41  *   RGIP metafile
42  *
43  * AUTHORS
44  *   Hans Olav Eggestad
45  *
46  * send your comments or suggestions to (gnuplot-info@lists.sourceforge.net).
47  *
48  */
49
50 /*
51  * Original for direct RGIP Metafile output.
52  */
53 /*
54  * Max pixels for X and Y in one window is 10000.
55  */
56 /*
57  * adapted to the new terminal layout by Stefan Bodewig (Dec. 1995)
58  */
59
60 #include "driver.h"
61
62 #ifdef TERM_REGISTER
63 register_term(rgip)
64 register_term(uniplex)
65 #endif
66
67 #ifdef TERM_PROTO
68 TERM_PUBLIC void RGIP_init __PROTO((void));
69 TERM_PUBLIC void RGIP_graphics __PROTO((void));
70 TERM_PUBLIC void RGIP_text __PROTO((void));
71 TERM_PUBLIC void RGIP_linetype __PROTO((int lt));
72 TERM_PUBLIC void RGIP_move __PROTO((unsigned int x, unsigned int y));
73 TERM_PUBLIC void RGIP_vector __PROTO((unsigned int ux, unsigned int uy));
74 TERM_PUBLIC int RGIP_text_angle __PROTO((int ang));
75 TERM_PUBLIC int RGIP_justify_text __PROTO((enum JUSTIFY mode));
76 TERM_PUBLIC void RGIP_put_text __PROTO((unsigned int x, unsigned int y, const char *str));
77 TERM_PUBLIC void RGIP_reset __PROTO((void));
78 TERM_PUBLIC void RGIP_do_point __PROTO((unsigned int x, unsigned int y, int number));
79 TERM_PUBLIC void RGIP_options __PROTO((void));
80 #define RGIP_X_MAX 10000
81 #define RGIP_Y_MAX 6700
82
83 #define RGIP_FONTSIZE 1
84 #define RGIP_SC (300)
85 #define RGIP_XMAX 9900
86 #define RGIP_YMAX 6600
87 #define RGIP_HTIC (100)
88 #define RGIP_VTIC (100)
89 #define RGIP_VCHAR (RGIP_FONTSIZE*RGIP_SC)
90 #define RGIP_HCHAR (RGIP_VCHAR*3/7)
91 #endif /* TERM_PROTO */
92
93 #ifndef TERM_PROTO_ONLY
94 #ifdef TERM_BODY
95
96
97 void RGIP_write_poly __PROTO((void));
98 static unsigned char *RGIP_cvts __PROTO((unsigned char *str, int *lcnt));
99 /* static void RGIP_setfont __PROTO((int sz)); */
100
101 #include <sys/types.h>
102 #include <sys/stat.h>
103
104 #define RGIPDOTS 0
105 #define RGIPMARK 1
106 #define RGIPTEXT 2
107 #define RGIPLINE 3
108 #define RGIPPOLY 4
109 #define RGIP_MAX_POLY 250
110 static char *RGIP_Obj[6] =
111 {"DOTS", "MARK", "TEXT", "LINE", "POLY"};
112
113 /*
114  * RGIP fontsises range from 1 to 8
115  */
116
117 #define RGIP_FACES 3
118 #define RGIP_FSTYLES 4
119 #define RGIP_FSIZES 8
120 #define RGIP_HELVETICA 0
121 #define RGIP_TIMES 1
122 #define RGIP_COURIER 2
123 #define RGIP_LINE_WIDTHS 8      /* future, currently invisible and visible 0
124                                    and 1 */
125 #define RGIP_LINE_TYPES 8
126 #define RGIP_COLORS 16
127 #define RGIP_POINT_TYPES 8
128
129
130
131
132 static int RGIP_orgX;           /* absolute-pixel-ORIgin of graph.      */
133 static int RGIP_orgY;
134 static int RGIP_orgx;           /* absolute-pixel-ORIgin of current plot. */
135 static int RGIP_orgy;
136 static int RGIP_posx;           /* current drawing position (lines).    */
137 static int RGIP_posy;
138 /* static int RGIP_inplot; */
139 static int RGIP_xmax = RGIP_XMAX;       /* width of graph in pixels.         */
140 static int RGIP_ymax = RGIP_YMAX;       /* height of graph in pixels.        */
141 static int RGIP_winx = RGIP_XMAX;       /* width of graph in pixels.         */
142 static int RGIP_winy = RGIP_YMAX;       /* height of graph in pixels.        */
143 /* static int RGIP_blofs; */            /* BaseLine OFfSet from bounding box.*/
144 static int RGIP_angle = 0;      /* 0 for horizontal text, 90 for vertical */
145 static int RGIP_portrait = 0;   /* 0 for horizontal text, 90 for vertical */
146 static enum JUSTIFY RGIP_justify = LEFT;        /* left/center/right */
147 static int RGIP_fface = 2;      /* Times */
148 static int RGIP_ftype = 1;      /* style roman */
149 static int RGIP_fontsize = RGIP_FONTSIZE;       /*  */
150 static int RGIP_tcol = 7;       /* text color */
151 static int RGIP_lsty = 1;       /* line style */
152 static int RGIP_lcol = 7;       /* line color */
153 static int RGIP_lwid = 1;       /* line width */
154 static int RGIP_fsty = 8;       /* fill style */
155 static int RGIP_fcol = 8;       /* fill color */
156 static int RGIP_mcol = 7;       /* marker color */
157 static int RGIP_msty = 1;       /* marker style */
158 static int RGIP_msize = 1;      /* marker size */
159
160 static int RGIP_win_horiz = 1;
161 static int RGIP_win_verti = 1;
162 static int RGIP_plot_nr = 0;
163
164 unsigned int RGIP_vecpos;
165 unsigned int RGIP_xvector[RGIP_MAX_POLY];
166 unsigned int RGIP_yvector[RGIP_MAX_POLY];
167 static unsigned char *RGIP_cvts();
168
169
170 TERM_PUBLIC void
171 RGIP_init()
172 {
173     register struct termentry *t = term;
174
175     RGIP_posx = RGIP_posy = 0;
176
177     if (RGIP_portrait) {
178         RGIP_orgX = (RGIP_Y_MAX - RGIP_YMAX) / 2;
179         RGIP_orgY = (RGIP_X_MAX - RGIP_XMAX) / 2;
180         RGIP_xmax = RGIP_winx = (int) (RGIP_YMAX / RGIP_win_horiz);
181         RGIP_ymax = RGIP_winy = (int) (RGIP_XMAX / RGIP_win_verti);
182     } else {
183         RGIP_orgX = (RGIP_X_MAX - RGIP_XMAX) / 2;
184         RGIP_orgY = (RGIP_Y_MAX - RGIP_YMAX) / 2;
185         RGIP_xmax = RGIP_winx = (int) (RGIP_XMAX / RGIP_win_horiz);
186         RGIP_ymax = RGIP_winy = (int) (RGIP_YMAX / RGIP_win_verti);
187     }
188
189     t->xmax = (unsigned int) (RGIP_xmax);
190     t->ymax = (unsigned int) (RGIP_ymax);
191
192     RGIP_vecpos = 0;
193 }
194
195 TERM_PUBLIC void
196 RGIP_graphics()
197 {
198     static int Gnr = 0;
199     struct stat buf;
200     unsigned char *p, fn[128];
201
202     int tmpx, tmpy;
203     /*    int xoff, yoff; */
204
205     if (RGIP_vecpos) {
206         RGIP_write_poly();
207     }
208     if (!Gnr || RGIP_plot_nr >= (RGIP_win_horiz * RGIP_win_verti)) {
209         fstat(fileno(gpoutfile), &buf);
210         if (S_ISREG(buf.st_mode)) {
211             if (outstr && (p = (unsigned char *) strchr(outstr, 'X'))) {
212                 /* substitute X with graphnr */
213                 if (!Gnr) {     /* delete the base file */
214                     unlink(outstr);     /* should we close it first ? ? ? */
215                 } else {
216                     fputs("%RI_GROUPEND\n", gpoutfile);
217                     fclose(gpoutfile);
218                 }
219                 *p = NUL;
220                 sprintf(fn, "%s%1d%s", outstr, ++Gnr, p + 1);
221                 if ((gpoutfile = fopen(fn, "w")) == (FILE *) NULL) {
222                     os_error(NO_CARET, "cannot reopen file with binary type; output unknown");
223                 }
224                 *p = 'X';       /* put back X */
225             }
226         }
227         fprintf(gpoutfile, "\
228 %RGIP_METAFILE: 1.0a\n\
229 %RI_GROUPSTART\n\
230 0 0 %d %d SetWindow\n\
231 100 100 %d %d 10 1 7 1 8 BOX\n",
232                 (RGIP_portrait) ? RGIP_Y_MAX : RGIP_X_MAX,
233                 (RGIP_portrait) ? RGIP_X_MAX : RGIP_Y_MAX,
234                 (RGIP_portrait) ? RGIP_YMAX : RGIP_XMAX,
235                 (RGIP_portrait) ? RGIP_XMAX : RGIP_YMAX);
236         RGIP_plot_nr = 0;
237     } else {
238         fputs("%RI_GROUPEND\n", gpoutfile);
239     }
240     fputs("%RI_GROUPSTART\n", gpoutfile);
241     RGIP_plot_nr++;
242     /* Gnr++; */
243     tmpx = RGIP_orgX + ((RGIP_plot_nr - 1) % RGIP_win_horiz) * RGIP_winx;
244     tmpy = RGIP_orgY + ((RGIP_win_verti - 1) - (int) ((RGIP_plot_nr - 1) / RGIP_win_horiz)) * RGIP_winy;
245     RGIP_orgx = tmpx + (int) ((RGIP_winx - RGIP_xmax) / 2);
246     RGIP_orgy = tmpy + (int) ((RGIP_winy - RGIP_ymax) / 2);
247
248
249     /* RGIP_linetype(-1); */
250 }
251
252 TERM_PUBLIC void
253 RGIP_text()
254 {
255 }
256
257 TERM_PUBLIC void
258 RGIP_linetype(int lt)
259 {
260 /*    int pen, pattern; */
261
262     if (RGIP_vecpos) {
263         RGIP_write_poly();
264     }
265
266     if (lt <= LT_BLACK) {
267         lt = 1;
268         RGIP_lwid = 5;
269     } else if (lt == LT_AXIS) {
270         lt = 5;
271         RGIP_lwid = 2;
272     } else {
273         RGIP_lwid = (int) (lt / RGIP_LINE_TYPES);
274         if (RGIP_lwid < 1)
275             RGIP_lwid = 1;
276         RGIP_lwid *= 2;
277         lt = (lt % RGIP_LINE_TYPES) + 1;
278     }
279     fputs("%RI_GROUPEND\n\
280 %RI_GROUPSTART\n", gpoutfile);
281
282     /* RGIP_lsty  = (lt == 0 || lt == 2) ? 1 : lt; */
283
284     RGIP_lsty = lt;
285 }
286
287
288 TERM_PUBLIC void
289 RGIP_move(unsigned int x, unsigned int y)
290 {
291 /*
292     fputs("%RI_GROUPEND\n", gpoutfile);
293     fputs("%RI_GROUPSTART\n", gpoutfile);
294 */
295     if (RGIP_vecpos) {
296         RGIP_write_poly();
297     }
298     RGIP_xvector[0] = x + RGIP_orgx;
299     RGIP_yvector[0] = y + RGIP_orgy;
300     RGIP_vecpos = 1;
301     /*
302        RGIP_posx = x;
303        RGIP_posy = y;
304      */
305 }
306
307
308 TERM_PUBLIC void
309 RGIP_vector(unsigned int ux, unsigned int uy)
310 {
311     /* store polygon-node */
312
313     RGIP_xvector[RGIP_vecpos] = ux + RGIP_orgx;
314     RGIP_yvector[RGIP_vecpos] = uy + RGIP_orgy;
315     RGIP_vecpos++;
316     if (RGIP_vecpos >= RGIP_MAX_POLY) {
317         RGIP_write_poly();
318         RGIP_xvector[RGIP_vecpos] = ux + RGIP_orgx;
319         RGIP_yvector[RGIP_vecpos] = uy + RGIP_orgy;
320         RGIP_vecpos++;
321     }
322 }
323
324 void
325 RGIP_write_poly()
326 {
327     register int i;
328
329     putc('[', gpoutfile);
330     for (i = 0; i < RGIP_vecpos; i++) {
331         if (!(i % 8))
332             putc('\n', gpoutfile);
333         fprintf(gpoutfile, " %1d\
334  %1d",
335                 RGIP_xvector[i],
336                 RGIP_yvector[i]);
337     }
338     RGIP_vecpos = 0;
339     putc(']', gpoutfile);
340
341     fprintf(gpoutfile, " %1d %d %1d %1d %1d %s\n", RGIP_lwid, RGIP_lsty,
342             RGIP_lcol, RGIP_fsty, RGIP_fcol, RGIP_Obj[RGIPPOLY]);
343
344     /*
345        RGIP_posx = ux;
346        RGIP_posy = uy;
347      */
348     /* RGIP_move(ux, uy); */
349 }
350
351
352 TERM_PUBLIC int
353 RGIP_text_angle(int ang)
354 {
355     if (RGIP_vecpos) {
356         RGIP_write_poly();
357     }
358     if (RGIP_angle != ang) {
359         RGIP_angle = ang;       /* record for later use */
360     }
361     return (TRUE);
362 }
363
364 TERM_PUBLIC int
365 RGIP_justify_text(enum JUSTIFY mode)
366 {
367     if (RGIP_vecpos) {
368         RGIP_write_poly();
369     }
370     RGIP_justify = mode;
371     return (TRUE);
372 }
373
374 static unsigned char *
375 RGIP_cvts(unsigned char *str, int *lcnt)
376 {
377     unsigned char *cp1;
378     unsigned char *cp2;
379     static unsigned char *buf = NULL;
380     int lc = 1;
381
382     lc = 1;
383     /* Free up old buffer, if there is one, get a new one.  Since       */
384     /* all transformations shorten the string, get a buffer that is     */
385     /* the same size as the input string.                               */
386
387     if (buf != NULL)
388         (void) free(buf);
389     buf = (unsigned char *) gp_alloc(strlen(str), "converted label string");
390
391     /* Do the transformations. */
392
393     cp1 = str;
394     cp2 = buf;
395     while (strlen(cp1) > 0) {
396         switch (*cp1) {
397         case '\\':              /* Escape sequence. */
398             if (*++cp1 == '\\') {
399                 /* Begin new line. */
400                 *cp2++ = '\n';
401                 lc++;
402                 break;
403             }
404         case '(':
405             *cp2++ = '\\';
406             *cp2++ = '(';
407             break;
408         case ')':
409             *cp2++ = '\\';
410             *cp2++ = ')';
411             break;
412             /* Fall through to just copy next char out. */
413
414         default:
415             *cp2++ = *cp1;
416             break;
417         }
418         cp1++;
419     }
420
421     *cp2++ = '\n';
422     *cp2 = NUL;
423     *lcnt = lc;
424     return (buf);
425 }
426
427 TERM_PUBLIC void
428 RGIP_put_text(unsigned int x, unsigned int y, const char *str)
429 {
430     register struct termentry *t = term;
431     unsigned char *cvstr, *p;
432     int xlines;                 /* lines */
433
434     if (RGIP_vecpos) {
435         RGIP_write_poly();
436     }
437     cvstr = RGIP_cvts(str, &xlines);
438
439     x += RGIP_orgx,
440         y += RGIP_orgy;
441
442     if (!RGIP_angle) {          /* horisontal */
443         y += (int) (t->v_char) * (xlines - 2) / 2;
444         /* y += (t->v_char)*xlines; */
445         y += (int) (t->v_char) / 4;
446     } else {
447         x -= (int) (t->v_char) * (xlines - 2) / 2;
448         x -= (int) (t->v_char) / 4;
449     }
450
451     while ((p = (unsigned char *) strchr(cvstr, '\n'))) {
452         *p = '\0';
453         if (strlen(cvstr))
454             fprintf(gpoutfile, "%1d %1d %1d  %1d (%s) %1d %1d %1d %1d %s\n",
455                     x, y, RGIP_justify, RGIP_angle, cvstr, RGIP_fface,
456                     RGIP_ftype, RGIP_fontsize, RGIP_tcol, RGIP_Obj[RGIPTEXT]);
457         cvstr = ++p;
458         if (RGIP_angle) {       /* vertical */
459             x += (t->v_char);
460         } else {
461             y -= (t->v_char);
462         }
463     }
464 }
465
466
467 TERM_PUBLIC void
468 RGIP_reset()
469 {
470     if (RGIP_vecpos) {
471         RGIP_write_poly();
472     }
473     fputs("%RI_GROUPEND\n", gpoutfile);
474     /* fputs("%RI_GROUPEND\n", gpoutfile); */
475 }
476
477 #if 0 /* HBB 20040619: found commented out --- why? */
478 RGIP_setfont(int sz)
479 {
480     RGIP_fontsize = (int) (sz);
481     if ( RGIP_fontsize < 1 )
482         RGIP_fontsize = 1;
483     term->v_char = RGIP_fontsize * RGIP_SC;
484     term->h_char = RGIP_fontsize * RGIP_SC * 3 / 7;
485 }
486 #endif
487
488 TERM_PUBLIC void
489 RGIP_do_point(unsigned int x, unsigned int y, int number)
490 {
491
492     x += RGIP_orgx,
493         y += RGIP_orgy;
494
495     if (number < 0) {           /* do dot */
496         fprintf(gpoutfile, "%1d %1d %1d %s\n",
497                 x, y, RGIP_mcol, RGIP_Obj[RGIPDOTS]);
498         return;
499     }
500     RGIP_msty = (number % RGIP_POINT_TYPES) + 1;
501     RGIP_msize = ((int) (number / RGIP_POINT_TYPES)) + 1;
502
503     fprintf(gpoutfile, "%1d %1d %1d %1d %1d %s\n",
504             x, y, RGIP_msize, RGIP_msty, RGIP_mcol, RGIP_Obj[RGIPMARK]);
505 }
506
507 TERM_PUBLIC void
508 RGIP_options()
509 {
510     struct value a;
511
512     while (!END_OF_COMMAND) {
513         if (almost_equals(c_token, "p$ortrait")) {
514             RGIP_portrait = TRUE;
515             c_token++;
516         } else if (almost_equals(c_token, "l$andscape")) {
517             RGIP_portrait = FALSE;
518             c_token++;
519         } else if (equals(c_token, "[")) {      /* windows spesified */
520             c_token++;
521             /* if (RGIP_plot_nr>1) */
522             if (equals(c_token, "]")) {
523                 /* RGIP_page(); */
524                 c_token++;
525                 continue;
526             }
527             if (END_OF_COMMAND) {
528                 int_error(c_token, "no. windows: [horizontal,vertical] expected");
529             } else if (!equals(c_token, ",")) {
530                 RGIP_win_horiz = (int) real(const_express(&a));
531             }
532             if (!equals(c_token, ","))
533                 int_error(c_token, "',' expected");
534             c_token++;
535             if (!equals(c_token, "]")) {
536                 RGIP_win_verti = (int) real(const_express(&a));
537             }
538             if (!equals(c_token, "]"))
539                 int_error(c_token, "expecting ']'");
540             c_token++;
541         } else {
542             /* We have font size specified */
543             RGIP_fontsize = (int) real(const_express(&a));
544             if (RGIP_fontsize < 1)
545                 RGIP_fontsize = 1;
546             term->v_char = (unsigned int) (RGIP_fontsize * RGIP_SC);
547             term->h_char = (unsigned int) (RGIP_fontsize * RGIP_SC * 3 / 7);
548         }
549     }
550     sprintf(term_options, "%s %d [%1d,%1d]",
551             (RGIP_portrait) ? "portrait" : "landscape",
552             RGIP_fontsize, RGIP_win_horiz, RGIP_win_verti);
553 }
554
555 #endif /* TERM_BODY */
556
557 #ifdef TERM_TABLE
558
559 TERM_TABLE_START(rgip_driver)
560     "rgip", "RGIP metafile (Uniplex). Option: fontsize (1-8)",
561     RGIP_XMAX, RGIP_YMAX, RGIP_VCHAR, RGIP_HCHAR,
562     RGIP_VTIC, RGIP_HTIC, RGIP_options, RGIP_init, RGIP_reset,
563     RGIP_text, null_scale, RGIP_graphics, RGIP_move,
564     RGIP_vector, RGIP_linetype, RGIP_put_text, RGIP_text_angle,
565     RGIP_justify_text, RGIP_do_point, do_arrow, set_font_null
566 TERM_TABLE_END(rgip_driver)
567
568 #undef LAST_TERM
569 #define LAST_TERM rgip_driver
570
571 TERM_TABLE_START(uniplex_driver)
572     "uniplex", "RGIP metafile (Uniplex). Option: fontsize (1-8) (Same as rgip)",
573     RGIP_XMAX, RGIP_YMAX, RGIP_VCHAR, RGIP_HCHAR,
574     RGIP_VTIC, RGIP_HTIC, RGIP_options, RGIP_init, RGIP_reset,
575     RGIP_text, null_scale, RGIP_graphics, RGIP_move,
576     RGIP_vector, RGIP_linetype, RGIP_put_text, RGIP_text_angle,
577     RGIP_justify_text, RGIP_do_point, do_arrow, set_font_null
578 TERM_TABLE_END(uniplex_driver)
579
580 #undef LAST_TERM
581 #define LAST_TERM uniplex_driver
582
583 #endif /* TERM_TABLE */
584 #endif /* TERM_PROTO_ONLY */
585
586 #ifdef TERM_HELP
587 START_HELP(rgip)
588 "1 rgip",
589 "?commands set terminal rgip",
590 "?set terminal rgip",
591 "?set term rgip",
592 "?terminal rgip",
593 "?term rgip",
594 "?rgip",
595 "?commands set terminal uniplex",
596 "?set terminal uniplex",
597 "?set term uniplex",
598 "?terminal uniplex",
599 "?term uniplex",
600 "?uniplex",
601 " The `rgip` and `uniplex` terminal drivers support RGIP metafiles.  They can",
602 " combine several graphs on a single page, but only one page is allowed in a",
603 " given output file.",
604 "",
605 " Syntax:",
606 "       set terminal rgip | uniplex {portrait | landscape}",
607 "                                   {[<horiz>,<vert>]} {<fontsize>}",
608 "",
609 " permissible values for the font size are in the range 1--8, with the default",
610 " being 1.  The default layout is landscape.  Graphs are placed on the page in",
611 " a `horiz`x`vert` grid, which defaults to [1,1].",
612 "",
613 " Example:",
614 "       set terminal uniplex portrait [2,3]",
615 "",
616 " puts six graphs on a page in three rows of two in portrait orientation."
617 END_HELP(rgip)
618 #endif /* TERM_HELP */