Back to index

lightning-sunbird  0.9+nobinonly
plugin.cpp
Go to the documentation of this file.
00001 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
00002 /* ***** BEGIN LICENSE BLOCK *****
00003  * Version: MPL 1.1/GPL 2.0/LGPL 2.1
00004  *
00005  * The contents of this file are subject to the Mozilla Public License Version
00006  * 1.1 (the "License"); you may not use this file except in compliance with
00007  * the License. You may obtain a copy of the License at
00008  * http://www.mozilla.org/MPL/
00009  *
00010  * Software distributed under the License is distributed on an "AS IS" basis,
00011  * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
00012  * for the specific language governing rights and limitations under the
00013  * License.
00014  *
00015  * The Original Code is Mozilla Communicator client code.
00016  *
00017  * The Initial Developer of the Original Code is
00018  * Netscape Communications Corporation.
00019  * Portions created by the Initial Developer are Copyright (C) 1998
00020  * the Initial Developer. All Rights Reserved.
00021  *
00022  * Contributor(s):
00023  *
00024  * Alternatively, the contents of this file may be used under the terms of
00025  * either the GNU General Public License Version 2 or later (the "GPL"), or
00026  * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
00027  * in which case the provisions of the GPL or the LGPL are applicable instead
00028  * of those above. If you wish to allow use of your version of this file only
00029  * under the terms of either the GPL or the LGPL, and not to allow others to
00030  * use your version of this file under the terms of the MPL, indicate your
00031  * decision by deleting the provisions above and replace them with the notice
00032  * and other provisions required by the GPL or the LGPL. If you do not delete
00033  * the provisions above, a recipient may use your version of this file under
00034  * the terms of any one of the MPL, the GPL or the LGPL.
00035  *
00036  * ***** END LICENSE BLOCK ***** */
00037 
00038 #include <windows.h>
00039 #include <windowsx.h>
00040 #include <assert.h>
00041 
00042 #include "resource.h"
00043 
00044 #include "plugin.h"
00045 #include "utils.h"
00046 #include "dialogs.h"
00047 #include "dbg.h"
00048 #include "nsIServiceManager.h"
00049 #include "nsIPref.h"
00050 
00051 nsIServiceManager * gServiceManager = NULL;
00052 
00053 static char szNullPluginWindowClassName[] = CLASS_NULL_PLUGIN;
00054 
00055 static LRESULT CALLBACK NP_LOADDS PluginWndProc(HWND, UINT, WPARAM, LPARAM);
00056 
00057 static char szDefaultPluginFinderURL[] = DEFAULT_PLUGINFINDER_URL;
00058 static char szPageUrlForJavaScript[] = PAGE_URL_FOR_JAVASCRIPT;
00059 static char szPageUrlForJVM[] = JVM_SMARTUPDATE_URL;
00060 //static char szPluginFinderCommandFormatString[] = PLUGINFINDER_COMMAND;
00061 static char szPluginFinderCommandBeginning[] = PLUGINFINDER_COMMAND_BEGINNING;
00062 static char szPluginFinderCommandEnd[] = PLUGINFINDER_COMMAND_END;
00063 
00064 BOOL RegisterNullPluginWindowClass()
00065 {
00066   assert(hInst != NULL);
00067 
00068   WNDCLASS wc;
00069 
00070   memset(&wc, 0, sizeof(wc));
00071 
00072   wc.lpfnWndProc   = (WNDPROC)PluginWndProc;
00073   wc.cbWndExtra    = sizeof(DWORD);
00074   wc.hInstance     = hInst;
00075   wc.hIcon         = LoadIcon(hInst, IDI_APPLICATION);
00076   wc.hCursor       = NULL;
00077   wc.hbrBackground = HBRUSH(COLOR_WINDOW + 1);
00078   wc.lpszClassName = szNullPluginWindowClassName;
00079 
00080   ATOM aRet = RegisterClass(&wc);
00081   return (aRet != NULL);
00082 }
00083 
00084 void UnregisterNullPluginWindowClass()
00085 {
00086   assert(hInst != NULL);
00087   UnregisterClass(szNullPluginWindowClassName, hInst);
00088 }
00089 
00090 /*********************************************/
00091 /*                                           */
00092 /*       CPlugin class implementation        */
00093 /*                                           */
00094 /*********************************************/
00095 
00096 CPlugin::CPlugin(HINSTANCE hInst, 
00097                  NPP pNPInstance, 
00098                  WORD wMode, 
00099                  NPMIMEType pluginType, 
00100                  LPSTR szPageURL, 
00101                  LPSTR szFileURL, 
00102                  LPSTR szFileExtension,
00103                  BOOL bHidden) :
00104   m_pNPInstance(pNPInstance),
00105   m_wMode(wMode),
00106   m_hInst(hInst),
00107   m_hWnd(NULL),
00108   m_hWndParent(NULL),
00109   m_hWndDialog(NULL),
00110   m_hIcon(NULL),
00111   m_pNPMIMEType(NULL),
00112   m_szPageURL(NULL),
00113   m_szFileURL(NULL),
00114   m_szFileExtension(NULL),
00115   m_bOnline(TRUE),
00116   m_bJava(TRUE),
00117   m_bJavaScript(TRUE),
00118   m_bSmartUpdate(TRUE),
00119   m_szURLString(NULL),
00120   m_szCommandMessage(NULL),
00121   m_bWaitingStreamFromPFS(FALSE),
00122   m_PFSStream(NULL),
00123   m_bHidden(bHidden)
00124 {
00125   dbgOut1("CPlugin::CPlugin()");
00126   assert(m_hInst != NULL);
00127   assert(m_pNPInstance != NULL);
00128 
00129   if(pluginType && *pluginType)
00130   {
00131     m_pNPMIMEType = (NPMIMEType)new char[lstrlen((LPSTR)pluginType) + 1];
00132     if(m_pNPMIMEType != NULL)
00133       lstrcpy((LPSTR)m_pNPMIMEType, pluginType);
00134   }
00135 
00136   if(szPageURL && *szPageURL)
00137   {
00138     m_szPageURL = new char[lstrlen(szPageURL) + 1];
00139     if(m_szPageURL != NULL)
00140       lstrcpy(m_szPageURL, szPageURL);
00141   }
00142   
00143   if(szFileURL && *szFileURL)
00144   {
00145     m_szFileURL = new char[lstrlen(szFileURL) + 1];
00146     if(m_szFileURL != NULL)
00147       lstrcpy(m_szFileURL, szFileURL);
00148   }
00149 
00150   if(szFileExtension && *szFileExtension)
00151   {
00152     m_szFileExtension = new char[lstrlen(szFileExtension) + 1];
00153     if(m_szFileExtension != NULL)
00154       lstrcpy(m_szFileExtension, szFileExtension);
00155   }
00156 
00157   m_hIcon = LoadIcon(m_hInst, MAKEINTRESOURCE(IDI_PLUGICON));
00158 
00159   char szString[1024] = {'\0'};
00160   LoadString(m_hInst, IDS_CLICK_TO_GET, szString, sizeof(szString));
00161   if(*szString)
00162   {
00163     m_szCommandMessage = new char[lstrlen(szString) + 1];
00164     if(m_szCommandMessage != NULL)
00165       lstrcpy(m_szCommandMessage, szString);
00166   }
00167 }
00168 
00169 CPlugin::~CPlugin()
00170 {
00171   dbgOut1("CPlugin::~CPlugin()");
00172 
00173   if(m_pNPMIMEType != NULL)
00174   {
00175     delete [] m_pNPMIMEType;
00176     m_pNPMIMEType = NULL;
00177   }
00178 
00179   if(m_szPageURL != NULL)
00180   {
00181     delete [] m_szPageURL;
00182     m_szPageURL = NULL;
00183   }
00184 
00185   if(m_szFileURL != NULL)
00186   {
00187     delete [] m_szFileURL;
00188     m_szFileURL = NULL;
00189   }
00190 
00191   if(m_szFileExtension != NULL)
00192   {
00193     delete [] m_szFileExtension;
00194     m_szFileExtension = NULL;
00195   }
00196 
00197   if(m_szURLString != NULL)
00198   {
00199     delete [] m_szURLString;
00200     m_szURLString = NULL;
00201   }
00202 
00203   if(m_hIcon != NULL)
00204   {
00205     DestroyIcon(m_hIcon);
00206     m_hIcon = NULL;
00207   }
00208 
00209   if(m_szCommandMessage != NULL)
00210   {
00211     delete [] m_szCommandMessage;
00212     m_szCommandMessage = NULL;
00213   }
00214 }
00215 
00216 BOOL CPlugin::init(HWND hWndParent)
00217 {
00218   dbgOut1("CPlugin::init()");
00219 
00220   nsISupports * sm = NULL;
00221   nsIPref * nsPrefService = NULL;
00222   PRBool bSendUrls = PR_FALSE; // default to false if problem getting pref
00223 
00224   // note that Mozilla will add reference, so do not forget to release
00225   NPN_GetValue(NULL, NPNVserviceManager, &sm);
00226 
00227   // do a QI on the service manager we get back to ensure it's the one we are expecting
00228   if(sm) {
00229     sm->QueryInterface(NS_GET_IID(nsIServiceManager), (void**)&gServiceManager);
00230     NS_RELEASE(sm);
00231   }
00232   
00233   if (gServiceManager) {
00234     // get service using its contract id and use it to allocate the memory
00235     gServiceManager->GetServiceByContractID(NS_PREF_CONTRACTID, NS_GET_IID(nsIPref), (void **)&nsPrefService);
00236     if(nsPrefService) {      
00237       nsPrefService->GetBoolPref("application.use_ns_plugin_finder", &bSendUrls);
00238       NS_RELEASE(nsPrefService);
00239     }
00240   }
00241   m_bSmartUpdate = bSendUrls;
00242 
00243   if(!m_bHidden)
00244   {
00245     assert(IsWindow(hWndParent));
00246 
00247     if(IsWindow(hWndParent))
00248       m_hWndParent = hWndParent;
00249 
00250     RECT rcParent;
00251     GetClientRect(m_hWndParent, &rcParent);
00252 
00253     CreateWindow(szNullPluginWindowClassName, 
00254                  "NULL Plugin", 
00255                  WS_CHILD,
00256                  0,0, rcParent.right, rcParent.bottom,
00257                  m_hWndParent,
00258                  (HMENU)NULL,
00259                  m_hInst,
00260                  (LPVOID)this);
00261 
00262     assert(m_hWnd != NULL);
00263     if((m_hWnd == NULL) || (!IsWindow(m_hWnd)))
00264       return FALSE;
00265 
00266     UpdateWindow(m_hWnd);
00267     ShowWindow(m_hWnd, SW_SHOW);
00268   }
00269 
00270   if(IsNewMimeType((LPSTR)m_pNPMIMEType) || m_bHidden)
00271     showGetPluginDialog();
00272 
00273   return TRUE;
00274 }
00275 
00276 void CPlugin::shut()
00277 {
00278   dbgOut1("CPlugin::shut()");
00279 
00280   if(m_hWndDialog != NULL)
00281   {
00282     DestroyWindow(m_hWndDialog);
00283     m_hWndDialog = NULL;
00284   }
00285 
00286   if(m_hWnd != NULL)
00287   {
00288     DestroyWindow(m_hWnd);
00289     m_hWnd = NULL;
00290   }
00291 
00292   // we should release the service manager
00293   NS_IF_RELEASE(gServiceManager);
00294   gServiceManager = NULL;
00295 }
00296 
00297 HWND CPlugin::getWindow()
00298 {
00299   return m_hWnd;
00300 }
00301 
00302 BOOL CPlugin::useDefaultURL_P()
00303 {
00304   if((m_szPageURL == NULL) && (m_szFileURL == NULL))
00305     return TRUE;
00306   else
00307     return FALSE;
00308 }
00309 
00310 BOOL CPlugin::doSmartUpdate_P()
00311 {
00312   // due to current JavaScript problems never do it smart for now 5.1.98
00313   return FALSE;
00314 
00315   if(m_bOnline && m_bJava && m_bJavaScript && m_bSmartUpdate && useDefaultURL_P())
00316     return TRUE;
00317   else
00318     return FALSE;
00319 }
00320 
00321 LPSTR CPlugin::createURLString()
00322 {
00323   if(m_szURLString != NULL)
00324   {
00325     delete [] m_szURLString;
00326     m_szURLString = NULL;
00327   }
00328 
00329   // check if there is file URL first
00330   if(!m_bSmartUpdate && m_szFileURL != NULL)
00331   {
00332     m_szURLString = new char[lstrlen(m_szFileURL) + 1];
00333     if(m_szURLString == NULL)
00334       return NULL;
00335     lstrcpy(m_szURLString, m_szFileURL);
00336     return m_szURLString;
00337   }
00338   
00339   // if not get the page URL
00340   char * szAddress = NULL;
00341   char *urlToOpen = NULL;
00342   char contentTypeIsJava = 0;
00343 
00344   if (NULL != m_pNPMIMEType) {
00345     contentTypeIsJava = (0 == strcmp("application/x-java-vm",
00346                                  m_pNPMIMEType)) ? 1 : 0;
00347   }
00348   
00349   if(!m_bSmartUpdate && m_szPageURL != NULL && !contentTypeIsJava)
00350   {
00351     szAddress = new char[lstrlen(m_szPageURL) + 1];
00352     if(szAddress == NULL)
00353       return NULL;
00354     lstrcpy(szAddress, m_szPageURL);
00355 
00356     m_szURLString = new char[lstrlen(szAddress) + 1 + lstrlen((LPSTR)m_pNPMIMEType) + 1];
00357 
00358     if(m_szURLString == NULL)
00359       return NULL;
00360 
00361     // Append the MIME type to the URL
00362     wsprintf(m_szURLString, "%s?%s", szAddress, (LPSTR)m_pNPMIMEType);
00363   }
00364   else // default
00365   {
00366     if(!m_bSmartUpdate)
00367     {
00368       urlToOpen = szDefaultPluginFinderURL;
00369       
00370       if (contentTypeIsJava) {
00371         urlToOpen = szPageUrlForJVM;
00372       }
00373 
00374       szAddress = new char[lstrlen(urlToOpen) + 1];
00375       if(szAddress == NULL)
00376         return NULL;
00377       lstrcpy(szAddress, urlToOpen);
00378 
00379       m_szURLString = new char[lstrlen(szAddress) + 10 + 
00380                                lstrlen((LPSTR)m_pNPMIMEType) + 1];
00381 
00382       if(m_szURLString == NULL)
00383         return NULL;
00384 
00385       // Append the MIME type to the URL
00386       wsprintf(m_szURLString, "%s?mimetype=%s", 
00387                szAddress, (LPSTR)m_pNPMIMEType);
00388     }
00389     else
00390     {
00391       urlToOpen = szPageUrlForJavaScript;
00392 
00393       if (contentTypeIsJava) {
00394         urlToOpen = szPageUrlForJVM;
00395       }
00396 
00397       // wsprintf doesn't like null pointers on NT or 98, so
00398       // change any null string pointers to null strings
00399       if (!m_szPageURL) {
00400         m_szPageURL = new char[1];
00401         m_szPageURL[0] = '\0';
00402       }
00403 
00404       if (!m_szFileURL) {
00405         m_szFileURL = new char[1];
00406         m_szFileURL[0] = '\0';
00407       }
00408 
00409       m_szURLString = new char[lstrlen(szPluginFinderCommandBeginning) + lstrlen(urlToOpen) + 10 + 
00410                                lstrlen((LPSTR)m_pNPMIMEType) + 13 +
00411                                lstrlen((LPSTR)m_szPageURL) + 11 + 
00412                                lstrlen((LPSTR)m_szFileURL) +
00413                                lstrlen(szPluginFinderCommandEnd) + 1];
00414       wsprintf(m_szURLString, "%s%s?mimetype=%s&pluginspage=%s&pluginurl=%s%s",
00415                szPluginFinderCommandBeginning, urlToOpen, 
00416                (LPSTR)m_pNPMIMEType, m_szPageURL, m_szFileURL, szPluginFinderCommandEnd);
00417 
00418     }
00419   }
00420 
00421   if(szAddress != NULL)
00422     delete [] szAddress;
00423 
00424   return m_szURLString;
00425 }
00426 
00427 void CPlugin::getPluginRegular()
00428 {
00429   assert(m_bOnline);
00430 
00431   char * szURL = createURLString();
00432 
00433   assert(szURL != NULL);
00434   if(szURL == NULL)
00435     return;
00436 
00437   dbgOut3("CPlugin::getPluginRegular(), %#08x '%s'", m_pNPInstance, szURL);
00438 
00439   NPN_GetURL(m_pNPInstance, szURL, NULL);
00440   m_bWaitingStreamFromPFS = TRUE;
00441 }
00442 
00443 void CPlugin::getPluginSmart()
00444 {
00445 /*
00446   static char szJSString[2048];
00447 
00448   wsprintf(szJSString, 
00449            szPluginFinderCommandFormatString, 
00450            szDefaultPluginFinderURL, 
00451            m_pNPMIMEType, 
00452            (m_szFileExtension != NULL) ? m_szFileExtension : szDefaultFileExt);
00453 
00454   dbgOut3("%#08x '%s'", m_pNPInstance, szJSString);
00455 
00456   assert(*szJSString);
00457 
00458   NPN_GetURL(m_pNPInstance, szJSString, "smartupdate_plugin_finder");
00459 */
00460 }
00461 
00462 void CPlugin::showGetPluginDialog()
00463 {
00464   assert(m_pNPMIMEType != NULL);
00465   if(m_pNPMIMEType == NULL)
00466     return;
00467 
00468   // Get environment
00469   BOOL bOffline = FALSE;
00470 
00471   NPN_GetValue(m_pNPInstance, NPNVisOfflineBool, (void *)&bOffline);
00472   NPN_GetValue(m_pNPInstance, NPNVjavascriptEnabledBool, (void *)&m_bJavaScript);
00473   //NPN_GetValue(m_pNPInstance, NPNVasdEnabledBool, (void *)&m_bSmartUpdate);
00474 
00475   m_bOnline = !bOffline;
00476 
00477 #ifdef OJI
00478   if(m_bOnline && m_bJavaScript && m_bSmartUpdate && useDefaultURL_P())
00479   {
00480     JRIEnv *penv = NPN_GetJavaEnv();
00481     m_bJava = (penv != NULL);
00482   }
00483 #else
00484   m_bJava = FALSE;
00485 #endif
00486 
00487   dbgOut1("Environment:");
00488   dbgOut2("%s", m_bOnline ? "On-line" : "Off-line");
00489   dbgOut2("Java %s", m_bJava ? "Enabled" : "Disabled");
00490   dbgOut2("JavaScript %s", m_bJavaScript ? "Enabled" : "Disabled");
00491   dbgOut2("SmartUpdate %s", m_bSmartUpdate ? "Enabled" : "Disabled");
00492 
00493   if((!m_bSmartUpdate && (m_szPageURL != NULL) || (m_szFileURL != NULL)) || !m_bJavaScript)
00494   {
00495     // we don't want it more than once
00496     if(m_hWndDialog == NULL)
00497       CreateDialogParam(m_hInst, MAKEINTRESOURCE(IDD_PLUGIN_DOWNLOAD), m_hWnd,
00498                         (DLGPROC)GetPluginDialogProc, (LPARAM)this);
00499   }
00500   else
00501     getPlugin();
00502 }
00503 
00504 void CPlugin::getPlugin()
00505 {
00506   if(m_szCommandMessage != NULL)
00507   {
00508     delete [] m_szCommandMessage;
00509     m_szCommandMessage = NULL;
00510   }
00511 
00512   char szString[1024] = {'\0'};
00513   LoadString(m_hInst, IDS_CLICK_WHEN_DONE, szString, sizeof(szString));
00514   if(*szString)
00515   {
00516     m_szCommandMessage = new char[lstrlen(szString) + 1];
00517     if(m_szCommandMessage != NULL)
00518       lstrcpy(m_szCommandMessage, szString);
00519   }
00520 
00521   InvalidateRect(m_hWnd, NULL, TRUE);
00522   UpdateWindow(m_hWnd);
00523 
00524   getPluginRegular();
00525 }
00526 
00527 //*******************
00528 // NP API handles
00529 //*******************
00530 void CPlugin::resize()
00531 {
00532   dbgOut1("CPlugin::resize()");
00533 }
00534 
00535 void CPlugin::print(NPPrint * pNPPrint)
00536 {
00537   dbgOut1("CPlugin::print()");
00538 
00539   if(pNPPrint == NULL)
00540     return;
00541 }
00542 
00543 void CPlugin::URLNotify(const char * szURL)
00544 {
00545   dbgOut2("CPlugin::URLNotify(), URL '%s'", szURL);
00546 
00547   NPStream * pStream = NULL;
00548   char buf[256];
00549 
00550   assert(m_hInst != NULL);
00551   assert(m_pNPInstance != NULL);
00552   
00553   int iSize = LoadString(m_hInst, IDS_GOING2HTML, buf, sizeof(buf));
00554 
00555   NPError rc = NPN_NewStream(m_pNPInstance, "text/html", "asd_plugin_finder", &pStream);
00556   if (rc != NPERR_NO_ERROR)
00557     return;
00558 
00559   //char buf[] = "<html>\n<body>\n\n<h2 align=center>NPN_NewStream / NPN_Write - This seems to work.</h2>\n\n</body>\n</html>";
00560   
00561   NPN_Write(m_pNPInstance, pStream, iSize, buf);
00562 
00563   NPN_DestroyStream(m_pNPInstance, pStream, NPRES_DONE);
00564 }
00565 
00566 NPError CPlugin::newStream(NPMIMEType type, NPStream *stream, NPBool seekable, uint16 *stype)
00567 {
00568   if (!m_bWaitingStreamFromPFS)
00569     return NPERR_NO_ERROR;
00570 
00571   m_bWaitingStreamFromPFS = FALSE;
00572   m_PFSStream = stream;
00573 
00574   if (stream) {
00575     if (type && !strcmp(type, "application/x-xpinstall"))
00576       NPN_GetURL(m_pNPInstance, stream->url, "_self");
00577     else
00578       NPN_GetURL(m_pNPInstance, stream->url, "_blank");
00579   }
00580 
00581   return NPERR_NO_ERROR;
00582 }
00583 
00584 NPError CPlugin::destroyStream(NPStream *stream, NPError reason)
00585 {
00586   if (stream == m_PFSStream)
00587     m_PFSStream = NULL;
00588 
00589   return NPERR_NO_ERROR;
00590 }
00591 
00592 BOOL CPlugin::readyToRefresh()
00593 {
00594   char szString[1024] = {'\0'};
00595   LoadString(m_hInst, IDS_CLICK_WHEN_DONE, szString, sizeof(szString));
00596   if(m_szCommandMessage == NULL)
00597     return FALSE;
00598 
00599   return (lstrcmp(m_szCommandMessage, szString) == 0);
00600 }
00601 
00602 //***************************
00603 // Windows message handlers
00604 //***************************
00605 void CPlugin::onCreate(HWND hWnd)
00606 {
00607   m_hWnd = hWnd;
00608 }
00609 
00610 void CPlugin::onLButtonUp(HWND hWnd, int x, int y, UINT keyFlags)
00611 {
00612   if(!readyToRefresh())
00613     showGetPluginDialog();
00614   else
00615     NPN_GetURL(m_pNPInstance, "javascript:navigator.plugins.refresh(true)", "_self");
00616 }
00617 
00618 void CPlugin::onRButtonUp(HWND hWnd, int x, int y, UINT keyFlags)
00619 {
00620   if(!readyToRefresh())
00621     showGetPluginDialog();
00622   else
00623     NPN_GetURL(m_pNPInstance, "javascript:navigator.plugins.refresh(true)", "_self");
00624 }
00625 
00626 static void DrawCommandMessage(HDC hDC, LPSTR szString, LPRECT lprc)
00627 {
00628   if(szString == NULL)
00629     return;
00630 
00631   HFONT hFont = GetStockFont(DEFAULT_GUI_FONT);
00632   if(hFont == NULL)
00633     return;
00634 
00635   HFONT hFontOld = SelectFont(hDC, hFont);
00636   SIZE sz;
00637   GetTextExtentPoint32(hDC, szString, lstrlen(szString), &sz);
00638   POINT pt;
00639   pt.x = sz.cx;
00640   pt.y = sz.cy;
00641   LPtoDP(hDC, &pt, 1);
00642 
00643   int iY = (lprc->bottom / 2) - ((32) / 2) + 36;
00644   int iX = 0;
00645 
00646   if(lprc->right > pt.x)
00647     iX = lprc->right/2 - pt.x/2;
00648   else
00649     iX = 1;
00650 
00651   RECT rcText;
00652   rcText.left   = iX;
00653   rcText.right  = rcText.left + pt.x;
00654   rcText.top    = iY;
00655   rcText.bottom = rcText.top + pt.y;
00656 
00657   int iModeOld = SetBkMode(hDC, TRANSPARENT);
00658   COLORREF crColorOld = SetTextColor(hDC, RGB(0,0,0));
00659   DrawText(hDC, szString, lstrlen(szString), &rcText, DT_CENTER|DT_VCENTER);
00660   SetTextColor(hDC, crColorOld);
00661   SetBkMode(hDC, iModeOld);
00662   SelectFont(hDC, hFontOld);
00663 }
00664 
00665 void CPlugin::onPaint(HWND hWnd)
00666 {
00667   RECT rc;
00668   HDC hDC;
00669   PAINTSTRUCT ps;
00670   int x, y;
00671 
00672   hDC = BeginPaint(hWnd, &ps);
00673   GetClientRect(hWnd, &rc);
00674 
00675   x = (rc.right / 2) - (32 / 2);
00676   y = (rc.bottom / 2) - ((32) / 2);
00677 
00678   if(rc.right > 34 && rc.bottom > 34)
00679   {
00680     if(m_hIcon != NULL)
00681       DrawIcon(hDC, x, y, m_hIcon);
00682 
00683     POINT pt[5];
00684 
00685     // left vert and top horiz highlight
00686     pt[0].x = 1;            pt[0].y = rc.bottom-1;
00687     pt[1].x = 1;            pt[1].y = 1;
00688     pt[2].x = rc.right-1; pt[2].y = 1;
00689 
00690     HPEN hPen3DLight  = CreatePen(PS_SOLID, 1, GetSysColor(COLOR_3DLIGHT));
00691     HPEN hPen3DShadow = CreatePen(PS_SOLID, 1, GetSysColor(COLOR_3DSHADOW));
00692     HPEN hPen3DDKShadow = CreatePen(PS_SOLID, 1, GetSysColor(COLOR_3DDKSHADOW));
00693 
00694     HPEN hPenOld = SelectPen(hDC, hPen3DLight);
00695     Polyline(hDC, pt, 3);
00696 
00697     // left vert and top horiz shadow
00698     pt[0].x = 2;            pt[0].y = rc.bottom-3;
00699     pt[1].x = 2;            pt[1].y = 2;
00700     pt[2].x = rc.right-2; pt[2].y = 2;
00701     SelectPen(hDC, hPen3DShadow);
00702     Polyline(hDC, pt, 3);
00703 
00704     // right vert and bottom horiz highlight
00705     pt[0].x = rc.right-3; pt[0].y = 2;
00706     pt[1].x = rc.right-3; pt[1].y = rc.bottom-3;
00707     pt[2].x = 2;            pt[2].y = rc.bottom-3;
00708     SelectPen(hDC, hPen3DLight);
00709     Polyline(hDC, pt, 3);
00710 
00711     // right vert and bottom horiz shadow
00712     pt[0].x = rc.right-1; pt[0].y = 1;
00713     pt[1].x = rc.right-1; pt[1].y = rc.bottom-1;
00714     pt[2].x = 0;            pt[2].y = rc.bottom-1;
00715     SelectPen(hDC, hPen3DDKShadow);
00716     Polyline(hDC, pt, 3);
00717 
00718     // restore the old pen
00719     SelectPen(hDC, hPenOld);
00720 
00721     DeletePen(hPen3DDKShadow);
00722     DeletePen(hPen3DShadow);
00723     DeletePen(hPen3DLight);
00724     
00725     DrawCommandMessage(hDC, m_szCommandMessage, &rc);
00726   }
00727   else
00728     if(m_hIcon != NULL)
00729       DrawIconEx(hDC, x, y, m_hIcon, rc.right - rc.left, rc.bottom - rc.top, 0, NULL, DI_NORMAL);
00730 
00731   EndPaint (hWnd, &ps);
00732 }
00733 
00734 //**************************
00735 // Plugin window procedure
00736 //**************************
00737 static LRESULT CALLBACK NP_LOADDS PluginWndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
00738 {
00739   CPlugin *pPlugin = (CPlugin *)GetWindowLong(hWnd, GWL_USERDATA);
00740                         
00741   switch(message)
00742   {
00743     case WM_CREATE:
00744       pPlugin = (CPlugin *)(((CREATESTRUCT FAR*)lParam)->lpCreateParams);
00745       assert(pPlugin != NULL);
00746       SetWindowLong(hWnd, GWL_USERDATA, (LONG)pPlugin);
00747       pPlugin->onCreate(hWnd);
00748       return 0L;
00749     case WM_LBUTTONUP:
00750       HANDLE_WM_LBUTTONUP(hWnd, wParam, lParam, pPlugin->onLButtonUp);
00751       return 0L;
00752     case WM_RBUTTONUP:
00753       HANDLE_WM_RBUTTONUP(hWnd, wParam, lParam, pPlugin->onRButtonUp);
00754       return 0L;
00755     case WM_PAINT:
00756       HANDLE_WM_PAINT(hWnd, wParam, lParam, pPlugin->onPaint);
00757       return 0L;
00758     case WM_MOUSEMOVE:
00759       dbgOut1("MouseMove");
00760       break;
00761 
00762     default:
00763       break;
00764   }
00765   return(DefWindowProc(hWnd, message, wParam, lParam));
00766 }