home *** CD-ROM | disk | FTP | other *** search
/ CICA 1995 May / cica_0595_4.zip / cica_0595_4 / UTIL / GPT34SRC / OS2 / GCLIENT.C < prev    next >
C/C++ Source or Header  |  1993-05-11  |  38KB  |  1,106 lines

  1. #ifdef INCRCSDATA
  2. static char RCSid[]="$Id: gclient.c%v 3.38.2.96 1993/03/15 21:39:29 woo Exp woo $" ;
  3. #endif
  4.  
  5. /****************************************************************************
  6.  
  7.     PROGRAM: Gnupmdrv
  8.     
  9.     MODULE:  gclient.c
  10.         
  11.     This file contains the client window procedures for Gnupmdrv
  12.     
  13. ****************************************************************************/
  14.  
  15. /*
  16.  * PM driver for GNUPLOT
  17.  * Copyright (C) 1992   Roger Fearick
  18.  *
  19.  * Permission to use, copy, and distribute this software and its
  20.  * documentation for any purpose with or without fee is hereby granted, 
  21.  * provided that the above copyright notice appear in all copies and 
  22.  * that both that copyright notice and this permission notice appear 
  23.  * in supporting documentation.
  24.  *
  25.  * Permission to modify the software is granted, but not the right to
  26.  * distribute the modified code.  Modifications are to be distributed 
  27.  * as patches to released version.
  28.  *  
  29.  * This software is provided "as is" without express or implied warranty.
  30.  * 
  31.  *
  32.  * AUTHOR
  33.  * 
  34.  *   Gnuplot driver for OS/2:  Roger Fearick
  35.  * 
  36.  * Send your comments or suggestions to 
  37.  *  info-gnuplot@dartmouth.edu.
  38.  * This is a mailing list; to join it send a note to 
  39.  *  info-gnuplot-request@dartmouth.edu.  
  40.  * Send bug reports to
  41.  *  bug-gnuplot@dartmouth.edu.
  42. **/
  43.  
  44. #define INCL_PM
  45. #define INCL_WIN
  46. #define INCL_SPL
  47. #define INCL_SPLDOSPRINT
  48. #define INCL_WINSTDFONT
  49. #define INCL_DOSMEMMGR
  50. #define INCL_DOSPROCESS
  51. #define INCL_DOSERRORS
  52. #define INCL_DOSFILEMGR
  53. #define INCL_DOSNMPIPES
  54. #define INCL_DOSSESMGR
  55. #define INCL_DOSSEMAPHORES
  56. #define INCL_DOSMISC
  57. #define INCL_DOSQUEUES
  58. #define INCL_WINSWITCHLIST
  59. #include <os2.h>
  60. #include <string.h>
  61. #include <stdio.h>
  62. #include <stdlib.h>
  63. #include <unistd.h>
  64. #include <process.h>
  65. #include "gnupmdrv.h"
  66.  
  67. /*==== g l o b a l    d a t a ================================================*/
  68.  
  69. extern char szIPCName[] ;       /* name used in IPC with gnuplot */
  70.  
  71. /*==== l o c a l    d a t a ==================================================*/
  72.  
  73. #define   GNUBUF    1024        /* buffer for gnuplot commands */
  74. #define   PIPEBUF   4096        /* size of pipe buffers */
  75. #define   CMDALLOC  4096        /* command buffer allocation increment (ints) */
  76. #define   ENVSIZE   2048        /* size of environment */ 
  77. #define   GNUPAGE   4096        /* size of gnuplot page in pixels (driver dependent) */
  78.  
  79. #define   PAUSE_DLG 1           /* pause handled in dialog box */
  80. #define   PAUSE_BTN 2           /* pause handled by menu item */
  81. #define   PAUSE_GNU 3           /* pause handled by Gnuplot */
  82.  
  83. static HWND     hWndstart ;     /* used for errors in startup */
  84. static ULONG    pidGnu=0L ;      /* gnuplot session id */
  85. static ULONG    ppidGnu=0L ;      /* gnuplot pid */
  86. static HPS      hpsScreen ;     /* screen pres. space */
  87.  
  88. static HSWITCH hSwitch = 0 ;    /* switching between windows */
  89. static SWCNTRL swGnu ;
  90.  
  91. static BOOL     bLineTypes = FALSE ;
  92. static BOOL     bLineThick = FALSE ;
  93. static BOOL     bColours = TRUE ;
  94. static BOOL     bShellPos = FALSE ;
  95. static BOOL     bPlotPos = FALSE ;
  96. static ULONG    ulPlotPos[4] ;
  97. static ULONG    ulShellPos[4] ;
  98. static char     szFontNameSize[FONTBUF] ;
  99. static char     achPrinterName[128] = "" ;
  100. static PRQINFO3 infPrinter = { "" } ;
  101. static HMTX     semCommands ;
  102. static HEV      semStartSeq ;   /* semaphore to start things in right sequence */
  103. static HEV      semPause ;
  104. static ULONG    ulPauseReply = 1 ;
  105. static ULONG    ulPauseMode  = PAUSE_DLG ;
  106.  
  107.             /* commands from gnuplot come via this ... */
  108.             
  109. static HPIPE    hRead = 0L ; 
  110.            
  111.             /* stuff for screen-draw thread control */
  112.             
  113. static BOOL     bExist ; 
  114. static BOOL     bStopDraw ; 
  115. static HEV      semDrawDone ;
  116. static HEV      semStartDraw ;
  117.  
  118.             /* command buffer */
  119.             
  120. static int ncalloc = 0 ;
  121. static int ic = 0 ;
  122. static volatile int *commands = NULL ;
  123.  
  124. /*==== f u n c t i o n s =====================================================*/
  125.  
  126. int             DoPrint( HWND ) ;
  127. MRESULT         WmClientCmdProc( HWND , ULONG, MPARAM, MPARAM ) ; 
  128. void            ChangeCheck( HWND, USHORT, USHORT ) ;
  129. BOOL            QueryIni( HAB ) ;
  130. static void     SaveIni( void ) ;
  131. static void     ThreadDraw( void ) ;
  132. static void     DoPaint( HWND, HPS ) ;
  133. static void     Display( void ) ;
  134. void            SelectFont( HPS, char *, short );
  135. static void     ReadGnu( void ) ;
  136. static void     WaitEnd( void ) ;
  137. static void     AllocMore() ;
  138. static int      BufRead( HFILE, void*, int, PULONG ) ;
  139. int             GetNewFont( HWND, HPS ) ;
  140.  
  141.  
  142. /*==== c o d e ===============================================================*/
  143.  
  144. MRESULT EXPENTRY DisplayClientWndProc(HWND hWnd, ULONG message, MPARAM mp1, MPARAM mp2)
  145. /*
  146. **  Window proc for main window
  147. **  -- passes most stuff to active child window via WmClientCmdProc
  148. **  -- passes DDE messages to DDEProc
  149. */
  150. {
  151.     HDC     hdcScreen ;
  152.     SIZEL   sizlPage ;
  153.     TID     tidDraw, tidSpawn ;
  154.     char    *pp ;
  155.     ULONG   ulID ;
  156.     ULONG   ulFlag ;
  157.     char    szErrs[128] ;
  158.     
  159.     switch (message) {
  160.  
  161.         case WM_CREATE:
  162.  
  163.                 // set initial values
  164.             ChangeCheck( hWnd, IDM_LINES_THICK, bLineThick?IDM_LINES_THICK:0 ) ;
  165.             ChangeCheck( hWnd, IDM_LINES_SOLID, bLineTypes?0:IDM_LINES_SOLID ) ;
  166.             ChangeCheck( hWnd, IDM_COLOURS, bColours?IDM_COLOURS:0 ) ;
  167.             hWndstart = hWnd ;  /* used in ReadGnu for errors */ 
  168.                 // disable close from system menu (close only from gnuplot)
  169.             WinSendMsg( WinWindowFromID( WinQueryWindow( hWnd, QW_PARENT ), FID_SYSMENU ),
  170.                         MM_SETITEMATTR,
  171.                         MPFROM2SHORT(SC_CLOSE, TRUE ),
  172.                         MPFROM2SHORT(MIA_DISABLED, MIA_DISABLED ) ) ;
  173.                 // setup semaphores
  174.             DosCreateMutexSem( NULL, &semCommands, 0L, 0L ) ;
  175.             DosCreateEventSem( NULL, &semStartDraw, 0L, 0L ) ;
  176.             DosCreateEventSem( NULL, &semDrawDone, 0L, 0L ) ;
  177.             DosCreateEventSem( NULL, &semStartSeq, 0L, 0L ) ;
  178.             DosCreateEventSem( NULL, &semPause, 0L, 0L ) ;
  179.             bStopDraw = FALSE ;
  180.             bExist = TRUE ;
  181.                 // create a dc and hps to draw on the screen
  182.             hdcScreen = WinOpenWindowDC( hWnd ) ;
  183.             sizlPage.cx = GNUPAGE ; sizlPage.cy = GNUPAGE ;
  184.             hpsScreen = GpiCreatePS( hab, hdcScreen, &sizlPage,
  185.                            PU_ARBITRARY|GPIT_MICRO|GPIA_ASSOC) ;
  186.                 // spawn a thread to do the drawing
  187.             DosCreateThread( &tidDraw, (PFNTHREAD)ThreadDraw, 0L, 0L, 8192L ) ;
  188.                 // then spawn server for GNUPLOT ...
  189.             DosCreateThread( &tidSpawn, (PFNTHREAD)ReadGnu, 0L, 0L, 8192L ) ;
  190.             DosWaitEventSem( semStartSeq, SEM_INDEFINITE_WAIT ) ;
  191.                 // get details of command-line window
  192.             hSwitch = WinQuerySwitchHandle( 0, ppidGnu ) ;
  193.             WinQuerySwitchEntry( hSwitch, &swGnu ) ;
  194.                 // set size of this window
  195.             WinSetWindowPos( WinQueryWindow( hWnd, QW_PARENT ), 
  196.                              HWND_TOP,
  197.                              ulShellPos[0],
  198.                              ulShellPos[1],
  199.                              ulShellPos[2],
  200.                              ulShellPos[3], 
  201.                              bShellPos?SWP_SIZE|SWP_MOVE|SWP_SHOW|SWP_ACTIVATE:SWP_SHOW|SWP_ACTIVATE ) ;
  202.                 //  clear screen 
  203.             DosPostEventSem( semDrawDone ) ;  
  204.             break ;
  205.             
  206.  
  207.         case WM_COMMAND:
  208.  
  209.             return WmClientCmdProc( hWnd , message , mp1 , mp2 ) ;
  210.  
  211.         case WM_CLOSE:
  212.  
  213.             if( WinSendMsg( hWnd, WM_USER_PRINT_QBUSY, 0L, 0L ) != 0L ) {
  214.                 WinMessageBox( HWND_DESKTOP,
  215.                                hWnd, 
  216.                                "Still printing - not closed",
  217.                                APP_NAME,
  218.                                0,
  219.                                MB_OK | MB_ICONEXCLAMATION ) ;
  220.                 return 0L ;
  221.                 }
  222.               return (WinDefWindowProc(hWnd, message, mp1, mp2));
  223.  
  224.         case WM_PAINT:
  225.  
  226.             DoPaint( hWnd, hpsScreen ) ;
  227.             break ;     
  228.  
  229.         case WM_SIZE :
  230.             
  231.             WinInvalidateRect( hWnd, NULL, TRUE ) ;
  232.             break ;
  233.  
  234.         case WM_PRESPARAMCHANGED:
  235.         
  236.             pp = malloc(FONTBUF) ;
  237.             if( WinQueryPresParam( hWnd, 
  238.                                    PP_FONTNAMESIZE, 
  239.                                    0, 
  240.                                    &ulID, 
  241.                                    FONTBUF, 
  242.                                    pp, 
  243.                                    QPF_NOINHERIT ) != 0L ) {
  244.                 strcpy( szFontNameSize, pp ) ;
  245.                 WinInvalidateRect( hWnd, NULL, TRUE ) ;
  246.                 }
  247.             free(pp) ; 
  248.             break ;
  249.             
  250.         case WM_USER_PRINT_BEGIN:
  251.         case WM_USER_PRINT_OK :
  252.         case WM_USER_DEV_ERROR :
  253.         case WM_USER_PRINT_ERROR :
  254.         case WM_USER_PRINT_QBUSY :
  255.  
  256.             return( PrintCmdProc( hWnd, message, mp1, mp2 ) ) ;
  257.  
  258.         case WM_GNUPLOT:
  259.                 // display the plot         
  260.             WinSetWindowPos( hwndFrame, HWND_TOP, 0,0,0,0, SWP_ACTIVATE|SWP_ZORDER ) ;
  261.             WinInvalidateRect( hWnd, NULL, TRUE ) ;
  262.             return 0L ;
  263.  
  264.         case WM_PAUSEPLOT:
  265.                 /* put pause message on screen, or enable 'continue' button */
  266.             if( ulPauseMode == PAUSE_DLG ) {
  267.                 WinLoadDlg( HWND_DESKTOP,
  268.                             hWnd,
  269.                             (PFNWP)PauseMsgDlgProc,
  270.                             0L,
  271.                             IDD_PAUSEBOX,
  272.                             (char*)mp1 ) ; 
  273.                 }
  274.             else { 
  275.                 WinEnableMenuItem( WinWindowFromID( 
  276.                                    WinQueryWindow( hWnd, QW_PARENT ), FID_MENU ),
  277.                                    IDM_CONTINUE,
  278.                                    TRUE ) ;            
  279.                 }
  280.             return 0L ;
  281.  
  282.         case WM_PAUSEEND:
  283.             /* resume plotting */
  284.             ulPauseReply = (ULONG) mp1 ;
  285.             DosPostEventSem( semPause ) ;
  286.             return 0L ;
  287.     
  288.     default:         /* Passes it on if unproccessed    */
  289.         return (WinDefWindowProc(hWnd, message, mp1, mp2));
  290.     }
  291.     return (NULL);
  292. }
  293.  
  294. MRESULT WmClientCmdProc(HWND hWnd, ULONG message, MPARAM mp1, MPARAM mp2)
  295. /*
  296. **   Handle client window command (menu) messages
  297. **   -- mostly passed on to active child window
  298. **
  299. */
  300.     {
  301.     ULONG usDlg ;
  302.     extern HWND hApp ;
  303.     static ulPauseItem = IDM_PAUSEDLG ;
  304.  
  305.     switch( (USHORT) SHORT1FROMMP( mp1 ) ) {
  306.                 
  307.         case IDM_ABOUT :    /* show the 'About' box */
  308.              
  309.             WinDlgBox( HWND_DESKTOP,
  310.                        hWnd , 
  311.                        (PFNWP)About ,
  312.                        0L,
  313.                        ID_ABOUT, 
  314.                        NULL ) ;
  315.             break ;
  316.  
  317.  
  318.         case IDM_PRINT :    /* print plot */
  319.  
  320.             if( SetupPrinter( hWnd, achPrinterName, &infPrinter ) )
  321.                 WinPostMsg( hWnd, WM_USER_PRINT_BEGIN, (MPARAM)&infPrinter, 0L ) ; 
  322.             break ;
  323.  
  324.         case IDM_PRINTSETUP :    /* select printer */
  325.  
  326.             WinDlgBox( HWND_DESKTOP,
  327.                        hWnd ,
  328.                        (PFNWP)QPrintersDlgProc,
  329.                        0L,
  330.                        IDD_QUERYPRINT, 
  331.                        achPrinterName ) ;
  332.             break ;
  333.  
  334.         case IDM_LINES_THICK:
  335.                 // change line setting
  336.             bLineThick = !bLineThick ;
  337.             ChangeCheck( hWnd, IDM_LINES_THICK, bLineThick?IDM_LINES_THICK:0 ) ;
  338.             WinInvalidateRect( hWnd, NULL, TRUE ) ;
  339.             break ;
  340.  
  341.         case IDM_LINES_SOLID:
  342.                 // change line setting
  343.             bLineTypes = !bLineTypes ;
  344.             ChangeCheck( hWnd, IDM_LINES_SOLID, bLineTypes?0:IDM_LINES_SOLID ) ;
  345.             WinInvalidateRect( hWnd, NULL, TRUE ) ;
  346.             break ;
  347.  
  348.         case IDM_COLOURS:
  349.                 // change colour setting
  350.             bColours = !bColours ;        
  351.             ChangeCheck( hWnd, IDM_COLOURS, bColours?IDM_COLOURS:0 ) ;
  352.             WinInvalidateRect( hWnd, NULL, TRUE ) ;
  353.             break ;
  354.  
  355.         case IDM_FONTS:
  356.         
  357.             if( GetNewFont( hWnd, hpsScreen ) ) 
  358.                 WinInvalidateRect( hWnd, NULL, TRUE ) ;
  359.             break ;
  360.             
  361.         case IDM_SAVE :
  362.             SaveIni() ;
  363.             break ;
  364.             
  365.         case IDM_COMMAND:       /* go back to GNUPLOT command window */            
  366.             WinSwitchToProgram( hSwitch ) ;
  367.             break ;
  368.  
  369.         case IDM_CONTINUE:
  370.             WinPostMsg( hWnd, WM_PAUSEEND, 1L, 0L ) ; 
  371.             WinEnableMenuItem( WinWindowFromID( 
  372.                                WinQueryWindow( hWnd, QW_PARENT ), FID_MENU ),
  373.                                IDM_CONTINUE,
  374.                                FALSE ) ;            
  375.             break ;
  376.             
  377.         case IDM_PAUSEGNU:  /* gnuplot handles pause */
  378.             ChangeCheck( hWnd, ulPauseItem, IDM_PAUSEGNU ) ;
  379.             ulPauseItem = IDM_PAUSEGNU ;
  380.             ulPauseMode = PAUSE_GNU ;
  381.             break ;
  382.             
  383.         case IDM_PAUSEDLG:  /* pause message in dlg box */
  384.             ChangeCheck( hWnd, ulPauseItem, IDM_PAUSEDLG ) ;
  385.             ulPauseItem = IDM_PAUSEDLG ;
  386.             ulPauseMode = PAUSE_DLG ;
  387.             break ;
  388.             
  389.         case IDM_PAUSEBTN:  /* pause uses menu button, no message */
  390.             ChangeCheck( hWnd, ulPauseItem, IDM_PAUSEBTN ) ;
  391.             ulPauseItem = IDM_PAUSEBTN ;
  392.             ulPauseMode = PAUSE_BTN ;
  393.             break ;
  394.           
  395.         case IDM_HELPFORHELP:
  396.             WinSendMsg(WinQueryHelpInstance(hWnd),
  397.                        HM_DISPLAY_HELP, 0L, 0L ) ;
  398.             return 0L ;
  399.  
  400.         case IDM_EXTENDEDHELP:
  401.             WinSendMsg(WinQueryHelpInstance(hWnd),
  402.                         HM_EXT_HELP, 0L, 0L);
  403.             return 0L ;
  404.  
  405.         case IDM_KEYSHELP:
  406.             WinSendMsg(WinQueryHelpInstance(hWnd),
  407.                        HM_KEYS_HELP, 0L, 0L);
  408.             return 0L ;
  409.  
  410.         case IDM_HELPINDEX:
  411.             WinSendMsg(WinQueryHelpInstance(hWnd),
  412.                        HM_HELP_INDEX, 0L, 0L);
  413.             return 0L ;
  414.  
  415.         default : 
  416.     
  417.             return WinDefWindowProc( hWnd, message, mp1, mp2 ) ;
  418.  
  419.         }  
  420.     return( NULL ) ;
  421.     }                      
  422.  
  423. void ChangeCheck( HWND hWnd , USHORT wItem1 , USHORT wItem2 )
  424. /*
  425. **  Utility function:
  426. **
  427. **  move check mark from menu item 1 to item 2
  428. */
  429.     {
  430.     HWND hMenu ;
  431.  
  432.     hMenu = WinWindowFromID( WinQueryWindow( hWnd, QW_PARENT ), 
  433.                              FID_MENU ) ;            
  434.     if( wItem1 != 0 )
  435.         WinSendMsg( hMenu,
  436.                     MM_SETITEMATTR,
  437.                     MPFROM2SHORT( wItem1, TRUE ),
  438.                     MPFROM2SHORT( MIA_CHECKED, 0 ) ) ;
  439.     if( wItem2 != 0 )
  440.         WinSendMsg( hMenu,
  441.                     MM_SETITEMATTR,
  442.                     MPFROM2SHORT( wItem2, TRUE ),
  443.                     MPFROM2SHORT( MIA_CHECKED, MIA_CHECKED ) ) ;
  444.     }       
  445.  
  446. BOOL QueryIni( HAB hab )
  447. /*
  448. ** Query INI file
  449. */
  450.     {
  451.     BOOL         bPos, bData ;
  452.     ULONG        ulOpts[4] ;
  453.     HINI         hini ;
  454.     ULONG        ulCB ;
  455.     char         *p ;
  456.     
  457.             // get default printer name    
  458.             
  459.     PrfQueryProfileString( HINI_PROFILE,
  460.                            "PM_SPOOLER",
  461.                            "PRINTER",
  462.                            ";",
  463.                            achPrinterName,
  464.                            (long) sizeof achPrinterName ) ;
  465.     if( (p=strchr( achPrinterName, ';' )) != NULL ) *p = '\0' ;
  466.     
  467.             // read gnuplot ini file
  468.  
  469.     hini = PrfOpenProfile( hab, GNUINI ) ;
  470.     ulCB = sizeof( ulShellPos ) ;
  471.     bPos = PrfQueryProfileData( hini, APP_NAME, INISHELLPOS, &ulShellPos, &ulCB ) ;
  472.     ulCB = sizeof( ulOpts ) ;
  473.     bData = PrfQueryProfileData( hini, APP_NAME, INIOPTS, &ulOpts, &ulCB ) ;
  474.     if( bData ) {
  475.         bLineTypes = (BOOL)ulOpts[0] ;
  476.         bLineThick = (BOOL)ulOpts[1] ;
  477.         bColours = (BOOL)ulOpts[2] ;
  478.         ulPauseMode = ulOpts[3] ;
  479.         }
  480.     else {
  481.         bLineTypes = FALSE ;  /* default values */
  482.         bLineThick = FALSE ;
  483.         bColours = TRUE ;
  484.         ulPauseMode = 1 ;
  485.         }
  486.     PrfQueryProfileString( hini, APP_NAME, INIFONT, INITIAL_FONT, 
  487.                                  szFontNameSize, FONTBUF ) ;
  488.     PrfCloseProfile( hini ) ;
  489.     bShellPos = bPos ;
  490.     return bPos ;
  491.     }
  492.  
  493. static void SaveIni( )
  494. /*
  495. ** save data in ini file
  496. */
  497.     {
  498.     SWP swp ;
  499.     HINI  hini ;
  500.     ULONG ulOpts[4] ;
  501.     
  502.     hini = PrfOpenProfile( hab, GNUINI ) ;
  503.     WinQueryWindowPos( hwndFrame, &swp ) ;
  504.     ulPlotPos[0] = swp.x ;
  505.     ulPlotPos[1] = swp.y ;
  506.     ulPlotPos[2] = swp.cx ;
  507.     ulPlotPos[3] = swp.cy ;
  508.     PrfWriteProfileData( hini, APP_NAME, INISHELLPOS, &ulPlotPos, sizeof(ulPlotPos) ) ;
  509. /*
  510.     WinQueryWindowPos( swGnu.hwnd, &swp ) ;
  511.     ulPlotPos[0] = swp.x ;
  512.     ulPlotPos[1] = swp.y ;
  513.     ulPlotPos[2] = swp.cx ;
  514.     ulPlotPos[3] = swp.cy ;
  515.     PrfWriteProfileData( hini, APP_NAME, INIPLOTPOS, &ulPlotPos, sizeof(ulPlotPos) ) ;
  516. */
  517.     ulOpts[0] = (ULONG)bLineTypes ;
  518.     ulOpts[1] = (ULONG)bLineThick ; 
  519.     ulOpts[2] = (ULONG)bColours ;
  520.     ulOpts[3] = ulPauseMode ; 
  521.     PrfWriteProfileData( hini, APP_NAME, INIOPTS, &ulOpts, sizeof(ulOpts) ) ;
  522.     PrfWriteProfileString( hini, APP_NAME, INIFONT, szFontNameSize ) ;
  523.     PrfCloseProfile( hini ) ;
  524.     }
  525.  
  526. static void DoPaint( HWND hWnd, HPS hps  ) 
  527. /*
  528. **  Paint the screen with current data 
  529. */
  530.     {
  531.     RECTL rectClient ;
  532.     ULONG ulCount ;    
  533.     bStopDraw = TRUE ;    // stop any drawing in progress and wait for 
  534.                           // thread to signal completion 
  535.     DosWaitEventSem( semDrawDone, SEM_INDEFINITE_WAIT ) ;
  536.     DosResetEventSem( semDrawDone, &ulCount ) ;
  537.     WinBeginPaint( hWnd , hps, NULL ) ;
  538.     DosPostEventSem( semStartDraw ) ;  // start drawing
  539.     }
  540.  
  541. static void ThreadDraw( )
  542. /*
  543. **  Thread to draw plot
  544. */
  545.     {
  546.     HAB  hab ;
  547.     RECTL rectClient ;
  548.     ULONG ulCount ;
  549.  
  550.         /* initialize and wait until ready to draw */
  551.     
  552.     hab = WinInitialize( 0 ) ;
  553.  
  554.         /* ok - draw until window is destroyed */
  555.  
  556.     while( bExist )  {
  557.  
  558.                 // indicate access to window 
  559.         DosWaitEventSem( semStartDraw, SEM_INDEFINITE_WAIT ) ;
  560.         DosResetEventSem( semStartDraw, &ulCount ) ;
  561.  
  562.                 // will be set TRUE if we decide to stop in the middle, but now
  563.         bStopDraw = FALSE ;         
  564.         
  565.         GpiResetPS( hpsScreen, GRES_ALL ) ;        
  566.         WinQueryWindowRect( hApp, (PRECTL)&rectClient ) ;
  567.         GpiSetPageViewport( hpsScreen, &rectClient ) ;
  568.  
  569.         WinFillRect( hpsScreen, &rectClient, CLR_WHITE ) ;
  570.  
  571.         ScalePS( hpsScreen, &rectClient, 0 ) ;
  572.  
  573.         PlotThings( hpsScreen, 0L ) ;
  574.                 // ok, say that we did it
  575.  
  576.         WinEndPaint( hpsScreen ) ;
  577.         DosPostEventSem( semDrawDone ) ;
  578.         }
  579.    
  580.     WinTerminate( hab ) ;
  581.     }
  582.  
  583.  
  584. enum JUSTIFY { LEFT, CENTRE, RIGHT } jmode;
  585.  
  586. void PlotThings( HPS hps, long lColour ) 
  587. /*
  588. **  Plot a spectrum and related graphs on the designated presentation space
  589. **
  590. **  Input:
  591. **          HPS hps         -- presentation space handle of plot ps
  592. **          long lColour    -- number of physical colours, used mainly by
  593. **                             printer drivers to set black & white mode.
  594. **                             If 0, assume screen display
  595. **
  596. **  Note: use semaphore to prevent access to command list while
  597. **        pipe thread is reallocating the list.
  598. */
  599.     {
  600.     int i, lt, ta, col, sl, n, x, y, cx, cy, width ;
  601.     int icnow ;
  602.     int cmd ;
  603.     char *str, *buf ;
  604.     long sw ;
  605.     POINTL ptl ;
  606.     POINTL aptl[4] ;    
  607.     FONTMETRICS fm ;
  608.     HDC hdc ;
  609.     long lVOffset ;
  610.     long yDeviceRes ;
  611.     long lCurCol ;
  612.     long lOldLine = 0 ;
  613.     BOOL bBW ;
  614.     GRADIENTL grdl ;
  615.     BOOL bHorz = TRUE ;
  616.     SIZEF sizHor, sizVer ;
  617.         /* sometime, make these user modifiable... */
  618.     static long lLineTypes[7] = { LINETYPE_SOLID,
  619.                                   LINETYPE_SHORTDASH,
  620.                                   LINETYPE_DOT,
  621.                                   LINETYPE_DASHDOT,
  622.                                   LINETYPE_LONGDASH,
  623.                                   LINETYPE_DOUBLEDOT,
  624.                                   LINETYPE_DASHDOUBLEDOT } ;
  625.     static long lCols[15] =     { CLR_BLACK,
  626.                                   CLR_DARKGRAY,
  627.                                   CLR_BLUE,
  628.                                   CLR_RED,
  629.                                   CLR_GREEN,
  630.                                   CLR_CYAN,
  631.                                   CLR_PINK,
  632.                                   CLR_YELLOW,
  633.                                   CLR_DARKBLUE,
  634.                                   CLR_DARKRED,
  635.                                   CLR_DARKGREEN,
  636.                                   CLR_DARKCYAN,
  637.                                   CLR_DARKPINK,
  638.                                   CLR_BROWN,
  639.                                   CLR_PALEGRAY } ;
  640.  
  641.     if( commands == NULL ) return ;
  642.  
  643.         /* check for colourless devices */
  644.  
  645.     if( lColour== 1 || lColour == 2 ) bBW = TRUE ;
  646.     else bBW = FALSE ;
  647.  
  648.         /* get vertical offset for horizontal text strings */
  649.         /* (0.5 em height, so string in vertically centered
  650.            about plot position */
  651.  
  652.     GpiQueryFontMetrics( hps, sizeof( FONTMETRICS ), &fm ) ;
  653.     lVOffset = fm.lEmHeight ;
  654.  
  655.     
  656.    /* loop over accumulated commands from inboard driver */
  657.  
  658.     DosRequestMutexSem( semCommands, SEM_INDEFINITE_WAIT ) ;
  659.  
  660.     GpiSetLineWidth( hps, bLineThick?LINEWIDTH_THICK:LINEWIDTH_NORMAL ) ;
  661.     for( i=0; bExist && i<ic; ) {
  662.  
  663.             if( bStopDraw ) break ;
  664.  
  665.             cmd = commands[i++];
  666.  
  667.       /*   PM_vector(x,y) - draw vector  */
  668.             if (cmd == 'V') { 
  669.                  ptl.x = (LONG)commands[i++] ; ptl.y = (LONG)commands[i++] ;
  670.                  GpiLine( hps, &ptl ) ;
  671.              }
  672.  
  673.       /*   PM_move(x,y) - move  */
  674.             else if (cmd == 'M')  {
  675.                 ptl.x = (LONG)commands[i++] ; ptl.y = (LONG)commands[i++] ;
  676.                 GpiMove( hps, &ptl ) ;
  677.                 }
  678.         
  679.       /*   PM_put_text(x,y,str) - draw text   */
  680.             else if (cmd == 'T') { 
  681.                 x = commands[i++] ;
  682.                 y = commands[i++] ;
  683.             str = (char*)&commands[i] ; 
  684.             sl = strlen(str) ;
  685.             i += 1+sl/sizeof(int) ;
  686.                 lCurCol = GpiQueryColor( hps ) ;
  687.                 GpiSetColor( hps, CLR_BLACK ) ;
  688.                 GpiQueryTextBox( hps, (LONG)strlen( str ), str, 4L, aptl ) ;
  689.                 if( bHorz ) sw = aptl[3].x ;
  690.                 else sw = aptl[3].y ;
  691.                 switch(jmode) {
  692.                 case LEFT:   sw = 0;     break;
  693.                 case CENTRE: sw = -sw/2; break;
  694.                 case RIGHT:  sw = -sw;   break;
  695.                     }
  696.                 if( bHorz ) {
  697.                     ptl.x = (LONG)(x+sw) ; ptl.y = (LONG)(y-lVOffset/4) ;
  698.                     }
  699.                 else {
  700.                     ptl.x = (LONG)x ; ptl.y = (LONG)(y+sw) ;
  701.                     }
  702.                 GpiCharStringAt( hps, &ptl, (LONG) strlen( str ) , str ) ;
  703.                 GpiSetColor( hps, lCurCol ) ;
  704.             }
  705.  
  706.       /*   PM_justify_text(mode) - set text justification mode  */
  707.             else if (cmd == 'J') 
  708.                 jmode = commands[i++] ;
  709.  
  710.       /*   PM_linetype(type) - set line type  */
  711.       /* mapped to colour */
  712.             else if (cmd == 'L') { 
  713.                 lt = commands[i++] ;
  714.         /* linetype = -2 axes, -1 border, 0 arrows, all to 0 */
  715.             col = lt ;
  716.                 if( lt == -1 ) GpiSetLineWidth( hps, LINEWIDTH_NORMAL ) ;
  717.                 else GpiSetLineWidth( hps, bLineThick?LINEWIDTH_THICK:LINEWIDTH_NORMAL ) ;
  718.                 if( lt < 0 ) lt = 0 ;
  719.             lt = (lt%8);
  720.             col = (col+2)%16 ;
  721.                 if( bLineTypes || bBW ) {
  722.                     GpiSetLineType( hps, lLineTypes[lt] ) ;
  723.                     }
  724.                 if( !bBW )  /* maintain some flexibility here in case we don't want
  725.                            the model T option */ 
  726.                     if( bColours ) GpiSetColor( hps, lCols[col] ) ;
  727.                     else GpiSetColor( hps, CLR_BLACK ) ;
  728.                 }
  729.  
  730.             else if (cmd == 'D') { /* point/dot mode - may need colour change */
  731.                 lt = commands[i++] ;  /* 1: enter point mode, 0: exit */
  732.                 if( bLineTypes || bBW ) {
  733.                     if( lt == 1 ) lOldLine = GpiSetLineType( hps, lLineTypes[0] ) ;
  734.                     else GpiSetLineType( hps, lOldLine ) ;
  735.                     }
  736.                 }
  737.  
  738.       /*   PM_text_angle(ang) - set text angle, 0 horz, 1 vert  */
  739.             else if (cmd == 'A') { 
  740.                 ta = commands[i++] ;
  741.                 if( ta == 0 ) {
  742.                     grdl.x = 0L ; grdl.y = 0L ;
  743.                     GpiSetCharAngle( hps, &grdl ) ;
  744.                     if( !bHorz ) {
  745.                         GpiQueryCharBox( hps, &sizVer ) ;
  746.                         sizHor.cx = sizVer.cy ; sizHor.cy = sizVer.cx ;
  747.                         GpiSetCharBox( hps, &sizHor ) ;
  748.                         bHorz = TRUE ;
  749.                         }
  750.                     }
  751.                 else if( ta == 1 ) {
  752.                     grdl.x = 0L ; grdl.y = 1L ;
  753.                     GpiSetCharAngle( hps, &grdl ) ;
  754.                     if( bHorz ) {
  755.                         GpiQueryCharBox( hps, &sizHor ) ;
  756.                         sizVer.cx = sizHor.cy ; sizVer.cy = sizHor.cx ;
  757.                         GpiSetCharBox( hps, &sizVer ) ;
  758.                         bHorz = FALSE ;
  759.                         }
  760.                     }
  761.                 else continue ;            
  762.                 }
  763.             }
  764.         DosReleaseMutexSem( semCommands ) ;
  765.     }
  766.     
  767. short ScalePS( HPS hps, PRECTL prect, USHORT usFlags )
  768. /*
  769. **  Get a font to use
  770. **  Scale the plot area to world coords for subsequent plotting
  771. */
  772.     {
  773.     RECTL rectView, rectClient ;
  774.     SIZEL sizePage ;
  775.     static char *szFontName ;
  776.     static short shFontSize ;
  777.         
  778.     rectClient = *prect ;
  779.     sizePage.cx = GNUPAGE ; 
  780.     sizePage.cy = GNUPAGE ; 
  781.  
  782.     sscanf( szFontNameSize, "%d", &shFontSize ) ;
  783.     szFontName = strchr( szFontNameSize, '.' ) + 1 ;
  784.     rectView.xLeft = 0L ;
  785.     rectView.xRight = sizePage.cx ;
  786.     rectView.yBottom = 0L ; rectView.yTop = sizePage.cy ;
  787.     GpiSetPS( hps, &sizePage, PU_ARBITRARY ) ;
  788.     GpiSetPageViewport( hps, &rectClient ) ;
  789.     SelectFont( hps, szFontName, shFontSize ) ;
  790.     GpiSetGraphicsField( hps, &rectView ) ;
  791.     return 0 ;
  792.     }
  793.  
  794. void SelectFont( HPS hps, char *szFont, short shPointSize )
  795. /*
  796. **  Select a named and sized outline (adobe) font
  797. */
  798.     {
  799.      HDC         hdc ;
  800.      static FATTRS fat ;
  801.      LONG   xDeviceRes, yDeviceRes ;
  802.      POINTL ptlFont ;
  803.      SIZEF  sizfx ;
  804.      static LONG lcid = 0L ;
  805.  
  806.      fat.usRecordLength  = sizeof fat ;
  807.      fat.fsSelection     = 0 ;
  808.      fat.lMatch          = 0 ;
  809.      fat.idRegistry      = 0 ;
  810.      fat.usCodePage      = GpiQueryCp (hps) ;
  811.      fat.lMaxBaselineExt = 0 ;
  812.      fat.lAveCharWidth   = 0 ;
  813.      fat.fsType          = 0 ;
  814.      fat.fsFontUse       = FATTR_FONTUSE_OUTLINE |
  815.                            FATTR_FONTUSE_TRANSFORMABLE ;
  816.  
  817.      strcpy (fat.szFacename, szFont) ;
  818.  
  819.      if( lcid == 0L ) lcid = 1L ;
  820.      else {
  821.         GpiSetCharSet( hps, 0L) ;
  822.         GpiDeleteSetId( hps, lcid ) ;
  823.         }
  824.      GpiCreateLogFont (hps, NULL, lcid, &fat) ;
  825.      GpiSetCharSet( hps, lcid ) ;
  826.  
  827.      hdc = GpiQueryDevice (hps) ;
  828.  
  829.      DevQueryCaps (hdc, CAPS_HORIZONTAL_RESOLUTION, 1L, &xDeviceRes) ;
  830.      DevQueryCaps (hdc, CAPS_VERTICAL_RESOLUTION,   1L, &yDeviceRes) ;
  831.  
  832.                          // Find desired font size in pixels
  833.  
  834.      ptlFont.x = 254L * (long)shPointSize * xDeviceRes / 720000L ;
  835.      ptlFont.y = 254L * (long)shPointSize * yDeviceRes / 720000L ;
  836.  
  837.                          // Convert to page units
  838.  
  839.      GpiConvert (hps, CVTC_DEVICE, CVTC_PAGE, 1L, &ptlFont) ;
  840.  
  841.                          // Set the character box
  842.  
  843.      sizfx.cx = MAKEFIXED (ptlFont.x, 0) ;
  844.      sizfx.cy = MAKEFIXED (ptlFont.y, 0) ;
  845.  
  846.      GpiSetCharBox (hps, &sizfx) ;
  847.     }
  848.  
  849. static void ReadGnu()
  850. /*
  851. ** Thread to read plot commands from  GNUPLOT pm driver.
  852. ** Opens named pipe, then clears semaphore to allow GNUPLOT driver to proceed.
  853. ** Reads commands and builds a command list.
  854. */
  855.     {
  856.     char *szEnv ;
  857.     char *szFileBuf ;
  858.     ULONG rc; 
  859.     USHORT usErr ;
  860.     ULONG cbR ;
  861.     STARTDATA start ;
  862.     USHORT i ;
  863.     PID ppid ;
  864.     unsigned char buff[2] ;
  865.     int len ;
  866.     HEV hev ;
  867.     static char *szPauseText = NULL ;
  868.     ULONG ulPause ;
  869.     char *pszPipeName, *pszSemName ;
  870.     
  871. #ifdef USEOWNALLOC
  872.     DosAllocMem( &commands, 64*1024*1024, PAG_READ|PAG_WRITE ) ;
  873. #endif
  874.  
  875.     DosEnterCritSec() ;
  876.     pszPipeName = malloc( 256 ) ;
  877.     pszSemName  = malloc( 256 ) ;
  878.     DosExitCritSec() ;
  879.     strcpy( pszPipeName, "\\pipe\\" ) ;
  880.     strcpy( pszSemName, "\\sem32\\" ) ;
  881.     strcat( pszPipeName, szIPCName ) ;
  882.     strcat( pszSemName, szIPCName ) ;
  883.  
  884.             /* open a named pipe for communication with gnuplot */
  885.  
  886.     rc = DosCreateNPipe( pszPipeName,
  887.                          &hRead, 
  888.                          NP_ACCESS_DUPLEX|NP_NOINHERIT|NP_NOWRITEBEHIND ,
  889.                          1|NP_WAIT|NP_READMODE_MESSAGE|NP_TYPE_MESSAGE,
  890.                          PIPEBUF,
  891.                          PIPEBUF,
  892.                          0xFFFFFFFF) ;
  893.     hev = 0 ;       /* OK, gnuplot can try to open npipe ... */
  894.     DosOpenEventSem( pszSemName, &hev ) ;
  895.     DosPostEventSem( hev ) ;
  896.     
  897.  
  898.     
  899.         /* attach to gnuplot */
  900.  
  901.     if( DosConnectNPipe( hRead ) == 0L ) {
  902.  
  903.         /* store graphics commands */
  904.         /* use semaphore to prevent problems with drawing while reallocating
  905.            the command buffers */
  906.  
  907.         DosRead( hRead, &ppidGnu, 4, &cbR ) ;
  908.         DosPostEventSem( semStartSeq ) ;         /* once we've got pidGnu */
  909.  
  910.  
  911.         while (1) {
  912.         
  913.             usErr=BufRead(hRead,buff, 1, &cbR) ;
  914.             if( usErr != 0 ) break ;
  915.  
  916.             switch( *buff ) {
  917.                 case 'G' :    /* enter graphics mode */
  918.                     /* wait for access to command list and lock it */
  919.                     DosRequestMutexSem( semCommands, SEM_INDEFINITE_WAIT ) ;
  920.                     DosEnterCritSec() ;
  921. #ifdef USEOWNALLOC
  922.                     if( ncalloc > 0 ) {
  923.                         DosSetMem( commands, ncalloc*sizeof(int), PAG_DECOMMIT ) ;
  924. #else
  925.                        if (commands!=NULL) {    // delete all old commands and prepare for new
  926.                         free(commands);
  927. #endif
  928.                         }
  929.                     ic = 0 ;
  930.                     ncalloc = CMDALLOC ;
  931. #ifdef USEOWNALLOC
  932.                     DosSetMem( commands, ncalloc*sizeof(int), PAG_COMMIT|PAG_DEFAULT ) ;
  933. #else
  934.                     commands = (int*)malloc(ncalloc*sizeof(int)) ;
  935. #endif
  936.                     DosExitCritSec() ;
  937.                     DosReleaseMutexSem( semCommands ) ;
  938.                     break ;
  939.                     
  940.                 case 'E' :     /* leave graphics mode (graph completed) */
  941.                     Display() ; /* plot graph */
  942.                     break ;
  943.                     
  944.                 case 'R' :
  945.                     /* gnuplot has reset drivers, we do nothing */
  946.                     break ;
  947.  
  948.                 case 'M' :   /* move */
  949.                 case 'V' :   /* draw vector */
  950.                     commands[ ic++ ] = (int)*buff ; 
  951.                     if( ic+2 >= ncalloc ) AllocMore() ;
  952.                     BufRead(hRead,&commands[ic], 2*sizeof(int), &cbR) ;
  953.                     ic+=2 ;
  954.                     break ;
  955.                   
  956.                 case 'P' :   /* pause */
  957.                     BufRead(hRead,&len, sizeof(int), &cbR) ;
  958.                     len = (len+sizeof(int)-1)/sizeof(int) ;
  959.                     if( len > 0 ){  /* get pause text */
  960.                         szPauseText = malloc( len*sizeof(int) ) ;
  961.                         BufRead(hRead,szPauseText, len*sizeof(int), &cbR) ;
  962.                         }
  963.                     if( ulPauseMode != PAUSE_GNU ) {
  964.                              /* pause and wait for semaphore to be cleared */
  965.                         DosResetEventSem( semPause, &ulPause ) ;
  966.                         WinPostMsg( hApp, WM_PAUSEPLOT, (MPARAM) szPauseText, 0L ) ;
  967.                         DosWaitEventSem( semPause, SEM_INDEFINITE_WAIT ) ;
  968.                         }
  969.                     else { /* gnuplot handles pause */
  970.                         ulPauseReply = 2 ;
  971.                         }
  972.                     if( szPauseText != NULL ) free( szPauseText ) ;
  973.                     szPauseText = NULL ;
  974.                              /* reply to gnuplot so it can continue */
  975.                     DosWrite( hRead, &ulPauseReply, sizeof(int), &cbR ) ;
  976.                     break ; 
  977.                        
  978.                 case 'T' :   /* write text */
  979.                     commands[ ic++ ] = (int)*buff ; 
  980.                     if( ic+1 >= ncalloc ) AllocMore() ;
  981.                         /* read x, y, len */
  982.                     BufRead(hRead,&commands[ic++], sizeof(int), &cbR) ;
  983.                     BufRead(hRead,&commands[ic++], sizeof(int), &cbR) ;
  984.                     BufRead(hRead,&len, sizeof(int), &cbR) ;
  985.                     if( ic+1+((len+sizeof(int)-1)/sizeof(int)) >= ncalloc ) AllocMore() ;
  986.                     BufRead(hRead,&commands[ic], len, &cbR) ;
  987.                     if( len == 0 ) len = 1 ;
  988.                     ic += (len+sizeof(int)-1)/sizeof(int) ;
  989.                     break ;
  990.                     
  991.                 case 'J' :   /* justify */
  992.                 case 'A' :   /* text angle */
  993.                 case 'L' :   /* line type */
  994.                 case 'D' :   /* points mode */
  995.                 
  996.                     commands[ ic++ ] = (int)*buff ; 
  997.                     if( ic+1 >= ncalloc ) AllocMore() ;
  998.                     BufRead(hRead,&commands[ic++], sizeof(int), &cbR) ;
  999.                     break ;
  1000.  
  1001.                  default :  /* should handle error */
  1002.                     break ;
  1003.                  }
  1004.              }
  1005.         }
  1006.     DosEnterCritSec() ;
  1007.     free( szFileBuf ) ;
  1008.     free( szEnv ) ;
  1009.     DosExitCritSec() ;
  1010.     pidGnu = 0 ; /* gnuplot has shut down (?) */
  1011.     WinPostMsg( hApp, WM_CLOSE, 0L, 0L ) ;    
  1012.     }
  1013.  
  1014. static int BufRead( HFILE hfile, void *buf, int nBytes, ULONG *pcbR )
  1015. /*
  1016. ** pull next plot command out of buffer read from GNUPLOT
  1017. */
  1018.     {
  1019.     ULONG ulR, ulRR ;
  1020.     static char buffer[GNUBUF] ;
  1021.     static char *pbuffer = buffer+GNUBUF, *ebuffer = buffer+GNUBUF ;
  1022.     
  1023.     for( ; nBytes > 0 ; nBytes-- ) {
  1024.         if( pbuffer >= ebuffer ) {
  1025.             ulR = GNUBUF ;
  1026.             DosRead( hfile, buffer, ulR, &ulRR ) ;
  1027.             pbuffer = buffer ;
  1028.             ebuffer = pbuffer+ulRR ;
  1029.             }
  1030.         *(char*)buf++ = *pbuffer++ ;
  1031.         }
  1032.     return 0L ;
  1033.     } 
  1034.  
  1035. static void AllocMore()
  1036. /*
  1037. **  Allocate more memory for plot commands
  1038. */
  1039.     {
  1040.     DosRequestMutexSem( semCommands, SEM_INDEFINITE_WAIT ) ;
  1041.     DosEnterCritSec() ;
  1042. #ifdef USEOWNALLOC
  1043.     DosSetMem( commands+ncalloc, CMDALLOC*sizeof(int), PAG_COMMIT|PAG_DEFAULT ) ;
  1044. #endif
  1045.     ncalloc = ncalloc + CMDALLOC ;
  1046. #ifndef USEOWNALLOC
  1047.     commands = (int*)realloc(commands, ncalloc*sizeof(int)) ;
  1048. #endif
  1049.     DosExitCritSec() ;
  1050.     DosReleaseMutexSem( semCommands ) ;
  1051.     }
  1052.  
  1053. static void Display()
  1054. /*
  1055. **  Display gnuplot results 
  1056. **  -- must post message as this thread is not drawing thread
  1057. */
  1058.     {
  1059.     WinPostMsg( hApp, WM_GNUPLOT, 0L, 0L ) ;    
  1060.     }
  1061.  
  1062.  
  1063. int GetNewFont( HWND hwnd, HPS hps ) 
  1064. /*
  1065. ** Get a new font using standard font dialog
  1066. */
  1067.     {
  1068.     static FONTDLG pfdFontdlg;      /* Font dialog info structure */
  1069.     static int i1 =1 ;
  1070.     static int     iSize ;
  1071.     char szPtList[64] ;
  1072.     HWND    hwndFontDlg;     /* Font dialog window handle */
  1073.     char    *p ; 
  1074.     char szFamilyname[FACESIZE];
  1075.  
  1076.     if( i1 ) {
  1077.         strcpy( pfdFontdlg.fAttrs.szFacename, strchr( szFontNameSize, '.' ) + 1 ) ;
  1078.         strcpy( szFamilyname, strchr( szFontNameSize, '.' ) + 1 ) ;
  1079.         sscanf( szFontNameSize, "%d", &iSize ) ;
  1080.         memset(&pfdFontdlg, 0, sizeof(FONTDLG));
  1081.  
  1082.         pfdFontdlg.cbSize = sizeof(FONTDLG);
  1083.         pfdFontdlg.hpsScreen = hps;
  1084.  /*   szFamilyname[0] = 0;*/
  1085.         pfdFontdlg.pszFamilyname = szFamilyname;
  1086.         pfdFontdlg.usFamilyBufLen = FACESIZE;
  1087.         pfdFontdlg.fl = FNTS_HELPBUTTON | FNTS_CENTER | FNTS_VECTORONLY | FNTS_INITFROMFATTRS ; 
  1088.         pfdFontdlg.clrFore = CLR_BLACK;
  1089.         pfdFontdlg.clrBack = CLR_WHITE;
  1090.         pfdFontdlg.usWeight = 5 ;
  1091.         pfdFontdlg.fAttrs.usCodePage = 0;
  1092.         i1=0; 
  1093.         }
  1094.     sprintf( szPtList, "%d 8 10 12 14 18 24", iSize ) ;
  1095.     pfdFontdlg.pszPtSizeList = szPtList ;
  1096.     pfdFontdlg.fxPointSize = MAKEFIXED(iSize,0); 
  1097.     hwndFontDlg = WinFontDlg(HWND_DESKTOP, hwnd, &pfdFontdlg);
  1098.  
  1099.     if (hwndFontDlg && (pfdFontdlg.lReturn == DID_OK)) {
  1100.         iSize = FIXEDINT( pfdFontdlg.fxPointSize ) ;
  1101.         sprintf( szFontNameSize, "%d.%s", iSize, pfdFontdlg.fAttrs.szFacename ) ;
  1102.         return 1 ;
  1103.         }
  1104.     else return 0 ;
  1105.     }
  1106.