home *** CD-ROM | disk | FTP | other *** search
/ CD Actual 14 / CDACTUAL.iso / cdactual / demobin / share / os2 / NSPLUGIN / SAMPLE / NPCLOCK / NPCLOCK.CPP < prev    next >
Encoding:
C/C++ Source or Header  |  1996-12-10  |  27.3 KB  |  818 lines

  1. /***************************************************************************
  2.  *
  3.  * File name   :  npclock.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_WIN
  19. #define INCL_DOSPROCESS
  20. #define INCL_GPI
  21. #include <os2.h>
  22.  
  23. #include <string.h>
  24. #include <stdlib.h>
  25.  
  26. #ifndef _NPAPI_H_
  27. #include "npapi.h"
  28. #endif
  29.  
  30. #include "clock.hpp"
  31.  
  32. // constants for timer
  33. #define kTimerId         1
  34. #define kTimerFrequency  20
  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.     Clock           *pClock;
  54.     HPS             hps;
  55.     ULONG           fTimer;
  56.     BOOL            Transparency;
  57.     RECTL           rect;
  58. } PluginInstance;
  59.  
  60. MRESULT APIENTRY
  61. SubClassFunc(HWND hWnd,ULONG Message,MPARAM wParam, MPARAM lParam);
  62. void Draw(PluginInstance *This, HPS hps, POINTL *endPoint, BOOL fPrinting);
  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.     // set defaults
  244.     This->Transparency = FALSE;
  245.     BOOL AnalogClock = TRUE;
  246.  
  247.     // parse arguments and set values
  248.     for (int i=0; i<argc; i++ )
  249.     {
  250.         if (! stricmp(argn[i], "FORMAT"))
  251.         {
  252.             if (! stricmp(argv[i], "DIGITAL"))
  253.                 AnalogClock = FALSE;
  254.             AnalogClock = TRUE;    // remove this line when digital works better
  255.  
  256.         }
  257.         else if (! stricmp(argn[i], "TRANSPARENCY"))
  258.         {
  259.             if (! stricmp(argv[i], "TRUE"))
  260.                 This->Transparency = TRUE;
  261.         }
  262.     }
  263.  
  264.     This->fWindow = 0;
  265.     // mode is NP_EMBED, NP_FULL, or NP_BACKGROUND (see npapi.h)
  266.     This->fMode = mode;
  267.     This->hWnd = 0;
  268.     This->pSavedInstanceData = saved;
  269.     This->pNext = 0   ;
  270.     This->hps = NULL;
  271.     This->fTimer = FALSE;
  272.     This->pClock = new Clock();
  273.  
  274.     // depends on setting of FORMAT argument value
  275.     if (AnalogClock)
  276.         This->pClock->SetMode(DM_TIME | DM_ANALOG | DM_SECONDHAND);
  277.     else
  278.         This->pClock->SetMode(DM_TIME | DM_DIGITAL | DM_SECONDHAND);
  279.  
  280.     return NPERR_NO_ERROR;
  281. }
  282.  
  283.  
  284. //-----------------------------------------------------------------------------
  285. // NPP_Destroy:
  286. //-----------------------------------------------------------------------------
  287. NPError NP_LOADDS
  288. NPP_Destroy(NPP instance, NPSavedData** save)
  289. {
  290.     if (instance == 0   )
  291.         return NPERR_INVALID_INSTANCE_ERROR;
  292.  
  293.     PluginInstance* This = (PluginInstance*) instance->pdata;
  294.  
  295.     //
  296.     // *Developers*: If desired, call NP_MemAlloc to create a
  297.     // NPSavedDate structure containing any state information
  298.     // that you want restored if this plugin instance is later
  299.     // recreated.
  300.     //
  301.  
  302.     if (This != 0   )
  303.     {
  304.         // stop the timer
  305.         if (This->fTimer)
  306.         {
  307.             WinStopTimer(WinQueryAnchorBlock(This->hWnd), This->hWnd, kTimerId);
  308.             This->fTimer = FALSE;
  309.         }
  310.  
  311.         // destroy old PS and create new PS
  312.         if (! This->hps)
  313.             GpiDestroyPS(This->hps);
  314.  
  315.         // delete clock
  316.         delete This->pClock;
  317.  
  318.         // Remove the subclass for the client window
  319.         if(This->hWnd)
  320.         {
  321.             WinSubclassWindow(This->hWnd, This->lpfnOldWndProc);
  322.         }
  323.  
  324.         // make some saved instance data if necessary
  325.         if(This->pSavedInstanceData == 0   ) {
  326.             // make a struct header for the data
  327.             This->pSavedInstanceData =
  328.                 (NPSavedData*)NPN_MemAlloc(sizeof (struct _NPSavedData));
  329.  
  330.             // fill in the struct
  331.             if(This->pSavedInstanceData != 0   ) {
  332.                 This->pSavedInstanceData->len = 0;
  333.                 This->pSavedInstanceData->buf = 0   ;
  334.  
  335.                 // replace the def below and references to it with your data
  336.                 #define SIDATA "aSavedInstanceDataBlock"
  337.  
  338.                 // the data
  339.                 This->pSavedInstanceData->buf = NPN_MemAlloc(sizeof SIDATA);
  340.  
  341.                 if(This->pSavedInstanceData->buf != 0   ) {
  342.                     strcpy((char*)This->pSavedInstanceData->buf, SIDATA);
  343.                     This->pSavedInstanceData->len = sizeof SIDATA;
  344.                 }
  345.             }
  346.  
  347.         }
  348.  
  349.         // save some instance data
  350.         *save = This->pSavedInstanceData;
  351.  
  352.         NPN_MemFree(instance->pdata);
  353.         instance->pdata = 0   ;
  354.     }
  355.  
  356.     return NPERR_NO_ERROR;
  357. }
  358.  
  359.  
  360. //----------------------------------------------------------------------------
  361. // NPP_SetWindow:
  362. //----------------------------------------------------------------------------
  363. NPError NP_LOADDS
  364. NPP_SetWindow(NPP instance, NPWindow* window)
  365. {
  366.     if (instance == 0   )
  367.         return NPERR_INVALID_INSTANCE_ERROR;
  368.  
  369.     PluginInstance* This = (PluginInstance*) instance->pdata;
  370.  
  371.     //
  372.     // *Developers*: Before setting fWindow to point to the
  373.     // new window, you may wish to compare the new window
  374.     // info to the previous window (if any) to note window
  375.     // size changes, etc.
  376.     //
  377.     if((window->window != 0   ) && (This->hWnd == 0   ))
  378.     {
  379.         This->fWindow = window;
  380.         This->hWnd    = (HWND)This->fWindow->window;
  381.  
  382.         // subclass the window
  383.         This->lpfnOldWndProc = WinSubclassWindow(This->hWnd, SubClassFunc);
  384.         AssociateInstance(This->hWnd, This);
  385.  
  386.         // create a PS
  387.         if (! This->hps)
  388.         {
  389.             HDC hdc = WinQueryWindowDC(This->hWnd);
  390.             if (! hdc)
  391.                 hdc = WinOpenWindowDC(This->hWnd);
  392.             SIZEL siz = { 0, 0 };
  393.             This->hps = GpiCreatePS(WinQueryAnchorBlock(This->hWnd), hdc, &siz,
  394.                                     PU_PELS | GPIT_MICRO | GPIA_ASSOC);
  395.         }
  396.     }
  397.     else {
  398.         // if window handle changed
  399.         if(This->hWnd != (HWND)window->window) {
  400.             // remember the new window
  401.             This->fWindow = window;
  402.  
  403.             // Remove the subclass for the old client window
  404.             WinSubclassWindow(This->hWnd, This->lpfnOldWndProc);
  405.  
  406.             // remember the new window handle
  407.             This->hWnd = (HWND)This->fWindow->window;
  408.  
  409.             if(This->hWnd != 0   ) {
  410.                 // subclass the new one
  411.                 This->lpfnOldWndProc = WinSubclassWindow(This->hWnd,
  412.                                                          SubClassFunc);
  413.                 AssociateInstance(This->hWnd, This);
  414.             }
  415.  
  416.             // stop old timer and start a new timer
  417.             WinStopTimer(WinQueryAnchorBlock(This->hWnd), This->hWnd, kTimerId);
  418.             WinStartTimer(WinQueryAnchorBlock(This->hWnd), This->hWnd,
  419.                           kTimerId, kTimerFrequency);
  420.  
  421.             // destroy old PS and create new PS
  422.             if (! This->hps)
  423.                 GpiDestroyPS(This->hps);
  424.             HDC hdc = WinQueryWindowDC(This->hWnd);
  425.             if (! hdc)
  426.                 hdc = WinOpenWindowDC(This->hWnd);
  427.             SIZEL siz = { 0, 0 };
  428.             This->hps = GpiCreatePS(WinQueryAnchorBlock(This->hWnd), hdc, &siz,
  429.                                     PU_TWIPS | GPIT_MICRO | GPIA_ASSOC);
  430.         }
  431.     }
  432.  
  433.     return NPERR_NO_ERROR;
  434. }
  435.  
  436.  
  437. //----------------------------------------------------------------------------
  438. // NPP_NewStream:
  439. //----------------------------------------------------------------------------
  440. NPError NP_LOADDS
  441. NPP_NewStream(NPP instance,
  442.               NPMIMEType type,
  443.               NPStream *stream,
  444.               NPBool seekable,
  445.               uint16 *stype)
  446. {
  447.     if (instance == 0   )
  448.         return NPERR_INVALID_INSTANCE_ERROR;
  449.     PluginInstance* This = (PluginInstance*) instance->pdata;
  450.  
  451.     // if your plugin must operate file based, you may wish to do this:
  452.     //    *stype = NP_ASFILE;
  453.     // remember, though, that use of NP_ASFILE is strongly discouraged;
  454.     // your plugin should attempt to work with data as it comes in on
  455.     // the stream if at all possible
  456.  
  457.     return NPERR_NO_ERROR;
  458. }
  459.  
  460.  
  461. //
  462. // *Developers*:
  463. // These next 2 functions are directly relevant in a plug-in which handles the
  464. // data in a streaming manner.  If you want zero bytes because no buffer space
  465. // is YET available, return 0.  As long as the stream has not been written
  466. // to the plugin, Navigator will continue trying to send bytes.  If the plugin
  467. // doesn't want them, just return some large number from NPP_WriteReady(), and
  468. // ignore them in NPP_Write().  For a NP_ASFILE stream, they are still called
  469. // but can safely be ignored using this strategy.
  470. //
  471.  
  472. int32 STREAMBUFSIZE = 0X0FFFFFFF;   // If we are reading from a file in
  473.                                     // NP_ASFILE mode, we can take any size
  474.                                     // stream in our write call (since we
  475.                                     // ignore it)
  476.  
  477. //----------------------------------------------------------------------------
  478. // NPP_WriteReady:
  479. //----------------------------------------------------------------------------
  480. int32 NP_LOADDS
  481. NPP_WriteReady(NPP instance, NPStream *stream)
  482. {
  483.     if (instance != 0   )
  484.         PluginInstance* This = (PluginInstance*) instance->pdata;
  485.  
  486.     return STREAMBUFSIZE;   // Number of bytes ready to accept in NPP_Write()
  487. }
  488.  
  489.  
  490. //----------------------------------------------------------------------------
  491. // NPP_Write:
  492. //----------------------------------------------------------------------------
  493. int32 NP_LOADDS
  494. NPP_Write(NPP instance, NPStream *stream,
  495.           int32 offset, int32 len, void *buffer)
  496. {
  497.     if (instance != 0   )
  498.         PluginInstance* This = (PluginInstance*) instance->pdata;
  499.  
  500.     return len;     // The number of bytes accepted.  Return a
  501.                     // negative number here if, e.g., there was an error
  502.                     // during plugin operation and you want to abort the
  503.                     // stream
  504. }
  505.  
  506.  
  507. //----------------------------------------------------------------------------
  508. // NPP_DestroyStream:
  509. //----------------------------------------------------------------------------
  510. NPError NP_LOADDS
  511. NPP_DestroyStream(NPP instance, NPStream *stream, NPError reason)
  512. {
  513.     if (instance == 0   )
  514.         return NPERR_INVALID_INSTANCE_ERROR;
  515.     PluginInstance* This = (PluginInstance*) instance->pdata;
  516.  
  517.     return NPERR_NO_ERROR;
  518. }
  519.  
  520.  
  521. //----------------------------------------------------------------------------
  522. // NPP_StreamAsFile:
  523. //----------------------------------------------------------------------------
  524. void NP_LOADDS
  525. NPP_StreamAsFile(NPP instance, NPStream *stream, const char* fname)
  526. {
  527.    if (instance == 0   )
  528.        return;
  529.  
  530.    PluginInstance* This = (PluginInstance*) instance->pdata;
  531.  
  532.    // invalidate window to ensure a redraw
  533.    WinInvalidateRect(This->hWnd, 0, TRUE);
  534. }
  535.  
  536.  
  537. //----------------------------------------------------------------------------
  538. // NPP_Print:
  539. //----------------------------------------------------------------------------
  540. void NP_LOADDS
  541. NPP_Print(NPP instance, NPPrint* printInfo)
  542. {
  543.     if(printInfo == 0   )   // trap invalid parm
  544.         return;
  545.  
  546.     if (instance != 0   )
  547.     {
  548.         PluginInstance* This = (PluginInstance*) instance->pdata;
  549.  
  550.         if (printInfo->mode == NP_FULL)
  551.         {
  552.             //
  553.             // *Developers*: If your plugin would like to take over
  554.             // printing completely when it is in full-screen mode,
  555.             // set printInfo->pluginPrinted to TRUE and print your
  556.             // plugin as you see fit.  If your plugin wants Netscape
  557.             // to handle printing in this case, set printInfo->pluginPrinted
  558.             // to FALSE (the default) and do nothing.  If you do want
  559.             // to handle printing yourself, printOne is true if the
  560.             // print button (as opposed to the print menu) was clicked.
  561.             // On the Macintosh, platformPrint is a THPrint; on Windows,
  562.             // platformPrint is a structure (defined in npapi.h) containing
  563.             // the printer name, port, etc.
  564.             //
  565.             void* platformPrint = printInfo->print.fullPrint.platformPrint;
  566.             NPBool printOne = printInfo->print.fullPrint.printOne;
  567.  
  568.             printInfo->print.fullPrint.pluginPrinted = FALSE; // Do the default
  569.  
  570.         }
  571.         else    // If not fullscreen, we must be embedded
  572.         {
  573.             //
  574.             // *Developers*: If your plugin is embedded, or is full-screen
  575.             // but you returned false in pluginPrinted above, NPP_Print
  576.             // will be called with mode == NP_EMBED.  The NPWindow
  577.             // in the printInfo gives the location and dimensions of
  578.             // the embedded plugin on the printed page.  On the Macintosh,
  579.             // platformPrint is the printer port; on Windows, platformPrint
  580.             // is the handle to the printing device context. On OS/2,
  581.             // platformPrint is the printing presentation space (HPS).
  582.             //
  583.             NPWindow* printWindow = &(printInfo->print.embedPrint.window);
  584.  
  585.             /* get Presentation Space and save it */
  586.             void* platformPrint = printInfo->print.embedPrint.platformPrint;
  587.             HPS hps = (HPS)platformPrint;
  588.  
  589.             /* create GPI various data structures about the drawing area */
  590.             POINTL offWindow = { (int)printWindow->x, (int)printWindow->y };
  591.             POINTL endPoint = { (int)printWindow->width, (int)printWindow->height };
  592.             This->rect.xLeft = (int)printWindow->x;
  593.             This->rect.yBottom = (int)printWindow->y;
  594.             This->rect.xRight = (int)printWindow->x + (int)printWindow->width;
  595.             This->rect.yTop = (int)printWindow->y + (int)printWindow->height;
  596.  
  597.             /* get model transform so origin is 0,0 */
  598.             MATRIXLF matModel;
  599.             GpiQueryModelTransformMatrix(hps, 9L, &matModel);
  600.             GpiTranslate(hps, &matModel, TRANSFORM_ADD, &offWindow);
  601.             GpiSetModelTransformMatrix(hps, 9L, &matModel, TRANSFORM_REPLACE);
  602.  
  603.             /* draw using common drawing routine */
  604.             Draw(This, hps, &endPoint, TRUE);
  605.  
  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.     static int inPaint = FALSE;
  654.     static int ignorePaint = TRUE;
  655.  
  656.     switch(Message) {
  657.     case WM_REALIZEPALETTE:
  658.         WinInvalidateRect(hWnd, 0, TRUE);
  659.         WinUpdateWindow(hWnd);
  660.         return 0;
  661.         break;
  662.  
  663.     case WM_TIMER:
  664.         {
  665.             if ((ULONG)wParam == kTimerId)
  666.             {
  667.                 /* get window size */
  668.                 RECTL rect;
  669.                 WinQueryWindowRect(hWnd, &rect);
  670.  
  671.                 /* draw updated clock */
  672.                 ULONG saveID = GpiSavePS(This->hps);
  673.                 if (This->pClock->Timer(This->hps,  &rect))
  674.                     WinInvalidateRect(hWnd, NULL, TRUE);
  675.                 GpiRestorePS(This->hps, saveID);
  676.             }
  677.         }
  678.         return (MRESULT)0;
  679.         break;
  680.  
  681.     case WM_BUTTON1DOWN:
  682.         WinSetFocus(HWND_DESKTOP,hWnd);
  683.         return(MRESULT)1;
  684.  
  685.     case WM_CHAR:
  686.         {
  687.              int flags = SHORT1FROMMP(wParam);
  688.              int usch  = SHORT1FROMMP(lParam);
  689.              int usvk  = SHORT2FROMMP(lParam);
  690.  
  691.              if (flags & KC_VIRTUALKEY)
  692.                 if (usvk == VK_F1)
  693.                 {
  694.                     This->Transparency = TRUE;
  695.                     WinInvalidateRect(hWnd, NULL, TRUE);
  696.                 }
  697.                 else
  698.                 if (usvk == VK_F2)
  699.                 {
  700.                     This->Transparency = FALSE;
  701.                     WinInvalidateRect(hWnd, NULL, TRUE);
  702.                 }
  703.  
  704.         }
  705.         break;
  706.  
  707.  
  708.     case WM_USER:
  709.         {
  710.             WinInvalidateRect(hWnd, NULL, TRUE);
  711.             WinShowWindow(hWnd,TRUE);
  712.             ignorePaint = FALSE;
  713.             return(MRESULT)1;
  714.         }
  715.         break;
  716.  
  717.     case WM_PAINT:
  718.         {
  719.             if (inPaint == TRUE && ignorePaint) {
  720.                 // pretend we painted....
  721.                 RECTL invalidRect;
  722.                 WinBeginPaint(hWnd, This->hps, &invalidRect);
  723.                 WinEndPaint(This->hps);
  724.                 return (MRESULT)1;
  725.             }
  726.  
  727.             HWND parent = WinQueryWindow(hWnd,QW_PARENT);
  728.             if ((This->Transparency) && ignorePaint )   {
  729.                 inPaint = TRUE;
  730.                 WinShowWindow(hWnd,FALSE);
  731.                 WinPostMsg(hWnd, WM_USER, 0, 0);
  732.                 MRESULT rc =  ((PFNWP)This->lpfnOldWndProc)(hWnd,Message,wParam,lParam);
  733.                 return(rc);
  734.             }
  735.  
  736.             inPaint = FALSE;
  737.             ignorePaint = TRUE;
  738.  
  739.          // /* invalidate the whole window */
  740.          // WinInvalidateRect(hWnd, NULL, TRUE);
  741.  
  742.             /* get PS associated with window */
  743.             RECTL invalidRect;
  744.             WinBeginPaint(hWnd, This->hps, &invalidRect);
  745.  
  746.             /* get window size and convert to world coordinates */
  747.             WinQueryWindowRect(hWnd, &This->rect);
  748.             POINTL pts[2] = { { 0L, 0L },
  749.                               { This->rect.xRight, This->rect.yTop }
  750.                             };
  751.             GpiConvert(This->hps, CVTC_DEVICE, CVTC_WORLD, 2L, pts);
  752.  
  753.             // set onscreen flag - always true for painting to screen
  754.             BOOL OnScreen = TRUE;
  755.             if (OnScreen)
  756.             {
  757.                 HRGN hrgnUsed;
  758.                 This->pClock->Size(This->rect, &hrgnUsed);
  759.             }
  760.  
  761.             // draw background if not transparent
  762.             if ((!This->Transparency))
  763.                 WinFillRect(This->hps, &This->rect, CLR_BACKGROUND);
  764.  
  765.             /* draw using common drawing routine */
  766.             Draw(This, This->hps, &pts[1], FALSE);
  767.             WinEndPaint(This->hps);
  768.  
  769.             // start the timer for the next draw
  770.             if (! This->fTimer)
  771.             {
  772.                 WinStartTimer(WinQueryAnchorBlock(hWnd), hWnd,
  773.                               kTimerId, kTimerFrequency);
  774.                 This->fTimer = TRUE;
  775.             }
  776.         }
  777.         return (MRESULT)0;
  778.         break;
  779.  
  780.     default:
  781.         break;
  782.     }
  783.  
  784.     return ((PFNWP)This->lpfnOldWndProc)(
  785.                           hWnd,
  786.                           Message,
  787.                           wParam,
  788.                           lParam);
  789. }
  790.  
  791. void Draw(PluginInstance *This, HPS hps, POINTL *endPoint, BOOL fPrinting)
  792. {
  793.     if (fPrinting)
  794.     {
  795.         // This->pClock->Draw(hps, &This->rect, !fPrinting, This->Transparency);
  796.         POINTL ptl = { 0, 0 };
  797.         GpiMove(hps, &ptl);
  798.         GpiSetColor(hps, CLR_BLACK);
  799.         GpiBox(hps, DRO_OUTLINE, endPoint, 0L, 0L);
  800.         ptl.x += 40;
  801.         ptl.y = endPoint->y/4*3;
  802.         char *msg = "NPCLOCK Plugin";
  803.         GpiCharStringAt(hps, &ptl, strlen(msg), msg);
  804.         ptl.y = endPoint->y/4*2;
  805.         msg = "does not print";
  806.         GpiCharStringAt(hps, &ptl, strlen(msg), msg);
  807.         ptl.y = endPoint->y/4;
  808.         msg = "correctly yet.";
  809.         GpiCharStringAt(hps, &ptl, strlen(msg), msg);
  810.     }
  811.     else
  812.     {
  813.         ULONG saveID = GpiSavePS(hps);
  814.         This->pClock->Draw(hps, &This->rect, !fPrinting, This->Transparency);
  815.         GpiRestorePS(hps, saveID);
  816.     }
  817. }
  818.