home *** CD-ROM | disk | FTP | other *** search
/ DOS/V Power Report 1997 December / VPR9712B.ISO / Nsos2 / OS2PLUG.EXE / SAMPLE / NPSHELL / npshell.cpp < prev    next >
Text File  |  1997-03-19  |  22KB  |  621 lines

  1. /***************************************************************************
  2.  *
  3.  * File name   :  npshell.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.  * This file defines a "shell" plugin that plugin developers can use
  17.  * as the basis for a real plugin.  This shell just provides empty
  18.  * implementations of all functions that the plugin can implement
  19.  * that will be called by Netscape (the NPP_xxx methods defined in
  20.  * npapi.h).
  21.  *
  22.  ***************************************************************************/
  23.  
  24. #define INCL_WIN
  25. #define INCL_DOSPROCESS
  26. #define INCL_GPI
  27. #include <os2.h>
  28.  
  29. #include <string.h>
  30. #include <stdlib.h>
  31.  
  32. #ifndef _NPAPI_H_
  33. #include "npapi.h"
  34. #endif
  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.     PFNWP           lpfnOldWndProc;
  51.     NPSavedData*    pSavedInstanceData;
  52.     PluginInstance* pNext;
  53. } PluginInstance;
  54.  
  55. MRESULT APIENTRY
  56. SubClassFunc(HWND hWnd,ULONG Message,MPARAM wParam, MPARAM lParam);
  57.  
  58. void Draw(PluginInstance *This, HPS hps, POINTL *endPoint, BOOL fPrinting);
  59.  
  60. HMODULE DLLInstance;
  61.  
  62. #if defined ( __cplusplus )
  63. extern "C" {
  64. #endif
  65.  
  66. /* _CRT_init is the C run-time environment initialization function.         */
  67. /* It will return 0 to indicate success and -1 to indicate failure.         */
  68.    int _CRT_init(void);
  69.  
  70. /* __ctordtorInit calls the C++ run-time constructors for static objects.   */
  71.    void __ctordtorInit(void);
  72.  
  73. /* __ctordtorTerm calls the C++ run-time destructors for static objects.    */
  74.    void __ctordtorTerm(void);
  75.  
  76. #ifdef   STATIC_LINK
  77.  
  78. /* _CRT_term is the C run-time environment termination function.            */
  79. /* It only needs to be called when the C run-time functions are statically  */
  80. /* linked.                                                                  */
  81.    void _CRT_term(void);
  82.  
  83. #else
  84.  
  85. /* A clean up routine registered with DosExitList must be used if runtime   */
  86. /* calls are required at exit AND the runtime is dynamically linked.  This  */
  87. /* will guarantee that this clean up routine is run before the library DLL  */
  88. /* is terminated.  Do any application housekeeping in cleanup()             */
  89.     static void _System cleanup(ULONG ulReason);
  90.  
  91. #endif
  92.  
  93.  
  94. #if defined ( __cplusplus )
  95. }
  96. #endif
  97.  
  98.  
  99. extern "C"
  100. unsigned long _System _DLL_InitTerm(unsigned long hModule, unsigned long
  101.                                     ulFlag)
  102. {
  103.     DLLInstance = (HMODULE) hModule;
  104.     switch (ulFlag)
  105.     {
  106.         case 0:
  107.             if ( _CRT_init() == -1 )
  108.             {
  109.                 return(0UL);
  110.             }
  111. #if defined ( __cplusplus )
  112.             __ctordtorInit();
  113. #endif
  114.  
  115. #ifndef  STATIC_LINK
  116.  
  117.          /*******************************************************************/
  118.          /* A DosExitList routine must be used to clean up if runtime calls */
  119.          /* are required at exit and the runtime is dynamically linked.     */
  120.          /*******************************************************************/
  121.  
  122.             DosExitList(0x0000FF00|EXLST_ADD, cleanup);
  123. #endif
  124.             break;
  125.         case 1:
  126.  
  127. #if defined ( __cplusplus )
  128.             __ctordtorTerm();
  129. #endif
  130.  
  131. #ifdef  STATIC_LINK
  132.             _CRT_term();
  133. #endif
  134.             break;
  135.     }
  136.  
  137.     return 1;
  138. }
  139.  
  140. #ifndef  STATIC_LINK
  141. static void cleanup(ULONG ulReason)
  142. {
  143.    /* do any DLL cleanup here if needed AND if dynamically linked to the */
  144.    /* C Runtime libraries                                                */
  145.    DosExitList(EXLST_EXIT, cleanup);   /* remember to unlink ourselves   */
  146.    return ;
  147. }
  148. #endif
  149.  
  150. // A plugin instance typically will subclass the plugin's client window, so
  151. // it can get Windows messages, (such as paint, palettechanged, keybd, etc).
  152. // To do work associated with a specific plugin instance the WndProc which
  153. // receives the Windows messages, (named "SubClassFunc" herein), needs access
  154. // to the "This" (PluginInstance*) ptr.
  155. // If the plugin wants all the keyboard messages, it will have to
  156. // create a frame window with it's own accelerator table (even it it is empty)
  157. // and insure that that frame tracks the plugin window that Navigator creates,
  158. // otherwise the Navigator Accelerators will interfere with the WM_CHARs
  159. // that the plugin windows receive...
  160.  
  161. // When Navigator registers the plugin client's window class, (the class for
  162. // the window passed in NPP_SetWindow()), Navigator reserves 4
  163. // "extra" window bytes for the plugins use... at QWL_USER
  164. // Associate the hWnd with pInstance by setting the hWnd member of the
  165. // PluginInstance struct.
  166. static void AssociateInstance(HWND hWnd, PluginInstance* pInstance)
  167. {
  168.     pInstance->hWnd = hWnd;     // redundant, but usefull to get hwnd from
  169.                                 // pinstance later.
  170.     BOOL rc = WinSetWindowULong(hWnd, QWL_USER, (ULONG)pInstance);
  171. }
  172.  
  173. // Find the PluginInstance associated with this hWnd and return it
  174. static PluginInstance* GetInstance(HWND hWnd)
  175. {
  176.     return (PluginInstance*)WinQueryWindowULong(hWnd, QWL_USER);
  177. }
  178.  
  179. //----------------------------------------------------------------------------
  180. // NPP_Initialize:
  181. //----------------------------------------------------------------------------
  182. NPError NPP_Initialize(void)
  183. {
  184.     // do your one time initialization here, such as dynamically loading
  185.     // dependant DLLs
  186.     return NPERR_NO_ERROR;
  187. }
  188.  
  189.  
  190. //----------------------------------------------------------------------------
  191. // NPP_Shutdown:
  192. //----------------------------------------------------------------------------
  193. void NPP_Shutdown(void)
  194. {
  195.     // do your one time uninitialization here, such as unloading dynamically
  196.     // loaded DLLs
  197. }
  198.  
  199.  
  200. //----------------------------------------------------------------------------
  201. // NPP_New:
  202. //----------------------------------------------------------------------------
  203. NPError NP_LOADDS
  204. NPP_New(NPMIMEType pluginType,
  205.                 NPP instance,
  206.                 uint16 mode,
  207.                 int16 argc,
  208.                 char* argn[],
  209.                 char* argv[],
  210.                 NPSavedData* saved)
  211. {
  212.     if (instance == NULL)
  213.         return NPERR_INVALID_INSTANCE_ERROR;
  214.  
  215.     instance->pdata = NPN_MemAlloc(sizeof(PluginInstance));
  216.     PluginInstance* This = (PluginInstance*) instance->pdata;
  217.  
  218.     if (This == NULL)
  219.         return NPERR_OUT_OF_MEMORY_ERROR;
  220.     //
  221.     // *Developers*: Initialize fields of your plugin
  222.     // instance data here.  If the NPSavedData is non-
  223.     // NULL, you can use that data (returned by you from
  224.     // NPP_Destroy to set up the new plugin instance.
  225.     //
  226.  
  227.     This->fWindow = 0;
  228.     // mode is NP_EMBED, NP_FULL, or NP_BACKGROUND (see npapi.h)
  229.     This->fMode = mode;
  230.     This->hWnd = 0;
  231.     This->pSavedInstanceData = saved;
  232.     This->pNext = 0   ;
  233.  
  234.     return NPERR_NO_ERROR;
  235. }
  236.  
  237.  
  238. //-----------------------------------------------------------------------------
  239. // NPP_Destroy:
  240. //-----------------------------------------------------------------------------
  241. NPError NP_LOADDS
  242. NPP_Destroy(NPP instance, NPSavedData** save)
  243. {
  244.     if (instance == 0   )
  245.         return NPERR_INVALID_INSTANCE_ERROR;
  246.  
  247.     PluginInstance* This = (PluginInstance*) instance->pdata;
  248.  
  249.     //
  250.     // *Developers*: If desired, call NP_MemAlloc to create a
  251.     // NPSavedDate structure containing any state information
  252.     // that you want restored if this plugin instance is later
  253.     // recreated.
  254.     //
  255.  
  256.     if (This != 0   )
  257.     {
  258.         // Remove the subclass for the client window
  259.         if(This->hWnd)
  260.         {
  261.             WinSubclassWindow(This->hWnd, This->lpfnOldWndProc);
  262.         }
  263.  
  264.         // make some saved instance data if necessary
  265.         if(This->pSavedInstanceData == 0   ) {
  266.             // make a struct header for the data
  267.             This->pSavedInstanceData =
  268.                 (NPSavedData*)NPN_MemAlloc(sizeof (struct _NPSavedData));
  269.  
  270.             // fill in the struct
  271.             if(This->pSavedInstanceData != 0   ) {
  272.                 This->pSavedInstanceData->len = 0;
  273.                 This->pSavedInstanceData->buf = 0   ;
  274.  
  275.                 // replace the def below and references to it with your data
  276.                 #define SIDATA "aSavedInstanceDataBlock"
  277.  
  278.                 // the data
  279.                 This->pSavedInstanceData->buf = NPN_MemAlloc(sizeof SIDATA);
  280.  
  281.                 if(This->pSavedInstanceData->buf != 0   ) {
  282.                     strcpy((char*)This->pSavedInstanceData->buf, SIDATA);
  283.                     This->pSavedInstanceData->len = sizeof SIDATA;
  284.                 }
  285.             }
  286.         }
  287.  
  288.         // save some instance data
  289.         *save = This->pSavedInstanceData;
  290.  
  291.         NPN_MemFree(instance->pdata);
  292.         instance->pdata = 0   ;
  293.     }
  294.  
  295.     return NPERR_NO_ERROR;
  296. }
  297.  
  298.  
  299. //----------------------------------------------------------------------------
  300. // NPP_SetWindow:
  301. //----------------------------------------------------------------------------
  302. NPError NP_LOADDS
  303. NPP_SetWindow(NPP instance, NPWindow* window)
  304. {
  305.     if (instance == 0   )
  306.         return NPERR_INVALID_INSTANCE_ERROR;
  307.  
  308.     PluginInstance* This = (PluginInstance*) instance->pdata;
  309.  
  310.     //
  311.     // *Developers*: Before setting fWindow to point to the
  312.     // new window, you may wish to compare the new window
  313.     // info to the previous window (if any) to note window
  314.     // size changes, etc.
  315.     //
  316.     if((window->window != 0   ) && (This->hWnd == 0   ))
  317.     {
  318.         This->fWindow = window;
  319.         This->hWnd    = (HWND)This->fWindow->window;
  320.  
  321.         // subclass the window
  322.         This->lpfnOldWndProc = WinSubclassWindow(This->hWnd, SubClassFunc);
  323.         AssociateInstance(This->hWnd, This);
  324.     }
  325.     else {
  326.         // if window handle changed
  327.         if(This->hWnd != (HWND)window->window) {
  328.             // remember the new window
  329.             This->fWindow = window;
  330.  
  331.             // Remove the subclass for the old client window
  332.             WinSubclassWindow(This->hWnd, This->lpfnOldWndProc);
  333.  
  334.             // remember the new window handle
  335.             This->hWnd = (HWND)This->fWindow->window;
  336.  
  337.             if(This->hWnd != 0   ) {
  338.                 // subclass the new one
  339.                 This->lpfnOldWndProc = WinSubclassWindow(This->hWnd,
  340.                                                          SubClassFunc);
  341.                 AssociateInstance(This->hWnd, This);
  342.             }
  343.         }
  344.     }
  345.  
  346.     return NPERR_NO_ERROR;
  347. }
  348.  
  349.  
  350. //----------------------------------------------------------------------------
  351. // NPP_NewStream:
  352. //----------------------------------------------------------------------------
  353. NPError NP_LOADDS
  354. NPP_NewStream(NPP instance,
  355.               NPMIMEType type,
  356.               NPStream *stream,
  357.               NPBool seekable,
  358.               uint16 *stype)
  359. {
  360.     if (instance == 0   )
  361.         return NPERR_INVALID_INSTANCE_ERROR;
  362.     PluginInstance* This = (PluginInstance*) instance->pdata;
  363.  
  364.     // if your plugin must operate file based, you may wish to do this:
  365.     //    *stype = NP_ASFILE;
  366.     // remember, though, that use of NP_ASFILE is strongly discouraged;
  367.     // your plugin should attempt to work with data as it comes in on
  368.     // the stream if at all possible
  369.  
  370.     return NPERR_NO_ERROR;
  371. }
  372.  
  373.  
  374. //
  375. // *Developers*:
  376. // These next 2 functions are directly relevant in a plug-in which handles the
  377. // data in a streaming manner.  If you want zero bytes because no buffer space
  378. // is YET available, return 0.  As long as the stream has not been written
  379. // to the plugin, Navigator will continue trying to send bytes.  If the plugin
  380. // doesn't want them, just return some large number from NPP_WriteReady(), and
  381. // ignore them in NPP_Write().  For a NP_ASFILE stream, they are still called
  382. // but can safely be ignored using this strategy.
  383. //
  384.  
  385. int32 STREAMBUFSIZE = 0X0FFFFFFF;   // If we are reading from a file in
  386.                                     // NP_ASFILE mode, we can take any size
  387.                                     // stream in our write call (since we
  388.                                     // ignore it)
  389.  
  390. //----------------------------------------------------------------------------
  391. // NPP_WriteReady:
  392. //----------------------------------------------------------------------------
  393. int32 NP_LOADDS
  394. NPP_WriteReady(NPP instance, NPStream *stream)
  395. {
  396.     if (instance != 0   )
  397.         PluginInstance* This = (PluginInstance*) instance->pdata;
  398.  
  399.     return STREAMBUFSIZE;   // Number of bytes ready to accept in NPP_Write()
  400. }
  401.  
  402.  
  403. //----------------------------------------------------------------------------
  404. // NPP_Write:
  405. //----------------------------------------------------------------------------
  406. int32 NP_LOADDS
  407. NPP_Write(NPP instance, NPStream *stream,
  408.           int32 offset, int32 len, void *buffer)
  409. {
  410.     if (instance != 0   )
  411.         PluginInstance* This = (PluginInstance*) instance->pdata;
  412.  
  413.     return len;     // The number of bytes accepted.  Return a
  414.                     // negative number here if, e.g., there was an error
  415.                     // during plugin operation and you want to abort the
  416.                     // stream
  417. }
  418.  
  419.  
  420. //----------------------------------------------------------------------------
  421. // NPP_DestroyStream:
  422. //----------------------------------------------------------------------------
  423. NPError NP_LOADDS
  424. NPP_DestroyStream(NPP instance, NPStream *stream, NPError reason)
  425. {
  426.     if (instance == 0   )
  427.         return NPERR_INVALID_INSTANCE_ERROR;
  428.     PluginInstance* This = (PluginInstance*) instance->pdata;
  429.  
  430.     return NPERR_NO_ERROR;
  431. }
  432.  
  433.  
  434. //----------------------------------------------------------------------------
  435. // NPP_StreamAsFile:
  436. //----------------------------------------------------------------------------
  437. void NP_LOADDS
  438. NPP_StreamAsFile(NPP instance, NPStream *stream, const char* fname)
  439. {
  440.    if (instance == 0   )
  441.        return;
  442.  
  443.    PluginInstance* This = (PluginInstance*) instance->pdata;
  444.  
  445.    // invalidate window to ensure a redraw
  446.    WinInvalidateRect(This->hWnd, 0, TRUE);
  447. }
  448.  
  449.  
  450. //----------------------------------------------------------------------------
  451. // NPP_Print:
  452. //----------------------------------------------------------------------------
  453. void NP_LOADDS
  454. NPP_Print(NPP instance, NPPrint* printInfo)
  455. {
  456.     if(printInfo == 0   )   // trap invalid parm
  457.         return;
  458.  
  459.     if (instance != 0   )
  460.     {
  461.         PluginInstance* This = (PluginInstance*) instance->pdata;
  462.  
  463.         if (printInfo->mode == NP_FULL)
  464.         {
  465.             //
  466.             // *Developers*: If your plugin would like to take over
  467.             // printing completely when it is in full-screen mode,
  468.             // set printInfo->pluginPrinted to TRUE and print your
  469.             // plugin as you see fit.  If your plugin wants Netscape
  470.             // to handle printing in this case, set printInfo->pluginPrinted
  471.             // to FALSE (the default) and do nothing.  If you do want
  472.             // to handle printing yourself, printOne is true if the
  473.             // print button (as opposed to the print menu) was clicked.
  474.             // On the Macintosh, platformPrint is a THPrint; on Windows,
  475.             // platformPrint is a structure (defined in npapi.h) containing
  476.             // the printer name, port, etc.
  477.             //
  478.             void* platformPrint = printInfo->print.fullPrint.platformPrint;
  479.             NPBool printOne = printInfo->print.fullPrint.printOne;
  480.  
  481.             printInfo->print.fullPrint.pluginPrinted = FALSE; // Do the default
  482.  
  483.         }
  484.         else    // If not fullscreen, we must be embedded
  485.         {
  486.             //
  487.             // *Developers*: If your plugin is embedded, or is full-screen
  488.             // but you returned false in pluginPrinted above, NPP_Print
  489.             // will be called with mode == NP_EMBED.  The NPWindow
  490.             // in the printInfo gives the location and dimensions of
  491.             // the embedded plugin on the printed page.  On the Macintosh,
  492.             // platformPrint is the printer port; on Windows, platformPrint
  493.             // is the handle to the printing device context. On OS/2,
  494.             // platformPrint is the printing presentation space (HPS).
  495.             //
  496.             NPWindow* printWindow = &(printInfo->print.embedPrint.window);
  497.  
  498.             /* get Presentation Space */
  499.             void* platformPrint = printInfo->print.embedPrint.platformPrint;
  500.             HPS hps = (HPS)platformPrint;
  501.  
  502.             /* create GPI various data structures about the drawing area */
  503.             POINTL offWindow = { (int)printWindow->x, (int)printWindow->y };
  504.             POINTL endPoint = { (int)printWindow->width, (int)printWindow->height };
  505.             RECTL rect = { (int)printWindow->x,
  506.                            (int)printWindow->y,
  507.                            (int)printWindow->x + (int)printWindow->width,
  508.                            (int)printWindow->y + (int)printWindow->height };
  509.  
  510.             /* set model transform so origin is 0,0 */
  511.             MATRIXLF matModel;
  512.             GpiQueryModelTransformMatrix(hps, 9L, &matModel);
  513.             GpiTranslate(hps, &matModel, TRANSFORM_ADD, &offWindow);
  514.             GpiSetModelTransformMatrix(hps, 9L, &matModel, TRANSFORM_REPLACE);
  515.  
  516.             /* draw using common drawing routine */
  517.             Draw(This, hps, &endPoint, TRUE);
  518.         }
  519.     }
  520. }
  521.  
  522.  
  523. //----------------------------------------------------------------------------
  524. // NPP_HandleEvent:
  525. // Mac-only.
  526. //----------------------------------------------------------------------------
  527. int16 NP_LOADDS NPP_HandleEvent(NPP instance, void* event)
  528. {
  529.     NPBool eventHandled = FALSE;
  530.     if (instance == 0   )
  531.         return eventHandled;
  532.  
  533.     PluginInstance* This = (PluginInstance*) instance->pdata;
  534.  
  535.     //
  536.     // *Developers*: The "event" passed in is a Macintosh
  537.     // EventRecord*.  The event.what field can be any of the
  538.     // normal Mac event types, or one of the following additional
  539.     // types defined in npapi.h: getFocusEvent, loseFocusEvent,
  540.     // adjustCursorEvent.  The focus events inform your plugin
  541.     // that it will become, or is no longer, the recepient of
  542.     // key events.  If your plugin doesn't want to receive key
  543.     // events, return false when passed at getFocusEvent.  The
  544.     // adjustCursorEvent is passed repeatedly when the mouse is
  545.     // over your plugin; if your plugin doesn't want to set the
  546.     // cursor, return false.  Handle the standard Mac events as
  547.     // normal.  The return value for all standard events is currently
  548.     // ignored except for the key event: for key events, only return
  549.     // true if your plugin has handled that particular key event.
  550.     //
  551.  
  552.     return eventHandled;
  553. }
  554.  
  555. //
  556. // Here is a sample subclass function.
  557. //
  558. MRESULT APIENTRY
  559. SubClassFunc(  HWND hWnd,
  560.                ULONG Message,
  561.                MPARAM wParam,
  562.                MPARAM lParam)
  563. {
  564.     PluginInstance *This = GetInstance(hWnd);
  565.  
  566.     switch(Message) {
  567.     case WM_REALIZEPALETTE:
  568.         WinInvalidateRect(hWnd, 0, TRUE);
  569.         WinUpdateWindow(hWnd);
  570.         return 0;
  571.         break;
  572.  
  573.     case WM_PAINT:
  574.         {
  575.             /* invalidate the whole window */
  576.             WinInvalidateRect(hWnd, NULL, TRUE);
  577.  
  578.             /* get PS associated with window  and set to PU_TWIPS coordinates */
  579.             RECTL invalidRect;
  580.             HPS hps = WinBeginPaint(hWnd, NULL, &invalidRect);
  581.             SIZEL siz = { 0,0 };
  582.             GpiSetPS(hps, &siz, PU_TWIPS);
  583.  
  584.             /* get window size and convert to world coordinates */
  585.             RECTL rect;
  586.             WinQueryWindowRect(hWnd, &rect);
  587.             POINTL pts[2] = { { 0L, 0L },
  588.                               { rect.xRight, rect.yTop }
  589.                             };
  590.             GpiConvert(hps, CVTC_DEVICE, CVTC_WORLD, 2L, pts);
  591.  
  592.             /* draw using common drawing routine */
  593.             Draw(This, hps, &pts[1], FALSE);
  594.             WinEndPaint(hps);
  595.         }
  596.         return (MRESULT)0;
  597.         break;
  598.  
  599.     default:
  600.         break;
  601.     }
  602.  
  603.     return ((PFNWP)This->lpfnOldWndProc)(
  604.                           hWnd,
  605.                           Message,
  606.                           wParam,
  607.                           lParam);
  608. }
  609.  
  610. void Draw(PluginInstance *This, HPS hps, POINTL *endPoint, BOOL fPrinting)
  611. {
  612.     // Draw random colored box.
  613.     // Notice when you resize the browser window, the plugin actually gets
  614.     // drawn twice. You may want to draw into a bitmap and bitblt to
  615.     // improve performance if you plugin does a lot of drawing.
  616.     POINTL ptl = { 0, 0 };
  617.     GpiMove(hps, &ptl);
  618.     GpiSetColor(hps, rand()%15+1);
  619.     GpiBox(hps, DRO_OUTLINEFILL, endPoint, 0L, 0L);
  620. }
  621.