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