Back to index

lightning-sunbird  0.9+nobinonly
npevents.cpp
Go to the documentation of this file.
00001 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
00002  *
00003  * ***** BEGIN LICENSE BLOCK *****
00004  * Version: MPL 1.1/GPL 2.0/LGPL 2.1
00005  *
00006  * The contents of this file are subject to the Mozilla Public License Version
00007  * 1.1 (the "License"); you may not use this file except in compliance with
00008  * the License. You may obtain a copy of the License at
00009  * http://www.mozilla.org/MPL/
00010  *
00011  * Software distributed under the License is distributed on an "AS IS" basis,
00012  * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
00013  * for the specific language governing rights and limitations under the
00014  * License.
00015  *
00016  * The Original Code is mozilla.org Code.
00017  *
00018  * The Initial Developer of the Original Code is
00019  * Netscape Communications Corporation.
00020  * Portions created by the Initial Developer are Copyright (C) 1998
00021  * the Initial Developer. All Rights Reserved.
00022  *
00023  * Contributor(s):
00024  *   Neil Hodgson <nhodgson@bigpond.net.au>
00025  *   Mark Hammond <MarkH@ActiveState.com>
00026  *
00027  * Alternatively, the contents of this file may be used under the terms of
00028  * either the GNU General Public License Version 2 or later (the "GPL"), or
00029  * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
00030  * in which case the provisions of the GPL or the LGPL are applicable instead
00031  * of those above. If you wish to allow use of your version of this file only
00032  * under the terms of either the GPL or the LGPL, and not to allow others to
00033  * use your version of this file under the terms of the MPL, indicate your
00034  * decision by deleting the provisions above and replace them with the notice
00035  * and other provisions required by the GPL or the LGPL. If you do not delete
00036  * the provisions above, a recipient may use your version of this file under
00037  * the terms of any one of the MPL, the GPL or the LGPL.
00038  *
00039  * ***** END LICENSE BLOCK ***** */
00040 
00041 // npevents.cxx
00042 // Demonstration plugin for Mozilla that handles events, focus and keystrokes.
00043 // See README.txt for more details.
00044 
00045 #include "nsplugin.h"
00046 #include "nsIServiceManager.h"
00047 #include "nsISupports.h"
00048 #include "nsIFactory.h"
00049 #include "nsIGenericFactory.h"
00050 #include "nsString.h"
00051 #include "nsIAllocator.h"
00052 
00053 #include "nsIEventsPluginInstance.h"
00054 
00055 #include <stdio.h> 
00056 #include <string.h> 
00057 
00058 #if defined (XP_WIN)
00059 
00060 #include <windows.h>
00061 
00062 #elif defined (XP_UNIX)
00063 
00064 #include <gdk/gdkprivate.h> 
00065 #include <gtk/gtk.h> 
00066 #include <gdk/gdkkeysyms.h> 
00067 #include <gtkmozbox.h> 
00068 
00069 #endif 
00070 
00071 #define EVENTSPLUGIN_DEBUG
00072 
00076 #define NS_EVENTSAMPLEPLUGIN_CID { 0xcb2ef72a, 0x856a, 0x4818, { 0x8e, 0x72, 0x34, 0x39, 0x39, 0x5e, 0x33, 0x5f } }
00077 
00078 #if defined(XP_UNIX)
00079 typedef struct _PlatformInstance {
00080        GtkWidget *moz_box;
00081        Display * display;
00082        uint32 x, y;
00083        uint32 width, height;
00084 }
00085 PlatformInstance;
00086 
00087 typedef GtkWidget* WinID;
00088 
00089 #endif // XP_UNIX
00090 
00091 #if defined(XP_WIN)
00092 typedef struct _PlatformInstance
00093 {
00094        WNDPROC fOldChildWindowProc; // The original WNDPROC of the edit control.
00095        WNDPROC fParentWindowProc; // The Mozilla WNDPROC for main (parent) window.
00096 } PlatformInstance;
00097 
00098 // Unique string for associating a pointer with our WNDPROC
00099 static const char* gInstanceLookupString = "instance->pdata";
00100 
00101 typedef HWND WinID;
00102 
00103 #endif // XP_WIN
00104 
00105 static NS_DEFINE_CID(kPluginManagerCID, NS_PLUGINMANAGER_CID);
00106 static NS_DEFINE_CID(kEventsPluginCID, NS_EVENTSAMPLEPLUGIN_CID);
00107 
00108 const char *kPluginName = "Events Sample Plug-in";
00109 const char *kPluginDescription = "Sample plugin that demonstrates events, focus and keystrokes.";
00110 #define PLUGIN_MIME_TYPE "application/x-events-sample-plugin"
00111 
00112 static const char* kMimeTypes[] = {
00113     PLUGIN_MIME_TYPE
00114 };
00115 
00116 static const char* kMimeDescriptions[] = {
00117     "Event Sample Plug-in"
00118 };
00119 
00120 static const char* kFileExtensions[] = {
00121     "smpev"
00122 };
00123 
00124 static const PRInt32 kNumMimeTypes = sizeof(kMimeTypes) / sizeof(*kMimeTypes);
00125 
00127 // EventsPluginInstance represents an instance of the EventsPlugin class.
00128 
00129 class EventsPluginInstance :
00130        public nsIPluginInstance,
00131        public nsIEventsSampleInstance {
00132 public:
00134     // for implementing a generic module
00135     static NS_METHOD
00136     Create(nsISupports* aOuter, REFNSIID aIID, void** aResult);
00137 
00138     static NS_METHOD
00139     RegisterSelf(nsIComponentManager* aCompMgr,
00140                  nsIFile* aPath,
00141                  const char* aRegistryLocation,
00142                  const char* aComponentType,
00143                  const nsModuleComponentInfo *info);
00144 
00145     static NS_METHOD
00146     UnregisterSelf(nsIComponentManager* aCompMgr,
00147                    nsIFile* aPath,
00148                    const char* aRegistryLocation,
00149                    const nsModuleComponentInfo *info);
00150 
00151 
00152        NS_DECL_ISUPPORTS
00153        NS_DECL_NSIEVENTSSAMPLEINSTANCE
00154 
00156        // from nsIEventHandler:
00157 
00158        NS_IMETHOD HandleEvent(nsPluginEvent* event, PRBool* handled);
00159 
00161        // from nsIPluginInstance:
00162 
00163        NS_IMETHOD Initialize(nsIPluginInstancePeer *peer);
00164 
00165        // Required backpointer to the peer.
00166        NS_IMETHOD GetPeer(nsIPluginInstancePeer **result);
00167 
00168        NS_IMETHOD Start(void);
00169 
00170        NS_IMETHOD Stop(void);
00171 
00172        NS_IMETHOD Destroy(void);
00173 
00174        NS_IMETHOD SetWindow(nsPluginWindow* window);
00175 
00176        NS_IMETHOD NewStream(nsIPluginStreamListener** listener);
00177 
00178        NS_IMETHOD Print(nsPluginPrint* platformPrint);
00179 
00180        NS_IMETHOD GetValue(nsPluginInstanceVariable variable, void *value);
00181 
00183        // EventsPluginInstance specific methods:
00184 
00185        EventsPluginInstance();
00186        virtual ~EventsPluginInstance();
00187 
00188        void PlatformNew(void);
00189        nsresult PlatformDestroy(void);
00190        void PlatformResetWindow();
00191        PRInt16 PlatformHandleEvent(nsPluginEvent* event);
00192        void PlatformResizeWindow(nsPluginWindow* window);
00193        nsresult PlatformCreateWindow(nsPluginWindow* window);
00194 
00195        void SetMode(nsPluginMode mode) { fMode = mode; }
00196 
00197 protected:
00199        // Implementation methods
00200        nsresult DoSetWindow(nsPluginWindow* window);
00201 
00202        // Data
00203        nsCOMPtr<nsIPluginInstancePeer> fPeer;
00204        nsPluginWindow *fWindow; // no nsCOMPtr as not an interface!
00205        nsPluginMode fMode;
00206        PlatformInstance fPlatform;
00207 
00208        WinID wMain; // The window created by Mozilla for us.
00209        WinID wChild; // The window we create as a child of the nsWindow.
00210 
00212        // Platform specific helpers
00213 #ifdef XP_WIN
00214        static LRESULT CALLBACK WndProcChild(HWND hWnd, UINT Msg, WPARAM wParam, LPARAM lParam);
00215 #endif
00216 };
00217 
00219 // EventsPluginStream represents the stream used by EvMozs
00220 // to receive data from the browser.
00221 
00222 class EventsPluginStreamListener : public nsIPluginStreamListener {
00223 public:
00224 
00225        NS_DECL_ISUPPORTS
00226 
00228        // from nsIPluginStreamListener:
00229 
00230        // Notify the observer that the URL has started to load.  This method is
00231        // called only once, at the beginning of a URL load.
00232        NS_IMETHOD OnStartBinding(nsIPluginStreamInfo* pluginInfo);
00233 
00234        // Notify the client that data is available in the input stream.  This method is
00235        // called whenver data is written into the input stream by the networking library.
00236        NS_IMETHOD OnDataAvailable(nsIPluginStreamInfo* pluginInfo,
00237                                   nsIInputStream* input,
00238                                   PRUint32 length);
00239 
00240        NS_IMETHOD OnFileAvailable(nsIPluginStreamInfo* pluginInfo, const char* fileName);
00241 
00242        // Notify the observer that the URL has finished loading.  This method is
00243        // called once when the networking library has finished processing the
00244        // URL transaction initiatied via the nsINetService::Open(...) call.
00245        NS_IMETHOD OnStopBinding(nsIPluginStreamInfo* pluginInfo, nsresult status);
00246 
00247        NS_IMETHOD OnNotify(const char* url, nsresult status);
00248 
00249        NS_IMETHOD GetStreamType(nsPluginStreamType *result);
00250 
00252        // EventsPluginStreamListener specific methods:
00253 
00254        EventsPluginStreamListener(EventsPluginInstance *inst_, const char* url);
00255        virtual ~EventsPluginStreamListener(void);
00256 
00257 protected:
00258        const char* fMessageName;
00259        EventsPluginInstance *inst;
00260 };
00261 
00262 // The module loader information.
00263 static const nsModuleComponentInfo gComponentInfo[] = {
00264     { "Events Sample Plugin",
00265       NS_EVENTSAMPLEPLUGIN_CID,
00266       NS_INLINE_PLUGIN_CONTRACTID_PREFIX PLUGIN_MIME_TYPE,
00267       EventsPluginInstance::Create,
00268       EventsPluginInstance::RegisterSelf,
00269       EventsPluginInstance::UnregisterSelf },
00270 };
00271 
00272 NS_IMPL_NSGETMODULE(EventsPlugin, gComponentInfo)
00273 
00274 
00275 
00276 // EventsPluginInstance static Methods
00278 
00279 NS_METHOD
00280 EventsPluginInstance::Create(nsISupports* aOuter, REFNSIID aIID, void** aResult)
00281 {
00282     NS_PRECONDITION(aOuter == nsnull, "no aggregation");
00283     if (aOuter)
00284         return NS_ERROR_NO_AGGREGATION;
00285 
00286     EventsPluginInstance* plugin = new EventsPluginInstance();
00287     if (! plugin)
00288         return NS_ERROR_OUT_OF_MEMORY;
00289 
00290     nsresult rv;
00291     NS_ADDREF(plugin);
00292     rv = plugin->QueryInterface(aIID, aResult);
00293     NS_RELEASE(plugin);
00294     return rv;
00295 }
00296 
00297 NS_METHOD
00298 EventsPluginInstance::RegisterSelf(nsIComponentManager* aCompMgr,
00299                                    nsIFile* aPath,
00300                                    const char* aRegistryLocation,
00301                                    const char* aComponentType,
00302                                    const nsModuleComponentInfo *info)
00303 {
00304     nsresult rv;
00305 
00306     nsIServiceManager *svcMgr;
00307     rv = aCompMgr->QueryInterface(NS_GET_IID(nsIServiceManager),
00308                                   NS_REINTERPRET_CAST(void**, &svcMgr));
00309     if (NS_FAILED(rv))
00310         return rv;
00311 
00312     nsIPluginManager* pm;
00313     rv = svcMgr->GetService(kPluginManagerCID,
00314                             NS_GET_IID(nsIPluginManager),
00315                             NS_REINTERPRET_CAST(void**, &pm));
00316     NS_RELEASE(svcMgr);
00317 
00318     if (NS_SUCCEEDED(rv)) {
00319         rv = pm->RegisterPlugin(kEventsPluginCID,
00320                                 kPluginName,
00321                                 kPluginDescription,
00322                                 kMimeTypes,
00323                                 kMimeDescriptions,
00324                                 kFileExtensions,
00325                                 kNumMimeTypes);
00326 
00327         NS_RELEASE(pm);
00328     }
00329 
00330     return rv;
00331 }
00332 
00333 
00334 NS_METHOD
00335 EventsPluginInstance::UnregisterSelf(nsIComponentManager* aCompMgr,
00336                                      nsIFile* aPath,
00337                                      const char* aRegistryLocation,
00338                                      const nsModuleComponentInfo *info)
00339 {
00340     nsresult rv;
00341 
00342     nsIServiceManager *svcMgr;
00343     rv = aCompMgr->QueryInterface(NS_GET_IID(nsIServiceManager),
00344                                   NS_REINTERPRET_CAST(void**, &svcMgr));
00345     if (NS_FAILED(rv))
00346         return rv;
00347 
00348     nsIPluginManager* pm;
00349     rv = svcMgr->GetService(kPluginManagerCID,
00350                             NS_GET_IID(nsIPluginManager),
00351                             NS_REINTERPRET_CAST(void**, &pm));
00352     NS_RELEASE(svcMgr);
00353 
00354     if (NS_SUCCEEDED(rv)) {
00355         rv = pm->UnregisterPlugin(kEventsPluginCID);
00356         NS_RELEASE(pm);
00357     }
00358 
00359     return rv;
00360 }
00361 
00363 // EventsPluginInstance Methods
00365 
00366 // These macros produce simple version of QueryInterface and AddRef.
00367 // See the nsISupports.h header file for details.
00368 
00369 NS_IMPL_ISUPPORTS2(EventsPluginInstance, nsIPluginInstance, nsIEventsSampleInstance)
00370 
00371 EventsPluginInstance::EventsPluginInstance() :
00372               fPeer(NULL), fWindow(NULL), fMode(nsPluginMode_Embedded)
00373 {
00374        wChild = 0;
00375 }
00376 
00377 EventsPluginInstance::~EventsPluginInstance(void) {
00378 }
00379 
00380 
00381 NS_METHOD EventsPluginInstance::Initialize(nsIPluginInstancePeer *peer) {
00382 #ifdef EVENTSPLUGIN_DEBUG
00383        printf("EventsPluginInstance::Initialize\n");
00384 #endif 
00385 
00386        NS_ASSERTION(peer != NULL, "null peer");
00387 
00388        fPeer = peer;
00389        nsCOMPtr<nsIPluginTagInfo> taginfo;
00390        const char* const* names = nsnull;
00391        const char* const* values = nsnull;
00392        PRUint16 count = 0;
00393        nsresult result;
00394 
00395        peer->AddRef();
00396        result = peer->GetMode(&fMode);
00397        if (NS_FAILED(result)) return result;
00398 
00399        taginfo = do_QueryInterface(peer, &result);
00400        if (NS_SUCCEEDED(result)) {
00401               taginfo->GetAttributes(count, names, values);
00402        }
00403 
00404        PlatformNew();       /* Call Platform-specific initializations */
00405        return NS_OK;
00406 }
00407 
00408 NS_METHOD EventsPluginInstance::GetPeer(nsIPluginInstancePeer* *result) {
00409 #ifdef EVENTSPLUGIN_DEBUG
00410        printf("EventsPluginInstance::GetPeer\n");
00411 #endif 
00412 
00413        *result = fPeer;
00414        NS_IF_ADDREF(*result);
00415        return NS_OK;
00416 }
00417 
00418 NS_METHOD EventsPluginInstance::Start(void) {
00419 #ifdef EVENTSPLUGIN_DEBUG
00420        printf("EventsPluginInstance::Start\n");
00421 #endif 
00422 
00423        return NS_OK;
00424 }
00425 
00426 NS_METHOD EventsPluginInstance::Stop(void) {
00427 #ifdef EVENTSPLUGIN_DEBUG
00428        printf("EventsPluginInstance::Stop\n");
00429 #endif 
00430 
00431        return NS_OK;
00432 }
00433 
00434 NS_METHOD EventsPluginInstance::Destroy(void) {
00435 #ifdef EVENTSPLUGIN_DEBUG
00436        printf("EventsPluginInstance::Destroy\n");
00437 #endif 
00438 
00439        PlatformDestroy(); // Perform platform specific cleanup
00440        return NS_OK;
00441 }
00442 
00443 /*+++++++++++++++++++++++++++++++++++++++++++++++++
00444  * NPP_SetWindow:
00445  * Sets the window in which a plug-in draws, and returns an error value. 
00446  * 
00447  * NPP_SetWindow informs the plug-in instance specified by instance of the
00448  * the window denoted by window in which the instance draws. This nsPluginWindow
00449  * pointer is valid for the life of the instance, or until NPP_SetWindow is called
00450  * again with a different value. Subsequent calls to NPP_SetWindow for a given
00451  * instance typically indicate that the window has been resized. If either window
00452  * or window->window are NULL, the plug-in must not perform any additional
00453  * graphics operations on the window and should free any resources associated
00454  * with the window. 
00455  +++++++++++++++++++++++++++++++++++++++++++++++++*/
00456 NS_METHOD EventsPluginInstance::SetWindow(nsPluginWindow* window) {
00457 #ifdef EVENTSPLUGIN_DEBUG
00458        printf("EventsPluginInstance::SetWindow\n");
00459 #endif 
00460 
00461        nsresult result;
00462        result = DoSetWindow(window);
00463        fWindow = window;
00464        return result;
00465 }
00466 
00467 nsresult EventsPluginInstance::DoSetWindow(nsPluginWindow* window) {
00468        /*
00469         * PLUGIN DEVELOPERS:
00470         *     Before setting window to point to the
00471         *     new window, you may wish to compare the new window
00472         *     info to the previous window (if any) to note window
00473         *     size changes, etc.
00474         */
00475         nsresult result = NS_OK;
00476        if ( fWindow != NULL ) {
00477               // If we already have a window, clean it up 
00478               // before working with the new window
00479               if ( window && window->window && wMain == (WinID)window->window ) {
00480                      /* The new window is the same as the old one. Exit now. */
00481                      PlatformResizeWindow(window);
00482                      return NS_OK;
00483               }
00484               // Otherwise, just reset the window ready for the new one.
00485               PlatformResetWindow();
00486        }
00487        else if ( (window == NULL) || ( window->window == NULL ) ) {
00488               /* We can just get out of here if there is no current
00489                * window and there is no new window to use. */ 
00490               return NS_OK;
00491        }
00492        if (window && window->window) {
00493               // Remember our main parent window.
00494               wMain = (WinID)window->window;
00495               // And create the child window.
00496               result = PlatformCreateWindow(window);
00497        }
00498        return result;
00499 }
00500 
00501 NS_METHOD EventsPluginInstance::NewStream(nsIPluginStreamListener** listener) {
00502 #ifdef EVENTSPLUGIN_DEBUG
00503        printf("EventsPluginInstance::NewStream\n");
00504 #endif 
00505 
00506        if (listener != NULL) {
00507               EventsPluginStreamListener* sl =
00508                   new EventsPluginStreamListener(this, "http://www.mozilla.org");
00509               if (!sl)
00510                      return NS_ERROR_UNEXPECTED;
00511               sl->AddRef();
00512               *listener = sl;
00513        }
00514 
00515        return NS_OK;
00516 }
00517 
00518 NS_METHOD EventsPluginInstance::Print(nsPluginPrint* printInfo) {
00519 #ifdef EVENTSPLUGIN_DEBUG
00520        printf("EventsPluginInstance::Print\n");
00521 #endif 
00522 
00523        if (printInfo == NULL)
00524               return NS_ERROR_FAILURE;
00525 
00526        if (printInfo->mode == nsPluginMode_Full) {
00527               /*
00528                * PLUGIN DEVELOPERS:
00529                *     If your plugin would like to take over
00530                *     printing completely when it is in full-screen mode,
00531                *     set printInfo->pluginPrinted to TRUE and print your
00532                *     plugin as you see fit.  If your plugin wants Netscape
00533                *     to handle printing in this case, set
00534                *     printInfo->pluginPrinted to FALSE (the default) and
00535                *     do nothing.  If you do want to handle printing
00536                *     yourself, printOne is true if the print button
00537                *     (as opposed to the print menu) was clicked.
00538                *     On the Macintosh, platformPrint is a THPrint; on
00539                *     Windows, platformPrint is a structure
00540                *     (defined in npapi.h) containing the printer name, port,
00541                *     etc.
00542                */
00543 
00544               /* Do the default*/
00545               printInfo->print.fullPrint.pluginPrinted = PR_FALSE;
00546        } else {      /* If not fullscreen, we must be embedded */
00547               /*
00548                * PLUGIN DEVELOPERS:
00549                *     If your plugin is embedded, or is full-screen
00550                *     but you returned false in pluginPrinted above, NPP_Print
00551                *     will be called with mode == nsPluginMode_Embedded.  The nsPluginWindow
00552                *     in the printInfo gives the location and dimensions of
00553                *     the embedded plugin on the printed page.  On the
00554                *     Macintosh, platformPrint is the printer port; on
00555                *     Windows, platformPrint is the handle to the printing
00556                *     device context.
00557                */
00558        }
00559        return NS_OK;
00560 }
00561 
00562 /*+++++++++++++++++++++++++++++++++++++++++++++++++
00563  * NPP_HandleEvent:
00564  * Mac-only, but stub must be present for Windows
00565  * Delivers a platform-specific event to the instance. 
00566  * 
00567  * On the Macintosh, event is a pointer to a standard Macintosh EventRecord.
00568  * All standard event types are passed to the instance as appropriate. In general,
00569  * return TRUE if you handle the event and FALSE if you ignore the event. 
00570  +++++++++++++++++++++++++++++++++++++++++++++++++*/
00571 
00572 NS_METHOD EventsPluginInstance::HandleEvent(nsPluginEvent* event, PRBool* handled) {
00573 #ifdef EVENTSPLUGIN_DEBUG
00574        printf("EventsPluginInstance::HandleEvent\n");
00575 #endif 
00576 
00577        *handled = (PRBool)PlatformHandleEvent(event);
00578        return NS_OK;
00579 }
00580 
00581 NS_METHOD EventsPluginInstance::GetValue(nsPluginInstanceVariable /*variable*/, void * /*value*/) {
00582 #ifdef EVENTSPLUGIN_DEBUG
00583        printf("EventsPluginInstance::GetValue\n");
00584 #endif 
00585 
00586        return NS_ERROR_FAILURE;
00587 }
00588 
00590 // EventsPluginStreamListener Methods
00592 
00593 EventsPluginStreamListener::EventsPluginStreamListener(EventsPluginInstance* inst_,
00594         const char* msgName)
00595               : fMessageName(msgName), inst(inst_) {
00596 #ifdef EVENTSPLUGIN_DEBUG
00597        printf("EventsPluginStreamListener: EventsPluginStreamListener for %s\n", fMessageName);
00598 #endif
00599 }
00600 
00601 EventsPluginStreamListener::~EventsPluginStreamListener(void) {
00602 }
00603 
00604 // This macro produces a simple version of QueryInterface, AddRef and Release.
00605 // See the nsISupports.h header file for details.
00606 
00607 NS_IMPL_ISUPPORTS1(EventsPluginStreamListener, nsIPluginStreamListener)
00608 
00609 NS_METHOD EventsPluginStreamListener::OnStartBinding(nsIPluginStreamInfo * /*pluginInfo*/) {
00610 #ifdef EVENTSPLUGIN_DEBUG
00611        printf("EventsPluginStreamListener::OnStartBinding\n");
00612        printf("EventsPluginStreamListener: Opening plugin stream for %s\n", fMessageName);
00613 #endif 
00614        return NS_OK;
00615 }
00616 
00617 NS_METHOD EventsPluginStreamListener::OnDataAvailable(
00618     nsIPluginStreamInfo * /*pluginInfo*/,
00619     nsIInputStream* input,
00620     PRUint32 length) {
00621 
00622 #ifdef EVENTSPLUGIN_DEBUG
00623        printf("EventsPluginStreamListener::OnDataAvailable\n");
00624 #endif 
00625 
00626        char* buffer = new char[length];
00627        if (buffer) {
00628               PRUint32 amountRead = 0;
00629               nsresult rslt = input->Read(buffer, length, &amountRead);
00630               if (rslt == NS_OK) {
00631                      char msg[256];
00632                      sprintf(msg, "### Received %d bytes for %s\n", length, fMessageName);
00633               }
00634               delete buffer;
00635        }
00636        return NS_OK;
00637 }
00638 
00639 NS_METHOD EventsPluginStreamListener::OnFileAvailable(
00640     nsIPluginStreamInfo * /*pluginInfo*/,
00641     const char* fileName) {
00642 
00643 #ifdef EVENTSPLUGIN_DEBUG
00644        printf("EventsPluginStreamListener::OnFileAvailable\n");
00645 #endif 
00646 
00647        char msg[256];
00648        sprintf(msg, "### File available for %s: %s\n", fMessageName, fileName);
00649        return NS_OK;
00650 }
00651 
00652 NS_METHOD EventsPluginStreamListener::OnStopBinding(
00653     nsIPluginStreamInfo * /*pluginInfo*/,
00654     nsresult /*status*/) {
00655 
00656 #ifdef EVENTSPLUGIN_DEBUG
00657        printf("EventsPluginStreamListener::OnStopBinding\n");
00658 #endif 
00659 
00660        char msg[256];
00661        sprintf(msg, "### Closing plugin stream for %s\n", fMessageName);
00662        return NS_OK;
00663 }
00664 
00665 NS_METHOD EventsPluginStreamListener::OnNotify(const char * /*url*/, nsresult /*status*/) {
00666 #ifdef EVENTSPLUGIN_DEBUG
00667        printf("EventsPluginStreamListener::OnNotify\n");
00668 #endif 
00669 
00670        return NS_OK;
00671 }
00672 
00673 NS_METHOD EventsPluginStreamListener::GetStreamType(nsPluginStreamType *result) {
00674 #ifdef EVENTSPLUGIN_DEBUG
00675        printf("EventsPluginStreamListener::GetStreamType\n");
00676 #endif 
00677 
00678        *result = nsPluginStreamType_Normal;
00679        return NS_OK;
00680 }
00681 
00683 // Platform-Specific Implemenations
00684 
00685 // UNIX Implementations
00686 
00687 #ifdef XP_UNIX
00688 
00689 void EventsPluginInstance::PlatformNew(void) {
00690        fPlatform.moz_box = 0;
00691 }
00692 
00693 nsresult EventsPluginInstance::PlatformDestroy(void) {
00694        // the mozbox will be destroyed by the native destruction of the
00695        // widget's parent.
00696        return NS_OK;
00697 }
00698 
00699 void EventsPluginInstance::PlatformResetWindow() {
00700 #ifdef EVENTSPLUGIN_DEBUG
00701        printf("EventsPluginInstance::PlatformResetWindow\n");
00702 #endif
00703        fPlatform.moz_box = 0;
00704 }
00705 
00706 nsresult EventsPluginInstance::PlatformCreateWindow(nsPluginWindow* window) {
00707 #ifdef EVENTSPLUGIN_DEBUG
00708        printf("EventsPluginInstance::PlatformCreateWindow %lx\n", (long)window);
00709 #endif 
00710 
00711        Window x_window = (Window)window->window;
00712        GdkWindow *gdk_window = (GdkWindow *)gdk_xid_table_lookup(x_window);
00713        if (!gdk_window) {
00714               fprintf(stderr, "NO WINDOW!!!\n");
00715               return NS_ERROR_FAILURE;
00716        }
00717        fPlatform.moz_box = gtk_mozbox_new(gdk_window);
00718 
00719        wChild = gtk_entry_new();
00720        gtk_container_add(GTK_CONTAINER(fPlatform.moz_box), wChild);
00721        gtk_widget_show_all(fPlatform.moz_box);
00722        return NS_OK;
00723 }
00724 
00725 void EventsPluginInstance::PlatformResizeWindow(nsPluginWindow* window) {
00726        NS_PRECONDITION(wChild, "Have no wChild!");
00727 #ifdef EVENTSPLUGIN_DEBUG
00728        printf("EventsPluginInstance::PlatformResizeWindow to size (%d,%d)\n", window->width, window->height);
00729 #endif
00730        // Mozilla has already sized the mozbox - we just need to handle the child.
00731        gtk_widget_set_usize(wChild, window->width, window->height);
00732 }
00733 
00734 int16 EventsPluginInstance::PlatformHandleEvent(nsPluginEvent * /*event*/) {
00735        /* UNIX Plugins do not use HandleEvent */
00736        return 0;
00737 }
00738 
00739 /* attribute string text; */
00740 NS_IMETHODIMP EventsPluginInstance::GetVal(char * *aText) {
00741 #ifdef EVENTSPLUGIN_DEBUG
00742        printf("EventsPluginInstance::GetVal\n");
00743 #endif 
00744        char *text = gtk_entry_get_text(GTK_ENTRY(wChild));
00745        *aText = reinterpret_cast<char*>(nsAllocator::Clone(text, strlen(text) + 1));
00746        return (*aText) ? NS_OK : NS_ERROR_OUT_OF_MEMORY;
00747 }
00748 
00749 NS_IMETHODIMP EventsPluginInstance::SetVal(const char * aText) {
00750 #ifdef EVENTSPLUGIN_DEBUG
00751        printf("EventsPluginInstance::SetVal\n");
00752 #endif 
00753        gtk_entry_set_text(GTK_ENTRY(wChild), aText);
00754        return NS_OK;
00755 }
00756 #endif     /* XP_UNIX */
00757 
00758 // Windows Implementations
00759 
00760 #if defined(XP_WIN)
00761 
00762 void EventsPluginInstance::PlatformNew(void) {
00763        // Nothing to do!
00764 }
00765 
00766 nsresult EventsPluginInstance::PlatformDestroy(void) {
00767        wChild = 0;
00768        return NS_OK;
00769 }
00770 
00771 nsresult EventsPluginInstance::PlatformCreateWindow(nsPluginWindow* window) {
00772        // Remember parent wndproc.
00773        fPlatform.fParentWindowProc = (WNDPROC)::GetWindowLong(wMain, GWL_WNDPROC);
00774        NS_ABORT_IF_FALSE(fPlatform.fParentWindowProc!=NULL, "Couldn't get the parent WNDPROC");
00775 
00776        // Create the child window that fills our nsWindow 
00777        RECT rc;
00778        ::GetWindowRect(wMain, &rc);
00779 
00780        wChild = ::CreateWindow("Edit", // class - standard Windows edit control.
00781                                                  "", // title
00782                                                  WS_CHILD | WS_VISIBLE | ES_MULTILINE | ES_AUTOVSCROLL, // style
00783                                                  0, 0, rc.right-rc.left, rc.bottom-rc.top,
00784                                                  wMain, // parent
00785                                                  (HMENU)1111, // window ID
00786                                                  0, // instance
00787                                                  NULL); //creation data.
00788        NS_ABORT_IF_FALSE(wChild != NULL, "Failed to create the child window!");
00789        if (!wChild)
00790               return NS_ERROR_FAILURE;
00791        // Stash away our "this" pointer so our WNDPROC can talk to us.
00792        ::SetProp(wChild, gInstanceLookupString, (HANDLE)this);
00793        fPlatform.fOldChildWindowProc =
00794               (WNDPROC)::SetWindowLong( wChild,
00795                                                         GWL_WNDPROC, 
00796                                                         (LONG)EventsPluginInstance::WndProcChild);
00797        return NS_OK;
00798 }
00799 
00800 int16 EventsPluginInstance::PlatformHandleEvent(nsPluginEvent * /*event*/) {
00801        return NS_OK;
00802 }
00803 
00804 void EventsPluginInstance::PlatformResetWindow() {
00805 #ifdef EVENTSPLUGIN_DEBUG
00806        printf("EventsPluginInstance::PlatformResetWindow\n");
00807 #endif
00808        fPlatform.fParentWindowProc = NULL;
00809        ::SetWindowLong(wChild, GWL_WNDPROC, (LONG)fPlatform.fOldChildWindowProc);
00810        fPlatform.fOldChildWindowProc = NULL;
00811        wChild = NULL;
00812        wMain = NULL;
00813 }
00814 
00815 void EventsPluginInstance::PlatformResizeWindow(nsPluginWindow* window) {
00816 #ifdef EVENTSPLUGIN_DEBUG
00817        printf("EventsPluginInstance::PlatformResizeWindow with new size (%d,%d)\n", window->width, window->height);
00818 #endif
00819        RECT rc;
00820        NS_PRECONDITION(wMain != nsnull, "Must have a valid wMain to resize");
00821        ::GetClientRect(wMain, &rc);
00822        ::SetWindowPos(wChild, 0, rc.left, rc.top,
00823                       rc.right - rc.left, rc.bottom - rc.top, SWP_NOZORDER | SWP_NOACTIVATE);
00824 }
00825 
00826 /* attribute string text; */
00827 NS_IMETHODIMP EventsPluginInstance::GetVal(char * *aText) {
00828 #ifdef EVENTSPLUGIN_DEBUG
00829        printf("EventsPluginInstance::GetVal\n");
00830 #endif 
00831        static char *empty = "";
00832        char *value = empty;
00833        char buffer[256];
00834        if (wChild) {
00835               GetWindowText(wChild, buffer, sizeof(buffer)/sizeof(buffer[0]));
00836               value = buffer;
00837        }
00838        *aText = reinterpret_cast<char*>(nsAllocator::Clone(value, strlen(value) + 1));
00839        return (*aText) ? NS_OK : NS_ERROR_OUT_OF_MEMORY;
00840 }
00841 
00842 NS_IMETHODIMP EventsPluginInstance::SetVal(const char * aText) {
00843 #ifdef EVENTSPLUGIN_DEBUG
00844        printf("EventsPluginInstance::SetVal\n");
00845 #endif 
00846        NS_ABORT_IF_FALSE(wChild != 0, "Don't have a window!");
00847        SetWindowText(wChild, aText);
00848        return NS_OK;
00849 }
00850 
00851 // This is the WndProc for our child window (the edit control)
00852 LRESULT CALLBACK EventsPluginInstance::WndProcChild(HWND hWnd, UINT Msg, WPARAM wParam, LPARAM lParam) {
00853        EventsPluginInstance* inst = (EventsPluginInstance*) GetProp(hWnd, gInstanceLookupString);
00854        NS_ABORT_IF_FALSE(inst, "Could not get the inst from the Window!!");
00855        switch (Msg) {
00856        // NOTE: We DONT pass on DBLCLK messages, as both Scintilla and
00857        // Mozilla have their own special logic, and they step on each other.
00858        // (causing our child to see a double-click as a triple-click)
00859               case WM_KEYDOWN:
00860               case WM_SYSKEYDOWN:
00861               case WM_KEYUP:
00862               case WM_SYSKEYUP:
00863               case WM_CHAR:
00864               case WM_SYSCHAR:
00865               case WM_LBUTTONDOWN:
00866               case WM_LBUTTONUP:
00867               case WM_MBUTTONDOWN:
00868               case WM_MBUTTONUP:
00869               case WM_RBUTTONDOWN:
00870               case WM_RBUTTONUP:
00871               case WM_MOUSEMOVE:
00872                      // pretend the message happened in our parent.
00873                      return ::CallWindowProc(inst->fPlatform.fParentWindowProc, (HWND)inst->wMain, Msg, wParam, lParam);
00874               default:
00875                      // let our child's default handle it.
00876                      return ::CallWindowProc(inst->fPlatform.fOldChildWindowProc, hWnd, Msg, wParam, lParam);
00877        }
00878        /* not reached */
00879        NS_ABORT_IF_FALSE(0, "not reached!");
00880 }
00881 
00882 
00883 #endif     /* XP_WIN */