home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
DOS/V Power Report 1997 April
/
VPR9704B.ISO
/
nsos2
/
os2plug.exe
/
SAMPLE
/
NPSHELL
/
npshell.cpp
< prev
next >
Wrap
Text File
|
1996-11-13
|
22KB
|
633 lines
/***************************************************************************
*
* File name : npshell.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.
*
* This file defines a "shell" plugin that plugin developers can use
* as the basis for a real plugin. This shell just provides empty
* implementations of all functions that the plugin can implement
* that will be called by Netscape (the NPP_xxx methods defined in
* npapi.h).
*
***************************************************************************/
#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
//
// 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;
} PluginInstance;
MRESULT APIENTRY
SubClassFunc(HWND hWnd,ULONG Message,MPARAM wParam, MPARAM lParam);
void Draw(PluginInstance *This, HPS hps, POINTL *endPoint, BOOL fPrinting);
HMODULE DLLInstance;
extern "C" {
#if defined ( __cplusplus )
void __ctordtorInit(void);
void __ctordtorTerm(void);
#endif
}
/* _CRT_init is the C run-time environment initialization function. */
/* It will return 0 to indicate success and -1 to indicate failure. */
extern "C"
int _CRT_init(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. */
extern "C"
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. */
static void _System cleanup(ULONG ulReason);
#endif
/* __ctordtorInit is the C++ run-time environment initialization function. */
/* It is required to initialize static objects and destructors are setup */
extern "C"
void __ctordtorInit(void);
/* __ctordtorInit is the C++ run-time environment initialization function. */
/* It is required to insure static objects destructors are run */
/* You must call this before calling _CRT_term() */
extern "C"
void __ctordtorInit(void);
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);
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.
//* OS2 bugbug -- we need to reserve 4 bytes of window words to correct this
// gorp.....
// When Navigator registers the plugin client's window class, (the class for
// the window passed in NPP_SetWindow()), Navigator does not reserve any
// "extra" windows bytes. If it had, the plugin could simply have stored its
// "This" (PluginInstance*) ptr in the extra bytes. But Nav did not, and the
// plugin cannot, so a different technique must be used. The technique used
// is to keep a linked list of PluginInstance structures, and walk the list
// to find which one is associated with the window handle. Inefficient,
// grungy, complicates the code, etc. C'est la vie ...
PluginInstance* g_pHeadInstanceList = 0;
// Associate the hWnd with pInstance by setting the hWnd member of the
// PluginInstance struct. Also, add the PluginInstance struct to the list
// if necessary
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.
//
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 ;
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 )
{
// 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);
}
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);
}
}
}
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 */
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 };
RECTL rect = { (int)printWindow->x,
(int)printWindow->y,
(int)printWindow->x + (int)printWindow->width,
(int)printWindow->y + (int)printWindow->height };
/* set 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);
switch(Message) {
case WM_REALIZEPALETTE:
WinInvalidateRect(hWnd, 0, TRUE);
WinUpdateWindow(hWnd);
return 0;
break;
case WM_PAINT:
{
/* invalidate the whole window */
WinInvalidateRect(hWnd, NULL, TRUE);
/* get PS associated with window and set to PU_TWIPS coordinates */
RECTL invalidRect;
HPS hps = WinBeginPaint(hWnd, NULL, &invalidRect);
SIZEL siz = { 0,0 };
GpiSetPS(hps, &siz, PU_TWIPS);
/* get window size and convert to world coordinates */
RECTL rect;
WinQueryWindowRect(hWnd, &rect);
POINTL pts[2] = { { 0L, 0L },
{ rect.xRight, rect.yTop }
};
GpiConvert(hps, CVTC_DEVICE, CVTC_WORLD, 2L, pts);
/* draw using common drawing routine */
Draw(This, hps, &pts[1], FALSE);
WinEndPaint(hps);
}
return (MRESULT)0;
break;
default:
break;
}
return ((PFNWP)This->lpfnOldWndProc)(
hWnd,
Message,
wParam,
lParam);
}
void Draw(PluginInstance *This, HPS hps, POINTL *endPoint, BOOL fPrinting)
{
// Draw random colored box.
// Notice when you resize the browser window, the plugin actually gets
// drawn twice. You may want to draw into a bitmap and bitblt to
// improve performance if you plugin does a lot of drawing.
POINTL ptl = { 0, 0 };
GpiMove(hps, &ptl);
GpiSetColor(hps, rand()%15+1);
GpiBox(hps, DRO_OUTLINEFILL, endPoint, 0L, 0L);
}