X-Git-Url: http://git.maemo.org/git/?p=gnuplot;a=blobdiff_plain;f=src%2Fos2%2Fgclient.c;fp=src%2Fos2%2Fgclient.c;h=b8bedaf20c6f2d8257d2d1f94e92f0d53635f3a3;hp=0000000000000000000000000000000000000000;hb=39ec1247a71f61152a4a7f502a30f06a3896c5da;hpb=06be459be4f5f6a7c6ff878e84f355fb2575caa8 diff --git a/src/os2/gclient.c b/src/os2/gclient.c new file mode 100644 index 0000000..b8bedaf --- /dev/null +++ b/src/os2/gclient.c @@ -0,0 +1,4145 @@ +#ifdef INCRCSDATA +static char RCSid[]="$Id: gclient.c,v 1.47.2.1 2008/02/23 11:23:12 mikulik Exp $"; +#endif + +/**************************************************************************** + + PROGRAM: Gnupmdrv + + MODULE: gclient.c + + This file contains the client window procedures for Gnupmdrv + +****************************************************************************/ + +/* PM driver for GNUPLOT */ + +/*[ + * Copyright 1992, 1993, 1998, 2004 Roger Fearick + * + * Permission to use, copy, and distribute this software and its + * documentation for any purpose with or without fee is hereby granted, + * provided that the above copyright notice appear in all copies and + * that both that copyright notice and this permission notice appear + * in supporting documentation. + * + * Permission to modify the software is granted, but not the right to + * distribute the complete modified source code. Modifications are to + * be distributed as patches to the released version. Permission to + * distribute binaries produced by compiling modified sources is granted, + * provided you + * 1. distribute the corresponding source modifications from the + * released version in the form of a patch file along with the binaries, + * 2. add special version identification to distinguish your version + * in addition to the base release version number, + * 3. provide your name and address as the primary contact for the + * support of your modified version, and + * 4. retain our contact information in regard to use of the base + * software. + * Permission to distribute the released version of the source code along + * with corresponding source modifications in the form of a patch file is + * granted with same provisions 2 through 4 for binary distributions. + * + * This software is provided "as is" without express or implied warranty + * to the extent permitted by applicable law. +]*/ + +/* + * AUTHOR + * + * Gnuplot driver for OS/2: Roger Fearick + * + * + * CONTRIBUTIONS: + * + * Petr Mikulik (see PM labels) + * - menu item to keep aspect ratio on/off (October 1997) + * - mouse support (1998, 1999); changes made after gnuplot 3.7.0.5: + * - use gnuplot's pid in the name of shared memory (11. 5. 1999) + * - mouse in maps; distance in polar coords (14. 5. 1999) + * - event semaphore for sending data via shared memory; + * zooming completely revised; + * remap keys in 'case WM_CHAR'; + * Ctrl-C for breaking long drawings; + * new menu items under 'Mouse' and 'Utilities' (August 1999) + * - rewrite of mouse support for the new scheme common with X11 + * (October 1999 - January 2000) + * - pm3d stuff (since January 1999) + * + * Franz Bakan + * - communication gnupmdrv -> gnuplot via shared memory (April 1999) + * - date and time on x axis (August 1999) + */ + +#define INCL_PM +#define INCL_WIN +#define INCL_SPL +#define INCL_SPLDOSPRINT +#define INCL_WINSTDFONT +#define INCL_DOSMEMMGR +#define INCL_DOSPROCESS +#define INCL_DOSERRORS +#define INCL_DOSFILEMGR +#define INCL_DOSNMPIPES +#define INCL_DOSSESMGR +#define INCL_DOSSEMAPHORES +#define INCL_DOSMISC +#define INCL_DOSQUEUES +#define INCL_WINSWITCHLIST +#define INCL_GPIPRIMITIVES +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "config.h" +#include "term_api.h" +#include "gnupmdrv.h" +#include "pm_msgs.h" +#define GNUPMDRV +#include "mousecmn.h" + + +/*==== m i s c e l l a n e o u s =============================================*/ + +/* February 2008, according to the gnuplot bugs report #1773922 + The standard font selection dialog is somehow broken after saving options. + Use the font palette dialog instead. +*/ +/* #define STANDARD_FONT_DIALOG 1 */ +#undef STANDARD_FONT_DIALOG + +/*==== d e b u g g i n g =====================================================*/ + +#if 0 +# include "pmprintf.h" +# define DEBUG_IMAGE(a) PmPrintf a +#else +# define DEBUG_IMAGE(a) +#endif + +#if 0 +# include "pmprintf.h" +# define DEBUG_COLOR(a) PmPrintf a +#else +# define DEBUG_COLOR(a) +#endif + + +/*==== l o c a l d a t a ==================================================*/ + +static long lLineTypes[7] = { + LINETYPE_SOLID, + LINETYPE_SHORTDASH, + LINETYPE_DOT, + LINETYPE_DASHDOT, + LINETYPE_LONGDASH, + LINETYPE_DOUBLEDOT, + LINETYPE_DASHDOUBLEDOT +}; + +static long lCols[16] = { + CLR_BLACK, + CLR_DARKGRAY, + CLR_RED, + CLR_GREEN, + CLR_BLUE, + CLR_PINK, + CLR_CYAN, + CLR_BROWN, + CLR_YELLOW, + CLR_DARKBLUE, + CLR_DARKRED, + CLR_DARKGREEN, + CLR_DARKCYAN, + CLR_DARKPINK, + CLR_PALEGRAY, + CLR_WHITE +}; + +static long lCols_init = 0; +static long lCols_num = 16; +static long bkColor = -1; + +/* Note that there are 16 colours used for drawing. The two more + entries in this array were added by Ilya to avoid drawing white + line on white background. */ +#define nColors 16 +static LONG alColourTable[nColors + 2]; + +static BOOL bPMPaletteMode = TRUE; /* do we use PM palette manager? */ + +/* RGB equivalents of all normal CLR_xxx colour constants + Note: First entry corresponds to CLR_WHITE, which is negative (-2)! +*/ +static LONG rgb_colors[18]; +/* macro to facilitate translation */ +#define RGB_TRANS(v) rgb_colors[(v)-CLR_WHITE] + +/* A value of 0 indicates direct rgb colors without palette */ +/* FIXME: gnupmdrv crashes if this is > GNUBUF/4 ! */ +/* FIXME: this must be <= 256 (see PM_SET_COLOR) */ +#define RGB_PALETTE_SIZE 0 /* size of the 'virtual' palette used for + translation of index to RGB value */ + +/* FIXME: increasing GNUBUF circumvents a bug/limitation in BufRead: + it cannot read datablocks larger than GNUBUF */ +#define GNUBUF 131072 +//#define GNUBUF 2048 /* buffer for gnuplot commands */ +#define PIPEBUF 4096 /* size of pipe buffers */ +#define CMDALLOC 4096 /* command buffer allocation increment (ints) */ + +#define PAUSE_DLG 1 /* pause handled in dialog box */ +#define PAUSE_BTN 2 /* pause handled by menu item */ +#define PAUSE_GNU 3 /* pause handled by Gnuplot */ + +#define DEFLW 50 + +// ULONG ppidGnu = 0L; /* gnuplot pid */ -- now in gpexecute.c +static HDC hdcScreen; +static HPS hpsScreen; /* screen pres. space */ +static int iSeg = 1; + +static HSWITCH hSwitch = 0; /* switching between windows */ +static SWCNTRL swGnu; + +static BOOL bLineTypes = FALSE; // true if use dashed linetypes +static BOOL bColours = TRUE; +static BOOL bShellPos = FALSE; +static BOOL bPopFront = TRUE; +static BOOL bKeepRatio = TRUE; //PM +#if 0 +static BOOL bNewFont = FALSE; +#endif + +static double multLineHor = 1.; /* Horizontal and vertical spacing shifts */ +static double multLineVert = 0.; /* for multiline prints. */ + +static int codepage = 0; + +static int ulMouseSprintfFormatItem = IDM_MOUSE_FORMAT_XcY; +static BOOL bSend2gp = FALSE; +/* HBB FIXME 20040630: why isn't this 'static'? */ +const char *SetDataStyles[] = { + "boxes", "dots", "fsteps", "histeps", "impulses", + "lines", "linespoints", "points", "steps" +}; + +struct { + int on; // set to 1 during zooming + POINTL from, to; // corners +} zoombox = { 0 }; + + +static int zooming = 0; // set to 1 during zooming +static POINTL zoomrect_from, zoomrect_now; + +static ULONG ulPlotPos[4]; +static ULONG ulShellPos[4]; +static PAUSEDATA pausedata = {sizeof(PAUSEDATA), NULL, NULL}; +static char szFontNameSize[FONTBUF]; /* default name and size, format: "10.Helvetica" */ +/* FIXME: this might not always get updated on font change */ +static char szCurrentFontNameSize[FONTBUF]; /* currently selected font */ +static PRQINFO3 infPrinter = { "" }; +static QPRINT qPrintData = { + sizeof(QPRINT), 0.0, 0.0, 1.0, 1.0, 0, + "", "", &infPrinter, 0, NULL +}; +//static HEV semStartSeq; /* semaphore to start things in right sequence */ +static HEV semPause; +static HMTX semHpsAccess; +static ULONG ulPauseReply = 1; +static ULONG ulPauseMode = PAUSE_DLG; + +static HWND hSysMenu; + /* stuff for screen-draw thread control */ + +//static HEV semDrawDone; + + /* thread control */ + +static TID tidDraw, tidSpawn; + +static int breakDrawing = 0; + /* //PM flag for stopping (long) drawings */ + + /* font data */ + +static int lSupOffset = 0; +static int lSubOffset = 0; +static int lBaseSupOffset = 0; +static int lBaseSubOffset = 0; +static int lCharWidth = 217; +static int lCharHeight = 465; + + +//PM: Now variables for mouse + +/* useMouse is set to 1 when user switches mousing on, e.g. the mouse is + allowed +*/ +static int useMouse = 0; + +/* gnuplot's PM terminal sends GR_MOUSECAPABLE message from its init routine, which + sets the variable below to 1. Then we are sure that we talk to the + mouseable terminal and can read the mouseable data from the pipe. + Non-mouseable versions of PM terminal or non-new-gnuplot programs + using gnupmdrv will let this variable set to 0, thus no mousing occurs. +*/ +static char mouseTerminal = 0; + + +/* Lock (hide) mouse when building the plot (redrawing screen). + Otherwise gnupmdrv would crash when trying to display mouse position + in a window not yet plotted. +*/ +static char lock_mouse = 1; + +/* Structure for the ruler: on/off, position,... +*/ +static struct { + int on; + int x, y; /* ruler position */ +} ruler = {0,0,0,}; + +// Pointer definition +HWND hptrDefault, hptrCrossHair, hptrScaling, + hptrRotating, hptrZooming, hptrCurrent; + +// After passing gpPMmenu in PM_pipe and SET_GRAPHICS, it seems not to be possible +// to update the menu. Thus this flag is set on and menu is updated +// afterwards. +struct t_gpPMmenu gpPMmenu; +int gpPMmenu_update_req = 0; + +// colours of mouse-relating drawings (CLR_DEFAULT is not allowed!) +#define COLOR_MOUSE CLR_BLACK // mouse position +#define COLOR_ANNOTATE CLR_BLACK // annotating strings (MB3) +#define COLOR_RULER CLR_DARKPINK // colour of the ruler +#define COLOR_ERROR CLR_RED // colour of error messages + +static enum JUSTIFY jmode; + +static SIZEF sizBaseSubSup; +static SIZEF sizCurSubSup; +static SIZEF sizCurFont; +static long lVOffset = 0; +static SIZEF sizBaseFont; + +static struct _ft { + char *name; + LONG lcid; +} tabFont[256] = { + {NULL,0L}, + {NULL} +}; + + +/*==== f u n c t i o n s =====================================================*/ + +int DoPrint(HWND); +HBITMAP CopyToBitmap(HPS); +HMF CopyToMetaFile(HPS); +MRESULT WmClientCmdProc(HWND , ULONG, MPARAM, MPARAM); +void ChangeCheck(HWND, USHORT, USHORT); +BOOL QueryIni(HAB); +static void SaveIni(HWND); +static void ThreadDraw(void*); +static void DoPaint(HWND, HPS); +static void SelectFont(HPS, char *); +static void SwapFont(HPS, char *); +static void CopyToClipBrd(HWND); +static void ReadGnu(void*); +static void EditLineTypes(HWND, HPS, BOOL); +#if 0 +static void EditCharCell(HPS, SIZEF*); +#endif +static HPS InitScreenPS(void); +static int BufRead(HFILE, void*, int, PULONG); +static int GetNewFont(HWND, HPS); +void SigHandler(int); +static void FontExpand(char *); +#ifdef PM_KEEP_OLD_ENHANCED_TEXT +static char *ParseText(HPS, char *, BOOL, char *, int, int, BOOL, BOOL); +static void CharStringAt(HPS, int, int, int, char *); +static int QueryTextBox(HPS, int, char *); +#endif +static void LMove(HPS hps, POINTL *p); +static void LLine(HPS hps, POINTL *p); +static void LType(int iType); + +/* Functions related to the mouse processing */ +static void TextToClipboard(PCSZ); +static void GetMousePosViewport(HWND hWnd, int *mx, int *my); +static void MousePosToViewport(int *x, int *y, SHORT mx, SHORT my); +static void DisplayStatusLine(HPS hps); +static void UpdateStatusLine(HPS hps, char *text); +static void gpPMmenu_update(void); +static void DrawZoomBox(void); +static void DrawRuler(void); + +#define IGNORE_MOUSE (!mouseTerminal || useMouse==0 || lock_mouse) +/* || !gp4mouse.graph */ +/* don't react to mouse in the event handler, and avoid some crashes */ + +/* Drag'n'Drop support from PMEmacs */ +struct drop { + unsigned long cookie; + unsigned len; + char str[CCHMAXPATH]; +}; + +/* Circular buffer of objects recently dropped. */ + +#define DROP_MAX 8 +static int drop_count = 0; + +/* Each drop action is assigned a number, for relating drop events + with PMR_DROP requests. */ + +/* Finally, include the common mousing declarations and routines: */ +#define GNUPMDRV + /* let mousing.c know whether called from gclient.c or gplt_x11.c */ +#include "../gpexecute.h" + +/* End of new functions related to the mouse processing */ + +/*==== c o d e ===============================================================*/ + +/* An object is being dragged over the client window. Check whether + it can be dropped or not. */ + +void +report_error(HWND hWnd, char* s) +{ + HPS hps; + POINTL pt; + RECTL rc; + + hps = WinGetPS(hWnd); + GpiSetMix(hps, FM_OVERPAINT); + /* clear the rectangle below the text */ + /* GpiSetColor(hps, RGB_TRANS(CLR_CYAN)); */ + GpiSetColor(hps, RGB_TRANS(CLR_BACKGROUND)); + pt.x = 0; + pt.y = 0; + GpiMove(hps,&pt); + /* clear the whole line */ + GpiQueryPageViewport(hpsScreen,&rc); + pt.x = rc.xRight; + pt.y = 16; + GpiBox(hps, DRO_FILL, &pt, 0,0); + /* now write the mouse position on the screen */ + GpiSetColor(hps, RGB_TRANS(COLOR_ERROR)); /* set text color */ + GpiSetCharMode(hps,CM_MODE1); + + pt.x = 2; + pt.y = 2; + GpiCharStringAt(hps,&pt,(long)strlen(s),s); + WinReleasePS(hps); +} + +MRESULT +drag_over(HWND hWnd, PDRAGINFO pDraginfo) +{ + PDRAGITEM pditem; + USHORT indicator, operation; + +/* Redefine this macro for debugging. */ +#define DRAG_FAIL(x) report_error(hWnd,x) + + indicator = DOR_NODROPOP; operation = DO_COPY; + if (!DrgAccessDraginfo(pDraginfo)) + DRAG_FAIL("DrgAccessDraginfo failed"); + else if (!(pDraginfo->usOperation == DO_DEFAULT + || pDraginfo->usOperation == DO_COPY)) + DRAG_FAIL("Invalid operation"); + else if (DrgQueryDragitemCount(pDraginfo) < 1) + DRAG_FAIL("Invalid count"); + else if (DrgQueryDragitemCount(pDraginfo) > DROP_MAX - drop_count) + DRAG_FAIL("Circular buffer full"); + else { + pditem = DrgQueryDragitemPtr(pDraginfo, 0); + if (!(pditem->fsSupportedOps & DO_COPYABLE)) + DRAG_FAIL("Not copyable"); + else if (!DrgVerifyRMF(pditem, "DRM_OS2FILE", NULL)) + DRAG_FAIL("DrgVerifyRMF failed"); + else { + /* The object can be dropped (copied). */ + indicator = DOR_DROP; operation = DO_COPY; + } + } + DrgFreeDraginfo(pDraginfo); + return (MRFROM2SHORT(indicator, operation)); +} + + +/* An object is dropped on the client window. */ + +MRESULT +drag_drop(HWND hwnd, PDRAGINFO pDraginfo) +{ + PDRAGITEM pditem; + POINTL ptl; + char name[CCHMAXPATH]; + char path[CCHMAXPATH]; + char *p; + int count, idx, len; + + DrgAccessDraginfo(pDraginfo); + ptl.x = pDraginfo->xDrop; ptl.y = pDraginfo->yDrop; + WinMapWindowPoints(HWND_DESKTOP, hwnd, &ptl, 1); + count = DrgQueryDragitemCount(pDraginfo); + for (idx = 0; idx < count && drop_count < DROP_MAX; ++idx) { + pditem = DrgQueryDragitemPtr(pDraginfo, idx); + DrgQueryStrName(pditem->hstrContainerName, sizeof(path), path); + DrgQueryStrName(pditem->hstrSourceName, sizeof(name), name); + DrgSendTransferMsg(pditem->hwndItem, DM_ENDCONVERSATION, + MPFROMLONG(pditem->ulItemID), + MPFROMSHORT(DMFL_TARGETSUCCESSFUL)); + len = strlen(path); + if (len >= 1 && strchr("\\/:", path[len-1]) == NULL) + path[len++] = '/'; + if (len + strlen(name) + 1 <= sizeof(path)) { + strcpy(path + len, name); + for (p = path; *p != 0; ++p) + if (*p == '\\') + *p = '/'; + if (input_from_PM_Terminal) { + sprintf(input_from_PM_Terminal, + "set loadpath \"%.*s\"; load \"%s\"", + len, path, path); + gp_execute(0); + } + } else + report_error(hwnd, "Dropped path name too long"); + } /* for(idx) */ + + DrgDeleteDraginfoStrHandles(pDraginfo); + DrgFreeDraginfo(pDraginfo); + return(0); +} + +#if 0 +/* A color has been dropped on a frame(or the background color has + been changed with WinSetPresParam). */ + +static void +drop_color(HWND hwnd) +{ + RGB rgb; + char buf[3]; + + if (WinQueryPresParam(hwnd, PP_BACKGROUNDCOLOR, 0, NULL, + sizeof(rgb), &rgb, + QPF_NOINHERIT | QPF_PURERGBCOLOR) == sizeof(rgb) + ) { + buf[0] = rgb.bRed; + buf[1] = rgb.bGreen; + buf[2] = rgb.bBlue; +#if CAN_DROP_COLOR + send_drop_color(buf, 3); +#endif + } +} +#endif + +/* +** Window proc for main window +** -- passes most stuff to active child window via WmClientCmdProc +** -- passes DDE messages to DDEProc +*/ +MRESULT +EXPENTRY DisplayClientWndProc(HWND hWnd, ULONG message, MPARAM mp1, MPARAM mp2) +{ + static RECTL rectlPaint = { 0, 0, 0, 0 }; + static int iPaintCount = 0; + static int firstcall = 1; + static int prev_mx = 0, prev_my = 0; /* previous mouse position */ + int mx, my; /* current mouse position */ + +#if 1 + GetMousePosViewport(hWnd, &mx, &my); +#else + /* The following cannot be used because `message' is not OK for + * WM_CHAR */ + /* macro which gets mouse coords in pixels */ + mx = MOUSEMSG(&message)->x; + my = MOUSEMSG(&message)->y; + /* viewport units --- this trashes mx,my! */ + MousePosToViewport(&mx, &my, mx, my); +#endif + + /* Graphics part, SET_GRAPHICS, required to update menu */ + if (gpPMmenu_update_req) + gpPMmenu_update(); + + /* mouse events first */ + switch (message) { + case WM_MOUSEMOVE: + if (IGNORE_MOUSE) { + WinSetPointer(HWND_DESKTOP, hptrDefault); /* set default pointer */ + return 0L; + } + /* was the mouse moved? */ + if ((prev_mx != mx) || (prev_my != my)) { +#if 1 + WinSetPointer(HWND_DESKTOP, hptrCurrent); +#else + WinSetPointer(HWND_DESKTOP, hptrCrossHair); +#endif + if (zoombox.on) { + DrawZoomBox(); /* erase zoom box */ + zoombox.to.x = mx; zoombox.to.y = my; + DrawZoomBox(); /* draw new zoom box */ + } + /* track(show) mouse position -- send the event to gnuplot */ + gp_exec_event(GE_motion, mx, my, 0, 0, 0); + } + prev_mx = mx; + prev_my = my; + return 0L; /* end of WM_MOUSEMOVE */ + + case WM_BUTTON1DOWN: + WinSetFocus(HWND_DESKTOP, hWnd); + if (! IGNORE_MOUSE) + gp_exec_event(GE_buttonpress, mx, my, 1, 0, 0); + return 0L; + + case WM_BUTTON2DOWN: + WinSetFocus(HWND_DESKTOP, hWnd); + if (!IGNORE_MOUSE) + gp_exec_event(GE_buttonpress, mx, my, 3, 0, 0); + return 0L; + + case WM_BUTTON3DOWN: + WinSetFocus(HWND_DESKTOP, hWnd); + if (!IGNORE_MOUSE) + gp_exec_event(GE_buttonpress, mx, my, 2, 0, 0); + return 0L; + + case WM_BUTTON1DBLCLK: + if (!IGNORE_MOUSE) + gp_exec_event(GE_buttonrelease, mx, my, 1, 0, 0); + return 0L; + + case WM_BUTTON2DBLCLK: + if (!IGNORE_MOUSE) + /* Note: 9999 should be replaced by time! */ + gp_exec_event(GE_buttonrelease, mx, my, 3, 9999, 0); + return 0L; + + case WM_BUTTON3DBLCLK: + if (!IGNORE_MOUSE) + gp_exec_event(GE_buttonrelease, mx, my, 2, 9999, 0); + return 0L; + +#if 1 + case WM_BUTTON1UP: +#else + case WM_BUTTON1CLICK: +#endif + if (!IGNORE_MOUSE) + gp_exec_event(GE_buttonrelease, mx, my, 1, 9999, 0); + return 0L; + +#if 0 + case WM_BUTTON2UP: +#else + case WM_BUTTON2CLICK: +#endif + if (!IGNORE_MOUSE) + gp_exec_event(GE_buttonrelease, mx, my, 3, 9999, 0); + return 0L; + +#if 1 + case WM_BUTTON3UP: +#else + case WM_BUTTON3CLICK: +#endif + if (!IGNORE_MOUSE) + gp_exec_event(GE_buttonrelease, mx, my, 2, 9999, 0); + return 0L; + + } /* switch over mouse events */ + + + switch (message) { + case WM_CREATE: + { + SIZEL sizlPage; + LONG NumColors; + LONG PalSupport; + + /* set initial values */ + ChangeCheck(hWnd, IDM_LINES_THICK, bWideLines?IDM_LINES_THICK:0); + ChangeCheck(hWnd, IDM_LINES_SOLID, bLineTypes?0:IDM_LINES_SOLID); + ChangeCheck(hWnd, IDM_COLOURS, bColours?IDM_COLOURS:0); + ChangeCheck(hWnd, IDM_FRONT, bPopFront?IDM_FRONT:0); + ChangeCheck(hWnd, IDM_KEEPRATIO, bKeepRatio?IDM_KEEPRATIO:0); + ChangeCheck(hWnd, IDM_USEMOUSE, useMouse?IDM_USEMOUSE:0); +#if 0 + ChangeCheck(hWnd, IDM_MOUSE_POLAR_DISTANCE, mousePolarDistance?IDM_MOUSE_POLAR_DISTANCE:0); +#endif + + /* disable close from system menu(close only from gnuplot) */ + hApp = WinQueryWindow(hWnd, QW_PARENT); /* temporary assignment.. */ + hSysMenu = WinWindowFromID(hApp, FID_SYSMENU); + /* setup semaphores */ + /* DosCreateEventSem(NULL, &semDrawDone, 0L, 0L); */ + /* DosCreateEventSem(NULL, &semStartSeq, 0L, 0L); */ + DosCreateEventSem(NULL, &semPause, 0L, 0L); + DosCreateMutexSem(NULL, &semHpsAccess, 0L, 1L); + + /* create a dc and hps to draw on the screen */ + hdcScreen = WinOpenWindowDC(hWnd); + + /* How many colors can be displayed ? */ + DevQueryCaps(hdcScreen, CAPS_COLORS, 1, &NumColors); + /* Is Palette Manager supported at all? */ + DevQueryCaps(hdcScreen, CAPS_ADDITIONAL_GRAPHICS, 1, &PalSupport); + + /* Determine if PM Palette Manager should be used */ + bPMPaletteMode = (PalSupport & CAPS_PALETTE_MANAGER) && + (NumColors <= 256); + DEBUG_COLOR(( "WM_CREATE: colors = %i, pm = %i, rgb = %i", + NumColors, PalSupport & CAPS_PALETTE_MANAGER, !bPMPaletteMode )); + + sizlPage.cx = 0; sizlPage.cy = 0; + sizlPage.cx = 19500; sizlPage.cy = 12500; + hpsScreen = GpiCreatePS(hab, hdcScreen, &sizlPage, + PU_HIMETRIC|GPIT_NORMAL|GPIA_ASSOC); + /* spawn server for GNUPLOT ... */ + tidSpawn = _beginthread(ReadGnu, NULL, 32768, NULL); + /* initialize pointers */ + hptrDefault = WinQuerySysPointer(HWND_DESKTOP, SPTR_ARROW, FALSE); + hptrCrossHair = WinLoadPointer(HWND_DESKTOP,(ULONG)0, IDP_CROSSHAIR); + hptrScaling = WinLoadPointer(HWND_DESKTOP,(ULONG)0, IDP_SCALING); + hptrRotating = WinLoadPointer(HWND_DESKTOP,(ULONG)0, IDP_ROTATING); + hptrZooming = WinQuerySysPointer(HWND_DESKTOP, SPTR_MOVE, FALSE); + hptrCurrent = hptrCrossHair; + + break; + } + + case WM_GPSTART: + /* Show the Mouse menu if connected to mouseable PM terminal */ + if (1 || mouseTerminal) /* PM: workaround for a bug---SEE "BUGS 2" IN README!!! */ + /* if (mouseTerminal) */ + WinEnableMenuItem(WinWindowFromID( + WinQueryWindow(hApp, QW_PARENT), + FID_MENU), + IDM_MOUSE, TRUE); + if (!input_from_PM_Terminal) { /* no feedback */ +#define NOFEEDBACK(X) \ + WinEnableMenuItem(WinWindowFromID( \ + WinQueryWindow(hApp, QW_PARENT), \ + FID_MENU), \ + X, FALSE) + NOFEEDBACK(IDM_SET_GRID); + NOFEEDBACK(IDM_SET_LINLOGY); + NOFEEDBACK(IDM_SET_AUTOSCALE); + NOFEEDBACK(IDM_DO_REPLOT); + NOFEEDBACK(IDM_DO_RELOAD); + NOFEEDBACK(IDM_DO_SENDCOMMAND); + NOFEEDBACK(IDM_SET); +#undef NOFEEDBACK + } + + /* get details of command-line window */ + hSwitch = WinQuerySwitchHandle(0, ppidGnu); + WinQuerySwitchEntry(hSwitch, &swGnu); + + if (firstcall) { + /* set size of this window */ + WinSetWindowPos( + WinQueryWindow(hWnd, QW_PARENT), + bPopFront?HWND_TOP:swGnu.hwnd, + ulShellPos[0], + ulShellPos[1], + ulShellPos[2], + ulShellPos[3], + bShellPos + ? (bPopFront + ? SWP_SIZE|SWP_MOVE|SWP_SHOW|SWP_ACTIVATE + : SWP_SIZE|SWP_MOVE|SWP_SHOW|SWP_ZORDER) + : (bPopFront + ? SWP_SHOW|SWP_ACTIVATE + : SWP_SHOW|SWP_ZORDER)); + signal(SIGTERM, SigHandler); + firstcall = 0; + } + if (!bPopFront) WinSwitchToProgram(hSwitch); + /* DosPostEventSem(semDrawDone); */ + DosReleaseMutexSem(semHpsAccess); + return 0; + + case WM_COMMAND: + return WmClientCmdProc(hWnd, message, mp1, mp2); + + case WM_CHAR: + { + /* Note: doc for WM_CHAR is available in PMMSG.INF */ + USHORT usFlag = SHORT1FROMMP(mp1); /* keyboard control codes */ + SHORT key = SHORT2FROMMP(mp2); /* virtual key code */ + static int last_modifier_mask = -99; + int modifier_mask = + ((usFlag & KC_SHIFT) ? Mod_Shift : 0) + | ((usFlag & KC_CTRL) ? Mod_Ctrl : 0) + | ((usFlag & KC_ALT) ? Mod_Alt : 0); + + if (modifier_mask != last_modifier_mask) { + gp_exec_event(GE_modifier, mx, my, modifier_mask, 0, 0); + last_modifier_mask = modifier_mask; + } +#if 0 + if (!(usFlag & KC_SCANCODE)) + return 0L; // only modifier mask has changed */ +#endif + if (usFlag & KC_KEYUP) + return 0L; /* ignore key release events */ +#if 0 + { + FILE *ff = fopen("deb", "a"); + fprintf(ff, "key = %i c=%c\n", (int) key, (char) key); + fclose(ff); + } +#endif + + switch (key) { + case VK_SPACE: { + /* raise gnuplot's window */ + HWND hw = WinQueryWindow(swGnu.hwnd, QW_BOTTOM); + WinSetFocus(HWND_DESKTOP, hw); + WinSendMsg(hw, message, + MPFROM2SHORT((USHORT)(KC_SCANCODE), 1), + 0 /* MPFROMSHORT(key) */ + ); + WinSwitchToProgram(hSwitch); + break; + } + /* remap virtual keys to gnuplot's codes: */ + case VK_BACKSPACE: + key = GP_BackSpace; + break; + case VK_TAB: + key = GP_Tab; + break; + case VK_NEWLINE: + key = GP_Return; + break; + case VK_PAUSE: + key = GP_Pause; + break; + case VK_SCRLLOCK: + key = GP_Scroll_Lock; + break; + case VK_SYSRQ: + key = GP_Sys_Req; + break; + case VK_ESC: + key = GP_Escape; + break; + case VK_DELETE: + key = GP_Delete; + break; + case VK_INSERT: + key = GP_KP_Insert; + break; + case VK_HOME: + key = GP_Home; + break; + case VK_LEFT: + key = GP_Left; + break; + case VK_UP: + key = GP_Up; + break; + case VK_RIGHT: + key = GP_Right; + break; + case VK_DOWN: + key = GP_Down; + break; + case VK_END: + key = GP_End; + break; + case VK_PAGEUP: + key = GP_PageUp; + break; + case VK_PAGEDOWN: + key = GP_PageDown; + break; + case VK_F1: + key = GP_F1; + break; + case VK_F2: + key = GP_F2; + break; + case VK_F3: + key = GP_F3; + break; + case VK_F4: + key = GP_F4; + break; + case VK_F5: + key = GP_F5; + break; + case VK_F6: + key = GP_F6; + break; + case VK_F7: + key = GP_F7; + break; + case VK_F8: + key = GP_F8; + break; + case VK_F9: + key = GP_F9; + break; + case VK_F10: + key = GP_F10; + break; + case VK_F11: + key = GP_F11; + break; + case VK_F12: + key = GP_F12; + break; + case VK_SHIFT: + case VK_CTRL: + case VK_ALT: + gp_exec_event(GE_modifier, mx, my, modifier_mask, 0, 0); + return 0L; + default: + key = SHORT1FROMMP(mp2); /* character key code */ + } /* switch(key) */ + + if (key) + gp_exec_event(GE_keypress, mx, my, key, 0, 0); + + return 0L; + } /*case(WM_CHAR) */ + + case WM_DESTROY: + if (WinSendMsg(hWnd, WM_USER_PRINT_QBUSY, 0L, 0L) != 0L) { + WinMessageBox(HWND_DESKTOP, + hWnd, + "Still printing - not closed", + APP_NAME, + 0, + MB_OK | MB_ICONEXCLAMATION); + return 0L; + } + return(WinDefWindowProc(hWnd, message, mp1, mp2)); + + case WM_PAINT: + { + ULONG ulCount; + PID pid; TID tid; + HPS hps_tmp; + RECTL rectl_tmp; + + DosQueryMutexSem(semHpsAccess, &pid, &tid, &ulCount); + if ((ulCount > 0) &&(tid != tidDraw)) { + /* simple repaint while building plot or metafile */ + /* use temporary PS */ + lock_mouse = 1; /* PM: this may help against gnupmdrv crashes */ + hps_tmp = WinBeginPaint(hWnd,0,&rectl_tmp); + WinFillRect(hps_tmp,&rectl_tmp,CLR_BACKGROUND); + WinEndPaint(hps_tmp); + /* add dirty rectangle to saved rectangle */ + /* to be repainted when PS is available again */ + WinUnionRect(hab,&rectlPaint,&rectl_tmp,&rectlPaint); + lock_mouse = 0; + iPaintCount ++; + break; + } + lock_mouse = 1; + WinInvalidateRect(hWnd, &rectlPaint, TRUE); + DoPaint(hWnd, hpsScreen); + WinSetRectEmpty(hab, &rectlPaint); + lock_mouse = 0; + break; + } + + case WM_SIZE : + WinInvalidateRect(hWnd, NULL, TRUE); + break; + + case WM_PRESPARAMCHANGED: { + char *pp = malloc(FONTBUF); + ULONG ulID; + + if (WinQueryPresParam(hWnd, + PP_FONTNAMESIZE, + 0, + &ulID, + FONTBUF, + pp, + QPF_NOINHERIT) != 0L) { + strcpy(szFontNameSize, pp); +#if 0 + bNewFont = TRUE; +#endif + WinInvalidateRect(hWnd, NULL, TRUE); + } + free(pp); +#ifndef STANDARD_FONT_DIALOG + gp_execute("replot"); +#endif + break; + } + + case WM_USER_PRINT_BEGIN: + case WM_USER_PRINT_OK : + case WM_USER_DEV_ERROR : + case WM_USER_PRINT_ERROR : + case WM_USER_PRINT_QBUSY : + return(PrintCmdProc(hWnd, message, mp1, mp2)); + + case WM_GNUPLOT: + /* display the plot */ + lock_mouse = 1; + if (bPopFront) { + SWP swp; /* pop to front only if the window is not minimized */ + + if ((WinQueryWindowPos(hwndFrame,(PSWP) &swp) == TRUE) + &&((swp.fl & SWP_MINIMIZE) == 0)) + WinSetWindowPos(hwndFrame, HWND_TOP, 0,0,0,0, SWP_ACTIVATE|SWP_ZORDER); + } + if (iPaintCount > 0) { /* if outstanding paint messages, repaint */ + WinInvalidateRect(hWnd, &rectlPaint, TRUE); + iPaintCount = 0; + } + lock_mouse = 0; + return 0L; + + case WM_PAUSEPLOT: + { + SWP swp; /* restore the window if it has been minimized */ + + if ((WinQueryWindowPos(hwndFrame, &swp) == TRUE) + &&((swp.fl & SWP_MINIMIZE) != 0)) + WinSetWindowPos(hwndFrame, HWND_TOP, 0,0,0,0, + SWP_RESTORE|SWP_SHOW|SWP_ACTIVATE); + /* put pause message on screen, or enable 'continue' button */ + if (ulPauseMode == PAUSE_DLG) { + pausedata.pszMessage =(char*)mp1; + WinLoadDlg(HWND_DESKTOP, + hWnd, + (PFNWP)PauseMsgDlgProc, + 0L, + IDD_PAUSEBOX, + &pausedata); + } else { + WinEnableMenuItem(WinWindowFromID( + WinQueryWindow(hWnd, QW_PARENT), FID_MENU), + IDM_CONTINUE, TRUE); + } + return 0L; + } + + case WM_PAUSEEND: + /* resume plotting */ + ulPauseReply =(ULONG) mp1; + DosPostEventSem(semPause); + return 0L; + +/* New event handles for mouse processing */ + +#if 0 /* already defined */ + case WM_MOUSEMOVE: + return 0L; +#endif + +#if 0 + case WM_BUTTON1DBLCLK: + /* put the mouse coordinates to the clipboard */ + if (!IGNORE_MOUSE) { + SHORT mx = MOUSEMSG(&message)->x; + SHORT my = MOUSEMSG(&message)->y; + double x, y; + char s[256]; + int frm = ulMouseSprintfFormatItem - IDM_MOUSE_FORMAT_X_Y; + + /* Note: Another solution of getting mouse position + *(available at any method, not just in this handle + * event) is the following one: + * + * ok = WinQueryPointerPos(HWND_DESKTOP, &pt); // pt contains pos wrt desktop + * WinMapWindowPoints(HWND_DESKTOP, hWnd, &pt, 1); // pt contains pos wrt our hwnd window + * sprintf(s,"[%li,%li]",pt.x,pt.y); + */ + + } + return 0L; /* end of case WM_BUTTON1DBLCLK */ +#endif + + case WM_BUTTON2CLICK: /* WM_BUTTON2UP: */ + /* make zoom */ + if (! IGNORE_MOUSE) { + POINTL tmp; + HPS hps = WinGetPS(hWnd); + + if (pausing) { /* zoom is not allowed during pause */ + DosBeep(440,111); + break; + } + DosBeep(555,155); + zoomrect_from.x = MOUSEMSG(&message)->x; + zoomrect_from.y = MOUSEMSG(&message)->y; + /* set opposite corner */ + tmp.x = zoomrect_now.x = zoomrect_from.x + 50; + tmp.y = zoomrect_now.y = zoomrect_from.y + 50; + /* move mouse to opposite corner */ + WinMapWindowPoints(hWnd, HWND_DESKTOP, &tmp, 1); + WinSetPointerPos(HWND_DESKTOP, tmp.x, tmp.y); + WinReleasePS(hps); + zooming = 1; + } + return 0; /* return from: case WM_BUTTON3DOWN(zoom) */ + + case WM_BUTTON3UP: /* WM_BUTTON3DBLCLK: */ + /* write mouse position to screen */ + if (! IGNORE_MOUSE) { + SHORT mx = MOUSEMSG(&message)->x; /* mouse position */ + SHORT my = MOUSEMSG(&message)->y; + char s[256]; + POINTL pt; + HPS hps = WinGetPS(hWnd); + + GpiSetColor(hps, RGB_TRANS(COLOR_ANNOTATE)); /* set color of the text */ + GpiSetCharMode(hps,CM_MODE1); + pt.x = mx; pt.y = my+4; + GpiCharStringAt(hps,&pt,(long)strlen(s),s); + /* draw a cross at the clicked position */ + pt.x = mx-3; pt.y = my; GpiMove(hps,&pt); + pt.x += 7; GpiLine(hps,&pt); + pt.x = mx; pt.y = my - 3; GpiMove(hps,&pt); + pt.y += 7; GpiLine(hps,&pt); + WinReleasePS(hps); + } + return 0L; /* end of case WM_BUTTON3... */ + + /* End of new event handles for mouse processing */ + +#if 0 + case WM_PRESPARAMCHANGED: + if (LONGFROMMP(mp1) == PP_BACKGROUNDCOLOR) + drop_color(hWnd); + return 0; +#endif + + case DM_DRAGOVER: + /* Determine whether the object can be dropped. */ + return(drag_over(hWnd, (PDRAGINFO) mp1)); + + case DM_DROP: + /* Drop an object. */ + return(drag_drop(hWnd, (PDRAGINFO) mp1)); + + default: /* Passes it on if unproccessed */ + return(WinDefWindowProc(hWnd, message, mp1, mp2)); + } /* switch(message) */ + + return(NULL); +} + + +#if 0 /* unused */ +/* + * Gets the pointer position(in pixels) in the window hWnd + */ +void +GetPointerPos(HWND hWnd, PPOINTL p) +{ + WinQueryPointerPos(HWND_DESKTOP, p); + /* this is position wrt desktop */ + WinMapWindowPoints(HWND_DESKTOP, hWnd, p, 1); + /* pos. wrt our window in pixels */ +} +#endif + + +/* passing either n(n>=0) or f(when n==-1) */ +void +SetMouseCoords(HWND hWnd, MPARAM mp1, int n, char *f) +{ + char s[100]; + + ChangeCheck(hWnd, ulMouseSprintfFormatItem, SHORT1FROMMP(mp1)); + ulMouseSprintfFormatItem = SHORT1FROMMP(mp1); + if (n >= 0) + sprintf(s,"set mouse mouseformat %i clipboardformat %i", n, n); + else + sprintf(s,"set mouse mouseformat \"%s\" clipboardformat \"%s\"", f, f); + gp_execute(s); +} + + +/* +** Handle client window command(menu) messages +*/ +MRESULT +WmClientCmdProc(HWND hWnd, ULONG message, MPARAM mp1, MPARAM mp2) +{ + static int ulPauseItem = IDM_PAUSEDLG; + // static int ulMouseCoordItem = IDM_MOUSE_COORDINATES_REAL; + int mx, my; + + GetMousePosViewport(hWnd,&mx,&my); + + switch ((USHORT) SHORT1FROMMP(mp1)) { + case IDM_ABOUT : /* show the 'About' box */ + WinDlgBox(HWND_DESKTOP, + hWnd , + (PFNWP)About , + 0L, + ID_ABOUT, + NULL); + break; + + case IDM_GPLOTINF: /* view gnuplot.inf */ + { + const char cmd_prefix[] = "start view "; + const char helpfile[] = "gnuplot.inf"; + char *cmd; + char *gnuplot_path; + unsigned cmd_length; + + cmd_length = strlen(cmd_prefix) + strlen(helpfile); + gnuplot_path = getenv("GNUPLOT"); + if (gnuplot_path != NULL) + cmd_length += strlen(gnuplot_path) + 1; + + cmd = (char *)malloc( cmd_length ); + strcpy(cmd, cmd_prefix); + if (gnuplot_path != NULL) { + strcat(cmd, gnuplot_path); + strcat(cmd, "\\"); + } + strcat(cmd, helpfile); + system(cmd); + free(cmd); + break; + } + + case IDM_PRINT : /* print plot */ + if (SetupPrinter(hWnd, &qPrintData)) { + WinPostMsg(hWnd, + WM_USER_PRINT_BEGIN, + (MPARAM) &qPrintData, + (MPARAM) hpsScreen); + } + break; + + case IDM_PRINTSETUP : /* select printer */ + WinDlgBox(HWND_DESKTOP, + hWnd , + (PFNWP) QPrintersDlgProc, + 0L, + IDD_QUERYPRINT, + qPrintData.szPrinterName); + break; + + case IDM_LINES_THICK: + /* change line setting */ + bWideLines = !bWideLines; + ChangeCheck(hWnd, IDM_LINES_THICK, bWideLines?IDM_LINES_THICK:0); + WinInvalidateRect(hWnd, NULL, TRUE); + break; + + case IDM_LINES_SOLID: + /* change line setting */ + bLineTypes = !bLineTypes; + ChangeCheck(hWnd, IDM_LINES_SOLID, bLineTypes?0:IDM_LINES_SOLID); + EditLineTypes(hWnd, hpsScreen, bLineTypes); + WinInvalidateRect(hWnd, NULL, TRUE); + break; + + case IDM_COLOURS: + /* change colour setting */ + bColours = !bColours; + ChangeCheck(hWnd, IDM_COLOURS, bColours?IDM_COLOURS:0); + WinInvalidateRect(hWnd, NULL, TRUE); + break; + + case IDM_FRONT: + /* toggle z-order forcing */ + bPopFront = !bPopFront; + ChangeCheck(hWnd, IDM_FRONT, bPopFront?IDM_FRONT:0); + break; + + case IDM_KEEPRATIO: + /* toggle keep aspect ratio */ + bKeepRatio = !bKeepRatio; + ChangeCheck(hWnd, IDM_KEEPRATIO, bKeepRatio?IDM_KEEPRATIO:0); + WinInvalidateRect(hWnd, NULL, TRUE); /* redraw screen */ + break; + + case IDM_FONTS: + if (GetNewFont(hWnd, hpsScreen)) { +#if 0 + bNewFont = TRUE; +#endif + WinInvalidateRect(hWnd, NULL, TRUE); + } + break; + + case IDM_SAVE: + SaveIni(hWnd); + break; + + case IDM_COPY: + /* copy to clipboard */ + if (WinOpenClipbrd(hab)) { + CopyToClipBrd(hWnd); + } else { + WinMessageBox(HWND_DESKTOP, + hWnd, + "Can't open clipboard", + APP_NAME, + 0, + MB_OK | MB_ICONEXCLAMATION); + } + break; + + case IDM_CLEARCLIP : /* clear clipboard */ + if (WinOpenClipbrd(hab)) { + WinEmptyClipbrd(hab); + WinCloseClipbrd(hab); + } else { + WinMessageBox(HWND_DESKTOP, + hWnd, + "Can't open clipboard", + APP_NAME, + 0, + MB_OK | MB_ICONEXCLAMATION); + } + break; + + case IDM_COMMAND: /* go back to GNUPLOT command window */ + WinSwitchToProgram(hSwitch); + break; + + case IDM_CONTINUE: + WinPostMsg(hWnd, WM_PAUSEEND,(MPARAM)1L,(MPARAM)0L); + WinEnableMenuItem(WinWindowFromID( + WinQueryWindow(hWnd, QW_PARENT), FID_MENU), + IDM_CONTINUE, + FALSE); + break; + + case IDM_PAUSEGNU: /* gnuplot handles pause */ + ChangeCheck(hWnd, ulPauseItem, IDM_PAUSEGNU); + ulPauseItem = IDM_PAUSEGNU; + ulPauseMode = PAUSE_GNU; + break; + + case IDM_PAUSEDLG: /* pause message in dlg box */ + ChangeCheck(hWnd, ulPauseItem, IDM_PAUSEDLG); + ulPauseItem = IDM_PAUSEDLG; + ulPauseMode = PAUSE_DLG; + break; + + case IDM_PAUSEBTN: /* pause uses menu button, no message */ + ChangeCheck(hWnd, ulPauseItem, IDM_PAUSEBTN); + ulPauseItem = IDM_PAUSEBTN; + ulPauseMode = PAUSE_BTN; + break; + + case IDM_HELPFORHELP: + WinSendMsg(WinQueryHelpInstance(hWnd), + HM_DISPLAY_HELP, 0L, 0L); + return 0L; + + case IDM_EXTENDEDHELP: + WinSendMsg(WinQueryHelpInstance(hWnd), + HM_EXT_HELP, 0L, 0L); + return 0L; + + case IDM_KEYSHELP: + WinSendMsg(WinQueryHelpInstance(hWnd), + HM_KEYS_HELP, 0L, 0L); + return 0L; + + case IDM_HELPINDEX: + WinSendMsg(WinQueryHelpInstance(hWnd), + HM_HELP_INDEX, 0L, 0L); + return 0L; + + + /* Now new mousing stuff: */ + + case IDM_USEMOUSE: /* toggle using/not using mouse cursor tracking */ + useMouse = !useMouse; + ChangeCheck(hWnd, IDM_USEMOUSE, useMouse?IDM_USEMOUSE:0); + gp_execute(useMouse ? "set mouse" : "unset mouse"); +#if 0 + if (!useMouse) /* redraw screen */ + WinInvalidateRect(hWnd, NULL, TRUE); +#endif + return 0L; + + case IDM_MOUSE_HELP: + gp_exec_event(GE_keypress, mx, my, 'h', 1, 0); + return 0L; + +#if 0 + case IDM_MOUSE_COORDINATES_REAL: + ChangeCheck(hWnd, ulMouseCoordItem, IDM_MOUSE_COORDINATES_REAL); + ulMouseCoordItem = IDM_MOUSE_COORDINATES_REAL; + return 0L; + + case IDM_MOUSE_COORDINATES_PIXELS: + ChangeCheck(hWnd, ulMouseCoordItem, IDM_MOUSE_COORDINATES_PIXELS); + ulMouseCoordItem = IDM_MOUSE_COORDINATES_PIXELS; + return 0L; + + case IDM_MOUSE_COORDINATES_SCREEN: + ChangeCheck(hWnd, ulMouseCoordItem, IDM_MOUSE_COORDINATES_SCREEN); + ulMouseCoordItem = IDM_MOUSE_COORDINATES_SCREEN; + return 0L; + + case IDM_MOUSE_COORDINATES_XDATE: + ChangeCheck(hWnd, ulMouseCoordItem, IDM_MOUSE_COORDINATES_XDATE); + ulMouseCoordItem = IDM_MOUSE_COORDINATES_XDATE; + return 0L; + + case IDM_MOUSE_COORDINATES_XTIME: + ChangeCheck(hWnd, ulMouseCoordItem, IDM_MOUSE_COORDINATES_XTIME); + ulMouseCoordItem = IDM_MOUSE_COORDINATES_XTIME; + return 0L; + + case IDM_MOUSE_COORDINATES_XDATETIME: + ChangeCheck(hWnd, ulMouseCoordItem, IDM_MOUSE_COORDINATES_XDATETIME); + ulMouseCoordItem = IDM_MOUSE_COORDINATES_XDATETIME; + return 0L; +#endif + + case IDM_MOUSE_CMDS2CLIP: + /* toggle copying the command sent to gnuplot to clipboard */ + bSend2gp = !bSend2gp; + ChangeCheck(hWnd, IDM_MOUSE_CMDS2CLIP, bSend2gp?IDM_MOUSE_CMDS2CLIP:0); + return 0L; + + case IDM_MOUSE_FORMAT_pXcYp: + SetMouseCoords(hWnd, mp1, -1, "[%g, %g]"); + return 0L; + case IDM_MOUSE_FORMAT_XcY: + SetMouseCoords(hWnd, mp1, 1, NULL); + return 0L; + case IDM_MOUSE_FORMAT_TIMEFMT: + SetMouseCoords(hWnd, mp1, 3, NULL); + return 0L; + case IDM_MOUSE_FORMAT_DATE: + SetMouseCoords(hWnd, mp1, 4, NULL); + return 0L; + case IDM_MOUSE_FORMAT_TIME: + SetMouseCoords(hWnd, mp1, 5, NULL); + return 0L; + case IDM_MOUSE_FORMAT_DATETIME: + SetMouseCoords(hWnd, mp1, 6, NULL); + return 0L; + case IDM_MOUSE_FORMAT_X_Y: + SetMouseCoords(hWnd, mp1, -1, "%g %g"); + return 0L; + case IDM_MOUSE_FORMAT_XcYc: + SetMouseCoords(hWnd, mp1, -1, "%g %g "); + return 0L; + case IDM_MOUSE_FORMAT_XcYs: + SetMouseCoords(hWnd, mp1, -1, "%g %g, "); + return 0L; + + case IDM_MOUSE_POLAR_DISTANCE: + /* toggle using/not using polar coords of distance */ + gp_execute(gpPMmenu.polar_distance + ? "set mouse nopolardistance" + : "set mouse polardistance"); + return 0L; + + case IDM_MOUSE_ZOOMNEXT: /* zoom to next level */ + gp_exec_event(GE_keypress, mx, my, 'n', 1, 0); + return 0L; + + case IDM_MOUSE_UNZOOM: /* unzoom one level back */ + gp_exec_event(GE_keypress, mx, my, 'p', 1, 0); + return 0L; + + case IDM_MOUSE_UNZOOMALL: /* unzoom to the first level */ + gp_exec_event(GE_keypress, mx, my, 'u', 1, 0); + return 0L; + + case IDM_MOUSE_RULER: + { + int mx, my; + + GetMousePosViewport(hWnd,&mx,&my); + gp_exec_event(GE_keypress, mx, my, 'r', 1, 0); + return 0L; + } + + case IDM_BREAK_DRAWING: + breakDrawing = 1; + return 0L; + + case IDM_SET_GRID: + { + gp_exec_event(GE_keypress, mx, my, 'g', 1, 0); + return 0L; + } + + case IDM_SET_LINLOGY: + { + gp_exec_event(GE_keypress, mx, my, 'l', 1, 0); + return 0L; + } + + case IDM_SET_AUTOSCALE: + gp_execute("set autoscale; replot"); + return 0L; + + case IDM_DO_REPLOT: + gp_execute("replot"); + return 0L; + + case IDM_DO_RELOAD: + gp_execute("history !load"); + return 0L; + + case IDM_DO_SENDCOMMAND: + if (input_from_PM_Terminal) { + if (pausing) + DosBeep(440,111); + else + WinDlgBox(HWND_DESKTOP, hWnd, SendCommandDlgProc, + NULLHANDLE, IDM_DO_SENDCOMMAND, + input_from_PM_Terminal); + } + return (MRESULT) 0; + + case IDM_SET_D_S_BOXES: + case IDM_SET_D_S_DOTS: + case IDM_SET_D_S_FSTEPS: + case IDM_SET_D_S_HISTEPS: + case IDM_SET_D_S_IMPULSES: + case IDM_SET_D_S_LINES: + case IDM_SET_D_S_LINESPOINTS: + case IDM_SET_D_S_POINTS: + case IDM_SET_D_S_STEPS: + if (input_from_PM_Terminal) + sprintf(input_from_PM_Terminal, "set style data %s; replot", + SetDataStyles[(USHORT) SHORT1FROMMP(mp1) - IDM_SET_D_S_BOXES ]); + gp_execute(0); + return 0L; + + case IDM_SET_F_S_BOXES: + case IDM_SET_F_S_DOTS: + case IDM_SET_F_S_FSTEPS: + case IDM_SET_F_S_HISTEPS: + case IDM_SET_F_S_IMPULSES: + case IDM_SET_F_S_LINES: + case IDM_SET_F_S_LINESPOINTS: + case IDM_SET_F_S_POINTS: + case IDM_SET_F_S_STEPS: + if (input_from_PM_Terminal) + sprintf(input_from_PM_Terminal, "set style function %s; replot", + SetDataStyles[(USHORT) SHORT1FROMMP(mp1) - IDM_SET_F_S_BOXES ]); + gp_execute(0); + return 0L; + + default : + return WinDefWindowProc(hWnd, message, mp1, mp2); + } /* switch(message) */ + + return(NULL); +} + + +/* +** Utility function: +** +** move check mark from menu item 1 to item 2 +*/ +void +ChangeCheck(HWND hWnd , USHORT wItem1 , USHORT wItem2) +{ + HWND hMenu = WinWindowFromID(WinQueryWindow(hWnd, QW_PARENT), + FID_MENU); + + if (wItem1 != 0) + WinSendMsg(hMenu, + MM_SETITEMATTR, + MPFROM2SHORT(wItem1, TRUE), + MPFROM2SHORT(MIA_CHECKED, 0)); + if (wItem2 != 0) + WinSendMsg(hMenu, + MM_SETITEMATTR, + MPFROM2SHORT(wItem2, TRUE), + MPFROM2SHORT(MIA_CHECKED, MIA_CHECKED)); +} + + +/* +** Copy window to clipboard as bitmap. +*/ +static void +CopyToClipBrd(HWND hWnd) +{ + HAB hab; + HBITMAP hbm; + HMF hmf; + + hab = WinQueryAnchorBlock(hWnd); + WinEmptyClipbrd(hab); + hbm = CopyToBitmap(hpsScreen); + WinSetClipbrdData(hab,(ULONG) hbm, CF_BITMAP, CFI_HANDLE); + hmf = CopyToMetaFile(hpsScreen); + WinSetClipbrdData(hab,(ULONG) hmf, CF_METAFILE, CFI_HANDLE); + WinCloseClipbrd(hab); +} + + +/* +** Copy ps to a bitmap. +*/ +HBITMAP CopyToBitmap(HPS hps) +{ + HPS hpsMem; + HWND hwnd; + HAB hab; + PSZ psz[4] = {NULL, "Display", NULL, NULL}; + HDC hdcMem, hdcScr; + SIZEL sizel; + BITMAPINFOHEADER2 bmp; + HBITMAP hbm; + LONG alData[2]; + RECTL rectl; + POINTL aptl[6]; + + hdcScr = GpiQueryDevice(hps); + hwnd = WinWindowFromDC(hdcScr); + hab = WinQueryAnchorBlock(hwnd); + hdcMem = DevOpenDC(hab, + OD_MEMORY, + "*", + 4L, + (PDEVOPENDATA) psz, + hdcScr); + sizel.cx = 0/*GNUPAGE*/; + sizel.cy = 0/*GNUPAGE*/; + hpsMem = GpiCreatePS(hab, hdcMem, &sizel, + PU_PELS | GPIA_ASSOC | GPIT_MICRO); + GpiQueryDeviceBitmapFormats(hpsMem, 2L, alData); + WinQueryWindowRect(hwnd, &rectl); + memset(&bmp, 0, sizeof(bmp)); + bmp.cbFix =(ULONG) sizeof(bmp); + bmp.cx =(SHORT)(rectl.xRight - rectl.xLeft); + bmp.cy =(SHORT)(rectl.yTop - rectl.yBottom); + bmp.cPlanes = alData[0]; + bmp.cBitCount = alData[1]; + hbm = GpiCreateBitmap(hpsMem, &bmp, 0, NULL, NULL); + GpiSetBitmap(hpsMem, hbm); + aptl[0].x = 0; + aptl[0].y = 0; + aptl[1].x =(LONG) bmp.cx; + aptl[1].y =(LONG) bmp.cy; + aptl[2].x = 0; + aptl[2].y = 0; + GpiBitBlt(hpsMem, hps, 3L, aptl, ROP_SRCCOPY, BBO_IGNORE); + GpiDestroyPS(hpsMem); + DevCloseDC(hdcMem); + return hbm; +} + + +/* +** Copy ps to a metafile. +*/ +HMF +CopyToMetaFile(HPS hps) +{ + HDC hdcMF, hdcOld; + HAB hab; + HWND hwnd; + PSZ psz[4] = {NULL,"Display",NULL,NULL}; + HMF hmf; + hdcOld = GpiQueryDevice(hps); + hwnd = WinWindowFromDC(hdcOld); + hab = WinQueryAnchorBlock(hwnd); + hdcMF = DevOpenDC(hab, OD_METAFILE, "*", 4L, psz, hdcOld); + + DosRequestMutexSem(semHpsAccess,(ULONG) SEM_INDEFINITE_WAIT); + GpiSetDrawingMode(hps, DM_DRAW); + GpiAssociate(hps, 0); + GpiAssociate(hps, hdcMF); + ScalePS(hps); + GpiDrawChain(hps); + GpiAssociate(hps, 0); + GpiAssociate(hps, hdcOld); + DosReleaseMutexSem(semHpsAccess); + hmf = DevCloseDC(hdcMF); + return hmf; +} + + +/* +** Query INI file +*/ +BOOL +QueryIni(HAB hab) +{ + BOOL bPos, bData, bSwp ; + ULONG ulOpts[5]; + HINI hini; + ULONG ulCB; + char *p; + static SWP pauseswp; + + /* read gnuplot ini file */ + + hini = PrfOpenProfile(hab, szIniFile); + ulCB = sizeof(ulShellPos); + bPos = PrfQueryProfileData(hini, APP_NAME, INISHELLPOS, &ulShellPos, &ulCB); + ulCB = sizeof(SWP); + bSwp = PrfQueryProfileData(hini, APP_NAME, INIPAUSEPOS, &pauseswp, &ulCB); + if (bSwp) + pausedata.pswp = &pauseswp; + ulCB = sizeof(ulOpts); + bData = PrfQueryProfileData(hini, APP_NAME, INIOPTS, &ulOpts, &ulCB); + if (bData) { + bLineTypes =(BOOL)ulOpts[0]; + bWideLines =(BOOL)ulOpts[1]; + bColours =(BOOL)ulOpts[2]; + ulPauseMode = ulOpts[3]; + bPopFront =(BOOL)ulOpts[4]; + } else { + bLineTypes = FALSE; /* default values */ + /* bWideLines = FALSE; */ + bColours = TRUE; + bPopFront = TRUE; + ulPauseMode = 1; + } + ulCB = 4*sizeof(float); + PrfQueryProfileData(hini, APP_NAME, INIFRAC, &qPrintData.xsize, &ulCB); + if (PrfQueryProfileSize(hini, APP_NAME, INIPRDRIV, &ulCB)) { + PDRIVDATA pdriv =(PDRIVDATA) malloc(ulCB); + if (pdriv != NULL) { + PrfQueryProfileData(hini, APP_NAME, INIPRDRIV, pdriv, &ulCB); + qPrintData.pdriv = pdriv; + qPrintData.cbpdriv = ulCB; + } + } + PrfQueryProfileString(hini, APP_NAME, INIPRPR, "", + qPrintData.szPrinterName, + (long) sizeof qPrintData.szPrinterName); + PrfQueryProfileString(hini, APP_NAME, INIFONT, INITIAL_FONT, + szFontNameSize, FONTBUF); + ulCB = sizeof(ulOpts); + bData = PrfQueryProfileData(hini, APP_NAME, INICHAR, &ulOpts, &ulCB); + if (bData) { + lCharWidth = ulOpts[0]; + lCharHeight = ulOpts[1]; + } else { + lCharWidth = 217; + lCharHeight = 465; + } + ulCB = sizeof(bKeepRatio); + bData = PrfQueryProfileData(hini, APP_NAME, INIKEEPRATIO, &ulOpts, &ulCB); + if (bData) bKeepRatio =(BOOL)ulOpts[0]; + + /* Mousing: */ + /* Ignore reading "Use mouse" --- no good idea to have mouse on by default. + Maybe it was the reason of some crashes(mouse init before draw). + ulCB = sizeof(useMouse); + bData = PrfQueryProfileData(hini, APP_NAME, INIUSEMOUSE, &ulOpts, &ulCB); + if (bData) useMouse =(int)ulOpts[0]; + */ + /* ignore reading mouse cursor(real, relative or pixels). + Reason/bug: it does not switch the check mark in the menu, even + though it works as expected. + ulCB = sizeof(mouse_mode); + bData = PrfQueryProfileData(hini, APP_NAME, INIMOUSECOORD, &ulOpts, &ulCB); + if (bData) mouse_mode =(ULONG)ulOpts[0]; + */ + + PrfCloseProfile(hini); + + if (qPrintData.szPrinterName[0] == '\0') { + /* get default printer name */ + PrfQueryProfileString(HINI_PROFILE, + "PM_SPOOLER", + "PRINTER", + ";", + qPrintData.szPrinterName, + (long) sizeof qPrintData.szPrinterName); + if ((p=strchr(qPrintData.szPrinterName, ';')) != NULL) + *p = '\0'; + } + bShellPos = bPos; + return bPos; +} + + +/* +** save data in ini file +*/ +static void +SaveIni(HWND hWnd) +{ + SWP swp; + HINI hini; + ULONG ulOpts[5]; + HAB hab; + + hab = WinQueryAnchorBlock(hWnd); + hini = PrfOpenProfile(hab, szIniFile); + if (hini != NULLHANDLE) { + WinQueryWindowPos(hwndFrame, &swp); + ulPlotPos[0] = swp.x; + ulPlotPos[1] = swp.y; + ulPlotPos[2] = swp.cx; + ulPlotPos[3] = swp.cy; + PrfWriteProfileData(hini, APP_NAME, INISHELLPOS, &ulPlotPos, + sizeof(ulPlotPos)); + if (pausedata.pswp != NULL) + PrfWriteProfileData(hini, APP_NAME, INIPAUSEPOS, + pausedata.pswp, sizeof(SWP)); + ulOpts[0] =(ULONG)bLineTypes; + ulOpts[1] =(ULONG)bWideLines; + ulOpts[2] =(ULONG)bColours; + ulOpts[3] = ulPauseMode; + ulOpts[4] =(ULONG)bPopFront; + PrfWriteProfileData(hini, APP_NAME, INIOPTS, &ulOpts, sizeof(ulOpts)); + PrfWriteProfileData(hini, APP_NAME, INIFRAC, &qPrintData.xsize, + 4*sizeof(float)); + if (qPrintData.pdriv != NULL) + PrfWriteProfileData(hini, APP_NAME, INIPRDRIV, qPrintData.pdriv, + qPrintData.cbpdriv); + PrfWriteProfileString(hini, APP_NAME, INIPRPR, + qPrintData.szPrinterName[0] == '\0'? NULL: + qPrintData.szPrinterName); + PrfWriteProfileString(hini, APP_NAME, INIFONT, szFontNameSize); + ulOpts[0] =(ULONG)lCharWidth; + ulOpts[1] =(ULONG)lCharHeight; + PrfWriteProfileData(hini, APP_NAME, INICHAR, &ulOpts, sizeof(ulOpts)); + PrfWriteProfileData(hini, APP_NAME, INIKEEPRATIO, &bKeepRatio, + sizeof(bKeepRatio)); + + /* Mouse stuff */ + /* Ignore reading "Use mouse" --- no good idea to have mouse on by default. + Maybe it was the reason of some crashes(mouse init before draw). + PrfWriteProfileData(hini, APP_NAME, INIUSEMOUSE, &useMouse, sizeof(useMouse)); + */ + /* Do not write the mouse coord. mode. + PrfWriteProfileData(hini, APP_NAME, INIMOUSECOORD, &mouse_mode, sizeof(mouse_mode)); + */ + PrfCloseProfile(hini); + } else { + WinMessageBox(HWND_DESKTOP, + HWND_DESKTOP, + "Can't write ini file", + APP_NAME, + 0, + MB_OK | MB_ICONEXCLAMATION); + } +} + + +/* +** Paint the screen with current data +*/ +static void +DoPaint(HWND hWnd, HPS hps) +{ + static RECTL rectl; + + if (tidDraw != 0) { + /* already drawing - stop it; include the rectl now + being drawn in, in the update region; and return + without calling beginpaint so that the paint + message is resent */ + GpiSetStopDraw(hpsScreen, SDW_ON); + DosSleep(1); + WinInvalidateRect(hWnd, &rectl, TRUE); + return; + } + /* winbeginpaint here, so paint message is + not resent when we return, then spawn a + thread to do the drawing */ + WinBeginPaint(hWnd, hps, &rectl); /*rl */ + tidDraw = _beginthread(ThreadDraw, NULL, 32768, NULL); +} + + +/* +** Thread to draw plot on screen +*/ +static void +ThreadDraw(void* arg) +{ + HAB hab = WinInitialize(0); + + InitScreenPS(); + + DosRequestMutexSem(semHpsAccess,(ULONG) SEM_INDEFINITE_WAIT); + ScalePS(hpsScreen); + GpiSetStopDraw(hpsScreen, SDW_OFF); + GpiSetDrawingMode(hpsScreen, DM_DRAW); + GpiDrawChain(hpsScreen); + DrawRuler(); + DisplayStatusLine(hpsScreen); + WinEndPaint(hpsScreen); + DosReleaseMutexSem(semHpsAccess); + WinTerminate(hab); + tidDraw = 0; +#if 0 + /* This does not work here(why?!), thus moved to pm.trm: PM_text(); */ + gp_exec_event(GE_plotdone, mx, my, 0, 0, 0); /* enable again zoom and scale by mouse motions */ +#endif +} + + +/* +** Initialise the screen ps for drawing +*/ +HPS +InitScreenPS() +{ + RECTL rectClient; + int nColour = 0; + + GpiResetPS(hpsScreen, GRES_ATTRS); +#if 0 /* Use default background color(the original version) */ + GpiErase(hpsScreen); + WinQueryWindowRect(hApp,(PRECTL)&rectClient); +#else /* PM 14.3.2000: Use always white background */ + WinQueryWindowRect(hApp,(PRECTL)&rectClient); + WinFillRect(hpsScreen,&rectClient,CLR_WHITE); +#endif + if (bKeepRatio) { + double ratio = 1.560; + double xs = rectClient.xRight - rectClient.xLeft; + double ys = rectClient.yTop - rectClient.yBottom; + + if (ys > xs/ratio) { /* reduce ys to fit */ + rectClient.yTop = rectClient.yBottom +(int)(xs/ratio); + } else if (ys < xs/ratio) { /* reduce xs to fit */ + rectClient.xRight = rectClient.xLeft +(int)(ys*ratio); + } + } else + /* PM: why this -10? Otherwise the right axis is too close to + * the right border. However, this -10 should be taken into + * account for mousing! Or can it be inside a transformation? + */ + rectClient.xRight -= 10; + + GpiSetPageViewport(hpsScreen, &rectClient); + if (!bColours) { + int i; + + nColour = 16; + alColourTable[0] = 0xFFFFFF; + for (i=1; i0) */ + ULONG *rgbTable = NULL; /* current colour table (this is a 'virtual' palette) */ + + hab = WinInitialize(0); + DosEnterCritSec(); + pszPipeName = malloc(256); + pszSemName = malloc(256); + DosExitCritSec(); + strcpy(pszPipeName, "\\pipe\\"); + strcpy(pszSemName, "\\sem32\\"); + strcat(pszPipeName, szIPCName); + strcat(pszSemName, szIPCName); + + /* open a named pipe for communication with gnuplot */ + + rc = DosCreateNPipe(pszPipeName, + &hRead, + NP_ACCESS_DUPLEX|NP_NOINHERIT|NP_NOWRITEBEHIND , + 1|NP_WAIT|NP_READMODE_MESSAGE|NP_TYPE_MESSAGE, + PIPEBUF, + PIPEBUF, + 0xFFFFFFFF); + hev = 0; /* OK, gnuplot can try to open npipe ... */ + DosOpenEventSem(pszSemName, &hev); + DosPostEventSem(hev); + + /* attach to gnuplot */ + server: + + if (DosConnectNPipe(hRead) == 0L) { + WinPostMsg(hSysMenu, + MM_SETITEMATTR, + MPFROM2SHORT(SC_CLOSE, TRUE), + MPFROM2SHORT(MIA_DISABLED, MIA_DISABLED)); + + /* store graphics commands */ + /* use semaphore to prevent problems with drawing while reallocating + the command buffers */ + + DosRead(hRead, &ppidGnu, 4, &cbR); + + sprintf(mouseShareMemName, "\\SHAREMEM\\GP%i_Mouse_Input",(int)ppidGnu); + if (DosGetNamedSharedMem(&input_from_PM_Terminal, + mouseShareMemName, + PAG_WRITE)) { + /*now: gray menu items; old code: DosBeep(1440L,1000L); // indicates error */ + input_from_PM_Terminal = 0; + } + + semInputReady = 0; + /* semaphore 'semInputReady' must be open later in order to avoid problems */ + /* with the server mode; also 'bhave_*' init here because of server */ + + /* DosPostEventSem(semStartSeq); // once we've got pidGnu */ + WinPostMsg(hApp, WM_GPSTART, 0, 0); + + + hps = hpsScreen; + InitScreenPS(); + while (1) { + usErr=BufRead(hRead,buff, 1, &cbR); + if (usErr != 0) + break; + + if (breakDrawing) { + /* PM: drawing has been stopped(by Ctrl-C)... */ + hps = 0; /* ...thus drawings go to nowhere... */ + if (*buff == SET_TEXT) { /* ...unless 'plot finished' command */ + POINTL p; + hps = hpsScreen; /* drawings back to screen */ + breakDrawing = 0; + GpiSetColor(hps, RGB_TRANS(CLR_RED)); /* cross the unfinished plot */ + GpiBeginPath(hps, 1); + p.x = p.y = 0; GpiMove(hps, &p); + p.x = 19500; p.y = 12500; GpiLine(hps, &p); + p.x = 0; p.y = 12500; GpiMove(hps, &p); + p.x = 19500; p.y = 0; GpiLine(hps, &p); + GpiEndPath(hps); + GpiStrokePath(hps, 1, 0); + } + } + + switch (*buff) { + case SET_GRAPHICS : /* enter graphics mode */ + { + image_list_entry *ile; + + if (tidDraw != 0) { + /* already drawing - stop it */ + GpiSetStopDraw(hpsScreen, SDW_ON); + while (tidDraw != 0) DosSleep(1); + } + /* wait for access to command list and lock it */ + /* DosWaitEventSem(semDrawDone, SEM_INDEFINITE_WAIT); */ + /* DosEnterCritSec(); */ + DosRequestMutexSem(semHpsAccess,(ULONG) SEM_INDEFINITE_WAIT); + InitScreenPS(); + ScalePS(hps); + /* DosResetEventSem(semDrawDone, &ulCount); */ + GpiSetDrawingMode(hps, DM_DRAWANDRETAIN); + for (i=1;i<=iSeg;i++) + GpiDeleteSegment(hps, i); + iSeg = 1; + GpiOpenSegment(hps, iSeg); + /* DosExitCritSec(); */ + GpiSetLineEnd(hps, LINEEND_ROUND); + GpiSetLineWidthGeom(hps, linewidth); + GpiSetCharBox(hps, &sizBaseFont); + + /* free image buffers from previous plot, if any */ + while (image_list) { + DEBUG_IMAGE(("freeing image from last plot")); + ile = image_list; + image_list = ile->next; + free(ile->image); + free(ile->pbmi); + free(ile); + } + + break; + } + + case GR_QUERY : /* query terminal info */ + /* mouseable gnupmdrv sends greetings to mouseable PM terminal */ + if (mouseTerminal) { + int i=0xABCD; + + DosWrite(hRead, &i, sizeof(int), &cbR); + } + DosWrite(hRead, &lCharWidth, sizeof(int), &cbR); + DosWrite(hRead, &lCharHeight, sizeof(int), &cbR); + break; + + case SET_TEXT : /* leave graphics mode(graph completed) */ + if (bPath) { + GpiEndPath(hps); + GpiStrokePath(hps, 1, 0); + bPath = FALSE; + } + GpiCloseSegment(hps); + DrawRuler(); + DisplayStatusLine(hps); + /* DosPostEventSem(semDrawDone); */ + DosReleaseMutexSem(semHpsAccess); + WinPostMsg(hApp, WM_GNUPLOT, 0L, 0L); + break; + + case GR_RESET : + /* gnuplot has reset drivers, allow user to kill this */ + WinPostMsg(hSysMenu, + MM_SETITEMATTR, + MPFROM2SHORT(SC_CLOSE, TRUE), + MPFROM2SHORT(MIA_DISABLED,(USHORT)0)); + + /* if we are keeping us on the screen, wait for new connection */ + if (bServer||bPersist) { + DosDisConnectNPipe(hRead); + goto server; + } + break; + + case GR_RESUME : + { + /* resume after multiplot */ + DosRequestMutexSem(semHpsAccess,(ULONG) SEM_INDEFINITE_WAIT); + /* DosWaitEventSem(semDrawDone, SEM_INDEFINITE_WAIT); */ + iSeg++; + /* DosResetEventSem(semDrawDone, &ulCount); */ + GpiSetDrawingMode(hps, DM_DRAWANDRETAIN); + GpiOpenSegment(hps, iSeg); + break; + } + + case 's' : + /* suspend after multiplot */ + break; + + case GR_MOVE : /* move */ + case GR_DRAW : /* draw vector */ + { + LONG curr_color; + + if (pm3d_color >= 0) { + curr_color = GpiQueryColor(hps); + GpiSetColor(hps, pm3d_color); + } + if (*buff=='M') { + if (bPath) { + GpiEndPath(hps); + GpiStrokePath(hps, 1, 0); + bPath = FALSE; + } + } else { + if (bWideLines/*bWideLines*/ && !bPath) { + GpiBeginPath(hps, 1); + bPath = TRUE; + } + } + BufRead(hRead,&ptl.x, 2*sizeof(int), &cbR); + if ((*buff=='V') && bDots) + ptl.x += 5; + else if ((*buff=='M') && bDots) + ptl.x -= 5; + if (*buff == 'M') + LMove(hps, &ptl); + else + LLine(hps, &ptl); + + if (pm3d_color >= 0) + GpiSetColor(hps, curr_color); + } + break; + + case GR_PAUSE : /* pause */ + { + int len; + + pausing = 1; + BufRead(hRead, &len, sizeof(int), &cbR); + len = (len + sizeof(int) - 1) / sizeof(int); + if (len > 0){ /* get pause text */ + DosEnterCritSec(); + szPauseText = malloc(len*sizeof(int)); + DosExitCritSec(); + BufRead(hRead,szPauseText, len*sizeof(int), &cbR); + } + if (ulPauseMode != PAUSE_GNU) { + /* pause and wait for semaphore to be cleared */ + DosResetEventSem(semPause, &ulPause); + WinPostMsg(hApp, WM_PAUSEPLOT,(MPARAM) szPauseText, 0L); + DosWaitEventSem(semPause, SEM_INDEFINITE_WAIT); + } else { /* gnuplot handles pause */ + ulPauseReply = 2; + } + DosEnterCritSec(); + if (szPauseText != NULL) + free(szPauseText); + szPauseText = NULL; + DosExitCritSec(); + /* reply to gnuplot so it can continue */ + DosWrite(hRead, &ulPauseReply, sizeof(int), &cbR); + pausing = 0; + break; + } + + case GR_ENH_TEXT : /* write enhanced text */ + if (bPath) { + GpiEndPath(hps); + GpiStrokePath(hps, 1, 0); + bPath = FALSE; + } + { + unsigned int x, y, len; + unsigned int mode; + int textwidth, textheight; + char *str; + POINTL aptl[TXTBOX_COUNT]; + + /* read x, y, mode, len */ + BufRead(hRead, &x, sizeof(int), &cbR); + BufRead(hRead, &y, sizeof(int), &cbR); + BufRead(hRead, &mode, sizeof(int), &cbR); + BufRead(hRead, &len, sizeof(int), &cbR); + + DosEnterCritSec(); + len =(len+sizeof(int)-1)/sizeof(int); + if (len == 0) len = 1; /*?? how about read */ + str = malloc(len*sizeof(int)); + *str = '\0'; + DosExitCritSec(); + BufRead(hRead, str, len*sizeof(int), &cbR); + + GpiQueryTextBox(hps, strlen(str), str, TXTBOX_COUNT, aptl); + textwidth = aptl[TXTBOX_CONCAT].x; + textheight = aptl[TXTBOX_CONCAT].y; + + /* only display text if requested */ + if (mode & 0x01) { + LONG curr_color; + + if (pm3d_color >= 0) { + curr_color = GpiQueryColor(hps); + GpiSetColor(hps, pm3d_color); + } + ptl.x = (LONG) (x + multLineVert * (lVOffset / 4)); + ptl.y = (LONG) (y - multLineHor * (lVOffset / 4)); + + GpiSetBackMix(hps, BM_LEAVEALONE); + GpiCharStringAt(hps, &ptl, strlen(str), str); + + if (pm3d_color >= 0) + GpiSetColor(hps, curr_color); + } + + /* report back textwidth */ + DosWrite(hRead, &textwidth, sizeof(textwidth), &cbR); + DosWrite(hRead, &textheight, sizeof(textheight), &cbR); + + DosEnterCritSec(); + free(str); + DosExitCritSec(); + + break; + } + + case GR_TEXT : /* write text */ + /* read x, y, len */ + if (bPath) { + GpiEndPath(hps); + GpiStrokePath(hps, 1, 0); + bPath = FALSE; + } + { + unsigned int x, y, len; + int sw; + char *str; + LONG curr_color; +#ifndef PM_KEEP_OLD_ENHANCED_TEXT + POINTL aptl[TXTBOX_COUNT]; +#endif + BufRead(hRead,&x, sizeof(int), &cbR); + BufRead(hRead,&y, sizeof(int), &cbR); + BufRead(hRead,&len, sizeof(int), &cbR); + + DosEnterCritSec(); + len =(len+sizeof(int)-1)/sizeof(int); + if (len == 0) len = 1; /*?? how about read */ + str = malloc(len*sizeof(int)); + *str = '\0'; + DosExitCritSec(); + BufRead(hRead, str, len*sizeof(int), &cbR); + if (pm3d_color >= 0) { + curr_color = GpiQueryColor(hps); + GpiSetColor(hps, pm3d_color); + } + +#ifdef PM_KEEP_OLD_ENHANCED_TEXT + sw = QueryTextBox(hps, strlen(str), str); +#else + GpiQueryTextBox(hps, strlen(str), str, TXTBOX_COUNT, aptl); + sw = aptl[TXTBOX_BOTTOMRIGHT].x; +#endif + + switch (jmode) { + case LEFT: + sw = 0; + break; + case CENTRE: + sw /= -2; + break; + case RIGHT: + sw *= -1; + break; + } + + ptl.x = (LONG) (x + multLineHor * sw + multLineVert * (lVOffset / 4)); + ptl.y = (LONG) (y + multLineVert * sw - multLineHor * (lVOffset / 4)); + + GpiSetBackMix(hps, BM_LEAVEALONE); + +#ifdef PM_KEEP_OLD_ENHANCED_TEXT + if (bEnhanced) + CharStringAt(hps, ptl.x, ptl.y, strlen(str) , str); + else +#endif + GpiCharStringAt(hps, &ptl, strlen(str), str); + + if (pm3d_color >= 0) + GpiSetColor(hps, curr_color); + + DosEnterCritSec(); + free(str); + DosExitCritSec(); + + break; + } + + case SET_JUSTIFY : /* justify */ + BufRead(hRead, &jmode, sizeof(int), &cbR); + //printf( "SET_JUSTIFY: %i", jmode ); + break; + + case SET_ANGLE : /* text angle */ + { + int ta, t1; + GRADIENTL grdl; + + if (bPath) { + GpiEndPath(hps); + GpiStrokePath(hps, 1, 0); + bPath = FALSE; + } + BufRead(hRead, &ta, sizeof(int), &cbR); + t1 = ta % 360; + if (t1 < 0) + t1 += 360; + switch (t1) { + case 0: + grdl.x = 1L; + grdl.y = 0L; + multLineHor = 1; + multLineVert = 0; + break; + case 90: + grdl.x = 0L; + grdl.y = 1L; + multLineHor = 0; + multLineVert = 1; + break; + case 180: + grdl.x = -1L; + grdl.y = 0L; + multLineHor = -1; + multLineVert = 0; + break; + case 270: + grdl.x = 0L; + grdl.y = -1L; + multLineHor = 0; + multLineVert = -1; + break; + default: { + double t = t1 * M_PI/180; + + grdl.x = (LONG) (100 * cos(t)); + grdl.y = (LONG) (100 * sin(t)); + multLineHor = cos(t); + multLineVert = sin(t); + } /* default case */ + } /* switch(t1) */ + + GpiSetCharAngle(hps, &grdl); + break; + } + + case SET_LINE : /* line type */ + { + int lt, col; + + if (bPath) { + GpiEndPath(hps); + GpiStrokePath(hps, 1, 0); + bPath = FALSE; + } + BufRead(hRead,<, sizeof(int), &cbR); + /* linetype = -2 axes, -1 border, 0 arrows, all to 0 */ + col = lt; + if (lt == -2) GpiSetLineWidthGeom(hps, DEFLW*0.85); + else if (lt == -1) GpiSetLineWidthGeom(hps, DEFLW*0.6); + else GpiSetLineWidthGeom(hps, linewidth); + if (lt < 0) lt = 0; + lt =(lt%8); + col =(col+2)%16; + GpiLabel(hps, lLineTypes[lt]); + lOldLine = lt; + LType((bLineTypes) ? lt : 0); + /* GpiSetLineType(hps, (bLineTypes) ? lLineTypes[lt] : lLineTypes[0]); */ + /* maintain some flexibility here in case we don't want + * the model T option */ + if (bColours) + GpiSetColor(hps, RGB_TRANS(lCols[col])); + /* else GpiSetColor(hps, RGB_TRANS(CLR_BLACK)); */ + else + GpiSetColor(hps, RGB_TRANS(CLR_NEUTRAL)); + pm3d_color = -1; /* switch off using pm3d colours */ + break; + } + + case SET_FILLBOX : /* fill box */ + { + int style; + unsigned int x, y, w, h; + POINTL pt; + + BufRead(hRead,&style, sizeof(style), &cbR); + BufRead(hRead,&x, sizeof(x), &cbR); + BufRead(hRead,&y, sizeof(y), &cbR); + BufRead(hRead,&w, sizeof(w), &cbR); + BufRead(hRead,&h, sizeof(h), &cbR); + pt.x = x; + pt.y = y; + GpiMove(hpsScreen, &pt); + pt.x += w; + pt.y += h; + + switch(style & 0xf) { + + case FS_SOLID: + { + /* style == 1 --> fill with intensity according to filldensity */ + static const ULONG patternlist[] = { + PATSYM_NOSHADE, PATSYM_DENSE8, PATSYM_DENSE7, + PATSYM_DENSE6, PATSYM_DENSE5, PATSYM_DENSE4, + PATSYM_DENSE3, PATSYM_DENSE2, PATSYM_DENSE1, + PATSYM_SOLID + }; + unsigned pattern; + + pattern = (unsigned) trunc(9*((style >> 4) / 100.0) + 0.5); + if (pattern > 10) + pattern = 9; /* only 10 patterns in list */ + GpiSetMix(hps, FM_OVERPAINT); + GpiSetBackMix(hps, BM_OVERPAINT); + GpiSetPattern(hps, patternlist[pattern]); + break; + } + + case FS_PATTERN: + { + /* style == 2 --> fill with pattern according to fillpattern */ + /* the upper 3 nibbles of 'style' contain pattern number */ + static const ULONG patternlist[] = { + PATSYM_NOSHADE, PATSYM_DIAGHATCH, + PATSYM_HATCH, PATSYM_SOLID, + PATSYM_DIAG4, PATSYM_DIAG2, + PATSYM_DIAG3, PATSYM_DIAG1 + }; + unsigned pattern; + + pattern = (style >> 4) % 8; + GpiSetMix(hps, FM_OVERPAINT); + GpiSetBackMix(hps, BM_OVERPAINT); + GpiSetPattern(hps, patternlist[pattern]); + break; + } + + case FS_EMPTY: + default: + { + /* style == 0 or unknown --> fill with background color */ + GpiSetMix(hps, FM_OVERPAINT); + GpiSetBackMix(hps, BM_OVERPAINT); + //GpiSetColor(hps, RGB_TRANS(CLR_BACKGROUND)); // fixes 'with boxes' white on white + GpiSetPattern(hps, PATSYM_SOLID); + } + } + GpiBox(hps, DRO_FILL, &pt, 0,0); + break; + } + + case SET_LINEWIDTH : /* line width */ + { + int lw; + + if (bPath) { + GpiEndPath(hps); + GpiStrokePath(hps, 1, 0); + bPath = FALSE; + } + BufRead(hRead,&lw, sizeof(int), &cbR); + GpiSetLineWidthGeom(hps, DEFLW*lw/100); + linewidth = DEFLW*lw/100; + break; + } + + case SET_POINTMODE : /* points mode */ + { + int lt; + + BufRead(hRead,<, sizeof(int), &cbR); + /* 1: enter point mode, 0: exit */ + if (bLineTypes) { + if (lt==1) + LType(0); + else + LType(lOldLine); +#if 0 + if (lt == 1) + lOldLine = GpiSetLineType(hps, lLineTypes[0]); + else + GpiSetLineType(hps, lOldLine); +#endif /* 0 */ + } +#if 0 + if (lt == 1) + GpiSetLineWidthGeom(hps, 20); + else + GpiSetLineWidthGeom(hps, 50); +#endif /* 0 */ + bDots = lt; + } + break; + + case SET_FONT : /* set font */ + { + int len; + + BufRead(hRead, &len, sizeof(int), &cbR); + len = (len + sizeof(int) - 1) / sizeof(int); + + if (len == 0) { + SwapFont(hps, NULL); + strcpy(szCurrentFontNameSize, szFontNameSize); + } else { + char font[FONTBUF]; + char *p, *tmp, *str; + + tmp = str = malloc(len * sizeof(int)); + BufRead(hRead, str, len * sizeof(int), &cbR); + p = strchr(str, ','); + if (p==NULL) + strcpy(font, "10"); + else { + *p = '\0'; + strcpy(font, p+1); + } + strcat(font, "."); + /* allow abbreviation of some well known font names */ + FontExpand(str); + strcat(font, str); + free(tmp); + SwapFont(hps, font); + strcpy(szCurrentFontNameSize, font); + } /* else(len==0) */ + break; + } + + case GR_QUERY_FONT : /* query current font */ + { + int namelen; + + namelen = strlen(szCurrentFontNameSize); + DosWrite(hRead, &namelen, sizeof(int), &cbR); + DosWrite(hRead, szCurrentFontNameSize, namelen, &cbR); + /* FIXME: is padding necessary? */ + break; + } + + case SET_OPTIONS : /* set options */ + { + int len; + char *str; + + BufRead(hRead,&len, sizeof(int), &cbR); + len =(len + sizeof(int) - 1) / sizeof(int); + bWideLines = FALSE; /* reset options */ +#ifdef PM_KEEP_OLD_ENHANCED_TEXT + bEnhanced = FALSE; +#endif + if (len > 0) { + char *p; + + p = str = malloc(len * sizeof(int)); + BufRead(hRead, str, len * sizeof(int), &cbR); + while ((p=strchr(p,'-')) != NULL) { + ++p; + if (*p == 'w') + bWideLines = TRUE; +#ifdef PM_KEEP_OLD_ENHANCED_TEXT + if (*p == 'e') + bEnhanced = TRUE; +#endif + ++p; + } + free(str); + } + break; + } + + case SET_SPECIAL : /* set special options */ + { + char opt; +#ifdef PM_KEEP_OLD_ENHANCED_TEXT + char param; + static int prev_bEnhanced = 0; +#endif + + BufRead(hRead,&opt, 1, &cbR); + switch (opt) { +#ifdef PM_KEEP_OLD_ENHANCED_TEXT + case 'e': /* enhanced mode on, off and restore */ + BufRead(hRead,¶m, 1, &cbR); + switch (param) { + case '0': prev_bEnhanced = bEnhanced; + bEnhanced = 0; + break; + case '1': prev_bEnhanced = bEnhanced; + bEnhanced = 1; + break; + case '2': bEnhanced = prev_bEnhanced; + break; + } + break; +#endif + case 'c': /* set codepage */ + BufRead(hRead,&codepage, sizeof(codepage), &cbR); + break; + case '^': /* raise window */ + WinSetWindowPos( hwndFrame, HWND_TOP, 0,0,0,0, SWP_RESTORE|SWP_SHOW|SWP_ACTIVATE|SWP_ZORDER ) ; + WinSetFocus( HWND_DESKTOP, hApp ) ; + break; + case '_': /* lower window */ + WinSetWindowPos( hwndFrame, HWND_BOTTOM, 0,0,0,0, SWP_ZORDER ) ; + break; + } + break; + } + + case PUT_TMPTEXT : + { /* put_tmptext(int i, char c[]) term API */ + /* i = 0 at statusline, + 1,2: at corners of zoom box, with \r separating text */ + int where, l; + static char *text = NULL; + static int text_alloc = -1; + + /* Position of the "table" of values resulting from + * mouse movement(and clicks). Negative y value would + * position it at the top of the window---not + * implemented. */ + BufRead(hRead,&where, sizeof(int), &cbR); + BufRead(hRead,&l, sizeof(int), &cbR); + if (text_alloc < l) + text = realloc(text, text_alloc = l+10); + BufRead(hRead,&text[0], l, &cbR); + switch (where) { + case 0: + UpdateStatusLine(hps,text); + break; + case 1: + case 2: + break; /* not implemented */ + } + break; + } + + /* Implementation problems(I haven't understood that from + * .INF doc): what is the difference between + * GpiCreateLogColorTable and GpiCreatePalette? */ + case GR_MAKE_PALETTE : + { + unsigned char c; + int smooth_colors; + LONG lRetCount; + + /* read switch */ + BufRead(hRead, &c, sizeof(c), &cbR); + if (c == 0) { + /* gnuplot asks for the number of colours in palette */ + smooth_colors = (bPMPaletteMode ? (256 - nColors) : RGB_PALETTE_SIZE); + DosWrite(hRead, &smooth_colors, sizeof(int), &cbR); + DEBUG_COLOR(("GR_MAKE_PALETTE: max %i colours", smooth_colors)); + break; + } + + /* read the number of colours for the palette */ + BufRead(hRead, &smooth_colors, sizeof(int), &cbR); + free(rgbTable); + rgbTable = malloc(smooth_colors * sizeof(ULONG)); + + /* append new RGB table after */ + DEBUG_COLOR(("GR_MAKE_PALETTE: reading palette with %i colours", smooth_colors)); + BufRead(hRead, &rgbTable[bPMPaletteMode ? nColors : 0], + smooth_colors * sizeof(ULONG), &cbR); + + if (bPMPaletteMode) { + int i; + ULONG cclr; + + /* preserve the first nColors entries of current palette */ + /* retrieve the current table */ + lRetCount = GpiQueryLogColorTable(hps, 0L, 0L, nColors, alColourTable); + if ((lRetCount > 0) && (lRetCount != nColors)) /* ring for developers! */ + DosBeep(880, 777); + for (i=0; i 0x%x", (int)c, pm3d_color)); + break; + } + + case GR_SET_RGBCOLOR : + { + int rgb_color; + + BufRead(hRead, &rgb_color, sizeof(rgb_color), &cbR); + + /* Find an approximate color in the current palette */ + if (bPMPaletteMode) + pm3d_color = GpiQueryColorIndex(hps, 0, rgb_color); + else + pm3d_color = rgb_color; +#if 0 + { + int real_rgb = GpiQueryRGBColor(hps, LCOLOPT_REALIZED, pm3d_color); + DEBUG_COLOR(( "GR_SET_RGBCOLOR: req = %x nearest = %x index = %x", + rgb_color, real_rgb, pm3d_color )); + } +#endif + break; + } + + case GR_FILLED_POLYGON : + { + int points, x,y, i; + LONG curr_color; + POINTL p; + + BufRead(hRead, &points, sizeof(points), &cbR); + GpiSetPattern(hps, PATSYM_SOLID); + GpiSetBackMix(hps, BM_OVERPAINT); + if (pm3d_color >= 0) { + curr_color = GpiQueryColor(hps); + GpiSetColor(hps, pm3d_color); + } + + /* using colours defined in the palette */ + GpiBeginArea(hps, BA_BOUNDARY | BA_ALTERNATE); + for (i = 0; i < points; i++) { + BufRead(hRead, &x, sizeof(x), &cbR); + BufRead(hRead, &y, sizeof(y), &cbR); + p.x = x; p.y = y; + if (i) + GpiLine(hps, &p); + else + GpiMove(hps, &p); + } + GpiEndArea(hps); + if (pm3d_color >= 0) + GpiSetColor(hps, curr_color); + break; + } + + case GR_RGB_IMAGE : + { + unsigned int i, M, N, image_size; + POINTL corner[4]; + PBYTE image; + PBITMAPINFO2 pbmi; + POINTL points[4]; + LONG hits; + PERRINFO perriBlk; + image_list_entry *ile; + + BufRead(hRead, &M, sizeof(M), &cbR); + BufRead(hRead, &N, sizeof(N), &cbR); + for (i=0; i<4; i++) { + BufRead(hRead, &(corner[i].x), sizeof(int), &cbR); + BufRead(hRead, &(corner[i].y), sizeof(int), &cbR); + } + BufRead(hRead, &image_size, sizeof(image_size), &cbR); + DEBUG_IMAGE(("GR_IMAGE: M=%i, N=%i, size=%i", M, N, image_size)); + DEBUG_IMAGE(("GR_IMAGE: corner [0]=(%i,%i) [1]=(%i,%i)", corner[0].x, corner[0].y, corner[1].x, corner[1].y)); + image = (PBYTE) malloc(image_size); + /* FIXME: does not work if GNUBUF < image_size ! */ + BufRead(hRead, image, image_size, &cbR); + + points[0].x = corner[0].x; + points[0].y = corner[1].y; + points[1].x = corner[1].x; + points[1].y = corner[0].y; + points[2].x = points[2].y = 0; + points[3].x = M; + points[3].y = N; + + pbmi = (PBITMAPINFO2) calloc( sizeof(BITMAPINFOHEADER2), 1 ); + pbmi->cbFix = sizeof(BITMAPINFOHEADER2); + pbmi->cx = M; + pbmi->cy = N; + pbmi->cPlanes = 1; + pbmi->cBitCount = 24; + pbmi->ulCompression = BCA_UNCOMP; + hits = GpiDrawBits(hps, image, pbmi, 4, &points, ROP_SRCCOPY, BBO_IGNORE ); + +#if 0 + if (hits == GPI_ERROR) { + perriBlk = WinGetErrorInfo(hab); + if (perriBlk) { + PSZ pszOffset, pszErrMsg; + pszOffset = ((PSZ)perriBlk) + perriBlk->offaoffszMsg; + pszErrMsg = ((PSZ)perriBlk) + *((PULONG)pszOffset); + if (perriBlk->cDetailLevel >= 2) + pszErrMsg = ((PSZ)perriBlk) + ((PULONG)pszOffset)[1]; + DEBUG_IMAGE(("GpiDrawBits code=%x msg=%s", perriBlk->idError, pszErrMsg)); + // DEBUG_IMAGE(("GpiDrawBits code=%x", perriErrorInfo->idError)); + WinFreeErrorInfo(perriBlk); + } + } +#endif + + /* We have to keep the image and the image header in memory since + we use retained graphics */ + ile = (image_list_entry *) malloc(sizeof(image_list_entry)); + ile->next = image_list; + ile->pbmi = pbmi; + ile->image = image; + image_list = ile; + + break; + } + + case SET_RULER : { /* set_ruler(int x, int y) term API: x<0 switches ruler off */ + int x, y; + + BufRead(hRead, &x, sizeof(x), &cbR); + BufRead(hRead, &y, sizeof(y), &cbR); + DrawRuler(); /* remove previous drawing, if any */ + if (x < 0) { + ruler.on = 0; + break; + } + ruler.on = 1; + ruler.x = x; + ruler.y = y; + DrawRuler(); + break; + } + + case SET_CURSOR : { /* set_cursor(int c, int x, int y) term API */ + int c, x, y; + + BufRead(hRead, &c, sizeof(x), &cbR); + BufRead(hRead, &x, sizeof(x), &cbR); + BufRead(hRead, &y, sizeof(y), &cbR); + switch (c) { + case -2: { /* move mouse to the given point */ + RECTL rc; + POINTL pt; + + GpiQueryPageViewport(hpsScreen,&rc); + /* only distance is important */ + rc.xRight -= rc.xLeft; + rc.yTop -= rc.yBottom; + /* window => pixels coordinates */ + pt.x =(long int) ((x * (double) rc.xRight) / 19500.0); + pt.y =(long int) ((x * (double) rc.yTop) / 12500.0); + WinMapWindowPoints(hApp, HWND_DESKTOP, &pt, 1); + WinSetPointerPos(HWND_DESKTOP, pt.x, pt.y); + break; + } + case -1: /* start zooming; zooming cursor */ + zoombox.on = 1; + zoombox.from.x = zoombox.to.x = x; + zoombox.from.y = zoombox.to.y = y; + break; + case 0: /* standard cross-hair cursor */ + WinSetPointer(HWND_DESKTOP, + hptrCurrent =(useMouse + ?hptrCrossHair + :hptrDefault)); + break; + case 1: /* cursor during rotation */ + WinSetPointer(HWND_DESKTOP, hptrCurrent = hptrRotating); + break; + case 2: /* cursor during scaling */ + WinSetPointer(HWND_DESKTOP, hptrCurrent = hptrScaling); + break; + case 3: /* cursor during zooming */ + WinSetPointer(HWND_DESKTOP, hptrCurrent = hptrZooming); + break; + } + if (c>=0 && zoombox.on) { /* erase zoom box */ + DrawZoomBox(); + zoombox.on = 0; + } + break; + } + + case SET_CLIPBOARD : { /* set_clipboard(const char s[]) term API */ + int len; + char *s; + + BufRead(hRead, &len, sizeof(int), &cbR); + s = malloc(len + 1); + BufRead(hRead,s, len+1, &cbR); + TextToClipboard(s); + free(s); + break; + } + + case SET_MENU : /* update menu according to the gnuplot core + * settings, e.g.(un)checking menu items */ + if (mouseTerminal) { + /* we are connected to mouseable terminal */ + BufRead(hRead, &gpPMmenu, sizeof(gpPMmenu), &cbR); + if (useMouse != gpPMmenu.use_mouse) + WinSetPointer(HWND_DESKTOP, + hptrCurrent = (gpPMmenu.use_mouse + ?hptrCrossHair + :hptrDefault)); + useMouse = gpPMmenu.use_mouse; + gpPMmenu_update_req = 1; + } + break; + + case GR_MOUSECAPABLE : + /* notification of being connected to a mouse-enabled terminal */ + mouseTerminal = 1; + break; + + default : /* should handle error */ + break; + } + } + } + DosDisConnectNPipe(hRead); + WinPostMsg(hApp, WM_CLOSE, 0L, 0L); +} + + +static void +EditLineTypes(HWND hwnd, HPS hps, BOOL bDashed) +{ + int i; + + GpiSetDrawingMode(hps, DM_RETAIN); + GpiOpenSegment(hps, iSeg); + GpiSetEditMode(hps, SEGEM_REPLACE); + for (i=0; i<7; i++) { + while (GpiSetElementPointerAtLabel(hps, lLineTypes[i])) { + GpiOffsetElementPointer(hps, 1); + GpiSetLineType(hps, bDashed?lLineTypes[i]:lLineTypes[0]); + } + GpiSetElementPointer(hps, 0); + } + GpiSetEditMode(hps, SEGEM_INSERT); + GpiCloseSegment(hps); +} + + +#if 0 +/* +** Edit segment to change char cell(font size) +*/ +static void +EditCharCell(HPS hps, SIZEF *psize) +{ + int i; + LONG rl, rc; + SIZEF sizH, sizV; + int iVert = 0; + + sizH = *psize; + sizV.cx = sizH.cy; + sizV.cy = sizH.cx; + GpiSetDrawingMode(hps, DM_RETAIN); + GpiOpenSegment(hps, iSeg); + GpiSetEditMode(hps, SEGEM_REPLACE); + i=0; + while (GpiSetElementPointer(hps, i)) { + rc = GpiQueryElementPointer(hps); + if (rc != i) + break; + rl = GpiQueryElementType(hps, &rc, 0, NULL); + if (rc == 0x34 || rc == 0x74) { + LONG gdata; + + GpiQueryElement(hps, 5, 4, (PBYTE) &gdata); + if (gdata == 0) + iVert = 0; + else + iVert = 1; + } + else if (rc==0x33 || rc==0x03) + GpiSetCharBox(hps, iVert ? &sizV : &sizH); + ++i; + } + GpiSetEditMode(hps, SEGEM_INSERT); + GpiCloseSegment(hps); +} +#endif + +/* +** pull next plot command out of buffer read from GNUPLOT +*/ +static int +BufRead(HFILE hfile, void *buf, int nBytes, ULONG *pcbR) +{ + ULONG ulR, ulRR; + int rc; + static char buffer[GNUBUF]; + static char *pbuffer = buffer+GNUBUF, *ebuffer = buffer+GNUBUF; + + for (; nBytes > 0; nBytes--) { + if (pbuffer >= ebuffer) { + ulR = GNUBUF; + rc = DosRead(hfile, buffer, ulR, &ulRR); + if (rc != 0) + return rc; + if (ulRR == 0) + return 1; + pbuffer = buffer; + ebuffer = pbuffer+ulRR; + } + *(char*)buf++ = *pbuffer++; + } + return 0L; +} + + +#ifdef STANDARD_FONT_DIALOG + +/* +** Get a new font using standard font dialog +*/ +int +GetNewFont(HWND hwnd, HPS hps) +{ + static FONTDLG pfdFontdlg; /* Font dialog info structure */ + static int i1 =1; + static int iSize; + char szPtList[64]; + HWND hwndFontDlg; /* Font dialog window handle */ + char szFamilyname[FACESIZE]; + + if (i1) { + strcpy(pfdFontdlg.fAttrs.szFacename, strchr(szFontNameSize, '.') + 1); + strcpy(szFamilyname, strchr(szFontNameSize, '.') + 1); + sscanf(szFontNameSize, "%d", &iSize); + memset(&pfdFontdlg, 0, sizeof(FONTDLG)); + + pfdFontdlg.cbSize = sizeof(FONTDLG); + pfdFontdlg.hpsScreen = hps; + /* szFamilyname[0] = 0; */ + pfdFontdlg.pszFamilyname = szFamilyname; + pfdFontdlg.usFamilyBufLen = FACESIZE; + pfdFontdlg.fl = FNTS_HELPBUTTON | + FNTS_CENTER | FNTS_VECTORONLY | + FNTS_OWNERDRAWPREVIEW; + pfdFontdlg.clrFore = CLR_BLACK; + pfdFontdlg.clrBack = CLR_WHITE; + pfdFontdlg.usWeight = FWEIGHT_NORMAL; + pfdFontdlg.fAttrs.usCodePage = codepage; + pfdFontdlg.fAttrs.usRecordLength = sizeof(FATTRS); + } + sprintf(szPtList, "%d 8 10 12 14 18 24", iSize); + pfdFontdlg.pszPtSizeList = szPtList; + pfdFontdlg.fxPointSize = MAKEFIXED(iSize,0); + hwndFontDlg = WinFontDlg(HWND_DESKTOP, hwnd, &pfdFontdlg); + if (i1) { + pfdFontdlg.fl = FNTS_HELPBUTTON | + FNTS_CENTER | FNTS_VECTORONLY | + FNTS_INITFROMFATTRS; + i1=0; + } + if (hwndFontDlg &&(pfdFontdlg.lReturn == DID_OK)) { + iSize = FIXEDINT(pfdFontdlg.fxPointSize); + sprintf(szFontNameSize, "%d.%s", iSize, pfdFontdlg.fAttrs.szFacename); + return 1; + } else + return 0; +} + +#else + +/* +** Get a new font using standard font palette +*/ +int +GetNewFont(HWND hwnd, HPS hps) +{ + HOBJECT hObject; + ULONG ulView = 0; /* OPEN_DEFAULT */ + BOOL fSuccess = FALSE; + + hObject = WinQueryObject(""); + if (hObject != NULL) + { fSuccess = WinOpenObject(hObject, ulView, TRUE); } + if (fSuccess) return 1; + else return 0; +} + +#endif /* STANDARD_FONT_DIALOG */ + + +/* +** Handle termination signal to free up resources before +** termination. +*/ +void SigHandler(int sig) +{ + if (sig == SIGTERM) { + if (bPersist) { + DosKillThread(tidSpawn); + return; + } + DosEnterCritSec(); + DosKillThread(tidSpawn); + DosKillThread(tidDraw); + DosExitCritSec(); + exit(0); + } +} + + +#ifdef PM_KEEP_OLD_ENHANCED_TEXT + +/* disable debugging info */ +#define TEXT_DEBUG(x) /* fprintf x */ ; + +/* process a bit of string, and return the last character used. + * p is start of string + * brace is TRUE to keep processing to }, FALSE for do one character + * fontname & fontsize are obvious + * base is the current baseline + * widthflag is TRUE if the width of this should count, + * FALSE for zero width boxes + * showflag is TRUE if this should be shown, + * FALSE if it should not be shown(like TeX \phantom) + */ + +static char *starttext = NULL; +static int textlen = 0; +static BOOL bText = FALSE; +static int textwidth = 0; +static POINTL ptlText; +static FILE *ff; + +static char +*ParseText( + HPS hps, + char *p, + BOOL brace, + char *fontname, + int fontsize, int base, + BOOL widthflag, BOOL showflag) +{ + POINTL aptl[TXTBOX_COUNT]; + BOOL bChangeFont = FALSE; + TEXT_DEBUG((ff, "RECURSE WITH [%p] %s, %d %s %.1f %.1f %d %d\n", + p, p, brace, fontname, fontsize, base, + widthflag, showflag)); + + /* Start each recursion with a clean string */ +#if 0 + { + FILE *ff = fopen("deb","a"); + int i=textlen; + + for (i=0;i 0) { + GpiQueryTextBox(hps, textlen, starttext, TXTBOX_COUNT, aptl); + textwidth += aptl[TXTBOX_BOTTOMRIGHT].x * multLineHor; + textwidth += aptl[TXTBOX_BOTTOMRIGHT].y * multLineVert; + } + + if (bText) { + if (textlen > 0) { + GpiCharStringAt(hps, &ptlText, textlen, starttext); + ptlText.x += aptl[TXTBOX_CONCAT].x - multLineVert * base; + ptlText.y += aptl[TXTBOX_CONCAT].y + multLineHor * base; + } else { + ptlText.x -= multLineVert * base; + ptlText.y += multLineHor * base; + } + } + textlen = 0; + starttext = p; + + if (fontname != NULL) { + char szFont[FONTBUF]; + + sprintf(szFont, "%d.%s", fontsize, fontname); + SwapFont(hps, szFont); + bChangeFont = TRUE; + } + if (base != 0) + GpiSetCharBox(hps, &sizCurSubSup); + + for (; *p; ++p) { + int shift; + + switch (*p) { + case '}': + /*{{{ deal with it*/ + if (brace) { + brace = 0; + } + break; + /*}}}*/ + + case '_': + case '^': + /*{{{ deal with super/sub script*/ + shift = ((*p == '^') ? lSupOffset : lSubOffset); + p = ParseText(hps, p+1, FALSE, + NULL/*fontname*/, fontsize*0.8, + base+shift, widthflag, showflag); + break; + /*}}}*/ + + case '{': + { + char *savepos=NULL, save=0; + char *localfontname=fontname, ch; + char localfontbuf[FONTBUF]; + int recode=1; + int f=fontsize; + char *q=localfontbuf; + + /*{{{ recurse(possibly with a new font) */ + + TEXT_DEBUG((ff,"Dealing with {\n")); + if (*++p == '/') { + /* then parse a fontname, optional fontsize */ + while (*++p == ' ') + ; /* do nothing */ + if (*p=='-') { + recode=0; + while (*++p == ' ') + ; /* do nothing */ + } + localfontname = p; + while ((ch = *p) > ' ' && ch != '=') { + localfontname=localfontbuf; + if (*p=='_') + *q=' '; + else + *q=*p; + ++p;++q; + } + *q = '\0'; + FontExpand(localfontbuf); + save = *(savepos=p); + if (ch == '=') { + *p++ = '\0'; + /*{{{ get optional font size*/ + TEXT_DEBUG((ff,"Calling strtod(%s) ...", p)); + f = strtod(p, &p); + TEXT_DEBUG((ff,"Retured %.1f and %s\n", f, p)); + + if (!f) + f = fontsize; + + TEXT_DEBUG((ff,"Font size %.1f\n", f)); + /*}}}*/ + } else { + *p++ = '\0'; + f = fontsize; + } + + while (*p == ' ') + ++p; + + if (!(*localfontname)) { + localfontname = fontname; + if (f != fontsize) + localfontname = strchr(szFontNameSize, '.') + 1; + } + } /* if ('/') */ + /*}}}*/ + + TEXT_DEBUG((ff,"Before recursing, we are at [%p] %s\n", p, p)); + + p = ParseText(hps,p, TRUE, localfontname, f, base, widthflag, showflag); + + TEXT_DEBUG((ff,"BACK WITH %s\n", p)); + if (savepos) + /* restore overwritten character */ + *savepos = save; + + break; + } + + case '@' : + /*{{{ phantom box - prints next 'char', then restores currentpoint */ + + p = ParseText(hps, ++p, FALSE, NULL/*fontname*/, fontsize, + base, FALSE, showflag); + + break; + /*}}}*/ + + case '&' : + /*{{{ character skip - skips space equal to length of character(s) */ + + p = ParseText(hps, ++p, FALSE, NULL/*fontname*/, fontsize, + base, widthflag, FALSE); + + break; + /*}}}*/ + + case '\\': + { + char buffer[4]; /* should need only one char.. */ + char *q = buffer; + + *q = '\0'; + ParseText(hps,q, FALSE, NULL, fontsize, base, widthflag, showflag); + + /*{{{ is it an escape */ + /* special cases */ + if (p[1]=='\\' || p[1]=='{' || p[1]=='}') { + *q++=p[1]; + ++p; + } +#if 0 + else if (p[1] >= '0' && p[1] <= '7') { + /* up to 3 octal digits */ + int c = 0; + + c+=p[1]; + ++p; + if (p[1] >= '0' && p[1] <= '7') { + c = c * 8 + p[1]; + ++p; + if (p[1] >= '0' && p[1] <= '7') { + c = c * 8 + p[1]; + ++p; + } + } + *q++ = c; + break; + } +#endif /* 0 */ + + *q = '\0'; + textlen = 1; + starttext=buffer; + ParseText(hps,q, FALSE, NULL/*fontname*/, fontsize, + base, widthflag, showflag); + starttext=p+1; + textlen = 0; + /*}}}*/ + break; + } + + default: + ++textlen; + + /*}}}*/ + } /* switch(character) */ + + /* like TeX, we only do one character in a recursion, unless it's + * in braces + */ + if (!brace) + break; + } + + if (textlen > 0) { + GpiQueryTextBox(hps, textlen, starttext, TXTBOX_COUNT, aptl); + if (widthflag) { + textwidth += aptl[TXTBOX_BOTTOMRIGHT].x * multLineHor; + textwidth += aptl[TXTBOX_BOTTOMRIGHT].y * multLineVert; + } + } + if (bText) { + if (textlen > 0) { + if (showflag) + GpiCharStringAt(hps, &ptlText, textlen, starttext); + if (widthflag) { + ptlText.x += aptl[TXTBOX_CONCAT].x; + ptlText.y += aptl[TXTBOX_CONCAT].y; + } + } + if (base != 0) { + ptlText.x += multLineVert * base; + ptlText.y -= multLineHor * base; + } + } + if (bChangeFont) { + SwapFont(hps, NULL); + bChangeFont = FALSE; + } + if (base != 0) + GpiSetCharBox(hps, &sizBaseFont); + + textlen = 0; + starttext = p+1; + return p; +} + + +static void +CharStringAt(HPS hps, int x, int y, int len, char *str) +{ + /* flush any pending graphics(all the XShow routines do this...) */ + char *fontname; + int fontsize; + + if (!strlen(str)) + return; + + /* set up the globals */ + + ptlText.x = x; + ptlText.y = y; + bText = TRUE; + starttext = NULL; + textlen = 0; + textwidth = 0; + sscanf(szFontNameSize, "%d", &fontsize); + fontname = strchr(szFontNameSize, '.') + 1; + + while (*(str = ParseText(hps, str, TRUE, NULL, + fontsize, + 0.0, TRUE, TRUE))) + ; /* do nothing */ +} + + +static int +QueryTextBox(HPS hps, int len, char *str) +{ + char *fontname; + int fontsize; + + if (!strlen(str)) + return 0; + + /* set up the globals */ + bText = FALSE; + starttext = NULL; + textlen = 0; + textwidth = 0; + sscanf(szFontNameSize, "%d", &fontsize); + fontname = strchr(szFontNameSize, '.') + 1; + + while (*(str = ParseText(hps, str, TRUE, NULL, + fontsize, + 0.0, TRUE, TRUE))) + ; /* do nothing */ + + return textwidth; +} + +#endif + + +void +FontExpand(char *name) +{ + if (strcmp(name,"S") == 0) + strcpy(name, "Symbol Set"); + if (strcmp(name,"Symbol") == 0) + strcpy(name, "Symbol Set"); + else if (strcmp(name,"H") == 0) + strcpy(name, "Helvetica"); + else if (strcmp(name,"T") == 0) + strcpy(name, "Times New Roman"); + else if (strcmp(name,"C") == 0) + strcpy(name, "Courier"); +} + + +/*=======================================*/ + +static POINTL pCur; +static int iLinebegin = 1; +static int iLtype = 0; +static int iState = 0; +static double togo = 0.0; +static int iPatt[8][9] = { + { 0, 0, 0, 0, 0, 0, 0, 0, 0 }, + { 300, 200, -1, 0, 0, 0, 0, 0, 0 }, + { 150, 150, -1, 0, 0, 0, 0, 0, 0 }, + { 300, 200, 150, 200, -1, 0, 0, 0, 0 }, + { 500, 200, -1, 0, 0, 0, 0, 0, 0 }, + { 300, 200, 150, 200, 150, 200, -1, 0, 0 }, + { 300, 200, 150, 200, 150, 200, 150, 200, -1 }, + { 500, 200, 150, 200, -1, 0, 0, 0, 0 } +}; + + +void +LMove(HPS hps, POINTL *p) +{ + double ds, dx, dy; + + if (iLinebegin) { + pCur = *p; + GpiMove(hps, p); + } else if (iLtype == 0) + GpiMove(hps, p); + else { + dx = p->x - pCur.x; + dy = p->y - pCur.y; + ds = sqrt(dx*dx + dy*dy); + dx /= ds; dy /= ds; + while (ds > 0.0) { + if (ds < togo) { + togo -= ds; + ds = 0.0; + GpiMove(hps, p); + pCur = *p; + } else { + POINTL pn; + + pn.x = pCur.x + togo * dx; + pn.y = pCur.y + togo * dy; + GpiMove(hps, &pn); + pCur = pn; + ds -= togo; + iState++; + if (iPatt[iLtype][iState] < 0) { + togo = iPatt[iLtype][0]; + iState = 0; + } else + togo = iPatt[iLtype][iState]; + } + } + } +} + + +void +LLine(HPS hps, POINTL *p) +{ + double ds, dx, dy; + + if (iLinebegin) + iLinebegin = 0; + + if (iLtype == 0) + GpiLine(hps, p); + else { + dx = p->x - pCur.x; + dy = p->y - pCur.y; + ds = sqrt(dx*dx + dy*dy); + dx /= ds; dy /= ds; + while (ds > 0.0) { + if (ds < togo) { + togo -= ds; + ds = 0.0; + if (iState & 1) + GpiMove(hps, p); + else + GpiLine(hps, p); + pCur = *p; + } else { + POINTL pn; + + pn.x = pCur.x + togo * dx; + pn.y = pCur.y + togo * dy; + if (iState & 1) + GpiMove(hps, &pn); + else + GpiLine(hps, &pn); + pCur = pn; + ds -= togo; + iState++; + if (iPatt[iLtype][iState] < 0) { + togo = iPatt[iLtype][0]; + iState = 0; + } else + togo = iPatt[iLtype][iState]; + } + } + } +} + +void +LType(int iType) +{ + iLinebegin = 1; + if (iType > 7) + iType = 0; + iLtype = iType; + iState = 0; + togo = iPatt[iLtype][0]; +} + + +/* Now routines for mouse etc. */ + +static void +TextToClipboard(PCSZ szTextIn) +{ + /* copy string given by szTextIn to the clipboard */ + PSZ szTextOut = NULL; + ULONG ulRC = DosAllocSharedMem( + (PVOID*) &szTextOut, NULL, + strlen(szTextIn) + 1, + PAG_READ | PAG_WRITE | PAG_COMMIT | OBJ_GIVEABLE); + + if (!ulRC) { + HAB hab = 0; + + strcpy(szTextOut, szTextIn); + WinOpenClipbrd(hab); + WinEmptyClipbrd(hab); + WinSetClipbrdData(hab,(ULONG) szTextOut, CF_TEXT, CFI_POINTER); + WinCloseClipbrd(hab); + } +} + + +/* Draw the ruler +*/ +static void +DrawRuler() +{ + POINTL p; + + if (!ruler.on || ruler.x < 0) + return; + /* GpiSetColor(hpsScreen, RGB_TRANS(COLOR_RULER)); */ + GpiSetColor(hpsScreen, RGB_TRANS(CLR_RED)); + GpiSetLineWidth(hpsScreen, LINEWIDTH_THICK); + GpiSetMix(hpsScreen, FM_INVERT); + /*GpiBeginPath(hpsScreen, 1); // will this help? I don't know, but makes thic cross */ + + p.x = 0; + p.y = ruler.y; + GpiMove(hpsScreen, &p); + + p.x = 19500; + GpiLine(hpsScreen, &p); + + p.x = ruler.x; + p.y = 0; + GpiMove(hpsScreen, &p); + + p.y = 12500; + GpiLine(hpsScreen, &p); + + /*GpiEndPath(hpsScreen); */ + /*GpiStrokePath(hpsScreen, 1, 0); */ +} + + +#if 0 +/* This routine recalculates mouse/pointer position [mx,my] in [in pixels] +current window to the real/true [x,y] coordinates of the plotted graph. +*/ +void +MousePosToGraphPos( + double *x, double *y, + HWND hWnd, + SHORT mx, SHORT my, + ULONG mouse_mode) +{ + RECTL rc; + + if (mouse_mode == MOUSE_COORDINATES_PIXELS) { + *x = mx; + *y = my; + return; + } + + /* Rectangle where we are moving: viewport, not the full window! */ + GpiQueryPageViewport(hpsScreen, &rc); + + /* only distance is important */ + rc.xRight -= rc.xLeft; + rc.yTop -= rc.yBottom; + + if (mouse_mode == MOUSE_COORDINATES_SCREEN) { + *x =(double) mx / rc.xRight; + *y =(double) my / rc.yTop; + return; + } + + /* px=px(mx); mouse=>gnuplot driver coordinates */ + *x = mx * 19500.0 / rc.xRight; + *y = my * 12500.0 / rc.yTop; + + /* main job of transformation, which is not device dependent */ + MousePosToGraphPosReal(x, y); +} +#endif + + +/* + * This routine recalculates mouse/pointer position [mx,my] in [in pixels] + * current window to the viewport coordinates + */ +static void +MousePosToViewport(int *x, int *y, SHORT mx, SHORT my) +{ + RECTL rc; + + /* Rectangle where we are moving: viewport, not the full window! */ + GpiQueryPageViewport(hpsScreen, &rc); + + rc.xRight -= rc.xLeft; + rc.yTop -= rc.yBottom; /* only distance is important */ + + /* px=px(mx); mouse=>gnuplot driver coordinates */ + *x =(int)(mx * 19500.0 / rc.xRight + 0.5); + *y =(int)(my * 12500.0 / rc.yTop + 0.5); +} + + +/* + * This routine gets the mouse/pointer position in the current window and + * recalculates it to the viewport coordinates + */ +static void +GetMousePosViewport(HWND hWnd, int *mx, int *my) +{ + POINTL p; + + WinQueryPointerPos(HWND_DESKTOP, &p); /* this is position wrt desktop */ + WinMapWindowPoints(HWND_DESKTOP, hWnd, &p, 1); /* pos. wrt our window in pixels */ + MousePosToViewport(mx,my,p.x,p.y); +} + + +/* + * Status line previous and current text: + */ +static char *sl_curr_text = NULL; + +/* + * Display the status line by the text + */ +static void +DisplayStatusLine(HPS hps) +{ + POINTL pt; + + if (!sl_curr_text) + return; + GpiSetColor(hps, RGB_TRANS(COLOR_MOUSE)); /* set text color */ + GpiSetCharMode(hps, CM_MODE1); + pt.x = 2; + pt.y = 2; + GpiSetMix(hps, FM_INVERT); + /* GpiSetMix(hps, FM_XOR); */ + GpiCharStringAt(hps, &pt,(long) strlen(sl_curr_text), sl_curr_text); +} + + +/* + * Update the status line by the text; firstly erase the previous text + */ +static void +UpdateStatusLine(HPS hps, char *text) +{ + if (gpPMmenu_update_req) + gpPMmenu_update(); /* check for updated menu */ + if (sl_curr_text) { + /* erase the previous text */ + DisplayStatusLine(hps); + free(sl_curr_text); + } + if (!text || !*text) + sl_curr_text = 0; + else { + /* display new text */ + sl_curr_text = strdup(text); + DisplayStatusLine(hps); + } +} + + +/* + * Graphics part SET_GRAPHICS or anything else required to update menu according to + * the items in gpPMmenu + */ +static void +gpPMmenu_update() +{ +#if 0 + if (!gpPMmenu_update_req) + return; +#endif + + ChangeCheck(hApp, IDM_USEMOUSE, useMouse ? IDM_USEMOUSE:0); + WinEnableMenuItem(/* can this situation be unzoomed back? */ + WinWindowFromID(WinQueryWindow(hApp, QW_PARENT), FID_MENU), + IDM_MOUSE_UNZOOM,(gpPMmenu.where_zoom_queue & 1) ? TRUE : FALSE); + WinEnableMenuItem(/* can this situation be unzoomed to the beginning? */ + WinWindowFromID(WinQueryWindow(hApp, QW_PARENT), FID_MENU), + IDM_MOUSE_UNZOOMALL,(gpPMmenu.where_zoom_queue & 2) ? TRUE : FALSE); + if ( + WinEnableMenuItem(/* can this situation be zoomed next? */ + WinWindowFromID(WinQueryWindow(hApp, QW_PARENT), FID_MENU), + IDM_MOUSE_ZOOMNEXT,(gpPMmenu.where_zoom_queue & 4) ? TRUE : FALSE) + == TRUE) gpPMmenu_update_req = 0; + ChangeCheck(hApp, IDM_MOUSE_POLAR_DISTANCE, gpPMmenu.polar_distance?IDM_MOUSE_POLAR_DISTANCE:0); +} + + +static void +DrawZoomBox() +{ + if (!zoombox.on) + return; + GpiSetLineWidth(hpsScreen, LINEWIDTH_NORMAL); + GpiSetLineType(hpsScreen,LINETYPE_SHORTDASH); + GpiSetMix(hpsScreen,FM_INVERT); + GpiMove(hpsScreen, &zoombox.from); + GpiBox(hpsScreen, DRO_OUTLINE, &zoombox.to, 0,0); + GpiSetLineType(hpsScreen,LINETYPE_DEFAULT); +} + +/* eof gclient.c */ +