home *** CD-ROM | disk | FTP | other *** search
/ OS/2 Shareware BBS: 35 Internet / 35-Internet.zip / npmeta.zip / NPMETA.CPP < prev    next >
Text File  |  1997-06-30  |  31KB  |  862 lines

  1. /***************************************************************************
  2.  *
  3.  * File name   :  npdraw.cpp
  4.  *
  5.  *  Copyright (C) 1996 IBM Corporation
  6.  *
  7.  *      DISCLAIMER OF WARRANTIES.  The following [enclosed] code is
  8.  *      sample code created by IBM Corporation. This sample code is not
  9.  *      part of any standard or IBM product and is provided to you solely
  10.  *      for  the purpose of assisting you in the development of your
  11.  *      applications.  The code is provided "AS IS", without
  12.  *      warranty of any kind.  IBM shall not be liable for any damages
  13.  *      arising out of your use of the sample code, even if they have been
  14.  *      advised of the possibility of such damages.
  15.  *
  16.  ***************************************************************************/
  17.  
  18. #define INCL_DOS
  19. #define INCL_WIN
  20. #define INCL_DOSPROCESS
  21. #define INCL_GPI
  22. #include <os2.h>
  23.  
  24. #include <string.h>
  25. #include <stdlib.h>
  26.  
  27. #ifndef _NPAPI_H_
  28. #include "npapi.h"
  29. #endif
  30.  
  31. #include <pprintf.h>
  32. const char* szPPR="\\pipe\\printf";
  33. const char* szPPR1="\\pipe\\printf1";
  34.  
  35. #define DEBUG_PRINT
  36. #ifndef DEBUG_PRINT
  37. extern "C"
  38. int pprintf( const char* , const char* , ... ) {
  39.   return 0;
  40. }
  41. #endif
  42.  
  43. int pprMatrix( PCSZ sz, MATRIXLF* matlf ) {
  44.   return pprintf( sz, "\t%12d,%12d,%12d\n\r\t%12d,%12d,%12d\n\r\t%12d,%12d,%12d\n\r",
  45.      (int)matlf->fxM11, (int)matlf->fxM12, (int)matlf->lM13,
  46.      (int)matlf->fxM21, (int)matlf->fxM22, (int)matlf->lM23,
  47.      (int)matlf->lM31, (int)matlf->lM32, (int)matlf->lM33 );
  48. }
  49.  
  50. //
  51. // Instance state information about the plugin.
  52. //
  53. // *Developers*: Use this struct to hold per-instance
  54. //               information that you'll need in the
  55. //               various functions in this file.
  56. //
  57.  
  58. typedef struct _PluginInstance PluginInstance;
  59. typedef struct _PluginInstance
  60. {
  61.     NPWindow*       fWindow;
  62.     HWND            hWnd;
  63.     uint16          fMode;
  64.     HPS             hps;
  65.     HMF             hmf;
  66.     PCHAR           bufMeta;
  67.     ULONG           cbMeta;
  68.     ULONG           offMeta;
  69.     RECTL           rclMeta;
  70.     RECTL           rclWnd;
  71.     PFNWP           lpfnOldWndProc;
  72.     NPSavedData*    pSavedInstanceData;
  73.     PluginInstance* pNext;
  74. } PluginInstance;
  75.  
  76. MRESULT APIENTRY
  77. SubClassFunc(HWND hWnd,ULONG Message,MPARAM wParam, MPARAM lParam);
  78.  
  79. void Draw(PluginInstance *This, HPS hps, BOOL fPrinting, BOOL fReset);
  80. void SetTransform( PluginInstance *This, HPS hps, PRECTL rcl );
  81. void SetMatrix( PluginInstance *This, HPS hps, PRECTL rclWin, MATRIXLF* mtlf );
  82. void SelectMetaFile( PluginInstance *This, HMF hmf );
  83.  
  84. HMODULE DLLInstance=NULL;
  85.  
  86. #if defined ( __cplusplus )
  87. extern "C" {
  88. #endif
  89.  
  90. /* _CRT_init is the C run-time environment initialization function.         */
  91. /* It will return 0 to indicate success and -1 to indicate failure.         */
  92.    int _CRT_init(void);
  93.  
  94. /* __ctordtorInit calls the C++ run-time constructors for static objects.   */
  95.    void __ctordtorInit(void);
  96.  
  97. /* __ctordtorTerm calls the C++ run-time destructors for static objects.    */
  98.    void __ctordtorTerm(void);
  99.  
  100. #ifdef   STATIC_LINK
  101.  
  102. /* _CRT_term is the C run-time environment termination function.            */
  103. /* It only needs to be called when the C run-time functions are statically  */
  104. /* linked.                                                                  */
  105.    void _CRT_term(void);
  106.  
  107. #else
  108.  
  109. /* A clean up routine registered with DosExitList must be used if runtime   */
  110. /* calls are required at exit AND the runtime is dynamically linked.  This  */
  111. /* will guarantee that this clean up routine is run before the library DLL  */
  112. /* is terminated.  Do any application housekeeping in cleanup()             */
  113.     static void _System cleanup(ULONG ulReason);
  114.  
  115. #endif
  116.  
  117.  
  118. #if defined ( __cplusplus )
  119. }
  120. #endif
  121.  
  122.  
  123. extern "C"
  124. unsigned long _System _DLL_InitTerm(unsigned long hModule, unsigned long
  125.                                     ulFlag)
  126. {
  127.     DLLInstance = (HMODULE) hModule;
  128.     switch (ulFlag)
  129.     {
  130.         case 0:
  131.             if ( _CRT_init() == -1 )
  132.             {
  133.                 return(0UL);
  134.             }
  135. #if defined ( __cplusplus )
  136.             __ctordtorInit();
  137. #endif
  138.  
  139. #ifndef  STATIC_LINK
  140.  
  141.          /*******************************************************************/
  142.          /* A DosExitList routine must be used to clean up if runtime calls */
  143.          /* are required at exit and the runtime is dynamically linked.     */
  144.          /*******************************************************************/
  145.  
  146.             DosExitList(0x0000FF00|EXLST_ADD, cleanup);
  147. #endif
  148.             break;
  149.         case 1:
  150.  
  151. #if defined ( __cplusplus )
  152.             __ctordtorTerm();
  153. #endif
  154.  
  155. #ifdef  STATIC_LINK
  156.             _CRT_term();
  157. #endif
  158.             break;
  159.     }
  160.  
  161.     return 1;
  162. }
  163.  
  164. #ifndef  STATIC_LINK
  165. static void cleanup(ULONG ulReason)
  166. {
  167.    /* do any DLL cleanup here if needed AND if dynamically linked to the */
  168.    /* C Runtime libraries                                                */
  169.    DosExitList(EXLST_EXIT, cleanup);   /* remember to unlink ourselves   */
  170.    return ;
  171. }
  172. #endif
  173.  
  174. // A plugin instance typically will subclass the plugin's client window, so
  175. // it can get Windows messages, (such as paint, palettechanged, keybd, etc).
  176. // To do work associated with a specific plugin instance the WndProc which
  177. // receives the Windows messages, (named "SubClassFunc" herein), needs access
  178. // to the "This" (PluginInstance*) ptr.
  179. // If the plugin wants all the keyboard messages, it will have to
  180. // create a frame window with it's own accelerator table (even it it is empty)
  181. // and insure that that frame tracks the plugin window that Navigator creates,
  182. // otherwise the Navigator Accelerators will interfere with the WM_CHARs
  183. // that the plugin windows receive...
  184.  
  185. // When Navigator registers the plugin client's window class, (the class for
  186. // the window passed in NPP_SetWindow()), Navigator reserves 4
  187. // "extra" window bytes for the plugins use... at QWL_USER
  188. // Associate the hWnd with pInstance by setting the hWnd member of the
  189. // PluginInstance struct.
  190. static void AssociateInstance(HWND hWnd, PluginInstance* pInstance)
  191. {
  192.     pInstance->hWnd = hWnd;     // redundant, but usefull to get hwnd from
  193.                                 // pinstance later.
  194.     BOOL rc = WinSetWindowULong(hWnd, QWL_USER, (ULONG)pInstance);
  195. }
  196.  
  197. // Find the PluginInstance associated with this hWnd and return it
  198. static PluginInstance* GetInstance(HWND hWnd)
  199. {
  200.     return (PluginInstance*)WinQueryWindowULong(hWnd, QWL_USER);
  201. }
  202.  
  203. //----------------------------------------------------------------------------
  204. // NPP_Initialize:
  205. //----------------------------------------------------------------------------
  206. NPError NPP_Initialize(void)
  207. {
  208.     // do your one time initialization here, such as dynamically loading
  209.     // dependant DLLs
  210.     return NPERR_NO_ERROR;
  211. }
  212.  
  213.  
  214. //----------------------------------------------------------------------------
  215. // NPP_Shutdown:
  216. //----------------------------------------------------------------------------
  217. void NPP_Shutdown(void)
  218. {
  219.     // do your one time uninitialization here, such as unloading dynamically
  220.     // loaded DLLs
  221. }
  222.  
  223.  
  224. //----------------------------------------------------------------------------
  225. // NPP_New:
  226. //----------------------------------------------------------------------------
  227. NPError NP_LOADDS
  228. NPP_New(NPMIMEType pluginType,
  229.                 NPP instance,
  230.                 uint16 mode,
  231.                 int16 argc,
  232.                 char* argn[],
  233.                 char* argv[],
  234.                 NPSavedData* saved)
  235. {
  236.   if ( instance == NULL ) return NPERR_INVALID_INSTANCE_ERROR;
  237.  
  238.   instance->pdata = NPN_MemAlloc(sizeof(PluginInstance));
  239.   PluginInstance* This = (PluginInstance*) instance->pdata;
  240.  
  241.   if ( This == NULL ) return NPERR_OUT_OF_MEMORY_ERROR;
  242.   //
  243.   // *Developers*: Initialize fields of your plugin
  244.   // instance data here.  If the NPSavedData is non-
  245.   // NULL, you can use that data (returned by you from
  246.   // NPP_Destroy to set up the new plugin instance.
  247.   //
  248.  
  249.   This->fWindow = 0;
  250.   // mode is NP_EMBED, NP_FULL, or NP_BACKGROUND (see npapi.h)
  251.   This->fMode = mode;
  252.   This->hWnd = 0;
  253.   This->hps = NULL;
  254.   This->hmf = NULL;
  255.   This->bufMeta=NULL;
  256.   This->cbMeta=0;
  257.   This->offMeta=0;
  258.   This->pSavedInstanceData = saved;
  259.   This->pNext = 0;
  260.  
  261.   return NPERR_NO_ERROR;
  262. }
  263.  
  264.  
  265. //-----------------------------------------------------------------------------
  266. // NPP_Destroy:
  267. //-----------------------------------------------------------------------------
  268. NPError NP_LOADDS
  269. NPP_Destroy(NPP instance, NPSavedData** save) {
  270.   if ( instance == 0 ) return NPERR_INVALID_INSTANCE_ERROR;
  271.  
  272.   PluginInstance* This = (PluginInstance*) instance->pdata;
  273.  
  274.   //
  275.   // *Developers*: If desired, call NP_MemAlloc to create a
  276.   // NPSavedDate structure containing any state information
  277.   // that you want restored if this plugin instance is later
  278.   // recreated.
  279.   //
  280.  
  281.   if ( This ) {
  282.     // destroy hmf and PS
  283.     if ( This->hmf ) GpiDeleteMetaFile( This->hmf );
  284.     if ( This->hps ) GpiDestroyPS( This->hps );
  285.     // delete buffer
  286.     if ( This->bufMeta ) {
  287.       free( This->bufMeta );
  288.       This->bufMeta=NULL;
  289.       This->cbMeta=0;
  290.       This->offMeta=0;
  291.     }
  292.     // Remove the subclass for the client window
  293.     if ( This->hWnd ) WinSubclassWindow( This->hWnd, This->lpfnOldWndProc );
  294.     // make some saved instance data if necessary
  295.     if ( This->pSavedInstanceData == 0 ) {
  296.       // make a struct header for the data
  297.       This->pSavedInstanceData =
  298.           (NPSavedData*)NPN_MemAlloc(sizeof (struct _NPSavedData));
  299.       // fill in the struct
  300.       if ( This->pSavedInstanceData != 0 ) {
  301.         This->pSavedInstanceData->len = 0;
  302.         This->pSavedInstanceData->buf = 0;
  303.  
  304.         // replace the def below and references to it with your data
  305.         #define SIDATA "aSavedInstanceDataBlock"
  306.  
  307.         // the data
  308.         This->pSavedInstanceData->buf = NPN_MemAlloc(sizeof SIDATA);
  309.  
  310.         if( This->pSavedInstanceData->buf ) {
  311.           strcpy((char*)This->pSavedInstanceData->buf, SIDATA);
  312.           This->pSavedInstanceData->len = sizeof SIDATA;
  313.         }
  314.       }
  315.     }
  316.  
  317.     // save some instance data
  318.     *save = This->pSavedInstanceData;
  319.  
  320.     NPN_MemFree(instance->pdata);
  321.     instance->pdata = 0;
  322.   }
  323.   return NPERR_NO_ERROR;
  324. }
  325.  
  326.  
  327. //----------------------------------------------------------------------------
  328. // NPP_SetWindow:
  329. //----------------------------------------------------------------------------
  330. NPError NP_LOADDS
  331. NPP_SetWindow(NPP instance, NPWindow* window) {
  332.   pprintf( szPPR, "NPP_SetWindow\n\r" );
  333.   if ( instance == 0 ) return NPERR_INVALID_INSTANCE_ERROR;
  334.  
  335.   PluginInstance* This = (PluginInstance*) instance->pdata;
  336.  
  337.   //
  338.   // *Developers*: Before setting fWindow to point to the
  339.   // new window, you may wish to compare the new window
  340.   // info to the previous window (if any) to note window
  341.   // size changes, etc.
  342.   //
  343.  
  344.   // if window handle changed
  345.   if ( This->hWnd != (HWND)window->window ) {
  346.     pprintf( szPPR, "HWND (hmf %x) changed, %x --> %x\n\r", This->hmf, (int)This->hWnd, (int)window->window );
  347.     // remember the new window
  348.     This->fWindow = window;
  349.     if ( This->hWnd ) {
  350.       // Remove the subclass for the old client window
  351.       WinSubclassWindow(This->hWnd, This->lpfnOldWndProc);
  352.     }
  353.     // remember the new window handle
  354.     This->hWnd = (HWND)This->fWindow->window;
  355.     // subclass the window
  356.     This->lpfnOldWndProc = WinSubclassWindow(This->hWnd, SubClassFunc);
  357.     AssociateInstance( This->hWnd, This );
  358.     /* paint a background for the drawing */
  359.     WinQueryWindowRect( This->hWnd, &This->rclWnd );
  360. //    WinFillRect( This->hps, &This->rclWnd, CLR_PALEGRAY );
  361.     // destroy old PS and create new PS
  362.     if ( This->hps ) GpiDestroyPS( This->hps );
  363.     HDC hdc = WinQueryWindowDC( This->hWnd );
  364.     if ( !hdc ) hdc = WinOpenWindowDC( This->hWnd );
  365.     SIZEL siz={ 0, 0 };
  366.     HAB hab=WinQueryAnchorBlock( This->hWnd );
  367.     This->hps = GpiCreatePS( hab, hdc, &siz,
  368.                                   PU_PELS | GPIT_NORMAL | GPIA_ASSOC );
  369.     pprintf( szPPR, "GpiCreatePS, hdc=%x, hps=%x\n\r", (int)hdc, (int)This->hps );
  370.     if ( !This->hps ) {
  371.       pprintf( szPPR, "GpiCreatePS failed, Err=%x\n\r",
  372.         WinGetLastError( hab ) );
  373.     }
  374.     SetTransform( This, This->hps, &This->rclWnd );
  375.   } else { // check if window coordinates changed.
  376.            //It may happens for full-screan
  377.     RECTL rcl;
  378.     WinQueryWindowRect( This->hWnd, &rcl );
  379.     if ( memcmp( &This->rclWnd, &rcl, sizeof( rcl ) ) ) {
  380.       pprintf( szPPR, "Rect (hmf %x) changed, ( %d, %d ) - ( %d, %d ) --> ( %d, %d ) - ( %d, %d )\n\r",
  381.         This->hmf,
  382.         This->rclWnd.xLeft, This->rclWnd.yBottom, This->rclWnd.xRight, This->rclWnd.yTop,
  383.         rcl.xLeft, rcl.yBottom, rcl.xRight, rcl.yTop );
  384.       memcpy( &This->rclWnd, &rcl, sizeof( rcl ) );
  385.       SetTransform( This, This->hps, &This->rclWnd );
  386.     }
  387.   }
  388.   return NPERR_NO_ERROR;
  389. }
  390.  
  391.  
  392. //----------------------------------------------------------------------------
  393. // NPP_NewStream:
  394. //----------------------------------------------------------------------------
  395. NPError NP_LOADDS
  396. NPP_NewStream(NPP instance,
  397.               NPMIMEType type,
  398.               NPStream *stream,
  399.               NPBool seekable,
  400.               uint16 *stype)
  401. {
  402.   if ( instance == 0 ) return NPERR_INVALID_INSTANCE_ERROR;
  403.   PluginInstance* This = (PluginInstance*) instance->pdata;
  404. //  pprintf( szPPR, "NPP_NewStream( url=%s, end=%d )\n\r", stream->url, stream->end );
  405.   // delete buffer
  406.   if ( This->bufMeta ) {
  407.     free( This->bufMeta );
  408.     This->bufMeta=NULL;
  409.     This->cbMeta=0;
  410.     This->offMeta=0;
  411.   }
  412.   if ( stream->end ) This->cbMeta=stream->end;
  413.   else This->cbMeta=0x10000; // 64K initial size for unknown size stream
  414.   //create buffer
  415.   This->bufMeta=(char*)malloc( This->cbMeta );
  416.  
  417.   // if your plugin must operate file based, you may wish to do this:
  418.   //    *stype = NP_ASFILE;
  419.   // remember, though, that use of NP_ASFILE is strongly discouraged;
  420.   // your plugin should attempt to work with data as it comes in on
  421.   // the stream if at all possible
  422.  
  423. //  *stype = NP_ASFILE;
  424.  
  425.   return NPERR_NO_ERROR;
  426. }
  427.  
  428.  
  429. //
  430. // *Developers*:
  431. // These next 2 functions are directly relevant in a plug-in which handles the
  432. // data in a streaming manner.  If you want zero bytes because no buffer space
  433. // is YET available, return 0.  As long as the stream has not been written
  434. // to the plugin, Navigator will continue trying to send bytes.  If the plugin
  435. // doesn't want them, just return some large number from NPP_WriteReady(), and
  436. // ignore them in NPP_Write().  For a NP_ASFILE stream, they are still called
  437. // but can safely be ignored using this strategy.
  438. //
  439.  
  440. //----------------------------------------------------------------------------
  441. // NPP_WriteReady:
  442. //----------------------------------------------------------------------------
  443. int32 NP_LOADDS
  444. NPP_WriteReady(NPP instance, NPStream *stream) {
  445.   if ( instance == 0 ) return NPERR_INVALID_INSTANCE_ERROR;
  446.   PluginInstance* This = (PluginInstance*) instance->pdata;
  447.   int rest=This->cbMeta-This->offMeta;
  448.   if ( rest<=0 ) {
  449.     This->bufMeta=(char*)realloc( This->bufMeta, This->cbMeta*=2 );
  450.     rest=This->cbMeta-This->offMeta;
  451.   }
  452.   return rest;   // Number of bytes ready to accept in NPP_Write()
  453. }
  454.  
  455.  
  456. //----------------------------------------------------------------------------
  457. // NPP_Write:
  458. //----------------------------------------------------------------------------
  459. int32 NP_LOADDS
  460. NPP_Write(NPP instance, NPStream *stream,
  461.           int32 offset, int32 len, void *buffer) {
  462.   if ( instance == 0 ) return NPERR_INVALID_INSTANCE_ERROR;
  463.   PluginInstance* This = (PluginInstance*) instance->pdata;
  464. //  pprintf( szPPR, "NPP_Write off=%d len=%d\n\r", offset, len );
  465.   if ( This->bufMeta ) {
  466.     int rest=This->cbMeta-offset;
  467.     if ( len>rest ) len=rest;
  468.     memcpy( This->bufMeta+offset, buffer, len );
  469.     This->offMeta=offset+len;
  470.   }
  471.   return len;
  472. }
  473.  
  474.  
  475. //----------------------------------------------------------------------------
  476. // NPP_DestroyStream:
  477. //----------------------------------------------------------------------------
  478. NPError NP_LOADDS
  479. NPP_DestroyStream(NPP instance, NPStream *stream, NPError reason) {
  480.   if ( instance == 0 ) return NPERR_INVALID_INSTANCE_ERROR;
  481.   PluginInstance* This = (PluginInstance*) instance->pdata;
  482.  
  483.   if ( reason == NPRES_DONE && This->bufMeta ) {
  484.     // create metafile from buffer
  485.  
  486.     // 1-st, create empty metafile
  487.     HAB hab=WinQueryAnchorBlock( This->hWnd );
  488.     DEVOPENSTRUC dop;
  489.     dop.pszLogAddress = (PSZ) NULL;
  490.     dop.pszDriverName = "DISPLAY";
  491.     HDC hdcMeta = DevOpenDC( hab,
  492.         OD_METAFILE,                 /* Metafile device context             */
  493.         "*",                         /* Ignores OS2.INI                     */
  494.         2L,                          /* Uses first two fields               */
  495.         (PDEVOPENDATA) &dop,         /* Device information                  */
  496.         (HDC) NULLHANDLE );          /* Compatible device context           */
  497.     SIZEL sizlPage={ 0, 0 };
  498.     HPS hpsMeta = GpiCreatePS( hab, hdcMeta, &sizlPage, PU_PELS | GPIA_ASSOC );
  499.     GpiAssociate( hpsMeta, (HDC)NULLHANDLE );
  500.     HMF hmf = DevCloseDC( hdcMeta );
  501.     GpiDestroyPS( hpsMeta );
  502.  
  503.     // 2-nd, add real data
  504.     GpiSetMetaFileBits( hmf, 0, This->offMeta, This->bufMeta );
  505.     SelectMetaFile( This, hmf );
  506.   }
  507.   // delete buffer
  508.   if ( This->bufMeta ) {
  509.     free( This->bufMeta );
  510.     This->bufMeta=NULL;
  511.     This->cbMeta=0;
  512.     This->offMeta=0;
  513.   }
  514.   return NPERR_NO_ERROR;
  515. }
  516.  
  517.  
  518. //----------------------------------------------------------------------------
  519. // NPP_StreamAsFile:
  520. //----------------------------------------------------------------------------
  521. void NP_LOADDS
  522. NPP_StreamAsFile(NPP instance, NPStream *stream, const char* fname) {
  523.   if ( instance == 0 ) return;
  524.   PluginInstance* This = (PluginInstance*) instance->pdata;
  525.   if ( This ) {
  526.     HAB hab=WinQueryAnchorBlock( This->hWnd );
  527.     HMF hmf=GpiLoadMetaFile( hab, fname );
  528.     if ( hmf ) {
  529.       SelectMetaFile( This, hmf );
  530.     } else pprintf( szPPR, "GpiLoadMetaFile( %s ) failed\n\r", fname );
  531.   }
  532. }
  533.  
  534.  
  535. //----------------------------------------------------------------------------
  536. // NPP_Print:
  537. //----------------------------------------------------------------------------
  538. void NP_LOADDS
  539. NPP_Print(NPP instance, NPPrint* printInfo) {
  540.   pprintf( szPPR, "NPP_Print\n\r" );
  541.   if ( printInfo == 0 ) return;  // trap invalid parm
  542.   if ( instance ) {
  543.     PluginInstance* This = (PluginInstance*) instance->pdata;
  544.  
  545.     if ( printInfo->mode == NP_FULL ) {
  546.       //
  547.       // *Developers*: If your plugin would like to take over
  548.       // printing completely when it is in full-screen mode,
  549.       // set printInfo->pluginPrinted to TRUE and print your
  550.       // plugin as you see fit.  If your plugin wants Netscape
  551.       // to handle printing in this case, set printInfo->pluginPrinted
  552.       // to FALSE (the default) and do nothing.  If you do want
  553.       // to handle printing yourself, printOne is true if the
  554.       // print button (as opposed to the print menu) was clicked.
  555.       // On the Macintosh, platformPrint is a THPrint; on Windows,
  556.       // platformPrint is a structure (defined in npapi.h) containing
  557.       // the printer name, port, etc.
  558.       //
  559.       void* platformPrint = printInfo->print.fullPrint.platformPrint;
  560.       NPBool printOne = printInfo->print.fullPrint.printOne;
  561.  
  562.       printInfo->print.fullPrint.pluginPrinted = FALSE; // Do the default
  563.  
  564.     } else {   // If not fullscreen, we must be embedded
  565.       //
  566.       // *Developers*: If your plugin is embedded, or is full-screen
  567.       // but you returned false in pluginPrinted above, NPP_Print
  568.       // will be called with mode == NP_EMBED.  The NPWindow
  569.       // in the printInfo gives the location and dimensions of
  570.       // the embedded plugin on the printed page.  On the Macintosh,
  571.       // platformPrint is the printer port; on Windows, platformPrint
  572.       // is the handle to the printing device context. On OS/2,
  573.       // platformPrint is the printing presentation space (HPS).
  574.       //
  575.       NPWindow* printWindow = &(printInfo->print.embedPrint.window);
  576.  
  577.       /* get Presentation Space and save it */
  578.       void* platformPrint = printInfo->print.embedPrint.platformPrint;
  579.       HPS hps = (HPS)platformPrint;
  580.  
  581.       /* create GPI various data structures about the drawing area */
  582.       POINTL offWindow = { (int)printWindow->x, (int)printWindow->y };
  583.       RECTL rect = { (int)printWindow->x,
  584.                      (int)printWindow->y,
  585.                      (int)printWindow->x + (int)printWindow->width,
  586.                      (int)printWindow->y + (int)printWindow->height };
  587.  
  588.       /* get model transform so origin is 0,0 */
  589. //      MATRIXLF matModel;
  590. //      GpiQueryModelTransformMatrix( hps, 9L, &matModel );
  591. //      GpiTranslate( hps, &matModel, TRANSFORM_ADD, &offWindow );
  592. //      GpiSetModelTransformMatrix( hps, 9L, &matModel, TRANSFORM_REPLACE );
  593.  
  594.       if ( This->hmf ) {
  595. //        pprintf( szPPR, "PrintWindow ( %d, %d ) - ( %d, %d )\n\r",
  596. //        rect.xLeft, rect.yBottom, rect.xRight, rect.yTop );
  597.         MATRIXLF mtlf;
  598. /*
  599.         GpiQueryDefaultViewMatrix( hps, 9L, &mtlf );
  600.         pprintf( szPPR, "GpiQueryDefaultViewMatrix\n\r" );
  601.         pprMatrix( szPPR, &mtlf );
  602.         GpiQueryModelTransformMatrix( hps, 9L, &mtlf );
  603.         pprintf( szPPR, "GpiQueryModelTransformMatrix\n\r" );
  604.         pprMatrix( szPPR, &mtlf );
  605.         GpiQueryViewingTransformMatrix( hps, 9L, &mtlf );
  606.         pprintf( szPPR, "GpiQueryViewingTransformMatrix\n\r" );
  607.         pprMatrix( szPPR, &mtlf );
  608.  
  609.         SIZEL siz;
  610.         LONG lOpt=GpiQueryPS( hps, &siz );
  611.         pprintf( szPPR, "GpiQueryPS : (%d, %d), %x\n\r", siz.cx, siz.cy, lOpt );
  612. */
  613.         HAB hab=WinQueryAnchorBlock( This->hWnd );
  614.  
  615.         SetMatrix( This, hps, &rect, &mtlf );
  616.         // for correct GpiPlayMetaFile output
  617.         if ( GpiSetViewingTransformMatrix( hps, 9L, &mtlf, TRANSFORM_REPLACE ) ) {
  618. //          pprintf( szPPR, "GpiSetViewingTransformMatrix done\n\r" );
  619. //          pprMatrix( szPPR, &mtlf );
  620.         } else {
  621.           pprintf( szPPR, "GpiSetViewingTransformMatrix failed, Err=%x\n\r",
  622.             WinGetLastError( hab ) );
  623.         }
  624. /*
  625.         if ( GpiSetDefaultViewMatrix( hps, 9L, &mtlf, TRANSFORM_REPLACE ) ) {
  626.           pprintf( szPPR, "GpiSetDefaultViewMatrix done\n\r" );
  627.           pprMatrix( szPPR, &mtlf );
  628.         } else {
  629.           pprintf( szPPR, "GpiSetDefaultViewMatrix failed, Err=%x\n\r",
  630.             WinGetLastError( hab ) );
  631.         }
  632. */
  633.         // for correct box display
  634.         if ( GpiSetModelTransformMatrix( hps, 9L, &mtlf, TRANSFORM_REPLACE ) ) {
  635. //          pprintf( szPPR, "GpiSetModelTransformMatrix done\n\r" );
  636. //          pprMatrix( szPPR, &mtlf );
  637.         } else {
  638.           pprintf( szPPR, "GpiSetModelTransformMatrix failed, Err=%x\n\r",
  639.             WinGetLastError( hab ) );
  640.         }
  641.  
  642.       }
  643.       /* draw using common drawing routine */
  644.       Draw( This, hps, TRUE, FALSE );
  645.     }
  646.   }
  647. }
  648.  
  649.  
  650. //----------------------------------------------------------------------------
  651. // NPP_HandleEvent:
  652. // Mac-only.
  653. //----------------------------------------------------------------------------
  654. int16 NP_LOADDS NPP_HandleEvent(NPP instance, void* event)
  655. {
  656.     NPBool eventHandled = FALSE;
  657.     if (instance == 0   )
  658.         return eventHandled;
  659.  
  660.     PluginInstance* This = (PluginInstance*) instance->pdata;
  661.  
  662.     //
  663.     // *Developers*: The "event" passed in is a Macintosh
  664.     // EventRecord*.  The event.what field can be any of the
  665.     // normal Mac event types, or one of the following additional
  666.     // types defined in npapi.h: getFocusEvent, loseFocusEvent,
  667.     // adjustCursorEvent.  The focus events inform your plugin
  668.     // that it will become, or is no longer, the recepient of
  669.     // key events.  If your plugin doesn't want to receive key
  670.     // events, return false when passed at getFocusEvent.  The
  671.     // adjustCursorEvent is passed repeatedly when the mouse is
  672.     // over your plugin; if your plugin doesn't want to set the
  673.     // cursor, return false.  Handle the standard Mac events as
  674.     // normal.  The return value for all standard events is currently
  675.     // ignored except for the key event: for key events, only return
  676.     // true if your plugin has handled that particular key event.
  677.     //
  678.  
  679.     return eventHandled;
  680. }
  681.  
  682. //
  683. // Here is a sample subclass function.
  684. //
  685. MRESULT APIENTRY
  686. SubClassFunc(  HWND hWnd,
  687.                ULONG Message,
  688.                MPARAM wParam,
  689.                MPARAM lParam)
  690. {
  691.   PluginInstance *This = GetInstance(hWnd);
  692.  
  693.   switch(Message) {
  694.   case WM_REALIZEPALETTE:
  695.     WinInvalidateRect(hWnd, 0, TRUE);
  696.     WinUpdateWindow(hWnd);
  697.     return 0;
  698.     break;
  699.  
  700.   case WM_PAINT:
  701.     {
  702.  
  703.       RECTL rcl;
  704.       WinQueryWindowRect( This->hWnd, &rcl );
  705.       pprintf( szPPR, "Rect (hmf %x) : ( %d, %d ) - ( %d, %d )\n\r",
  706.         This->hmf,
  707.         rcl.xLeft, rcl.yBottom, rcl.xRight, rcl.yTop );
  708.       WinInvalidateRect(hWnd, 0, TRUE);
  709.  
  710.       RECTL invalidRect;
  711.       WinBeginPaint( hWnd, This->hps, &invalidRect );
  712.  
  713.       /* draw using common drawing routine */
  714.       Draw( This, This->hps, FALSE, TRUE );
  715.       WinEndPaint( This->hps );
  716.  
  717.       return (MRESULT)0;
  718.     }
  719.     break;
  720.  
  721.   default:
  722.     break;
  723.   }
  724.  
  725.   return ((PFNWP)This->lpfnOldWndProc)( hWnd, Message, wParam, lParam );
  726. }
  727.  
  728. void Draw( PluginInstance *This, HPS hps, BOOL fPrinting, BOOL fReset ) {
  729. /*
  730.   if (fPrinting) {
  731.     // You do not normally print a streaming plugin. We will display a
  732.     // bounding rectangle and a message string (if it fits)
  733.     POINTL ptl = { 0, 0 };
  734.     GpiMove(hps, &ptl);
  735.     GpiSetColor(hps, CLR_BLACK);
  736.     GpiBox(hps, DRO_OUTLINE, endPoint, 0L, 0L);
  737.     ptl.x += 40;
  738.     ptl.y = endPoint->y/4*3;
  739.     char *msg = "NPDRAW Plugin";
  740.     GpiCharStringAt(hps, &ptl, strlen(msg), msg);
  741.     ptl.y = endPoint->y/4*2;
  742.     msg = "does not print";
  743.     GpiCharStringAt(hps, &ptl, strlen(msg), msg);
  744.     ptl.y = endPoint->y/4;
  745.     msg = "streaming data.";
  746.     GpiCharStringAt(hps, &ptl, strlen(msg), msg);
  747.   } else
  748. */
  749.   {
  750.     if ( This->hmf ) {
  751.       LONG lSegCount=0;
  752.       char szDesc[20];
  753.       LONG opt[9]={0,LT_DEFAULT,0,LC_LOADDISC,RES_NORESET,
  754.                    SUP_DEFAULT,CTAB_REPLACE,CREA_DEFAULT,
  755.                    DDEF_DEFAULT};
  756.       HAB hab=WinQueryAnchorBlock( This->hWnd );
  757.       LONG lHits=GpiPlayMetaFile( hps, This->hmf, 9L, opt, &lSegCount,
  758.         sizeof( szDesc ), szDesc );
  759.       if ( lHits!=GPI_OK ) pprintf( szPPR, "GpiPlayMetaFile error %d (%s)\n\r", lHits, szDesc );
  760.       else pprintf( szPPR, "GpiPlayMetaFile OK (%s)\n\r", szDesc );
  761.       if ( fReset ) {
  762.         pprintf( szPPR, "Reset hps\n\r" );
  763.         MATRIXLF   matlfSaveTransform;
  764.         if ( GpiQueryDefaultViewMatrix( hps, 9L, &matlfSaveTransform ) ) {
  765.           if ( GpiResetPS( hps, GRES_ALL ) ) {
  766.             if ( GpiSetDefaultViewMatrix( hps, 9L, &matlfSaveTransform, TRANSFORM_REPLACE ) ) {
  767. //              pprintf( szPPR, "DefaultViewMatrix preserved:\n\r" );
  768. //              pprMatrix( szPPR, &matlfSaveTransform );
  769.             } else {
  770.               pprintf( szPPR, "GpiSetDefaultViewMatrix failed, Err=%x\n\r",
  771.                 WinGetLastError( hab ) );
  772.             }
  773.           } else {
  774.             pprintf( szPPR, "GpiResetPS failed, Err=%x\n\r",
  775.               WinGetLastError( hab ) );
  776.           }
  777.         } else {
  778.           pprintf( szPPR, "GpiQueryDefaultViewMatrix failed, Err=%x\n\r",
  779.             WinGetLastError( hab ) );
  780.         }
  781.       }
  782.     }
  783.   }
  784. }
  785.  
  786. void SetTransform( PluginInstance *This, HPS hps, PRECTL rclWin ) {
  787.   if ( !This->hmf ) return;
  788.   HAB hab=WinQueryAnchorBlock( This->hWnd );
  789.   MATRIXLF mtlf;
  790.   SetMatrix( This, hps, rclWin, &mtlf );
  791.   if ( GpiSetDefaultViewMatrix( hps, 9L, &mtlf, TRANSFORM_REPLACE ) ) {
  792. //    pprintf( szPPR, "GpiSetDefaultViewMatrix done\n\r" );
  793. //    pprMatrix( szPPR, &mtlf );
  794.   } else {
  795.     pprintf( szPPR, "GpiSetDefaultViewMatrix failed, Err=%x\n\r",
  796.       WinGetLastError( hab ) );
  797.   }
  798. }
  799.  
  800. void SetMatrix( PluginInstance *This, HPS hps, PRECTL rclWin, MATRIXLF* mtlf ) {
  801.   if ( !This->hmf ) return;
  802.   HAB hab=WinQueryAnchorBlock( This->hWnd );
  803.   pprintf( szPPR, "Metafile rect (%d, %d) - (%d, %d)\n\r",
  804.     This->rclMeta.xLeft, This->rclMeta.yBottom, This->rclMeta.xRight, This->rclMeta.yTop );
  805.   pprintf( szPPR, "Window rect (%d, %d) - (%d, %d)\n\r",
  806.     rclWin->xLeft, rclWin->yBottom, rclWin->xRight, rclWin->yTop );
  807.   int dxMeta=This->rclMeta.xRight-This->rclMeta.xLeft;
  808.   int dyMeta=This->rclMeta.yTop-This->rclMeta.yBottom;
  809.   int dxWin=rclWin->xRight-rclWin->xLeft;
  810.   int dyWin=rclWin->yTop-rclWin->yBottom;
  811.   FIXED afxScale[2] = { (dxWin*0x10000)/dxMeta,
  812.                         (dyWin*0x10000)/dyMeta };
  813.   POINTL ptlScaleOffset = { rclWin->xLeft-This->rclMeta.xLeft,
  814.                             rclWin->yBottom-This->rclMeta.yBottom };
  815.   if ( GpiTranslate( hps, mtlf, TRANSFORM_REPLACE, &ptlScaleOffset ) ) {
  816. //    pprintf( szPPR, "offset= (%12d,%12d)\n\r", ptlScaleOffset.x, ptlScaleOffset.y );
  817. //    pprMatrix( szPPR, mtlf );
  818.   } else {
  819.     pprintf( szPPR, "GpiTranslate failed, Err=%x\n\r",
  820.       WinGetLastError( hab ) );
  821.   }
  822.   ptlScaleOffset.x=rclWin->xLeft;
  823.   ptlScaleOffset.y=rclWin->yBottom;
  824.   if ( GpiScale( hps, mtlf, TRANSFORM_ADD, afxScale, &ptlScaleOffset ) ) {
  825. //    pprintf( szPPR, "scale= (%12d,%12d)\n\r", afxScale[0], afxScale[1] );
  826. //    pprMatrix( szPPR, mtlf );
  827.   } else {
  828.     pprintf( szPPR, "GpiScale failed, Err=%x\n\r",
  829.       WinGetLastError( hab ) );
  830.   }
  831. }
  832.  
  833. void SelectMetaFile( PluginInstance *This, HMF hmf ) {
  834.   if ( This->hmf ) GpiDeleteMetaFile( This->hmf );
  835.   This->hmf=hmf;
  836.   HAB hab=WinQueryAnchorBlock( This->hWnd );
  837.   HPS hps=This->hps;
  838.   if ( !hps ) {
  839.     pprintf( szPPR, "No hps ???\n\r" );
  840.     return;
  841.   }
  842.   //calculate bounds
  843.   HDC hdc = WinQueryWindowDC( This->hWnd );
  844.   if ( !hdc ) hdc = WinOpenWindowDC( This->hWnd );
  845.   GpiResetBoundaryData( hps );
  846.   if ( GpiAssociate( hps, NULL ) ) {
  847.     GpiSetDrawControl( hps, DCTL_BOUNDARY, DCTL_ON );
  848.     Draw( This, hps, FALSE, FALSE );
  849.     if ( GpiQueryBoundaryData( hps, &This->rclMeta ) && (This->rclMeta.xLeft<This->rclMeta.xRight) ) {
  850.       if ( !GpiAssociate( hps, hdc ) ) pprintf( szPPR, "GpfAssociate( hps, hdc ) failed\n\r" );
  851.       GpiSetDrawControl( hps, DCTL_BOUNDARY, DCTL_OFF );
  852.       GpiResetPS( hps, GRES_ALL);
  853.       SetTransform( This, hps, &This->rclWnd );
  854.     } else {
  855.       pprintf( szPPR, "GpiQueryBoundaryData failed, Err=%x\n\r",
  856.         WinGetLastError( hab ) );
  857.     }
  858.   } else pprintf( szPPR, "GpfAssociate( hps, NULL ) failed\n\r" );
  859.   // invalidate window to ensure a redraw
  860.   WinInvalidateRect( This->hWnd, 0, TRUE );
  861. }
  862.