/usr/bin/gnuplot symlinks packageing problems were fixed gor gnuplot-x11
[gnuplot] / term / dumb.trm
1 /* Hello, Emacs, this is -*-C-*-
2  * $Id: dumb.trm,v 1.26.2.1 2008/08/16 18:11:53 sfeam Exp $
3  *
4  */
5
6 /* GNUPLOT - dumb.trm */
7
8 /*[
9  * Copyright 1991 - 1993, 1998, 2004   Thomas Williams, Colin Kelley
10  *
11  * Permission to use, copy, and distribute this software and its
12  * documentation for any purpose with or without fee is hereby granted,
13  * provided that the above copyright notice appear in all copies and
14  * that both that copyright notice and this permission notice appear
15  * in supporting documentation.
16  *
17  * Permission to modify the software is granted, but not the right to
18  * distribute the complete modified source code.  Modifications are to
19  * be distributed as patches to the released version.  Permission to
20  * distribute binaries produced by compiling modified sources is granted,
21  * provided you
22  *   1. distribute the corresponding source modifications from the
23  *    released version in the form of a patch file along with the binaries,
24  *   2. add special version identification to distinguish your version
25  *    in addition to the base release version number,
26  *   3. provide your name and address as the primary contact for the
27  *    support of your modified version, and
28  *   4. retain our contact information in regard to use of the base
29  *    software.
30  * Permission to distribute the released version of the source code along
31  * with corresponding source modifications in the form of a patch file is
32  * granted with same provisions 2 through 4 for binary distributions.
33  *
34  * This software is provided "as is" without express or implied warranty
35  * to the extent permitted by applicable law.
36 ]*/
37
38 /*
39  * This file is included by ../term.c.
40  *
41  * This terminal driver supports:
42  *   DUMB terminals
43  *
44  * AUTHORS
45  *   Francois Pinard, 91-04-03
46  *           INTERNET: pinard@iro.umontreal.ca
47  *
48  *   Ethan A Merritt Nov 2003
49  *      Added support for enhanced text mode.
50  *      Yes, this is frivolous, but it serves as an example for
51  *      adding enhanced text to other terminals.  You can disable
52  *      it by adding a line
53  *      #define NO_DUMB_ENHANCED_SUPPORT
54  *
55  * send your comments or suggestions to (gnuplot-info@lists.sourceforge.net).
56  *
57  */
58 #include "driver.h"
59
60 #ifdef TERM_REGISTER
61 register_term(dumb_driver)
62 #endif
63
64 #ifdef TERM_PROTO
65 TERM_PUBLIC void DUMB_options __PROTO((void));
66 TERM_PUBLIC void DUMB_init __PROTO((void));
67 TERM_PUBLIC void DUMB_graphics __PROTO((void));
68 TERM_PUBLIC void DUMB_text __PROTO((void));
69 TERM_PUBLIC void DUMB_reset __PROTO((void));
70 TERM_PUBLIC void DUMB_linetype __PROTO((int linetype));
71 TERM_PUBLIC void DUMB_move __PROTO((unsigned int x, unsigned int y));
72 TERM_PUBLIC void DUMB_point __PROTO((unsigned int x, unsigned int y,
73                                      int point));
74 TERM_PUBLIC void DUMB_vector __PROTO((unsigned int x, unsigned int y));
75 TERM_PUBLIC void DUMB_put_text __PROTO((unsigned int x, unsigned int y,
76                                         const char *str));
77 TERM_PUBLIC void DUMB_arrow __PROTO((unsigned int sx, unsigned int sy,
78                                      unsigned int ex, unsigned int ey,
79                                      int head));
80
81 #ifndef NO_DUMB_ENHANCED_SUPPORT
82 /* To support "set term dumb enhanced" (don't ask why!) */
83 TERM_PUBLIC void ENHdumb_put_text __PROTO((unsigned int x, unsigned int y, const char str[]));
84 TERM_PUBLIC void ENHdumb_OPEN __PROTO((char * fontname, double fontsize,
85                                     double base, TBOOLEAN widthflag, TBOOLEAN showflag,
86                                     int overprint));
87 TERM_PUBLIC void ENHdumb_FLUSH __PROTO((void));
88 #else
89 #define ENHdumb_put_text NULL
90 #endif
91
92
93 #define DUMB_XMAX 79
94 #define DUMB_YMAX 24
95
96 #endif /* TERM_PROTO */
97
98 #ifdef TERM_BODY
99
100 #define DUMB_AXIS_CONST '\1'
101 #define DUMB_BORDER_CONST '\2'
102
103 /* matrix of characters */
104 static char *dumb_matrix = NULL;
105 /* matrix of priority at each position */
106 static char *dumb_priority = NULL;
107 /* current character used to draw */
108 static char dumb_pen;
109 /* current X position */
110 static int dumb_x;
111 /* current Y position */
112 static int dumb_y;
113 static int dumb_xmax = DUMB_XMAX;
114 static int dumb_ymax = DUMB_YMAX;
115 static int dumb_feed = 1;
116
117 #define DUMB_PIXEL(x,y) dumb_matrix[dumb_xmax*(y)+(x)]
118
119 static void dumb_set_pixel __PROTO((int x, int y, int v, int p));
120
121 enum DUMB_id { DUMB_FEED, DUMB_NOFEED, DUMB_ENH, DUMB_NOENH, DUMB_SIZE, DUMB_OTHER };
122
123 static struct gen_table DUMB_opts[] =
124 {
125     { "f$eed", DUMB_FEED },
126     { "nof$eed", DUMB_NOFEED },
127     { "enh$anced", DUMB_ENH },
128     { "noe$nhanced", DUMB_NOENH },
129     { "size", DUMB_SIZE },
130     { NULL, DUMB_OTHER }
131 };
132
133 TERM_PUBLIC void
134 DUMB_options()
135 {
136     int x, y;
137     struct value a;
138
139     while (!END_OF_COMMAND) {
140         switch(lookup_table(&DUMB_opts[0],c_token)) {
141         case DUMB_FEED:
142             c_token++;
143             dumb_feed = 1;
144             break;
145         case DUMB_NOFEED:
146             c_token++;
147             dumb_feed = 0;
148             break;
149 #ifndef NO_DUMB_ENHANCED_SUPPORT
150         case DUMB_ENH:
151             c_token++;
152             term->put_text = ENHdumb_put_text;
153             term->flags |= TERM_ENHANCED_TEXT;
154             break;
155         case DUMB_NOENH:
156             c_token++;
157             term->put_text = DUMB_put_text;
158             term->flags &= ~TERM_ENHANCED_TEXT;
159             break;
160 #endif
161         case DUMB_SIZE:
162             c_token++;
163             /* Fall through */
164
165         case DUMB_OTHER:
166         default:
167             x = (int) real(const_express(&a));
168             if (!END_OF_COMMAND) {
169                 if (equals(c_token,","))
170                     c_token++;
171                 y = (int) real(const_express(&a));
172                 dumb_xmax = term->xmax = x;
173                 dumb_ymax = term->ymax = y;
174             }
175             break;
176         }
177     }
178
179     sprintf(term_options, "%sfeed %s %d %d",
180             dumb_feed ? "" : "no",
181             term->put_text == ENHdumb_put_text ? "enhanced" : "",
182             dumb_xmax, dumb_ymax);
183 }
184
185
186 static void
187 dumb_set_pixel(int x, int y, int v, int p)
188 {
189     if ((unsigned) x <= dumb_xmax &&    /* ie x>=0 && x<=dumb_xmax */
190         (unsigned) y <= dumb_ymax &&
191         p > dumb_priority[dumb_xmax * y + x]) {
192         dumb_matrix[dumb_xmax * y + x] = v;
193         dumb_priority[dumb_xmax * y + x] = p;
194     }
195 }
196
197
198 TERM_PUBLIC void
199 DUMB_init()
200 {
201     if (dumb_matrix)
202         free(dumb_matrix);
203
204     dumb_matrix = gp_alloc((dumb_xmax+1) * (dumb_ymax+1) * 2, "dumb terminal");
205
206     dumb_priority = dumb_matrix + dumb_xmax * dumb_ymax;
207 }
208
209
210 TERM_PUBLIC void
211 DUMB_graphics()
212 {
213     int i;
214     char *pm = dumb_matrix, *pp = dumb_priority;
215
216     for (i = dumb_xmax * dumb_ymax; i > 0; i--) {
217         *pm++ = ' ';
218         *pp++ = 0;
219     }
220 }
221
222
223 TERM_PUBLIC void
224 DUMB_text()
225 {
226     int x, y, l;
227
228     putc('\f', gpoutfile);
229     for (y = dumb_ymax - 1; y >= 0; y--) {
230         for (l = dumb_xmax; l > 0 && DUMB_PIXEL(l - 1, y) == ' '; l--);
231         for (x = 0; x < l; x++)
232             putc(DUMB_PIXEL(x, y), gpoutfile);
233         if (dumb_feed || y > 0)
234             putc('\n', gpoutfile);
235     }
236     fflush(gpoutfile);
237 }
238
239
240 TERM_PUBLIC void
241 DUMB_reset()
242 {
243     if (dumb_matrix)
244         free(dumb_matrix);
245     dumb_matrix = NULL;
246 }
247
248
249 TERM_PUBLIC void
250 DUMB_linetype(int linetype)
251 {
252     static char pen_type[7] = { '*', '#', '$', '%', '@', '&', '=' };
253
254     if (linetype == LT_BLACK)
255         dumb_pen = DUMB_BORDER_CONST;
256     else if (linetype == LT_AXIS)
257         dumb_pen = DUMB_AXIS_CONST;
258     else if (linetype <= LT_NODRAW)
259         dumb_pen = ' ';
260     else {
261         linetype = linetype % 7;
262         dumb_pen = pen_type[linetype];
263     }
264 }
265
266
267 TERM_PUBLIC void
268 DUMB_move(unsigned int x, unsigned int y)
269 {
270     dumb_x = x;
271     dumb_y = y;
272 }
273
274
275 TERM_PUBLIC void
276 DUMB_point(unsigned int x, unsigned int y, int point)
277 {
278     dumb_set_pixel(x, y, point == -1 ? '.' : point % 26 + 'A', 4);
279 }
280
281
282 TERM_PUBLIC void
283 DUMB_vector(unsigned int arg_x, unsigned int arg_y)
284 {
285     int x = arg_x;              /* we need signed int, since
286                                  * unsigned-signed=unsigned and */
287     int y = arg_y;              /* abs and cast to double wouldn't work */
288     char pen, pen1;
289     int priority;
290     int delta;
291
292     if (ABS(y - dumb_y) > ABS(x - dumb_x)) {
293         switch (dumb_pen) {
294         case DUMB_AXIS_CONST:
295             pen = ':';
296             pen1 = '+';
297             priority = 1;
298             break;
299
300         case DUMB_BORDER_CONST:
301             pen = '|';
302             pen1 = '+';
303             priority = 2;
304             break;
305
306         default:
307             pen = dumb_pen;
308             pen1 = dumb_pen;
309             priority = 3;
310             break;
311         }
312         dumb_set_pixel(dumb_x, dumb_y, pen1, priority);
313         for (delta = 1; delta < ABS(y - dumb_y); delta++) {
314             dumb_set_pixel(dumb_x  + (int) ((double) (x - dumb_x) *
315                                             delta / ABS(y - dumb_y) + 0.5),
316                            dumb_y + delta * sign(y - dumb_y), pen, priority);
317         }
318         dumb_set_pixel(x, y, pen1, priority);
319     } else if (ABS(x - dumb_x) > ABS(y - dumb_y)) {
320         switch (dumb_pen) {
321         case DUMB_AXIS_CONST:
322             pen = '.';
323             pen1 = '+';
324             priority = 1;
325             break;
326
327         case DUMB_BORDER_CONST:
328             pen = '-';
329             pen1 = '+';
330             priority = 2;
331             break;
332
333         default:
334             pen = dumb_pen;
335             pen1 = dumb_pen;
336             priority = 3;
337             break;
338         }
339         dumb_set_pixel(dumb_x, dumb_y, pen1, priority);
340         for (delta = 1; delta < ABS(x - dumb_x); delta++)
341             dumb_set_pixel(dumb_x + delta * sign(x - dumb_x),
342                            dumb_y +
343                            (int) ((double) (y - dumb_y) * delta / ABS(x - dumb_x)
344                                   + 0.5),
345                            pen, priority);
346         dumb_set_pixel(x, y, pen1, priority);
347     } else {
348         switch (dumb_pen) {
349         case DUMB_AXIS_CONST:   /* zero length axis */
350             pen = '+';
351             priority = 1;
352             break;
353
354         case DUMB_BORDER_CONST: /* zero length border */
355             pen = '+';
356             priority = 2;
357             break;
358
359         default:
360             pen = dumb_pen;
361             priority = 3;
362             break;
363         }
364         for (delta = 0; delta <= ABS(x - dumb_x); delta++)
365             dumb_set_pixel(dumb_x + delta * sign(x - dumb_x),
366                            dumb_y + delta * sign(y - dumb_y),
367                            pen, priority);
368     }
369     dumb_x = x;
370     dumb_y = y;
371 }
372
373
374 TERM_PUBLIC void
375 DUMB_put_text(unsigned int x, unsigned int y, const char *str)
376 {
377     int length;
378
379     length = strlen(str);
380     if (x + length > dumb_xmax)
381         x = GPMAX(0, dumb_xmax - length);
382
383     for (; x < dumb_xmax && *str; x++, str++)
384         dumb_set_pixel(x, y, *str, 5);
385 }
386
387
388 TERM_PUBLIC void
389 DUMB_arrow(
390     unsigned int sx, unsigned int sy,
391     unsigned int ex, unsigned int ey,
392     int head)           /* ignored */
393 {
394     char saved_pen;
395     char saved_x;
396     char saved_y;
397
398     (void) head;                /* dummy usage avoid compiler warnings */
399     saved_pen = dumb_pen;
400     saved_x = dumb_x;
401     saved_y = dumb_y;
402
403     dumb_pen = '>';
404     dumb_x = sx;
405     dumb_y = sy;
406     DUMB_vector(ex, ey);
407
408     dumb_pen = saved_pen;
409     dumb_x = saved_x;
410     dumb_y = saved_y;
411 }
412
413
414 #ifndef NO_DUMB_ENHANCED_SUPPORT
415 /*
416  * The code from here on serves as an example of how to
417  * add enhanced text mode support to even a dumb driver.
418  */
419
420 static TBOOLEAN ENHdumb_opened_string;
421 static TBOOLEAN ENHdumb_show = TRUE;
422 static int ENHdumb_overprint = 0;
423 static TBOOLEAN ENHdumb_widthflag = TRUE;
424 static unsigned int ENHdumb_xsave, ENHdumb_ysave;
425 #define ENHdumb_fontsize 1
426 #define ENHdumb_font ""
427 static double ENHdumb_base;
428
429 TERM_PUBLIC void
430 ENHdumb_OPEN(
431     char *fontname,
432     double fontsize, double base,
433     TBOOLEAN widthflag, TBOOLEAN showflag,
434     int overprint)
435 {
436     /* There are two special cases:
437      * overprint = 3 means save current position
438      * overprint = 4 means restore saved position
439      */
440     if (overprint == 3) {
441         ENHdumb_xsave = dumb_x;
442         ENHdumb_ysave = dumb_y;
443         return;
444     } else if (overprint == 4) {
445         DUMB_move(ENHdumb_xsave, ENHdumb_ysave);
446         return;
447     }
448
449
450     if (!ENHdumb_opened_string) {
451         ENHdumb_opened_string = TRUE;
452         /* Start new text fragment */
453             enhanced_cur_text = &enhanced_text[0];
454         /* Scale fractional font height to vertical units of display */
455             ENHdumb_base = base * 2;
456         /* Keep track of whether we are supposed to show this string */
457             ENHdumb_show = showflag;
458         /* 0/1/2  no overprint / 1st pass / 2nd pass */
459             ENHdumb_overprint = overprint;
460         /* widthflag FALSE means do not update text position after printing */
461             ENHdumb_widthflag = widthflag;
462         /* Many drivers will need to do something about font selection here */
463             /* but dumb is dumb */
464     }
465 }
466
467 TERM_PUBLIC void
468 ENHdumb_FLUSH()
469 {
470     char *str = enhanced_text;  /* The fragment to print */
471     int x = dumb_x;             /* The current position  */
472     int len;
473
474     if (ENHdumb_opened_string) {
475         *enhanced_cur_text = '\0';
476         len = strlen(str);
477
478         /* print the string fragment, perhaps invisibly */
479         /* NB: base expresses offset from current y pos */
480         for (; x < dumb_xmax && *str; x++, str++)
481             if (ENHdumb_show)
482                 dumb_set_pixel(x, dumb_y+ENHdumb_base, *str, 5);
483
484         if (!ENHdumb_widthflag)
485             /* don't update position */
486             ;
487         else if (ENHdumb_overprint == 1)
488             /* First pass of overprint, leave position in center of fragment */
489             dumb_x += len / 2;
490         else
491             /* Normal case is to update position to end of fragment */
492             dumb_x += len;
493
494         ENHdumb_opened_string = FALSE;
495     }
496 }
497
498 TERM_PUBLIC void
499 ENHdumb_put_text(unsigned int x, unsigned int y, const char *str)
500 {
501     /* If no enhanced text processing is needed, we can use the plain  */
502     /* vanilla put_text() routine instead of this fancy recursive one. */
503     if (ignore_enhanced_text || !strpbrk(str, "{}^_@&~")) {
504         DUMB_put_text(x,y,str);
505         return;
506     }
507
508     /* Set up global variables needed by enhanced_recursion() */
509     enhanced_fontscale = 1.0;
510     ENHdumb_opened_string = FALSE;
511     strncpy(enhanced_escape_format,"%c",sizeof(enhanced_escape_format));
512
513     DUMB_move(x,y);
514
515     /* Set the recursion going. We say to keep going until a
516      * closing brace, but we don't really expect to find one.
517      * If the return value is not the nul-terminator of the
518      * string, that can only mean that we did find an unmatched
519      * closing brace in the string. We increment past it (else
520      * we get stuck in an infinite loop) and try again.
521      */
522     while (*(str = enhanced_recursion((char *)str, TRUE,
523                         ENHdumb_font, ENHdumb_fontsize,
524                         0.0, TRUE, TRUE, 0))) {
525         (term->enhanced_flush)();
526
527         /* I think we can only get here if *str == '}' */
528             enh_err_check(str);
529
530         if (!*++str)
531             break; /* end of string */
532
533         /* else carry on and process the rest of the string */
534     }
535 }
536 #endif /* NO_DUMB_ENHANCED_SUPPORT */
537
538 #endif /* TERM_BODY */
539
540 #ifdef TERM_TABLE
541 TERM_TABLE_START(dumb_driver)
542     "dumb", "ascii art for anything that prints text",
543     DUMB_XMAX, DUMB_YMAX, 1, 1,
544     1, 1, DUMB_options, DUMB_init, DUMB_reset,
545     DUMB_text, null_scale, DUMB_graphics, DUMB_move, DUMB_vector,
546     DUMB_linetype, DUMB_put_text, null_text_angle,
547     null_justify_text, DUMB_point, DUMB_arrow, set_font_null,
548     0,                          /* pointsize */
549     TERM_CAN_MULTIPLOT,
550     NULL, NULL, NULL, NULL
551 #ifdef USE_MOUSE
552     , NULL, NULL, NULL, NULL, NULL
553 #endif
554     , NULL, NULL, NULL, NULL
555 #ifdef WITH_IMAGE
556     , NULL
557 #endif
558 #ifndef NO_DUMB_ENHANCED_SUPPORT
559     , ENHdumb_OPEN, ENHdumb_FLUSH, do_enh_writec
560 #endif /* NO_DUMB_ENHANCED_SUPPORT */
561 TERM_TABLE_END(dumb_driver)
562
563 #undef LAST_TERM
564 #define LAST_TERM dumb_driver
565
566 #endif /* TERM_TABLE */
567
568 #ifdef TERM_HELP
569 START_HELP(dumb)
570 "1 dumb",
571 "?commands set terminal dumb",
572 "?set terminal dumb",
573 "?set term dumb",
574 "?terminal dumb",
575 "?term dumb",
576 "?dumb",
577 " The `dumb` terminal driver has an optional size specification and trailing",
578 " linefeed control.",
579 "",
580 " Syntax:",
581 "       set terminal dumb {[no]feed} {<xsize> <ysize>}",
582 #ifndef NO_DUMB_ENHANCED_SUPPORT
583 "                         {[no]enhanced}",
584 #endif
585 "",
586 " where <xsize> and <ysize> set the size of the dumb terminals. Default is",
587 " 79 by 24. The last newline is printed only if `feed` is enabled.",
588 "",
589 " Examples:",
590 "       set term dumb nofeed",
591 "       set term dumb 79 49 # VGA screen---why would anyone do that?"
592 END_HELP(dumb)
593 #endif /* TERM_HELP */