home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
DOS/V Power Report 1997 December
/
VPR9712B.ISO
/
Nsos2
/
OS2PLUG.EXE
/
SAMPLE
/
NPCLOCK
/
npclock.cpp
< prev
next >
Wrap
Text File
|
1997-03-19
|
29KB
|
823 lines
/***************************************************************************
*
* File name : npclock.cpp
*
* Copyright (C) 1996 IBM Corporation
*
* DISCLAIMER OF WARRANTIES. The following [enclosed] code is
* sample code created by IBM Corporation. This sample code is not
* part of any standard or IBM product and is provided to you solely
* for the purpose of assisting you in the development of your
* applications. The code is provided "AS IS", without
* warranty of any kind. IBM shall not be liable for any damages
* arising out of your use of the sample code, even if they have been
* advised of the possibility of such damages.
*
***************************************************************************/
#define INCL_WIN
#define INCL_DOSPROCESS
#define INCL_GPI
#include <os2.h>
#include <string.h>
#include <stdlib.h>
#ifndef _NPAPI_H_
#include "npapi.h"
#endif
#include "clock.hpp"
// constants for timer
#define kTimerId 1
#define kTimerFrequency 20
//
// Instance state information about the plugin.
//
// *Developers*: Use this struct to hold per-instance
// information that you'll need in the
// various functions in this file.
//
typedef struct _PluginInstance PluginInstance;
typedef struct _PluginInstance
{
NPWindow* fWindow;
HWND hWnd;
uint16 fMode;
PFNWP lpfnOldWndProc;
NPSavedData* pSavedInstanceData;
PluginInstance* pNext;
Clock *pClock;
HPS hps;
ULONG fTimer;
BOOL Transparency;
RECTL rect;
} PluginInstance;
MRESULT APIENTRY
SubClassFunc(HWND hWnd,ULONG Message,MPARAM wParam, MPARAM lParam);
void Draw(PluginInstance *This, HPS hps, POINTL *endPoint, BOOL fPrinting);
HMODULE DLLInstance;
#if defined ( __cplusplus )
extern "C" {
#endif
/* _CRT_init is the C run-time environment initialization function. */
/* It will return 0 to indicate success and -1 to indicate failure. */
int _CRT_init(void);
/* __ctordtorInit calls the C++ run-time constructors for static objects. */
void __ctordtorInit(void);
/* __ctordtorTerm calls the C++ run-time destructors for static objects. */
void __ctordtorTerm(void);
#ifdef STATIC_LINK
/* _CRT_term is the C run-time environment termination function. */
/* It only needs to be called when the C run-time functions are statically */
/* linked. */
void _CRT_term(void);
#else
/* A clean up routine registered with DosExitList must be used if runtime */
/* calls are required at exit AND the runtime is dynamically linked. This */
/* will guarantee that this clean up routine is run before the library DLL */
/* is terminated. Do any application housekeeping in cleanup() */
static void _System cleanup(ULONG ulReason);
#endif
#if defined ( __cplusplus )
}
#endif
extern "C"
unsigned long _System _DLL_InitTerm(unsigned long hModule, unsigned long
ulFlag)
{
DLLInstance = (HMODULE) hModule;
switch (ulFlag)
{
case 0:
if ( _CRT_init() == -1 )
{
return(0UL);
}
#if defined ( __cplusplus )
__ctordtorInit();
#endif
#ifndef STATIC_LINK
/*******************************************************************/
/* A DosExitList routine must be used to clean up if runtime calls */
/* are required at exit and the runtime is dynamically linked. */
/*******************************************************************/
DosExitList(0x0000FF00|EXLST_ADD, cleanup);
#endif
break;
case 1:
#if defined ( __cplusplus )
__ctordtorTerm();
#endif
#ifdef STATIC_LINK
_CRT_term();
#endif
break;
}
return 1;
}
#ifndef STATIC_LINK
static void cleanup(ULONG ulReason)
{
/* do any DLL cleanup here if needed AND if dynamically linked to the */
/* C Runtime libraries */
DosExitList(EXLST_EXIT, cleanup); /* remember to unlink ourselves */
return ;
}
#endif
// A plugin instance typically will subclass the plugin's client window, so
// it can get Windows messages, (such as paint, palettechanged, keybd, etc).
// To do work associated with a specific plugin instance the WndProc which
// receives the Windows messages, (named "SubClassFunc" herein), needs access
// to the "This" (PluginInstance*) ptr.
// If the plugin wants all the keyboard messages, it will have to
// create a frame window with it's own accelerator table (even it it is empty)
// and insure that that frame tracks the plugin window that Navigator creates,
// otherwise the Navigator Accelerators will interfere with the WM_CHARs
// that the plugin windows receive...
// When Navigator registers the plugin client's window class, (the class for
// the window passed in NPP_SetWindow()), Navigator reserves 4
// "extra" window bytes for the plugins use... at QWL_USER
// Associate the hWnd with pInstance by setting the hWnd member of the
// PluginInstance struct.
static void AssociateInstance(HWND hWnd, PluginInstance* pInstance)
{
pInstance->hWnd = hWnd; // redundant, but usefull to get hwnd from
// pinstance later.
BOOL rc = WinSetWindowULong(hWnd, QWL_USER, (ULONG)pInstance);
}
// Find the PluginInstance associated with this hWnd and return it
static PluginInstance* GetInstance(HWND hWnd)
{
return (PluginInstance*)WinQueryWindowULong(hWnd, QWL_USER);
}
//----------------------------------------------------------------------------
// NPP_Initialize:
//----------------------------------------------------------------------------
NPError NPP_Initialize(void)
{
// do your one time initialization here, such as dynamically loading
// dependant DLLs
return NPERR_NO_ERROR;
}
//----------------------------------------------------------------------------
// NPP_Shutdown:
//----------------------------------------------------------------------------
void NPP_Shutdown(void)
{
// do your one time uninitialization here, such as unloading dynamically
// loaded DLLs
}
//----------------------------------------------------------------------------
// NPP_New:
//----------------------------------------------------------------------------
NPError NP_LOADDS
NPP_New(NPMIMEType pluginType,
NPP instance,
uint16 mode,
int16 argc,
char* argn[],
char* argv[],
NPSavedData* saved)
{
if (instance == NULL)
return NPERR_INVALID_INSTANCE_ERROR;
instance->pdata = NPN_MemAlloc(sizeof(PluginInstance));
PluginInstance* This = (PluginInstance*) instance->pdata;
if (This == NULL)
return NPERR_OUT_OF_MEMORY_ERROR;
//
// *Developers*: Initialize fields of your plugin
// instance data here. If the NPSavedData is non-
// NULL, you can use that data (returned by you from
// NPP_Destroy to set up the new plugin instance.
//
// set defaults
This->Transparency = FALSE;
BOOL AnalogClock = TRUE;
// parse arguments and set values
for (int i=0; i<argc; i++ )
{
if (! stricmp(argn[i], "FORMAT"))
{
if (! stricmp(argv[i], "DIGITAL"))
AnalogClock = FALSE;
AnalogClock = TRUE; // remove this line when digital works better
}
else if (! stricmp(argn[i], "TRANSPARENCY"))
{
if (! stricmp(argv[i], "TRUE"))
This->Transparency = TRUE;
}
}
This->fWindow = 0;
// mode is NP_EMBED, NP_FULL, or NP_BACKGROUND (see npapi.h)
This->fMode = mode;
This->hWnd = 0;
This->pSavedInstanceData = saved;
This->pNext = 0 ;
This->hps = NULL;
This->fTimer = FALSE;
This->pClock = new Clock();
// depends on setting of FORMAT argument value
if (AnalogClock)
This->pClock->SetMode(DM_TIME | DM_ANALOG | DM_SECONDHAND);
else
This->pClock->SetMode(DM_TIME | DM_DIGITAL | DM_SECONDHAND);
return NPERR_NO_ERROR;
}
//-----------------------------------------------------------------------------
// NPP_Destroy:
//-----------------------------------------------------------------------------
NPError NP_LOADDS
NPP_Destroy(NPP instance, NPSavedData** save)
{
if (instance == 0 )
return NPERR_INVALID_INSTANCE_ERROR;
PluginInstance* This = (PluginInstance*) instance->pdata;
//
// *Developers*: If desired, call NP_MemAlloc to create a
// NPSavedDate structure containing any state information
// that you want restored if this plugin instance is later
// recreated.
//
if (This != 0 )
{
// stop the timer
if (This->fTimer)
{
WinStopTimer(WinQueryAnchorBlock(This->hWnd), This->hWnd, kTimerId);
This->fTimer = FALSE;
}
// destroy old PS and create new PS
if (! This->hps)
GpiDestroyPS(This->hps);
// delete clock
delete This->pClock;
// Remove the subclass for the client window
if(This->hWnd)
{
WinSubclassWindow(This->hWnd, This->lpfnOldWndProc);
}
// make some saved instance data if necessary
if(This->pSavedInstanceData == 0 ) {
// make a struct header for the data
This->pSavedInstanceData =
(NPSavedData*)NPN_MemAlloc(sizeof (struct _NPSavedData));
// fill in the struct
if(This->pSavedInstanceData != 0 ) {
This->pSavedInstanceData->len = 0;
This->pSavedInstanceData->buf = 0 ;
// replace the def below and references to it with your data
#define SIDATA "aSavedInstanceDataBlock"
// the data
This->pSavedInstanceData->buf = NPN_MemAlloc(sizeof SIDATA);
if(This->pSavedInstanceData->buf != 0 ) {
strcpy((char*)This->pSavedInstanceData->buf, SIDATA);
This->pSavedInstanceData->len = sizeof SIDATA;
}
}
}
// save some instance data
*save = This->pSavedInstanceData;
NPN_MemFree(instance->pdata);
instance->pdata = 0 ;
}
return NPERR_NO_ERROR;
}
//----------------------------------------------------------------------------
// NPP_SetWindow:
//----------------------------------------------------------------------------
NPError NP_LOADDS
NPP_SetWindow(NPP instance, NPWindow* window)
{
if (instance == 0 )
return NPERR_INVALID_INSTANCE_ERROR;
PluginInstance* This = (PluginInstance*) instance->pdata;
//
// *Developers*: Before setting fWindow to point to the
// new window, you may wish to compare the new window
// info to the previous window (if any) to note window
// size changes, etc.
//
if((window->window != 0 ) && (This->hWnd == 0 ))
{
This->fWindow = window;
This->hWnd = (HWND)This->fWindow->window;
// subclass the window
This->lpfnOldWndProc = WinSubclassWindow(This->hWnd, SubClassFunc);
AssociateInstance(This->hWnd, This);
// create a PS
if (! This->hps)
{
HDC hdc = WinQueryWindowDC(This->hWnd);
if (! hdc)
hdc = WinOpenWindowDC(This->hWnd);
SIZEL siz = { 0, 0 };
This->hps = GpiCreatePS(WinQueryAnchorBlock(This->hWnd), hdc, &siz,
PU_PELS | GPIT_MICRO | GPIA_ASSOC);
}
}
else {
// if window handle changed
if(This->hWnd != (HWND)window->window) {
// remember the new window
This->fWindow = window;
// Remove the subclass for the old client window
WinSubclassWindow(This->hWnd, This->lpfnOldWndProc);
// remember the new window handle
This->hWnd = (HWND)This->fWindow->window;
if(This->hWnd != 0 ) {
// subclass the new one
This->lpfnOldWndProc = WinSubclassWindow(This->hWnd,
SubClassFunc);
AssociateInstance(This->hWnd, This);
}
// stop old timer and start a new timer
WinStopTimer(WinQueryAnchorBlock(This->hWnd), This->hWnd, kTimerId);
WinStartTimer(WinQueryAnchorBlock(This->hWnd), This->hWnd,
kTimerId, kTimerFrequency);
// destroy old PS and create new PS
if (! This->hps)
GpiDestroyPS(This->hps);
HDC hdc = WinQueryWindowDC(This->hWnd);
if (! hdc)
hdc = WinOpenWindowDC(This->hWnd);
SIZEL siz = { 0, 0 };
This->hps = GpiCreatePS(WinQueryAnchorBlock(This->hWnd), hdc, &siz,
PU_TWIPS | GPIT_MICRO | GPIA_ASSOC);
}
}
return NPERR_NO_ERROR;
}
//----------------------------------------------------------------------------
// NPP_NewStream:
//----------------------------------------------------------------------------
NPError NP_LOADDS
NPP_NewStream(NPP instance,
NPMIMEType type,
NPStream *stream,
NPBool seekable,
uint16 *stype)
{
if (instance == 0 )
return NPERR_INVALID_INSTANCE_ERROR;
PluginInstance* This = (PluginInstance*) instance->pdata;
// if your plugin must operate file based, you may wish to do this:
// *stype = NP_ASFILE;
// remember, though, that use of NP_ASFILE is strongly discouraged;
// your plugin should attempt to work with data as it comes in on
// the stream if at all possible
return NPERR_NO_ERROR;
}
//
// *Developers*:
// These next 2 functions are directly relevant in a plug-in which handles the
// data in a streaming manner. If you want zero bytes because no buffer space
// is YET available, return 0. As long as the stream has not been written
// to the plugin, Navigator will continue trying to send bytes. If the plugin
// doesn't want them, just return some large number from NPP_WriteReady(), and
// ignore them in NPP_Write(). For a NP_ASFILE stream, they are still called
// but can safely be ignored using this strategy.
//
int32 STREAMBUFSIZE = 0X0FFFFFFF; // If we are reading from a file in
// NP_ASFILE mode, we can take any size
// stream in our write call (since we
// ignore it)
//----------------------------------------------------------------------------
// NPP_WriteReady:
//----------------------------------------------------------------------------
int32 NP_LOADDS
NPP_WriteReady(NPP instance, NPStream *stream)
{
if (instance != 0 )
PluginInstance* This = (PluginInstance*) instance->pdata;
return STREAMBUFSIZE; // Number of bytes ready to accept in NPP_Write()
}
//----------------------------------------------------------------------------
// NPP_Write:
//----------------------------------------------------------------------------
int32 NP_LOADDS
NPP_Write(NPP instance, NPStream *stream,
int32 offset, int32 len, void *buffer)
{
if (instance != 0 )
PluginInstance* This = (PluginInstance*) instance->pdata;
return len; // The number of bytes accepted. Return a
// negative number here if, e.g., there was an error
// during plugin operation and you want to abort the
// stream
}
//----------------------------------------------------------------------------
// NPP_DestroyStream:
//----------------------------------------------------------------------------
NPError NP_LOADDS
NPP_DestroyStream(NPP instance, NPStream *stream, NPError reason)
{
if (instance == 0 )
return NPERR_INVALID_INSTANCE_ERROR;
PluginInstance* This = (PluginInstance*) instance->pdata;
return NPERR_NO_ERROR;
}
//----------------------------------------------------------------------------
// NPP_StreamAsFile:
//----------------------------------------------------------------------------
void NP_LOADDS
NPP_StreamAsFile(NPP instance, NPStream *stream, const char* fname)
{
if (instance == 0 )
return;
PluginInstance* This = (PluginInstance*) instance->pdata;
// invalidate window to ensure a redraw
WinInvalidateRect(This->hWnd, 0, TRUE);
}
//----------------------------------------------------------------------------
// NPP_Print:
//----------------------------------------------------------------------------
void NP_LOADDS
NPP_Print(NPP instance, NPPrint* printInfo)
{
if(printInfo == 0 ) // trap invalid parm
return;
if (instance != 0 )
{
PluginInstance* This = (PluginInstance*) instance->pdata;
if (printInfo->mode == NP_FULL)
{
//
// *Developers*: If your plugin would like to take over
// printing completely when it is in full-screen mode,
// set printInfo->pluginPrinted to TRUE and print your
// plugin as you see fit. If your plugin wants Netscape
// to handle printing in this case, set printInfo->pluginPrinted
// to FALSE (the default) and do nothing. If you do want
// to handle printing yourself, printOne is true if the
// print button (as opposed to the print menu) was clicked.
// On the Macintosh, platformPrint is a THPrint; on Windows,
// platformPrint is a structure (defined in npapi.h) containing
// the printer name, port, etc.
//
void* platformPrint = printInfo->print.fullPrint.platformPrint;
NPBool printOne = printInfo->print.fullPrint.printOne;
printInfo->print.fullPrint.pluginPrinted = FALSE; // Do the default
}
else // If not fullscreen, we must be embedded
{
//
// *Developers*: If your plugin is embedded, or is full-screen
// but you returned false in pluginPrinted above, NPP_Print
// will be called with mode == NP_EMBED. The NPWindow
// in the printInfo gives the location and dimensions of
// the embedded plugin on the printed page. On the Macintosh,
// platformPrint is the printer port; on Windows, platformPrint
// is the handle to the printing device context. On OS/2,
// platformPrint is the printing presentation space (HPS).
//
NPWindow* printWindow = &(printInfo->print.embedPrint.window);
/* get Presentation Space and save it */
void* platformPrint = printInfo->print.embedPrint.platformPrint;
HPS hps = (HPS)platformPrint;
/* create GPI various data structures about the drawing area */
POINTL offWindow = { (int)printWindow->x, (int)printWindow->y };
POINTL endPoint = { (int)printWindow->width, (int)printWindow->height };
This->rect.xLeft = (int)printWindow->x;
This->rect.yBottom = (int)printWindow->y;
This->rect.xRight = (int)printWindow->x + (int)printWindow->width;
This->rect.yTop = (int)printWindow->y + (int)printWindow->height;
/* get model transform so origin is 0,0 */
MATRIXLF matModel;
GpiQueryModelTransformMatrix(hps, 9L, &matModel);
GpiTranslate(hps, &matModel, TRANSFORM_ADD, &offWindow);
GpiSetModelTransformMatrix(hps, 9L, &matModel, TRANSFORM_REPLACE);
/* draw using common drawing routine */
Draw(This, hps, &endPoint, TRUE);
}
}
}
//----------------------------------------------------------------------------
// NPP_HandleEvent:
// Mac-only.
//----------------------------------------------------------------------------
int16 NP_LOADDS NPP_HandleEvent(NPP instance, void* event)
{
NPBool eventHandled = FALSE;
if (instance == 0 )
return eventHandled;
PluginInstance* This = (PluginInstance*) instance->pdata;
//
// *Developers*: The "event" passed in is a Macintosh
// EventRecord*. The event.what field can be any of the
// normal Mac event types, or one of the following additional
// types defined in npapi.h: getFocusEvent, loseFocusEvent,
// adjustCursorEvent. The focus events inform your plugin
// that it will become, or is no longer, the recepient of
// key events. If your plugin doesn't want to receive key
// events, return false when passed at getFocusEvent. The
// adjustCursorEvent is passed repeatedly when the mouse is
// over your plugin; if your plugin doesn't want to set the
// cursor, return false. Handle the standard Mac events as
// normal. The return value for all standard events is currently
// ignored except for the key event: for key events, only return
// true if your plugin has handled that particular key event.
//
return eventHandled;
}
//
// Here is a sample subclass function.
//
MRESULT APIENTRY
SubClassFunc( HWND hWnd,
ULONG Message,
MPARAM wParam,
MPARAM lParam)
{
PluginInstance *This = GetInstance(hWnd);
static int needPaint = FALSE;
static int ignorePaint = TRUE;
switch(Message) {
case WM_REALIZEPALETTE:
WinInvalidateRect(hWnd, 0, TRUE);
WinUpdateWindow(hWnd);
return 0;
break;
case WM_TIMER:
{
if ((ULONG)wParam == kTimerId)
{
/* get window size */
RECTL rect;
WinQueryWindowRect(hWnd, &rect);
/* draw updated clock */
ULONG saveID = GpiSavePS(This->hps);
if (This->pClock->Timer(This->hps, &rect))
WinInvalidateRect(hWnd, NULL, TRUE);
GpiRestorePS(This->hps, saveID);
}
}
return (MRESULT)0;
break;
case WM_BUTTON1DOWN:
WinSetFocus(HWND_DESKTOP,hWnd);
return(MRESULT)1;
case WM_CHAR:
{
int flags = SHORT1FROMMP(wParam);
int usch = SHORT1FROMMP(lParam);
int usvk = SHORT2FROMMP(lParam);
if (flags & KC_VIRTUALKEY)
if (usvk == VK_F1)
{
This->Transparency = TRUE;
WinInvalidateRect(hWnd, NULL, TRUE);
}
else
if (usvk == VK_F2)
{
This->Transparency = FALSE;
WinInvalidateRect(hWnd, NULL, TRUE);
}
}
break;
case WM_SEM3:
{ // see comments for WP_PAINT below
WinInvalidateRect(hWnd, NULL, TRUE);
ignorePaint = FALSE;
WinShowWindow(hWnd,TRUE);
return(MRESULT)1;
}
break;
case WM_PAINT:
{
/* This is a really tricky way to simulate transparency in ns30.
We only do this when transparency="true" is on the embed tag.
Initially we ignore all paint messages (ignorepaint=true),
but remember when we get a wm_paint (needPaint=true).
We post a WM_SEM3 (netscape uses WM_SEM4 so we can't!)
when we get the first WM_PAINT. Then we hide our window and
pass the paint to the old subclass (really WinDefWindowProc)
which causes the parent to paint (giving us our background)
We later get the WM_SEM3 be cause we need a very low priority
message, one that will arrive AFTER all the painting is done.
When we later get the WM_SEM3, we set ignorepaint=false so
that we really do paint this time.
Then we show our window (causing another paint).
Since netscape as already painted the background for us!
Don't try this at home... */
if (needPaint == TRUE && ignorePaint) {
// pretend we painted....
RECTL invalidRect;
WinBeginPaint(hWnd, This->hps, &invalidRect);
WinEndPaint(This->hps);
return (MRESULT)1;
}
HWND parent = WinQueryWindow(hWnd,QW_PARENT);
if ((This->Transparency) && ignorePaint ) {
needPaint = TRUE;
WinShowWindow(hWnd,FALSE);
WinPostMsg(hWnd, WM_SEM3, 0, 0);
MRESULT rc = ((PFNWP)This->lpfnOldWndProc)(hWnd,Message,wParam,lParam);
return(rc);
}
needPaint = FALSE;
ignorePaint = TRUE;
// /* invalidate the whole window */
// WinInvalidateRect(hWnd, NULL, TRUE);
/* get PS associated with window */
RECTL invalidRect;
WinBeginPaint(hWnd, This->hps, &invalidRect);
/* get window size and convert to world coordinates */
WinQueryWindowRect(hWnd, &This->rect);
POINTL pts[2] = { { 0L, 0L },
{ This->rect.xRight, This->rect.yTop }
};
GpiConvert(This->hps, CVTC_DEVICE, CVTC_WORLD, 2L, pts);
// set onscreen flag - always true for painting to screen
BOOL OnScreen = TRUE;
if (OnScreen)
{
HRGN hrgnUsed;
This->pClock->Size(This->rect, &hrgnUsed);
}
// draw background if not transparent
if ((!This->Transparency))
WinFillRect(This->hps, &This->rect, CLR_BACKGROUND);
/* draw using common drawing routine */
Draw(This, This->hps, &pts[1], FALSE);
WinEndPaint(This->hps);
// start the timer for the next draw
if (! This->fTimer)
{
WinStartTimer(WinQueryAnchorBlock(hWnd), hWnd,
kTimerId, kTimerFrequency);
This->fTimer = TRUE;
}
}
return (MRESULT)0;
break;
default:
break;
}
return ((PFNWP)This->lpfnOldWndProc)(
hWnd,
Message,
wParam,
lParam);
}
void Draw(PluginInstance *This, HPS hps, POINTL *endPoint, BOOL fPrinting)
{
if (fPrinting)
{
// This->pClock->Draw(hps, &This->rect, !fPrinting, This->Transparency);
POINTL ptl = { 0, 0 };
GpiMove(hps, &ptl);
GpiSetColor(hps, CLR_BLACK);
GpiBox(hps, DRO_OUTLINE, endPoint, 0L, 0L);
ptl.x += 40;
ptl.y = endPoint->y/4*3;
char *msg = "NPCLOCK Plugin";
GpiCharStringAt(hps, &ptl, strlen(msg), msg);
ptl.y = endPoint->y/4*2;
msg = "does not print";
GpiCharStringAt(hps, &ptl, strlen(msg), msg);
ptl.y = endPoint->y/4;
msg = "correctly yet.";
GpiCharStringAt(hps, &ptl, strlen(msg), msg);
}
else
{
ULONG saveID = GpiSavePS(hps);
This->pClock->Draw(hps, &This->rect, !fPrinting, This->Transparency);
GpiRestorePS(hps, saveID);
}
}