This is gclient.c in view mode; [Download] [Up]
#ifdef INCRCSDATA static char RCSid[]="$Id: gclient.c%v 3.38.2.96 1993/03/15 21:39:29 woo Exp woo $" ; #endif /**************************************************************************** PROGRAM: Gnupmdrv MODULE: gclient.c This file contains the client window procedures for Gnupmdrv ****************************************************************************/ /* * PM driver for GNUPLOT * Copyright (C) 1992 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 modified code. Modifications are to be distributed * as patches to released version. * * This software is provided "as is" without express or implied warranty. * * * AUTHOR * * Gnuplot driver for OS/2: Roger Fearick * * Send your comments or suggestions to * info-gnuplot@dartmouth.edu. * This is a mailing list; to join it send a note to * info-gnuplot-request@dartmouth.edu. * Send bug reports to * bug-gnuplot@dartmouth.edu. **/ #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 #include <os2.h> #include <string.h> #include <stdio.h> #include <stdlib.h> #include <unistd.h> #include <process.h> #include "gnupmdrv.h" /*==== g l o b a l d a t a ================================================*/ extern char szIPCName[] ; /* name used in IPC with gnuplot */ /*==== l o c a l d a t a ==================================================*/ #define GNUBUF 1024 /* buffer for gnuplot commands */ #define PIPEBUF 4096 /* size of pipe buffers */ #define CMDALLOC 4096 /* command buffer allocation increment (ints) */ #define ENVSIZE 2048 /* size of environment */ #define GNUPAGE 4096 /* size of gnuplot page in pixels (driver dependent) */ #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 */ static HWND hWndstart ; /* used for errors in startup */ static ULONG pidGnu=0L ; /* gnuplot session id */ static ULONG ppidGnu=0L ; /* gnuplot pid */ static HPS hpsScreen ; /* screen pres. space */ static HSWITCH hSwitch = 0 ; /* switching between windows */ static SWCNTRL swGnu ; static BOOL bLineTypes = FALSE ; static BOOL bLineThick = FALSE ; static BOOL bColours = TRUE ; static BOOL bShellPos = FALSE ; static BOOL bPlotPos = FALSE ; static ULONG ulPlotPos[4] ; static ULONG ulShellPos[4] ; static char szFontNameSize[FONTBUF] ; static char achPrinterName[128] = "" ; static PRQINFO3 infPrinter = { "" } ; static HMTX semCommands ; static HEV semStartSeq ; /* semaphore to start things in right sequence */ static HEV semPause ; static ULONG ulPauseReply = 1 ; static ULONG ulPauseMode = PAUSE_DLG ; /* commands from gnuplot come via this ... */ static HPIPE hRead = 0L ; /* stuff for screen-draw thread control */ static BOOL bExist ; static BOOL bStopDraw ; static HEV semDrawDone ; static HEV semStartDraw ; /* command buffer */ static int ncalloc = 0 ; static int ic = 0 ; static volatile int *commands = NULL ; /*==== f u n c t i o n s =====================================================*/ int DoPrint( HWND ) ; MRESULT WmClientCmdProc( HWND , ULONG, MPARAM, MPARAM ) ; void ChangeCheck( HWND, USHORT, USHORT ) ; BOOL QueryIni( HAB ) ; static void SaveIni( void ) ; static void ThreadDraw( void ) ; static void DoPaint( HWND, HPS ) ; static void Display( void ) ; void SelectFont( HPS, char *, short ); static void ReadGnu( void ) ; static void WaitEnd( void ) ; static void AllocMore() ; static int BufRead( HFILE, void*, int, PULONG ) ; int GetNewFont( HWND, HPS ) ; /*==== c o d e ===============================================================*/ MRESULT EXPENTRY DisplayClientWndProc(HWND hWnd, ULONG message, MPARAM mp1, MPARAM mp2) /* ** Window proc for main window ** -- passes most stuff to active child window via WmClientCmdProc ** -- passes DDE messages to DDEProc */ { HDC hdcScreen ; SIZEL sizlPage ; TID tidDraw, tidSpawn ; char *pp ; ULONG ulID ; ULONG ulFlag ; char szErrs[128] ; switch (message) { case WM_CREATE: // set initial values ChangeCheck( hWnd, IDM_LINES_THICK, bLineThick?IDM_LINES_THICK:0 ) ; ChangeCheck( hWnd, IDM_LINES_SOLID, bLineTypes?0:IDM_LINES_SOLID ) ; ChangeCheck( hWnd, IDM_COLOURS, bColours?IDM_COLOURS:0 ) ; hWndstart = hWnd ; /* used in ReadGnu for errors */ // disable close from system menu (close only from gnuplot) WinSendMsg( WinWindowFromID( WinQueryWindow( hWnd, QW_PARENT ), FID_SYSMENU ), MM_SETITEMATTR, MPFROM2SHORT(SC_CLOSE, TRUE ), MPFROM2SHORT(MIA_DISABLED, MIA_DISABLED ) ) ; // setup semaphores DosCreateMutexSem( NULL, &semCommands, 0L, 0L ) ; DosCreateEventSem( NULL, &semStartDraw, 0L, 0L ) ; DosCreateEventSem( NULL, &semDrawDone, 0L, 0L ) ; DosCreateEventSem( NULL, &semStartSeq, 0L, 0L ) ; DosCreateEventSem( NULL, &semPause, 0L, 0L ) ; bStopDraw = FALSE ; bExist = TRUE ; // create a dc and hps to draw on the screen hdcScreen = WinOpenWindowDC( hWnd ) ; sizlPage.cx = GNUPAGE ; sizlPage.cy = GNUPAGE ; hpsScreen = GpiCreatePS( hab, hdcScreen, &sizlPage, PU_ARBITRARY|GPIT_MICRO|GPIA_ASSOC) ; // spawn a thread to do the drawing DosCreateThread( &tidDraw, (PFNTHREAD)ThreadDraw, 0L, 0L, 8192L ) ; // then spawn server for GNUPLOT ... DosCreateThread( &tidSpawn, (PFNTHREAD)ReadGnu, 0L, 0L, 8192L ) ; DosWaitEventSem( semStartSeq, SEM_INDEFINITE_WAIT ) ; // get details of command-line window hSwitch = WinQuerySwitchHandle( 0, ppidGnu ) ; WinQuerySwitchEntry( hSwitch, &swGnu ) ; // set size of this window WinSetWindowPos( WinQueryWindow( hWnd, QW_PARENT ), HWND_TOP, ulShellPos[0], ulShellPos[1], ulShellPos[2], ulShellPos[3], bShellPos?SWP_SIZE|SWP_MOVE|SWP_SHOW|SWP_ACTIVATE:SWP_SHOW|SWP_ACTIVATE ) ; // clear screen DosPostEventSem( semDrawDone ) ; break ; case WM_COMMAND: return WmClientCmdProc( hWnd , message , mp1 , mp2 ) ; case WM_CLOSE: 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: DoPaint( hWnd, hpsScreen ) ; break ; case WM_SIZE : WinInvalidateRect( hWnd, NULL, TRUE ) ; break ; case WM_PRESPARAMCHANGED: pp = malloc(FONTBUF) ; if( WinQueryPresParam( hWnd, PP_FONTNAMESIZE, 0, &ulID, FONTBUF, pp, QPF_NOINHERIT ) != 0L ) { strcpy( szFontNameSize, pp ) ; WinInvalidateRect( hWnd, NULL, TRUE ) ; } free(pp) ; 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 WinSetWindowPos( hwndFrame, HWND_TOP, 0,0,0,0, SWP_ACTIVATE|SWP_ZORDER ) ; WinInvalidateRect( hWnd, NULL, TRUE ) ; return 0L ; case WM_PAUSEPLOT: /* put pause message on screen, or enable 'continue' button */ if( ulPauseMode == PAUSE_DLG ) { WinLoadDlg( HWND_DESKTOP, hWnd, (PFNWP)PauseMsgDlgProc, 0L, IDD_PAUSEBOX, (char*)mp1 ) ; } 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 ; default: /* Passes it on if unproccessed */ return (WinDefWindowProc(hWnd, message, mp1, mp2)); } return (NULL); } MRESULT WmClientCmdProc(HWND hWnd, ULONG message, MPARAM mp1, MPARAM mp2) /* ** Handle client window command (menu) messages ** -- mostly passed on to active child window ** */ { ULONG usDlg ; extern HWND hApp ; static ulPauseItem = IDM_PAUSEDLG ; switch( (USHORT) SHORT1FROMMP( mp1 ) ) { case IDM_ABOUT : /* show the 'About' box */ WinDlgBox( HWND_DESKTOP, hWnd , (PFNWP)About , 0L, ID_ABOUT, NULL ) ; break ; case IDM_PRINT : /* print plot */ if( SetupPrinter( hWnd, achPrinterName, &infPrinter ) ) WinPostMsg( hWnd, WM_USER_PRINT_BEGIN, (MPARAM)&infPrinter, 0L ) ; break ; case IDM_PRINTSETUP : /* select printer */ WinDlgBox( HWND_DESKTOP, hWnd , (PFNWP)QPrintersDlgProc, 0L, IDD_QUERYPRINT, achPrinterName ) ; break ; case IDM_LINES_THICK: // change line setting bLineThick = !bLineThick ; ChangeCheck( hWnd, IDM_LINES_THICK, bLineThick?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 ) ; 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_FONTS: if( GetNewFont( hWnd, hpsScreen ) ) WinInvalidateRect( hWnd, NULL, TRUE ) ; break ; case IDM_SAVE : SaveIni() ; break ; case IDM_COMMAND: /* go back to GNUPLOT command window */ WinSwitchToProgram( hSwitch ) ; break ; case IDM_CONTINUE: WinPostMsg( hWnd, WM_PAUSEEND, 1L, 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 ; default : return WinDefWindowProc( hWnd, message, mp1, mp2 ) ; } return( NULL ) ; } void ChangeCheck( HWND hWnd , USHORT wItem1 , USHORT wItem2 ) /* ** Utility function: ** ** move check mark from menu item 1 to item 2 */ { HWND hMenu ; 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 ) ) ; } BOOL QueryIni( HAB hab ) /* ** Query INI file */ { BOOL bPos, bData ; ULONG ulOpts[4] ; HINI hini ; ULONG ulCB ; char *p ; // get default printer name PrfQueryProfileString( HINI_PROFILE, "PM_SPOOLER", "PRINTER", ";", achPrinterName, (long) sizeof achPrinterName ) ; if( (p=strchr( achPrinterName, ';' )) != NULL ) *p = '\0' ; // read gnuplot ini file hini = PrfOpenProfile( hab, GNUINI ) ; ulCB = sizeof( ulShellPos ) ; bPos = PrfQueryProfileData( hini, APP_NAME, INISHELLPOS, &ulShellPos, &ulCB ) ; ulCB = sizeof( ulOpts ) ; bData = PrfQueryProfileData( hini, APP_NAME, INIOPTS, &ulOpts, &ulCB ) ; if( bData ) { bLineTypes = (BOOL)ulOpts[0] ; bLineThick = (BOOL)ulOpts[1] ; bColours = (BOOL)ulOpts[2] ; ulPauseMode = ulOpts[3] ; } else { bLineTypes = FALSE ; /* default values */ bLineThick = FALSE ; bColours = TRUE ; ulPauseMode = 1 ; } PrfQueryProfileString( hini, APP_NAME, INIFONT, INITIAL_FONT, szFontNameSize, FONTBUF ) ; PrfCloseProfile( hini ) ; bShellPos = bPos ; return bPos ; } static void SaveIni( ) /* ** save data in ini file */ { SWP swp ; HINI hini ; ULONG ulOpts[4] ; hini = PrfOpenProfile( hab, GNUINI ) ; 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) ) ; /* WinQueryWindowPos( swGnu.hwnd, &swp ) ; ulPlotPos[0] = swp.x ; ulPlotPos[1] = swp.y ; ulPlotPos[2] = swp.cx ; ulPlotPos[3] = swp.cy ; PrfWriteProfileData( hini, APP_NAME, INIPLOTPOS, &ulPlotPos, sizeof(ulPlotPos) ) ; */ ulOpts[0] = (ULONG)bLineTypes ; ulOpts[1] = (ULONG)bLineThick ; ulOpts[2] = (ULONG)bColours ; ulOpts[3] = ulPauseMode ; PrfWriteProfileData( hini, APP_NAME, INIOPTS, &ulOpts, sizeof(ulOpts) ) ; PrfWriteProfileString( hini, APP_NAME, INIFONT, szFontNameSize ) ; PrfCloseProfile( hini ) ; } static void DoPaint( HWND hWnd, HPS hps ) /* ** Paint the screen with current data */ { RECTL rectClient ; ULONG ulCount ; bStopDraw = TRUE ; // stop any drawing in progress and wait for // thread to signal completion DosWaitEventSem( semDrawDone, SEM_INDEFINITE_WAIT ) ; DosResetEventSem( semDrawDone, &ulCount ) ; WinBeginPaint( hWnd , hps, NULL ) ; DosPostEventSem( semStartDraw ) ; // start drawing } static void ThreadDraw( ) /* ** Thread to draw plot */ { HAB hab ; RECTL rectClient ; ULONG ulCount ; /* initialize and wait until ready to draw */ hab = WinInitialize( 0 ) ; /* ok - draw until window is destroyed */ while( bExist ) { // indicate access to window DosWaitEventSem( semStartDraw, SEM_INDEFINITE_WAIT ) ; DosResetEventSem( semStartDraw, &ulCount ) ; // will be set TRUE if we decide to stop in the middle, but now bStopDraw = FALSE ; GpiResetPS( hpsScreen, GRES_ALL ) ; WinQueryWindowRect( hApp, (PRECTL)&rectClient ) ; GpiSetPageViewport( hpsScreen, &rectClient ) ; WinFillRect( hpsScreen, &rectClient, CLR_WHITE ) ; ScalePS( hpsScreen, &rectClient, 0 ) ; PlotThings( hpsScreen, 0L ) ; // ok, say that we did it WinEndPaint( hpsScreen ) ; DosPostEventSem( semDrawDone ) ; } WinTerminate( hab ) ; } enum JUSTIFY { LEFT, CENTRE, RIGHT } jmode; void PlotThings( HPS hps, long lColour ) /* ** Plot a spectrum and related graphs on the designated presentation space ** ** Input: ** HPS hps -- presentation space handle of plot ps ** long lColour -- number of physical colours, used mainly by ** printer drivers to set black & white mode. ** If 0, assume screen display ** ** Note: use semaphore to prevent access to command list while ** pipe thread is reallocating the list. */ { int i, lt, ta, col, sl, n, x, y, cx, cy, width ; int icnow ; int cmd ; char *str, *buf ; long sw ; POINTL ptl ; POINTL aptl[4] ; FONTMETRICS fm ; HDC hdc ; long lVOffset ; long yDeviceRes ; long lCurCol ; long lOldLine = 0 ; BOOL bBW ; GRADIENTL grdl ; BOOL bHorz = TRUE ; SIZEF sizHor, sizVer ; /* sometime, make these user modifiable... */ static long lLineTypes[7] = { LINETYPE_SOLID, LINETYPE_SHORTDASH, LINETYPE_DOT, LINETYPE_DASHDOT, LINETYPE_LONGDASH, LINETYPE_DOUBLEDOT, LINETYPE_DASHDOUBLEDOT } ; static long lCols[15] = { CLR_BLACK, CLR_DARKGRAY, CLR_BLUE, CLR_RED, CLR_GREEN, CLR_CYAN, CLR_PINK, CLR_YELLOW, CLR_DARKBLUE, CLR_DARKRED, CLR_DARKGREEN, CLR_DARKCYAN, CLR_DARKPINK, CLR_BROWN, CLR_PALEGRAY } ; if( commands == NULL ) return ; /* check for colourless devices */ if( lColour== 1 || lColour == 2 ) bBW = TRUE ; else bBW = FALSE ; /* get vertical offset for horizontal text strings */ /* (0.5 em height, so string in vertically centered about plot position */ GpiQueryFontMetrics( hps, sizeof( FONTMETRICS ), &fm ) ; lVOffset = fm.lEmHeight ; /* loop over accumulated commands from inboard driver */ DosRequestMutexSem( semCommands, SEM_INDEFINITE_WAIT ) ; GpiSetLineWidth( hps, bLineThick?LINEWIDTH_THICK:LINEWIDTH_NORMAL ) ; for( i=0; bExist && i<ic; ) { if( bStopDraw ) break ; cmd = commands[i++]; /* PM_vector(x,y) - draw vector */ if (cmd == 'V') { ptl.x = (LONG)commands[i++] ; ptl.y = (LONG)commands[i++] ; GpiLine( hps, &ptl ) ; } /* PM_move(x,y) - move */ else if (cmd == 'M') { ptl.x = (LONG)commands[i++] ; ptl.y = (LONG)commands[i++] ; GpiMove( hps, &ptl ) ; } /* PM_put_text(x,y,str) - draw text */ else if (cmd == 'T') { x = commands[i++] ; y = commands[i++] ; str = (char*)&commands[i] ; sl = strlen(str) ; i += 1+sl/sizeof(int) ; lCurCol = GpiQueryColor( hps ) ; GpiSetColor( hps, CLR_BLACK ) ; GpiQueryTextBox( hps, (LONG)strlen( str ), str, 4L, aptl ) ; if( bHorz ) sw = aptl[3].x ; else sw = aptl[3].y ; switch(jmode) { case LEFT: sw = 0; break; case CENTRE: sw = -sw/2; break; case RIGHT: sw = -sw; break; } if( bHorz ) { ptl.x = (LONG)(x+sw) ; ptl.y = (LONG)(y-lVOffset/4) ; } else { ptl.x = (LONG)x ; ptl.y = (LONG)(y+sw) ; } GpiCharStringAt( hps, &ptl, (LONG) strlen( str ) , str ) ; GpiSetColor( hps, lCurCol ) ; } /* PM_justify_text(mode) - set text justification mode */ else if (cmd == 'J') jmode = commands[i++] ; /* PM_linetype(type) - set line type */ /* mapped to colour */ else if (cmd == 'L') { lt = commands[i++] ; /* linetype = -2 axes, -1 border, 0 arrows, all to 0 */ col = lt ; if( lt == -1 ) GpiSetLineWidth( hps, LINEWIDTH_NORMAL ) ; else GpiSetLineWidth( hps, bLineThick?LINEWIDTH_THICK:LINEWIDTH_NORMAL ) ; if( lt < 0 ) lt = 0 ; lt = (lt%8); col = (col+2)%16 ; if( bLineTypes || bBW ) { GpiSetLineType( hps, lLineTypes[lt] ) ; } if( !bBW ) /* maintain some flexibility here in case we don't want the model T option */ if( bColours ) GpiSetColor( hps, lCols[col] ) ; else GpiSetColor( hps, CLR_BLACK ) ; } else if (cmd == 'D') { /* point/dot mode - may need colour change */ lt = commands[i++] ; /* 1: enter point mode, 0: exit */ if( bLineTypes || bBW ) { if( lt == 1 ) lOldLine = GpiSetLineType( hps, lLineTypes[0] ) ; else GpiSetLineType( hps, lOldLine ) ; } } /* PM_text_angle(ang) - set text angle, 0 horz, 1 vert */ else if (cmd == 'A') { ta = commands[i++] ; if( ta == 0 ) { grdl.x = 0L ; grdl.y = 0L ; GpiSetCharAngle( hps, &grdl ) ; if( !bHorz ) { GpiQueryCharBox( hps, &sizVer ) ; sizHor.cx = sizVer.cy ; sizHor.cy = sizVer.cx ; GpiSetCharBox( hps, &sizHor ) ; bHorz = TRUE ; } } else if( ta == 1 ) { grdl.x = 0L ; grdl.y = 1L ; GpiSetCharAngle( hps, &grdl ) ; if( bHorz ) { GpiQueryCharBox( hps, &sizHor ) ; sizVer.cx = sizHor.cy ; sizVer.cy = sizHor.cx ; GpiSetCharBox( hps, &sizVer ) ; bHorz = FALSE ; } } else continue ; } } DosReleaseMutexSem( semCommands ) ; } short ScalePS( HPS hps, PRECTL prect, USHORT usFlags ) /* ** Get a font to use ** Scale the plot area to world coords for subsequent plotting */ { RECTL rectView, rectClient ; SIZEL sizePage ; static char *szFontName ; static short shFontSize ; rectClient = *prect ; sizePage.cx = GNUPAGE ; sizePage.cy = GNUPAGE ; sscanf( szFontNameSize, "%d", &shFontSize ) ; szFontName = strchr( szFontNameSize, '.' ) + 1 ; rectView.xLeft = 0L ; rectView.xRight = sizePage.cx ; rectView.yBottom = 0L ; rectView.yTop = sizePage.cy ; GpiSetPS( hps, &sizePage, PU_ARBITRARY ) ; GpiSetPageViewport( hps, &rectClient ) ; SelectFont( hps, szFontName, shFontSize ) ; GpiSetGraphicsField( hps, &rectView ) ; return 0 ; } void SelectFont( HPS hps, char *szFont, short shPointSize ) /* ** Select a named and sized outline (adobe) font */ { HDC hdc ; static FATTRS fat ; LONG xDeviceRes, yDeviceRes ; POINTL ptlFont ; SIZEF sizfx ; static LONG lcid = 0L ; fat.usRecordLength = sizeof fat ; fat.fsSelection = 0 ; fat.lMatch = 0 ; fat.idRegistry = 0 ; fat.usCodePage = GpiQueryCp (hps) ; fat.lMaxBaselineExt = 0 ; fat.lAveCharWidth = 0 ; fat.fsType = 0 ; fat.fsFontUse = FATTR_FONTUSE_OUTLINE | FATTR_FONTUSE_TRANSFORMABLE ; strcpy (fat.szFacename, szFont) ; if( lcid == 0L ) lcid = 1L ; else { GpiSetCharSet( hps, 0L) ; GpiDeleteSetId( hps, lcid ) ; } GpiCreateLogFont (hps, NULL, lcid, &fat) ; GpiSetCharSet( hps, lcid ) ; hdc = GpiQueryDevice (hps) ; DevQueryCaps (hdc, CAPS_HORIZONTAL_RESOLUTION, 1L, &xDeviceRes) ; DevQueryCaps (hdc, CAPS_VERTICAL_RESOLUTION, 1L, &yDeviceRes) ; // Find desired font size in pixels ptlFont.x = 254L * (long)shPointSize * xDeviceRes / 720000L ; ptlFont.y = 254L * (long)shPointSize * yDeviceRes / 720000L ; // Convert to page units GpiConvert (hps, CVTC_DEVICE, CVTC_PAGE, 1L, &ptlFont) ; // Set the character box sizfx.cx = MAKEFIXED (ptlFont.x, 0) ; sizfx.cy = MAKEFIXED (ptlFont.y, 0) ; GpiSetCharBox (hps, &sizfx) ; } static void ReadGnu() /* ** Thread to read plot commands from GNUPLOT pm driver. ** Opens named pipe, then clears semaphore to allow GNUPLOT driver to proceed. ** Reads commands and builds a command list. */ { char *szEnv ; char *szFileBuf ; ULONG rc; USHORT usErr ; ULONG cbR ; STARTDATA start ; USHORT i ; PID ppid ; unsigned char buff[2] ; int len ; HEV hev ; static char *szPauseText = NULL ; ULONG ulPause ; char *pszPipeName, *pszSemName ; #ifdef USEOWNALLOC DosAllocMem( &commands, 64*1024*1024, PAG_READ|PAG_WRITE ) ; #endif 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 */ if( DosConnectNPipe( hRead ) == 0L ) { /* store graphics commands */ /* use semaphore to prevent problems with drawing while reallocating the command buffers */ DosRead( hRead, &ppidGnu, 4, &cbR ) ; DosPostEventSem( semStartSeq ) ; /* once we've got pidGnu */ while (1) { usErr=BufRead(hRead,buff, 1, &cbR) ; if( usErr != 0 ) break ; switch( *buff ) { case 'G' : /* enter graphics mode */ /* wait for access to command list and lock it */ DosRequestMutexSem( semCommands, SEM_INDEFINITE_WAIT ) ; DosEnterCritSec() ; #ifdef USEOWNALLOC if( ncalloc > 0 ) { DosSetMem( commands, ncalloc*sizeof(int), PAG_DECOMMIT ) ; #else if (commands!=NULL) { // delete all old commands and prepare for new free(commands); #endif } ic = 0 ; ncalloc = CMDALLOC ; #ifdef USEOWNALLOC DosSetMem( commands, ncalloc*sizeof(int), PAG_COMMIT|PAG_DEFAULT ) ; #else commands = (int*)malloc(ncalloc*sizeof(int)) ; #endif DosExitCritSec() ; DosReleaseMutexSem( semCommands ) ; break ; case 'E' : /* leave graphics mode (graph completed) */ Display() ; /* plot graph */ break ; case 'R' : /* gnuplot has reset drivers, we do nothing */ break ; case 'M' : /* move */ case 'V' : /* draw vector */ commands[ ic++ ] = (int)*buff ; if( ic+2 >= ncalloc ) AllocMore() ; BufRead(hRead,&commands[ic], 2*sizeof(int), &cbR) ; ic+=2 ; break ; case 'P' : /* pause */ BufRead(hRead,&len, sizeof(int), &cbR) ; len = (len+sizeof(int)-1)/sizeof(int) ; if( len > 0 ){ /* get pause text */ szPauseText = malloc( len*sizeof(int) ) ; 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 ; } if( szPauseText != NULL ) free( szPauseText ) ; szPauseText = NULL ; /* reply to gnuplot so it can continue */ DosWrite( hRead, &ulPauseReply, sizeof(int), &cbR ) ; break ; case 'T' : /* write text */ commands[ ic++ ] = (int)*buff ; if( ic+1 >= ncalloc ) AllocMore() ; /* read x, y, len */ BufRead(hRead,&commands[ic++], sizeof(int), &cbR) ; BufRead(hRead,&commands[ic++], sizeof(int), &cbR) ; BufRead(hRead,&len, sizeof(int), &cbR) ; if( ic+1+((len+sizeof(int)-1)/sizeof(int)) >= ncalloc ) AllocMore() ; BufRead(hRead,&commands[ic], len, &cbR) ; if( len == 0 ) len = 1 ; ic += (len+sizeof(int)-1)/sizeof(int) ; break ; case 'J' : /* justify */ case 'A' : /* text angle */ case 'L' : /* line type */ case 'D' : /* points mode */ commands[ ic++ ] = (int)*buff ; if( ic+1 >= ncalloc ) AllocMore() ; BufRead(hRead,&commands[ic++], sizeof(int), &cbR) ; break ; default : /* should handle error */ break ; } } } DosEnterCritSec() ; free( szFileBuf ) ; free( szEnv ) ; DosExitCritSec() ; pidGnu = 0 ; /* gnuplot has shut down (?) */ WinPostMsg( hApp, WM_CLOSE, 0L, 0L ) ; } static int BufRead( HFILE hfile, void *buf, int nBytes, ULONG *pcbR ) /* ** pull next plot command out of buffer read from GNUPLOT */ { ULONG ulR, ulRR ; static char buffer[GNUBUF] ; static char *pbuffer = buffer+GNUBUF, *ebuffer = buffer+GNUBUF ; for( ; nBytes > 0 ; nBytes-- ) { if( pbuffer >= ebuffer ) { ulR = GNUBUF ; DosRead( hfile, buffer, ulR, &ulRR ) ; pbuffer = buffer ; ebuffer = pbuffer+ulRR ; } *(char*)buf++ = *pbuffer++ ; } return 0L ; } static void AllocMore() /* ** Allocate more memory for plot commands */ { DosRequestMutexSem( semCommands, SEM_INDEFINITE_WAIT ) ; DosEnterCritSec() ; #ifdef USEOWNALLOC DosSetMem( commands+ncalloc, CMDALLOC*sizeof(int), PAG_COMMIT|PAG_DEFAULT ) ; #endif ncalloc = ncalloc + CMDALLOC ; #ifndef USEOWNALLOC commands = (int*)realloc(commands, ncalloc*sizeof(int)) ; #endif DosExitCritSec() ; DosReleaseMutexSem( semCommands ) ; } static void Display() /* ** Display gnuplot results ** -- must post message as this thread is not drawing thread */ { WinPostMsg( hApp, WM_GNUPLOT, 0L, 0L ) ; } int GetNewFont( HWND hwnd, HPS hps ) /* ** Get a new font using standard font dialog */ { static FONTDLG pfdFontdlg; /* Font dialog info structure */ static int i1 =1 ; static int iSize ; char szPtList[64] ; HWND hwndFontDlg; /* Font dialog window handle */ char *p ; 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_INITFROMFATTRS ; pfdFontdlg.clrFore = CLR_BLACK; pfdFontdlg.clrBack = CLR_WHITE; pfdFontdlg.usWeight = 5 ; pfdFontdlg.fAttrs.usCodePage = 0; i1=0; } 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 (hwndFontDlg && (pfdFontdlg.lReturn == DID_OK)) { iSize = FIXEDINT( pfdFontdlg.fxPointSize ) ; sprintf( szFontNameSize, "%d.%s", iSize, pfdFontdlg.fAttrs.szFacename ) ; return 1 ; } else return 0 ; }
These are the contents of the former NiCE NeXT User Group NeXTSTEP/OpenStep software archive, currently hosted by Netfuture.ch.