home *** CD-ROM | disk | FTP | other *** search
/ OS/2 Shareware BBS: 10 Tools / 10-Tools.zip / os2plug.exe / SAMPLE / NPDRAW / npdraw.cpp < prev    next >
Text File  |  1996-12-06  |  27KB  |  775 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. #include <IString.hpp>
  28. #include <strstrea.h>
  29.  
  30. #ifndef _NPAPI_H_
  31. #include "npapi.h"
  32. #endif
  33.  
  34. #include "draw.h"
  35.  
  36. //
  37. // Instance state information about the plugin.
  38. //
  39. // *Developers*: Use this struct to hold per-instance
  40. //               information that you'll need in the
  41. //               various functions in this file.
  42. //
  43.  
  44. typedef struct _PluginInstance PluginInstance;
  45. typedef struct _PluginInstance
  46. {
  47.     NPWindow*       fWindow;
  48.     HWND            hWnd;
  49.     uint16          fMode;
  50.     HPS             hps;
  51.     NPStream*       Stream;
  52.     ULONG           SegmentID;
  53.     PFNWP           lpfnOldWndProc;
  54.     NPSavedData*    pSavedInstanceData;
  55.     PluginInstance* pNext;
  56. } PluginInstance;
  57.  
  58. MRESULT APIENTRY
  59. SubClassFunc(HWND hWnd,ULONG Message,MPARAM wParam, MPARAM lParam);
  60.  
  61. void Draw(PluginInstance *This, HPS hps, POINTL *endPoint, BOOL fPrinting);
  62. void parseStream(NPP instance, PluginInstance *This, istrstream *str, ULONG len);
  63.  
  64. HMODULE DLLInstance;
  65.  
  66. extern "C" {
  67.  #if defined ( __cplusplus )
  68.    void __ctordtorInit(void);
  69.    void __ctordtorTerm(void);
  70.  #endif
  71. }
  72.  
  73. /* _CRT_init is the C run-time environment initialization function.         */
  74. /* It will return 0 to indicate success and -1 to indicate failure.         */
  75. extern "C"
  76. int _CRT_init(void);
  77.  
  78. #ifdef   STATIC_LINK
  79. /* _CRT_term is the C run-time environment termination function.            */
  80. /* It only needs to be called when the C run-time functions are statically  */
  81. /* linked.                                                                  */
  82. extern "C"
  83. void _CRT_term(void);
  84.  
  85. #else
  86.  
  87. /* A clean up routine registered with DosExitList must be used if runtime   */
  88. /* calls are required at exit AND the runtime is dynamically linked.  This  */
  89. /* will guarantee that this clean up routine is run before the library DLL  */
  90. /* is terminated.                                                           */
  91.  
  92. static void _System cleanup(ULONG ulReason);
  93. #endif
  94.  
  95.  
  96. /* __ctordtorInit is the C++ run-time environment initialization function.  */
  97. /* It is required to initialize static objects and destructors are setup    */
  98. extern "C"
  99.    void __ctordtorInit(void);
  100.  
  101.  
  102. /* __ctordtorInit is the C++ run-time environment initialization function.  */
  103. /* It is required to insure static objects destructors are run              */
  104. /* You must call this before calling _CRT_term()                            */
  105. extern "C"
  106.    void __ctordtorInit(void);
  107.  
  108. extern "C"
  109. unsigned long _System _DLL_InitTerm(unsigned long hModule, unsigned long
  110.                                     ulFlag)
  111. {
  112.     DLLInstance = (HMODULE) hModule;
  113.     switch (ulFlag)
  114.     {
  115.         case 0:
  116.             if ( _CRT_init() == -1 )
  117.             {
  118.                 return(0UL);
  119.             }
  120. #if defined ( __cplusplus )
  121.             __ctordtorInit();
  122. #endif
  123.  
  124. #ifndef  STATIC_LINK
  125.  
  126.          /*******************************************************************/
  127.          /* A DosExitList routine must be used to clean up if runtime calls */
  128.          /* are required at exit and the runtime is dynamically linked.     */
  129.          /*******************************************************************/
  130.  
  131.             DosExitList(0x0000FF00|EXLST_ADD, cleanup);
  132. #endif
  133.             break;
  134.         case 1:
  135.  
  136. #if defined ( __cplusplus )
  137.             __ctordtorTerm();
  138. #endif
  139.  
  140. #ifdef  STATIC_LINK
  141.             _CRT_term();
  142. #endif
  143.             break;
  144.     }
  145.  
  146.     return 1;
  147. }
  148.  
  149. #ifndef  STATIC_LINK
  150. static void cleanup(ULONG ulReason)
  151. {
  152.    /* do any DLL cleanup here if needed AND if dynamically linked to the */
  153.    /* C Runtime libraries                                                */
  154.    DosExitList(EXLST_EXIT, cleanup);
  155.    return ;
  156. }
  157. #endif
  158.  
  159. // A plugin instance typically will subclass the plugin's client window, so
  160. // it can get Windows messages, (such as paint, palettechanged, keybd, etc).
  161. // To do work associated with a specific plugin instance the WndProc which
  162. // receives the Windows messages, (named "SubClassFunc" herein), needs access
  163. // to the "This" (PluginInstance*) ptr.
  164.  
  165. //* OS2 bugbug -- we need to reserve 4 bytes of window words to correct this
  166. //  gorp.....
  167.  
  168. // When Navigator registers the plugin client's window class, (the class for
  169. // the window passed in NPP_SetWindow()), Navigator does not reserve any
  170. // "extra" windows bytes.  If it had, the plugin could simply have stored its
  171. // "This" (PluginInstance*) ptr in the extra bytes.  But Nav did not, and the
  172. // plugin cannot, so a different technique must be used.  The technique used
  173. // is to keep a linked list of PluginInstance structures, and walk the list
  174. // to find which one is associated with the window handle.  Inefficient,
  175. // grungy, complicates the code, etc.  C'est la vie ...
  176.  
  177. PluginInstance* g_pHeadInstanceList = 0;
  178.  
  179. // Associate the hWnd with pInstance by setting the hWnd member of the
  180. // PluginInstance struct.  Also, add the PluginInstance struct to the list
  181. // if necessary
  182. static void AssociateInstance(HWND hWnd, PluginInstance* pInstance)
  183. {
  184.     pInstance->hWnd = hWnd;     // redundant, but usefull to get hwnd from
  185.                                 // pinstance later.
  186.     BOOL rc = WinSetWindowULong(hWnd, QWL_USER, (ULONG)pInstance);
  187. }
  188.  
  189. // Find the PluginInstance associated with this hWnd and return it
  190. static PluginInstance* GetInstance(HWND hWnd)
  191. {
  192.     return (PluginInstance*)WinQueryWindowULong(hWnd, QWL_USER);
  193. }
  194.  
  195. //----------------------------------------------------------------------------
  196. // NPP_Initialize:
  197. //----------------------------------------------------------------------------
  198. NPError NPP_Initialize(void)
  199. {
  200.     // do your one time initialization here, such as dynamically loading
  201.     // dependant DLLs
  202.     return NPERR_NO_ERROR;
  203. }
  204.  
  205.  
  206. //----------------------------------------------------------------------------
  207. // NPP_Shutdown:
  208. //----------------------------------------------------------------------------
  209. void NPP_Shutdown(void)
  210. {
  211.     // do your one time uninitialization here, such as unloading dynamically
  212.     // loaded DLLs
  213. }
  214.  
  215.  
  216. //----------------------------------------------------------------------------
  217. // NPP_New:
  218. //----------------------------------------------------------------------------
  219. NPError NP_LOADDS
  220. NPP_New(NPMIMEType pluginType,
  221.                 NPP instance,
  222.                 uint16 mode,
  223.                 int16 argc,
  224.                 char* argn[],
  225.                 char* argv[],
  226.                 NPSavedData* saved)
  227. {
  228.     if (instance == NULL)
  229.         return NPERR_INVALID_INSTANCE_ERROR;
  230.  
  231.     instance->pdata = NPN_MemAlloc(sizeof(PluginInstance));
  232.     PluginInstance* This = (PluginInstance*) instance->pdata;
  233.  
  234.     if (This == NULL)
  235.         return NPERR_OUT_OF_MEMORY_ERROR;
  236.     //
  237.     // *Developers*: Initialize fields of your plugin
  238.     // instance data here.  If the NPSavedData is non-
  239.     // NULL, you can use that data (returned by you from
  240.     // NPP_Destroy to set up the new plugin instance.
  241.     //
  242.  
  243.     This->fWindow = 0;
  244.     // mode is NP_EMBED, NP_FULL, or NP_BACKGROUND (see npapi.h)
  245.     This->fMode = mode;
  246.     This->hWnd = 0;
  247.     This->hps = NULL;
  248.     This->Stream = 0;
  249.     This->SegmentID = 0;
  250.     This->pSavedInstanceData = saved;
  251.     This->pNext = 0;
  252.  
  253.     // test get URL - open new window every time this plugin is used
  254.     // NPN_GetURL(instance, "http://home.netscape.com/", "_blank");
  255.  
  256.     return NPERR_NO_ERROR;
  257. }
  258.  
  259.  
  260. //-----------------------------------------------------------------------------
  261. // NPP_Destroy:
  262. //-----------------------------------------------------------------------------
  263. NPError NP_LOADDS
  264. NPP_Destroy(NPP instance, NPSavedData** save)
  265. {
  266.     if (instance == 0   )
  267.         return NPERR_INVALID_INSTANCE_ERROR;
  268.  
  269.     PluginInstance* This = (PluginInstance*) instance->pdata;
  270.  
  271.     //
  272.     // *Developers*: If desired, call NP_MemAlloc to create a
  273.     // NPSavedDate structure containing any state information
  274.     // that you want restored if this plugin instance is later
  275.     // recreated.
  276.     //
  277.  
  278.     if (This != 0   )
  279.     {
  280.         // destroy old PS and create new PS
  281.         if (! This->hps)
  282.             GpiDestroyPS(This->hps);
  283.  
  284.         // Remove the subclass for the client window
  285.         if(This->hWnd)
  286.         {
  287.             WinSubclassWindow(This->hWnd, This->lpfnOldWndProc);
  288.         }
  289.  
  290.         // make some saved instance data if necessary
  291.         if(This->pSavedInstanceData == 0   ) {
  292.             // make a struct header for the data
  293.             This->pSavedInstanceData =
  294.                 (NPSavedData*)NPN_MemAlloc(sizeof (struct _NPSavedData));
  295.  
  296.             // fill in the struct
  297.             if(This->pSavedInstanceData != 0   ) {
  298.                 This->pSavedInstanceData->len = 0;
  299.                 This->pSavedInstanceData->buf = 0   ;
  300.  
  301.                 // replace the def below and references to it with your data
  302.                 #define SIDATA "aSavedInstanceDataBlock"
  303.  
  304.                 // the data
  305.                 This->pSavedInstanceData->buf = NPN_MemAlloc(sizeof SIDATA);
  306.  
  307.                 if(This->pSavedInstanceData->buf != 0   ) {
  308.                     strcpy((char*)This->pSavedInstanceData->buf, SIDATA);
  309.                     This->pSavedInstanceData->len = sizeof SIDATA;
  310.                 }
  311.             }
  312.         }
  313.  
  314.         // save some instance data
  315.         *save = This->pSavedInstanceData;
  316.  
  317.         NPN_MemFree(instance->pdata);
  318.         instance->pdata = 0   ;
  319.     }
  320.  
  321.     return NPERR_NO_ERROR;
  322. }
  323.  
  324.  
  325. //----------------------------------------------------------------------------
  326. // NPP_SetWindow:
  327. //----------------------------------------------------------------------------
  328. NPError NP_LOADDS
  329. NPP_SetWindow(NPP instance, NPWindow* window)
  330. {
  331.     if (instance == 0   )
  332.         return NPERR_INVALID_INSTANCE_ERROR;
  333.  
  334.     PluginInstance* This = (PluginInstance*) instance->pdata;
  335.  
  336.     //
  337.     // *Developers*: Before setting fWindow to point to the
  338.     // new window, you may wish to compare the new window
  339.     // info to the previous window (if any) to note window
  340.     // size changes, etc.
  341.     //
  342.     if((window->window != 0   ) && (This->hWnd == 0   ))
  343.     {
  344.         This->fWindow = window;
  345.         This->hWnd    = (HWND)This->fWindow->window;
  346.  
  347.         // subclass the window
  348.         This->lpfnOldWndProc = WinSubclassWindow(This->hWnd, SubClassFunc);
  349.         AssociateInstance(This->hWnd, This);
  350.  
  351.         /* paint a background for the drawing */
  352.         RECTL rect;
  353.         WinQueryWindowRect(This->hWnd, &rect);
  354.         WinFillRect(This->hps, &rect, CLR_PALEGRAY);
  355.  
  356.         // create a PS
  357.         if (! This->hps)
  358.         {
  359.             HDC hdc = WinQueryWindowDC(This->hWnd);
  360.             if (! hdc)
  361.                 hdc = WinOpenWindowDC(This->hWnd);
  362.             SIZEL siz = { 0, 0 };
  363.             This->hps = GpiCreatePS(WinQueryAnchorBlock(This->hWnd), hdc, &siz,
  364.                                     PU_PELS | GPIT_NORMAL | GPIA_ASSOC);
  365.         }
  366.     }
  367.     else {
  368.         // if window handle changed
  369.         if(This->hWnd != (HWND)window->window) {
  370.             // remember the new window
  371.             This->fWindow = window;
  372.  
  373.             // Remove the subclass for the old client window
  374.             WinSubclassWindow(This->hWnd, This->lpfnOldWndProc);
  375.  
  376.             // remember the new window handle
  377.             This->hWnd = (HWND)This->fWindow->window;
  378.  
  379.             if(This->hWnd != 0   ) {
  380.                 // subclass the new one
  381.                 This->lpfnOldWndProc = WinSubclassWindow(This->hWnd,
  382.                                                          SubClassFunc);
  383.                 AssociateInstance(This->hWnd, This);
  384.             }
  385.  
  386.             /* paint a background for the drawing */
  387.             RECTL rect;
  388.             WinQueryWindowRect(This->hWnd, &rect);
  389.             WinFillRect(This->hps, &rect, CLR_PALEGRAY);
  390.  
  391.             // destroy old PS and create new PS
  392.             if (! This->hps)
  393.                 GpiDestroyPS(This->hps);
  394.             HDC hdc = WinQueryWindowDC(This->hWnd);
  395.             if (! hdc)
  396.                 hdc = WinOpenWindowDC(This->hWnd);
  397.             SIZEL siz = { 0, 0 };
  398.             This->hps = GpiCreatePS(WinQueryAnchorBlock(This->hWnd), hdc, &siz,
  399.                                     PU_TWIPS | GPIT_MICRO | GPIA_ASSOC);
  400.         }
  401.     }
  402.  
  403.     return NPERR_NO_ERROR;
  404. }
  405.  
  406.  
  407. //----------------------------------------------------------------------------
  408. // NPP_NewStream:
  409. //----------------------------------------------------------------------------
  410. NPError NP_LOADDS
  411. NPP_NewStream(NPP instance,
  412.               NPMIMEType type,
  413.               NPStream *stream,
  414.               NPBool seekable,
  415.               uint16 *stype)
  416. {
  417.     if (instance == 0   )
  418.         return NPERR_INVALID_INSTANCE_ERROR;
  419.     PluginInstance* This = (PluginInstance*) instance->pdata;
  420.  
  421.     // if your plugin must operate file based, you may wish to do this:
  422.     //    *stype = NP_ASFILE;
  423.     // remember, though, that use of NP_ASFILE is strongly discouraged;
  424.     // your plugin should attempt to work with data as it comes in on
  425.     // the stream if at all possible
  426.  
  427.     // initialize stream and length (in bytes)
  428.     This->Stream = stream;
  429.     This->SegmentID = 0;
  430.  
  431.     return NPERR_NO_ERROR;
  432. }
  433.  
  434.  
  435. //
  436. // *Developers*:
  437. // These next 2 functions are directly relevant in a plug-in which handles the
  438. // data in a streaming manner.  If you want zero bytes because no buffer space
  439. // is YET available, return 0.  As long as the stream has not been written
  440. // to the plugin, Navigator will continue trying to send bytes.  If the plugin
  441. // doesn't want them, just return some large number from NPP_WriteReady(), and
  442. // ignore them in NPP_Write().  For a NP_ASFILE stream, they are still called
  443. // but can safely be ignored using this strategy.
  444. //
  445.  
  446. int32 STREAMBUFSIZE = TOTAL_WIDTH;  // get a multiple of the data we understand
  447.  
  448. //----------------------------------------------------------------------------
  449. // NPP_WriteReady:
  450. //----------------------------------------------------------------------------
  451. int32 NP_LOADDS
  452. NPP_WriteReady(NPP instance, NPStream *stream)
  453. {
  454.     if (instance == 0   )
  455.         return NPERR_INVALID_INSTANCE_ERROR;
  456.     PluginInstance* This = (PluginInstance*) instance->pdata;
  457.  
  458.     return STREAMBUFSIZE;   // Number of bytes ready to accept in NPP_Write()
  459. }
  460.  
  461.  
  462. //----------------------------------------------------------------------------
  463. // NPP_Write:
  464. //----------------------------------------------------------------------------
  465. int32 NP_LOADDS
  466. NPP_Write(NPP instance, NPStream *stream,
  467.           int32 offset, int32 len, void *buffer)
  468. {
  469.     if (instance == 0   )
  470.         return NPERR_INVALID_INSTANCE_ERROR;
  471.     PluginInstance* This = (PluginInstance*) instance->pdata;
  472.  
  473.     // copy into our buffer only as much as we can handle
  474.     int myLen;
  475.     if (len < STREAMBUFSIZE)
  476.         myLen = len;
  477.     else
  478.         myLen = STREAMBUFSIZE;
  479.     char *myBuf = (char *)malloc(myLen);
  480.     memcpy(myBuf, buffer, myLen);
  481.  
  482.     /* set retain mode */
  483.     GpiSetDrawingMode(This->hps, DM_DRAWANDRETAIN);
  484.     This->SegmentID++;
  485.     GpiOpenSegment(This->hps, This->SegmentID);
  486.  
  487.     /* setup transform to graphics commands are scaled from standard 100x100 */
  488.     /* to the size of the window */
  489.     /* Would really like to do this once in NewStream but SetWindow has not */
  490.     /* yet been called so we don't know the size of the window. We could avoid */
  491.     /* setting the transform once by setting a flag but it's not important */
  492.     /* in this example because of the DosSleep later */
  493.     RECTL rcl;
  494.     WinQueryWindowRect(This->hWnd, &rcl);
  495.     MATRIXLF mtlf;
  496.     FIXED afxScale[2] = { (rcl.xRight - rcl.xLeft) * 0x10000 / MAX_X,
  497.                           (rcl.yTop - rcl.yBottom) * 0x10000 / MAX_Y };
  498.     POINTL ptlScaleOffset = {0, 0};
  499.     GpiScale(This->hps, &mtlf, TRANSFORM_REPLACE, afxScale, &ptlScaleOffset);
  500.     GpiSetModelTransformMatrix(This->hps, 9L, &mtlf, TRANSFORM_REPLACE);
  501.  
  502.     /* put buffer into a stream and parse it */
  503.     istrstream str((char *)buffer, myLen);
  504.     parseStream(instance, This, &str, myLen);
  505.     GpiCloseSegment(This->hps);
  506.  
  507.     /* free data buffer */
  508.     free(myBuf);
  509.  
  510.     return myLen;    // The number of bytes accepted.  Return a
  511.                      // negative number here if, e.g., there was an error
  512.                      // during plugin operation and you want to abort the
  513.                      // stream
  514. }
  515.  
  516.  
  517. //----------------------------------------------------------------------------
  518. // NPP_DestroyStream:
  519. //----------------------------------------------------------------------------
  520. NPError NP_LOADDS
  521. NPP_DestroyStream(NPP instance, NPStream *stream, NPError reason)
  522. {
  523.     if (instance == 0   )
  524.         return NPERR_INVALID_INSTANCE_ERROR;
  525.     PluginInstance* This = (PluginInstance*) instance->pdata;
  526.     This->Stream = 0;
  527.     // if (reason == NPRES_DONE)
  528.     This->SegmentID = 0;
  529.  
  530.     return NPERR_NO_ERROR;
  531. }
  532.  
  533.  
  534. //----------------------------------------------------------------------------
  535. // NPP_StreamAsFile:
  536. //----------------------------------------------------------------------------
  537. void NP_LOADDS
  538. NPP_StreamAsFile(NPP instance, NPStream *stream, const char* fname)
  539. {
  540.    if (instance == 0   )
  541.        return;
  542.  
  543.    PluginInstance* This = (PluginInstance*) instance->pdata;
  544.  
  545.    // invalidate window to ensure a redraw
  546.    WinInvalidateRect(This->hWnd, 0, TRUE);
  547. }
  548.  
  549.  
  550. //----------------------------------------------------------------------------
  551. // NPP_Print:
  552. //----------------------------------------------------------------------------
  553. void NP_LOADDS
  554. NPP_Print(NPP instance, NPPrint* printInfo)
  555. {
  556.     if(printInfo == 0   )   // trap invalid parm
  557.         return;
  558.  
  559.     if (instance != 0   )
  560.     {
  561.         PluginInstance* This = (PluginInstance*) instance->pdata;
  562.  
  563.         if (printInfo->mode == NP_FULL)
  564.         {
  565.             //
  566.             // *Developers*: If your plugin would like to take over
  567.             // printing completely when it is in full-screen mode,
  568.             // set printInfo->pluginPrinted to TRUE and print your
  569.             // plugin as you see fit.  If your plugin wants Netscape
  570.             // to handle printing in this case, set printInfo->pluginPrinted
  571.             // to FALSE (the default) and do nothing.  If you do want
  572.             // to handle printing yourself, printOne is true if the
  573.             // print button (as opposed to the print menu) was clicked.
  574.             // On the Macintosh, platformPrint is a THPrint; on Windows,
  575.             // platformPrint is a structure (defined in npapi.h) containing
  576.             // the printer name, port, etc.
  577.             //
  578.             void* platformPrint = printInfo->print.fullPrint.platformPrint;
  579.             NPBool printOne = printInfo->print.fullPrint.printOne;
  580.  
  581.             printInfo->print.fullPrint.pluginPrinted = FALSE; // Do the default
  582.  
  583.         }
  584.         else    // If not fullscreen, we must be embedded
  585.         {
  586.             //
  587.             // *Developers*: If your plugin is embedded, or is full-screen
  588.             // but you returned false in pluginPrinted above, NPP_Print
  589.             // will be called with mode == NP_EMBED.  The NPWindow
  590.             // in the printInfo gives the location and dimensions of
  591.             // the embedded plugin on the printed page.  On the Macintosh,
  592.             // platformPrint is the printer port; on Windows, platformPrint
  593.             // is the handle to the printing device context. On OS/2,
  594.             // platformPrint is the printing presentation space (HPS).
  595.             //
  596.             NPWindow* printWindow = &(printInfo->print.embedPrint.window);
  597.  
  598.             /* get Presentation Space and save it */
  599.             void* platformPrint = printInfo->print.embedPrint.platformPrint;
  600.             HPS hps = (HPS)platformPrint;
  601.  
  602.             /* create GPI various data structures about the drawing area */
  603.             POINTL offWindow = { (int)printWindow->x, (int)printWindow->y };
  604.             POINTL endPoint = { (int)printWindow->width, (int)printWindow->height };
  605.             RECTL rect = { (int)printWindow->x,
  606.                            (int)printWindow->y,
  607.                            (int)printWindow->x + (int)printWindow->width,
  608.                            (int)printWindow->y + (int)printWindow->height };
  609.  
  610.             /* get model transform so origin is 0,0 */
  611.             MATRIXLF matModel;
  612.             GpiQueryModelTransformMatrix(hps, 9L, &matModel);
  613.             GpiTranslate(hps, &matModel, TRANSFORM_ADD, &offWindow);
  614.             GpiSetModelTransformMatrix(hps, 9L, &matModel, TRANSFORM_REPLACE);
  615.  
  616.             /* draw using common drawing routine */
  617.             Draw(This, hps, &endPoint, TRUE);
  618.         }
  619.     }
  620. }
  621.  
  622.  
  623. //----------------------------------------------------------------------------
  624. // NPP_HandleEvent:
  625. // Mac-only.
  626. //----------------------------------------------------------------------------
  627. int16 NP_LOADDS NPP_HandleEvent(NPP instance, void* event)
  628. {
  629.     NPBool eventHandled = FALSE;
  630.     if (instance == 0   )
  631.         return eventHandled;
  632.  
  633.     PluginInstance* This = (PluginInstance*) instance->pdata;
  634.  
  635.     //
  636.     // *Developers*: The "event" passed in is a Macintosh
  637.     // EventRecord*.  The event.what field can be any of the
  638.     // normal Mac event types, or one of the following additional
  639.     // types defined in npapi.h: getFocusEvent, loseFocusEvent,
  640.     // adjustCursorEvent.  The focus events inform your plugin
  641.     // that it will become, or is no longer, the recepient of
  642.     // key events.  If your plugin doesn't want to receive key
  643.     // events, return false when passed at getFocusEvent.  The
  644.     // adjustCursorEvent is passed repeatedly when the mouse is
  645.     // over your plugin; if your plugin doesn't want to set the
  646.     // cursor, return false.  Handle the standard Mac events as
  647.     // normal.  The return value for all standard events is currently
  648.     // ignored except for the key event: for key events, only return
  649.     // true if your plugin has handled that particular key event.
  650.     //
  651.  
  652.     return eventHandled;
  653. }
  654.  
  655. //
  656. // Here is a sample subclass function.
  657. //
  658. MRESULT APIENTRY
  659. SubClassFunc(  HWND hWnd,
  660.                ULONG Message,
  661.                MPARAM wParam,
  662.                MPARAM lParam)
  663. {
  664.     PluginInstance *This = GetInstance(hWnd);
  665.  
  666.     switch(Message) {
  667.     case WM_REALIZEPALETTE:
  668.         WinInvalidateRect(hWnd, 0, TRUE);
  669.         WinUpdateWindow(hWnd);
  670.         return 0;
  671.         break;
  672.  
  673.     case WM_PAINT:
  674.         {
  675.             /* invalidate the whole window */
  676.             WinInvalidateRect(hWnd, NULL, TRUE);
  677.  
  678.             /* get PS associated with window */
  679.             RECTL invalidRect;
  680.             WinBeginPaint(hWnd, This->hps, &invalidRect);
  681.  
  682.             /* get window size and convert to world coordinates */
  683.             RECTL rect;
  684.             WinQueryWindowRect(hWnd, &rect);
  685.             POINTL pts[2] = { { 0L, 0L },
  686.                               { rect.xRight, rect.yTop }
  687.                             };
  688.             GpiConvert(This->hps, CVTC_DEVICE, CVTC_WORLD, 2L, pts);
  689.  
  690.             /* draw using common drawing routine */
  691.             WinFillRect(This->hps, &rect, CLR_PALEGRAY);
  692.             Draw(This, This->hps, &pts[1], FALSE);
  693.             WinEndPaint(This->hps);
  694.  
  695.         return (MRESULT)0;
  696.         }
  697.         break;
  698.  
  699.     default:
  700.         break;
  701.     }
  702.  
  703.     return ((PFNWP)This->lpfnOldWndProc)(
  704.                           hWnd,
  705.                           Message,
  706.                           wParam,
  707.                           lParam);
  708. }
  709.  
  710. void Draw(PluginInstance *This, HPS hps, POINTL *endPoint, BOOL fPrinting)
  711. {
  712.     if (fPrinting)
  713.     {
  714.         // You do not normally print a streaming plugin. We will display a
  715.         // bounding rectangle and a message string (if it fits)
  716.         POINTL ptl = { 0, 0 };
  717.         GpiMove(hps, &ptl);
  718.         GpiSetColor(hps, CLR_BLACK);
  719.         GpiBox(hps, DRO_OUTLINE, endPoint, 0L, 0L);
  720.         ptl.x += 40;
  721.         ptl.y = endPoint->y/4*3;
  722.         char *msg = "NPDRAW Plugin";
  723.         GpiCharStringAt(hps, &ptl, strlen(msg), msg);
  724.         ptl.y = endPoint->y/4*2;
  725.         msg = "does not print";
  726.         GpiCharStringAt(hps, &ptl, strlen(msg), msg);
  727.         ptl.y = endPoint->y/4;
  728.         msg = "streaming data.";
  729.         GpiCharStringAt(hps, &ptl, strlen(msg), msg);
  730.     }
  731.     else
  732.     {
  733.         GpiSetDrawingMode(hps, DM_DRAW);
  734.         GpiDrawChain(hps);
  735.     }
  736. }
  737.  
  738.  
  739. void parseStream(NPP instance, PluginInstance *This, istrstream *str, ULONG len)
  740. {
  741.     IString type;
  742.     int color, xStart, yStart, xEnd, yEnd;
  743.     str->setf(ios::skipws);
  744.  
  745.     for (int i=0; i<len/TOTAL_WIDTH; i++)
  746.     {
  747.         *str >> type >> color >> xStart >> yStart >> xEnd >> yEnd;
  748.  
  749.         /* draw the graphic */
  750.         GpiSetColor(This->hps, color);
  751.         POINTL ptl = { xStart, yStart };
  752.         GpiMove(This->hps, &ptl);
  753.         ptl.x = xEnd;
  754.         ptl.y = yEnd;
  755.         if (type == "L")
  756.         {
  757.             GpiLine(This->hps, &ptl);
  758.             NPN_Status(instance, "Processed line");
  759.         }
  760.         if (type == "R")
  761.         {
  762.             GpiBox(This->hps, DRO_OUTLINE, &ptl, 0, 0);
  763.             NPN_Status(instance, "Processed rectangle");
  764.         }
  765.         if (type == "F")
  766.         {
  767.             GpiBox(This->hps, DRO_FILL, &ptl, 0, 0);
  768.             NPN_Status(instance, "Processed filled box");
  769.         }
  770.  
  771.         /* simulate slow network with delay */
  772.         DosSleep(DELAY);
  773.     }
  774. }
  775.