Initial release of Maemo 5 port of gnuplot
[gnuplot] / src / os2 / gclient.c
1 #ifdef INCRCSDATA
2 static char RCSid[]="$Id: gclient.c,v 1.47.2.1 2008/02/23 11:23:12 mikulik Exp $";
3 #endif
4
5 /****************************************************************************
6
7     PROGRAM: Gnupmdrv
8
9     MODULE:  gclient.c
10
11     This file contains the client window procedures for Gnupmdrv
12
13 ****************************************************************************/
14
15 /* PM driver for GNUPLOT */
16
17 /*[
18  * Copyright 1992, 1993, 1998, 2004   Roger Fearick
19  *
20  * Permission to use, copy, and distribute this software and its
21  * documentation for any purpose with or without fee is hereby granted,
22  * provided that the above copyright notice appear in all copies and
23  * that both that copyright notice and this permission notice appear
24  * in supporting documentation.
25  *
26  * Permission to modify the software is granted, but not the right to
27  * distribute the complete modified source code.  Modifications are to
28  * be distributed as patches to the released version.  Permission to
29  * distribute binaries produced by compiling modified sources is granted,
30  * provided you
31  *   1. distribute the corresponding source modifications from the
32  *    released version in the form of a patch file along with the binaries,
33  *   2. add special version identification to distinguish your version
34  *    in addition to the base release version number,
35  *   3. provide your name and address as the primary contact for the
36  *    support of your modified version, and
37  *   4. retain our contact information in regard to use of the base
38  *    software.
39  * Permission to distribute the released version of the source code along
40  * with corresponding source modifications in the form of a patch file is
41  * granted with same provisions 2 through 4 for binary distributions.
42  *
43  * This software is provided "as is" without express or implied warranty
44  * to the extent permitted by applicable law.
45 ]*/
46
47 /*
48  * AUTHOR
49  *
50  *   Gnuplot driver for OS/2:  Roger Fearick
51  *
52  *
53  * CONTRIBUTIONS:
54  *
55  *   Petr Mikulik  (see PM labels)
56  *       - menu item to keep aspect ratio on/off (October 1997)
57  *       - mouse support (1998, 1999); changes made after gnuplot 3.7.0.5:
58  *          - use gnuplot's pid in the name of shared memory (11. 5. 1999)
59  *          - mouse in maps; distance in polar coords (14. 5. 1999)
60  *          - event semaphore for sending data via shared memory;
61  *            zooming completely revised;
62  *            remap keys in 'case WM_CHAR';
63  *            Ctrl-C for breaking long drawings;
64  *            new menu items under 'Mouse' and 'Utilities' (August 1999)
65  *      - rewrite of mouse support for the new scheme common with X11
66  *            (October 1999 - January 2000)
67  *      - pm3d stuff (since January 1999)
68  *
69  *   Franz Bakan
70  *       - communication gnupmdrv -> gnuplot via shared memory (April 1999)
71  *       - date and time on x axis (August 1999)
72  */
73
74 #define INCL_PM
75 #define INCL_WIN
76 #define INCL_SPL
77 #define INCL_SPLDOSPRINT
78 #define INCL_WINSTDFONT
79 #define INCL_DOSMEMMGR
80 #define INCL_DOSPROCESS
81 #define INCL_DOSERRORS
82 #define INCL_DOSFILEMGR
83 #define INCL_DOSNMPIPES
84 #define INCL_DOSSESMGR
85 #define INCL_DOSSEMAPHORES
86 #define INCL_DOSMISC
87 #define INCL_DOSQUEUES
88 #define INCL_WINSWITCHLIST
89 #define INCL_GPIPRIMITIVES
90 #include <os2.h>
91 #include <string.h>
92 #include <stdio.h>
93 #include <io.h>
94 #include <fcntl.h>
95 #include <math.h>
96 #include <float.h>
97 #include <stdlib.h>
98 #include <unistd.h>
99 #include <process.h>
100 #include <signal.h>
101 #include <time.h>
102 #include "config.h"
103 #include "term_api.h"
104 #include "gnupmdrv.h"
105 #include "pm_msgs.h"
106 #define GNUPMDRV
107 #include "mousecmn.h"
108
109
110 /*==== m i s c e l l a n e o u s =============================================*/
111
112 /* February 2008, according to the gnuplot bugs report #1773922
113    The standard font selection dialog is somehow broken after saving options.
114    Use the font palette dialog instead.
115 */
116 /* #define STANDARD_FONT_DIALOG 1 */
117 #undef STANDARD_FONT_DIALOG
118
119 /*==== d e b u g g i n g =====================================================*/
120
121 #if 0
122 # include "pmprintf.h"
123 # define DEBUG_IMAGE(a) PmPrintf a
124 #else
125 # define DEBUG_IMAGE(a)
126 #endif
127
128 #if 0
129 # include "pmprintf.h"
130 # define DEBUG_COLOR(a) PmPrintf a
131 #else
132 # define DEBUG_COLOR(a)
133 #endif
134
135
136 /*==== l o c a l    d a t a ==================================================*/
137
138 static long lLineTypes[7] = {
139     LINETYPE_SOLID,
140     LINETYPE_SHORTDASH,
141     LINETYPE_DOT,
142     LINETYPE_DASHDOT,
143     LINETYPE_LONGDASH,
144     LINETYPE_DOUBLEDOT,
145     LINETYPE_DASHDOUBLEDOT
146 };
147
148 static long lCols[16] = {
149     CLR_BLACK,
150     CLR_DARKGRAY,
151     CLR_RED,
152     CLR_GREEN,
153     CLR_BLUE,
154     CLR_PINK,
155     CLR_CYAN,
156     CLR_BROWN,
157     CLR_YELLOW,
158     CLR_DARKBLUE,
159     CLR_DARKRED,
160     CLR_DARKGREEN,
161     CLR_DARKCYAN,
162     CLR_DARKPINK,
163     CLR_PALEGRAY,
164     CLR_WHITE
165 };
166
167 static long lCols_init = 0;
168 static long lCols_num = 16;
169 static long bkColor = -1;
170
171 /* Note that there are 16 colours used for drawing. The two more
172    entries in this array were added by Ilya to avoid drawing white
173    line on white background. */
174 #define nColors 16
175 static LONG alColourTable[nColors + 2];
176
177 static BOOL bPMPaletteMode = TRUE; /* do we use PM palette manager? */
178
179 /* RGB equivalents of all normal CLR_xxx colour constants
180    Note: First entry corresponds to CLR_WHITE, which is negative (-2)!
181 */
182 static LONG rgb_colors[18];
183 /* macro to facilitate translation */
184 #define RGB_TRANS(v) rgb_colors[(v)-CLR_WHITE]
185
186 /* A value of 0 indicates direct rgb colors without palette */
187 /* FIXME: gnupmdrv crashes if this is > GNUBUF/4 ! */
188 /* FIXME: this must be <= 256 (see PM_SET_COLOR)   */
189 #define   RGB_PALETTE_SIZE 0    /* size of the 'virtual' palette used for 
190                                    translation of index to RGB value */
191
192 /* FIXME: increasing GNUBUF circumvents a bug/limitation in BufRead:
193    it cannot read datablocks larger than GNUBUF */
194 #define   GNUBUF    131072
195 //#define   GNUBUF    2048        /* buffer for gnuplot commands */
196 #define   PIPEBUF   4096        /* size of pipe buffers */
197 #define   CMDALLOC  4096        /* command buffer allocation increment (ints) */
198
199 #define   PAUSE_DLG 1           /* pause handled in dialog box */
200 #define   PAUSE_BTN 2           /* pause handled by menu item */
201 #define   PAUSE_GNU 3           /* pause handled by Gnuplot */
202
203 #define   DEFLW     50
204
205 // ULONG    ppidGnu = 0L;  /* gnuplot pid  */ -- now in gpexecute.c
206 static HDC      hdcScreen;
207 static HPS      hpsScreen;     /* screen pres. space */
208 static int      iSeg = 1;
209
210 static HSWITCH hSwitch = 0;    /* switching between windows */
211 static SWCNTRL swGnu;
212
213 static BOOL     bLineTypes = FALSE;    // true if use dashed linetypes
214 static BOOL     bColours = TRUE;
215 static BOOL     bShellPos = FALSE;
216 static BOOL     bPopFront = TRUE;
217 static BOOL     bKeepRatio = TRUE;      //PM
218 #if 0
219 static BOOL     bNewFont = FALSE;
220 #endif
221
222 static double   multLineHor  = 1.; /* Horizontal and vertical spacing shifts */
223 static double   multLineVert = 0.; /* for multiline prints.                 */
224
225 static int      codepage = 0;
226
227 static int      ulMouseSprintfFormatItem = IDM_MOUSE_FORMAT_XcY;
228 static BOOL     bSend2gp = FALSE;
229 /* HBB FIXME 20040630: why isn't this 'static'? */
230 const  char  *SetDataStyles[] = {
231     "boxes", "dots", "fsteps", "histeps", "impulses",
232     "lines", "linespoints", "points", "steps"
233 };
234
235 struct {
236     int on;  // set to 1 during zooming
237     POINTL from, to; // corners
238 } zoombox = { 0 };
239
240
241 static int zooming = 0;  // set to 1 during zooming
242 static POINTL zoomrect_from, zoomrect_now;
243
244 static ULONG    ulPlotPos[4];
245 static ULONG    ulShellPos[4];
246 static PAUSEDATA pausedata = {sizeof(PAUSEDATA), NULL, NULL};
247 static char     szFontNameSize[FONTBUF];        /* default name and size, format: "10.Helvetica" */
248 /* FIXME: this might not always get updated on font change */
249 static char     szCurrentFontNameSize[FONTBUF]; /* currently selected font */
250 static PRQINFO3 infPrinter = { "" };
251 static QPRINT   qPrintData = {
252     sizeof(QPRINT), 0.0, 0.0, 1.0, 1.0, 0,
253     "", "", &infPrinter, 0, NULL
254 };
255 //static HEV      semStartSeq;   /* semaphore to start things in right sequence */
256 static HEV      semPause;
257 static HMTX     semHpsAccess;
258 static ULONG    ulPauseReply = 1;
259 static ULONG    ulPauseMode  = PAUSE_DLG;
260
261 static HWND     hSysMenu;
262             /* stuff for screen-draw thread control */
263
264 //static HEV      semDrawDone;
265
266             /* thread control */
267
268 static TID     tidDraw, tidSpawn;
269
270 static int breakDrawing = 0;
271             /* //PM flag for stopping (long) drawings */
272
273             /* font data */
274
275 static int lSupOffset = 0;
276 static int lSubOffset = 0;
277 static int lBaseSupOffset = 0;
278 static int lBaseSubOffset = 0;
279 static int lCharWidth = 217;
280 static int lCharHeight = 465;
281
282
283 //PM: Now variables for mouse
284
285 /* useMouse is set to 1 when user switches mousing on, e.g. the mouse is
286    allowed
287 */
288 static int useMouse = 0;
289
290 /* gnuplot's PM terminal sends GR_MOUSECAPABLE message from its init routine, which
291    sets the variable below to 1. Then we are sure that we talk to the
292    mouseable terminal and can read the mouseable data from the pipe.
293    Non-mouseable versions of PM terminal or non-new-gnuplot programs
294    using gnupmdrv will let this variable set to 0, thus no mousing occurs.
295 */
296 static char mouseTerminal = 0;
297
298
299 /* Lock (hide) mouse when building the plot (redrawing screen).
300    Otherwise gnupmdrv would crash when trying to display mouse position
301    in a window not yet plotted.
302 */
303 static char lock_mouse = 1;
304
305 /* Structure for the ruler: on/off, position,...
306 */
307 static struct {
308    int on;
309    int x, y;  /* ruler position */
310 } ruler = {0,0,0,};
311
312 // Pointer definition
313 HWND hptrDefault, hptrCrossHair, hptrScaling,
314     hptrRotating, hptrZooming, hptrCurrent;
315
316 // After passing gpPMmenu in PM_pipe and SET_GRAPHICS, it seems not to be possible
317 // to update the menu. Thus this flag is set on and menu is updated
318 // afterwards.
319 struct t_gpPMmenu gpPMmenu;
320 int gpPMmenu_update_req = 0;
321
322 // colours of mouse-relating drawings (CLR_DEFAULT is not allowed!)
323 #define COLOR_MOUSE    CLR_BLACK    // mouse position
324 #define COLOR_ANNOTATE CLR_BLACK    // annotating strings (MB3)
325 #define COLOR_RULER    CLR_DARKPINK // colour of the ruler
326 #define COLOR_ERROR    CLR_RED      // colour of error messages
327
328 static enum JUSTIFY jmode;
329
330 static SIZEF sizBaseSubSup;
331 static SIZEF sizCurSubSup;
332 static SIZEF sizCurFont;
333 static long lVOffset = 0;
334 static SIZEF sizBaseFont;
335
336 static struct _ft {
337     char *name;
338     LONG  lcid;
339 } tabFont[256] = {
340     {NULL,0L},
341     {NULL}
342 };
343
344
345 /*==== f u n c t i o n s =====================================================*/
346
347 int             DoPrint(HWND);
348 HBITMAP         CopyToBitmap(HPS);
349 HMF             CopyToMetaFile(HPS);
350 MRESULT         WmClientCmdProc(HWND , ULONG, MPARAM, MPARAM);
351 void            ChangeCheck(HWND, USHORT, USHORT);
352 BOOL            QueryIni(HAB);
353 static void     SaveIni(HWND);
354 static void     ThreadDraw(void*);
355 static void     DoPaint(HWND, HPS);
356 static void     SelectFont(HPS, char *);
357 static void     SwapFont(HPS, char *);
358 static void     CopyToClipBrd(HWND);
359 static void     ReadGnu(void*);
360 static void     EditLineTypes(HWND, HPS, BOOL);
361 #if 0
362 static void     EditCharCell(HPS, SIZEF*);
363 #endif
364 static HPS      InitScreenPS(void);
365 static int      BufRead(HFILE, void*, int, PULONG);
366 static int      GetNewFont(HWND, HPS);
367 void            SigHandler(int);
368 static void     FontExpand(char *);
369 #ifdef PM_KEEP_OLD_ENHANCED_TEXT
370 static char    *ParseText(HPS, char *, BOOL, char *, int, int, BOOL, BOOL);
371 static void     CharStringAt(HPS, int, int, int, char *);
372 static int      QueryTextBox(HPS, int, char *);
373 #endif
374 static void     LMove(HPS hps, POINTL *p);
375 static void     LLine(HPS hps, POINTL *p);
376 static void     LType(int iType);
377
378 /* Functions related to the mouse processing */
379 static void     TextToClipboard(PCSZ);
380 static void     GetMousePosViewport(HWND hWnd, int *mx, int *my);
381 static void     MousePosToViewport(int *x, int *y, SHORT mx, SHORT my);
382 static void     DisplayStatusLine(HPS hps);
383 static void     UpdateStatusLine(HPS hps, char *text);
384 static void     gpPMmenu_update(void);
385 static void     DrawZoomBox(void);
386 static void     DrawRuler(void);
387
388 #define IGNORE_MOUSE (!mouseTerminal || useMouse==0 || lock_mouse)
389 /* || !gp4mouse.graph */
390 /*  don't react to mouse in the event handler, and avoid some crashes */
391
392 /* Drag'n'Drop support from PMEmacs */
393 struct drop {
394     unsigned long cookie;
395     unsigned len;
396     char str[CCHMAXPATH];
397 };
398
399 /* Circular buffer of objects recently dropped.  */
400
401 #define DROP_MAX 8
402 static int drop_count = 0;
403
404 /* Each drop action is assigned a number, for relating drop events
405    with PMR_DROP requests. */
406
407 /* Finally, include the common mousing declarations and routines: */
408 #define GNUPMDRV
409   /* let mousing.c know whether called from gclient.c or gplt_x11.c */
410 #include "../gpexecute.h"
411
412 /* End of new functions related to the mouse processing */
413
414 /*==== c o d e ===============================================================*/
415
416 /* An object is being dragged over the client window.  Check whether
417    it can be dropped or not. */
418
419 void
420 report_error(HWND hWnd, char* s)
421 {
422       HPS hps;
423       POINTL pt;
424       RECTL rc;
425
426       hps = WinGetPS(hWnd);
427       GpiSetMix(hps, FM_OVERPAINT);
428       /* clear the rectangle below the text */
429       /* GpiSetColor(hps, RGB_TRANS(CLR_CYAN)); */
430       GpiSetColor(hps, RGB_TRANS(CLR_BACKGROUND));
431       pt.x = 0;
432       pt.y = 0;
433       GpiMove(hps,&pt);
434       /* clear the whole line */
435       GpiQueryPageViewport(hpsScreen,&rc);
436       pt.x = rc.xRight;
437       pt.y = 16;
438       GpiBox(hps, DRO_FILL, &pt, 0,0);
439       /* now write the mouse position on the screen */
440       GpiSetColor(hps, RGB_TRANS(COLOR_ERROR)); /* set text color */
441       GpiSetCharMode(hps,CM_MODE1);
442
443       pt.x = 2;
444       pt.y = 2;
445       GpiCharStringAt(hps,&pt,(long)strlen(s),s);
446       WinReleasePS(hps);
447 }
448
449 MRESULT
450 drag_over(HWND hWnd, PDRAGINFO pDraginfo)
451 {
452     PDRAGITEM pditem;
453     USHORT indicator, operation;
454
455 /* Redefine this macro for debugging. */
456 #define DRAG_FAIL(x) report_error(hWnd,x)
457
458     indicator = DOR_NODROPOP; operation = DO_COPY;
459     if (!DrgAccessDraginfo(pDraginfo))
460         DRAG_FAIL("DrgAccessDraginfo failed");
461     else if (!(pDraginfo->usOperation == DO_DEFAULT
462                || pDraginfo->usOperation == DO_COPY))
463         DRAG_FAIL("Invalid operation");
464     else if (DrgQueryDragitemCount(pDraginfo) < 1)
465         DRAG_FAIL("Invalid count");
466     else if (DrgQueryDragitemCount(pDraginfo) > DROP_MAX - drop_count)
467         DRAG_FAIL("Circular buffer full");
468     else {
469         pditem = DrgQueryDragitemPtr(pDraginfo, 0);
470         if (!(pditem->fsSupportedOps & DO_COPYABLE))
471             DRAG_FAIL("Not copyable");
472         else if (!DrgVerifyRMF(pditem, "DRM_OS2FILE", NULL))
473             DRAG_FAIL("DrgVerifyRMF failed");
474         else {
475             /* The object can be dropped (copied). */
476             indicator = DOR_DROP; operation = DO_COPY;
477         }
478     }
479     DrgFreeDraginfo(pDraginfo);
480     return (MRFROM2SHORT(indicator, operation));
481 }
482
483
484 /* An object is dropped on the client window. */
485
486 MRESULT
487 drag_drop(HWND hwnd, PDRAGINFO pDraginfo)
488 {
489   PDRAGITEM pditem;
490   POINTL ptl;
491   char name[CCHMAXPATH];
492   char path[CCHMAXPATH];
493   char *p;
494   int count, idx, len;
495
496   DrgAccessDraginfo(pDraginfo);
497   ptl.x = pDraginfo->xDrop; ptl.y = pDraginfo->yDrop;
498   WinMapWindowPoints(HWND_DESKTOP, hwnd, &ptl, 1);
499   count = DrgQueryDragitemCount(pDraginfo);
500   for (idx = 0; idx < count && drop_count < DROP_MAX; ++idx) {
501       pditem = DrgQueryDragitemPtr(pDraginfo, idx);
502       DrgQueryStrName(pditem->hstrContainerName, sizeof(path), path);
503       DrgQueryStrName(pditem->hstrSourceName, sizeof(name), name);
504       DrgSendTransferMsg(pditem->hwndItem, DM_ENDCONVERSATION,
505                          MPFROMLONG(pditem->ulItemID),
506                          MPFROMSHORT(DMFL_TARGETSUCCESSFUL));
507       len = strlen(path);
508       if (len >= 1 && strchr("\\/:", path[len-1]) == NULL)
509           path[len++] = '/';
510       if (len + strlen(name) + 1 <= sizeof(path)) {
511           strcpy(path + len, name);
512           for (p = path; *p != 0; ++p)
513               if (*p == '\\')
514                   *p = '/';
515           if (input_from_PM_Terminal) {
516               sprintf(input_from_PM_Terminal,
517                       "set loadpath \"%.*s\"; load \"%s\"",
518                       len, path, path);
519               gp_execute(0);
520           }
521       } else
522           report_error(hwnd, "Dropped path name too long");
523   } /* for(idx) */
524
525   DrgDeleteDraginfoStrHandles(pDraginfo);
526   DrgFreeDraginfo(pDraginfo);
527   return(0);
528 }
529
530 #if 0
531 /* A color has been dropped on a frame(or the background color has
532    been changed with WinSetPresParam). */
533
534 static void
535 drop_color(HWND hwnd)
536 {
537     RGB rgb;
538     char buf[3];
539
540     if (WinQueryPresParam(hwnd, PP_BACKGROUNDCOLOR, 0, NULL,
541                           sizeof(rgb), &rgb,
542                           QPF_NOINHERIT | QPF_PURERGBCOLOR) == sizeof(rgb)
543         ) {
544         buf[0] = rgb.bRed;
545         buf[1] = rgb.bGreen;
546         buf[2] = rgb.bBlue;
547 #if CAN_DROP_COLOR
548         send_drop_color(buf, 3);
549 #endif
550     }
551 }
552 #endif
553
554 /*
555 **  Window proc for main window
556 **  -- passes most stuff to active child window via WmClientCmdProc
557 **  -- passes DDE messages to DDEProc
558 */
559 MRESULT
560 EXPENTRY DisplayClientWndProc(HWND hWnd, ULONG message, MPARAM mp1, MPARAM mp2)
561 {
562     static RECTL   rectlPaint = { 0, 0, 0, 0 };
563     static int     iPaintCount = 0;
564     static int     firstcall = 1;
565     static int     prev_mx = 0, prev_my = 0;            /* previous mouse position */
566     int            mx, my;                              /* current mouse position  */
567
568 #if 1
569     GetMousePosViewport(hWnd, &mx, &my);
570 #else
571     /* The following cannot be used because `message' is not OK for
572      * WM_CHAR */
573     /* macro which gets mouse coords in pixels */
574     mx = MOUSEMSG(&message)->x;
575     my = MOUSEMSG(&message)->y;
576     /* viewport units --- this trashes mx,my! */
577     MousePosToViewport(&mx, &my, mx, my);
578 #endif
579
580     /* Graphics part, SET_GRAPHICS, required to update menu */
581     if (gpPMmenu_update_req)
582         gpPMmenu_update();
583
584     /* mouse events first */
585     switch (message) {
586     case WM_MOUSEMOVE:
587         if (IGNORE_MOUSE) {
588             WinSetPointer(HWND_DESKTOP, hptrDefault); /* set default pointer */
589             return 0L;
590         }
591         /* was the mouse moved? */
592         if ((prev_mx != mx) || (prev_my != my)) {
593 #if 1
594             WinSetPointer(HWND_DESKTOP, hptrCurrent);
595 #else
596             WinSetPointer(HWND_DESKTOP, hptrCrossHair);
597 #endif
598             if (zoombox.on) {
599                 DrawZoomBox(); /* erase zoom box */
600                 zoombox.to.x = mx; zoombox.to.y = my;
601                 DrawZoomBox(); /* draw new zoom box */
602             }
603             /* track(show) mouse position -- send the event to gnuplot */
604             gp_exec_event(GE_motion, mx, my, 0, 0, 0);
605         }
606         prev_mx = mx;
607         prev_my = my;
608         return 0L; /* end of WM_MOUSEMOVE */
609
610     case WM_BUTTON1DOWN:
611         WinSetFocus(HWND_DESKTOP, hWnd);
612         if (! IGNORE_MOUSE)
613             gp_exec_event(GE_buttonpress, mx, my, 1, 0, 0);
614         return 0L;
615
616     case WM_BUTTON2DOWN:
617         WinSetFocus(HWND_DESKTOP, hWnd);
618         if (!IGNORE_MOUSE)
619             gp_exec_event(GE_buttonpress, mx, my, 3, 0, 0);
620         return 0L;
621
622     case WM_BUTTON3DOWN:
623         WinSetFocus(HWND_DESKTOP, hWnd);
624         if (!IGNORE_MOUSE)
625             gp_exec_event(GE_buttonpress, mx, my, 2, 0, 0);
626         return 0L;
627
628     case WM_BUTTON1DBLCLK:
629         if (!IGNORE_MOUSE)
630             gp_exec_event(GE_buttonrelease, mx, my, 1, 0, 0);
631         return 0L;
632
633     case WM_BUTTON2DBLCLK:
634         if (!IGNORE_MOUSE)
635             /* Note: 9999 should be replaced by time! */
636             gp_exec_event(GE_buttonrelease, mx, my, 3, 9999, 0);
637         return 0L;
638
639     case WM_BUTTON3DBLCLK:
640         if (!IGNORE_MOUSE)
641             gp_exec_event(GE_buttonrelease, mx, my, 2, 9999, 0);
642         return 0L;
643
644 #if 1
645     case WM_BUTTON1UP:
646 #else
647     case WM_BUTTON1CLICK:
648 #endif
649         if (!IGNORE_MOUSE)
650             gp_exec_event(GE_buttonrelease, mx, my, 1, 9999, 0);
651         return 0L;
652
653 #if 0
654     case WM_BUTTON2UP:
655 #else
656     case WM_BUTTON2CLICK:
657 #endif
658         if (!IGNORE_MOUSE)
659             gp_exec_event(GE_buttonrelease, mx, my, 3, 9999, 0);
660         return 0L;
661
662 #if 1
663     case WM_BUTTON3UP:
664 #else
665     case WM_BUTTON3CLICK:
666 #endif
667         if (!IGNORE_MOUSE)
668             gp_exec_event(GE_buttonrelease, mx, my, 2, 9999, 0);
669         return 0L;
670
671     } /* switch over mouse events */
672
673
674     switch (message) {
675     case WM_CREATE:
676     {
677         SIZEL   sizlPage;
678         LONG    NumColors;
679         LONG    PalSupport;
680
681         /* set initial values */
682         ChangeCheck(hWnd, IDM_LINES_THICK, bWideLines?IDM_LINES_THICK:0);
683         ChangeCheck(hWnd, IDM_LINES_SOLID, bLineTypes?0:IDM_LINES_SOLID);
684         ChangeCheck(hWnd, IDM_COLOURS, bColours?IDM_COLOURS:0);
685         ChangeCheck(hWnd, IDM_FRONT, bPopFront?IDM_FRONT:0);
686         ChangeCheck(hWnd, IDM_KEEPRATIO, bKeepRatio?IDM_KEEPRATIO:0);
687         ChangeCheck(hWnd, IDM_USEMOUSE, useMouse?IDM_USEMOUSE:0);
688 #if 0
689         ChangeCheck(hWnd, IDM_MOUSE_POLAR_DISTANCE, mousePolarDistance?IDM_MOUSE_POLAR_DISTANCE:0);
690 #endif
691
692         /* disable close from system menu(close only from gnuplot) */
693         hApp = WinQueryWindow(hWnd, QW_PARENT); /* temporary assignment.. */
694         hSysMenu = WinWindowFromID(hApp, FID_SYSMENU);
695         /* setup semaphores */
696         /* DosCreateEventSem(NULL, &semDrawDone, 0L, 0L); */
697         /* DosCreateEventSem(NULL, &semStartSeq, 0L, 0L); */
698         DosCreateEventSem(NULL, &semPause, 0L, 0L);
699         DosCreateMutexSem(NULL, &semHpsAccess, 0L, 1L);
700
701         /* create a dc and hps to draw on the screen */
702         hdcScreen = WinOpenWindowDC(hWnd);
703
704         /* How many colors can be displayed ? */
705         DevQueryCaps(hdcScreen, CAPS_COLORS, 1, &NumColors);
706         /* Is Palette Manager supported at all? */
707         DevQueryCaps(hdcScreen, CAPS_ADDITIONAL_GRAPHICS, 1, &PalSupport);
708
709         /* Determine if PM Palette Manager should be used */
710         bPMPaletteMode = (PalSupport & CAPS_PALETTE_MANAGER) &&
711                          (NumColors <= 256);
712         DEBUG_COLOR(( "WM_CREATE: colors = %i, pm = %i, rgb = %i",
713                 NumColors, PalSupport & CAPS_PALETTE_MANAGER, !bPMPaletteMode ));
714
715         sizlPage.cx = 0; sizlPage.cy = 0;
716         sizlPage.cx = 19500; sizlPage.cy = 12500;
717         hpsScreen = GpiCreatePS(hab, hdcScreen, &sizlPage,
718                                 PU_HIMETRIC|GPIT_NORMAL|GPIA_ASSOC);
719         /* spawn server for GNUPLOT ... */
720         tidSpawn = _beginthread(ReadGnu, NULL, 32768, NULL);
721         /* initialize pointers */
722         hptrDefault = WinQuerySysPointer(HWND_DESKTOP, SPTR_ARROW, FALSE);
723         hptrCrossHair = WinLoadPointer(HWND_DESKTOP,(ULONG)0, IDP_CROSSHAIR);
724         hptrScaling = WinLoadPointer(HWND_DESKTOP,(ULONG)0, IDP_SCALING);
725         hptrRotating = WinLoadPointer(HWND_DESKTOP,(ULONG)0, IDP_ROTATING);
726         hptrZooming = WinQuerySysPointer(HWND_DESKTOP, SPTR_MOVE, FALSE);
727         hptrCurrent = hptrCrossHair;
728
729         break;
730     }
731
732     case WM_GPSTART:
733         /* Show the Mouse menu if connected to mouseable PM terminal */
734         if (1 || mouseTerminal) /* PM: workaround for a bug---SEE "BUGS 2" IN README!!! */
735             /* if (mouseTerminal) */
736             WinEnableMenuItem(WinWindowFromID(
737                                   WinQueryWindow(hApp, QW_PARENT),
738                                   FID_MENU),
739                               IDM_MOUSE, TRUE);
740         if (!input_from_PM_Terminal) { /* no feedback */
741 #define NOFEEDBACK(X)                                                   \
742             WinEnableMenuItem(WinWindowFromID(                          \
743                                   WinQueryWindow(hApp, QW_PARENT),      \
744                                   FID_MENU),                            \
745                               X, FALSE)
746             NOFEEDBACK(IDM_SET_GRID);
747             NOFEEDBACK(IDM_SET_LINLOGY);
748             NOFEEDBACK(IDM_SET_AUTOSCALE);
749             NOFEEDBACK(IDM_DO_REPLOT);
750             NOFEEDBACK(IDM_DO_RELOAD);
751             NOFEEDBACK(IDM_DO_SENDCOMMAND);
752             NOFEEDBACK(IDM_SET);
753 #undef NOFEEDBACK
754         }
755
756         /* get details of command-line window */
757         hSwitch = WinQuerySwitchHandle(0, ppidGnu);
758         WinQuerySwitchEntry(hSwitch, &swGnu);
759
760         if (firstcall) {
761             /* set size of this window */
762             WinSetWindowPos(
763                 WinQueryWindow(hWnd, QW_PARENT),
764                 bPopFront?HWND_TOP:swGnu.hwnd,
765                 ulShellPos[0],
766                 ulShellPos[1],
767                 ulShellPos[2],
768                 ulShellPos[3],
769                 bShellPos
770                 ? (bPopFront
771                    ? SWP_SIZE|SWP_MOVE|SWP_SHOW|SWP_ACTIVATE
772                    : SWP_SIZE|SWP_MOVE|SWP_SHOW|SWP_ZORDER)
773                 : (bPopFront
774                    ? SWP_SHOW|SWP_ACTIVATE
775                    : SWP_SHOW|SWP_ZORDER));
776             signal(SIGTERM, SigHandler);
777             firstcall = 0;
778         }
779         if (!bPopFront) WinSwitchToProgram(hSwitch);
780         /* DosPostEventSem(semDrawDone); */
781         DosReleaseMutexSem(semHpsAccess);
782         return 0;
783
784     case WM_COMMAND:
785         return WmClientCmdProc(hWnd, message, mp1, mp2);
786
787     case WM_CHAR:
788     {
789         /* Note: doc for WM_CHAR is available in PMMSG.INF */
790         USHORT usFlag = SHORT1FROMMP(mp1); /* keyboard control codes */
791         SHORT  key = SHORT2FROMMP(mp2);    /* virtual key code */
792         static int last_modifier_mask = -99;
793         int modifier_mask =
794             ((usFlag & KC_SHIFT) ? Mod_Shift : 0)
795             | ((usFlag & KC_CTRL) ? Mod_Ctrl : 0)
796             | ((usFlag & KC_ALT) ? Mod_Alt : 0);
797
798         if (modifier_mask != last_modifier_mask) {
799             gp_exec_event(GE_modifier, mx, my, modifier_mask, 0, 0);
800             last_modifier_mask = modifier_mask;
801         }
802 #if 0
803         if (!(usFlag & KC_SCANCODE))
804             return 0L; // only modifier mask has changed */
805 #endif
806         if (usFlag & KC_KEYUP)
807             return 0L;   /* ignore key release events */
808 #if 0
809         {
810             FILE *ff = fopen("deb", "a");
811             fprintf(ff, "key = %i c=%c\n", (int) key, (char) key);
812             fclose(ff);
813         }
814 #endif
815
816         switch (key) {
817         case VK_SPACE: {
818             /* raise gnuplot's window */
819             HWND hw = WinQueryWindow(swGnu.hwnd, QW_BOTTOM);
820             WinSetFocus(HWND_DESKTOP, hw);
821             WinSendMsg(hw, message,
822                        MPFROM2SHORT((USHORT)(KC_SCANCODE), 1),
823                        0 /* MPFROMSHORT(key) */
824                 );
825             WinSwitchToProgram(hSwitch);
826             break;
827         }
828             /* remap virtual keys to gnuplot's codes: */
829         case VK_BACKSPACE:
830             key = GP_BackSpace;
831             break;
832         case VK_TAB:
833             key = GP_Tab;
834             break;
835         case VK_NEWLINE:
836             key = GP_Return;
837             break;
838         case VK_PAUSE:
839             key = GP_Pause;
840             break;
841         case VK_SCRLLOCK:
842             key = GP_Scroll_Lock;
843             break;
844         case VK_SYSRQ:
845             key = GP_Sys_Req;
846             break;
847         case VK_ESC:
848             key = GP_Escape;
849             break;
850         case VK_DELETE:
851             key = GP_Delete;
852             break;
853         case VK_INSERT:
854             key = GP_KP_Insert;
855             break;
856         case VK_HOME:
857             key = GP_Home;
858             break;
859         case VK_LEFT:
860             key = GP_Left;
861             break;
862         case VK_UP:
863             key = GP_Up;
864             break;
865         case VK_RIGHT:
866             key = GP_Right;
867             break;
868         case VK_DOWN:
869             key = GP_Down;
870             break;
871         case VK_END:
872             key = GP_End;
873             break;
874         case VK_PAGEUP:
875             key = GP_PageUp;
876             break;
877         case VK_PAGEDOWN:
878             key = GP_PageDown;
879             break;
880         case VK_F1:
881             key = GP_F1;
882             break;
883         case VK_F2:
884             key = GP_F2;
885             break;
886         case VK_F3:
887             key = GP_F3;
888             break;
889         case VK_F4:
890             key = GP_F4;
891             break;
892         case VK_F5:
893             key = GP_F5;
894             break;
895         case VK_F6:
896             key = GP_F6;
897             break;
898         case VK_F7:
899             key = GP_F7;
900             break;
901         case VK_F8:
902             key = GP_F8;
903             break;
904         case VK_F9:
905             key = GP_F9;
906             break;
907         case VK_F10:
908             key = GP_F10;
909             break;
910         case VK_F11:
911             key = GP_F11;
912             break;
913         case VK_F12:
914             key = GP_F12;
915             break;
916         case VK_SHIFT:
917         case VK_CTRL:
918         case VK_ALT:
919             gp_exec_event(GE_modifier, mx, my, modifier_mask, 0, 0);
920             return 0L;
921         default:
922             key = SHORT1FROMMP(mp2); /* character key code */
923         } /* switch(key) */
924
925         if (key)
926             gp_exec_event(GE_keypress, mx, my, key, 0, 0);
927
928         return 0L;
929     } /*case(WM_CHAR) */
930
931     case WM_DESTROY:
932         if (WinSendMsg(hWnd, WM_USER_PRINT_QBUSY, 0L, 0L) != 0L) {
933             WinMessageBox(HWND_DESKTOP,
934                           hWnd,
935                           "Still printing - not closed",
936                           APP_NAME,
937                           0,
938                           MB_OK | MB_ICONEXCLAMATION);
939             return 0L;
940         }
941         return(WinDefWindowProc(hWnd, message, mp1, mp2));
942
943     case WM_PAINT:
944     {
945         ULONG ulCount;
946         PID pid; TID tid;
947         HPS hps_tmp;
948         RECTL rectl_tmp;
949
950         DosQueryMutexSem(semHpsAccess, &pid, &tid, &ulCount);
951         if ((ulCount > 0) &&(tid != tidDraw)) {
952             /* simple repaint while building plot or metafile */
953             /* use temporary PS                   */
954             lock_mouse = 1; /* PM: this may help against gnupmdrv crashes */
955             hps_tmp = WinBeginPaint(hWnd,0,&rectl_tmp);
956             WinFillRect(hps_tmp,&rectl_tmp,CLR_BACKGROUND);
957             WinEndPaint(hps_tmp);
958             /* add dirty rectangle to saved rectangle     */
959             /* to be repainted when PS is available again */
960             WinUnionRect(hab,&rectlPaint,&rectl_tmp,&rectlPaint);
961             lock_mouse = 0;
962             iPaintCount ++;
963             break;
964         }
965         lock_mouse = 1;
966         WinInvalidateRect(hWnd, &rectlPaint, TRUE);
967         DoPaint(hWnd, hpsScreen);
968         WinSetRectEmpty(hab, &rectlPaint);
969         lock_mouse = 0;
970         break;
971     }
972
973     case WM_SIZE :
974         WinInvalidateRect(hWnd, NULL, TRUE);
975         break;
976
977     case WM_PRESPARAMCHANGED: {
978         char *pp = malloc(FONTBUF);
979         ULONG ulID;
980
981         if (WinQueryPresParam(hWnd,
982                               PP_FONTNAMESIZE,
983                               0,
984                               &ulID,
985                               FONTBUF,
986                               pp,
987                               QPF_NOINHERIT) != 0L) {
988             strcpy(szFontNameSize, pp);
989 #if 0
990             bNewFont = TRUE;
991 #endif
992             WinInvalidateRect(hWnd, NULL, TRUE);
993         }
994         free(pp);
995 #ifndef STANDARD_FONT_DIALOG
996         gp_execute("replot");
997 #endif
998         break;
999     }
1000
1001     case WM_USER_PRINT_BEGIN:
1002     case WM_USER_PRINT_OK :
1003     case WM_USER_DEV_ERROR :
1004     case WM_USER_PRINT_ERROR :
1005     case WM_USER_PRINT_QBUSY :
1006         return(PrintCmdProc(hWnd, message, mp1, mp2));
1007
1008     case WM_GNUPLOT:
1009         /* display the plot */
1010         lock_mouse = 1;
1011         if (bPopFront) {
1012             SWP swp; /* pop to front only if the window is not minimized */
1013
1014             if ((WinQueryWindowPos(hwndFrame,(PSWP) &swp) == TRUE)
1015                 &&((swp.fl & SWP_MINIMIZE) == 0))
1016                 WinSetWindowPos(hwndFrame, HWND_TOP, 0,0,0,0, SWP_ACTIVATE|SWP_ZORDER);
1017         }
1018         if (iPaintCount > 0) { /* if outstanding paint messages, repaint */
1019             WinInvalidateRect(hWnd, &rectlPaint, TRUE);
1020             iPaintCount = 0;
1021         }
1022         lock_mouse = 0;
1023         return 0L;
1024
1025     case WM_PAUSEPLOT:
1026     {
1027         SWP swp; /* restore the window if it has been minimized */
1028
1029         if ((WinQueryWindowPos(hwndFrame, &swp) == TRUE)
1030             &&((swp.fl & SWP_MINIMIZE) != 0))
1031             WinSetWindowPos(hwndFrame, HWND_TOP, 0,0,0,0,
1032                             SWP_RESTORE|SWP_SHOW|SWP_ACTIVATE);
1033         /* put pause message on screen, or enable 'continue' button */
1034         if (ulPauseMode == PAUSE_DLG) {
1035             pausedata.pszMessage =(char*)mp1;
1036             WinLoadDlg(HWND_DESKTOP,
1037                        hWnd,
1038                        (PFNWP)PauseMsgDlgProc,
1039                        0L,
1040                        IDD_PAUSEBOX,
1041                        &pausedata);
1042         } else {
1043             WinEnableMenuItem(WinWindowFromID(
1044                                   WinQueryWindow(hWnd, QW_PARENT), FID_MENU),
1045                               IDM_CONTINUE, TRUE);
1046         }
1047         return 0L;
1048     }
1049
1050     case WM_PAUSEEND:
1051         /* resume plotting */
1052         ulPauseReply =(ULONG) mp1;
1053         DosPostEventSem(semPause);
1054         return 0L;
1055
1056 /* New event handles for mouse processing */
1057
1058 #if 0 /* already defined */
1059     case WM_MOUSEMOVE:
1060         return  0L;
1061 #endif
1062
1063 #if 0
1064     case WM_BUTTON1DBLCLK:
1065         /* put the mouse coordinates to the clipboard */
1066         if (!IGNORE_MOUSE) {
1067             SHORT mx = MOUSEMSG(&message)->x;
1068             SHORT my = MOUSEMSG(&message)->y;
1069             double x, y;
1070             char s[256];
1071             int frm = ulMouseSprintfFormatItem - IDM_MOUSE_FORMAT_X_Y;
1072
1073             /* Note: Another solution of getting mouse position
1074              *(available at any method, not just in this handle
1075              * event) is the following one:
1076              *
1077              * ok = WinQueryPointerPos(HWND_DESKTOP, &pt); // pt contains pos wrt desktop
1078              * WinMapWindowPoints(HWND_DESKTOP, hWnd, &pt, 1); // pt contains pos wrt our hwnd window
1079              * sprintf(s,"[%li,%li]",pt.x,pt.y);
1080              */
1081
1082         }
1083         return 0L; /* end of case WM_BUTTON1DBLCLK */
1084 #endif
1085
1086     case WM_BUTTON2CLICK: /* WM_BUTTON2UP: */
1087         /* make zoom */
1088         if (! IGNORE_MOUSE) {
1089             POINTL tmp;
1090             HPS hps = WinGetPS(hWnd);
1091
1092             if (pausing) { /* zoom is not allowed during pause */
1093                 DosBeep(440,111);
1094                 break;
1095             }
1096             DosBeep(555,155);
1097             zoomrect_from.x = MOUSEMSG(&message)->x;
1098             zoomrect_from.y = MOUSEMSG(&message)->y;
1099             /* set opposite corner */
1100             tmp.x = zoomrect_now.x = zoomrect_from.x + 50;
1101             tmp.y = zoomrect_now.y = zoomrect_from.y + 50;
1102             /* move mouse to opposite corner */
1103             WinMapWindowPoints(hWnd, HWND_DESKTOP, &tmp, 1);
1104             WinSetPointerPos(HWND_DESKTOP, tmp.x, tmp.y);
1105             WinReleasePS(hps);
1106             zooming = 1;
1107         }
1108         return 0; /* return from: case WM_BUTTON3DOWN(zoom) */
1109
1110     case WM_BUTTON3UP: /* WM_BUTTON3DBLCLK: */
1111         /* write mouse position to screen */
1112         if (! IGNORE_MOUSE) {
1113             SHORT mx = MOUSEMSG(&message)->x; /* mouse position */
1114             SHORT my = MOUSEMSG(&message)->y;
1115             char s[256];
1116             POINTL pt;
1117             HPS hps = WinGetPS(hWnd);
1118
1119             GpiSetColor(hps, RGB_TRANS(COLOR_ANNOTATE));    /* set color of the text */
1120             GpiSetCharMode(hps,CM_MODE1);
1121             pt.x = mx; pt.y = my+4;
1122             GpiCharStringAt(hps,&pt,(long)strlen(s),s);
1123             /* draw a cross at the clicked position */
1124             pt.x = mx-3; pt.y = my; GpiMove(hps,&pt);
1125             pt.x += 7; GpiLine(hps,&pt);
1126             pt.x = mx; pt.y = my - 3; GpiMove(hps,&pt);
1127             pt.y += 7; GpiLine(hps,&pt);
1128             WinReleasePS(hps);
1129         }
1130         return 0L; /* end of case WM_BUTTON3... */
1131
1132         /* End of new event handles for mouse processing */
1133
1134 #if 0
1135     case WM_PRESPARAMCHANGED:
1136         if (LONGFROMMP(mp1) == PP_BACKGROUNDCOLOR)
1137             drop_color(hWnd);
1138         return 0;
1139 #endif
1140
1141     case DM_DRAGOVER:
1142         /* Determine whether the object can be dropped. */
1143         return(drag_over(hWnd, (PDRAGINFO) mp1));
1144
1145     case DM_DROP:
1146         /* Drop an object. */
1147         return(drag_drop(hWnd, (PDRAGINFO) mp1));
1148
1149     default:         /* Passes it on if unproccessed    */
1150         return(WinDefWindowProc(hWnd, message, mp1, mp2));
1151     } /* switch(message) */
1152
1153     return(NULL);
1154 }
1155
1156
1157 #if 0 /* unused */
1158 /*
1159  * Gets the pointer position(in pixels) in the window hWnd
1160  */
1161 void
1162 GetPointerPos(HWND hWnd, PPOINTL p)
1163 {
1164     WinQueryPointerPos(HWND_DESKTOP, p);
1165     /* this is position wrt desktop */
1166     WinMapWindowPoints(HWND_DESKTOP, hWnd, p, 1);
1167     /* pos. wrt our window in pixels */
1168 }
1169 #endif
1170
1171
1172 /* passing either n(n>=0) or f(when n==-1) */
1173 void
1174 SetMouseCoords(HWND hWnd, MPARAM mp1, int n, char *f)
1175 {
1176     char s[100];
1177
1178     ChangeCheck(hWnd, ulMouseSprintfFormatItem, SHORT1FROMMP(mp1));
1179     ulMouseSprintfFormatItem = SHORT1FROMMP(mp1);
1180     if (n >= 0)
1181         sprintf(s,"set mouse mouseformat %i clipboardformat %i", n, n);
1182     else
1183         sprintf(s,"set mouse mouseformat \"%s\" clipboardformat \"%s\"", f, f);
1184     gp_execute(s);
1185 }
1186
1187
1188 /*
1189 **   Handle client window command(menu) messages
1190 */
1191 MRESULT
1192 WmClientCmdProc(HWND hWnd, ULONG message, MPARAM mp1, MPARAM mp2)
1193 {
1194     static int ulPauseItem = IDM_PAUSEDLG;
1195     // static int ulMouseCoordItem = IDM_MOUSE_COORDINATES_REAL;
1196     int mx, my;
1197
1198     GetMousePosViewport(hWnd,&mx,&my);
1199
1200     switch ((USHORT) SHORT1FROMMP(mp1)) {
1201     case IDM_ABOUT :    /* show the 'About' box */
1202         WinDlgBox(HWND_DESKTOP,
1203                   hWnd ,
1204                   (PFNWP)About ,
1205                   0L,
1206                   ID_ABOUT,
1207                   NULL);
1208         break;
1209
1210     case IDM_GPLOTINF:  /* view gnuplot.inf */
1211     {
1212         const char cmd_prefix[] = "start view ";
1213         const char helpfile[] = "gnuplot.inf";
1214         char *cmd;
1215         char *gnuplot_path;
1216         unsigned cmd_length;
1217
1218         cmd_length = strlen(cmd_prefix) + strlen(helpfile);
1219         gnuplot_path = getenv("GNUPLOT");
1220         if (gnuplot_path != NULL)
1221             cmd_length += strlen(gnuplot_path) + 1;
1222
1223         cmd = (char *)malloc( cmd_length );
1224         strcpy(cmd, cmd_prefix);
1225         if (gnuplot_path != NULL) {
1226             strcat(cmd, gnuplot_path);
1227             strcat(cmd, "\\");
1228         }
1229         strcat(cmd, helpfile);
1230         system(cmd);
1231         free(cmd);
1232         break;
1233     }
1234
1235     case IDM_PRINT :    /* print plot */
1236         if (SetupPrinter(hWnd, &qPrintData)) {
1237             WinPostMsg(hWnd,
1238                        WM_USER_PRINT_BEGIN,
1239                        (MPARAM) &qPrintData,
1240                        (MPARAM) hpsScreen);
1241         }
1242         break;
1243
1244     case IDM_PRINTSETUP :    /* select printer */
1245         WinDlgBox(HWND_DESKTOP,
1246                   hWnd ,
1247                   (PFNWP) QPrintersDlgProc,
1248                   0L,
1249                   IDD_QUERYPRINT,
1250                   qPrintData.szPrinterName);
1251         break;
1252
1253     case IDM_LINES_THICK:
1254         /* change line setting */
1255         bWideLines = !bWideLines;
1256         ChangeCheck(hWnd, IDM_LINES_THICK, bWideLines?IDM_LINES_THICK:0);
1257         WinInvalidateRect(hWnd, NULL, TRUE);
1258         break;
1259
1260     case IDM_LINES_SOLID:
1261         /* change line setting */
1262         bLineTypes = !bLineTypes;
1263         ChangeCheck(hWnd, IDM_LINES_SOLID, bLineTypes?0:IDM_LINES_SOLID);
1264         EditLineTypes(hWnd, hpsScreen, bLineTypes);
1265         WinInvalidateRect(hWnd, NULL, TRUE);
1266         break;
1267
1268     case IDM_COLOURS:
1269         /* change colour setting */
1270         bColours = !bColours;
1271         ChangeCheck(hWnd, IDM_COLOURS, bColours?IDM_COLOURS:0);
1272         WinInvalidateRect(hWnd, NULL, TRUE);
1273         break;
1274
1275     case IDM_FRONT:
1276         /* toggle z-order forcing */
1277         bPopFront = !bPopFront;
1278         ChangeCheck(hWnd, IDM_FRONT, bPopFront?IDM_FRONT:0);
1279         break;
1280
1281     case IDM_KEEPRATIO:
1282         /* toggle keep aspect ratio */
1283         bKeepRatio = !bKeepRatio;
1284         ChangeCheck(hWnd, IDM_KEEPRATIO, bKeepRatio?IDM_KEEPRATIO:0);
1285         WinInvalidateRect(hWnd, NULL, TRUE); /* redraw screen */
1286         break;
1287
1288     case IDM_FONTS:
1289         if (GetNewFont(hWnd, hpsScreen)) {
1290 #if 0
1291             bNewFont = TRUE;
1292 #endif
1293             WinInvalidateRect(hWnd, NULL, TRUE);
1294         }
1295         break;
1296
1297     case IDM_SAVE:
1298         SaveIni(hWnd);
1299         break;
1300
1301     case IDM_COPY:
1302         /* copy to clipboard */
1303         if (WinOpenClipbrd(hab)) {
1304             CopyToClipBrd(hWnd);
1305         } else {
1306             WinMessageBox(HWND_DESKTOP,
1307                           hWnd,
1308                           "Can't open clipboard",
1309                           APP_NAME,
1310                           0,
1311                           MB_OK | MB_ICONEXCLAMATION);
1312         }
1313         break;
1314
1315     case IDM_CLEARCLIP :         /* clear clipboard */
1316         if (WinOpenClipbrd(hab)) {
1317             WinEmptyClipbrd(hab);
1318             WinCloseClipbrd(hab);
1319         } else {
1320             WinMessageBox(HWND_DESKTOP,
1321                           hWnd,
1322                           "Can't open clipboard",
1323                           APP_NAME,
1324                           0,
1325                           MB_OK | MB_ICONEXCLAMATION);
1326         }
1327         break;
1328
1329     case IDM_COMMAND:       /* go back to GNUPLOT command window */
1330         WinSwitchToProgram(hSwitch);
1331         break;
1332
1333     case IDM_CONTINUE:
1334         WinPostMsg(hWnd, WM_PAUSEEND,(MPARAM)1L,(MPARAM)0L);
1335         WinEnableMenuItem(WinWindowFromID(
1336                               WinQueryWindow(hWnd, QW_PARENT), FID_MENU),
1337                           IDM_CONTINUE,
1338                           FALSE);
1339         break;
1340
1341     case IDM_PAUSEGNU:  /* gnuplot handles pause */
1342         ChangeCheck(hWnd, ulPauseItem, IDM_PAUSEGNU);
1343         ulPauseItem = IDM_PAUSEGNU;
1344         ulPauseMode = PAUSE_GNU;
1345         break;
1346
1347     case IDM_PAUSEDLG:  /* pause message in dlg box */
1348         ChangeCheck(hWnd, ulPauseItem, IDM_PAUSEDLG);
1349         ulPauseItem = IDM_PAUSEDLG;
1350         ulPauseMode = PAUSE_DLG;
1351         break;
1352
1353     case IDM_PAUSEBTN:  /* pause uses menu button, no message */
1354         ChangeCheck(hWnd, ulPauseItem, IDM_PAUSEBTN);
1355         ulPauseItem = IDM_PAUSEBTN;
1356         ulPauseMode = PAUSE_BTN;
1357         break;
1358
1359     case IDM_HELPFORHELP:
1360         WinSendMsg(WinQueryHelpInstance(hWnd),
1361                    HM_DISPLAY_HELP, 0L, 0L);
1362         return 0L;
1363
1364     case IDM_EXTENDEDHELP:
1365         WinSendMsg(WinQueryHelpInstance(hWnd),
1366                    HM_EXT_HELP, 0L, 0L);
1367         return 0L;
1368
1369     case IDM_KEYSHELP:
1370         WinSendMsg(WinQueryHelpInstance(hWnd),
1371                    HM_KEYS_HELP, 0L, 0L);
1372         return 0L;
1373
1374     case IDM_HELPINDEX:
1375         WinSendMsg(WinQueryHelpInstance(hWnd),
1376                    HM_HELP_INDEX, 0L, 0L);
1377         return 0L;
1378
1379
1380         /* Now new mousing stuff: */
1381
1382     case IDM_USEMOUSE: /* toggle using/not using mouse cursor tracking */
1383         useMouse = !useMouse;
1384         ChangeCheck(hWnd, IDM_USEMOUSE, useMouse?IDM_USEMOUSE:0);
1385         gp_execute(useMouse ? "set mouse" : "unset mouse");
1386 #if 0
1387         if (!useMouse) /* redraw screen */
1388             WinInvalidateRect(hWnd, NULL, TRUE);
1389 #endif
1390         return 0L;
1391
1392     case IDM_MOUSE_HELP:
1393         gp_exec_event(GE_keypress, mx, my, 'h', 1, 0);
1394         return 0L;
1395
1396 #if 0
1397     case IDM_MOUSE_COORDINATES_REAL:
1398         ChangeCheck(hWnd, ulMouseCoordItem, IDM_MOUSE_COORDINATES_REAL);
1399         ulMouseCoordItem = IDM_MOUSE_COORDINATES_REAL;
1400         return 0L;
1401
1402     case IDM_MOUSE_COORDINATES_PIXELS:
1403         ChangeCheck(hWnd, ulMouseCoordItem, IDM_MOUSE_COORDINATES_PIXELS);
1404         ulMouseCoordItem = IDM_MOUSE_COORDINATES_PIXELS;
1405         return 0L;
1406
1407     case IDM_MOUSE_COORDINATES_SCREEN:
1408         ChangeCheck(hWnd, ulMouseCoordItem, IDM_MOUSE_COORDINATES_SCREEN);
1409         ulMouseCoordItem = IDM_MOUSE_COORDINATES_SCREEN;
1410         return 0L;
1411
1412     case IDM_MOUSE_COORDINATES_XDATE:
1413         ChangeCheck(hWnd, ulMouseCoordItem, IDM_MOUSE_COORDINATES_XDATE);
1414         ulMouseCoordItem = IDM_MOUSE_COORDINATES_XDATE;
1415         return 0L;
1416
1417     case IDM_MOUSE_COORDINATES_XTIME:
1418         ChangeCheck(hWnd, ulMouseCoordItem, IDM_MOUSE_COORDINATES_XTIME);
1419         ulMouseCoordItem = IDM_MOUSE_COORDINATES_XTIME;
1420         return 0L;
1421
1422     case IDM_MOUSE_COORDINATES_XDATETIME:
1423         ChangeCheck(hWnd, ulMouseCoordItem, IDM_MOUSE_COORDINATES_XDATETIME);
1424         ulMouseCoordItem = IDM_MOUSE_COORDINATES_XDATETIME;
1425         return 0L;
1426 #endif
1427
1428     case IDM_MOUSE_CMDS2CLIP:
1429         /* toggle copying the command sent to gnuplot to clipboard */
1430         bSend2gp = !bSend2gp;
1431         ChangeCheck(hWnd, IDM_MOUSE_CMDS2CLIP, bSend2gp?IDM_MOUSE_CMDS2CLIP:0);
1432         return 0L;
1433
1434     case IDM_MOUSE_FORMAT_pXcYp:
1435         SetMouseCoords(hWnd, mp1, -1, "[%g, %g]");
1436         return 0L;
1437     case IDM_MOUSE_FORMAT_XcY:
1438         SetMouseCoords(hWnd, mp1, 1, NULL);
1439         return 0L;
1440     case IDM_MOUSE_FORMAT_TIMEFMT:
1441         SetMouseCoords(hWnd, mp1, 3, NULL);
1442         return 0L;
1443     case IDM_MOUSE_FORMAT_DATE:
1444         SetMouseCoords(hWnd, mp1, 4, NULL);
1445         return 0L;
1446     case IDM_MOUSE_FORMAT_TIME:
1447         SetMouseCoords(hWnd, mp1, 5, NULL);
1448         return 0L;
1449     case IDM_MOUSE_FORMAT_DATETIME:
1450         SetMouseCoords(hWnd, mp1, 6, NULL);
1451         return 0L;
1452     case IDM_MOUSE_FORMAT_X_Y:
1453         SetMouseCoords(hWnd, mp1, -1, "%g %g");
1454         return 0L;
1455     case IDM_MOUSE_FORMAT_XcYc:
1456         SetMouseCoords(hWnd, mp1, -1, "%g %g ");
1457         return 0L;
1458     case IDM_MOUSE_FORMAT_XcYs:
1459         SetMouseCoords(hWnd, mp1, -1, "%g %g, ");
1460         return 0L;
1461
1462     case IDM_MOUSE_POLAR_DISTANCE:
1463         /* toggle using/not using polar coords of distance */
1464         gp_execute(gpPMmenu.polar_distance
1465                    ? "set mouse nopolardistance"
1466                    : "set mouse polardistance");
1467         return 0L;
1468
1469     case IDM_MOUSE_ZOOMNEXT: /* zoom to next level */
1470         gp_exec_event(GE_keypress, mx, my, 'n', 1, 0);
1471         return 0L;
1472
1473     case IDM_MOUSE_UNZOOM: /* unzoom one level back */
1474         gp_exec_event(GE_keypress, mx, my, 'p', 1, 0);
1475         return 0L;
1476
1477     case IDM_MOUSE_UNZOOMALL: /* unzoom to the first level */
1478         gp_exec_event(GE_keypress, mx, my, 'u', 1, 0);
1479         return 0L;
1480
1481     case IDM_MOUSE_RULER:
1482     {
1483         int mx, my;
1484
1485         GetMousePosViewport(hWnd,&mx,&my);
1486         gp_exec_event(GE_keypress, mx, my, 'r', 1, 0);
1487         return 0L;
1488     }
1489
1490     case IDM_BREAK_DRAWING:
1491         breakDrawing = 1;
1492         return 0L;
1493
1494     case IDM_SET_GRID:
1495     {
1496         gp_exec_event(GE_keypress, mx, my, 'g', 1, 0);
1497         return 0L;
1498     }
1499
1500     case IDM_SET_LINLOGY:
1501     {
1502         gp_exec_event(GE_keypress, mx, my, 'l', 1, 0);
1503         return 0L;
1504     }
1505
1506     case IDM_SET_AUTOSCALE:
1507         gp_execute("set autoscale; replot");
1508         return 0L;
1509
1510     case IDM_DO_REPLOT:
1511         gp_execute("replot");
1512         return 0L;
1513
1514     case IDM_DO_RELOAD:
1515         gp_execute("history !load");
1516         return 0L;
1517
1518     case IDM_DO_SENDCOMMAND:
1519         if (input_from_PM_Terminal) {
1520             if (pausing)
1521                 DosBeep(440,111);
1522             else
1523                 WinDlgBox(HWND_DESKTOP, hWnd, SendCommandDlgProc,
1524                           NULLHANDLE, IDM_DO_SENDCOMMAND,
1525                           input_from_PM_Terminal);
1526         }
1527         return (MRESULT) 0;
1528
1529     case IDM_SET_D_S_BOXES:
1530     case IDM_SET_D_S_DOTS:
1531     case IDM_SET_D_S_FSTEPS:
1532     case IDM_SET_D_S_HISTEPS:
1533     case IDM_SET_D_S_IMPULSES:
1534     case IDM_SET_D_S_LINES:
1535     case IDM_SET_D_S_LINESPOINTS:
1536     case IDM_SET_D_S_POINTS:
1537     case IDM_SET_D_S_STEPS:
1538         if (input_from_PM_Terminal)
1539             sprintf(input_from_PM_Terminal, "set style data %s; replot",
1540                     SetDataStyles[(USHORT) SHORT1FROMMP(mp1) - IDM_SET_D_S_BOXES ]);
1541         gp_execute(0);
1542         return 0L;
1543
1544     case IDM_SET_F_S_BOXES:
1545     case IDM_SET_F_S_DOTS:
1546     case IDM_SET_F_S_FSTEPS:
1547     case IDM_SET_F_S_HISTEPS:
1548     case IDM_SET_F_S_IMPULSES:
1549     case IDM_SET_F_S_LINES:
1550     case IDM_SET_F_S_LINESPOINTS:
1551     case IDM_SET_F_S_POINTS:
1552     case IDM_SET_F_S_STEPS:
1553         if (input_from_PM_Terminal)
1554             sprintf(input_from_PM_Terminal, "set style function %s; replot",
1555                     SetDataStyles[(USHORT) SHORT1FROMMP(mp1) - IDM_SET_F_S_BOXES ]);
1556         gp_execute(0);
1557         return 0L;
1558
1559     default :
1560         return WinDefWindowProc(hWnd, message, mp1, mp2);
1561     } /* switch(message) */
1562
1563     return(NULL);
1564 }
1565
1566
1567 /*
1568 **  Utility function:
1569 **
1570 **  move check mark from menu item 1 to item 2
1571 */
1572 void
1573 ChangeCheck(HWND hWnd , USHORT wItem1 , USHORT wItem2)
1574 {
1575     HWND hMenu = WinWindowFromID(WinQueryWindow(hWnd, QW_PARENT),
1576                                  FID_MENU);
1577
1578     if (wItem1 != 0)
1579         WinSendMsg(hMenu,
1580                    MM_SETITEMATTR,
1581                    MPFROM2SHORT(wItem1, TRUE),
1582                    MPFROM2SHORT(MIA_CHECKED, 0));
1583     if (wItem2 != 0)
1584         WinSendMsg(hMenu,
1585                    MM_SETITEMATTR,
1586                    MPFROM2SHORT(wItem2, TRUE),
1587                    MPFROM2SHORT(MIA_CHECKED, MIA_CHECKED));
1588 }
1589
1590
1591 /*
1592 **  Copy window to clipboard as bitmap.
1593 */
1594 static void
1595 CopyToClipBrd(HWND hWnd)
1596 {
1597     HAB hab;
1598     HBITMAP hbm;
1599     HMF     hmf;
1600
1601     hab = WinQueryAnchorBlock(hWnd);
1602     WinEmptyClipbrd(hab);
1603     hbm = CopyToBitmap(hpsScreen);
1604     WinSetClipbrdData(hab,(ULONG) hbm, CF_BITMAP, CFI_HANDLE);
1605     hmf = CopyToMetaFile(hpsScreen);
1606     WinSetClipbrdData(hab,(ULONG) hmf, CF_METAFILE, CFI_HANDLE);
1607     WinCloseClipbrd(hab);
1608 }
1609
1610
1611 /*
1612 **  Copy ps to a bitmap.
1613 */
1614 HBITMAP CopyToBitmap(HPS hps)
1615 {
1616     HPS     hpsMem;
1617     HWND    hwnd;
1618     HAB     hab;
1619     PSZ     psz[4] = {NULL, "Display", NULL, NULL};
1620     HDC     hdcMem, hdcScr;
1621     SIZEL   sizel;
1622     BITMAPINFOHEADER2 bmp;
1623     HBITMAP hbm;
1624     LONG    alData[2];
1625     RECTL   rectl;
1626     POINTL  aptl[6];
1627
1628     hdcScr = GpiQueryDevice(hps);
1629     hwnd = WinWindowFromDC(hdcScr);
1630     hab = WinQueryAnchorBlock(hwnd);
1631     hdcMem = DevOpenDC(hab,
1632                        OD_MEMORY,
1633                        "*",
1634                        4L,
1635                        (PDEVOPENDATA) psz,
1636                        hdcScr);
1637     sizel.cx = 0/*GNUPAGE*/;
1638     sizel.cy = 0/*GNUPAGE*/;
1639     hpsMem = GpiCreatePS(hab, hdcMem, &sizel,
1640                          PU_PELS | GPIA_ASSOC | GPIT_MICRO);
1641     GpiQueryDeviceBitmapFormats(hpsMem, 2L, alData);
1642     WinQueryWindowRect(hwnd, &rectl);
1643     memset(&bmp, 0, sizeof(bmp));
1644     bmp.cbFix =(ULONG) sizeof(bmp);
1645     bmp.cx =(SHORT)(rectl.xRight - rectl.xLeft);
1646     bmp.cy =(SHORT)(rectl.yTop - rectl.yBottom);
1647     bmp.cPlanes = alData[0];
1648     bmp.cBitCount = alData[1];
1649     hbm = GpiCreateBitmap(hpsMem, &bmp, 0, NULL, NULL);
1650     GpiSetBitmap(hpsMem, hbm);
1651     aptl[0].x = 0;
1652     aptl[0].y = 0;
1653     aptl[1].x =(LONG) bmp.cx;
1654     aptl[1].y =(LONG) bmp.cy;
1655     aptl[2].x = 0;
1656     aptl[2].y = 0;
1657     GpiBitBlt(hpsMem, hps, 3L, aptl, ROP_SRCCOPY, BBO_IGNORE);
1658     GpiDestroyPS(hpsMem);
1659     DevCloseDC(hdcMem);
1660     return hbm;
1661 }
1662
1663
1664 /*
1665 **  Copy ps to a metafile.
1666 */
1667 HMF
1668 CopyToMetaFile(HPS hps)
1669 {
1670     HDC hdcMF, hdcOld;
1671     HAB hab;
1672     HWND hwnd;
1673     PSZ psz[4] = {NULL,"Display",NULL,NULL};
1674     HMF hmf;
1675     hdcOld = GpiQueryDevice(hps);
1676     hwnd = WinWindowFromDC(hdcOld);
1677     hab = WinQueryAnchorBlock(hwnd);
1678     hdcMF = DevOpenDC(hab, OD_METAFILE, "*", 4L, psz, hdcOld);
1679
1680     DosRequestMutexSem(semHpsAccess,(ULONG) SEM_INDEFINITE_WAIT);
1681     GpiSetDrawingMode(hps, DM_DRAW);
1682     GpiAssociate(hps, 0);
1683     GpiAssociate(hps, hdcMF);
1684     ScalePS(hps);
1685     GpiDrawChain(hps);
1686     GpiAssociate(hps, 0);
1687     GpiAssociate(hps, hdcOld);
1688     DosReleaseMutexSem(semHpsAccess);
1689     hmf = DevCloseDC(hdcMF);
1690     return hmf;
1691 }
1692
1693
1694 /*
1695 ** Query INI file
1696 */
1697 BOOL
1698 QueryIni(HAB hab)
1699 {
1700     BOOL         bPos, bData, bSwp ;
1701     ULONG        ulOpts[5];
1702     HINI         hini;
1703     ULONG        ulCB;
1704     char         *p;
1705     static SWP   pauseswp;
1706
1707     /* read gnuplot ini file */
1708
1709     hini = PrfOpenProfile(hab, szIniFile);
1710     ulCB = sizeof(ulShellPos);
1711     bPos = PrfQueryProfileData(hini, APP_NAME, INISHELLPOS, &ulShellPos, &ulCB);
1712     ulCB = sizeof(SWP);
1713     bSwp = PrfQueryProfileData(hini, APP_NAME, INIPAUSEPOS, &pauseswp, &ulCB);
1714     if (bSwp)
1715         pausedata.pswp = &pauseswp;
1716     ulCB = sizeof(ulOpts);
1717     bData = PrfQueryProfileData(hini, APP_NAME, INIOPTS, &ulOpts, &ulCB);
1718     if (bData) {
1719         bLineTypes =(BOOL)ulOpts[0];
1720         bWideLines =(BOOL)ulOpts[1];
1721         bColours =(BOOL)ulOpts[2];
1722         ulPauseMode = ulOpts[3];
1723         bPopFront =(BOOL)ulOpts[4];
1724     } else {
1725         bLineTypes = FALSE;  /* default values */
1726         /*   bWideLines = FALSE; */
1727         bColours = TRUE;
1728         bPopFront = TRUE;
1729         ulPauseMode = 1;
1730     }
1731     ulCB = 4*sizeof(float);
1732     PrfQueryProfileData(hini, APP_NAME, INIFRAC, &qPrintData.xsize, &ulCB);
1733     if (PrfQueryProfileSize(hini, APP_NAME, INIPRDRIV, &ulCB)) {
1734         PDRIVDATA pdriv =(PDRIVDATA) malloc(ulCB);
1735         if (pdriv != NULL) {
1736             PrfQueryProfileData(hini, APP_NAME, INIPRDRIV, pdriv, &ulCB);
1737             qPrintData.pdriv = pdriv;
1738             qPrintData.cbpdriv = ulCB;
1739         }
1740     }
1741     PrfQueryProfileString(hini, APP_NAME, INIPRPR, "",
1742                           qPrintData.szPrinterName,
1743                           (long) sizeof qPrintData.szPrinterName);
1744     PrfQueryProfileString(hini, APP_NAME, INIFONT, INITIAL_FONT,
1745                           szFontNameSize, FONTBUF);
1746     ulCB = sizeof(ulOpts);
1747     bData = PrfQueryProfileData(hini, APP_NAME, INICHAR, &ulOpts, &ulCB);
1748     if (bData) {
1749         lCharWidth = ulOpts[0];
1750         lCharHeight = ulOpts[1];
1751     } else {
1752         lCharWidth = 217;
1753         lCharHeight = 465;
1754     }
1755     ulCB = sizeof(bKeepRatio);
1756     bData = PrfQueryProfileData(hini, APP_NAME, INIKEEPRATIO, &ulOpts, &ulCB);
1757     if (bData) bKeepRatio =(BOOL)ulOpts[0];
1758
1759     /* Mousing: */
1760     /* Ignore reading "Use mouse" --- no good idea to have mouse on by default.
1761        Maybe it was the reason of some crashes(mouse init before draw).
1762        ulCB = sizeof(useMouse);
1763        bData = PrfQueryProfileData(hini, APP_NAME, INIUSEMOUSE, &ulOpts, &ulCB);
1764        if (bData) useMouse =(int)ulOpts[0];
1765     */
1766     /* ignore reading mouse cursor(real, relative or pixels).
1767        Reason/bug: it does not switch the check mark in the menu, even
1768        though it works as expected.
1769        ulCB = sizeof(mouse_mode);
1770        bData = PrfQueryProfileData(hini, APP_NAME, INIMOUSECOORD, &ulOpts, &ulCB);
1771        if (bData) mouse_mode =(ULONG)ulOpts[0];
1772     */
1773
1774     PrfCloseProfile(hini);
1775
1776     if (qPrintData.szPrinterName[0] == '\0') {
1777         /* get default printer name     */
1778         PrfQueryProfileString(HINI_PROFILE,
1779                               "PM_SPOOLER",
1780                               "PRINTER",
1781                               ";",
1782                               qPrintData.szPrinterName,
1783                               (long) sizeof qPrintData.szPrinterName);
1784         if ((p=strchr(qPrintData.szPrinterName, ';')) != NULL)
1785             *p = '\0';
1786     }
1787     bShellPos = bPos;
1788     return bPos;
1789 }
1790
1791
1792 /*
1793 ** save data in ini file
1794 */
1795 static void
1796 SaveIni(HWND hWnd)
1797 {
1798     SWP     swp;
1799     HINI    hini;
1800     ULONG   ulOpts[5];
1801     HAB     hab;
1802
1803     hab = WinQueryAnchorBlock(hWnd);
1804     hini = PrfOpenProfile(hab, szIniFile);
1805     if (hini != NULLHANDLE) {
1806         WinQueryWindowPos(hwndFrame, &swp);
1807         ulPlotPos[0] = swp.x;
1808         ulPlotPos[1] = swp.y;
1809         ulPlotPos[2] = swp.cx;
1810         ulPlotPos[3] = swp.cy;
1811         PrfWriteProfileData(hini, APP_NAME, INISHELLPOS, &ulPlotPos,
1812                             sizeof(ulPlotPos));
1813         if (pausedata.pswp != NULL)
1814             PrfWriteProfileData(hini, APP_NAME, INIPAUSEPOS,
1815                                 pausedata.pswp, sizeof(SWP));
1816         ulOpts[0] =(ULONG)bLineTypes;
1817         ulOpts[1] =(ULONG)bWideLines;
1818         ulOpts[2] =(ULONG)bColours;
1819         ulOpts[3] = ulPauseMode;
1820         ulOpts[4] =(ULONG)bPopFront;
1821         PrfWriteProfileData(hini, APP_NAME, INIOPTS, &ulOpts, sizeof(ulOpts));
1822         PrfWriteProfileData(hini, APP_NAME, INIFRAC, &qPrintData.xsize,
1823                             4*sizeof(float));
1824         if (qPrintData.pdriv != NULL)
1825             PrfWriteProfileData(hini, APP_NAME, INIPRDRIV, qPrintData.pdriv,
1826                                 qPrintData.cbpdriv);
1827         PrfWriteProfileString(hini, APP_NAME, INIPRPR,
1828                               qPrintData.szPrinterName[0] == '\0'? NULL:
1829                               qPrintData.szPrinterName);
1830         PrfWriteProfileString(hini, APP_NAME, INIFONT, szFontNameSize);
1831         ulOpts[0] =(ULONG)lCharWidth;
1832         ulOpts[1] =(ULONG)lCharHeight;
1833         PrfWriteProfileData(hini, APP_NAME, INICHAR, &ulOpts, sizeof(ulOpts));
1834         PrfWriteProfileData(hini, APP_NAME, INIKEEPRATIO, &bKeepRatio,
1835                             sizeof(bKeepRatio));
1836
1837         /* Mouse stuff */
1838         /* Ignore reading "Use mouse" --- no good idea to have mouse on by default.
1839            Maybe it was the reason of some crashes(mouse init before draw).
1840            PrfWriteProfileData(hini, APP_NAME, INIUSEMOUSE, &useMouse, sizeof(useMouse));
1841         */
1842         /* Do not write the mouse coord. mode.
1843            PrfWriteProfileData(hini, APP_NAME, INIMOUSECOORD, &mouse_mode, sizeof(mouse_mode));
1844         */
1845         PrfCloseProfile(hini);
1846     } else {
1847         WinMessageBox(HWND_DESKTOP,
1848                       HWND_DESKTOP,
1849                       "Can't write ini file",
1850                       APP_NAME,
1851                       0,
1852                       MB_OK | MB_ICONEXCLAMATION);
1853     }
1854 }
1855
1856
1857 /*
1858 **  Paint the screen with current data
1859 */
1860 static void
1861 DoPaint(HWND hWnd, HPS hps)
1862 {
1863     static RECTL rectl;
1864
1865     if (tidDraw != 0) {
1866         /* already drawing - stop it; include the rectl now
1867            being drawn in, in the update region; and return
1868            without calling beginpaint so that the paint
1869            message is resent */
1870         GpiSetStopDraw(hpsScreen, SDW_ON);
1871         DosSleep(1);
1872         WinInvalidateRect(hWnd, &rectl, TRUE);
1873         return;
1874     }
1875     /* winbeginpaint here, so paint message is
1876        not resent when we return, then spawn a
1877        thread to do the drawing */
1878     WinBeginPaint(hWnd, hps, &rectl);                 /*rl */
1879     tidDraw = _beginthread(ThreadDraw, NULL, 32768, NULL);
1880 }
1881
1882
1883 /*
1884 **  Thread to draw plot on screen
1885 */
1886 static void
1887 ThreadDraw(void* arg)
1888 {
1889     HAB hab = WinInitialize(0);
1890
1891     InitScreenPS();
1892
1893     DosRequestMutexSem(semHpsAccess,(ULONG) SEM_INDEFINITE_WAIT);
1894     ScalePS(hpsScreen);
1895     GpiSetStopDraw(hpsScreen, SDW_OFF);
1896     GpiSetDrawingMode(hpsScreen, DM_DRAW);
1897     GpiDrawChain(hpsScreen);
1898     DrawRuler();
1899     DisplayStatusLine(hpsScreen);
1900     WinEndPaint(hpsScreen);
1901     DosReleaseMutexSem(semHpsAccess);
1902     WinTerminate(hab);
1903     tidDraw = 0;
1904 #if 0
1905     /* This does not work here(why?!), thus moved to pm.trm: PM_text(); */
1906     gp_exec_event(GE_plotdone, mx, my, 0, 0, 0); /* enable again zoom and scale by mouse motions */
1907 #endif
1908 }
1909
1910
1911 /*
1912 ** Initialise the screen ps for drawing
1913 */
1914 HPS
1915 InitScreenPS()
1916 {
1917     RECTL   rectClient;
1918     int     nColour = 0;
1919
1920     GpiResetPS(hpsScreen, GRES_ATTRS);
1921 #if 0 /* Use default background color(the original version) */
1922     GpiErase(hpsScreen);
1923     WinQueryWindowRect(hApp,(PRECTL)&rectClient);
1924 #else /* PM 14.3.2000: Use always white background */
1925     WinQueryWindowRect(hApp,(PRECTL)&rectClient);
1926     WinFillRect(hpsScreen,&rectClient,CLR_WHITE);
1927 #endif
1928     if (bKeepRatio) {
1929         double ratio = 1.560;
1930         double xs = rectClient.xRight - rectClient.xLeft;
1931         double ys = rectClient.yTop - rectClient.yBottom;
1932
1933         if (ys > xs/ratio) { /* reduce ys to fit */
1934             rectClient.yTop = rectClient.yBottom +(int)(xs/ratio);
1935         } else if (ys < xs/ratio) { /* reduce xs to fit */
1936             rectClient.xRight = rectClient.xLeft +(int)(ys*ratio);
1937         }
1938     } else
1939         /* PM: why this -10? Otherwise the right axis is too close to
1940          * the right border. However, this -10 should be taken into
1941          * account for mousing! Or can it be inside a transformation?
1942          */
1943         rectClient.xRight -= 10;
1944
1945     GpiSetPageViewport(hpsScreen, &rectClient);
1946     if (!bColours) {
1947         int i;
1948
1949         nColour = 16;
1950         alColourTable[0] = 0xFFFFFF;
1951         for (i=1; i<nColour; i++)
1952             alColourTable[i] = 0;
1953     }
1954
1955     if (bPMPaletteMode) {
1956         int i;
1957
1958         GpiCreateLogColorTable(hpsScreen, LCOL_RESET, LCOLF_CONSECRGB,
1959                                0, nColour, alColourTable);
1960         if (!lCols_init) { /* Ilya: avoid white line on white background */
1961             lCols_init = 1;
1962             GpiQueryLogColorTable(hpsScreen, 0, 0, 16, alColourTable + 2);
1963             alColourTable[2+CLR_WHITE] = 0xffffff;              /* -2 */
1964             alColourTable[2+CLR_BLACK] = 0;                     /* -1 */
1965             bkColor = alColourTable[2+CLR_BACKGROUND];
1966             i = -1;
1967             while (i++ < 16) {
1968                 if (alColourTable[2+lCols[i]] == bkColor) {
1969                     while (i++ < 16)
1970                         lCols[i - 1] = lCols[i];
1971                     lCols_num--;
1972                     break;
1973                 }
1974             }
1975         }
1976
1977         /* init rgb_colors: simple index translation only */
1978         for (i=0; i<18; i++)
1979             rgb_colors[i] = i + CLR_WHITE;
1980     } else {
1981         if (!lCols_init) {
1982             int i;
1983
1984             lCols_init = 1;
1985             /* get RGB values of all CLR_xxx constants */
1986             for (i=0; i<18; i++)
1987                 rgb_colors[i] = GpiQueryRGBColor(hpsScreen, LCOLOPT_REALIZED, i + CLR_WHITE );
1988         }
1989
1990         GpiCreateLogColorTable(hpsScreen, LCOL_RESET, LCOLF_RGB, 0, 0, 0);
1991     }
1992     return hpsScreen;
1993 }
1994
1995
1996 /*
1997 **  Get a font to use
1998 **  Scale the plot area to world coords for subsequent plotting
1999 */
2000 short
2001 ScalePS(HPS hps)
2002 {
2003     SelectFont(hps, szFontNameSize);
2004     return 0;
2005 }
2006
2007
2008 /*
2009 **  Select a named and sized outline font
2010 */
2011 void
2012 SelectFont(HPS hps, char *szFontNameSize)
2013 {
2014     HDC    hdc;
2015     FATTRS  fat;
2016     LONG   xDeviceRes, yDeviceRes;
2017     POINTL ptlFont;
2018     SIZEF  sizfx;
2019     static LONG lcid = 0L;
2020     static char *szFontName;
2021     static short shPointSize;
2022
2023     sscanf(szFontNameSize, "%hd", &shPointSize);
2024     szFontName = strchr(szFontNameSize, '.') + 1;
2025
2026     fat.usRecordLength  = sizeof fat;
2027     fat.fsSelection     = 0;
2028     fat.lMatch          = 0;
2029     fat.idRegistry      = 0;
2030     fat.usCodePage      = codepage; /*GpiQueryCp(hps); */
2031     fat.lMaxBaselineExt = 0;
2032     fat.lAveCharWidth   = 0;
2033     fat.fsType          = 0;
2034     fat.fsFontUse       = FATTR_FONTUSE_OUTLINE |
2035         FATTR_FONTUSE_TRANSFORMABLE;
2036
2037     strcpy(fat.szFacename, szFontName);
2038
2039     if (tabFont[0].name !=NULL)
2040         free(tabFont[0].name);
2041     tabFont[0].name = strdup(szFontName);
2042     tabFont[0].lcid = 10L;
2043
2044     lcid = GpiQueryCharSet(hps);
2045     if (lcid != 10L)
2046         lcid = 10L;
2047     else {
2048         GpiSetCharSet(hps, 0L);
2049         GpiDeleteSetId(hps, lcid);
2050     }
2051     GpiCreateLogFont(hps, NULL, lcid, &fat);
2052     GpiSetCharSet(hps, lcid);
2053
2054     hdc = GpiQueryDevice(hps);
2055
2056     DevQueryCaps(hdc, CAPS_HORIZONTAL_RESOLUTION, 1L, &xDeviceRes);
2057     DevQueryCaps(hdc, CAPS_VERTICAL_RESOLUTION,   1L, &yDeviceRes);
2058
2059     /* Find desired font size in pixels */
2060
2061     ptlFont.x = 2540L *(long)shPointSize / 72L;
2062     ptlFont.y = 2540L *(long)shPointSize / 72L;
2063
2064     /* Set the character box */
2065
2066     sizfx.cx = MAKEFIXED(ptlFont.x, 0);
2067     sizfx.cy = MAKEFIXED(ptlFont.y, 0);
2068     lVOffset = ptlFont.y;
2069
2070     sizBaseFont = sizfx;
2071     GpiSetCharBox(hps, &sizfx);
2072
2073     /* set up some useful globals */
2074     {
2075         FONTMETRICS fm;
2076
2077         GpiQueryFontMetrics(hps, sizeof(FONTMETRICS), &fm);
2078         lBaseSubOffset = -fm.lSubscriptYOffset;
2079         lBaseSupOffset = fm.lSuperscriptYOffset;
2080         lSubOffset = lBaseSubOffset;
2081         lSupOffset = lBaseSupOffset;
2082         lCharHeight = fm.lMaxAscender*1.2;
2083         lCharWidth  = fm.lAveCharWidth;
2084         sizBaseSubSup.cx = MAKEFIXED(ptlFont.x*0.7, 0);
2085         sizBaseSubSup.cy = MAKEFIXED(ptlFont.y*0.7, 0);
2086     }
2087     sizCurFont = sizBaseFont;
2088     sizCurSubSup = sizBaseSubSup;
2089 #if 0
2090     if (bNewFont) {
2091         /* EditCharCell(hps, &sizfx); */
2092         bNewFont = FALSE;
2093     }
2094 #endif
2095 }
2096
2097
2098 /*
2099 **  Select a named and sized outline(adobe) font
2100 */
2101 void
2102 SwapFont(HPS hps, char *szFNS)
2103 {
2104     HDC    hdc;
2105     FATTRS  fat;
2106     LONG   xDeviceRes, yDeviceRes;
2107     POINTL ptlFont;
2108     static LONG lcid = 0L;
2109     static int itab = 1;
2110     static char *szFontName;
2111     static short shPointSize;
2112
2113     if (szFNS == NULL) {    /* restore base font */
2114         sizCurFont = sizBaseFont;
2115         sizCurSubSup = sizBaseSubSup;
2116         lSubOffset = lBaseSubOffset;
2117         lSupOffset = lBaseSupOffset;
2118         GpiSetCharSet(hps, 10);
2119         GpiSetCharBox(hps, &sizBaseFont);
2120     } else {
2121         sscanf(szFNS, "%hd", &shPointSize);
2122         szFontName = strchr(szFNS, '.') + 1;
2123
2124         {
2125             int i;
2126
2127             lcid = 0;
2128             for (i=0; i<itab; i++) {
2129                 if (strcmp(szFontName, tabFont[i].name) == 0) {
2130                     lcid = tabFont[i].lcid;
2131                     break;
2132                 }
2133             }
2134         }
2135
2136         if (lcid == 0) {
2137             fat.usRecordLength  = sizeof fat;
2138             fat.fsSelection     = 0;
2139             fat.lMatch          = 0;
2140             fat.idRegistry      = 0;
2141             fat.usCodePage      = codepage; /*GpiQueryCp(hps); */
2142             fat.lMaxBaselineExt = 0;
2143             fat.lAveCharWidth   = 0;
2144             fat.fsType          = 0;
2145             fat.fsFontUse       = FATTR_FONTUSE_OUTLINE |
2146                 FATTR_FONTUSE_TRANSFORMABLE;
2147
2148             strcpy(fat.szFacename, szFontName);
2149
2150             tabFont[itab].name = strdup(szFontName);
2151             lcid = itab+10;
2152             tabFont[itab].lcid = lcid;
2153             ++itab;
2154
2155             /* lcid = 11L; */
2156             GpiSetCharSet(hps, 0L);
2157             GpiDeleteSetId(hps, lcid);
2158             GpiCreateLogFont(hps, NULL, lcid, &fat);
2159         } /* if (lcid) */
2160
2161         GpiSetCharSet(hps, lcid);
2162         hdc = GpiQueryDevice(hps);
2163
2164         DevQueryCaps(hdc, CAPS_HORIZONTAL_RESOLUTION, 1L, &xDeviceRes);
2165         DevQueryCaps(hdc, CAPS_VERTICAL_RESOLUTION,   1L, &yDeviceRes);
2166
2167         /* Find desired font size in pixels */
2168         ptlFont.x = 2540L *(long)shPointSize / 72L;
2169         ptlFont.y = 2540L *(long)shPointSize / 72L;
2170
2171         /* Set the character box */
2172         sizCurFont.cx = MAKEFIXED(ptlFont.x, 0);
2173         sizCurFont.cy = MAKEFIXED(ptlFont.y, 0);
2174         /* lVOffset = ptlFont.y; */
2175
2176         GpiSetCharBox(hps, &sizCurFont);
2177         sizCurSubSup.cx = MAKEFIXED(ptlFont.x*0.7, 0);
2178         sizCurSubSup.cy = MAKEFIXED(ptlFont.y*0.7, 0);
2179
2180         /* set up some useful globals */
2181         {
2182             FONTMETRICS fm;
2183
2184             GpiQueryFontMetrics(hps, sizeof(FONTMETRICS), &fm);
2185             lSubOffset = -fm.lSubscriptYOffset;
2186             lSupOffset = fm.lSuperscriptYOffset;
2187         }
2188     }
2189 }
2190
2191 typedef struct image_list_entry {
2192     PBITMAPINFO2 pbmi;
2193     PBYTE image;
2194     struct image_list_entry *next;
2195 } image_list_entry;
2196 static image_list_entry *image_list = NULL;
2197
2198
2199 /*
2200 ** Thread to read plot commands from GNUPLOT pm driver.
2201 ** Opens named pipe, then clears semaphore to allow GNUPLOT driver to proceed.
2202 ** Reads commands and builds a command list.
2203 */
2204 static void
2205 ReadGnu(void* arg)
2206 {
2207     HPIPE hRead = 0L;
2208     POINTL ptl;
2209     long lOldLine = 0;
2210     BOOL bPath = FALSE;
2211     BOOL bDots = FALSE;
2212     ULONG rc;
2213     USHORT usErr;
2214     ULONG cbR;
2215     USHORT i;
2216     unsigned char buff[2];
2217     HEV hev;
2218     static char *szPauseText = NULL;
2219     ULONG ulPause;
2220     char *pszPipeName, *pszSemName;
2221     HPS hps;
2222     HAB hab;
2223     int linewidth = DEFLW;
2224     HPAL pm3d_hpal = 0;     /* palette used for make_palette() */
2225     HPAL pm3d_hpal_old = 0; /* default palette used before make_palette() */
2226     LONG pm3d_color = 0;    /* current colour (used if it is >0) */
2227     ULONG *rgbTable = NULL; /* current colour table (this is a 'virtual' palette) */
2228
2229     hab = WinInitialize(0);
2230     DosEnterCritSec();
2231     pszPipeName = malloc(256);
2232     pszSemName  = malloc(256);
2233     DosExitCritSec();
2234     strcpy(pszPipeName, "\\pipe\\");
2235     strcpy(pszSemName, "\\sem32\\");
2236     strcat(pszPipeName, szIPCName);
2237     strcat(pszSemName, szIPCName);
2238
2239     /* open a named pipe for communication with gnuplot */
2240
2241     rc = DosCreateNPipe(pszPipeName,
2242                         &hRead,
2243                         NP_ACCESS_DUPLEX|NP_NOINHERIT|NP_NOWRITEBEHIND ,
2244                         1|NP_WAIT|NP_READMODE_MESSAGE|NP_TYPE_MESSAGE,
2245                         PIPEBUF,
2246                         PIPEBUF,
2247                         0xFFFFFFFF);
2248     hev = 0;       /* OK, gnuplot can try to open npipe ... */
2249     DosOpenEventSem(pszSemName, &hev);
2250     DosPostEventSem(hev);
2251
2252     /* attach to gnuplot */
2253   server:
2254
2255     if (DosConnectNPipe(hRead) == 0L) {
2256         WinPostMsg(hSysMenu,
2257                    MM_SETITEMATTR,
2258                    MPFROM2SHORT(SC_CLOSE, TRUE),
2259                    MPFROM2SHORT(MIA_DISABLED, MIA_DISABLED));
2260
2261         /* store graphics commands */
2262         /* use semaphore to prevent problems with drawing while reallocating
2263            the command buffers */
2264
2265         DosRead(hRead, &ppidGnu, 4, &cbR);
2266
2267         sprintf(mouseShareMemName, "\\SHAREMEM\\GP%i_Mouse_Input",(int)ppidGnu);
2268         if (DosGetNamedSharedMem(&input_from_PM_Terminal,
2269                                  mouseShareMemName,
2270                                  PAG_WRITE)) {
2271             /*now: gray menu items; old code: DosBeep(1440L,1000L); // indicates error */
2272             input_from_PM_Terminal = 0;
2273         }
2274
2275         semInputReady = 0;
2276         /* semaphore 'semInputReady' must be open later in order to avoid problems */
2277         /* with the server mode; also 'bhave_*' init here because of server */
2278
2279         /* DosPostEventSem(semStartSeq);         // once we've got pidGnu */
2280         WinPostMsg(hApp, WM_GPSTART, 0, 0);
2281
2282
2283         hps = hpsScreen;
2284         InitScreenPS();
2285         while (1) {
2286             usErr=BufRead(hRead,buff, 1, &cbR);
2287             if (usErr != 0)
2288                 break;
2289
2290             if (breakDrawing) {
2291                 /* PM: drawing has been stopped(by Ctrl-C)... */
2292                 hps = 0;        /*     ...thus drawings go to nowhere... */
2293                 if (*buff == SET_TEXT) { /* ...unless 'plot finished' command */
2294                     POINTL p;
2295                     hps = hpsScreen;  /* drawings back to screen */
2296                     breakDrawing = 0;
2297                     GpiSetColor(hps, RGB_TRANS(CLR_RED)); /* cross the unfinished plot */
2298                     GpiBeginPath(hps, 1);
2299                     p.x = p.y = 0; GpiMove(hps, &p);
2300                     p.x = 19500; p.y = 12500; GpiLine(hps, &p);
2301                     p.x = 0; p.y = 12500; GpiMove(hps, &p);
2302                     p.x = 19500; p.y = 0; GpiLine(hps, &p);
2303                     GpiEndPath(hps);
2304                     GpiStrokePath(hps, 1, 0);
2305                 }
2306             }
2307
2308             switch (*buff) {
2309             case SET_GRAPHICS :    /* enter graphics mode */
2310             {
2311                 image_list_entry *ile;
2312
2313                 if (tidDraw != 0) {
2314                     /* already drawing - stop it */
2315                     GpiSetStopDraw(hpsScreen, SDW_ON);
2316                     while (tidDraw != 0) DosSleep(1);
2317                 }
2318                 /* wait for access to command list and lock it */
2319                 /* DosWaitEventSem(semDrawDone, SEM_INDEFINITE_WAIT);                     */
2320                 /* DosEnterCritSec(); */
2321                 DosRequestMutexSem(semHpsAccess,(ULONG) SEM_INDEFINITE_WAIT);
2322                 InitScreenPS();
2323                 ScalePS(hps);
2324                 /* DosResetEventSem(semDrawDone, &ulCount); */
2325                 GpiSetDrawingMode(hps, DM_DRAWANDRETAIN);
2326                 for (i=1;i<=iSeg;i++)
2327                     GpiDeleteSegment(hps, i);
2328                 iSeg = 1;
2329                 GpiOpenSegment(hps, iSeg);
2330                 /* DosExitCritSec(); */
2331                 GpiSetLineEnd(hps, LINEEND_ROUND);
2332                 GpiSetLineWidthGeom(hps, linewidth);
2333                 GpiSetCharBox(hps, &sizBaseFont);
2334
2335                 /* free image buffers from previous plot, if any */
2336                 while (image_list) {
2337                     DEBUG_IMAGE(("freeing image from last plot"));
2338                     ile = image_list;
2339                     image_list = ile->next;
2340                     free(ile->image);
2341                     free(ile->pbmi);
2342                     free(ile);
2343                 }
2344
2345                 break;
2346             }
2347
2348             case GR_QUERY :     /* query terminal info */
2349                 /* mouseable gnupmdrv sends greetings to mouseable PM terminal */
2350                 if (mouseTerminal) {
2351                     int i=0xABCD;
2352
2353                     DosWrite(hRead, &i, sizeof(int), &cbR);
2354                 }
2355                 DosWrite(hRead, &lCharWidth, sizeof(int), &cbR);
2356                 DosWrite(hRead, &lCharHeight, sizeof(int), &cbR);
2357                 break;
2358
2359             case SET_TEXT :     /* leave graphics mode(graph completed) */
2360                 if (bPath) {
2361                     GpiEndPath(hps);
2362                     GpiStrokePath(hps, 1, 0);
2363                     bPath = FALSE;
2364                 }
2365                 GpiCloseSegment(hps);
2366                 DrawRuler();
2367                 DisplayStatusLine(hps);
2368                 /* DosPostEventSem(semDrawDone); */
2369                 DosReleaseMutexSem(semHpsAccess);
2370                 WinPostMsg(hApp, WM_GNUPLOT, 0L, 0L);
2371                 break;
2372
2373             case GR_RESET :
2374                 /* gnuplot has reset drivers, allow user to kill this */
2375                 WinPostMsg(hSysMenu,
2376                            MM_SETITEMATTR,
2377                            MPFROM2SHORT(SC_CLOSE, TRUE),
2378                            MPFROM2SHORT(MIA_DISABLED,(USHORT)0));
2379
2380                 /* if we are keeping us on the screen, wait for new connection */
2381                 if (bServer||bPersist) {
2382                     DosDisConnectNPipe(hRead);
2383                     goto server;
2384                 }
2385                 break;
2386
2387             case GR_RESUME :
2388             {
2389                 /* resume after multiplot */
2390                 DosRequestMutexSem(semHpsAccess,(ULONG) SEM_INDEFINITE_WAIT);
2391                 /* DosWaitEventSem(semDrawDone, SEM_INDEFINITE_WAIT); */
2392                 iSeg++;
2393                 /* DosResetEventSem(semDrawDone, &ulCount); */
2394                 GpiSetDrawingMode(hps, DM_DRAWANDRETAIN);
2395                 GpiOpenSegment(hps, iSeg);
2396                 break;
2397             }
2398
2399             case 's' :
2400                 /* suspend after multiplot */
2401                 break;
2402
2403             case GR_MOVE :   /* move */
2404             case GR_DRAW :   /* draw vector */
2405             {
2406                 LONG curr_color;
2407
2408                 if (pm3d_color >= 0) {
2409                     curr_color = GpiQueryColor(hps);
2410                     GpiSetColor(hps, pm3d_color);
2411                 }
2412                 if (*buff=='M') {
2413                     if (bPath) {
2414                         GpiEndPath(hps);
2415                         GpiStrokePath(hps, 1, 0);
2416                         bPath = FALSE;
2417                     }
2418                 } else {
2419                     if (bWideLines/*bWideLines*/ && !bPath) {
2420                         GpiBeginPath(hps, 1);
2421                         bPath = TRUE;
2422                     }
2423                 }
2424                 BufRead(hRead,&ptl.x, 2*sizeof(int), &cbR);
2425                 if ((*buff=='V') && bDots)
2426                     ptl.x += 5;
2427                 else if ((*buff=='M') && bDots)
2428                     ptl.x -= 5;
2429                 if (*buff == 'M')
2430                     LMove(hps, &ptl);
2431                 else
2432                     LLine(hps, &ptl);
2433
2434                 if (pm3d_color >= 0)
2435                     GpiSetColor(hps, curr_color);
2436             }
2437             break;
2438
2439             case GR_PAUSE  :   /* pause */
2440             {
2441                 int len;
2442
2443                 pausing = 1;
2444                 BufRead(hRead, &len, sizeof(int), &cbR);
2445                 len = (len + sizeof(int) - 1) / sizeof(int);
2446                 if (len > 0){  /* get pause text */
2447                     DosEnterCritSec();
2448                     szPauseText = malloc(len*sizeof(int));
2449                     DosExitCritSec();
2450                     BufRead(hRead,szPauseText, len*sizeof(int), &cbR);
2451                 }
2452                 if (ulPauseMode != PAUSE_GNU) {
2453                     /* pause and wait for semaphore to be cleared */
2454                     DosResetEventSem(semPause, &ulPause);
2455                     WinPostMsg(hApp, WM_PAUSEPLOT,(MPARAM) szPauseText, 0L);
2456                     DosWaitEventSem(semPause, SEM_INDEFINITE_WAIT);
2457                 } else { /* gnuplot handles pause */
2458                     ulPauseReply = 2;
2459                 }
2460                 DosEnterCritSec();
2461                 if (szPauseText != NULL)
2462                     free(szPauseText);
2463                 szPauseText = NULL;
2464                 DosExitCritSec();
2465                 /* reply to gnuplot so it can continue */
2466                 DosWrite(hRead, &ulPauseReply, sizeof(int), &cbR);
2467                 pausing = 0;
2468                 break;
2469             }
2470
2471             case GR_ENH_TEXT :  /* write enhanced text */
2472                 if (bPath) {
2473                     GpiEndPath(hps);
2474                     GpiStrokePath(hps, 1, 0);
2475                     bPath = FALSE;
2476                 }
2477                 {
2478                     unsigned int x, y, len;
2479                     unsigned int mode;
2480                     int textwidth, textheight;
2481                     char *str;
2482                     POINTL aptl[TXTBOX_COUNT];
2483
2484                     /* read x, y, mode, len */
2485                     BufRead(hRead, &x, sizeof(int), &cbR);
2486                     BufRead(hRead, &y, sizeof(int), &cbR);
2487                     BufRead(hRead, &mode, sizeof(int), &cbR);
2488                     BufRead(hRead, &len, sizeof(int), &cbR);
2489
2490                     DosEnterCritSec();
2491                     len =(len+sizeof(int)-1)/sizeof(int);
2492                     if (len == 0) len = 1; /*?? how about read */
2493                     str = malloc(len*sizeof(int));
2494                     *str = '\0';
2495                     DosExitCritSec();
2496                     BufRead(hRead, str, len*sizeof(int), &cbR);
2497
2498                     GpiQueryTextBox(hps, strlen(str), str, TXTBOX_COUNT, aptl);
2499                     textwidth = aptl[TXTBOX_CONCAT].x;
2500                     textheight = aptl[TXTBOX_CONCAT].y;
2501
2502                     /* only display text if requested */
2503                     if (mode & 0x01) {
2504                         LONG curr_color;
2505
2506                         if (pm3d_color >= 0) {
2507                             curr_color = GpiQueryColor(hps);
2508                             GpiSetColor(hps, pm3d_color);
2509                         }
2510                         ptl.x = (LONG) (x + multLineVert * (lVOffset / 4));
2511                         ptl.y = (LONG) (y - multLineHor * (lVOffset / 4));
2512
2513                         GpiSetBackMix(hps, BM_LEAVEALONE);
2514                         GpiCharStringAt(hps, &ptl, strlen(str), str);
2515
2516                         if (pm3d_color >= 0)
2517                             GpiSetColor(hps, curr_color);
2518                     }
2519
2520                     /* report back textwidth */
2521                     DosWrite(hRead, &textwidth, sizeof(textwidth), &cbR);
2522                     DosWrite(hRead, &textheight, sizeof(textheight), &cbR);
2523
2524                     DosEnterCritSec();
2525                     free(str);
2526                     DosExitCritSec();
2527
2528                     break;
2529                 }
2530
2531             case GR_TEXT :   /* write text */
2532                 /* read x, y, len */
2533                 if (bPath) {
2534                     GpiEndPath(hps);
2535                     GpiStrokePath(hps, 1, 0);
2536                     bPath = FALSE;
2537                 }
2538                 {
2539                     unsigned int x, y, len;
2540                     int sw;
2541                     char *str;
2542                     LONG curr_color;
2543 #ifndef PM_KEEP_OLD_ENHANCED_TEXT
2544                     POINTL aptl[TXTBOX_COUNT];
2545 #endif
2546                     BufRead(hRead,&x, sizeof(int), &cbR);
2547                     BufRead(hRead,&y, sizeof(int), &cbR);
2548                     BufRead(hRead,&len, sizeof(int), &cbR);
2549
2550                     DosEnterCritSec();
2551                     len =(len+sizeof(int)-1)/sizeof(int);
2552                     if (len == 0) len = 1; /*?? how about read */
2553                     str = malloc(len*sizeof(int));
2554                     *str = '\0';
2555                     DosExitCritSec();
2556                     BufRead(hRead, str, len*sizeof(int), &cbR);
2557                     if (pm3d_color >= 0) {
2558                         curr_color = GpiQueryColor(hps);
2559                         GpiSetColor(hps, pm3d_color);
2560                     }
2561
2562 #ifdef PM_KEEP_OLD_ENHANCED_TEXT
2563                     sw = QueryTextBox(hps, strlen(str), str);
2564 #else
2565                     GpiQueryTextBox(hps, strlen(str), str, TXTBOX_COUNT, aptl);
2566                     sw = aptl[TXTBOX_BOTTOMRIGHT].x;
2567 #endif
2568
2569                     switch (jmode) {
2570                     case LEFT:
2571                         sw = 0;
2572                         break;
2573                     case CENTRE:
2574                         sw /= -2;
2575                         break;
2576                     case RIGHT:
2577                         sw *= -1;
2578                         break;
2579                     }
2580
2581                     ptl.x = (LONG) (x + multLineHor * sw + multLineVert * (lVOffset / 4));
2582                     ptl.y = (LONG) (y + multLineVert * sw - multLineHor * (lVOffset / 4));      
2583
2584                     GpiSetBackMix(hps, BM_LEAVEALONE);
2585
2586 #ifdef PM_KEEP_OLD_ENHANCED_TEXT
2587                     if (bEnhanced)
2588                         CharStringAt(hps, ptl.x, ptl.y, strlen(str) , str);
2589                     else
2590 #endif
2591                         GpiCharStringAt(hps, &ptl, strlen(str), str);
2592
2593                     if (pm3d_color >= 0)
2594                         GpiSetColor(hps, curr_color);
2595
2596                     DosEnterCritSec();
2597                     free(str);
2598                     DosExitCritSec();
2599
2600                     break;
2601                 }
2602
2603             case SET_JUSTIFY :   /* justify */
2604                 BufRead(hRead, &jmode, sizeof(int), &cbR);
2605                 //printf( "SET_JUSTIFY: %i", jmode );
2606                 break;
2607
2608             case SET_ANGLE :   /* text angle */
2609             {
2610                 int ta, t1;
2611                 GRADIENTL grdl;
2612
2613                 if (bPath) {
2614                     GpiEndPath(hps);
2615                     GpiStrokePath(hps, 1, 0);
2616                     bPath = FALSE;
2617                 }
2618                 BufRead(hRead, &ta, sizeof(int), &cbR);
2619                 t1 = ta % 360;
2620                 if (t1 < 0)
2621                     t1 += 360;
2622                 switch (t1) {
2623                 case   0:
2624                     grdl.x =  1L;
2625                     grdl.y =  0L;
2626                     multLineHor = 1;
2627                     multLineVert = 0;
2628                     break;
2629                 case  90:
2630                     grdl.x =  0L;
2631                     grdl.y =  1L;
2632                     multLineHor = 0;
2633                     multLineVert = 1;
2634                     break;
2635                 case 180:
2636                     grdl.x = -1L;
2637                     grdl.y =  0L;
2638                     multLineHor = -1;
2639                     multLineVert = 0;
2640                     break;
2641                 case 270:
2642                     grdl.x =  0L;
2643                     grdl.y = -1L;
2644                     multLineHor = 0;
2645                     multLineVert = -1;
2646                     break;
2647                 default:  {
2648                     double t = t1 * M_PI/180;
2649
2650                     grdl.x = (LONG) (100 * cos(t));
2651                     grdl.y = (LONG) (100 * sin(t));
2652                     multLineHor = cos(t);
2653                     multLineVert = sin(t);
2654                 } /* default case */
2655                 } /* switch(t1) */
2656
2657                 GpiSetCharAngle(hps, &grdl);
2658                 break;
2659             }
2660
2661             case SET_LINE :   /* line type */
2662             {
2663                 int lt, col;
2664
2665                 if (bPath) {
2666                     GpiEndPath(hps);
2667                     GpiStrokePath(hps, 1, 0);
2668                     bPath = FALSE;
2669                 }
2670                 BufRead(hRead,&lt, sizeof(int), &cbR);
2671                 /* linetype = -2 axes, -1 border, 0 arrows, all to 0 */
2672                 col = lt;
2673                 if (lt == -2)     GpiSetLineWidthGeom(hps, DEFLW*0.85);
2674                 else if (lt == -1) GpiSetLineWidthGeom(hps, DEFLW*0.6);
2675                 else GpiSetLineWidthGeom(hps, linewidth);
2676                 if (lt < 0) lt = 0;
2677                 lt =(lt%8);
2678                 col =(col+2)%16;
2679                 GpiLabel(hps, lLineTypes[lt]);
2680                 lOldLine = lt;
2681                 LType((bLineTypes) ? lt : 0);
2682                 /* GpiSetLineType(hps, (bLineTypes) ? lLineTypes[lt] : lLineTypes[0]); */
2683                 /* maintain some flexibility here in case we don't want
2684                  * the model T option */
2685                 if (bColours)
2686                     GpiSetColor(hps, RGB_TRANS(lCols[col]));
2687                 /* else GpiSetColor(hps, RGB_TRANS(CLR_BLACK)); */
2688                 else
2689                     GpiSetColor(hps, RGB_TRANS(CLR_NEUTRAL));
2690                 pm3d_color = -1; /* switch off using pm3d colours */
2691                 break;
2692             }
2693
2694             case SET_FILLBOX :   /* fill box */
2695             {
2696                 int style;
2697                 unsigned int x, y, w, h;
2698                 POINTL pt;
2699
2700                 BufRead(hRead,&style, sizeof(style), &cbR);
2701                 BufRead(hRead,&x, sizeof(x), &cbR);
2702                 BufRead(hRead,&y, sizeof(y), &cbR);
2703                 BufRead(hRead,&w, sizeof(w), &cbR);
2704                 BufRead(hRead,&h, sizeof(h), &cbR);
2705                 pt.x = x;
2706                 pt.y = y;
2707                 GpiMove(hpsScreen, &pt);
2708                 pt.x += w;
2709                 pt.y += h;
2710
2711                 switch(style & 0xf) {
2712
2713                     case FS_SOLID:
2714                     {
2715                         /* style == 1 --> fill with intensity according to filldensity */
2716                         static const ULONG patternlist[] = {
2717                             PATSYM_NOSHADE, PATSYM_DENSE8, PATSYM_DENSE7,
2718                             PATSYM_DENSE6, PATSYM_DENSE5, PATSYM_DENSE4,
2719                             PATSYM_DENSE3, PATSYM_DENSE2, PATSYM_DENSE1,
2720                             PATSYM_SOLID
2721                         };
2722                         unsigned pattern;
2723
2724                         pattern = (unsigned) trunc(9*((style >> 4) / 100.0) + 0.5);
2725                         if (pattern > 10)
2726                             pattern = 9; /* only 10 patterns in list */
2727                         GpiSetMix(hps, FM_OVERPAINT);
2728                         GpiSetBackMix(hps, BM_OVERPAINT);
2729                         GpiSetPattern(hps, patternlist[pattern]);
2730                         break;
2731                     }
2732
2733                     case FS_PATTERN:
2734                     {
2735                         /* style == 2 --> fill with pattern according to fillpattern */
2736                         /* the upper 3 nibbles of 'style' contain pattern number */
2737                         static const ULONG patternlist[] = {
2738                             PATSYM_NOSHADE, PATSYM_DIAGHATCH,
2739                             PATSYM_HATCH, PATSYM_SOLID,
2740                             PATSYM_DIAG4, PATSYM_DIAG2,
2741                             PATSYM_DIAG3, PATSYM_DIAG1
2742                         };
2743                         unsigned pattern;
2744
2745                         pattern = (style >> 4) % 8;
2746                         GpiSetMix(hps, FM_OVERPAINT);
2747                         GpiSetBackMix(hps, BM_OVERPAINT);
2748                         GpiSetPattern(hps, patternlist[pattern]);
2749                         break;
2750                     }
2751
2752                     case FS_EMPTY:
2753                     default:
2754                     {
2755                         /* style == 0 or unknown --> fill with background color */
2756                         GpiSetMix(hps, FM_OVERPAINT);
2757                         GpiSetBackMix(hps, BM_OVERPAINT);
2758                         //GpiSetColor(hps, RGB_TRANS(CLR_BACKGROUND));  // fixes 'with boxes' white on white
2759                         GpiSetPattern(hps, PATSYM_SOLID);
2760                     }
2761                 }
2762                 GpiBox(hps, DRO_FILL, &pt, 0,0);
2763                 break;
2764             }
2765
2766             case SET_LINEWIDTH :   /* line width */
2767             {
2768                 int lw;
2769
2770                 if (bPath) {
2771                     GpiEndPath(hps);
2772                     GpiStrokePath(hps, 1, 0);
2773                     bPath = FALSE;
2774                 }
2775                 BufRead(hRead,&lw, sizeof(int), &cbR);
2776                 GpiSetLineWidthGeom(hps, DEFLW*lw/100);
2777                 linewidth = DEFLW*lw/100;
2778                 break;
2779             }
2780
2781             case SET_POINTMODE :   /* points mode */
2782             {
2783                 int lt;
2784
2785                 BufRead(hRead,&lt, sizeof(int), &cbR);
2786                 /* 1: enter point mode, 0: exit */
2787                 if (bLineTypes) {
2788                     if (lt==1)
2789                         LType(0);
2790                     else
2791                         LType(lOldLine);
2792 #if 0
2793                     if (lt == 1)
2794                         lOldLine = GpiSetLineType(hps, lLineTypes[0]);
2795                     else
2796                         GpiSetLineType(hps, lOldLine);
2797 #endif /* 0 */
2798                 }
2799 #if 0
2800                 if (lt == 1)
2801                     GpiSetLineWidthGeom(hps, 20);
2802                 else
2803                     GpiSetLineWidthGeom(hps, 50);
2804 #endif /* 0 */
2805                 bDots = lt;
2806             }
2807             break;
2808
2809             case SET_FONT :   /* set font */
2810             {
2811                 int len;
2812
2813                 BufRead(hRead, &len, sizeof(int), &cbR);
2814                 len = (len + sizeof(int) - 1) / sizeof(int);
2815
2816                 if (len == 0) {
2817                     SwapFont(hps, NULL);
2818                     strcpy(szCurrentFontNameSize, szFontNameSize);
2819                 } else {
2820                     char font[FONTBUF];
2821                     char *p, *tmp, *str;
2822
2823                     tmp = str = malloc(len * sizeof(int));
2824                     BufRead(hRead, str, len * sizeof(int), &cbR);
2825                     p = strchr(str, ',');
2826                     if (p==NULL)
2827                         strcpy(font, "10");
2828                     else {
2829                         *p = '\0';
2830                         strcpy(font, p+1);
2831                     }
2832                     strcat(font, ".");
2833                     /* allow abbreviation of some well known font names */
2834                     FontExpand(str);
2835                     strcat(font, str);
2836                     free(tmp);
2837                     SwapFont(hps, font);
2838                     strcpy(szCurrentFontNameSize, font);
2839                 } /* else(len==0) */
2840                 break;
2841             }
2842
2843             case GR_QUERY_FONT : /* query current font */
2844             {
2845                 int namelen;
2846
2847                 namelen = strlen(szCurrentFontNameSize);
2848                 DosWrite(hRead, &namelen, sizeof(int), &cbR);
2849                 DosWrite(hRead, szCurrentFontNameSize, namelen, &cbR);
2850                 /* FIXME: is padding necessary? */
2851                 break;
2852             }
2853
2854             case SET_OPTIONS :   /* set options */
2855             {
2856                 int len;
2857                 char *str;
2858
2859                 BufRead(hRead,&len, sizeof(int), &cbR);
2860                 len =(len + sizeof(int) - 1) / sizeof(int);
2861                 bWideLines = FALSE; /* reset options */
2862 #ifdef PM_KEEP_OLD_ENHANCED_TEXT
2863                 bEnhanced = FALSE;
2864 #endif
2865                 if (len > 0) {
2866                     char *p;
2867
2868                     p = str = malloc(len * sizeof(int));
2869                     BufRead(hRead, str, len * sizeof(int), &cbR);
2870                     while ((p=strchr(p,'-')) != NULL) {
2871                         ++p;
2872                         if (*p == 'w')
2873                             bWideLines = TRUE;
2874 #ifdef PM_KEEP_OLD_ENHANCED_TEXT
2875                         if (*p == 'e')
2876                             bEnhanced = TRUE;
2877 #endif
2878                         ++p;
2879                     }
2880                     free(str);
2881                 }
2882                 break;
2883             }
2884
2885             case SET_SPECIAL :   /* set special options */
2886             {
2887                 char opt;
2888 #ifdef PM_KEEP_OLD_ENHANCED_TEXT
2889                 char param;
2890                 static int prev_bEnhanced = 0;
2891 #endif
2892
2893                 BufRead(hRead,&opt, 1, &cbR);
2894                 switch (opt) {
2895 #ifdef PM_KEEP_OLD_ENHANCED_TEXT
2896                 case 'e': /* enhanced mode on, off and restore */
2897                     BufRead(hRead,&param, 1, &cbR);         
2898                     switch (param) {
2899                     case '0': prev_bEnhanced = bEnhanced;
2900                         bEnhanced = 0;
2901                         break;
2902                     case '1': prev_bEnhanced = bEnhanced;
2903                         bEnhanced = 1;
2904                         break;
2905                     case '2': bEnhanced = prev_bEnhanced;
2906                         break;
2907                     }
2908                     break;
2909 #endif
2910                 case 'c': /* set codepage */
2911                     BufRead(hRead,&codepage, sizeof(codepage), &cbR);
2912                     break;
2913                 case '^': /* raise window */
2914                     WinSetWindowPos( hwndFrame, HWND_TOP, 0,0,0,0, SWP_RESTORE|SWP_SHOW|SWP_ACTIVATE|SWP_ZORDER ) ;
2915                     WinSetFocus( HWND_DESKTOP, hApp ) ;
2916                     break;
2917                 case '_': /* lower window */
2918                     WinSetWindowPos( hwndFrame, HWND_BOTTOM, 0,0,0,0, SWP_ZORDER ) ;
2919                     break;
2920                 }
2921                 break;
2922             }
2923
2924             case PUT_TMPTEXT :
2925             {  /* put_tmptext(int i, char c[]) term API */
2926                 /* i = 0 at statusline,
2927                    1,2: at corners of zoom box, with \r separating text */
2928                 int where, l;
2929                 static char *text = NULL;
2930                 static int text_alloc = -1;
2931
2932                 /* Position of the "table" of values resulting from
2933                  * mouse movement(and clicks).  Negative y value would
2934                  * position it at the top of the window---not
2935                  * implemented. */
2936                 BufRead(hRead,&where, sizeof(int), &cbR);
2937                 BufRead(hRead,&l, sizeof(int), &cbR);
2938                 if (text_alloc < l)
2939                     text = realloc(text, text_alloc = l+10);
2940                 BufRead(hRead,&text[0], l, &cbR);
2941                 switch (where) {
2942                 case 0:
2943                     UpdateStatusLine(hps,text);
2944                     break;
2945                 case 1:
2946                 case 2:
2947                     break; /* not implemented */
2948                 }
2949                 break;
2950             }
2951
2952             /* Implementation problems(I haven't understood that from
2953              * .INF doc): what is the difference between
2954              * GpiCreateLogColorTable and GpiCreatePalette? */
2955             case GR_MAKE_PALETTE :
2956             {
2957                 unsigned char c;
2958                 int smooth_colors;
2959                 LONG lRetCount;
2960
2961                 /* read switch */
2962                 BufRead(hRead, &c, sizeof(c), &cbR);
2963                 if (c == 0) {
2964                     /* gnuplot asks for the number of colours in palette */
2965                     smooth_colors = (bPMPaletteMode ? (256 - nColors) : RGB_PALETTE_SIZE);
2966                     DosWrite(hRead, &smooth_colors, sizeof(int), &cbR);
2967                     DEBUG_COLOR(("GR_MAKE_PALETTE: max %i colours", smooth_colors));
2968                     break;
2969                 }
2970
2971                 /* read the number of colours for the palette */
2972                 BufRead(hRead, &smooth_colors, sizeof(int), &cbR);
2973                 free(rgbTable);
2974                 rgbTable = malloc(smooth_colors * sizeof(ULONG));
2975
2976                 /* append new RGB table after */
2977                 DEBUG_COLOR(("GR_MAKE_PALETTE: reading palette with %i colours", smooth_colors));
2978                 BufRead(hRead, &rgbTable[bPMPaletteMode ? nColors : 0],
2979                         smooth_colors * sizeof(ULONG), &cbR);
2980
2981                 if (bPMPaletteMode) {
2982                     int i;
2983                     ULONG cclr;
2984
2985                     /* preserve the first nColors entries of current palette */
2986                     /* retrieve the current table */
2987                     lRetCount = GpiQueryLogColorTable(hps, 0L, 0L, nColors, alColourTable);
2988                     if ((lRetCount > 0) && (lRetCount != nColors)) /* ring for developers! */
2989                         DosBeep(880, 777);
2990                     for (i=0; i<nColors; i++)
2991                         rgbTable[i] = alColourTable[i];
2992
2993                     if (pm3d_hpal != 0)
2994                         GpiDeletePalette(pm3d_hpal);
2995                     pm3d_hpal = GpiCreatePalette(hab, 0L, LCOLF_CONSECRGB,
2996                                              (long) (nColors + smooth_colors), rgbTable);
2997                     pm3d_hpal_old = GpiSelectPalette(hps, pm3d_hpal);
2998
2999                     /* tell presentation manager to use the new palette */
3000                     WinRealizePalette(WinWindowFromDC(hdcScreen), hps, &cclr);
3001                 }
3002                 break;
3003             }
3004
3005             case GR_RELEASE_PALETTE :
3006 #if 0 /* FIXME: REMOVE THIS ROUTINE COMPLETELY! */
3007                 if (pm3d_hpal) {
3008                     GpiDeletePalette(pm3d_hpal);
3009                     pm3d_hpal = 0;
3010                 }
3011                 /* GpiSelectPalette(hps, pm3d_hpal_old); */
3012 #endif
3013                 break;
3014
3015             case GR_SET_COLOR :
3016             {
3017                 /* FIXME: usgage of uchar limits the size of the 'virtual'
3018                           palette to 256 entries. (see also RGB_PALETTE_SIZE) */
3019                 unsigned char c;
3020
3021                 BufRead(hRead, &c, sizeof(c), &cbR);
3022                 if (bPMPaletteMode)
3023                     pm3d_color = c + nColors;
3024                 else
3025                     pm3d_color = rgbTable[c];
3026                 DEBUG_COLOR(("GR_SET_COLOR: %i -> 0x%x", (int)c, pm3d_color)); 
3027                 break;
3028             }
3029
3030             case GR_SET_RGBCOLOR :
3031             {
3032                 int rgb_color;
3033
3034                 BufRead(hRead, &rgb_color, sizeof(rgb_color), &cbR);
3035
3036                 /* Find an approximate color in the current palette */
3037                 if (bPMPaletteMode)
3038                     pm3d_color = GpiQueryColorIndex(hps, 0, rgb_color);
3039                 else
3040                     pm3d_color = rgb_color;
3041 #if 0
3042                 {
3043                 int real_rgb = GpiQueryRGBColor(hps, LCOLOPT_REALIZED, pm3d_color);
3044                 DEBUG_COLOR(( "GR_SET_RGBCOLOR: req = %x  nearest = %x  index = %x", 
3045                               rgb_color, real_rgb, pm3d_color ));
3046                 }
3047 #endif
3048                 break;
3049             }
3050
3051             case GR_FILLED_POLYGON :
3052             {
3053                 int points, x,y, i;
3054                 LONG curr_color;
3055                 POINTL p;
3056
3057                 BufRead(hRead, &points, sizeof(points), &cbR);
3058                 GpiSetPattern(hps, PATSYM_SOLID);
3059                 GpiSetBackMix(hps, BM_OVERPAINT);
3060                 if (pm3d_color >= 0) {
3061                     curr_color = GpiQueryColor(hps);
3062                     GpiSetColor(hps, pm3d_color);
3063                 }
3064
3065                 /* using colours defined in the palette */
3066                 GpiBeginArea(hps, BA_BOUNDARY | BA_ALTERNATE);
3067                 for (i = 0; i < points; i++) {
3068                     BufRead(hRead, &x, sizeof(x), &cbR);
3069                     BufRead(hRead, &y, sizeof(y), &cbR);
3070                     p.x = x; p.y = y;
3071                     if (i)
3072                         GpiLine(hps, &p);
3073                     else
3074                         GpiMove(hps, &p);
3075                 }
3076                 GpiEndArea(hps);
3077                 if (pm3d_color >= 0)
3078                     GpiSetColor(hps, curr_color);
3079                 break;
3080             }
3081
3082             case GR_RGB_IMAGE : 
3083             {
3084                 unsigned int i, M, N, image_size;
3085                 POINTL corner[4];
3086                 PBYTE image;
3087                 PBITMAPINFO2 pbmi;
3088                 POINTL points[4];
3089                 LONG hits;
3090                 PERRINFO perriBlk;
3091                 image_list_entry *ile;
3092
3093                 BufRead(hRead, &M, sizeof(M), &cbR);
3094                 BufRead(hRead, &N, sizeof(N), &cbR);
3095                 for (i=0; i<4; i++) {
3096                     BufRead(hRead, &(corner[i].x), sizeof(int), &cbR);
3097                     BufRead(hRead, &(corner[i].y), sizeof(int), &cbR);
3098                 }
3099                 BufRead(hRead, &image_size, sizeof(image_size), &cbR);
3100                 DEBUG_IMAGE(("GR_IMAGE: M=%i, N=%i, size=%i", M, N, image_size));
3101                 DEBUG_IMAGE(("GR_IMAGE: corner [0]=(%i,%i) [1]=(%i,%i)", corner[0].x, corner[0].y, corner[1].x, corner[1].y));
3102                 image = (PBYTE) malloc(image_size);
3103                 /* FIXME: does not work if GNUBUF < image_size ! */
3104                 BufRead(hRead, image, image_size, &cbR);
3105
3106                 points[0].x = corner[0].x;
3107                 points[0].y = corner[1].y;
3108                 points[1].x = corner[1].x; 
3109                 points[1].y = corner[0].y;
3110                 points[2].x = points[2].y = 0;
3111                 points[3].x = M;
3112                 points[3].y = N;
3113
3114                 pbmi = (PBITMAPINFO2) calloc( sizeof(BITMAPINFOHEADER2), 1 );
3115                 pbmi->cbFix = sizeof(BITMAPINFOHEADER2);
3116                 pbmi->cx = M;
3117                 pbmi->cy = N;
3118                 pbmi->cPlanes = 1;
3119                 pbmi->cBitCount = 24;
3120                 pbmi->ulCompression = BCA_UNCOMP;
3121                 hits = GpiDrawBits(hps, image, pbmi, 4, &points, ROP_SRCCOPY, BBO_IGNORE );
3122
3123 #if 0
3124                 if (hits == GPI_ERROR) {
3125                     perriBlk = WinGetErrorInfo(hab);
3126                     if (perriBlk) {
3127                         PSZ pszOffset, pszErrMsg;
3128                         pszOffset = ((PSZ)perriBlk) + perriBlk->offaoffszMsg;
3129                         pszErrMsg = ((PSZ)perriBlk) + *((PULONG)pszOffset);
3130                         if (perriBlk->cDetailLevel >= 2)
3131                                 pszErrMsg = ((PSZ)perriBlk) + ((PULONG)pszOffset)[1];
3132                         DEBUG_IMAGE(("GpiDrawBits code=%x msg=%s", perriBlk->idError, pszErrMsg));
3133                         // DEBUG_IMAGE(("GpiDrawBits code=%x", perriErrorInfo->idError)); 
3134                         WinFreeErrorInfo(perriBlk);
3135                     }
3136                 }
3137 #endif
3138
3139                 /* We have to keep the image and the image header in memory since
3140                    we use retained graphics */
3141                 ile = (image_list_entry *) malloc(sizeof(image_list_entry));
3142                 ile->next = image_list;
3143                 ile->pbmi = pbmi;
3144                 ile->image = image;
3145                 image_list = ile;
3146
3147                 break;
3148             }
3149
3150             case SET_RULER : { /* set_ruler(int x, int y) term API: x<0 switches ruler off */
3151                 int x, y;
3152
3153                 BufRead(hRead, &x, sizeof(x), &cbR);
3154                 BufRead(hRead, &y, sizeof(y), &cbR);
3155                 DrawRuler(); /* remove previous drawing, if any */
3156                 if (x < 0) {
3157                     ruler.on = 0;
3158                     break;
3159                 }
3160                 ruler.on = 1;
3161                 ruler.x = x;
3162                 ruler.y = y;
3163                 DrawRuler();
3164                 break;
3165             }
3166
3167             case SET_CURSOR : { /* set_cursor(int c, int x, int y) term API */
3168                 int c, x, y;
3169
3170                 BufRead(hRead, &c, sizeof(x), &cbR);
3171                 BufRead(hRead, &x, sizeof(x), &cbR);
3172                 BufRead(hRead, &y, sizeof(y), &cbR);
3173                 switch (c) {
3174                 case -2: { /* move mouse to the given point */
3175                     RECTL rc;
3176                     POINTL pt;
3177
3178                     GpiQueryPageViewport(hpsScreen,&rc);
3179                     /* only distance is important */
3180                     rc.xRight -= rc.xLeft;
3181                     rc.yTop -= rc.yBottom;
3182                     /* window => pixels coordinates */
3183                     pt.x =(long int) ((x * (double) rc.xRight) / 19500.0);
3184                     pt.y =(long int) ((x * (double) rc.yTop) / 12500.0);
3185                     WinMapWindowPoints(hApp, HWND_DESKTOP, &pt, 1);
3186                     WinSetPointerPos(HWND_DESKTOP, pt.x, pt.y);
3187                     break;
3188                 }
3189                 case -1: /* start zooming; zooming cursor */
3190                     zoombox.on = 1;
3191                     zoombox.from.x = zoombox.to.x = x;
3192                     zoombox.from.y = zoombox.to.y = y;
3193                     break;
3194                 case 0:  /* standard cross-hair cursor */
3195                     WinSetPointer(HWND_DESKTOP,
3196                                   hptrCurrent =(useMouse
3197                                                 ?hptrCrossHair
3198                                                 :hptrDefault));
3199                     break;
3200                 case 1:  /* cursor during rotation */
3201                     WinSetPointer(HWND_DESKTOP, hptrCurrent = hptrRotating);
3202                     break;
3203                 case 2:  /* cursor during scaling */
3204                     WinSetPointer(HWND_DESKTOP, hptrCurrent = hptrScaling);
3205                     break;
3206                 case 3:  /* cursor during zooming */
3207                     WinSetPointer(HWND_DESKTOP, hptrCurrent = hptrZooming);
3208                     break;
3209                 }
3210                 if (c>=0 && zoombox.on) { /* erase zoom box */
3211                     DrawZoomBox();
3212                     zoombox.on = 0;
3213                 }
3214                 break;
3215             }
3216
3217             case SET_CLIPBOARD : {  /* set_clipboard(const char s[]) term API */
3218                 int len;
3219                 char *s;
3220
3221                 BufRead(hRead, &len, sizeof(int), &cbR);
3222                 s = malloc(len + 1);
3223                 BufRead(hRead,s, len+1, &cbR);
3224                 TextToClipboard(s);
3225                 free(s);
3226                 break;
3227             }
3228
3229             case SET_MENU :   /* update menu according to the gnuplot core
3230                           * settings, e.g.(un)checking menu items */
3231                 if (mouseTerminal) {
3232                     /* we are connected to mouseable terminal */
3233                     BufRead(hRead, &gpPMmenu, sizeof(gpPMmenu), &cbR);
3234                     if (useMouse != gpPMmenu.use_mouse)
3235                         WinSetPointer(HWND_DESKTOP,
3236                                       hptrCurrent = (gpPMmenu.use_mouse
3237                                                      ?hptrCrossHair
3238                                                      :hptrDefault));
3239                     useMouse = gpPMmenu.use_mouse;
3240                     gpPMmenu_update_req = 1;
3241                 }
3242                 break;
3243
3244             case GR_MOUSECAPABLE :
3245                 /* notification of being connected to a mouse-enabled terminal */
3246                 mouseTerminal = 1;
3247                 break;
3248
3249             default :  /* should handle error */
3250                 break;
3251             }
3252         }
3253     }
3254     DosDisConnectNPipe(hRead);
3255     WinPostMsg(hApp, WM_CLOSE, 0L, 0L);
3256 }
3257
3258
3259 static void
3260 EditLineTypes(HWND hwnd, HPS hps, BOOL bDashed)
3261 {
3262     int i;
3263
3264     GpiSetDrawingMode(hps, DM_RETAIN);
3265     GpiOpenSegment(hps, iSeg);
3266     GpiSetEditMode(hps, SEGEM_REPLACE);
3267     for (i=0; i<7; i++) {
3268         while (GpiSetElementPointerAtLabel(hps, lLineTypes[i])) {
3269             GpiOffsetElementPointer(hps, 1);
3270             GpiSetLineType(hps, bDashed?lLineTypes[i]:lLineTypes[0]);
3271         }
3272         GpiSetElementPointer(hps, 0);
3273     }
3274     GpiSetEditMode(hps, SEGEM_INSERT);
3275     GpiCloseSegment(hps);
3276 }
3277
3278
3279 #if 0
3280 /*
3281 ** Edit segment to change char cell(font size)
3282 */
3283 static void
3284 EditCharCell(HPS hps, SIZEF *psize)
3285 {
3286     int i;
3287     LONG rl, rc;
3288     SIZEF sizH, sizV;
3289     int iVert = 0;
3290
3291     sizH = *psize;
3292     sizV.cx = sizH.cy;
3293     sizV.cy = sizH.cx;
3294     GpiSetDrawingMode(hps, DM_RETAIN);
3295     GpiOpenSegment(hps, iSeg);
3296     GpiSetEditMode(hps, SEGEM_REPLACE);
3297     i=0;
3298     while (GpiSetElementPointer(hps, i)) {
3299         rc = GpiQueryElementPointer(hps);
3300         if (rc != i)
3301             break;
3302         rl = GpiQueryElementType(hps, &rc, 0, NULL);
3303         if (rc == 0x34 || rc == 0x74) {
3304             LONG gdata;
3305
3306             GpiQueryElement(hps, 5, 4, (PBYTE) &gdata);
3307             if (gdata == 0)
3308                 iVert = 0;
3309             else
3310                 iVert = 1;
3311         }
3312         else if (rc==0x33 || rc==0x03)
3313             GpiSetCharBox(hps, iVert ? &sizV : &sizH);
3314         ++i;
3315     }
3316     GpiSetEditMode(hps, SEGEM_INSERT);
3317     GpiCloseSegment(hps);
3318 }
3319 #endif
3320
3321 /*
3322 ** pull next plot command out of buffer read from GNUPLOT
3323 */
3324 static int
3325 BufRead(HFILE hfile, void *buf, int nBytes, ULONG *pcbR)
3326 {
3327     ULONG ulR, ulRR;
3328     int rc;
3329     static char buffer[GNUBUF];
3330     static char *pbuffer = buffer+GNUBUF, *ebuffer = buffer+GNUBUF;
3331
3332     for (; nBytes > 0; nBytes--) {
3333         if (pbuffer >= ebuffer) {
3334             ulR = GNUBUF;
3335             rc = DosRead(hfile, buffer, ulR, &ulRR);
3336             if (rc != 0)
3337                 return rc;
3338             if (ulRR == 0)
3339                 return 1;
3340             pbuffer = buffer;
3341             ebuffer = pbuffer+ulRR;
3342         }
3343         *(char*)buf++ = *pbuffer++;
3344     }
3345     return 0L;
3346 }
3347
3348
3349 #ifdef STANDARD_FONT_DIALOG
3350
3351 /*
3352 ** Get a new font using standard font dialog
3353 */
3354 int
3355 GetNewFont(HWND hwnd, HPS hps)
3356 {
3357     static FONTDLG pfdFontdlg;      /* Font dialog info structure */
3358     static int i1 =1;
3359     static int iSize;
3360     char szPtList[64];
3361     HWND hwndFontDlg;     /* Font dialog window handle */
3362     char szFamilyname[FACESIZE];
3363
3364     if (i1) {
3365         strcpy(pfdFontdlg.fAttrs.szFacename, strchr(szFontNameSize, '.') + 1);
3366         strcpy(szFamilyname, strchr(szFontNameSize, '.') + 1);
3367         sscanf(szFontNameSize, "%d", &iSize);
3368         memset(&pfdFontdlg, 0, sizeof(FONTDLG));
3369
3370         pfdFontdlg.cbSize = sizeof(FONTDLG);
3371         pfdFontdlg.hpsScreen = hps;
3372         /*   szFamilyname[0] = 0; */
3373         pfdFontdlg.pszFamilyname = szFamilyname;
3374         pfdFontdlg.usFamilyBufLen = FACESIZE;
3375         pfdFontdlg.fl = FNTS_HELPBUTTON |
3376             FNTS_CENTER | FNTS_VECTORONLY |
3377             FNTS_OWNERDRAWPREVIEW;
3378         pfdFontdlg.clrFore = CLR_BLACK;
3379         pfdFontdlg.clrBack = CLR_WHITE;
3380         pfdFontdlg.usWeight = FWEIGHT_NORMAL;
3381         pfdFontdlg.fAttrs.usCodePage = codepage;
3382         pfdFontdlg.fAttrs.usRecordLength = sizeof(FATTRS);
3383     }
3384     sprintf(szPtList, "%d 8 10 12 14 18 24", iSize);
3385     pfdFontdlg.pszPtSizeList = szPtList;
3386     pfdFontdlg.fxPointSize = MAKEFIXED(iSize,0);
3387     hwndFontDlg = WinFontDlg(HWND_DESKTOP, hwnd, &pfdFontdlg);
3388     if (i1) {
3389         pfdFontdlg.fl = FNTS_HELPBUTTON |
3390             FNTS_CENTER | FNTS_VECTORONLY |
3391             FNTS_INITFROMFATTRS;
3392         i1=0;
3393     }
3394     if (hwndFontDlg &&(pfdFontdlg.lReturn == DID_OK)) {
3395         iSize = FIXEDINT(pfdFontdlg.fxPointSize);
3396         sprintf(szFontNameSize, "%d.%s", iSize, pfdFontdlg.fAttrs.szFacename);
3397         return 1;
3398     } else
3399         return 0;
3400 }
3401
3402 #else
3403
3404 /*
3405 ** Get a new font using standard font palette
3406 */
3407 int
3408 GetNewFont(HWND hwnd, HPS hps)
3409 {
3410  HOBJECT hObject;
3411  ULONG ulView = 0; /* OPEN_DEFAULT */
3412  BOOL fSuccess = FALSE;
3413
3414  hObject = WinQueryObject("<WP_FNTPAL>");
3415  if (hObject != NULL)
3416   { fSuccess = WinOpenObject(hObject, ulView, TRUE); }
3417   if (fSuccess) return 1;
3418   else return 0;
3419 }
3420
3421 #endif /* STANDARD_FONT_DIALOG */
3422
3423
3424 /*
3425 **  Handle termination signal to free up resources before
3426 **  termination.
3427 */
3428 void SigHandler(int sig)
3429 {
3430     if (sig == SIGTERM) {
3431         if (bPersist) {
3432             DosKillThread(tidSpawn);
3433             return;
3434         }
3435         DosEnterCritSec();
3436         DosKillThread(tidSpawn);
3437         DosKillThread(tidDraw);
3438         DosExitCritSec();
3439         exit(0);
3440     }
3441 }
3442
3443
3444 #ifdef PM_KEEP_OLD_ENHANCED_TEXT
3445
3446 /* disable debugging info */
3447 #define TEXT_DEBUG(x) /* fprintf x */ ;
3448
3449 /* process a bit of string, and return the last character used.
3450  * p is start of string
3451  * brace is TRUE to keep processing to }, FALSE for do one character
3452  * fontname & fontsize are obvious
3453  * base is the current baseline
3454  * widthflag is TRUE if the width of this should count,
3455  *              FALSE for zero width boxes
3456  * showflag is TRUE if this should be shown,
3457  *             FALSE if it should not be shown(like TeX \phantom)
3458  */
3459
3460 static char *starttext = NULL;
3461 static int  textlen = 0;
3462 static BOOL bText = FALSE;
3463 static int  textwidth = 0;
3464 static POINTL ptlText;
3465 static FILE *ff;
3466
3467 static char
3468 *ParseText(
3469     HPS hps,
3470     char *p,
3471     BOOL brace,
3472     char *fontname,
3473     int fontsize, int base,
3474     BOOL widthflag, BOOL showflag)
3475 {
3476     POINTL aptl[TXTBOX_COUNT];
3477     BOOL bChangeFont = FALSE;
3478     TEXT_DEBUG((ff, "RECURSE WITH [%p] %s, %d %s %.1f %.1f %d %d\n",
3479                 p, p, brace, fontname, fontsize, base,
3480                 widthflag, showflag));
3481
3482     /* Start each recursion with a clean string */
3483 #if 0
3484     {
3485         FILE *ff = fopen("deb","a");
3486         int i=textlen;
3487
3488         for (i=0;i<textlen;i++)
3489             fputc(starttext[i], ff);
3490         fputc('\n',ff);
3491         fclose(ff);
3492     }
3493 #endif /* 0 */
3494
3495     if (textlen > 0) {
3496         GpiQueryTextBox(hps, textlen, starttext, TXTBOX_COUNT, aptl);
3497         textwidth += aptl[TXTBOX_BOTTOMRIGHT].x * multLineHor;
3498         textwidth += aptl[TXTBOX_BOTTOMRIGHT].y * multLineVert;
3499     }
3500
3501     if (bText) {
3502         if (textlen > 0) {
3503             GpiCharStringAt(hps, &ptlText, textlen, starttext);
3504             ptlText.x += aptl[TXTBOX_CONCAT].x - multLineVert * base;
3505             ptlText.y += aptl[TXTBOX_CONCAT].y + multLineHor * base;
3506         } else {
3507             ptlText.x -= multLineVert * base;
3508             ptlText.y += multLineHor * base;
3509         }
3510     }
3511     textlen = 0;
3512     starttext = p;
3513
3514     if (fontname != NULL) {
3515         char szFont[FONTBUF];
3516
3517         sprintf(szFont, "%d.%s", fontsize, fontname);
3518         SwapFont(hps, szFont);
3519         bChangeFont = TRUE;
3520     }
3521     if (base != 0)
3522         GpiSetCharBox(hps, &sizCurSubSup);
3523
3524     for (; *p; ++p) {
3525         int shift;
3526
3527         switch (*p) {
3528         case '}':
3529             /*{{{  deal with it*/
3530             if (brace) {
3531                 brace = 0;
3532             }
3533             break;
3534             /*}}}*/
3535
3536         case '_':
3537         case '^':
3538             /*{{{  deal with super/sub script*/
3539             shift = ((*p == '^') ? lSupOffset : lSubOffset);
3540             p = ParseText(hps, p+1, FALSE,
3541                           NULL/*fontname*/, fontsize*0.8,
3542                           base+shift, widthflag, showflag);
3543             break;
3544             /*}}}*/
3545
3546         case '{':
3547         {
3548             char *savepos=NULL, save=0;
3549             char *localfontname=fontname, ch;
3550             char localfontbuf[FONTBUF];
3551             int recode=1;
3552             int f=fontsize;
3553             char *q=localfontbuf;
3554
3555             /*{{{  recurse(possibly with a new font) */
3556
3557             TEXT_DEBUG((ff,"Dealing with {\n"));
3558             if (*++p == '/') {
3559                 /* then parse a fontname, optional fontsize */
3560                 while (*++p == ' ')
3561                     ;           /* do nothing */
3562                 if (*p=='-') {
3563                     recode=0;
3564                     while (*++p == ' ')
3565                         ;       /* do nothing */
3566                 }
3567                 localfontname = p;
3568                 while ((ch = *p) > ' ' && ch != '=') {
3569                     localfontname=localfontbuf;
3570                     if (*p=='_')
3571                         *q=' ';
3572                     else
3573                         *q=*p;
3574                     ++p;++q;
3575                 }
3576                 *q = '\0';
3577                 FontExpand(localfontbuf);
3578                 save = *(savepos=p);
3579                 if (ch == '=') {
3580                     *p++ = '\0';
3581                     /*{{{  get optional font size*/
3582                     TEXT_DEBUG((ff,"Calling strtod(%s) ...", p));
3583                     f = strtod(p, &p);
3584                     TEXT_DEBUG((ff,"Retured %.1f and %s\n", f, p));
3585
3586                     if (!f)
3587                         f = fontsize;
3588
3589                     TEXT_DEBUG((ff,"Font size %.1f\n", f));
3590                     /*}}}*/
3591                 } else {
3592                     *p++ = '\0';
3593                     f = fontsize;
3594                 }
3595
3596                 while (*p == ' ')
3597                     ++p;
3598
3599                 if (!(*localfontname)) {
3600                     localfontname = fontname;
3601                     if (f != fontsize)
3602                         localfontname = strchr(szFontNameSize, '.') + 1;
3603                 }
3604             } /* if ('/') */
3605             /*}}}*/
3606
3607             TEXT_DEBUG((ff,"Before recursing, we are at [%p] %s\n", p, p));
3608
3609             p = ParseText(hps,p, TRUE, localfontname, f, base, widthflag, showflag);
3610
3611             TEXT_DEBUG((ff,"BACK WITH %s\n", p));
3612             if (savepos)
3613                 /* restore overwritten character */
3614                 *savepos = save;
3615
3616             break;
3617         }
3618
3619         case '@' :
3620             /*{{{  phantom box - prints next 'char', then restores currentpoint */
3621
3622             p = ParseText(hps, ++p, FALSE, NULL/*fontname*/, fontsize,
3623                           base, FALSE, showflag);
3624
3625             break;
3626             /*}}}*/
3627
3628         case '&' :
3629             /*{{{  character skip - skips space equal to length of character(s) */
3630
3631             p = ParseText(hps, ++p, FALSE, NULL/*fontname*/, fontsize,
3632                           base, widthflag, FALSE);
3633
3634             break;
3635             /*}}}*/
3636
3637         case '\\':
3638         {
3639             char buffer[4]; /* should need only one char.. */
3640             char *q = buffer;
3641
3642             *q = '\0';
3643             ParseText(hps,q, FALSE, NULL, fontsize, base, widthflag, showflag);
3644
3645             /*{{{  is it an escape */
3646             /* special cases */
3647             if (p[1]=='\\' || p[1]=='{' || p[1]=='}') {
3648                 *q++=p[1];
3649                 ++p;
3650             }
3651 #if 0
3652             else if (p[1] >= '0' && p[1] <= '7') {
3653                 /* up to 3 octal digits */
3654                 int c = 0;
3655
3656                 c+=p[1];
3657                 ++p;
3658                 if (p[1] >= '0' && p[1] <= '7') {
3659                     c = c * 8 + p[1];
3660                     ++p;
3661                     if (p[1] >= '0' && p[1] <= '7') {
3662                         c = c * 8 + p[1];
3663                         ++p;
3664                     }
3665                 }
3666                 *q++ = c;
3667                 break;
3668             }
3669 #endif /* 0 */
3670
3671             *q = '\0';
3672             textlen = 1;
3673             starttext=buffer;
3674             ParseText(hps,q, FALSE, NULL/*fontname*/, fontsize,
3675                       base, widthflag, showflag);
3676             starttext=p+1;
3677             textlen = 0;
3678             /*}}}*/
3679             break;
3680         }
3681
3682         default:
3683             ++textlen;
3684
3685             /*}}}*/
3686         } /* switch(character) */
3687
3688         /* like TeX, we only do one character in a recursion, unless it's
3689          * in braces
3690          */
3691         if (!brace)
3692             break;
3693     }
3694
3695     if (textlen > 0) {
3696         GpiQueryTextBox(hps, textlen, starttext, TXTBOX_COUNT, aptl);
3697         if (widthflag) {
3698             textwidth += aptl[TXTBOX_BOTTOMRIGHT].x * multLineHor;
3699             textwidth += aptl[TXTBOX_BOTTOMRIGHT].y * multLineVert;
3700         }
3701     }
3702     if (bText) {
3703         if (textlen > 0) {
3704             if (showflag)
3705                 GpiCharStringAt(hps, &ptlText, textlen, starttext);
3706             if (widthflag) {
3707                 ptlText.x += aptl[TXTBOX_CONCAT].x;
3708                 ptlText.y += aptl[TXTBOX_CONCAT].y;
3709             }
3710         }
3711         if (base != 0) {
3712             ptlText.x += multLineVert * base;
3713             ptlText.y -= multLineHor * base;
3714         }
3715     }
3716     if (bChangeFont) {
3717         SwapFont(hps, NULL);
3718         bChangeFont = FALSE;
3719     }
3720     if (base != 0)
3721         GpiSetCharBox(hps, &sizBaseFont);
3722
3723     textlen = 0;
3724     starttext = p+1;
3725     return p;
3726 }
3727
3728
3729 static void
3730 CharStringAt(HPS hps, int x, int y, int len, char *str)
3731 {
3732     /* flush any pending graphics(all the XShow routines do this...) */
3733     char *fontname;
3734     int fontsize;
3735
3736     if (!strlen(str))
3737         return;
3738
3739     /* set up the globals */
3740
3741     ptlText.x = x;
3742     ptlText.y = y;
3743     bText = TRUE;
3744     starttext = NULL;
3745     textlen = 0;
3746     textwidth = 0;
3747     sscanf(szFontNameSize, "%d", &fontsize);
3748     fontname = strchr(szFontNameSize, '.') + 1;
3749
3750     while (*(str = ParseText(hps, str, TRUE, NULL,
3751                              fontsize,
3752                              0.0, TRUE, TRUE)))
3753         ; /* do nothing */
3754 }
3755
3756
3757 static int
3758 QueryTextBox(HPS hps, int len, char *str)
3759 {
3760     char *fontname;
3761     int fontsize;
3762
3763     if (!strlen(str))
3764         return 0;
3765
3766     /* set up the globals */
3767     bText = FALSE;
3768     starttext = NULL;
3769     textlen = 0;
3770     textwidth = 0;
3771     sscanf(szFontNameSize, "%d", &fontsize);
3772     fontname = strchr(szFontNameSize, '.') + 1;
3773
3774     while (*(str = ParseText(hps, str, TRUE, NULL,
3775                              fontsize,
3776                              0.0, TRUE, TRUE)))
3777         ; /* do nothing */
3778
3779     return textwidth;
3780 }
3781
3782 #endif
3783
3784
3785 void
3786 FontExpand(char *name)
3787 {
3788     if (strcmp(name,"S") == 0)
3789         strcpy(name, "Symbol Set");
3790     if (strcmp(name,"Symbol") == 0)
3791         strcpy(name, "Symbol Set");
3792     else if (strcmp(name,"H") == 0)
3793         strcpy(name, "Helvetica");
3794     else if (strcmp(name,"T") == 0)
3795         strcpy(name, "Times New Roman");
3796     else if (strcmp(name,"C") == 0)
3797         strcpy(name, "Courier");
3798 }
3799
3800
3801 /*=======================================*/
3802
3803 static POINTL pCur;
3804 static int iLinebegin = 1;
3805 static int iLtype = 0;
3806 static int iState = 0;
3807 static double togo = 0.0;
3808 static int iPatt[8][9] = {
3809     {   0,   0,   0,   0,   0,   0,   0,   0,  0 },
3810     { 300, 200,  -1,   0,   0,   0,   0,   0,  0 },
3811     { 150, 150,  -1,   0,   0,   0,   0,   0,  0 },
3812     { 300, 200, 150, 200,  -1,   0,   0,   0,  0 },
3813     { 500, 200,  -1,   0,   0,   0,   0,   0,  0 },
3814     { 300, 200, 150, 200, 150, 200,  -1,   0,  0 },
3815     { 300, 200, 150, 200, 150, 200, 150, 200, -1 },
3816     { 500, 200, 150, 200,  -1,   0,   0,   0,  0 }
3817 };
3818
3819
3820 void
3821 LMove(HPS hps, POINTL *p)
3822 {
3823     double ds, dx, dy;
3824
3825     if (iLinebegin) {
3826         pCur = *p;
3827         GpiMove(hps, p);
3828     } else if (iLtype == 0)
3829         GpiMove(hps, p);
3830     else {
3831         dx = p->x - pCur.x;
3832         dy = p->y - pCur.y;
3833         ds = sqrt(dx*dx + dy*dy);
3834         dx /= ds; dy /= ds;
3835         while (ds > 0.0) {
3836             if (ds < togo) {
3837                 togo -= ds;
3838                 ds = 0.0;
3839                 GpiMove(hps, p);
3840                 pCur = *p;
3841             } else {
3842                 POINTL pn;
3843
3844                 pn.x = pCur.x + togo * dx;
3845                 pn.y = pCur.y + togo * dy;
3846                 GpiMove(hps, &pn);
3847                 pCur = pn;
3848                 ds -= togo;
3849                 iState++;
3850                 if (iPatt[iLtype][iState] < 0) {
3851                     togo = iPatt[iLtype][0];
3852                     iState = 0;
3853                 } else
3854                     togo = iPatt[iLtype][iState];
3855             }
3856         }
3857     }
3858 }
3859
3860
3861 void
3862 LLine(HPS hps, POINTL *p)
3863 {
3864     double ds, dx, dy;
3865
3866     if (iLinebegin)
3867         iLinebegin = 0;
3868
3869     if (iLtype == 0)
3870         GpiLine(hps, p);
3871     else {
3872         dx = p->x - pCur.x;
3873         dy = p->y - pCur.y;
3874         ds = sqrt(dx*dx + dy*dy);
3875         dx /= ds; dy /= ds;
3876         while (ds > 0.0) {
3877             if (ds < togo) {
3878                 togo -= ds;
3879                 ds = 0.0;
3880                 if (iState & 1)
3881                     GpiMove(hps, p);
3882                 else
3883                     GpiLine(hps, p);
3884                 pCur = *p;
3885             } else {
3886                 POINTL pn;
3887
3888                 pn.x = pCur.x + togo * dx;
3889                 pn.y = pCur.y + togo * dy;
3890                 if (iState & 1)
3891                     GpiMove(hps, &pn);
3892                 else
3893                     GpiLine(hps, &pn);
3894                 pCur = pn;
3895                 ds -= togo;
3896                 iState++;
3897                 if (iPatt[iLtype][iState] < 0) {
3898                     togo = iPatt[iLtype][0];
3899                     iState = 0;
3900                 } else
3901                     togo = iPatt[iLtype][iState];
3902             }
3903         }
3904     }
3905 }
3906
3907 void
3908 LType(int iType)
3909 {
3910     iLinebegin = 1;
3911     if (iType > 7)
3912         iType = 0;
3913     iLtype = iType;
3914     iState = 0;
3915     togo = iPatt[iLtype][0];
3916 }
3917
3918
3919 /* Now routines for mouse etc. */
3920
3921 static void
3922 TextToClipboard(PCSZ szTextIn)
3923 {
3924     /* copy string given by szTextIn to the clipboard */
3925     PSZ szTextOut = NULL;
3926     ULONG ulRC = DosAllocSharedMem(
3927         (PVOID*) &szTextOut, NULL,
3928         strlen(szTextIn) + 1,
3929         PAG_READ | PAG_WRITE | PAG_COMMIT | OBJ_GIVEABLE);
3930
3931     if (!ulRC) {
3932         HAB hab = 0;
3933
3934         strcpy(szTextOut, szTextIn);
3935         WinOpenClipbrd(hab);
3936         WinEmptyClipbrd(hab);
3937         WinSetClipbrdData(hab,(ULONG) szTextOut, CF_TEXT, CFI_POINTER);
3938         WinCloseClipbrd(hab);
3939     }
3940 }
3941
3942
3943 /* Draw the ruler
3944 */
3945 static void
3946 DrawRuler()
3947 {
3948     POINTL p;
3949
3950     if (!ruler.on || ruler.x < 0)
3951         return;
3952     /* GpiSetColor(hpsScreen, RGB_TRANS(COLOR_RULER)); */
3953     GpiSetColor(hpsScreen, RGB_TRANS(CLR_RED));
3954     GpiSetLineWidth(hpsScreen, LINEWIDTH_THICK);
3955     GpiSetMix(hpsScreen, FM_INVERT);
3956     /*GpiBeginPath(hpsScreen, 1); // will this help? I don't know, but makes thic cross */
3957
3958     p.x = 0;
3959     p.y = ruler.y;
3960     GpiMove(hpsScreen, &p);
3961
3962     p.x = 19500;
3963     GpiLine(hpsScreen, &p);
3964
3965     p.x = ruler.x;
3966     p.y = 0;
3967     GpiMove(hpsScreen, &p);
3968
3969     p.y = 12500;
3970     GpiLine(hpsScreen, &p);
3971
3972     /*GpiEndPath(hpsScreen); */
3973     /*GpiStrokePath(hpsScreen, 1, 0); */
3974 }
3975
3976
3977 #if 0
3978 /* This routine recalculates mouse/pointer position [mx,my] in [in pixels]
3979 current window to the real/true [x,y] coordinates of the plotted graph.
3980 */
3981 void
3982 MousePosToGraphPos(
3983     double *x, double *y,
3984     HWND hWnd,
3985     SHORT mx, SHORT my,
3986     ULONG mouse_mode)
3987 {
3988     RECTL rc;
3989
3990     if (mouse_mode == MOUSE_COORDINATES_PIXELS) {
3991         *x = mx;
3992         *y = my;
3993         return;
3994     }
3995
3996     /* Rectangle where we are moving: viewport, not the full window! */
3997     GpiQueryPageViewport(hpsScreen, &rc);
3998
3999     /* only distance is important */
4000     rc.xRight -= rc.xLeft;
4001     rc.yTop -= rc.yBottom;
4002
4003     if (mouse_mode == MOUSE_COORDINATES_SCREEN) {
4004         *x =(double) mx / rc.xRight;
4005         *y =(double) my / rc.yTop;
4006         return;
4007     }
4008
4009     /* px=px(mx); mouse=>gnuplot driver coordinates */
4010     *x = mx * 19500.0 / rc.xRight;
4011     *y = my * 12500.0 / rc.yTop;
4012
4013     /* main job of transformation, which is not device dependent */
4014     MousePosToGraphPosReal(x, y);
4015 }
4016 #endif
4017
4018
4019 /*
4020  * This routine recalculates mouse/pointer position [mx,my] in [in pixels]
4021  * current window to the viewport coordinates
4022  */
4023 static void
4024 MousePosToViewport(int *x, int *y, SHORT mx, SHORT my)
4025 {
4026     RECTL rc;
4027
4028     /* Rectangle where we are moving: viewport, not the full window! */
4029     GpiQueryPageViewport(hpsScreen, &rc);
4030
4031     rc.xRight -= rc.xLeft;
4032     rc.yTop -= rc.yBottom; /* only distance is important */
4033
4034     /* px=px(mx); mouse=>gnuplot driver coordinates */
4035     *x =(int)(mx * 19500.0 / rc.xRight + 0.5);
4036     *y =(int)(my * 12500.0 / rc.yTop + 0.5);
4037 }
4038
4039
4040 /*
4041  * This routine gets the mouse/pointer position in the current window and
4042  * recalculates it to the viewport coordinates
4043  */
4044 static void
4045 GetMousePosViewport(HWND hWnd, int *mx, int *my)
4046 {
4047     POINTL p;
4048
4049     WinQueryPointerPos(HWND_DESKTOP, &p); /* this is position wrt desktop */
4050     WinMapWindowPoints(HWND_DESKTOP, hWnd, &p, 1); /* pos. wrt our window in pixels */
4051     MousePosToViewport(mx,my,p.x,p.y);
4052 }
4053
4054
4055 /*
4056  * Status line previous and current text:
4057  */
4058 static char *sl_curr_text = NULL;
4059
4060 /*
4061  * Display the status line by the text
4062  */
4063 static void
4064 DisplayStatusLine(HPS hps)
4065 {
4066     POINTL pt;
4067
4068     if (!sl_curr_text)
4069         return;
4070     GpiSetColor(hps, RGB_TRANS(COLOR_MOUSE)); /* set text color */
4071     GpiSetCharMode(hps, CM_MODE1);
4072     pt.x = 2;
4073     pt.y = 2;
4074     GpiSetMix(hps, FM_INVERT);
4075     /* GpiSetMix(hps, FM_XOR); */
4076     GpiCharStringAt(hps, &pt,(long) strlen(sl_curr_text), sl_curr_text);
4077 }
4078
4079
4080 /*
4081  * Update the status line by the text; firstly erase the previous text
4082  */
4083 static void
4084 UpdateStatusLine(HPS hps, char *text)
4085 {
4086     if (gpPMmenu_update_req)
4087         gpPMmenu_update(); /* check for updated menu */
4088     if (sl_curr_text) {
4089         /* erase the previous text */
4090         DisplayStatusLine(hps);
4091         free(sl_curr_text);
4092     }
4093     if (!text || !*text)
4094         sl_curr_text = 0;
4095     else {
4096         /* display new text */
4097         sl_curr_text = strdup(text);
4098         DisplayStatusLine(hps);
4099     }
4100 }
4101
4102
4103 /*
4104  * Graphics part SET_GRAPHICS or anything else required to update menu according to
4105  * the items in gpPMmenu
4106  */
4107 static void
4108 gpPMmenu_update()
4109 {
4110 #if 0
4111     if (!gpPMmenu_update_req)
4112         return;
4113 #endif
4114
4115     ChangeCheck(hApp, IDM_USEMOUSE, useMouse ? IDM_USEMOUSE:0);
4116     WinEnableMenuItem(/* can this situation be unzoomed back? */
4117         WinWindowFromID(WinQueryWindow(hApp, QW_PARENT), FID_MENU),
4118         IDM_MOUSE_UNZOOM,(gpPMmenu.where_zoom_queue & 1) ? TRUE : FALSE);
4119     WinEnableMenuItem(/* can this situation be unzoomed to the beginning? */
4120         WinWindowFromID(WinQueryWindow(hApp, QW_PARENT), FID_MENU),
4121         IDM_MOUSE_UNZOOMALL,(gpPMmenu.where_zoom_queue & 2) ? TRUE : FALSE);
4122     if (
4123         WinEnableMenuItem(/* can this situation be zoomed next? */
4124             WinWindowFromID(WinQueryWindow(hApp, QW_PARENT), FID_MENU),
4125             IDM_MOUSE_ZOOMNEXT,(gpPMmenu.where_zoom_queue & 4) ? TRUE : FALSE)
4126         == TRUE) gpPMmenu_update_req = 0;
4127     ChangeCheck(hApp, IDM_MOUSE_POLAR_DISTANCE, gpPMmenu.polar_distance?IDM_MOUSE_POLAR_DISTANCE:0);
4128 }
4129
4130
4131 static void
4132 DrawZoomBox()
4133 {
4134     if (!zoombox.on)
4135         return;
4136     GpiSetLineWidth(hpsScreen, LINEWIDTH_NORMAL);
4137     GpiSetLineType(hpsScreen,LINETYPE_SHORTDASH);
4138     GpiSetMix(hpsScreen,FM_INVERT);
4139     GpiMove(hpsScreen, &zoombox.from);
4140     GpiBox(hpsScreen, DRO_OUTLINE, &zoombox.to, 0,0);
4141     GpiSetLineType(hpsScreen,LINETYPE_DEFAULT);
4142 }
4143
4144 /* eof gclient.c */
4145