mirror of
https://github.com/rn10950/RetroZilla.git
synced 2024-11-16 12:30:13 +01:00
1226 lines
34 KiB
C++
1226 lines
34 KiB
C++
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||
/* ***** BEGIN LICENSE BLOCK *****
|
||
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||
*
|
||
* The contents of this file are subject to the Mozilla Public License Version
|
||
* 1.1 (the "License"); you may not use this file except in compliance with
|
||
* the License. You may obtain a copy of the License at
|
||
* http://www.mozilla.org/MPL/
|
||
*
|
||
* Software distributed under the License is distributed on an "AS IS" basis,
|
||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
||
* for the specific language governing rights and limitations under the
|
||
* License.
|
||
*
|
||
* The Original Code is Mozilla Communicator client code.
|
||
*
|
||
* The Initial Developer of the Original Code is
|
||
* Netscape Communications Corporation.
|
||
* Portions created by the Initial Developer are Copyright (C) 1998
|
||
* the Initial Developer. All Rights Reserved.
|
||
*
|
||
* Contributor(s):
|
||
*
|
||
* Alternatively, the contents of this file may be used under the terms of
|
||
* either the GNU General Public License Version 2 or later (the "GPL"), or
|
||
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||
* in which case the provisions of the GPL or the LGPL are applicable instead
|
||
* of those above. If you wish to allow use of your version of this file only
|
||
* under the terms of either the GPL or the LGPL, and not to allow others to
|
||
* use your version of this file under the terms of the MPL, indicate your
|
||
* decision by deleting the provisions above and replace them with the notice
|
||
* and other provisions required by the GPL or the LGPL. If you do not delete
|
||
* the provisions above, a recipient may use your version of this file under
|
||
* the terms of any one of the MPL, the GPL or the LGPL.
|
||
*
|
||
* ***** END LICENSE BLOCK ***** */
|
||
|
||
|
||
#include "npapi.h"
|
||
|
||
#include <Carbon/Carbon.h>
|
||
#include <CoreFoundation/CoreFoundation.h>
|
||
|
||
#include <string.h>
|
||
#include <ctype.h>
|
||
#include <stdio.h>
|
||
|
||
#define PLUGINFINDER_COMMAND_BEGINNING "javascript:window.open(\""
|
||
#define PLUGINFINDER_COMMAND_END "\",\"plugin\",\"toolbar=no,status=no,resizable=no,scrollbars=no,height=252,width=626\");"
|
||
#define PLUGINFINDER_COMMAND_END2 "\",\"plugin\",\"toolbar=no,status=no,resizable=yes,scrollbars=yes,height=252,width=626\");"
|
||
|
||
|
||
//
|
||
// Instance state information about the plugin.
|
||
//
|
||
class CPlugin
|
||
{
|
||
public:
|
||
enum HiliteState { kUnhilited = 0, kHilited = 1 };
|
||
|
||
static NPError Initialize();
|
||
static void Shutdown();
|
||
|
||
// no ctor because CPlugin is allocated and constructed by hand.
|
||
// ideally, this should use placement |new|.
|
||
|
||
void Constructor(NPP instance, NPMIMEType type, uint16 mode, int16 argc, char* argn[], char* argv[]);
|
||
void Destructor();
|
||
|
||
void SetWindow(NPWindow* window);
|
||
void Print(NPPrint* printInfo);
|
||
Boolean HandleEvent(EventRecord*);
|
||
|
||
protected:
|
||
void Draw(HiliteState hilite);
|
||
void DrawString(const unsigned char* text, short width, short height, short centerX, Rect drawRect);
|
||
void MouseDown();
|
||
|
||
Boolean FocusDraw();
|
||
void RestoreDraw();
|
||
|
||
void DetermineURL(int16 argc, char* argn[], char* argv[]);
|
||
char * MakeDefaultURL(void);
|
||
void AddMimeTypeToList(StringPtr cTypeString);
|
||
Boolean CheckMimeTypes();
|
||
void AskAndLoadURL();
|
||
void RefreshPluginPage();
|
||
|
||
Ptr New(UInt32 size);
|
||
void Delete(Ptr ptr);
|
||
|
||
Boolean IsPluginHidden(int16 argc, char* argn[], char* argv[]);
|
||
|
||
private:
|
||
static CIconHandle sIconHandle;
|
||
static CursHandle sHandCursor;
|
||
static char* sAltText;
|
||
static char* sInstallCommand;
|
||
static char* sDefaultPage;
|
||
static char* sRefreshText;
|
||
static char* sJavaScriptPage;
|
||
static FSSpec sDataFileSpec; // only used for Mac OS 9
|
||
static Boolean sRunningOnOSX;
|
||
|
||
NPP fInstance;
|
||
NPWindow* fWindow;
|
||
uint16 fMode;
|
||
NPMIMEType fType;
|
||
char* fPageURL;
|
||
char* fFileURL;
|
||
NPBool m_bOffline;
|
||
NPBool m_bJavaScript;
|
||
|
||
GrafPtr fSavePort;
|
||
RgnHandle fSaveClip;
|
||
Rect fRevealedRect;
|
||
short fSavePortTop;
|
||
short fSavePortLeft;
|
||
Boolean fUserInstalledPlugin;
|
||
Boolean fHiddenPlugin;
|
||
Boolean fAskedLoadURL;
|
||
};
|
||
|
||
|
||
CIconHandle CPlugin::sIconHandle = NULL;
|
||
CursHandle CPlugin::sHandCursor = NULL;
|
||
char* CPlugin::sAltText = NULL;
|
||
char* CPlugin::sInstallCommand = NULL;
|
||
char* CPlugin::sDefaultPage = NULL;
|
||
char* CPlugin::sRefreshText = NULL;
|
||
char* CPlugin::sJavaScriptPage = NULL;
|
||
FSSpec CPlugin::sDataFileSpec;
|
||
Boolean CPlugin::sRunningOnOSX = false;
|
||
|
||
extern short gResFile;
|
||
|
||
// 'cicn'
|
||
const short rBrokenPluginIcon = 326;
|
||
|
||
// 'CURS'
|
||
const short rHandCursor = 128;
|
||
|
||
// 'STR '
|
||
const short rDefaultPluginURL = 128;
|
||
const short rAltTextString = 129;
|
||
const short rJavaScriptInstallCommand = 130;
|
||
const short rRefreshTextString = 131;
|
||
const short rJavaScriptPageURL = 132;
|
||
|
||
// 'STR#'
|
||
const short rTypeListStrings = 129;
|
||
|
||
static const char szPluginFinderCommandBeginning[] = PLUGINFINDER_COMMAND_BEGINNING;
|
||
static const char szPluginFinderCommandEnd[] = PLUGINFINDER_COMMAND_END;
|
||
|
||
|
||
//------------------------------------------------------------------------------------
|
||
// NPP_Initialize:
|
||
//------------------------------------------------------------------------------------
|
||
NPError NPP_Initialize(void)
|
||
{
|
||
return CPlugin::Initialize();
|
||
}
|
||
|
||
|
||
//------------------------------------------------------------------------------------
|
||
// NPP_Shutdown:
|
||
//------------------------------------------------------------------------------------
|
||
void NPP_Shutdown(void)
|
||
{
|
||
CPlugin::Shutdown();
|
||
}
|
||
|
||
|
||
//------------------------------------------------------------------------------------
|
||
// NPP_New:
|
||
//------------------------------------------------------------------------------------
|
||
NPError NPP_New(NPMIMEType type, NPP instance, uint16 mode, int16 argc, char* argn[], char* argv[], NPSavedData*)
|
||
{
|
||
if (instance == NULL)
|
||
return NPERR_INVALID_INSTANCE_ERROR;
|
||
|
||
CPlugin* This = (CPlugin*) (char*)NPN_MemAlloc(sizeof(CPlugin));
|
||
instance->pdata = This;
|
||
if (This != NULL)
|
||
{
|
||
This->Constructor(instance, type, mode, argc, argn, argv);
|
||
return NPERR_NO_ERROR;
|
||
}
|
||
else
|
||
return NPERR_OUT_OF_MEMORY_ERROR;
|
||
}
|
||
|
||
|
||
|
||
|
||
//------------------------------------------------------------------------------------
|
||
// NPP_Destroy:
|
||
//------------------------------------------------------------------------------------
|
||
NPError NP_LOADDS
|
||
NPP_Destroy(NPP instance, NPSavedData** /*save*/)
|
||
{
|
||
if (instance == NULL)
|
||
return NPERR_INVALID_INSTANCE_ERROR;
|
||
|
||
CPlugin* This = (CPlugin*) instance->pdata;
|
||
|
||
if (This != NULL)
|
||
{
|
||
This->Destructor();
|
||
NPN_MemFree(This);
|
||
instance->pdata = NULL;
|
||
}
|
||
|
||
return NPERR_NO_ERROR;
|
||
}
|
||
|
||
|
||
|
||
|
||
//------------------------------------------------------------------------------------
|
||
// NPP_SetWindow:
|
||
//------------------------------------------------------------------------------------
|
||
NPError NPP_SetWindow(NPP instance, NPWindow* window)
|
||
{
|
||
if (instance == NULL)
|
||
return NPERR_INVALID_INSTANCE_ERROR;
|
||
|
||
CPlugin* This = (CPlugin*) instance->pdata;
|
||
if (This != NULL)
|
||
This->SetWindow(window);
|
||
|
||
return NPERR_NO_ERROR;
|
||
}
|
||
|
||
|
||
|
||
//------------------------------------------------------------------------------------
|
||
// NPP_NewStream:
|
||
//------------------------------------------------------------------------------------
|
||
NPError NP_LOADDS
|
||
NPP_NewStream(NPP instance,
|
||
NPMIMEType /*type*/,
|
||
NPStream* /*stream*/,
|
||
NPBool /*seekable*/,
|
||
uint16* /*stype*/)
|
||
{
|
||
if (instance == NULL)
|
||
return NPERR_INVALID_INSTANCE_ERROR;
|
||
|
||
return NPERR_NO_ERROR;
|
||
}
|
||
|
||
|
||
|
||
int32 STREAMBUFSIZE = 0X0FFFFFFF; // If we are reading from a file in NPAsFile
|
||
// mode so 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*/)
|
||
{
|
||
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*/)
|
||
{
|
||
return len; // The number of bytes accepted
|
||
}
|
||
|
||
|
||
|
||
//------------------------------------------------------------------------------------
|
||
// NPP_DestroyStream:
|
||
//------------------------------------------------------------------------------------
|
||
NPError NP_LOADDS
|
||
NPP_DestroyStream(NPP instance, NPStream* /*stream*/, NPError /*reason*/)
|
||
{
|
||
if (instance == NULL)
|
||
return NPERR_INVALID_INSTANCE_ERROR;
|
||
|
||
return NPERR_NO_ERROR;
|
||
}
|
||
|
||
|
||
//------------------------------------------------------------------------------------
|
||
// NPP_StreamAsFile:
|
||
//------------------------------------------------------------------------------------
|
||
void NP_LOADDS
|
||
NPP_StreamAsFile(NPP /*instance*/, NPStream */*stream*/, const char* /*fname*/)
|
||
{
|
||
}
|
||
|
||
|
||
|
||
//------------------------------------------------------------------------------------
|
||
// NPP_Print:
|
||
//------------------------------------------------------------------------------------
|
||
void NP_LOADDS
|
||
NPP_Print(NPP instance, NPPrint* printInfo)
|
||
{
|
||
if (printInfo == NULL)
|
||
return;
|
||
|
||
if (instance != NULL)
|
||
{
|
||
if (printInfo->mode == NP_FULL)
|
||
printInfo->print.fullPrint.pluginPrinted = FALSE; // Do the default
|
||
else // If not fullscreen, we must be embedded
|
||
{
|
||
CPlugin* This = (CPlugin*) instance->pdata;
|
||
if (This != NULL)
|
||
This->Print(printInfo);
|
||
}
|
||
}
|
||
|
||
}
|
||
|
||
|
||
//------------------------------------------------------------------------------------
|
||
// NPP_HandleEvent:
|
||
// Mac-only.
|
||
//------------------------------------------------------------------------------------
|
||
int16 NPP_HandleEvent(NPP instance, void* event)
|
||
{
|
||
if (instance != NULL)
|
||
{
|
||
CPlugin* This = (CPlugin*) instance->pdata;
|
||
if (This != NULL && event != NULL)
|
||
return This->HandleEvent((EventRecord*) event);
|
||
}
|
||
|
||
return FALSE;
|
||
}
|
||
|
||
|
||
//------------------------------------------------------------------------------------
|
||
// NPP_URLNotify:
|
||
//------------------------------------------------------------------------------------
|
||
void NPP_URLNotify(NPP /*instance*/, const char* /*url*/, NPReason /*reason*/, void* /*notifyData*/)
|
||
{
|
||
}
|
||
|
||
#ifdef OJI
|
||
//------------------------------------------------------------------------------------
|
||
// NPP_GetJavaClass:
|
||
//------------------------------------------------------------------------------------
|
||
jref NPP_GetJavaClass(void)
|
||
{
|
||
return NULL;
|
||
}
|
||
#endif /* OJI */
|
||
|
||
#pragma mark -
|
||
|
||
//------------------------------------------------------------------------------------
|
||
// CPlugin::Initialize:
|
||
//------------------------------------------------------------------------------------
|
||
NPError CPlugin::Initialize()
|
||
{
|
||
Handle string;
|
||
short saveResFile = CurResFile();
|
||
|
||
UseResFile(gResFile);
|
||
|
||
long systemVersion;
|
||
OSErr err = ::Gestalt(gestaltSystemVersion, &systemVersion);
|
||
sRunningOnOSX = (err == noErr) && (systemVersion >= 0x00001000);
|
||
|
||
// Get Resources
|
||
CPlugin::sIconHandle = GetCIcon(rBrokenPluginIcon);
|
||
CPlugin::sHandCursor = GetCursor(rHandCursor);
|
||
|
||
// Get "alt text" string
|
||
string = Get1Resource('STR ', rAltTextString);
|
||
if (string && *string)
|
||
{
|
||
short stringLen = (*string)[0];
|
||
CPlugin::sAltText = (char*)NPN_MemAlloc(stringLen +1);
|
||
if (CPlugin::sAltText != NULL)
|
||
{
|
||
short src = 1;
|
||
short dest = 0;
|
||
while (src <= stringLen)
|
||
CPlugin::sAltText[dest++] = (*string)[src++];
|
||
CPlugin::sAltText[dest++] = 0;
|
||
}
|
||
}
|
||
ReleaseResource(string);
|
||
|
||
// Get "refresh text" string
|
||
string = Get1Resource('STR ', rRefreshTextString);
|
||
if (string && *string)
|
||
{
|
||
short stringLen = (*string)[0];
|
||
CPlugin::sRefreshText = (char*)NPN_MemAlloc(stringLen + 1);
|
||
if (CPlugin::sRefreshText != NULL)
|
||
{
|
||
short src = 1;
|
||
short dest = 0;
|
||
while (src <= stringLen)
|
||
CPlugin::sRefreshText[dest++] = (*string)[src++];
|
||
CPlugin::sRefreshText[dest++] = 0;
|
||
}
|
||
}
|
||
ReleaseResource(string);
|
||
|
||
// Get JavaScript install command string
|
||
string = Get1Resource('STR ', rJavaScriptInstallCommand);
|
||
if (string && *string)
|
||
{
|
||
short stringLen = (*string)[0];
|
||
CPlugin::sInstallCommand = (char*)NPN_MemAlloc(stringLen + 1);
|
||
if (CPlugin::sInstallCommand != NULL)
|
||
{
|
||
short src = 1;
|
||
short dest = 0;
|
||
while (src <= stringLen)
|
||
CPlugin::sInstallCommand[dest++] = (*string)[src++];
|
||
CPlugin::sInstallCommand[dest++] = 0;
|
||
}
|
||
}
|
||
ReleaseResource(string);
|
||
|
||
// Get default plug-in page URL
|
||
string = Get1Resource('STR ', rDefaultPluginURL);
|
||
if (string && *string)
|
||
{
|
||
short stringLen = (*string)[0];
|
||
CPlugin::sDefaultPage = (char*)NPN_MemAlloc(stringLen + 1);
|
||
if (CPlugin::sDefaultPage != NULL)
|
||
{
|
||
short src = 1;
|
||
short dest = 0;
|
||
while (src <= stringLen)
|
||
CPlugin::sDefaultPage[dest++] = (*string)[src++];
|
||
CPlugin::sDefaultPage[dest++] = 0;
|
||
}
|
||
}
|
||
ReleaseResource(string);
|
||
|
||
// Get javascript plug-in page URL
|
||
string = Get1Resource('STR ', rJavaScriptPageURL);
|
||
if (string && *string)
|
||
{
|
||
short stringLen = (*string)[0];
|
||
CPlugin::sJavaScriptPage = (char*)NPN_MemAlloc(stringLen + 1);
|
||
if (CPlugin::sJavaScriptPage != NULL)
|
||
{
|
||
short src = 1;
|
||
short dest = 0;
|
||
while (src <= stringLen)
|
||
CPlugin::sJavaScriptPage[dest++] = (*string)[src++];
|
||
CPlugin::sJavaScriptPage[dest++] = 0;
|
||
}
|
||
}
|
||
ReleaseResource(string);
|
||
|
||
UseResFile(saveResFile);
|
||
|
||
if (!sRunningOnOSX) // We'll make some CFPreferences the first time we have to on OS X
|
||
{
|
||
ProcessSerialNumber psn;
|
||
ProcessInfoRec info;
|
||
FSSpec fsTheApp;
|
||
SInt16 wResFile;
|
||
OSErr wErr;
|
||
|
||
psn.highLongOfPSN = 0;
|
||
psn.lowLongOfPSN = kCurrentProcess;
|
||
|
||
info.processInfoLength = sizeof(ProcessInfoRec);
|
||
info.processName = nil;
|
||
info.processAppSpec = &fsTheApp;
|
||
wErr = ::GetProcessInformation(&psn, &info);
|
||
if (wErr == noErr) {
|
||
wErr = FSMakeFSSpec(fsTheApp.vRefNum, fsTheApp.parID, "\p:Plug-ins:Default Plug-in Data", &sDataFileSpec);
|
||
if (wErr == fnfErr) {
|
||
FSpCreateResFile(&sDataFileSpec, 'MOSS', 'BINA', smSystemScript);
|
||
wResFile = FSpOpenResFile(&CPlugin::sDataFileSpec, fsRdWrPerm);
|
||
if (wResFile != -1) {
|
||
// create a STR# with 0 entires (i.e. only a count)
|
||
string = NewHandleClear(sizeof(SInt16));
|
||
AddResource(string, 'STR#', rTypeListStrings, "\p");
|
||
UpdateResFile(wResFile);
|
||
ReleaseResource(string);
|
||
}
|
||
FSClose(wResFile);
|
||
}
|
||
}
|
||
}
|
||
|
||
return NPERR_NO_ERROR;
|
||
}
|
||
|
||
|
||
//------------------------------------------------------------------------------------
|
||
// CPlugin::Shutdown:
|
||
//------------------------------------------------------------------------------------
|
||
void CPlugin::Shutdown()
|
||
{
|
||
if (CPlugin::sIconHandle != NULL)
|
||
::ReleaseResource((Handle) CPlugin::sIconHandle);
|
||
if (CPlugin::sHandCursor != NULL)
|
||
::ReleaseResource((Handle) CPlugin::sHandCursor);
|
||
|
||
if (CPlugin::sAltText != NULL)
|
||
NPN_MemFree(CPlugin::sAltText);
|
||
if (CPlugin::sInstallCommand != NULL)
|
||
NPN_MemFree(CPlugin::sInstallCommand);
|
||
if (CPlugin::sDefaultPage != NULL)
|
||
NPN_MemFree(CPlugin::sDefaultPage);
|
||
if(CPlugin::sRefreshText != NULL)
|
||
NPN_MemFree(CPlugin::sRefreshText);
|
||
}
|
||
|
||
|
||
//------------------------------------------------------------------------------------
|
||
// CPlugin::Constructor:
|
||
//------------------------------------------------------------------------------------
|
||
void CPlugin::Constructor(NPP instance, NPMIMEType type, uint16 mode, int16 argc, char* argn[], char* argv[])
|
||
{
|
||
fWindow = NULL;
|
||
fPageURL = NULL;
|
||
fFileURL = NULL;
|
||
fInstance = instance;
|
||
fMode = mode; // Mode is NP_EMBED, NP_FULL, or NP_BACKGROUND (see npapi.h)
|
||
fAskedLoadURL = false;
|
||
fUserInstalledPlugin = false;
|
||
|
||
// Save a copy of our mime type string
|
||
short typeLength = strlen(type);
|
||
fType = (char*)NPN_MemAlloc(typeLength+1);
|
||
if (fType != NULL)
|
||
strcpy(fType, type);
|
||
|
||
// Make a handy region for use in FocusDraw
|
||
fSaveClip = NewRgn();
|
||
|
||
// determine if the plugin is specified as HIDDEN
|
||
if(IsPluginHidden(argc, argn, argv))
|
||
fHiddenPlugin = true;
|
||
else
|
||
fHiddenPlugin = false;
|
||
|
||
// Get some information about our environment
|
||
NPN_GetValue(fInstance, NPNVisOfflineBool, (void *)&m_bOffline);
|
||
NPN_GetValue(fInstance, NPNVjavascriptEnabledBool, (void *)&m_bJavaScript);
|
||
|
||
// Figure out what URL we will go to
|
||
DetermineURL(argc, argn, argv);
|
||
}
|
||
|
||
|
||
//------------------------------------------------------------------------------------
|
||
// CPlugin::Destructor:
|
||
//------------------------------------------------------------------------------------
|
||
void CPlugin::Destructor()
|
||
{
|
||
if (fSaveClip != NULL)
|
||
DisposeRgn(fSaveClip);
|
||
|
||
if (fType != NULL)
|
||
NPN_MemFree(fType);
|
||
if (fFileURL != NULL)
|
||
NPN_MemFree(fFileURL);
|
||
if (fPageURL != NULL)
|
||
NPN_MemFree(fPageURL);
|
||
}
|
||
|
||
|
||
|
||
//------------------------------------------------------------------------------------
|
||
// CPlugin::SetWindow:
|
||
//------------------------------------------------------------------------------------
|
||
void CPlugin::SetWindow(NPWindow* window)
|
||
{
|
||
fWindow = window;
|
||
}
|
||
|
||
|
||
//------------------------------------------------------------------------------------
|
||
// CPlugin::Print:
|
||
//
|
||
// To print, we need to retrieve the printing window from the printInfo,
|
||
// temporarily make it our window, draw into it, and restore the window.
|
||
//
|
||
//------------------------------------------------------------------------------------
|
||
void CPlugin::Print(NPPrint* printInfo)
|
||
{
|
||
NPWindow* printWindow = &(printInfo->print.embedPrint.window);
|
||
|
||
NPWindow* oldWindow = fWindow;
|
||
fWindow = printWindow;
|
||
|
||
if (FocusDraw())
|
||
{
|
||
Draw(kUnhilited);
|
||
RestoreDraw();
|
||
}
|
||
|
||
fWindow = oldWindow;
|
||
}
|
||
|
||
|
||
//------------------------------------------------------------------------------------
|
||
// CPlugin::HandleEvent:
|
||
//------------------------------------------------------------------------------------
|
||
Boolean CPlugin::HandleEvent(EventRecord* ev)
|
||
{
|
||
Boolean eventHandled = false;
|
||
|
||
switch (ev->what)
|
||
{
|
||
case mouseDown:
|
||
MouseDown();
|
||
eventHandled = true;
|
||
break;
|
||
|
||
case updateEvt:
|
||
if (FocusDraw()) {
|
||
Draw(kUnhilited);
|
||
RestoreDraw();
|
||
}
|
||
eventHandled = true;
|
||
break;
|
||
|
||
case NPEventType_AdjustCursorEvent:
|
||
if (CPlugin::sHandCursor != NULL)
|
||
SetCursor(*CPlugin::sHandCursor);
|
||
if (fUserInstalledPlugin) {
|
||
if (CPlugin::sRefreshText != NULL)
|
||
NPN_Status(fInstance, CPlugin::sRefreshText);
|
||
} else {
|
||
if (CPlugin::sAltText != NULL)
|
||
NPN_Status(fInstance, CPlugin::sAltText);
|
||
}
|
||
eventHandled = true;
|
||
break;
|
||
|
||
case nullEvent:
|
||
//
|
||
// NOTE: We have to wait until idle time
|
||
// to ask the user if they want to visit
|
||
// the URL to avoid reentering XP code.
|
||
//
|
||
if (!fAskedLoadURL) {
|
||
if (CheckMimeTypes())
|
||
AskAndLoadURL();
|
||
fAskedLoadURL = true;
|
||
}
|
||
break;
|
||
default:
|
||
break;
|
||
}
|
||
|
||
return eventHandled;
|
||
}
|
||
|
||
|
||
|
||
//------------------------------------------------------------------------------------
|
||
// CPlugin::Draw:
|
||
//------------------------------------------------------------------------------------
|
||
void CPlugin::Draw(HiliteState hilite)
|
||
{
|
||
UInt8 *pTheText;
|
||
SInt32 height = fWindow->height;
|
||
SInt32 width = fWindow->width;
|
||
SInt32 centerX = (width) >> 1;
|
||
SInt32 centerY = (height) >> 1;
|
||
Rect drawRect;
|
||
RGBColor black = { 0x0000, 0x0000, 0x0000 };
|
||
RGBColor white = { 0xFFFF, 0xFFFF, 0xFFFF };
|
||
RGBColor hiliteColor = { 0x0000, 0x0000, 0x0000 };
|
||
short transform;
|
||
|
||
drawRect.top = 0;
|
||
drawRect.left = 0;
|
||
drawRect.bottom = height;
|
||
drawRect.right = width;
|
||
|
||
if (height < 4 && width < 4)
|
||
return;
|
||
|
||
PenNormal();
|
||
RGBForeColor(&black);
|
||
RGBBackColor(&white);
|
||
|
||
Pattern qdWhite;
|
||
FillRect(&drawRect, GetQDGlobalsWhite(&qdWhite));
|
||
|
||
if (hilite == kHilited) {
|
||
hiliteColor.red = 0xFFFF;
|
||
transform = ttSelected;
|
||
} else {
|
||
hiliteColor.blue = 0xFFFF;
|
||
transform = ttNone;
|
||
}
|
||
|
||
RGBForeColor(&hiliteColor);
|
||
FrameRect(&drawRect);
|
||
|
||
if (height > 32 && width > 32 && CPlugin::sIconHandle != NULL)
|
||
{
|
||
drawRect.top = centerY - 16;
|
||
drawRect.bottom = centerY + 16;
|
||
drawRect.left = centerX - 16;
|
||
drawRect.right = centerX + 16;
|
||
PlotCIconHandle(&drawRect, atAbsoluteCenter, transform, CPlugin::sIconHandle);
|
||
}
|
||
|
||
if (fUserInstalledPlugin) {
|
||
pTheText = (unsigned char*)CPlugin::sRefreshText;
|
||
} else {
|
||
pTheText = (unsigned char*)CPlugin::sAltText;
|
||
}
|
||
DrawString(pTheText, width, height, centerX, drawRect);
|
||
}
|
||
|
||
|
||
|
||
//------------------------------------------------------------------------------------
|
||
// CPlugin::MouseDown:
|
||
//
|
||
// Track the click in our plugin by drawing the icon enabled or disabled
|
||
// as the user moves the mouse in and out with the button held down. If
|
||
// they let up the mouse while still inside, get the URL.
|
||
//
|
||
//------------------------------------------------------------------------------------
|
||
void CPlugin::MouseDown()
|
||
{
|
||
if (FocusDraw())
|
||
{
|
||
Draw(kHilited);
|
||
Boolean inside = true;
|
||
|
||
// evil CPU-hogging loop on Mac OS X!
|
||
while (StillDown())
|
||
{
|
||
Point localMouse;
|
||
GetMouse(&localMouse);
|
||
Boolean insideNow = ::PtInRect(localMouse, &fRevealedRect);
|
||
|
||
if (insideNow != inside)
|
||
{
|
||
Draw(insideNow ? kHilited : kUnhilited);
|
||
inside = insideNow;
|
||
}
|
||
}
|
||
|
||
if (inside) {
|
||
Draw(kUnhilited);
|
||
if (!fUserInstalledPlugin)
|
||
AskAndLoadURL();
|
||
else
|
||
RefreshPluginPage();
|
||
}
|
||
|
||
RestoreDraw();
|
||
}
|
||
}
|
||
|
||
|
||
//------------------------------------------------------------------------------------
|
||
// CPlugin::FocusDraw:
|
||
//------------------------------------------------------------------------------------
|
||
Boolean CPlugin::FocusDraw()
|
||
{
|
||
if (fWindow == NULL)
|
||
return false;
|
||
|
||
NP_Port* npport = (NP_Port*) fWindow->window;
|
||
CGrafPtr ourPort = npport->port;
|
||
|
||
if (fWindow->clipRect.left < fWindow->clipRect.right)
|
||
{
|
||
GetPort(&fSavePort);
|
||
SetPort((GrafPtr) ourPort);
|
||
Rect portRect;
|
||
GetPortBounds(ourPort, &portRect);
|
||
fSavePortTop = portRect.top;
|
||
fSavePortLeft = portRect.left;
|
||
GetClip(fSaveClip);
|
||
|
||
fRevealedRect.top = fWindow->clipRect.top + npport->porty;
|
||
fRevealedRect.left = fWindow->clipRect.left + npport->portx;
|
||
fRevealedRect.bottom = fWindow->clipRect.bottom + npport->porty;
|
||
fRevealedRect.right = fWindow->clipRect.right + npport->portx;
|
||
SetOrigin(npport->portx, npport->porty);
|
||
ClipRect(&fRevealedRect);
|
||
|
||
return true;
|
||
}
|
||
else
|
||
return false;
|
||
}
|
||
|
||
|
||
//------------------------------------------------------------------------------------
|
||
// CPlugin::RestoreDraw:
|
||
//------------------------------------------------------------------------------------
|
||
void CPlugin::RestoreDraw()
|
||
{
|
||
SetOrigin(fSavePortLeft, fSavePortTop);
|
||
SetClip(fSaveClip);
|
||
SetPort(fSavePort);
|
||
}
|
||
|
||
|
||
|
||
//------------------------------------------------------------------------------------
|
||
// CPlugin::DetermineURL:
|
||
//
|
||
// Get a URL from either the parameters passed from the EMBED.
|
||
// Append "?" and our mime type and save for later use.
|
||
//
|
||
//------------------------------------------------------------------------------------
|
||
void CPlugin::DetermineURL(int16 argc, char* argn[], char* argv[])
|
||
{
|
||
char* url;
|
||
SInt32 additionalLength = 0;
|
||
SInt32 i;
|
||
|
||
// Appended to the URL will be a "?" and the mime type of this instance. This lets the server
|
||
// do something intelligent with a CGI script.
|
||
|
||
if (fType != NULL)
|
||
additionalLength += (strlen(fType) + 1); // Add 1 for '?'
|
||
|
||
// The page designer can specify a URL where the plugin for this type can be downloaded. Here
|
||
// we scan the arguments for this attribute and save it away if we
|
||
// find it for later use by LoadPluginURL().
|
||
//
|
||
for (i = 0; i < argc; i++) {
|
||
if ((strcasecmp(argn[i], "PLUGINSPAGE") == 0) || (strcasecmp(argn[i], "CODEBASE") == 0)) {
|
||
url = argv[i];
|
||
fPageURL = (char*)NPN_MemAlloc(strlen(url) + 1 + additionalLength); // Add 1 for '\0'
|
||
if (fPageURL != NULL) {
|
||
if (additionalLength > 0) {
|
||
sprintf(fPageURL, "%s?%s", url, fType);
|
||
} else {
|
||
strcpy(fPageURL, url);
|
||
}
|
||
}
|
||
break;
|
||
} else if ((strcasecmp(argn[i], "PLUGINURL") == 0) || (strcasecmp(argn[i], "CLASSID") == 0)) {
|
||
url = argv[i];
|
||
if (CPlugin::sInstallCommand != NULL) {
|
||
// Allocate a new string
|
||
fFileURL = (char*)NPN_MemAlloc(strlen(CPlugin::sInstallCommand) + 1 + strlen(url));
|
||
if (fFileURL != NULL)
|
||
sprintf(fFileURL, CPlugin::sInstallCommand, url);
|
||
}
|
||
break;
|
||
}
|
||
}
|
||
}
|
||
|
||
|
||
|
||
//------------------------------------------------------------------------------------
|
||
// CPlugin::MakeDefaultURL:
|
||
//
|
||
// Get a URL from our resources. Append "?" and our mime type and save for later use.
|
||
//
|
||
//------------------------------------------------------------------------------------
|
||
char *CPlugin::MakeDefaultURL(void)
|
||
{
|
||
char *pDefURL = NULL;
|
||
SInt32 additionalLength = 0;
|
||
|
||
// Appended to the URL will be a "?" and the mime type of this instance. This lets the server
|
||
// do something intelligent with a CGI script.
|
||
|
||
if (fType != NULL)
|
||
additionalLength += (strlen(fType) + 1); // Add 1 for '?'
|
||
|
||
if (!m_bJavaScript) {
|
||
if (CPlugin::sDefaultPage != NULL) {
|
||
pDefURL = (char*)NPN_MemAlloc(strlen(CPlugin::sDefaultPage) + 1 + additionalLength);
|
||
if (pDefURL != NULL) {
|
||
if (additionalLength > 0) {
|
||
sprintf(pDefURL, "%s?%s", CPlugin::sDefaultPage, fType);
|
||
} else {
|
||
strcpy(pDefURL, CPlugin::sDefaultPage);
|
||
}
|
||
}
|
||
}
|
||
} else {
|
||
if (CPlugin::sJavaScriptPage != NULL) {
|
||
pDefURL = (char*)NPN_MemAlloc(strlen(szPluginFinderCommandBeginning) +
|
||
strlen(CPlugin::sJavaScriptPage) +
|
||
additionalLength + strlen(szPluginFinderCommandEnd) + 1);
|
||
if (pDefURL != NULL) {
|
||
sprintf(pDefURL, "%s%s%s%s", szPluginFinderCommandBeginning,
|
||
CPlugin::sJavaScriptPage, fType, szPluginFinderCommandEnd);
|
||
}
|
||
}
|
||
}
|
||
return(pDefURL);
|
||
}
|
||
|
||
|
||
|
||
//------------------------------------------------------------------------------------
|
||
// CPlugin::AddMimeTypeToList:
|
||
//
|
||
// Check the mime type of this instance against our list
|
||
// of types we<77>ve seen before. If we find our type in the
|
||
// list, return false; otherwise, return true.
|
||
//
|
||
// type 'STR#' {
|
||
// integer = $$Countof(StringArray);
|
||
// array StringArray {
|
||
// pstring;
|
||
// };
|
||
//
|
||
//------------------------------------------------------------------------------------
|
||
void CPlugin::AddMimeTypeToList(StringPtr cTypeString)
|
||
{
|
||
if (sRunningOnOSX)
|
||
{
|
||
CFStringRef pluginKey = CFSTR("DefaultPluginSeenTypes"); // don't release this
|
||
CFStringRef mimeType = ::CFStringCreateWithPascalString(kCFAllocatorDefault, cTypeString, kCFStringEncodingASCII);
|
||
CFArrayRef prefsList = (CFArrayRef)::CFPreferencesCopyAppValue(pluginKey, kCFPreferencesCurrentApplication);
|
||
Boolean foundType = false;
|
||
|
||
if (prefsList == NULL)
|
||
{
|
||
CFStringRef stringArray[1];
|
||
stringArray[0] = mimeType;
|
||
|
||
prefsList = ::CFArrayCreate(kCFAllocatorDefault, (const void **)stringArray, 1, &kCFTypeArrayCallBacks);
|
||
if (prefsList)
|
||
{
|
||
::CFPreferencesSetAppValue(pluginKey, prefsList, kCFPreferencesCurrentApplication);
|
||
::CFRelease(prefsList);
|
||
}
|
||
}
|
||
else
|
||
{
|
||
if (::CFGetTypeID(prefsList) == ::CFArrayGetTypeID())
|
||
{
|
||
// first make sure it's not in the list
|
||
CFIndex count = ::CFArrayGetCount(prefsList);
|
||
for (CFIndex i = 0; i < count; i ++)
|
||
{
|
||
CFStringRef item = (CFStringRef)::CFArrayGetValueAtIndex(prefsList, i); // does not retain
|
||
if (item &&
|
||
(::CFGetTypeID(item) == ::CFStringGetTypeID()) &&
|
||
(::CFStringCompareWithOptions(item, mimeType,
|
||
CFRangeMake(0, ::CFStringGetLength(item)), kCFCompareCaseInsensitive) == kCFCompareEqualTo))
|
||
{
|
||
foundType = true;
|
||
break;
|
||
}
|
||
}
|
||
|
||
if (!foundType && !fHiddenPlugin)
|
||
{
|
||
CFMutableArrayRef typesArray = ::CFArrayCreateMutableCopy(kCFAllocatorDefault, 0, (CFArrayRef)prefsList);
|
||
if (typesArray)
|
||
{
|
||
::CFArrayAppendValue(typesArray, mimeType);
|
||
::CFPreferencesSetAppValue(pluginKey, typesArray, kCFPreferencesCurrentApplication);
|
||
}
|
||
}
|
||
}
|
||
::CFRelease(prefsList);
|
||
}
|
||
::CFRelease(mimeType);
|
||
}
|
||
else
|
||
{
|
||
Handle hTypeList;
|
||
SInt32 dwCount;
|
||
SInt32 index;
|
||
Str255 oldType;
|
||
SInt16 wResFile;
|
||
Boolean failedToFind = true;
|
||
|
||
wResFile = FSpOpenResFile(&CPlugin::sDataFileSpec, fsRdWrPerm);
|
||
if (wResFile != -1) {
|
||
hTypeList = Get1Resource('STR#', rTypeListStrings);
|
||
if (hTypeList != NULL) {
|
||
dwCount = **((short **)hTypeList);
|
||
|
||
// First make sure it's not already in the list.
|
||
for (index = 1; index <= dwCount; index++) {
|
||
GetIndString(oldType, rTypeListStrings, index);
|
||
|
||
// if the mimetype already exists in our list, or the plugin is NOT hidden,
|
||
// don't bring up the dialog box
|
||
if (EqualString(cTypeString, oldType, true, true) && !fHiddenPlugin) {
|
||
failedToFind = false;
|
||
break; // Found a match, so bail out!
|
||
}
|
||
}
|
||
if (failedToFind) {
|
||
// Grow the string list handle
|
||
Size itsSize = GetHandleSize(hTypeList);
|
||
Size typeSize = cTypeString[0] + 1;
|
||
SetHandleSize(hTypeList, itsSize + typeSize);
|
||
|
||
// Increment the count of strings in the list
|
||
(**((short**)hTypeList)) = (short)(++dwCount);
|
||
|
||
// Copy the data from our string into the handle
|
||
long dwCount = Munger(hTypeList, itsSize, NULL, typeSize, cTypeString, typeSize);
|
||
|
||
// Mark the resource as changed so it will be written out
|
||
if (dwCount > 0) {
|
||
ChangedResource(hTypeList);
|
||
UpdateResFile(wResFile);
|
||
}
|
||
}
|
||
ReleaseResource(hTypeList);
|
||
}
|
||
FSClose(wResFile);
|
||
}
|
||
}
|
||
}
|
||
|
||
|
||
|
||
//------------------------------------------------------------------------------------
|
||
// CPlugin::CheckMimeTypes:
|
||
//
|
||
// Check the mime type of this instance against our list
|
||
// of types we<77>ve seen before. If we find our type in the
|
||
// list, return false; otherwise, return true.
|
||
//
|
||
// type 'STR#' {
|
||
// integer = $$Countof(StringArray);
|
||
// array StringArray {
|
||
// pstring;
|
||
// };
|
||
//
|
||
//------------------------------------------------------------------------------------
|
||
Boolean CPlugin::CheckMimeTypes()
|
||
{
|
||
Boolean failedToFind = true;
|
||
|
||
if (sRunningOnOSX)
|
||
{
|
||
CFStringRef pluginKey = CFSTR("DefaultPluginSeenTypes"); // don't release this
|
||
CFStringRef mimeType = ::CFStringCreateWithCString(kCFAllocatorDefault, fType, kCFStringEncodingASCII);
|
||
CFArrayRef prefsList = (CFArrayRef)::CFPreferencesCopyAppValue(pluginKey, kCFPreferencesCurrentApplication);
|
||
if (prefsList)
|
||
{
|
||
if (::CFGetTypeID(prefsList) == ::CFArrayGetTypeID())
|
||
{
|
||
CFIndex count = ::CFArrayGetCount(prefsList);
|
||
for (CFIndex i = 0; i < count; i ++)
|
||
{
|
||
CFStringRef item = (CFStringRef)::CFArrayGetValueAtIndex(prefsList, i); // does not retain
|
||
if (item &&
|
||
(::CFGetTypeID(item) == ::CFStringGetTypeID()) &&
|
||
(::CFStringCompareWithOptions(item, mimeType,
|
||
CFRangeMake(0, ::CFStringGetLength(item)), kCFCompareCaseInsensitive) == kCFCompareEqualTo))
|
||
{
|
||
failedToFind = false;
|
||
break;
|
||
}
|
||
}
|
||
}
|
||
::CFRelease(prefsList);
|
||
}
|
||
::CFRelease(mimeType);
|
||
}
|
||
else
|
||
{
|
||
Handle hTypeList;
|
||
SInt32 index;
|
||
Str255 oldType;
|
||
Str255 ourType;
|
||
SInt16 wResFile;
|
||
|
||
wResFile = FSpOpenResFile(&CPlugin::sDataFileSpec, fsRdPerm);
|
||
if (wResFile != -1) {
|
||
hTypeList = Get1Resource('STR#', rTypeListStrings);
|
||
if (hTypeList != NULL) {
|
||
// Convert the mime-type C string to a Pascal string.
|
||
index = strlen(fType);
|
||
if (index > 255) { // don't blow out the Str255
|
||
index = 255;
|
||
}
|
||
BlockMoveData(fType, &ourType[1], index);
|
||
ourType[0] = index;
|
||
|
||
short count = **((short **)hTypeList);
|
||
|
||
// Iterate through all the strings in the list.
|
||
for (index = 1; index <= count; index++) {
|
||
GetIndString(oldType, rTypeListStrings, index);
|
||
|
||
// if the mimetype already exists in our list, or the plugin is NOT hidden,
|
||
// don't bring up the dialog box
|
||
if (EqualString(ourType, oldType, true, true) && !fHiddenPlugin) {
|
||
failedToFind = false;
|
||
break; // Found a match, so bail out!
|
||
}
|
||
}
|
||
ReleaseResource(hTypeList);
|
||
}
|
||
FSClose(wResFile);
|
||
}
|
||
}
|
||
return(failedToFind);
|
||
}
|
||
|
||
|
||
|
||
//------------------------------------------------------------------------------------
|
||
// CPlugin::AskAndLoadURL:
|
||
//------------------------------------------------------------------------------------
|
||
void CPlugin::AskAndLoadURL()
|
||
{
|
||
char *pTheURL;
|
||
SInt32 dwLen;
|
||
Str255 ourType;
|
||
|
||
if (!m_bOffline) {
|
||
// Convert the mime-type C string to a Pascal string.
|
||
dwLen = strlen(fType);
|
||
if (dwLen > 255) { // don't blow out the Str255
|
||
dwLen = 255;
|
||
}
|
||
BlockMoveData(fType, &ourType[1], dwLen);
|
||
ourType[0] = dwLen;
|
||
|
||
// NOTE: We need to set the cursor because almost always we will have set it to the
|
||
// hand cursor before we get here.
|
||
Cursor qdArrow;
|
||
SetCursor(GetQDGlobalsArrow(&qdArrow));
|
||
|
||
// Now that we<77>ve queried the user about this mime type,
|
||
// add it to our list so we won<6F>t bug them again.
|
||
AddMimeTypeToList(ourType);
|
||
|
||
//
|
||
// If the user clicked "Get the Plug-in", either execute the
|
||
// JavaScript file-installation URL, or ask Netscape to open
|
||
// a new window with the page URL. The title of the window
|
||
// is arbitrary since it has nothing to do with the actual
|
||
// window title shown to the user (it<69>s only used internally).
|
||
//
|
||
NPN_PushPopupsEnabledState(fInstance, true);
|
||
|
||
if (fFileURL != NULL) {
|
||
(void) NPN_GetURL(fInstance, fFileURL, "_current");
|
||
} else if (fPageURL != NULL) {
|
||
NPN_GetURL(fInstance, fPageURL, "_blank");
|
||
} else {
|
||
pTheURL = MakeDefaultURL();
|
||
if (!m_bJavaScript) {
|
||
NPN_GetURL(fInstance, pTheURL, "_blank");
|
||
} else {
|
||
NPN_GetURL(fInstance, pTheURL, NULL);
|
||
}
|
||
NPN_MemFree(pTheURL);
|
||
}
|
||
|
||
NPN_PopPopupsEnabledState(fInstance);
|
||
|
||
fUserInstalledPlugin = true;
|
||
if (FocusDraw()) {
|
||
Draw(kUnhilited);
|
||
RestoreDraw();
|
||
}
|
||
}
|
||
}
|
||
|
||
void CPlugin::RefreshPluginPage()
|
||
{
|
||
(void) NPN_GetURL(fInstance, "javascript:navigator.plugins.refresh(true);", "_self");
|
||
}
|
||
|
||
void CPlugin::DrawString(const unsigned char* text, short width, short height, short centerX, Rect drawRect)
|
||
{
|
||
short length, textHeight, textWidth;
|
||
|
||
if(text == NULL)
|
||
return;
|
||
|
||
length = strlen((char*)text);
|
||
TextFont(20);
|
||
TextFace(underline);
|
||
TextMode(srcCopy);
|
||
TextSize(10);
|
||
|
||
FontInfo fontInfo;
|
||
GetFontInfo(&fontInfo);
|
||
|
||
textHeight = fontInfo.ascent + fontInfo.descent + fontInfo.leading;
|
||
textWidth = TextWidth(text, 0, length);
|
||
|
||
if (width > textWidth && height > textHeight + 32)
|
||
{
|
||
MoveTo(centerX - (textWidth >> 1), drawRect.bottom + textHeight);
|
||
DrawText(text, 0, length);
|
||
}
|
||
}
|
||
|
||
Boolean CPlugin::IsPluginHidden(int16 argc, char* argn[], char* argv[])
|
||
{
|
||
int i;
|
||
for(i=0; i<argc; i++)
|
||
{
|
||
if(!strcasecmp(argn[i], "HIDDEN"))
|
||
if(!strcasecmp(argv[i], "TRUE"))
|
||
return true;
|
||
}
|
||
return false;
|
||
}
|