Initial release of Maemo 5 port of gnuplot
[gnuplot] / term / win.trm
1 /* Hello, Emacs, this is -*-C-*-
2  * $Id: win.trm,v 1.52.2.5 2008/09/09 16:42:52 sfeam Exp $
3  */
4
5 /* GNUPLOT - win.trm */
6
7 /*[
8  * Copyright 1992 - 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  *
39  * AUTHORS
40  *
41  *   Gnuplot for Windows:
42  *       Maurice Castro, Russell Lang
43  *
44  */
45
46
47 /* This file implements the terminal and printer display for gnuplot  */
48 /* under Microsoft Windows.                                           */
49 /*                                                                    */
50 /* The modifications to allow Gnuplot to run under Windows were made  */
51 /* by Maurice Castro (maurice@bruce.cs.monash.edu.au)                 */
52 /* and Russell Lang (rjl@monu1.cc.monash.edu.au)         19 Nov 1992  */
53 /*                                                                    */
54
55 /* Edit this file with tabstop=4 (vi :se ts=4)                        */
56
57 /*
58  * adapted to the new terminal layout by Stefan Bodewig (Dec. 1995)
59  */
60
61 #include "driver.h"
62
63 #ifdef TERM_REGISTER
64 register_term(windows)
65 #endif
66
67 #ifdef TERM_PROTO
68 TERM_PUBLIC void WIN_options __PROTO((void));
69 TERM_PUBLIC void WIN_init __PROTO((void));
70 TERM_PUBLIC void WIN_reset __PROTO((void));
71 TERM_PUBLIC void WIN_text __PROTO((void));
72 TERM_PUBLIC void WIN_graphics __PROTO((void));
73 TERM_PUBLIC void WIN_move __PROTO((unsigned int x, unsigned int y));
74 TERM_PUBLIC void WIN_vector __PROTO((unsigned int x, unsigned int y));
75 TERM_PUBLIC void WIN_linetype __PROTO((int lt));
76 TERM_PUBLIC void WIN_put_text __PROTO((unsigned int x, unsigned int y, const char *str));
77 TERM_PUBLIC int WIN_justify_text __PROTO((enum JUSTIFY mode));
78 TERM_PUBLIC int WIN_text_angle __PROTO((int ang));
79 TERM_PUBLIC void WIN_point __PROTO((unsigned int x, unsigned int y, int number));
80 TERM_PUBLIC void WIN_resume __PROTO((void));
81 TERM_PUBLIC void WIN_set_pointsize __PROTO((double));
82 TERM_PUBLIC void WIN_linewidth __PROTO((double linewidth));
83 #ifdef USE_MOUSE
84 TERM_PUBLIC void WIN_set_ruler __PROTO((int, int));
85 TERM_PUBLIC void WIN_set_cursor __PROTO((int, int, int));
86 TERM_PUBLIC void WIN_put_tmptext __PROTO((int, const char str[]));
87 TERM_PUBLIC void WIN_set_clipboard __PROTO((const char[]));
88 #endif
89 TERM_PUBLIC int WIN_make_palette __PROTO((t_sm_palette *palette));
90 TERM_PUBLIC void WIN_set_color __PROTO((t_colorspec *));
91 TERM_PUBLIC void WIN_filled_polygon __PROTO((int points, gpiPoint *corners));
92 TERM_PUBLIC void WIN_boxfill __PROTO((int, unsigned int, unsigned int, unsigned int, unsigned int));
93 /* To support "set term win enhanced" */
94 TERM_PUBLIC int WIN_set_font __PROTO((const char *font));
95 TERM_PUBLIC void WIN_enhanced_put_text __PROTO((unsigned int x, unsigned int y, const char *str));
96 TERM_PUBLIC void WIN_enhanced_open __PROTO((char * fontname, double fontsize,
97                         double base, TBOOLEAN widthflag, TBOOLEAN showflag,
98                         int overprint));
99 TERM_PUBLIC void WIN_enhanced_flush __PROTO((void));
100 #ifdef WITH_IMAGE
101 TERM_PUBLIC void WIN_image __PROTO((unsigned int, unsigned int, coordval *, gpiPoint *, t_imagecolor));
102 #endif
103
104
105 /* Initialization values - Guess Now Scale later */
106 #define WIN_XMAX (24000)
107 #define WIN_YMAX (18000)
108 #define WIN_HCHAR (WIN_XMAX/75)
109 #define WIN_VCHAR (WIN_YMAX/25)
110 #define WIN_HTIC (WIN_XMAX/160)
111 #define WIN_VTIC WIN_HTIC
112 #endif /* TERM_PROTO */
113
114 #ifndef TERM_PROTO_ONLY
115 #ifdef TERM_BODY
116
117 #include <windows.h>
118 #include "win/winmain.h"
119
120 #ifdef __MSC__
121 #include <io.h>                 /* for mktemp() */
122 #endif
123
124 #define WIN_POINT_TYPES 15      /* 20010411: raised */
125
126 /* Interface routines - create list of actions for Windows */
127
128 enum WIN_id { WIN_DEFAULT, WIN_MONOCHROME, WIN_COLOR,
129               WIN_ENHANCED, WIN_NOENHANCED, WIN_FONT, WIN_OTHER };
130
131 static struct gen_table WIN_opts[] =
132 {
133     { "d$efault", WIN_DEFAULT },
134     { "m$onochrome", WIN_MONOCHROME },
135     { "c$olor", WIN_COLOR },
136     { "c$olour", WIN_COLOR },
137     { "noenh$anced", WIN_NOENHANCED },
138     { "enh$anced", WIN_ENHANCED },
139     { "font", WIN_FONT },
140     { NULL, WIN_OTHER }
141 };
142
143 static int WIN_last_linetype = LT_NODRAW; /* HBB 20000813: linetype caching */
144
145 /* these variables are needed for enhanced text only */
146
147 /* FIXME: these are duplicates of struct graphwin members */
148 static char WIN_font[MAXFONTNAME] = WINFONT; 
149 static int WIN_fontsize = WINFONTSIZE;
150 static double WIN_angle = 0.;  /* unit is radian */
151
152 /* FIXME: these should most likely be members of struct graphwin */
153 static unsigned int WIN_x = 0;
154 static unsigned int WIN_y = 0;
155 static enum JUSTIFY WIN_justification = LEFT;
156
157 /* state variables for enhanced text processing */
158 static TBOOLEAN ENHwin_opened_string;
159 static TBOOLEAN ENHwin_show = TRUE;
160 static int ENHwin_overprint = 0;
161 static TBOOLEAN ENHwin_widthflag = TRUE;
162 static TBOOLEAN ENHwin_sizeonly = FALSE;
163 static double ENHwin_base;
164
165
166 TERM_PUBLIC void
167 WIN_options()
168 {
169     struct value a;
170     char *s;
171     TBOOLEAN set_font = FALSE, set_fontsize = FALSE;
172
173     while (!END_OF_COMMAND) {
174         switch(lookup_table(&WIN_opts[0],c_token)) {
175         case WIN_DEFAULT:
176             graphwin.color = TRUE;
177             strcpy(graphwin.fontname, WINFONT);
178             graphwin.fontsize = WINFONTSIZE;
179             strcpy(graphwin.deffontname, WINFONT);
180             graphwin.deffontsize = WINFONTSIZE;
181             c_token++;
182             break;
183         case WIN_MONOCHROME:
184             graphwin.color = FALSE;
185             c_token++;
186             break;
187         case WIN_COLOR:
188             graphwin.color = TRUE;
189             c_token++;
190             break;
191         case WIN_ENHANCED:
192             c_token++;
193             term->put_text = WIN_enhanced_put_text;
194             term->flags |= TERM_ENHANCED_TEXT;
195             break;
196         case WIN_NOENHANCED:
197             c_token++;
198             term->put_text = WIN_put_text;
199             term->flags &= ~TERM_ENHANCED_TEXT;
200             break;
201         case WIN_FONT:
202             c_token++;
203             /* Fall through to attempt to read font name */
204         case WIN_OTHER:
205         default:
206             /* Code copied from ps.trm and modified for windows terminal */
207             if ((s = try_to_get_string())) {
208                 char *comma;
209                 if (set_font)
210                     int_error(c_token,
211                               "extraneous argument in set terminal %s",
212                               term->name);
213                 set_font = TRUE;
214                 comma = strrchr(s,',');
215                 if (comma && (1 == sscanf(comma+1,"%i", &graphwin.fontsize))) {
216                     graphwin.deffontsize = graphwin.fontsize;
217                     set_fontsize = TRUE;
218                     *comma = '\0';
219                 }
220                 if (*s) {
221                     strncpy(graphwin.fontname, s, MAX_ID_LEN);
222                     strcpy(graphwin.deffontname, graphwin.fontname);
223                     free(s);
224                 }
225             } else {
226                 if (set_fontsize)
227                     int_error(c_token,
228                               "extraneous argument in set terminal %s",
229                               term->name);
230                 set_fontsize = TRUE;
231                 /* We have font size specified */
232                 graphwin.fontsize = (int) real(const_express(&a));
233                 graphwin.deffontsize = graphwin.fontsize;
234             }
235             break;
236         }
237     }
238
239     if (graphwin.fontname[0] == '\0')
240         sprintf(term_options, "%s %s", 
241                 graphwin.color ? "color" : "monochrome", 
242                 term->flags & TERM_ENHANCED_TEXT ? "enhanced" : "noenhanced");
243     else
244         sprintf(term_options, "%s %s font \"%s, %d\"",
245                 graphwin.color ? "color" : "monochrome",
246                 term->flags & TERM_ENHANCED_TEXT ? "enhanced" : "noenhanced",
247                 graphwin.fontname, graphwin.fontsize);
248
249     if (IsWindow(graphwin.hWndGraph) && IsIconic(graphwin.hWndGraph))
250         ShowWindow(graphwin.hWndGraph, SW_SHOWNORMAL);
251
252     GraphRedraw(&graphwin);
253 }
254
255 /* We don't actually do scaling, but we need to fix up the text size
256  * if the user has resized the window.
257  * Routine unused -- terminals are not allowed to do their own scale().
258  */
259 #if 0
260 int
261 WIN_scale()
262 {
263     term->h_char = graphwin.hchar;
264     term->v_char = graphwin.vchar;
265     term->h_tic = graphwin.htic;
266     term->v_tic = graphwin.vtic;
267     sprintf(term_options, "%s \"%s\" %d",
268             graphwin.color ? "color" : "monochrome",
269             graphwin.fontname, graphwin.fontsize);
270     return FALSE;               /* can't be done */
271 }
272 #endif
273
274 TERM_PUBLIC void
275 WIN_init()
276 {
277     if (!graphwin.hWndGraph) {
278         graphwin.xmax = WIN_XMAX;
279         graphwin.ymax = WIN_YMAX;
280         graphwin.htic = WIN_HTIC;
281         graphwin.vtic = WIN_VTIC;
282         GraphInit(&graphwin);
283 #ifdef WIN32
284         SetClassLong(graphwin.hWndGraph, GCL_HICON, (LONG) LoadIcon(graphwin.hInstance, "GRPICON"));
285 #else
286         SetClassWord(graphwin.hWndGraph, GCW_HICON, LoadIcon(graphwin.hInstance, "GRPICON"));
287 #endif
288         graphwin.resized = FALSE;
289     }
290     WIN_last_linetype = LT_NODRAW;      /* HBB 20000813: linetype caching */
291 }
292
293
294 TERM_PUBLIC void
295 WIN_reset()
296 {
297 }
298
299 TERM_PUBLIC void
300 WIN_text()
301 {
302     GraphEnd(&graphwin);
303 }
304
305 TERM_PUBLIC void
306 WIN_graphics()
307 {
308     GraphStart(&graphwin, pointsize);
309     WIN_last_linetype = LT_NODRAW;              /* HBB 20000813: linetype caching */
310 }
311
312 TERM_PUBLIC void
313 WIN_move(unsigned int x, unsigned int y)
314 {
315     /* Notice HBB 20010208: on Win32 platforms, passing int or
316      * unsigned int arguments to GraphOp() might cause problems: int
317      * is 32bits, but GraphOp() args are 16bit WORDS. */
318     GraphOp(&graphwin, W_move, x, y, NULL);
319
320     /* save current position, only needed for enhanced text */
321     WIN_x = x; 
322     WIN_y = y;
323 }
324
325 TERM_PUBLIC void
326 WIN_vector(unsigned int x, unsigned int y)
327 {
328     /* Notice HBB 20010208: --> WIN_move() */
329     GraphOp(&graphwin, W_vect, x, y, NULL);
330 }
331
332 TERM_PUBLIC void
333 WIN_linetype(int lt)
334 {
335     if (lt != WIN_last_linetype) {
336         /* Notice HBB 20010208: --> see WIN_move() */
337         GraphOp(&graphwin, W_line_type, lt, 0, NULL);
338         WIN_last_linetype = lt;
339     }
340 }
341
342 TERM_PUBLIC void
343 WIN_put_text(unsigned int x, unsigned int y, const char *str)
344 {
345     /* Notice HBB 20010208: --> WIN_move() */
346     GraphOp(&graphwin, W_put_text, x, y, str);
347 }
348
349 TERM_PUBLIC int
350 WIN_justify_text(enum JUSTIFY mode)
351 {
352     /* Notice HBB 20010208: --> WIN_move() */
353     GraphOp(&graphwin, W_justify, mode, 0, NULL);
354     /* store text justification, only needed for enhanced text */
355     WIN_justification = mode;
356     return (TRUE);
357 }
358
359 TERM_PUBLIC int
360 WIN_text_angle(int ang)
361 {
362     if (graphwin.rotate) {
363         /* Notice HBB 20010208: --> WIN_move() */
364         GraphOp(&graphwin, W_text_angle, ang, 0, NULL);
365
366         /* store text angle, only needed for enhanced text */
367         WIN_angle = (double)ang * M_PI / 180.;
368     }
369     return graphwin.rotate;
370 }
371
372 TERM_PUBLIC void
373 WIN_point(unsigned int x, unsigned int y, int number)
374 {
375     /* draw point shapes later to save memory */
376     /* size of point symbols */
377     graphwin.htic = pointsize * term->h_tic / 2;
378     graphwin.vtic = pointsize * term->v_tic / 2;
379     /* HBB 20010411: secure against pointtype -1 or lower */
380     if (number < -1)
381         number = -1;            /* refuse nonsense values */
382     if (number >= 0)
383         number %= WIN_POINT_TYPES;
384     number += 1;
385     /* Notice HBB 20010208: --> WIN_move() */
386     GraphOp(&graphwin, W_dot + number, x, y, NULL);
387 }
388
389 TERM_PUBLIC void
390 WIN_resume()
391 {
392     GraphResume(&graphwin);
393 }
394
395 TERM_PUBLIC void
396 WIN_set_pointsize(double s)
397 {
398     /* Save new pointsize as string */
399     char scale[30];
400
401     if (s < 0)
402         s = 1;
403     sprintf(scale, "%.15g", s);
404 #if 1
405     /* HBB 980309: it seems passing it as a string is a bad idea
406      * in Win16: it means the wgnuplot.dll has to parse the string
407      * via sscanf(), leading to crash (by stack overflow?). Alternative:
408      * pass it as a scaled-up integer. For the sake of compatibility,
409      * pass the string as well. */
410     /* Notice HBB 20010208: --> WIN_move() */
411     GraphOp(&graphwin, W_pointsize, (int) 100 * s, 0, scale);
412 #else
413     GraphOp(&graphwin, W_pointsize, 0, 0, scale);
414 #endif
415 }
416
417 TERM_PUBLIC void
418 WIN_linewidth(double linewidth)
419 {
420     /* HBB 20000813: New routine */
421     WIN_last_linetype = LT_NODRAW;        /* invalidate cached linetype */
422     /* Notice HBB 20010208: --> WIN_move() */
423     GraphOp(&graphwin, W_line_width, (int) 100 * linewidth, 0, NULL);
424 }
425
426 #ifdef USE_MOUSE
427
428 /* Implemented by Petr Mikulik, February 2001 --- the best Windows solutions
429  * come from OS/2 :-))
430  */
431
432 TERM_PUBLIC void
433 WIN_put_tmptext ( int i, const char str[] )
434 {
435     Graph_put_tmptext(&graphwin, i, str );
436 }
437
438 TERM_PUBLIC void
439 WIN_set_ruler ( int x, int y )
440 {
441     Graph_set_ruler(&graphwin, x, y );
442 }
443
444 TERM_PUBLIC void
445 WIN_set_cursor ( int c, int x, int y )
446 {
447     Graph_set_cursor(&graphwin, c, x, y );
448 }
449
450 TERM_PUBLIC void
451 WIN_set_clipboard ( const char s[] )
452 {
453     Graph_set_clipboard(&graphwin, s);
454 }
455
456 #endif /* USE_MOUSE */
457
458
459 #ifdef WITH_IMAGE
460
461 /* Note: this is a verbatim copy of PM_image (pm.trm) with only minor changes */
462
463 TERM_PUBLIC void
464 WIN_image(unsigned int M, unsigned int N, coordval *image,
465           gpiPoint *corner, t_imagecolor color_mode)
466 {
467     PBYTE rgb_image;
468     unsigned int image_size;
469     unsigned int pad_bytes;
470
471     /* IC_PALETTE and IC_RGB images are converted to a 24bit RGB format
472        suitable for Windows:
473         - sequence of lines is reversed 
474         - each line starts at a 4 byte boundary
475     */
476
477     /* fprintf(stderr, "WIN_image: %i x %i, mode=%s\n", M, N, color_mode==IC_RGB?"IC_RGB":"IC_PALETTE" ); */
478     pad_bytes = (4 - (3 * M) % 4) % 4; /* scan lines start on ULONG boundaries */
479
480     image_size = (M + pad_bytes ) * N * 3;
481     rgb_image = (PBYTE) gp_alloc(image_size, "WIN RGB image");
482
483     if (color_mode == IC_PALETTE) {
484         unsigned int x, y;
485
486         rgb_image += N * (3 * M + pad_bytes);
487         for (y=0; y<N; y++) {
488             rgb_image -= 3 * M + pad_bytes;
489             for(x=0; x<M; x++) {
490                 rgb255_color rgb255;
491                 rgb255maxcolors_from_gray(*image++, &rgb255);
492                 *(rgb_image++) = rgb255.b;
493                 *(rgb_image++) = rgb255.g;
494                 *(rgb_image++) = rgb255.r;
495             }
496             rgb_image -= 3 * M;
497         }
498     } else if (color_mode == IC_RGB) {
499         unsigned int x, y;
500
501         rgb_image += N * (3 * M + pad_bytes);
502         for (y=0; y<N; y++) {
503             rgb_image -= 3 * M + pad_bytes;
504             for(x=0; x<M; x++) {
505                 rgb255_color rgb255;
506                 rgb255.r = (BYTE) (*image++ * 255 + 0.5);
507                 rgb255.g = (BYTE) (*image++ * 255 + 0.5);
508                 rgb255.b = (BYTE) (*image++ * 255 + 0.5);
509                 *(rgb_image++) = rgb255.b;
510                 *(rgb_image++) = rgb255.g;
511                 *(rgb_image++) = rgb255.r;
512             }
513             rgb_image -= 3 * M;
514         }
515     }
516
517     /* squeze all the information into the buffer */
518     if ((color_mode == IC_PALETTE) || (color_mode == IC_RGB)) {
519         GraphOp(&graphwin, W_image, corner[0].x, corner[0].y, NULL);
520         GraphOp(&graphwin, W_image, corner[1].x, corner[1].y, NULL);
521         GraphOp(&graphwin, W_image, corner[2].x, corner[2].y, NULL);
522         GraphOp(&graphwin, W_image, corner[3].x, corner[3].y, NULL);
523         /* GraphOp() cannot be used here since the image might 
524            contain char(0), so use  GraphOpSize() instead */
525         GraphOpSize(&graphwin, W_image, M, N, rgb_image, image_size);
526     }
527
528     free(rgb_image);
529 }
530
531 #endif /* WITH_IMAGE */
532
533
534 TERM_PUBLIC int
535 WIN_make_palette(t_sm_palette *palette)
536 {
537     /* Win can do continuous colors. However, we round them only to 256 levels
538      * in order to pass an integer to GraphOp; it also reasonably limits
539      * the number of colors if "copy to clipboard" is used. Don't change this
540      * number unless you change it also in WIN_set_color() and in wgraph.c.
541      */
542     return 256;
543 }
544
545 TERM_PUBLIC void
546 WIN_set_color(t_colorspec *colorspec)
547 {
548     switch (colorspec->type ) {
549         case TC_FRAC:
550             GraphOp(&graphwin, W_pm3d_setcolor, (int)(256*colorspec->value), 0, NULL);
551             break;
552         case TC_RGB:
553             GraphOp(&graphwin, W_pm3d_setcolor, (colorspec->lt) & 0xffff, 0xff00 | ((colorspec->lt >> 16) & 0x00ff), NULL);
554             break;
555         case TC_LT:
556             /* set color only when second parameter to W_line_type equals 1 */
557             GraphOp(&graphwin, W_line_type, colorspec->lt, 1, NULL);
558             break;
559     }
560     WIN_last_linetype = LT_NODRAW;      /* invalidate cached linetype */
561 }
562
563 TERM_PUBLIC void
564 WIN_filled_polygon(int points, gpiPoint *corners)
565 {
566     int i;
567     /* Notice HBB 20010208: --> WIN_move() */
568     for (i=0; i<points; i++)
569         GraphOp(&graphwin, W_pm3d_filled_polygon_pt, corners[i].x, corners[i].y, NULL);
570     /* finish series: */
571     GraphOp(&graphwin, W_pm3d_filled_polygon_draw, points, 0, NULL);
572 }
573
574 TERM_PUBLIC void
575 WIN_boxfill(
576     int style,
577     unsigned int xleft, unsigned int ybottom,
578     unsigned int width, unsigned int height)
579 {
580     /* split into two commands to squeeze through all the necessary info */
581     /* Notice HBB 20010208: --> WIN_move() */
582     GraphOp(&graphwin, W_fillstyle, style, 0, NULL);
583     GraphOp(&graphwin, W_move, xleft, ybottom, NULL);
584     GraphOp(&graphwin, W_boxfill, width, height, NULL);
585 }
586
587
588 TERM_PUBLIC int
589 WIN_set_font(const char *font)
590 {
591     char fontname[MAXFONTNAME];
592     int  fontsize;
593
594     if (font != NULL) {
595         if (font[0] == '\0') {
596             strcpy(fontname, graphwin.deffontname);
597             fontsize = graphwin.deffontsize;
598         } else {
599             char *size;
600
601             size = strrchr(font, ',');
602             if (size == NULL) {
603                 /* only font name given */
604                 strcpy(fontname, font);
605                 fontsize = graphwin.deffontsize;
606             } else if (size == font) {
607                 /* only font size given */
608                 strcpy(fontname, graphwin.deffontname);
609                 sscanf(size+1,"%i", &fontsize);
610             } else {
611                 /* full font information supplied */
612                 strncpy(fontname, font, size-font);
613                 fontname[size-font] = '\0';
614                 sscanf(size+1,"%i", &fontsize);
615             }
616         }
617     }
618
619     if (font != NULL) {
620         GraphOp(&graphwin, W_font, fontsize, 0, fontname);
621         strcpy(WIN_font, fontname);
622         WIN_fontsize = fontsize;
623     }
624     else {
625         GraphOp(&graphwin, W_font, 0, 0, "");
626         strcpy(WIN_font, graphwin.deffontname);
627         WIN_fontsize = graphwin.deffontsize;
628     }
629     return TRUE;
630 }
631
632
633 TERM_PUBLIC void
634 WIN_enhanced_open(
635     char *fontname,
636     double fontsize, double base,
637     TBOOLEAN widthflag, TBOOLEAN showflag,
638     int overprint)
639 {
640     static const int win_scale = 40; /* scaling of base offset */  
641     static unsigned int ENHwin_xsave, ENHwin_ysave;
642     char *fontstring;
643
644     /* There are two special cases:
645      * overprint = 3 means save current position
646      * overprint = 4 means restore saved position
647      */
648     if (overprint == 3) {
649         ENHwin_xsave = WIN_x;
650         ENHwin_ysave = WIN_y;
651         return;
652     } else if (overprint == 4) {
653         WIN_x = ENHwin_xsave;
654         WIN_y = ENHwin_ysave;
655         return;
656     }
657
658     if (!ENHwin_opened_string) {
659         ENHwin_opened_string = TRUE;
660
661         /* Start new text fragment */
662         enhanced_cur_text = &enhanced_text[0];
663
664         /* Keep track of whether we are supposed to show this string */
665         ENHwin_show = showflag;
666
667         /* 0/1/2  no overprint / 1st pass / 2nd pass */
668         ENHwin_overprint = overprint;
669
670         /* widthflag FALSE means do not update text position after printing */
671         ENHwin_widthflag = widthflag;
672
673         /* Scale fractional font height to vertical units of display */
674         /* FIXME:       
675                 Font scaling is not done properly (yet) and will lead to
676                 non-optimal results for most font and size selections.
677                 OUTLINEFONTMETRICS could be used for better here.
678         */
679         ENHwin_base = win_scale * base;
680          
681         /* Select font */
682         /* FIXME: It would be nice to have fractional font sizes 
683                   for super- and subscripts. */
684         /* FIXME: sometimes fontname has zero length */
685         if ((fontname != NULL) && strlen(fontname) > 0) {
686             fontstring = malloc(strlen(fontname) + 16);
687             sprintf(fontstring, "%s,%i", fontname, (int)fontsize);
688         } else {
689             fontstring = malloc( strlen(graphwin.deffontname) + 16 );
690             sprintf( fontstring, "%s,%i", graphwin.deffontname, (int)fontsize);
691         }
692         WIN_set_font( fontstring );
693         free( fontstring );
694    }
695 }
696
697
698 TERM_PUBLIC void
699 WIN_enhanced_flush()
700 {
701     static unsigned int ENHwin_xsave, ENHwin_ysave;
702
703     if (ENHwin_opened_string) {
704         int width, height;
705         unsigned int x, y, len;
706
707         *enhanced_cur_text = '\0';
708         
709         /* print the string fragment, perhaps invisibly */
710         /* NB: base expresses offset from current y pos */
711         x = WIN_x - ENHwin_base * sin(WIN_angle);
712         y = WIN_y + ENHwin_base * cos(WIN_angle);
713
714         /* calculate length of string first */
715         len = GraphGetTextLength(&graphwin, enhanced_text, WIN_font, WIN_fontsize);
716         width = cos(WIN_angle) * len;
717         height = sin(WIN_angle) * len;
718
719         if (ENHwin_show && !ENHwin_sizeonly) {
720             /* display string */
721             GraphOp(&graphwin, W_put_text, x, y, enhanced_text);
722         }
723
724         /* update drawing position according to len */
725         if (!ENHwin_widthflag) {
726             width = 0; 
727             height = 0;
728         }
729         if (ENHwin_sizeonly) {
730             /* This is the first pass for justified printing.        */
731             /* We just adjust the starting position for second pass. */
732             if (WIN_justification == RIGHT) {
733                 WIN_x -= width;
734                 WIN_y -= height;
735             }
736             else if (WIN_justification == CENTRE) {
737                 WIN_x -= width / 2;
738                 WIN_y -= height / 2;
739             }
740             /* nothing to do for LEFT justified text */
741         }
742         else if (ENHwin_overprint == 1) {
743             /* Save current position */
744             ENHwin_xsave = WIN_x + width;
745             ENHwin_ysave = WIN_y + height;
746             /* First pass of overprint, leave position in center of fragment */
747             WIN_x += width / 2;
748             WIN_y += height / 2;
749         }
750         else if (ENHwin_overprint == 2) {
751             /* Restore current position,                          */
752             /* this sets the position behind the overprinted text */
753             WIN_x = ENHwin_xsave;
754             WIN_y = ENHwin_ysave;
755         }
756         else {
757             /* Normal case is to update position to end of fragment */
758             WIN_x += width;
759             WIN_y += height;
760         }
761
762         ENHwin_opened_string = FALSE;
763     }
764 }
765
766
767 TERM_PUBLIC void
768 WIN_enhanced_put_text(unsigned int x, unsigned int y, const char *str)
769 {
770     char *original_string = (char *)str;
771     unsigned int pass, num_passes;
772
773     /* If no enhanced text processing is needed, we can use the plain  */
774     /* vanilla put_text() routine instead of this fancy recursive one. */
775     if (ignore_enhanced_text || !strpbrk(str, "{}^_@&~")) {
776         WIN_put_text(x,y,str);
777         return;
778     }
779
780     /* Set up global variables needed by enhanced_recursion() */
781     ENHwin_opened_string = FALSE;
782     enhanced_fontscale = 1.0;
783     strncpy(enhanced_escape_format,"%c",sizeof(enhanced_escape_format));
784
785     /* Tell the terminal to move the drawing position */
786     /* we store the current position to WIN_x and WIN_y */
787     WIN_x = x; 
788     WIN_y = y;
789
790     /* Text justification requires two passes. During the first pass we */
791     /* don't draw anything, we just measure the space it will take.     */
792     /* Without justification one pass is enough                         */
793     if (WIN_justification == LEFT) {
794         num_passes = 1;
795     }
796     else {
797         num_passes = 2;
798         ENHwin_sizeonly = TRUE; 
799     }
800
801     for( pass=1; pass <= num_passes; pass++ ) {
802
803         /* This will restore the default font 
804            and update WIN_font and WIN_fontsize */
805         WIN_set_font(NULL); 
806
807         /* Set the recursion going. We say to keep going until a
808         * closing brace, but we don't really expect to find one.
809         * If the return value is not the nul-terminator of the
810         * string, that can only mean that we did find an unmatched
811         * closing brace in the string. We increment past it (else
812         * we get stuck in an infinite loop) and try again.
813         */
814         while (*(str = enhanced_recursion((char *)str, TRUE,
815                         NULL, WIN_fontsize,
816                         0.0, TRUE, TRUE, 0))) {
817             (term->enhanced_flush)();
818
819             /* I think we can only get here if *str == '}' */
820             enh_err_check(str);
821
822             if (!*++str)
823                 break; /* end of string */
824
825             /* else carry on and process the rest of the string */
826         }
827
828         /* In order to do text justification we need to do a second pass that */
829         /* uses information stored during the first pass.                     */
830         /* see WIN_enhanced_flush()                                           */
831         if (pass == 1) {
832             /* do the actual printing in the next pass */
833             ENHwin_sizeonly = FALSE;
834             str = original_string;
835
836             /* temporarily switch to left alignment since we do it ourselves */
837             GraphOp(&graphwin, W_justify, LEFT, 0, NULL);
838         }
839     }
840
841     /* restore default font */
842     WIN_set_font(NULL); 
843
844     /* restore text alignment */
845     if (num_passes > 1)
846         GraphOp(&graphwin, W_justify, WIN_justification, 0, NULL);
847 }
848
849 #endif /* TERM_BODY */
850
851 #ifdef TERM_TABLE
852
853 TERM_TABLE_START(win_driver)
854     "windows", "Microsoft Windows",
855     WIN_XMAX, WIN_YMAX, WIN_VCHAR, WIN_HCHAR,
856     WIN_VTIC, WIN_HTIC, WIN_options, WIN_init, WIN_reset,
857     WIN_text, null_scale, WIN_graphics, WIN_move, WIN_vector,
858     WIN_linetype, WIN_put_text, WIN_text_angle,
859     WIN_justify_text, WIN_point, do_arrow, WIN_set_font,
860     WIN_set_pointsize, TERM_CAN_MULTIPLOT|TERM_NO_OUTPUTFILE,
861     WIN_text /* suspend */ , WIN_resume,
862     WIN_boxfill, WIN_linewidth
863 #ifdef USE_MOUSE
864     , 0 /* WIN_waitforinput */,
865     WIN_put_tmptext, WIN_set_ruler, WIN_set_cursor, WIN_set_clipboard
866 #endif
867     , WIN_make_palette, 0 /* previous_palette */,
868     WIN_set_color, WIN_filled_polygon
869 #ifdef WITH_IMAGE
870     , WIN_image
871 #endif
872     , WIN_enhanced_open, WIN_enhanced_flush, do_enh_writec
873 TERM_TABLE_END(win_driver)
874
875 #undef LAST_TERM
876 #define LAST_TERM win_driver
877
878 #endif /* TERM_TABLE */
879 #endif /* TERM_PROTO_ONLY */
880
881 #ifdef TERM_HELP
882 START_HELP(windows)
883 "1 windows",
884 "?commands set terminal windows",
885 "?set terminal windows",
886 "?set term windows",
887 "?terminal windows",
888 "?term windows",
889 "?windows",
890 " Three options may be set in the `windows` terminal driver.",
891 "",
892 " Syntax:",
893 "       set terminal windows {color | monochrome}",
894 "                            {enhanced | noenhanced}",
895 "                            {{font} \"fontname{,fontsize}\" {<fontsize>}}",
896 "",
897 " where `color` and `monochrome` select colored or mono output,", 
898 " `enhanced` enables enhanced text mode features (subscripts,",
899 " superscripts and mixed fonts). See `enhanced` for more information.",
900 " `\"<fontname>\"` is the name of a valid Windows font, and `<fontsize>`",
901 " is the size of the font in points.",
902 "",
903 " Other options may be set with the graph-menu or the initialization file.",
904 "",
905 " The Windows version normally terminates immediately as soon as the end of",
906 " any files given as command line arguments is reached (i.e. in non-interactive",
907 " mode), unless you specify `-` as the last command line option.",
908 " It will also not show the text-window at all, in this mode, only the plot.",
909 " By giving the optional argument `-persist` (same as for gnuplot under x11;",
910 " former Windows-only options `/noend` or `-noend` are still accepted as well),",
911 " will not close gnuplot. Contrary to gnuplot on other operating systems,",
912 " gnuplot's interactive command line is accessible after the -persist option.",
913 "2 graph-menu",
914 "?commands set terminal windows graph-menu",
915 "?set terminal windows graph-menu",
916 "?set term windows graph-menu",
917 "?windows graph-menu",
918 "?graph-menu",
919 " The `gnuplot graph` window has the following options on a pop-up menu",
920 " accessed by pressing the right mouse button or selecting `Options` from the",
921 " system menu:",
922 "",
923 " `Bring to Top` when checked brings the graph window to the top after every",
924 " plot.",
925 "",
926 " `Color` when checked enables color linestyles.  When unchecked it forces",
927 " monochrome linestyles.",
928 "",
929 " `Copy to Clipboard` copies a bitmap and a Metafile picture.",
930 "",
931 " `Background...` sets the window background color.",
932 "",
933 " `Choose Font...` selects the font used in the graphics window.",
934 "",
935 " `Line Styles...` allows customization of the line colors and styles.",
936 "",
937 " `Print...` prints the graphics windows using a Windows printer driver and",
938 " allows selection of the printer and scaling of the output.  The output",
939 " produced by `Print` is not as good as that from `gnuplot`'s own printer",
940 " drivers.",
941 "",
942 " `Update wgnuplot.ini` saves the current window locations, window sizes, text",
943 " window font, text window font size, graph window font, graph window font",
944 " size, background color and linestyles to the initialization file",
945 " `WGNUPLOT.INI`.",
946 "2 printing",
947 "?commands set terminal windows printing",
948 "?set terminal windows printing",
949 "?set term windows printing",
950 "?windows printing",
951 "?printing",
952 " In order of preference, graphs may be be printed in the following ways.",
953 "",
954 " `1.` Use the `gnuplot` command `set terminal` to select a printer and `set",
955 " output` to redirect output to a file.",
956 "",
957 " `2.` Select the `Print...` command from the `gnuplot graph` window.  An extra",
958 " command `screendump` does this from the text window.",
959 "",
960 " `3.` If `set output \"PRN\"` is used, output will go to a temporary file.  When",
961 " you exit from `gnuplot` or when you change the output with another `set",
962 " output` command, a dialog box will appear for you to select a printer port.",
963 " If you choose OK, the output will be printed on the selected port, passing",
964 " unmodified through the print manager.  It is possible to accidentally (or",
965 " deliberately) send printer output meant for one printer to an incompatible",
966 " printer.",
967 "2 text-menu",
968 "?commands set terminal windows text-menu",
969 "?set terminal windows text-menu",
970 "?set term windows text-menu",
971 "?windows text-menu",
972 "?text-menu",
973 " The `gnuplot text` window has the following options on a pop-up menu accessed",
974 " by pressing the right mouse button or selecting `Options` from the system",
975 " menu:",
976 "",
977 " `Copy to Clipboard` copies marked text to the clipboard.",
978 "",
979 " `Paste` copies text from the clipboard as if typed by the user.",
980 "",
981 " `Choose Font...` selects the font used in the text window.",
982 "",
983 " `System Colors` when selected makes the text window honor the System Colors",
984 " set using the Control Panel.  When unselected, text is black or blue on a",
985 " white background.",
986 "",
987 " `Update wgnuplot.ini` saves the current text window location, text window",
988 " size, text window font and text window font size to the initialisation file",
989 " `WGNUPLOT.INI`.",
990 "",
991 " `MENU BAR`",
992 "",
993 " If the menu file `WGNUPLOT.MNU` is found in the same directory as",
994 " WGNUPLOT.EXE, then the menu specified in `WGNUPLOT.MNU` will be loaded.",
995 " Menu commands:",
996 "",
997 " [Menu] starts a new menu with the name on the following line.",
998 "",
999 " [EndMenu] ends the current menu.",
1000 "",
1001 " [--] inserts a horizontal menu separator.",
1002 "",
1003 " [|] inserts a vertical menu separator.",
1004 "",
1005 " [Button] puts the next macro on a push button instead of a menu.",
1006 "",
1007 " Macros take two lines with the macro name (menu entry) on the first line and",
1008 " the macro on the second line.  Leading spaces are ignored.  Macro commands:",
1009 "",
1010 " [INPUT] --- Input string with prompt terminated by [EOS] or {ENTER}",
1011 "",
1012 " [EOS] --- End Of String terminator.  Generates no output.",
1013 "",
1014 " [OPEN] --- Get name of file to open from list box, with title of list box",
1015 " terminated by [EOS], followed by default filename terminated by [EOS] or",
1016 " {ENTER}.",
1017 "",
1018 " [SAVE] --- Get name of file to save.  Similar to [OPEN]",
1019 "",
1020 " Macro character substitutions:",
1021 "",
1022 " {ENTER} --- Carriage Return '\\r'",
1023 "",
1024 " {TAB} --- Tab '\\011'",
1025 "",
1026 " {ESC} --- Escape '\\033'",
1027 "",
1028 " {^A} --- '\\001'",
1029 "",
1030 " ...",
1031 "",
1032 " {^_} --- '\\031'",
1033 "",
1034 " Macros are limited to 256 characters after expansion.",
1035 "2 wgnuplot.ini",
1036 "?commands set terminal windows wgnuplot.ini",
1037 "?set terminal windows wgnuplot.ini",
1038 "?set term windows wgnuplot.ini",
1039 "?windows wgnuplot.ini",
1040 "?wgnuplot.ini",
1041 " Windows `gnuplot` will read some of its options from the `[WGNUPLOT]` section",
1042 " of `WGNUPLOT.INI` in user's %APPDATA% directory.  A sample `WGNUPLOT.INI` file:",
1043 "",
1044 "       [WGNUPLOT]",
1045 "       TextOrigin=0 0",
1046 "       TextSize=640 150",
1047 "       TextFont=Terminal,9",
1048 "       GraphOrigin=0 150",
1049 "       GraphSize=640 330",
1050 "       GraphFont=Arial,10",
1051 "       GraphColor=1",
1052 "       GraphToTop=1",
1053 "       GraphBackground=255 255 255",
1054 "       Border=0 0 0 0 0",
1055 "       Axis=192 192 192 2 2",
1056 "       Line1=0 0 255 0 0",
1057 "       Line2=0 255 0 0 1",
1058 "       Line3=255 0 0 0 2",
1059 "       Line4=255 0 255 0 3",
1060 "       Line5=0 0 128 0 4",
1061 "",
1062 " The `GraphFont` entry specifies the font name and size in points.  The five",
1063 " numbers given in the `Border`, `Axis` and `Line` entries are the `Red`",
1064 " intensity (0--255), `Green` intensity, `Blue` intensity, `Color Linestyle`",
1065 " and `Mono Linestyle`.  `Linestyles` are 0=SOLID, 1=DASH, 2=DOT, 3=DASHDOT,",
1066 " 4=DASHDOTDOT.  In the sample `WGNUPLOT.INI` file above, Line 2 is a green",
1067 " solid line in color mode, or a dashed line in monochrome mode.  The default",
1068 " line width is 1 pixel.  If `Linestyle` is negative, it specifies the width of",
1069 " a SOLID line in pixels.  Line1 and any linestyle used with the `points` style",
1070 " must be SOLID with unit width."
1071 END_HELP(windows)
1072 #endif /* TERM_HELP */