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