2 static char RCSid[]="$Id: gclient.c,v 1.47.2.1 2008/02/23 11:23:12 mikulik Exp $";
5 /****************************************************************************
11 This file contains the client window procedures for Gnupmdrv
13 ****************************************************************************/
15 /* PM driver for GNUPLOT */
18 * Copyright 1992, 1993, 1998, 2004 Roger Fearick
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.
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,
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
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.
43 * This software is provided "as is" without express or implied warranty
44 * to the extent permitted by applicable law.
50 * Gnuplot driver for OS/2: Roger Fearick
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)
70 * - communication gnupmdrv -> gnuplot via shared memory (April 1999)
71 * - date and time on x axis (August 1999)
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
87 #define INCL_DOSQUEUES
88 #define INCL_WINSWITCHLIST
89 #define INCL_GPIPRIMITIVES
103 #include "term_api.h"
104 #include "gnupmdrv.h"
107 #include "mousecmn.h"
110 /*==== m i s c e l l a n e o u s =============================================*/
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.
116 /* #define STANDARD_FONT_DIALOG 1 */
117 #undef STANDARD_FONT_DIALOG
119 /*==== d e b u g g i n g =====================================================*/
122 # include "pmprintf.h"
123 # define DEBUG_IMAGE(a) PmPrintf a
125 # define DEBUG_IMAGE(a)
129 # include "pmprintf.h"
130 # define DEBUG_COLOR(a) PmPrintf a
132 # define DEBUG_COLOR(a)
136 /*==== l o c a l d a t a ==================================================*/
138 static long lLineTypes[7] = {
145 LINETYPE_DASHDOUBLEDOT
148 static long lCols[16] = {
167 static long lCols_init = 0;
168 static long lCols_num = 16;
169 static long bkColor = -1;
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. */
175 static LONG alColourTable[nColors + 2];
177 static BOOL bPMPaletteMode = TRUE; /* do we use PM palette manager? */
179 /* RGB equivalents of all normal CLR_xxx colour constants
180 Note: First entry corresponds to CLR_WHITE, which is negative (-2)!
182 static LONG rgb_colors[18];
183 /* macro to facilitate translation */
184 #define RGB_TRANS(v) rgb_colors[(v)-CLR_WHITE]
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 */
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) */
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 */
205 // ULONG ppidGnu = 0L; /* gnuplot pid */ -- now in gpexecute.c
206 static HDC hdcScreen;
207 static HPS hpsScreen; /* screen pres. space */
210 static HSWITCH hSwitch = 0; /* switching between windows */
211 static SWCNTRL swGnu;
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
219 static BOOL bNewFont = FALSE;
222 static double multLineHor = 1.; /* Horizontal and vertical spacing shifts */
223 static double multLineVert = 0.; /* for multiline prints. */
225 static int codepage = 0;
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"
236 int on; // set to 1 during zooming
237 POINTL from, to; // corners
241 static int zooming = 0; // set to 1 during zooming
242 static POINTL zoomrect_from, zoomrect_now;
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
255 //static HEV semStartSeq; /* semaphore to start things in right sequence */
257 static HMTX semHpsAccess;
258 static ULONG ulPauseReply = 1;
259 static ULONG ulPauseMode = PAUSE_DLG;
261 static HWND hSysMenu;
262 /* stuff for screen-draw thread control */
264 //static HEV semDrawDone;
268 static TID tidDraw, tidSpawn;
270 static int breakDrawing = 0;
271 /* //PM flag for stopping (long) drawings */
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;
283 //PM: Now variables for mouse
285 /* useMouse is set to 1 when user switches mousing on, e.g. the mouse is
288 static int useMouse = 0;
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.
296 static char mouseTerminal = 0;
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.
303 static char lock_mouse = 1;
305 /* Structure for the ruler: on/off, position,...
309 int x, y; /* ruler position */
312 // Pointer definition
313 HWND hptrDefault, hptrCrossHair, hptrScaling,
314 hptrRotating, hptrZooming, hptrCurrent;
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
319 struct t_gpPMmenu gpPMmenu;
320 int gpPMmenu_update_req = 0;
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
328 static enum JUSTIFY jmode;
330 static SIZEF sizBaseSubSup;
331 static SIZEF sizCurSubSup;
332 static SIZEF sizCurFont;
333 static long lVOffset = 0;
334 static SIZEF sizBaseFont;
345 /*==== f u n c t i o n s =====================================================*/
348 HBITMAP CopyToBitmap(HPS);
349 HMF CopyToMetaFile(HPS);
350 MRESULT WmClientCmdProc(HWND , ULONG, MPARAM, MPARAM);
351 void ChangeCheck(HWND, USHORT, USHORT);
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);
362 static void EditCharCell(HPS, SIZEF*);
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 *);
374 static void LMove(HPS hps, POINTL *p);
375 static void LLine(HPS hps, POINTL *p);
376 static void LType(int iType);
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);
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 */
392 /* Drag'n'Drop support from PMEmacs */
394 unsigned long cookie;
396 char str[CCHMAXPATH];
399 /* Circular buffer of objects recently dropped. */
402 static int drop_count = 0;
404 /* Each drop action is assigned a number, for relating drop events
405 with PMR_DROP requests. */
407 /* Finally, include the common mousing declarations and routines: */
409 /* let mousing.c know whether called from gclient.c or gplt_x11.c */
410 #include "../gpexecute.h"
412 /* End of new functions related to the mouse processing */
414 /*==== c o d e ===============================================================*/
416 /* An object is being dragged over the client window. Check whether
417 it can be dropped or not. */
420 report_error(HWND hWnd, char* s)
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));
434 /* clear the whole line */
435 GpiQueryPageViewport(hpsScreen,&rc);
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);
445 GpiCharStringAt(hps,&pt,(long)strlen(s),s);
450 drag_over(HWND hWnd, PDRAGINFO pDraginfo)
453 USHORT indicator, operation;
455 /* Redefine this macro for debugging. */
456 #define DRAG_FAIL(x) report_error(hWnd,x)
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");
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");
475 /* The object can be dropped (copied). */
476 indicator = DOR_DROP; operation = DO_COPY;
479 DrgFreeDraginfo(pDraginfo);
480 return (MRFROM2SHORT(indicator, operation));
484 /* An object is dropped on the client window. */
487 drag_drop(HWND hwnd, PDRAGINFO pDraginfo)
491 char name[CCHMAXPATH];
492 char path[CCHMAXPATH];
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));
508 if (len >= 1 && strchr("\\/:", path[len-1]) == NULL)
510 if (len + strlen(name) + 1 <= sizeof(path)) {
511 strcpy(path + len, name);
512 for (p = path; *p != 0; ++p)
515 if (input_from_PM_Terminal) {
516 sprintf(input_from_PM_Terminal,
517 "set loadpath \"%.*s\"; load \"%s\"",
522 report_error(hwnd, "Dropped path name too long");
525 DrgDeleteDraginfoStrHandles(pDraginfo);
526 DrgFreeDraginfo(pDraginfo);
531 /* A color has been dropped on a frame(or the background color has
532 been changed with WinSetPresParam). */
535 drop_color(HWND hwnd)
540 if (WinQueryPresParam(hwnd, PP_BACKGROUNDCOLOR, 0, NULL,
542 QPF_NOINHERIT | QPF_PURERGBCOLOR) == sizeof(rgb)
548 send_drop_color(buf, 3);
555 ** Window proc for main window
556 ** -- passes most stuff to active child window via WmClientCmdProc
557 ** -- passes DDE messages to DDEProc
560 EXPENTRY DisplayClientWndProc(HWND hWnd, ULONG message, MPARAM mp1, MPARAM mp2)
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 */
569 GetMousePosViewport(hWnd, &mx, &my);
571 /* The following cannot be used because `message' is not OK for
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);
580 /* Graphics part, SET_GRAPHICS, required to update menu */
581 if (gpPMmenu_update_req)
584 /* mouse events first */
588 WinSetPointer(HWND_DESKTOP, hptrDefault); /* set default pointer */
591 /* was the mouse moved? */
592 if ((prev_mx != mx) || (prev_my != my)) {
594 WinSetPointer(HWND_DESKTOP, hptrCurrent);
596 WinSetPointer(HWND_DESKTOP, hptrCrossHair);
599 DrawZoomBox(); /* erase zoom box */
600 zoombox.to.x = mx; zoombox.to.y = my;
601 DrawZoomBox(); /* draw new zoom box */
603 /* track(show) mouse position -- send the event to gnuplot */
604 gp_exec_event(GE_motion, mx, my, 0, 0, 0);
608 return 0L; /* end of WM_MOUSEMOVE */
611 WinSetFocus(HWND_DESKTOP, hWnd);
613 gp_exec_event(GE_buttonpress, mx, my, 1, 0, 0);
617 WinSetFocus(HWND_DESKTOP, hWnd);
619 gp_exec_event(GE_buttonpress, mx, my, 3, 0, 0);
623 WinSetFocus(HWND_DESKTOP, hWnd);
625 gp_exec_event(GE_buttonpress, mx, my, 2, 0, 0);
628 case WM_BUTTON1DBLCLK:
630 gp_exec_event(GE_buttonrelease, mx, my, 1, 0, 0);
633 case WM_BUTTON2DBLCLK:
635 /* Note: 9999 should be replaced by time! */
636 gp_exec_event(GE_buttonrelease, mx, my, 3, 9999, 0);
639 case WM_BUTTON3DBLCLK:
641 gp_exec_event(GE_buttonrelease, mx, my, 2, 9999, 0);
647 case WM_BUTTON1CLICK:
650 gp_exec_event(GE_buttonrelease, mx, my, 1, 9999, 0);
656 case WM_BUTTON2CLICK:
659 gp_exec_event(GE_buttonrelease, mx, my, 3, 9999, 0);
665 case WM_BUTTON3CLICK:
668 gp_exec_event(GE_buttonrelease, mx, my, 2, 9999, 0);
671 } /* switch over mouse events */
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);
689 ChangeCheck(hWnd, IDM_MOUSE_POLAR_DISTANCE, mousePolarDistance?IDM_MOUSE_POLAR_DISTANCE:0);
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);
701 /* create a dc and hps to draw on the screen */
702 hdcScreen = WinOpenWindowDC(hWnd);
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);
709 /* Determine if PM Palette Manager should be used */
710 bPMPaletteMode = (PalSupport & CAPS_PALETTE_MANAGER) &&
712 DEBUG_COLOR(( "WM_CREATE: colors = %i, pm = %i, rgb = %i",
713 NumColors, PalSupport & CAPS_PALETTE_MANAGER, !bPMPaletteMode ));
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;
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),
740 if (!input_from_PM_Terminal) { /* no feedback */
741 #define NOFEEDBACK(X) \
742 WinEnableMenuItem(WinWindowFromID( \
743 WinQueryWindow(hApp, QW_PARENT), \
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);
756 /* get details of command-line window */
757 hSwitch = WinQuerySwitchHandle(0, ppidGnu);
758 WinQuerySwitchEntry(hSwitch, &swGnu);
761 /* set size of this window */
763 WinQueryWindow(hWnd, QW_PARENT),
764 bPopFront?HWND_TOP:swGnu.hwnd,
771 ? SWP_SIZE|SWP_MOVE|SWP_SHOW|SWP_ACTIVATE
772 : SWP_SIZE|SWP_MOVE|SWP_SHOW|SWP_ZORDER)
774 ? SWP_SHOW|SWP_ACTIVATE
775 : SWP_SHOW|SWP_ZORDER));
776 signal(SIGTERM, SigHandler);
779 if (!bPopFront) WinSwitchToProgram(hSwitch);
780 /* DosPostEventSem(semDrawDone); */
781 DosReleaseMutexSem(semHpsAccess);
785 return WmClientCmdProc(hWnd, message, mp1, mp2);
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;
794 ((usFlag & KC_SHIFT) ? Mod_Shift : 0)
795 | ((usFlag & KC_CTRL) ? Mod_Ctrl : 0)
796 | ((usFlag & KC_ALT) ? Mod_Alt : 0);
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;
803 if (!(usFlag & KC_SCANCODE))
804 return 0L; // only modifier mask has changed */
806 if (usFlag & KC_KEYUP)
807 return 0L; /* ignore key release events */
810 FILE *ff = fopen("deb", "a");
811 fprintf(ff, "key = %i c=%c\n", (int) key, (char) key);
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) */
825 WinSwitchToProgram(hSwitch);
828 /* remap virtual keys to gnuplot's codes: */
842 key = GP_Scroll_Lock;
919 gp_exec_event(GE_modifier, mx, my, modifier_mask, 0, 0);
922 key = SHORT1FROMMP(mp2); /* character key code */
926 gp_exec_event(GE_keypress, mx, my, key, 0, 0);
932 if (WinSendMsg(hWnd, WM_USER_PRINT_QBUSY, 0L, 0L) != 0L) {
933 WinMessageBox(HWND_DESKTOP,
935 "Still printing - not closed",
938 MB_OK | MB_ICONEXCLAMATION);
941 return(WinDefWindowProc(hWnd, message, mp1, mp2));
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);
966 WinInvalidateRect(hWnd, &rectlPaint, TRUE);
967 DoPaint(hWnd, hpsScreen);
968 WinSetRectEmpty(hab, &rectlPaint);
974 WinInvalidateRect(hWnd, NULL, TRUE);
977 case WM_PRESPARAMCHANGED: {
978 char *pp = malloc(FONTBUF);
981 if (WinQueryPresParam(hWnd,
987 QPF_NOINHERIT) != 0L) {
988 strcpy(szFontNameSize, pp);
992 WinInvalidateRect(hWnd, NULL, TRUE);
995 #ifndef STANDARD_FONT_DIALOG
996 gp_execute("replot");
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));
1009 /* display the plot */
1012 SWP swp; /* pop to front only if the window is not minimized */
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);
1018 if (iPaintCount > 0) { /* if outstanding paint messages, repaint */
1019 WinInvalidateRect(hWnd, &rectlPaint, TRUE);
1027 SWP swp; /* restore the window if it has been minimized */
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,
1038 (PFNWP)PauseMsgDlgProc,
1043 WinEnableMenuItem(WinWindowFromID(
1044 WinQueryWindow(hWnd, QW_PARENT), FID_MENU),
1045 IDM_CONTINUE, TRUE);
1051 /* resume plotting */
1052 ulPauseReply =(ULONG) mp1;
1053 DosPostEventSem(semPause);
1056 /* New event handles for mouse processing */
1058 #if 0 /* already defined */
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;
1071 int frm = ulMouseSprintfFormatItem - IDM_MOUSE_FORMAT_X_Y;
1073 /* Note: Another solution of getting mouse position
1074 *(available at any method, not just in this handle
1075 * event) is the following one:
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);
1083 return 0L; /* end of case WM_BUTTON1DBLCLK */
1086 case WM_BUTTON2CLICK: /* WM_BUTTON2UP: */
1088 if (! IGNORE_MOUSE) {
1090 HPS hps = WinGetPS(hWnd);
1092 if (pausing) { /* zoom is not allowed during pause */
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);
1108 return 0; /* return from: case WM_BUTTON3DOWN(zoom) */
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;
1117 HPS hps = WinGetPS(hWnd);
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);
1130 return 0L; /* end of case WM_BUTTON3... */
1132 /* End of new event handles for mouse processing */
1135 case WM_PRESPARAMCHANGED:
1136 if (LONGFROMMP(mp1) == PP_BACKGROUNDCOLOR)
1142 /* Determine whether the object can be dropped. */
1143 return(drag_over(hWnd, (PDRAGINFO) mp1));
1146 /* Drop an object. */
1147 return(drag_drop(hWnd, (PDRAGINFO) mp1));
1149 default: /* Passes it on if unproccessed */
1150 return(WinDefWindowProc(hWnd, message, mp1, mp2));
1151 } /* switch(message) */
1159 * Gets the pointer position(in pixels) in the window hWnd
1162 GetPointerPos(HWND hWnd, PPOINTL p)
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 */
1172 /* passing either n(n>=0) or f(when n==-1) */
1174 SetMouseCoords(HWND hWnd, MPARAM mp1, int n, char *f)
1178 ChangeCheck(hWnd, ulMouseSprintfFormatItem, SHORT1FROMMP(mp1));
1179 ulMouseSprintfFormatItem = SHORT1FROMMP(mp1);
1181 sprintf(s,"set mouse mouseformat %i clipboardformat %i", n, n);
1183 sprintf(s,"set mouse mouseformat \"%s\" clipboardformat \"%s\"", f, f);
1189 ** Handle client window command(menu) messages
1192 WmClientCmdProc(HWND hWnd, ULONG message, MPARAM mp1, MPARAM mp2)
1194 static int ulPauseItem = IDM_PAUSEDLG;
1195 // static int ulMouseCoordItem = IDM_MOUSE_COORDINATES_REAL;
1198 GetMousePosViewport(hWnd,&mx,&my);
1200 switch ((USHORT) SHORT1FROMMP(mp1)) {
1201 case IDM_ABOUT : /* show the 'About' box */
1202 WinDlgBox(HWND_DESKTOP,
1210 case IDM_GPLOTINF: /* view gnuplot.inf */
1212 const char cmd_prefix[] = "start view ";
1213 const char helpfile[] = "gnuplot.inf";
1216 unsigned cmd_length;
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;
1223 cmd = (char *)malloc( cmd_length );
1224 strcpy(cmd, cmd_prefix);
1225 if (gnuplot_path != NULL) {
1226 strcat(cmd, gnuplot_path);
1229 strcat(cmd, helpfile);
1235 case IDM_PRINT : /* print plot */
1236 if (SetupPrinter(hWnd, &qPrintData)) {
1238 WM_USER_PRINT_BEGIN,
1239 (MPARAM) &qPrintData,
1240 (MPARAM) hpsScreen);
1244 case IDM_PRINTSETUP : /* select printer */
1245 WinDlgBox(HWND_DESKTOP,
1247 (PFNWP) QPrintersDlgProc,
1250 qPrintData.szPrinterName);
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);
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);
1269 /* change colour setting */
1270 bColours = !bColours;
1271 ChangeCheck(hWnd, IDM_COLOURS, bColours?IDM_COLOURS:0);
1272 WinInvalidateRect(hWnd, NULL, TRUE);
1276 /* toggle z-order forcing */
1277 bPopFront = !bPopFront;
1278 ChangeCheck(hWnd, IDM_FRONT, bPopFront?IDM_FRONT:0);
1282 /* toggle keep aspect ratio */
1283 bKeepRatio = !bKeepRatio;
1284 ChangeCheck(hWnd, IDM_KEEPRATIO, bKeepRatio?IDM_KEEPRATIO:0);
1285 WinInvalidateRect(hWnd, NULL, TRUE); /* redraw screen */
1289 if (GetNewFont(hWnd, hpsScreen)) {
1293 WinInvalidateRect(hWnd, NULL, TRUE);
1302 /* copy to clipboard */
1303 if (WinOpenClipbrd(hab)) {
1304 CopyToClipBrd(hWnd);
1306 WinMessageBox(HWND_DESKTOP,
1308 "Can't open clipboard",
1311 MB_OK | MB_ICONEXCLAMATION);
1315 case IDM_CLEARCLIP : /* clear clipboard */
1316 if (WinOpenClipbrd(hab)) {
1317 WinEmptyClipbrd(hab);
1318 WinCloseClipbrd(hab);
1320 WinMessageBox(HWND_DESKTOP,
1322 "Can't open clipboard",
1325 MB_OK | MB_ICONEXCLAMATION);
1329 case IDM_COMMAND: /* go back to GNUPLOT command window */
1330 WinSwitchToProgram(hSwitch);
1334 WinPostMsg(hWnd, WM_PAUSEEND,(MPARAM)1L,(MPARAM)0L);
1335 WinEnableMenuItem(WinWindowFromID(
1336 WinQueryWindow(hWnd, QW_PARENT), FID_MENU),
1341 case IDM_PAUSEGNU: /* gnuplot handles pause */
1342 ChangeCheck(hWnd, ulPauseItem, IDM_PAUSEGNU);
1343 ulPauseItem = IDM_PAUSEGNU;
1344 ulPauseMode = PAUSE_GNU;
1347 case IDM_PAUSEDLG: /* pause message in dlg box */
1348 ChangeCheck(hWnd, ulPauseItem, IDM_PAUSEDLG);
1349 ulPauseItem = IDM_PAUSEDLG;
1350 ulPauseMode = PAUSE_DLG;
1353 case IDM_PAUSEBTN: /* pause uses menu button, no message */
1354 ChangeCheck(hWnd, ulPauseItem, IDM_PAUSEBTN);
1355 ulPauseItem = IDM_PAUSEBTN;
1356 ulPauseMode = PAUSE_BTN;
1359 case IDM_HELPFORHELP:
1360 WinSendMsg(WinQueryHelpInstance(hWnd),
1361 HM_DISPLAY_HELP, 0L, 0L);
1364 case IDM_EXTENDEDHELP:
1365 WinSendMsg(WinQueryHelpInstance(hWnd),
1366 HM_EXT_HELP, 0L, 0L);
1370 WinSendMsg(WinQueryHelpInstance(hWnd),
1371 HM_KEYS_HELP, 0L, 0L);
1375 WinSendMsg(WinQueryHelpInstance(hWnd),
1376 HM_HELP_INDEX, 0L, 0L);
1380 /* Now new mousing stuff: */
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");
1387 if (!useMouse) /* redraw screen */
1388 WinInvalidateRect(hWnd, NULL, TRUE);
1392 case IDM_MOUSE_HELP:
1393 gp_exec_event(GE_keypress, mx, my, 'h', 1, 0);
1397 case IDM_MOUSE_COORDINATES_REAL:
1398 ChangeCheck(hWnd, ulMouseCoordItem, IDM_MOUSE_COORDINATES_REAL);
1399 ulMouseCoordItem = IDM_MOUSE_COORDINATES_REAL;
1402 case IDM_MOUSE_COORDINATES_PIXELS:
1403 ChangeCheck(hWnd, ulMouseCoordItem, IDM_MOUSE_COORDINATES_PIXELS);
1404 ulMouseCoordItem = IDM_MOUSE_COORDINATES_PIXELS;
1407 case IDM_MOUSE_COORDINATES_SCREEN:
1408 ChangeCheck(hWnd, ulMouseCoordItem, IDM_MOUSE_COORDINATES_SCREEN);
1409 ulMouseCoordItem = IDM_MOUSE_COORDINATES_SCREEN;
1412 case IDM_MOUSE_COORDINATES_XDATE:
1413 ChangeCheck(hWnd, ulMouseCoordItem, IDM_MOUSE_COORDINATES_XDATE);
1414 ulMouseCoordItem = IDM_MOUSE_COORDINATES_XDATE;
1417 case IDM_MOUSE_COORDINATES_XTIME:
1418 ChangeCheck(hWnd, ulMouseCoordItem, IDM_MOUSE_COORDINATES_XTIME);
1419 ulMouseCoordItem = IDM_MOUSE_COORDINATES_XTIME;
1422 case IDM_MOUSE_COORDINATES_XDATETIME:
1423 ChangeCheck(hWnd, ulMouseCoordItem, IDM_MOUSE_COORDINATES_XDATETIME);
1424 ulMouseCoordItem = IDM_MOUSE_COORDINATES_XDATETIME;
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);
1434 case IDM_MOUSE_FORMAT_pXcYp:
1435 SetMouseCoords(hWnd, mp1, -1, "[%g, %g]");
1437 case IDM_MOUSE_FORMAT_XcY:
1438 SetMouseCoords(hWnd, mp1, 1, NULL);
1440 case IDM_MOUSE_FORMAT_TIMEFMT:
1441 SetMouseCoords(hWnd, mp1, 3, NULL);
1443 case IDM_MOUSE_FORMAT_DATE:
1444 SetMouseCoords(hWnd, mp1, 4, NULL);
1446 case IDM_MOUSE_FORMAT_TIME:
1447 SetMouseCoords(hWnd, mp1, 5, NULL);
1449 case IDM_MOUSE_FORMAT_DATETIME:
1450 SetMouseCoords(hWnd, mp1, 6, NULL);
1452 case IDM_MOUSE_FORMAT_X_Y:
1453 SetMouseCoords(hWnd, mp1, -1, "%g %g");
1455 case IDM_MOUSE_FORMAT_XcYc:
1456 SetMouseCoords(hWnd, mp1, -1, "%g %g ");
1458 case IDM_MOUSE_FORMAT_XcYs:
1459 SetMouseCoords(hWnd, mp1, -1, "%g %g, ");
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");
1469 case IDM_MOUSE_ZOOMNEXT: /* zoom to next level */
1470 gp_exec_event(GE_keypress, mx, my, 'n', 1, 0);
1473 case IDM_MOUSE_UNZOOM: /* unzoom one level back */
1474 gp_exec_event(GE_keypress, mx, my, 'p', 1, 0);
1477 case IDM_MOUSE_UNZOOMALL: /* unzoom to the first level */
1478 gp_exec_event(GE_keypress, mx, my, 'u', 1, 0);
1481 case IDM_MOUSE_RULER:
1485 GetMousePosViewport(hWnd,&mx,&my);
1486 gp_exec_event(GE_keypress, mx, my, 'r', 1, 0);
1490 case IDM_BREAK_DRAWING:
1496 gp_exec_event(GE_keypress, mx, my, 'g', 1, 0);
1500 case IDM_SET_LINLOGY:
1502 gp_exec_event(GE_keypress, mx, my, 'l', 1, 0);
1506 case IDM_SET_AUTOSCALE:
1507 gp_execute("set autoscale; replot");
1511 gp_execute("replot");
1515 gp_execute("history !load");
1518 case IDM_DO_SENDCOMMAND:
1519 if (input_from_PM_Terminal) {
1523 WinDlgBox(HWND_DESKTOP, hWnd, SendCommandDlgProc,
1524 NULLHANDLE, IDM_DO_SENDCOMMAND,
1525 input_from_PM_Terminal);
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 ]);
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 ]);
1560 return WinDefWindowProc(hWnd, message, mp1, mp2);
1561 } /* switch(message) */
1568 ** Utility function:
1570 ** move check mark from menu item 1 to item 2
1573 ChangeCheck(HWND hWnd , USHORT wItem1 , USHORT wItem2)
1575 HWND hMenu = WinWindowFromID(WinQueryWindow(hWnd, QW_PARENT),
1581 MPFROM2SHORT(wItem1, TRUE),
1582 MPFROM2SHORT(MIA_CHECKED, 0));
1586 MPFROM2SHORT(wItem2, TRUE),
1587 MPFROM2SHORT(MIA_CHECKED, MIA_CHECKED));
1592 ** Copy window to clipboard as bitmap.
1595 CopyToClipBrd(HWND hWnd)
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);
1612 ** Copy ps to a bitmap.
1614 HBITMAP CopyToBitmap(HPS hps)
1619 PSZ psz[4] = {NULL, "Display", NULL, NULL};
1622 BITMAPINFOHEADER2 bmp;
1628 hdcScr = GpiQueryDevice(hps);
1629 hwnd = WinWindowFromDC(hdcScr);
1630 hab = WinQueryAnchorBlock(hwnd);
1631 hdcMem = DevOpenDC(hab,
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);
1653 aptl[1].x =(LONG) bmp.cx;
1654 aptl[1].y =(LONG) bmp.cy;
1657 GpiBitBlt(hpsMem, hps, 3L, aptl, ROP_SRCCOPY, BBO_IGNORE);
1658 GpiDestroyPS(hpsMem);
1665 ** Copy ps to a metafile.
1668 CopyToMetaFile(HPS hps)
1673 PSZ psz[4] = {NULL,"Display",NULL,NULL};
1675 hdcOld = GpiQueryDevice(hps);
1676 hwnd = WinWindowFromDC(hdcOld);
1677 hab = WinQueryAnchorBlock(hwnd);
1678 hdcMF = DevOpenDC(hab, OD_METAFILE, "*", 4L, psz, hdcOld);
1680 DosRequestMutexSem(semHpsAccess,(ULONG) SEM_INDEFINITE_WAIT);
1681 GpiSetDrawingMode(hps, DM_DRAW);
1682 GpiAssociate(hps, 0);
1683 GpiAssociate(hps, hdcMF);
1686 GpiAssociate(hps, 0);
1687 GpiAssociate(hps, hdcOld);
1688 DosReleaseMutexSem(semHpsAccess);
1689 hmf = DevCloseDC(hdcMF);
1700 BOOL bPos, bData, bSwp ;
1705 static SWP pauseswp;
1707 /* read gnuplot ini file */
1709 hini = PrfOpenProfile(hab, szIniFile);
1710 ulCB = sizeof(ulShellPos);
1711 bPos = PrfQueryProfileData(hini, APP_NAME, INISHELLPOS, &ulShellPos, &ulCB);
1713 bSwp = PrfQueryProfileData(hini, APP_NAME, INIPAUSEPOS, &pauseswp, &ulCB);
1715 pausedata.pswp = &pauseswp;
1716 ulCB = sizeof(ulOpts);
1717 bData = PrfQueryProfileData(hini, APP_NAME, INIOPTS, &ulOpts, &ulCB);
1719 bLineTypes =(BOOL)ulOpts[0];
1720 bWideLines =(BOOL)ulOpts[1];
1721 bColours =(BOOL)ulOpts[2];
1722 ulPauseMode = ulOpts[3];
1723 bPopFront =(BOOL)ulOpts[4];
1725 bLineTypes = FALSE; /* default values */
1726 /* bWideLines = FALSE; */
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;
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);
1749 lCharWidth = ulOpts[0];
1750 lCharHeight = ulOpts[1];
1755 ulCB = sizeof(bKeepRatio);
1756 bData = PrfQueryProfileData(hini, APP_NAME, INIKEEPRATIO, &ulOpts, &ulCB);
1757 if (bData) bKeepRatio =(BOOL)ulOpts[0];
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];
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];
1774 PrfCloseProfile(hini);
1776 if (qPrintData.szPrinterName[0] == '\0') {
1777 /* get default printer name */
1778 PrfQueryProfileString(HINI_PROFILE,
1782 qPrintData.szPrinterName,
1783 (long) sizeof qPrintData.szPrinterName);
1784 if ((p=strchr(qPrintData.szPrinterName, ';')) != NULL)
1793 ** save data in ini file
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,
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,
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));
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));
1842 /* Do not write the mouse coord. mode.
1843 PrfWriteProfileData(hini, APP_NAME, INIMOUSECOORD, &mouse_mode, sizeof(mouse_mode));
1845 PrfCloseProfile(hini);
1847 WinMessageBox(HWND_DESKTOP,
1849 "Can't write ini file",
1852 MB_OK | MB_ICONEXCLAMATION);
1858 ** Paint the screen with current data
1861 DoPaint(HWND hWnd, HPS hps)
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);
1872 WinInvalidateRect(hWnd, &rectl, TRUE);
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);
1884 ** Thread to draw plot on screen
1887 ThreadDraw(void* arg)
1889 HAB hab = WinInitialize(0);
1893 DosRequestMutexSem(semHpsAccess,(ULONG) SEM_INDEFINITE_WAIT);
1895 GpiSetStopDraw(hpsScreen, SDW_OFF);
1896 GpiSetDrawingMode(hpsScreen, DM_DRAW);
1897 GpiDrawChain(hpsScreen);
1899 DisplayStatusLine(hpsScreen);
1900 WinEndPaint(hpsScreen);
1901 DosReleaseMutexSem(semHpsAccess);
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 */
1912 ** Initialise the screen ps for drawing
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);
1929 double ratio = 1.560;
1930 double xs = rectClient.xRight - rectClient.xLeft;
1931 double ys = rectClient.yTop - rectClient.yBottom;
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);
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?
1943 rectClient.xRight -= 10;
1945 GpiSetPageViewport(hpsScreen, &rectClient);
1950 alColourTable[0] = 0xFFFFFF;
1951 for (i=1; i<nColour; i++)
1952 alColourTable[i] = 0;
1955 if (bPMPaletteMode) {
1958 GpiCreateLogColorTable(hpsScreen, LCOL_RESET, LCOLF_CONSECRGB,
1959 0, nColour, alColourTable);
1960 if (!lCols_init) { /* Ilya: avoid white line on white background */
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];
1968 if (alColourTable[2+lCols[i]] == bkColor) {
1970 lCols[i - 1] = lCols[i];
1977 /* init rgb_colors: simple index translation only */
1978 for (i=0; i<18; i++)
1979 rgb_colors[i] = i + CLR_WHITE;
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 );
1990 GpiCreateLogColorTable(hpsScreen, LCOL_RESET, LCOLF_RGB, 0, 0, 0);
1997 ** Get a font to use
1998 ** Scale the plot area to world coords for subsequent plotting
2003 SelectFont(hps, szFontNameSize);
2009 ** Select a named and sized outline font
2012 SelectFont(HPS hps, char *szFontNameSize)
2016 LONG xDeviceRes, yDeviceRes;
2019 static LONG lcid = 0L;
2020 static char *szFontName;
2021 static short shPointSize;
2023 sscanf(szFontNameSize, "%hd", &shPointSize);
2024 szFontName = strchr(szFontNameSize, '.') + 1;
2026 fat.usRecordLength = sizeof fat;
2027 fat.fsSelection = 0;
2030 fat.usCodePage = codepage; /*GpiQueryCp(hps); */
2031 fat.lMaxBaselineExt = 0;
2032 fat.lAveCharWidth = 0;
2034 fat.fsFontUse = FATTR_FONTUSE_OUTLINE |
2035 FATTR_FONTUSE_TRANSFORMABLE;
2037 strcpy(fat.szFacename, szFontName);
2039 if (tabFont[0].name !=NULL)
2040 free(tabFont[0].name);
2041 tabFont[0].name = strdup(szFontName);
2042 tabFont[0].lcid = 10L;
2044 lcid = GpiQueryCharSet(hps);
2048 GpiSetCharSet(hps, 0L);
2049 GpiDeleteSetId(hps, lcid);
2051 GpiCreateLogFont(hps, NULL, lcid, &fat);
2052 GpiSetCharSet(hps, lcid);
2054 hdc = GpiQueryDevice(hps);
2056 DevQueryCaps(hdc, CAPS_HORIZONTAL_RESOLUTION, 1L, &xDeviceRes);
2057 DevQueryCaps(hdc, CAPS_VERTICAL_RESOLUTION, 1L, &yDeviceRes);
2059 /* Find desired font size in pixels */
2061 ptlFont.x = 2540L *(long)shPointSize / 72L;
2062 ptlFont.y = 2540L *(long)shPointSize / 72L;
2064 /* Set the character box */
2066 sizfx.cx = MAKEFIXED(ptlFont.x, 0);
2067 sizfx.cy = MAKEFIXED(ptlFont.y, 0);
2068 lVOffset = ptlFont.y;
2070 sizBaseFont = sizfx;
2071 GpiSetCharBox(hps, &sizfx);
2073 /* set up some useful globals */
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);
2087 sizCurFont = sizBaseFont;
2088 sizCurSubSup = sizBaseSubSup;
2091 /* EditCharCell(hps, &sizfx); */
2099 ** Select a named and sized outline(adobe) font
2102 SwapFont(HPS hps, char *szFNS)
2106 LONG xDeviceRes, yDeviceRes;
2108 static LONG lcid = 0L;
2109 static int itab = 1;
2110 static char *szFontName;
2111 static short shPointSize;
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);
2121 sscanf(szFNS, "%hd", &shPointSize);
2122 szFontName = strchr(szFNS, '.') + 1;
2128 for (i=0; i<itab; i++) {
2129 if (strcmp(szFontName, tabFont[i].name) == 0) {
2130 lcid = tabFont[i].lcid;
2137 fat.usRecordLength = sizeof fat;
2138 fat.fsSelection = 0;
2141 fat.usCodePage = codepage; /*GpiQueryCp(hps); */
2142 fat.lMaxBaselineExt = 0;
2143 fat.lAveCharWidth = 0;
2145 fat.fsFontUse = FATTR_FONTUSE_OUTLINE |
2146 FATTR_FONTUSE_TRANSFORMABLE;
2148 strcpy(fat.szFacename, szFontName);
2150 tabFont[itab].name = strdup(szFontName);
2152 tabFont[itab].lcid = lcid;
2156 GpiSetCharSet(hps, 0L);
2157 GpiDeleteSetId(hps, lcid);
2158 GpiCreateLogFont(hps, NULL, lcid, &fat);
2161 GpiSetCharSet(hps, lcid);
2162 hdc = GpiQueryDevice(hps);
2164 DevQueryCaps(hdc, CAPS_HORIZONTAL_RESOLUTION, 1L, &xDeviceRes);
2165 DevQueryCaps(hdc, CAPS_VERTICAL_RESOLUTION, 1L, &yDeviceRes);
2167 /* Find desired font size in pixels */
2168 ptlFont.x = 2540L *(long)shPointSize / 72L;
2169 ptlFont.y = 2540L *(long)shPointSize / 72L;
2171 /* Set the character box */
2172 sizCurFont.cx = MAKEFIXED(ptlFont.x, 0);
2173 sizCurFont.cy = MAKEFIXED(ptlFont.y, 0);
2174 /* lVOffset = ptlFont.y; */
2176 GpiSetCharBox(hps, &sizCurFont);
2177 sizCurSubSup.cx = MAKEFIXED(ptlFont.x*0.7, 0);
2178 sizCurSubSup.cy = MAKEFIXED(ptlFont.y*0.7, 0);
2180 /* set up some useful globals */
2184 GpiQueryFontMetrics(hps, sizeof(FONTMETRICS), &fm);
2185 lSubOffset = -fm.lSubscriptYOffset;
2186 lSupOffset = fm.lSuperscriptYOffset;
2191 typedef struct image_list_entry {
2194 struct image_list_entry *next;
2196 static image_list_entry *image_list = NULL;
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.
2216 unsigned char buff[2];
2218 static char *szPauseText = NULL;
2220 char *pszPipeName, *pszSemName;
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) */
2229 hab = WinInitialize(0);
2231 pszPipeName = malloc(256);
2232 pszSemName = malloc(256);
2234 strcpy(pszPipeName, "\\pipe\\");
2235 strcpy(pszSemName, "\\sem32\\");
2236 strcat(pszPipeName, szIPCName);
2237 strcat(pszSemName, szIPCName);
2239 /* open a named pipe for communication with gnuplot */
2241 rc = DosCreateNPipe(pszPipeName,
2243 NP_ACCESS_DUPLEX|NP_NOINHERIT|NP_NOWRITEBEHIND ,
2244 1|NP_WAIT|NP_READMODE_MESSAGE|NP_TYPE_MESSAGE,
2248 hev = 0; /* OK, gnuplot can try to open npipe ... */
2249 DosOpenEventSem(pszSemName, &hev);
2250 DosPostEventSem(hev);
2252 /* attach to gnuplot */
2255 if (DosConnectNPipe(hRead) == 0L) {
2256 WinPostMsg(hSysMenu,
2258 MPFROM2SHORT(SC_CLOSE, TRUE),
2259 MPFROM2SHORT(MIA_DISABLED, MIA_DISABLED));
2261 /* store graphics commands */
2262 /* use semaphore to prevent problems with drawing while reallocating
2263 the command buffers */
2265 DosRead(hRead, &ppidGnu, 4, &cbR);
2267 sprintf(mouseShareMemName, "\\SHAREMEM\\GP%i_Mouse_Input",(int)ppidGnu);
2268 if (DosGetNamedSharedMem(&input_from_PM_Terminal,
2271 /*now: gray menu items; old code: DosBeep(1440L,1000L); // indicates error */
2272 input_from_PM_Terminal = 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 */
2279 /* DosPostEventSem(semStartSeq); // once we've got pidGnu */
2280 WinPostMsg(hApp, WM_GPSTART, 0, 0);
2286 usErr=BufRead(hRead,buff, 1, &cbR);
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 */
2295 hps = hpsScreen; /* drawings back to screen */
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);
2304 GpiStrokePath(hps, 1, 0);
2309 case SET_GRAPHICS : /* enter graphics mode */
2311 image_list_entry *ile;
2314 /* already drawing - stop it */
2315 GpiSetStopDraw(hpsScreen, SDW_ON);
2316 while (tidDraw != 0) DosSleep(1);
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);
2324 /* DosResetEventSem(semDrawDone, &ulCount); */
2325 GpiSetDrawingMode(hps, DM_DRAWANDRETAIN);
2326 for (i=1;i<=iSeg;i++)
2327 GpiDeleteSegment(hps, i);
2329 GpiOpenSegment(hps, iSeg);
2330 /* DosExitCritSec(); */
2331 GpiSetLineEnd(hps, LINEEND_ROUND);
2332 GpiSetLineWidthGeom(hps, linewidth);
2333 GpiSetCharBox(hps, &sizBaseFont);
2335 /* free image buffers from previous plot, if any */
2336 while (image_list) {
2337 DEBUG_IMAGE(("freeing image from last plot"));
2339 image_list = ile->next;
2348 case GR_QUERY : /* query terminal info */
2349 /* mouseable gnupmdrv sends greetings to mouseable PM terminal */
2350 if (mouseTerminal) {
2353 DosWrite(hRead, &i, sizeof(int), &cbR);
2355 DosWrite(hRead, &lCharWidth, sizeof(int), &cbR);
2356 DosWrite(hRead, &lCharHeight, sizeof(int), &cbR);
2359 case SET_TEXT : /* leave graphics mode(graph completed) */
2362 GpiStrokePath(hps, 1, 0);
2365 GpiCloseSegment(hps);
2367 DisplayStatusLine(hps);
2368 /* DosPostEventSem(semDrawDone); */
2369 DosReleaseMutexSem(semHpsAccess);
2370 WinPostMsg(hApp, WM_GNUPLOT, 0L, 0L);
2374 /* gnuplot has reset drivers, allow user to kill this */
2375 WinPostMsg(hSysMenu,
2377 MPFROM2SHORT(SC_CLOSE, TRUE),
2378 MPFROM2SHORT(MIA_DISABLED,(USHORT)0));
2380 /* if we are keeping us on the screen, wait for new connection */
2381 if (bServer||bPersist) {
2382 DosDisConnectNPipe(hRead);
2389 /* resume after multiplot */
2390 DosRequestMutexSem(semHpsAccess,(ULONG) SEM_INDEFINITE_WAIT);
2391 /* DosWaitEventSem(semDrawDone, SEM_INDEFINITE_WAIT); */
2393 /* DosResetEventSem(semDrawDone, &ulCount); */
2394 GpiSetDrawingMode(hps, DM_DRAWANDRETAIN);
2395 GpiOpenSegment(hps, iSeg);
2400 /* suspend after multiplot */
2403 case GR_MOVE : /* move */
2404 case GR_DRAW : /* draw vector */
2408 if (pm3d_color >= 0) {
2409 curr_color = GpiQueryColor(hps);
2410 GpiSetColor(hps, pm3d_color);
2415 GpiStrokePath(hps, 1, 0);
2419 if (bWideLines/*bWideLines*/ && !bPath) {
2420 GpiBeginPath(hps, 1);
2424 BufRead(hRead,&ptl.x, 2*sizeof(int), &cbR);
2425 if ((*buff=='V') && bDots)
2427 else if ((*buff=='M') && bDots)
2434 if (pm3d_color >= 0)
2435 GpiSetColor(hps, curr_color);
2439 case GR_PAUSE : /* pause */
2444 BufRead(hRead, &len, sizeof(int), &cbR);
2445 len = (len + sizeof(int) - 1) / sizeof(int);
2446 if (len > 0){ /* get pause text */
2448 szPauseText = malloc(len*sizeof(int));
2450 BufRead(hRead,szPauseText, len*sizeof(int), &cbR);
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 */
2461 if (szPauseText != NULL)
2465 /* reply to gnuplot so it can continue */
2466 DosWrite(hRead, &ulPauseReply, sizeof(int), &cbR);
2471 case GR_ENH_TEXT : /* write enhanced text */
2474 GpiStrokePath(hps, 1, 0);
2478 unsigned int x, y, len;
2480 int textwidth, textheight;
2482 POINTL aptl[TXTBOX_COUNT];
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);
2491 len =(len+sizeof(int)-1)/sizeof(int);
2492 if (len == 0) len = 1; /*?? how about read */
2493 str = malloc(len*sizeof(int));
2496 BufRead(hRead, str, len*sizeof(int), &cbR);
2498 GpiQueryTextBox(hps, strlen(str), str, TXTBOX_COUNT, aptl);
2499 textwidth = aptl[TXTBOX_CONCAT].x;
2500 textheight = aptl[TXTBOX_CONCAT].y;
2502 /* only display text if requested */
2506 if (pm3d_color >= 0) {
2507 curr_color = GpiQueryColor(hps);
2508 GpiSetColor(hps, pm3d_color);
2510 ptl.x = (LONG) (x + multLineVert * (lVOffset / 4));
2511 ptl.y = (LONG) (y - multLineHor * (lVOffset / 4));
2513 GpiSetBackMix(hps, BM_LEAVEALONE);
2514 GpiCharStringAt(hps, &ptl, strlen(str), str);
2516 if (pm3d_color >= 0)
2517 GpiSetColor(hps, curr_color);
2520 /* report back textwidth */
2521 DosWrite(hRead, &textwidth, sizeof(textwidth), &cbR);
2522 DosWrite(hRead, &textheight, sizeof(textheight), &cbR);
2531 case GR_TEXT : /* write text */
2532 /* read x, y, len */
2535 GpiStrokePath(hps, 1, 0);
2539 unsigned int x, y, len;
2543 #ifndef PM_KEEP_OLD_ENHANCED_TEXT
2544 POINTL aptl[TXTBOX_COUNT];
2546 BufRead(hRead,&x, sizeof(int), &cbR);
2547 BufRead(hRead,&y, sizeof(int), &cbR);
2548 BufRead(hRead,&len, sizeof(int), &cbR);
2551 len =(len+sizeof(int)-1)/sizeof(int);
2552 if (len == 0) len = 1; /*?? how about read */
2553 str = malloc(len*sizeof(int));
2556 BufRead(hRead, str, len*sizeof(int), &cbR);
2557 if (pm3d_color >= 0) {
2558 curr_color = GpiQueryColor(hps);
2559 GpiSetColor(hps, pm3d_color);
2562 #ifdef PM_KEEP_OLD_ENHANCED_TEXT
2563 sw = QueryTextBox(hps, strlen(str), str);
2565 GpiQueryTextBox(hps, strlen(str), str, TXTBOX_COUNT, aptl);
2566 sw = aptl[TXTBOX_BOTTOMRIGHT].x;
2581 ptl.x = (LONG) (x + multLineHor * sw + multLineVert * (lVOffset / 4));
2582 ptl.y = (LONG) (y + multLineVert * sw - multLineHor * (lVOffset / 4));
2584 GpiSetBackMix(hps, BM_LEAVEALONE);
2586 #ifdef PM_KEEP_OLD_ENHANCED_TEXT
2588 CharStringAt(hps, ptl.x, ptl.y, strlen(str) , str);
2591 GpiCharStringAt(hps, &ptl, strlen(str), str);
2593 if (pm3d_color >= 0)
2594 GpiSetColor(hps, curr_color);
2603 case SET_JUSTIFY : /* justify */
2604 BufRead(hRead, &jmode, sizeof(int), &cbR);
2605 //printf( "SET_JUSTIFY: %i", jmode );
2608 case SET_ANGLE : /* text angle */
2615 GpiStrokePath(hps, 1, 0);
2618 BufRead(hRead, &ta, sizeof(int), &cbR);
2648 double t = t1 * M_PI/180;
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 */
2657 GpiSetCharAngle(hps, &grdl);
2661 case SET_LINE : /* line type */
2667 GpiStrokePath(hps, 1, 0);
2670 BufRead(hRead,<, sizeof(int), &cbR);
2671 /* linetype = -2 axes, -1 border, 0 arrows, all to 0 */
2673 if (lt == -2) GpiSetLineWidthGeom(hps, DEFLW*0.85);
2674 else if (lt == -1) GpiSetLineWidthGeom(hps, DEFLW*0.6);
2675 else GpiSetLineWidthGeom(hps, linewidth);
2679 GpiLabel(hps, lLineTypes[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 */
2686 GpiSetColor(hps, RGB_TRANS(lCols[col]));
2687 /* else GpiSetColor(hps, RGB_TRANS(CLR_BLACK)); */
2689 GpiSetColor(hps, RGB_TRANS(CLR_NEUTRAL));
2690 pm3d_color = -1; /* switch off using pm3d colours */
2694 case SET_FILLBOX : /* fill box */
2697 unsigned int x, y, w, h;
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);
2707 GpiMove(hpsScreen, &pt);
2711 switch(style & 0xf) {
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,
2724 pattern = (unsigned) trunc(9*((style >> 4) / 100.0) + 0.5);
2726 pattern = 9; /* only 10 patterns in list */
2727 GpiSetMix(hps, FM_OVERPAINT);
2728 GpiSetBackMix(hps, BM_OVERPAINT);
2729 GpiSetPattern(hps, patternlist[pattern]);
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
2745 pattern = (style >> 4) % 8;
2746 GpiSetMix(hps, FM_OVERPAINT);
2747 GpiSetBackMix(hps, BM_OVERPAINT);
2748 GpiSetPattern(hps, patternlist[pattern]);
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);
2762 GpiBox(hps, DRO_FILL, &pt, 0,0);
2766 case SET_LINEWIDTH : /* line width */
2772 GpiStrokePath(hps, 1, 0);
2775 BufRead(hRead,&lw, sizeof(int), &cbR);
2776 GpiSetLineWidthGeom(hps, DEFLW*lw/100);
2777 linewidth = DEFLW*lw/100;
2781 case SET_POINTMODE : /* points mode */
2785 BufRead(hRead,<, sizeof(int), &cbR);
2786 /* 1: enter point mode, 0: exit */
2794 lOldLine = GpiSetLineType(hps, lLineTypes[0]);
2796 GpiSetLineType(hps, lOldLine);
2801 GpiSetLineWidthGeom(hps, 20);
2803 GpiSetLineWidthGeom(hps, 50);
2809 case SET_FONT : /* set font */
2813 BufRead(hRead, &len, sizeof(int), &cbR);
2814 len = (len + sizeof(int) - 1) / sizeof(int);
2817 SwapFont(hps, NULL);
2818 strcpy(szCurrentFontNameSize, szFontNameSize);
2821 char *p, *tmp, *str;
2823 tmp = str = malloc(len * sizeof(int));
2824 BufRead(hRead, str, len * sizeof(int), &cbR);
2825 p = strchr(str, ',');
2833 /* allow abbreviation of some well known font names */
2837 SwapFont(hps, font);
2838 strcpy(szCurrentFontNameSize, font);
2839 } /* else(len==0) */
2843 case GR_QUERY_FONT : /* query current font */
2847 namelen = strlen(szCurrentFontNameSize);
2848 DosWrite(hRead, &namelen, sizeof(int), &cbR);
2849 DosWrite(hRead, szCurrentFontNameSize, namelen, &cbR);
2850 /* FIXME: is padding necessary? */
2854 case SET_OPTIONS : /* set options */
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
2868 p = str = malloc(len * sizeof(int));
2869 BufRead(hRead, str, len * sizeof(int), &cbR);
2870 while ((p=strchr(p,'-')) != NULL) {
2874 #ifdef PM_KEEP_OLD_ENHANCED_TEXT
2885 case SET_SPECIAL : /* set special options */
2888 #ifdef PM_KEEP_OLD_ENHANCED_TEXT
2890 static int prev_bEnhanced = 0;
2893 BufRead(hRead,&opt, 1, &cbR);
2895 #ifdef PM_KEEP_OLD_ENHANCED_TEXT
2896 case 'e': /* enhanced mode on, off and restore */
2897 BufRead(hRead,¶m, 1, &cbR);
2899 case '0': prev_bEnhanced = bEnhanced;
2902 case '1': prev_bEnhanced = bEnhanced;
2905 case '2': bEnhanced = prev_bEnhanced;
2910 case 'c': /* set codepage */
2911 BufRead(hRead,&codepage, sizeof(codepage), &cbR);
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 ) ;
2917 case '_': /* lower window */
2918 WinSetWindowPos( hwndFrame, HWND_BOTTOM, 0,0,0,0, SWP_ZORDER ) ;
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 */
2929 static char *text = NULL;
2930 static int text_alloc = -1;
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
2936 BufRead(hRead,&where, sizeof(int), &cbR);
2937 BufRead(hRead,&l, sizeof(int), &cbR);
2939 text = realloc(text, text_alloc = l+10);
2940 BufRead(hRead,&text[0], l, &cbR);
2943 UpdateStatusLine(hps,text);
2947 break; /* not implemented */
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 :
2962 BufRead(hRead, &c, sizeof(c), &cbR);
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));
2971 /* read the number of colours for the palette */
2972 BufRead(hRead, &smooth_colors, sizeof(int), &cbR);
2974 rgbTable = malloc(smooth_colors * sizeof(ULONG));
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);
2981 if (bPMPaletteMode) {
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! */
2990 for (i=0; i<nColors; i++)
2991 rgbTable[i] = alColourTable[i];
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);
2999 /* tell presentation manager to use the new palette */
3000 WinRealizePalette(WinWindowFromDC(hdcScreen), hps, &cclr);
3005 case GR_RELEASE_PALETTE :
3006 #if 0 /* FIXME: REMOVE THIS ROUTINE COMPLETELY! */
3008 GpiDeletePalette(pm3d_hpal);
3011 /* GpiSelectPalette(hps, pm3d_hpal_old); */
3017 /* FIXME: usgage of uchar limits the size of the 'virtual'
3018 palette to 256 entries. (see also RGB_PALETTE_SIZE) */
3021 BufRead(hRead, &c, sizeof(c), &cbR);
3023 pm3d_color = c + nColors;
3025 pm3d_color = rgbTable[c];
3026 DEBUG_COLOR(("GR_SET_COLOR: %i -> 0x%x", (int)c, pm3d_color));
3030 case GR_SET_RGBCOLOR :
3034 BufRead(hRead, &rgb_color, sizeof(rgb_color), &cbR);
3036 /* Find an approximate color in the current palette */
3038 pm3d_color = GpiQueryColorIndex(hps, 0, rgb_color);
3040 pm3d_color = rgb_color;
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 ));
3051 case GR_FILLED_POLYGON :
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);
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);
3077 if (pm3d_color >= 0)
3078 GpiSetColor(hps, curr_color);
3084 unsigned int i, M, N, image_size;
3091 image_list_entry *ile;
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);
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);
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;
3114 pbmi = (PBITMAPINFO2) calloc( sizeof(BITMAPINFOHEADER2), 1 );
3115 pbmi->cbFix = sizeof(BITMAPINFOHEADER2);
3119 pbmi->cBitCount = 24;
3120 pbmi->ulCompression = BCA_UNCOMP;
3121 hits = GpiDrawBits(hps, image, pbmi, 4, &points, ROP_SRCCOPY, BBO_IGNORE );
3124 if (hits == GPI_ERROR) {
3125 perriBlk = WinGetErrorInfo(hab);
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);
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;
3150 case SET_RULER : { /* set_ruler(int x, int y) term API: x<0 switches ruler off */
3153 BufRead(hRead, &x, sizeof(x), &cbR);
3154 BufRead(hRead, &y, sizeof(y), &cbR);
3155 DrawRuler(); /* remove previous drawing, if any */
3167 case SET_CURSOR : { /* set_cursor(int c, int x, int y) term API */
3170 BufRead(hRead, &c, sizeof(x), &cbR);
3171 BufRead(hRead, &x, sizeof(x), &cbR);
3172 BufRead(hRead, &y, sizeof(y), &cbR);
3174 case -2: { /* move mouse to the given point */
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);
3189 case -1: /* start zooming; zooming cursor */
3191 zoombox.from.x = zoombox.to.x = x;
3192 zoombox.from.y = zoombox.to.y = y;
3194 case 0: /* standard cross-hair cursor */
3195 WinSetPointer(HWND_DESKTOP,
3196 hptrCurrent =(useMouse
3200 case 1: /* cursor during rotation */
3201 WinSetPointer(HWND_DESKTOP, hptrCurrent = hptrRotating);
3203 case 2: /* cursor during scaling */
3204 WinSetPointer(HWND_DESKTOP, hptrCurrent = hptrScaling);
3206 case 3: /* cursor during zooming */
3207 WinSetPointer(HWND_DESKTOP, hptrCurrent = hptrZooming);
3210 if (c>=0 && zoombox.on) { /* erase zoom box */
3217 case SET_CLIPBOARD : { /* set_clipboard(const char s[]) term API */
3221 BufRead(hRead, &len, sizeof(int), &cbR);
3222 s = malloc(len + 1);
3223 BufRead(hRead,s, len+1, &cbR);
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
3239 useMouse = gpPMmenu.use_mouse;
3240 gpPMmenu_update_req = 1;
3244 case GR_MOUSECAPABLE :
3245 /* notification of being connected to a mouse-enabled terminal */
3249 default : /* should handle error */
3254 DosDisConnectNPipe(hRead);
3255 WinPostMsg(hApp, WM_CLOSE, 0L, 0L);
3260 EditLineTypes(HWND hwnd, HPS hps, BOOL bDashed)
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]);
3272 GpiSetElementPointer(hps, 0);
3274 GpiSetEditMode(hps, SEGEM_INSERT);
3275 GpiCloseSegment(hps);
3281 ** Edit segment to change char cell(font size)
3284 EditCharCell(HPS hps, SIZEF *psize)
3294 GpiSetDrawingMode(hps, DM_RETAIN);
3295 GpiOpenSegment(hps, iSeg);
3296 GpiSetEditMode(hps, SEGEM_REPLACE);
3298 while (GpiSetElementPointer(hps, i)) {
3299 rc = GpiQueryElementPointer(hps);
3302 rl = GpiQueryElementType(hps, &rc, 0, NULL);
3303 if (rc == 0x34 || rc == 0x74) {
3306 GpiQueryElement(hps, 5, 4, (PBYTE) &gdata);
3312 else if (rc==0x33 || rc==0x03)
3313 GpiSetCharBox(hps, iVert ? &sizV : &sizH);
3316 GpiSetEditMode(hps, SEGEM_INSERT);
3317 GpiCloseSegment(hps);
3322 ** pull next plot command out of buffer read from GNUPLOT
3325 BufRead(HFILE hfile, void *buf, int nBytes, ULONG *pcbR)
3329 static char buffer[GNUBUF];
3330 static char *pbuffer = buffer+GNUBUF, *ebuffer = buffer+GNUBUF;
3332 for (; nBytes > 0; nBytes--) {
3333 if (pbuffer >= ebuffer) {
3335 rc = DosRead(hfile, buffer, ulR, &ulRR);
3341 ebuffer = pbuffer+ulRR;
3343 *(char*)buf++ = *pbuffer++;
3349 #ifdef STANDARD_FONT_DIALOG
3352 ** Get a new font using standard font dialog
3355 GetNewFont(HWND hwnd, HPS hps)
3357 static FONTDLG pfdFontdlg; /* Font dialog info structure */
3361 HWND hwndFontDlg; /* Font dialog window handle */
3362 char szFamilyname[FACESIZE];
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));
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);
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);
3389 pfdFontdlg.fl = FNTS_HELPBUTTON |
3390 FNTS_CENTER | FNTS_VECTORONLY |
3391 FNTS_INITFROMFATTRS;
3394 if (hwndFontDlg &&(pfdFontdlg.lReturn == DID_OK)) {
3395 iSize = FIXEDINT(pfdFontdlg.fxPointSize);
3396 sprintf(szFontNameSize, "%d.%s", iSize, pfdFontdlg.fAttrs.szFacename);
3405 ** Get a new font using standard font palette
3408 GetNewFont(HWND hwnd, HPS hps)
3411 ULONG ulView = 0; /* OPEN_DEFAULT */
3412 BOOL fSuccess = FALSE;
3414 hObject = WinQueryObject("<WP_FNTPAL>");
3415 if (hObject != NULL)
3416 { fSuccess = WinOpenObject(hObject, ulView, TRUE); }
3417 if (fSuccess) return 1;
3421 #endif /* STANDARD_FONT_DIALOG */
3425 ** Handle termination signal to free up resources before
3428 void SigHandler(int sig)
3430 if (sig == SIGTERM) {
3432 DosKillThread(tidSpawn);
3436 DosKillThread(tidSpawn);
3437 DosKillThread(tidDraw);
3444 #ifdef PM_KEEP_OLD_ENHANCED_TEXT
3446 /* disable debugging info */
3447 #define TEXT_DEBUG(x) /* fprintf x */ ;
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)
3460 static char *starttext = NULL;
3461 static int textlen = 0;
3462 static BOOL bText = FALSE;
3463 static int textwidth = 0;
3464 static POINTL ptlText;
3473 int fontsize, int base,
3474 BOOL widthflag, BOOL showflag)
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));
3482 /* Start each recursion with a clean string */
3485 FILE *ff = fopen("deb","a");
3488 for (i=0;i<textlen;i++)
3489 fputc(starttext[i], ff);
3496 GpiQueryTextBox(hps, textlen, starttext, TXTBOX_COUNT, aptl);
3497 textwidth += aptl[TXTBOX_BOTTOMRIGHT].x * multLineHor;
3498 textwidth += aptl[TXTBOX_BOTTOMRIGHT].y * multLineVert;
3503 GpiCharStringAt(hps, &ptlText, textlen, starttext);
3504 ptlText.x += aptl[TXTBOX_CONCAT].x - multLineVert * base;
3505 ptlText.y += aptl[TXTBOX_CONCAT].y + multLineHor * base;
3507 ptlText.x -= multLineVert * base;
3508 ptlText.y += multLineHor * base;
3514 if (fontname != NULL) {
3515 char szFont[FONTBUF];
3517 sprintf(szFont, "%d.%s", fontsize, fontname);
3518 SwapFont(hps, szFont);
3522 GpiSetCharBox(hps, &sizCurSubSup);
3529 /*{{{ deal with it*/
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);
3548 char *savepos=NULL, save=0;
3549 char *localfontname=fontname, ch;
3550 char localfontbuf[FONTBUF];
3553 char *q=localfontbuf;
3555 /*{{{ recurse(possibly with a new font) */
3557 TEXT_DEBUG((ff,"Dealing with {\n"));
3559 /* then parse a fontname, optional fontsize */
3568 while ((ch = *p) > ' ' && ch != '=') {
3569 localfontname=localfontbuf;
3577 FontExpand(localfontbuf);
3578 save = *(savepos=p);
3581 /*{{{ get optional font size*/
3582 TEXT_DEBUG((ff,"Calling strtod(%s) ...", p));
3584 TEXT_DEBUG((ff,"Retured %.1f and %s\n", f, p));
3589 TEXT_DEBUG((ff,"Font size %.1f\n", f));
3599 if (!(*localfontname)) {
3600 localfontname = fontname;
3602 localfontname = strchr(szFontNameSize, '.') + 1;
3607 TEXT_DEBUG((ff,"Before recursing, we are at [%p] %s\n", p, p));
3609 p = ParseText(hps,p, TRUE, localfontname, f, base, widthflag, showflag);
3611 TEXT_DEBUG((ff,"BACK WITH %s\n", p));
3613 /* restore overwritten character */
3620 /*{{{ phantom box - prints next 'char', then restores currentpoint */
3622 p = ParseText(hps, ++p, FALSE, NULL/*fontname*/, fontsize,
3623 base, FALSE, showflag);
3629 /*{{{ character skip - skips space equal to length of character(s) */
3631 p = ParseText(hps, ++p, FALSE, NULL/*fontname*/, fontsize,
3632 base, widthflag, FALSE);
3639 char buffer[4]; /* should need only one char.. */
3643 ParseText(hps,q, FALSE, NULL, fontsize, base, widthflag, showflag);
3645 /*{{{ is it an escape */
3647 if (p[1]=='\\' || p[1]=='{' || p[1]=='}') {
3652 else if (p[1] >= '0' && p[1] <= '7') {
3653 /* up to 3 octal digits */
3658 if (p[1] >= '0' && p[1] <= '7') {
3661 if (p[1] >= '0' && p[1] <= '7') {
3674 ParseText(hps,q, FALSE, NULL/*fontname*/, fontsize,
3675 base, widthflag, showflag);
3686 } /* switch(character) */
3688 /* like TeX, we only do one character in a recursion, unless it's
3696 GpiQueryTextBox(hps, textlen, starttext, TXTBOX_COUNT, aptl);
3698 textwidth += aptl[TXTBOX_BOTTOMRIGHT].x * multLineHor;
3699 textwidth += aptl[TXTBOX_BOTTOMRIGHT].y * multLineVert;
3705 GpiCharStringAt(hps, &ptlText, textlen, starttext);
3707 ptlText.x += aptl[TXTBOX_CONCAT].x;
3708 ptlText.y += aptl[TXTBOX_CONCAT].y;
3712 ptlText.x += multLineVert * base;
3713 ptlText.y -= multLineHor * base;
3717 SwapFont(hps, NULL);
3718 bChangeFont = FALSE;
3721 GpiSetCharBox(hps, &sizBaseFont);
3730 CharStringAt(HPS hps, int x, int y, int len, char *str)
3732 /* flush any pending graphics(all the XShow routines do this...) */
3739 /* set up the globals */
3747 sscanf(szFontNameSize, "%d", &fontsize);
3748 fontname = strchr(szFontNameSize, '.') + 1;
3750 while (*(str = ParseText(hps, str, TRUE, NULL,
3758 QueryTextBox(HPS hps, int len, char *str)
3766 /* set up the globals */
3771 sscanf(szFontNameSize, "%d", &fontsize);
3772 fontname = strchr(szFontNameSize, '.') + 1;
3774 while (*(str = ParseText(hps, str, TRUE, NULL,
3786 FontExpand(char *name)
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");
3801 /*=======================================*/
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 }
3821 LMove(HPS hps, POINTL *p)
3828 } else if (iLtype == 0)
3833 ds = sqrt(dx*dx + dy*dy);
3844 pn.x = pCur.x + togo * dx;
3845 pn.y = pCur.y + togo * dy;
3850 if (iPatt[iLtype][iState] < 0) {
3851 togo = iPatt[iLtype][0];
3854 togo = iPatt[iLtype][iState];
3862 LLine(HPS hps, POINTL *p)
3874 ds = sqrt(dx*dx + dy*dy);
3888 pn.x = pCur.x + togo * dx;
3889 pn.y = pCur.y + togo * dy;
3897 if (iPatt[iLtype][iState] < 0) {
3898 togo = iPatt[iLtype][0];
3901 togo = iPatt[iLtype][iState];
3915 togo = iPatt[iLtype][0];
3919 /* Now routines for mouse etc. */
3922 TextToClipboard(PCSZ szTextIn)
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);
3934 strcpy(szTextOut, szTextIn);
3935 WinOpenClipbrd(hab);
3936 WinEmptyClipbrd(hab);
3937 WinSetClipbrdData(hab,(ULONG) szTextOut, CF_TEXT, CFI_POINTER);
3938 WinCloseClipbrd(hab);
3950 if (!ruler.on || ruler.x < 0)
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 */
3960 GpiMove(hpsScreen, &p);
3963 GpiLine(hpsScreen, &p);
3967 GpiMove(hpsScreen, &p);
3970 GpiLine(hpsScreen, &p);
3972 /*GpiEndPath(hpsScreen); */
3973 /*GpiStrokePath(hpsScreen, 1, 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.
3983 double *x, double *y,
3990 if (mouse_mode == MOUSE_COORDINATES_PIXELS) {
3996 /* Rectangle where we are moving: viewport, not the full window! */
3997 GpiQueryPageViewport(hpsScreen, &rc);
3999 /* only distance is important */
4000 rc.xRight -= rc.xLeft;
4001 rc.yTop -= rc.yBottom;
4003 if (mouse_mode == MOUSE_COORDINATES_SCREEN) {
4004 *x =(double) mx / rc.xRight;
4005 *y =(double) my / rc.yTop;
4009 /* px=px(mx); mouse=>gnuplot driver coordinates */
4010 *x = mx * 19500.0 / rc.xRight;
4011 *y = my * 12500.0 / rc.yTop;
4013 /* main job of transformation, which is not device dependent */
4014 MousePosToGraphPosReal(x, y);
4020 * This routine recalculates mouse/pointer position [mx,my] in [in pixels]
4021 * current window to the viewport coordinates
4024 MousePosToViewport(int *x, int *y, SHORT mx, SHORT my)
4028 /* Rectangle where we are moving: viewport, not the full window! */
4029 GpiQueryPageViewport(hpsScreen, &rc);
4031 rc.xRight -= rc.xLeft;
4032 rc.yTop -= rc.yBottom; /* only distance is important */
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);
4041 * This routine gets the mouse/pointer position in the current window and
4042 * recalculates it to the viewport coordinates
4045 GetMousePosViewport(HWND hWnd, int *mx, int *my)
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);
4056 * Status line previous and current text:
4058 static char *sl_curr_text = NULL;
4061 * Display the status line by the text
4064 DisplayStatusLine(HPS hps)
4070 GpiSetColor(hps, RGB_TRANS(COLOR_MOUSE)); /* set text color */
4071 GpiSetCharMode(hps, CM_MODE1);
4074 GpiSetMix(hps, FM_INVERT);
4075 /* GpiSetMix(hps, FM_XOR); */
4076 GpiCharStringAt(hps, &pt,(long) strlen(sl_curr_text), sl_curr_text);
4081 * Update the status line by the text; firstly erase the previous text
4084 UpdateStatusLine(HPS hps, char *text)
4086 if (gpPMmenu_update_req)
4087 gpPMmenu_update(); /* check for updated menu */
4089 /* erase the previous text */
4090 DisplayStatusLine(hps);
4093 if (!text || !*text)
4096 /* display new text */
4097 sl_curr_text = strdup(text);
4098 DisplayStatusLine(hps);
4104 * Graphics part SET_GRAPHICS or anything else required to update menu according to
4105 * the items in gpPMmenu
4111 if (!gpPMmenu_update_req)
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);
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);
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);