home *** CD-ROM | disk | FTP | other *** search
/ OS/2 Shareware BBS: 10 Tools / 10-Tools.zip / wxos2240.zip / wxWindows-2.4.0 / contrib / src / applet / appletwindow.cpp < prev    next >
C/C++ Source or Header  |  2002-02-07  |  28KB  |  834 lines

  1. /****************************************************************************
  2. *
  3. *                       wxWindows HTML Applet Package
  4. *
  5. *               Copyright (C) 1991-2001 SciTech Software, Inc.
  6. *                            All rights reserved.
  7. *
  8. *  ========================================================================
  9. *
  10. *    The contents of this file are subject to the wxWindows License
  11. *    Version 3.0 (the "License"); you may not use this file except in
  12. *    compliance with the License. You may obtain a copy of the License at
  13. *    http://www.wxwindows.org/licence3.txt
  14. *
  15. *    Software distributed under the License is distributed on an
  16. *    "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
  17. *    implied. See the License for the specific language governing
  18. *    rights and limitations under the License.
  19. *
  20. *  ========================================================================
  21. *
  22. * Language:     ANSI C++
  23. * Environment:  Any
  24. *
  25. * Description:  Main wxHtmlAppletWindow class implementation
  26. *
  27. ****************************************************************************/
  28.  
  29. // Include private headers
  30. #include "wx/applet/applet.h"
  31. #include "wx/applet/window.h"
  32. #include "wx/applet/loadpage.h"
  33. #include "wx/applet/plugin.h"
  34.  
  35. // Preprocessor Stuff
  36. #include "wx/applet/prepinclude.h"
  37. #include "wx/applet/prepecho.h"
  38. #include "wx/applet/prepifelse.h"
  39.  
  40. // wxWindows headers
  41.  
  42. // Kind of pointless to use precompiled headers when this is the only
  43. // file in this lib that would need them.
  44. #include "wx/defs.h"
  45. #include "wx/spawnbrowser.h"
  46. #include "wx/html/forcelnk.h"
  47. #include "wx/log.h"
  48. #include "wx/msgdlg.h"
  49. #include "wx/tbarbase.h"
  50.  
  51. // crt
  52. #ifdef __WXMSW__
  53. #include <process.h>        // spawnl()
  54. #endif
  55.  
  56. /*---------------------------- Global variables ---------------------------*/
  57.  
  58. wxHashTable wxHtmlAppletWindow::m_Cookies;        
  59.         
  60. /*------------------------- Implementation --------------------------------*/
  61.  
  62. // Empty event handler. We include this event handler simply so that
  63. // sub-classes of wxApplet can reference wxApplet in the event tables
  64. // that they create as necessary.
  65. BEGIN_EVENT_TABLE(wxHtmlAppletWindow, wxHtmlWindow)
  66.     EVT_LOAD_PAGE(wxHtmlAppletWindow::OnLoadPage)
  67.     EVT_PAGE_LOADED(wxHtmlAppletWindow::OnPageLoaded)
  68. END_EVENT_TABLE()
  69.  
  70. // Implement the class functions for wxHtmlAppletWindow
  71. IMPLEMENT_CLASS(wxHtmlAppletWindow, wxHtmlWindow);
  72.  
  73. // Implement the dynamic class so it can be constructed dynamically
  74. IMPLEMENT_DYNAMIC_CLASS(VirtualData, wxObject);
  75.     
  76. // Define the wxAppletList implementation
  77. #include "wx/listimpl.cpp"
  78. WX_DEFINE_LIST(wxAppletList);
  79.  
  80. /****************************************************************************
  81. REMARKS:
  82. Constructor for the applet window class.
  83. ****************************************************************************/
  84. wxHtmlAppletWindow::wxHtmlAppletWindow(
  85.     wxWindow *parent,
  86.     wxWindowID id,
  87.     wxToolBarBase *navBar,
  88.     int navBackId,
  89.     int navForwardId,
  90.     const wxPoint& pos,
  91.     const wxSize& size,
  92.     long style,
  93.     const wxString& name)
  94.     : wxHtmlWindow(parent,id,pos,size,style,name), m_AppletList(wxKEY_STRING)
  95. {
  96.     // Init our locks
  97.     UnLock();
  98.  
  99.     // setup client navbars
  100.     if (navBar) {
  101.         m_NavBarEnabled = true;
  102.         m_NavBar = navBar;
  103.         m_NavBackId = navBackId;
  104.         m_NavForwardId = navForwardId;
  105.         }
  106.     else {
  107.         m_NavBarEnabled = false;
  108.         m_NavBar = NULL;
  109.         }
  110.  
  111.     m_NavBackId = navBackId;
  112.     m_NavForwardId = navForwardId;
  113.  
  114.     // Add HTML preprocessors
  115.     // deleting preprocessors is done by the code within the window
  116.     incPreprocessor = new wxIncludePrep(); // #include preprocessor
  117.     incPreprocessor->ChangeDirectory(m_FS); // give it access to our filesys object
  118.     this->AddProcessor(incPreprocessor);
  119.     this->AddProcessor(new wxEchoPrep());
  120.     this->AddProcessor(new wxIfElsePrep());
  121. }
  122.  
  123. /****************************************************************************
  124. REMARKS:
  125. Destructor for the applet window class.
  126. ****************************************************************************/
  127. wxHtmlAppletWindow::~wxHtmlAppletWindow()
  128. {
  129. }
  130.  
  131. /****************************************************************************
  132. PARAMETERS:
  133. dc  - wxDC object to draw on
  134.  
  135. REMARKS:
  136. ****************************************************************************/
  137. void wxHtmlAppletWindow::OnDraw(
  138.     wxDC& dc)
  139. {
  140.     wxHtmlWindow::OnDraw(dc);
  141. }
  142.  
  143. /****************************************************************************
  144. PARAMETERS:
  145. className       - Name of the applet class to create an object for
  146. size            - Initial size of the applet to be created
  147.  
  148. RETURNS:
  149. Pointer to the wxApplet created, or NULL if unable to create the applet.
  150.  
  151. REMARKS:
  152. This function is used to create new wxApplet objects dynamically based on the
  153. class name as a string. This allows instances of wxApplet classes to be
  154. created dynamically based on string values embedded in the custom tags of an
  155. HTML page.
  156. ****************************************************************************/
  157. wxApplet *wxHtmlAppletWindow::CreateApplet(
  158.     const wxString& classId,
  159.     const wxString& iName,
  160.     const wxHtmlTag& params,
  161.     const wxSize& size)
  162. {
  163.     // Dynamically create the class instance at runtime
  164.     wxObject *obj = wxCreateDynamicObject(classId.c_str());
  165.     wxApplet *applet = wxDynamicCast(obj,wxApplet);
  166.     if (!applet)
  167.         return NULL;
  168.     if (!applet->Create(this,params,size)) {
  169.         delete applet;
  170.         return NULL;
  171.         }
  172.     else {
  173.         // do some fixups on the size if its screwed up
  174.         wxSize nsize = applet->GetBestSize();
  175.         if (nsize.x < size.x) nsize.x = size.x;
  176.         if (nsize.y < size.y) nsize.y = size.y;
  177.         applet->SetSize(nsize);
  178.         }
  179.  
  180.     m_AppletList.Append(iName,(wxObject*)applet);
  181.     return applet;
  182. }
  183.  
  184. /****************************************************************************
  185. PARAMETERS:
  186. classId       - Name of the Plugin class to create an object for
  187.  
  188. RETURNS:
  189. Pointer to the wxplugIn created, or NULL if unable to create the PlugIn.
  190.  
  191. REMARKS:
  192. This function is used to create new wxPlugIn objects dynamically based on the
  193. class name as a string. This allows instances of wxPlugIn classes to be
  194. created dynamically based on string values embedded in the custom tags of an
  195. HTML page.
  196. ****************************************************************************/
  197. bool wxHtmlAppletWindow::CreatePlugIn(
  198.     const wxString& classId,
  199.     const wxString& cmdLine)
  200. {
  201.     // Dynamically create the class instance at runtime, execute it
  202.     // and then destroy it.
  203.     wxObject *obj = wxCreateDynamicObject(classId.c_str());
  204.     wxPlugIn *plugIn = wxDynamicCast(obj,wxPlugIn);
  205.     if (!plugIn)
  206.         return false;
  207.     if (!plugIn->Create(this)) {
  208.         delete plugIn;
  209.         return false;
  210.         }
  211.     plugIn->Run(cmdLine);
  212.     delete plugIn;
  213.     return true;
  214. }
  215.  
  216. /****************************************************************************
  217. PARAMETERS:
  218. appletName      - Name of the applet class to find
  219.  
  220. RETURNS:
  221. Pointer to the wxApplet found, or NULL if not found.
  222.  
  223. REMARKS:
  224. Find an instance of an applet based on it's name
  225. ****************************************************************************/
  226. wxApplet *wxHtmlAppletWindow::FindApplet(
  227.     const wxString& appletName)
  228. {
  229.     wxAppletList::Node *node = m_AppletList.Find(appletName);
  230.     if (!node)
  231.         return NULL;
  232.     return node->GetData();
  233. }
  234.  
  235. /****************************************************************************
  236. PARAMETERS:
  237. applet      - Pointer to the applet object to remove from the list
  238.  
  239. RETURNS:
  240. True if the applet was found and removed, false if not. The applet itself
  241. is *not* destroyed!
  242.  
  243. REMARKS:
  244. Remove an applet from the manager. Called during applet destruction
  245. ****************************************************************************/
  246. bool wxHtmlAppletWindow::RemoveApplet(
  247.     const wxApplet *applet)
  248. {
  249.     for (wxAppletList::Node *node = m_AppletList.GetFirst(); node; node = node->GetNext()) {
  250.         if (node->GetData() == applet) {
  251.             m_AppletList.DeleteNode(node);
  252.             return true;
  253.             }
  254.         }
  255.     return false;
  256. }
  257.  
  258. /****************************************************************************
  259. PARAMETERS:
  260. URL - New URL for the page to load
  261.  
  262. RETURNS:
  263. True if page loaded successfully, false if not
  264.  
  265. REMARKS:
  266. Remove an applet from the manager. Called during applet destruction
  267. ****************************************************************************/
  268. bool wxHtmlAppletWindow::LoadPage(
  269.     const wxString& link)
  270. {
  271.     wxString href(link);
  272.  
  273.     if (link.GetChar(0) == '?'){
  274.         wxString cmd = link.BeforeFirst('=');
  275.         wxString cmdValue = link.AfterFirst('=');
  276.  
  277.         // Launches the default Internet browser for the system.
  278.         if(!(cmd.CmpNoCase("?EXTERNAL"))) {
  279.             return wxSpawnBrowser(this, cmdValue.c_str());
  280.             }
  281.  
  282.         // Launches an external program on the system.
  283.         if (!(cmd.CmpNoCase("?EXECUTE"))) {
  284.             int waitflag = P_NOWAIT;
  285.             bool ret;
  286.             wxString currentdir;
  287.             wxString filename, path, ext;
  288.  
  289.             // Parse the params sent to the execute command. For now the only
  290.             // parm is "wait". wait will cause spawn wait, default is nowait.
  291.             // Since we only need one param for now I am not going to make this
  292.             // any smater then it needs to be. If we need more params later i'll
  293.             // fix it.
  294.             int i = cmdValue.Find('(');
  295.             if (i != -1) {
  296.                 wxString param = cmdValue.AfterFirst('(');
  297.                 cmdValue.Truncate(i);
  298.                 if (!param.CmpNoCase("wait)"))
  299.                     waitflag = P_WAIT;
  300.                 }
  301.  
  302.             currentdir = wxGetCwd();
  303.             //we don't want to change the path of the virtual file system so we have to use these
  304.             //functions rather than the filesystem
  305.             wxSplitPath(cmdValue, &path, &filename, &ext);
  306.             if (path.CmpNoCase("") != 0) wxSetWorkingDirectory(path);
  307.  
  308.             ret = !spawnl( waitflag, cmdValue , NULL );
  309.             //HACK should use wxExecute
  310.             //ret = wxExecute(filename, bool sync = FALSE, wxProcess *callback = NULL)
  311.             wxSetWorkingDirectory(currentdir);
  312.  
  313.             return ret;
  314.             }
  315.  
  316.         // Looks for a href in a variable stored as a cookie. The href can be
  317.         // changed on the fly.
  318.         if (!(cmd.CmpNoCase("?VIRTUAL"))){
  319.             wxObject *obj = FindCookie(cmdValue);
  320.             VirtualData *virtData = wxDynamicCast(obj,VirtualData);
  321.             if (virtData) {
  322.                 // recurse and loadpage, just in case the link is like another
  323.                 // ? link
  324.                 return LoadPage(virtData->GetHref());
  325.                 }
  326.             else {
  327. #ifdef CHECKED
  328.                 wxLogError(_T("VIRTUAL LINK ERROR: '%s' does not exist."), cmdValue.c_str());
  329. #endif
  330.                 return true;
  331.                 }
  332.             }
  333.  
  334.         // This launches a qlet - It is like an applet but is more generic in that it
  335.         // can be of any wxWin type so it then has the freedom to do more stuff.
  336.         if (!(cmd.CmpNoCase("?WXPLUGIN"))){
  337.             if (!cmdValue.IsNull()) {
  338.                 // TODO: We are going to need to add code to parse the command line
  339.                 //       parameters string in here in the future...
  340.                 wxString cmdLine = link.AfterFirst('(');
  341.                 cmdLine = cmdLine.BeforeLast(')');
  342.                 if (!CreatePlugIn(cmdValue,cmdLine)) {
  343. #ifdef CHECKED
  344.                     wxLogError(_T("Launch PlugIn ERROR: '%s' does not exist."), cmdValue.c_str());
  345. #endif
  346.                     }
  347.                 }
  348.              return true;
  349.             }
  350.  
  351.         // This used in a link or href will take you back in the history.
  352.         if (!(cmd.CmpNoCase("?BACK"))){
  353.             HistoryBack();
  354.             return true;
  355.             }
  356.  
  357.         // This used in a link or href will take you forward in the history
  358.         if (!(cmd.CmpNoCase("?FORWARD"))){
  359.             HistoryForward();
  360.             return true;
  361.             }
  362.         }
  363.  
  364.     // Inform all the applets that the new page is being loaded
  365.     for (wxAppletList::Node *node = m_AppletList.GetFirst(); node; node = node->GetNext())
  366.         (node->GetData())->OnLinkClicked(wxHtmlLinkInfo(href));
  367.     Show(false);
  368.  
  369.     m_openedlast = href;
  370.     bool stat = wxHtmlWindow::LoadPage(href);
  371.     Show(true);
  372.  
  373.     // Enable/Dis the navbar tools
  374.     if (m_NavBarEnabled) {
  375.         m_NavBar->EnableTool(m_NavForwardId,HistoryCanForward());
  376.         m_NavBar->EnableTool(m_NavBackId,HistoryCanBack());
  377.         }
  378.     return stat;
  379. }
  380.  
  381. /****************************************************************************
  382. PARAMETERS:
  383. URL - String URL that we are navigating to
  384.  
  385. REMARKS:
  386. Called when the user navigates to a new URL from the current page. We simply
  387. call the LoadPage function above to load the new page and display it.
  388. ****************************************************************************/
  389. void wxHtmlAppletWindow::OnLinkClicked(
  390.     const wxHtmlLinkInfo& link)
  391. {
  392.     LoadPage(link.GetHref());
  393. }
  394.  
  395. /****************************************************************************
  396. REMARKS:
  397. Called when the user navigates forward within the HTML history stack.
  398. We call all the applets in turn allowing them to handle the navigation
  399. command prior to being destructed when the current page is destroyed.
  400. ****************************************************************************/
  401. bool wxHtmlAppletWindow::HistoryForward()
  402. {
  403.     if (!HistoryCanForward())
  404.         return false;
  405.  
  406.     for (wxAppletList::Node *node = m_AppletList.GetFirst(); node; node = node->GetNext())
  407.         (node->GetData())->OnHistoryForward();
  408.  
  409.     return wxHtmlWindow::HistoryForward();
  410. }
  411.  
  412. /****************************************************************************
  413. REMARKS:
  414. Called when the user navigates backwards within the HTML history stack.
  415. We call all the applets in turn allowing them to handle the navigation
  416. command prior to being destructed when the current page is destroyed.
  417. ****************************************************************************/
  418. bool wxHtmlAppletWindow::HistoryBack()
  419. {
  420.     if (!HistoryCanBack())
  421.         return false;
  422.  
  423.     for (wxAppletList::Node *node = m_AppletList.GetFirst(); node; node = node->GetNext())
  424.         (node->GetData())->OnHistoryBack();
  425.  
  426.     return wxHtmlWindow::HistoryBack();
  427. }
  428.  
  429. /****************************************************************************
  430. REMARKS:
  431. This function is used to disable the navigation bars. If you want to
  432. toggle to the navbars off you must call this function.
  433. ****************************************************************************/
  434. void wxHtmlAppletWindow::DisableNavBar()
  435. {
  436.     m_NavBarEnabled = false;
  437. }
  438.  
  439. /****************************************************************************
  440. REMARKS:
  441. This function is used to enable the nav bars. If you toggle the nav bars on
  442. you must call this function.
  443. ****************************************************************************/
  444. void wxHtmlAppletWindow::EnableNavBar()
  445. {
  446.     m_NavBarEnabled = true;
  447. }
  448.  
  449. /****************************************************************************
  450. REMARKS:
  451. This function is used to set the nav bar to a new nav bar if you deleted the
  452. one that you were useing. Usally this happens when you toggle a nav bar
  453. on or off.
  454. ****************************************************************************/
  455. void wxHtmlAppletWindow::SetNavBar(wxToolBarBase *navBar)
  456. {
  457.     m_NavBar = navBar;
  458. }
  459.  
  460. /****************************************************************************
  461. PARAMETERS:
  462. msg - wxEvent message to be sent to all wxApplets
  463.  
  464. REMARKS:
  465. This function is called by the wxApplet's when they need to send a message
  466. to all other applets on the current page. This is the primary form of
  467. communication between applets on the page if they need to inform each
  468. other of internal information.
  469.  
  470. ****************************************************************************/
  471. void wxHtmlAppletWindow::SendAppletMessage(
  472.     wxAppletEvent& msg)
  473. {
  474.     // TODO: make a named target for messages, only send a message to the correct
  475.     // named applet
  476.  
  477.     // Process all applets in turn and send them the message
  478.     for (wxAppletList::Node *node = m_AppletList.GetFirst(); node; node = node->GetNext()) {
  479.         (node->GetData())->OnMessage(msg);
  480.         }
  481. }
  482.  
  483. /****************************************************************************
  484. PARAMETERS:
  485. name    - Uniq wxString used as hash key
  486. cookie  - wxObject data returned when name is found.
  487.  
  488. RETURNS:
  489. True if new cookie was added, false if cookie with same name already exists.
  490.  
  491. REMARKS:
  492. This function is called by the wxApplet's when they need register a cookie
  493. of data in the applet window's cookie table. Cookies are arbitrary data
  494. objects that are references by unique name's by the wxApplet. These
  495. values can be used to store and retrieve data that needs to remain
  496. persisent across invocations of the wxApplet. Ie: The first time an
  497. applet is created it would use the cookie to store data to maintain
  498. it's present state so that if you navigated back to the same page
  499. is would be able to re-load the prior state as though the applet
  500. was never actually destructed.
  501.  
  502. Note: If a cookie with the same name already exists, this function returns
  503.       false. Hence if you wish to replace a cookie you should first call
  504.       UnRegisterCookie to ensure the cookie is deleted and then call this
  505.       function.
  506. ****************************************************************************/
  507. bool wxHtmlAppletWindow::RegisterCookie(
  508.     const wxString& name,
  509.     wxObject *cookie)
  510. {
  511.     // Fail if the named cookie already exists!
  512.     if (m_Cookies.Get(name))
  513.         return false;
  514.     m_Cookies.Put(name,cookie);
  515.     return true;
  516. }
  517.  
  518. /****************************************************************************
  519. PARAMETERS:
  520. name - wxString uniq haskey used to remove item from hash
  521.  
  522. RETURNS:
  523. True if found and deleted, false if not found in table.
  524.  
  525. REMARKS:
  526. This function is called by the wxApplet's when they need de-register a
  527. cookie of data in the applet window's cookie table. The data in the
  528. cookie itself is also deleted before it is removed from the table.
  529. ****************************************************************************/
  530. bool wxHtmlAppletWindow::UnRegisterCookie(
  531.     const wxString& name)
  532. {
  533.     wxObject *data = m_Cookies.Delete(name);
  534.     if (data) {
  535.         delete data;
  536.         return true;
  537.         }
  538.     return false;
  539. }
  540.  
  541. /****************************************************************************
  542. PARAMETERS:
  543. msg - wxEvent message to be sent to all wxApplets
  544.  
  545. RETURNS:
  546. Pointer to the cookie data if found, NULL if not found.
  547.  
  548. REMARKS:
  549. This function is called by the wxApplet's when they need to find a cookie
  550. of data given it's public name. If the cookie is not found, NULL is
  551. returned.
  552. ****************************************************************************/
  553. wxObject *wxHtmlAppletWindow::FindCookie(
  554.     const wxString& name)
  555. {
  556.     return m_Cookies.Get(name);
  557. }
  558.  
  559. /****************************************************************************
  560. PARAMETERS:
  561. event   - Event to handle
  562.  
  563. REMARKS:
  564. This function handles delayed LoadPage events posted from applets that
  565. need to change the page for the current window to a new window.
  566. ****************************************************************************/
  567. void wxHtmlAppletWindow::OnLoadPage(
  568.     wxLoadPageEvent &event)
  569. {
  570.     // Test the mutex lock.
  571.     if (!(IsLocked())) {
  572.         Lock();
  573.         if (event.GetHtmlWindow() == this) {
  574.             if (LoadPage(event.GetHRef())) {
  575.                 // wxPageLoadedEvent evt;
  576.                 // NOTE: This is reserved for later use as we might need to send
  577.                 // page loaded events to applets.
  578.                 }
  579.             }
  580.         UnLock();
  581.         }
  582. }
  583.  
  584. /****************************************************************************
  585. PARAMETERS:
  586. event   - Event to handle
  587.  
  588. REMARKS:
  589. This function handles delayed LoadPage events posted from applets that
  590. need to change the page for the current window to a new window.
  591. ****************************************************************************/
  592. void wxHtmlAppletWindow::OnPageLoaded(
  593.     wxPageLoadedEvent &)
  594. {
  595.     Enable(true);
  596. }
  597.  
  598. /****************************************************************************
  599. PARAMETERS:
  600. none
  601.  
  602. REMARKS:
  603. This function tries to lock the mutex. If it can't, returns
  604. immediately with false.
  605. ***************************************************************************/
  606. bool wxHtmlAppletWindow::TryLock()
  607. {
  608.     if (!m_mutexLock) {
  609.         m_mutexLock = true;
  610.         return true;
  611.         }
  612.     return false;
  613. }
  614.  
  615. /****************************************************************************
  616. PARAMETERS:
  617. name    - name of the last applet that changed the data in this object
  618. group   - name of the group the allplet belongs to.
  619. href    - webpage to go to.
  620.  
  621. REMARKS:
  622. VirtualData is used to store information on the virtual links.
  623. ****************************************************************************/
  624. VirtualData::VirtualData(
  625.     wxString& name,
  626.     wxString& group,
  627.     wxString& href,
  628.     wxString& plugin )
  629. {
  630.     m_name = name;
  631.     m_group = group;
  632.     m_href = href;
  633.     m_plugIn = plugin;
  634. }
  635.  
  636. /****************************************************************************
  637. PARAMETERS:
  638. REMARKS:
  639. VirtualData is used to store information on the virtual links.
  640. ****************************************************************************/
  641. VirtualData::VirtualData()
  642. {
  643.     m_name.Empty();
  644.     m_group.Empty();
  645.     m_href.Empty();
  646. }
  647.  
  648. #include "wx/html/m_templ.h"
  649.  
  650. /****************************************************************************
  651. REMARKS:
  652. Implementation for the <embed> HTML tag handler. This handler takes care
  653. of automatically constructing the wxApplet objects of the appropriate
  654. class based on the <embed> tag information.
  655. ****************************************************************************/
  656. TAG_HANDLER_BEGIN(wxApplet, "WXAPPLET")
  657.  
  658. TAG_HANDLER_PROC(tag)
  659. {
  660.     wxWindow            *wnd;
  661.     wxHtmlAppletWindow    *appletWindow;
  662.     wxApplet            *applet;
  663.     wxString            classId;
  664.     wxString            name;
  665.     int                 width, height;
  666.  
  667.     // Get access to our wxHtmlAppletWindow class
  668.     wnd = m_WParser->GetWindow();
  669.     if ((appletWindow = wxDynamicCast(wnd,wxHtmlAppletWindow)) == NULL)
  670.         return false;
  671.  
  672.     // Parse the applet dimensions from the tag
  673.     wxSize size = wxDefaultSize;
  674.     int al;
  675.     if (tag.HasParam("WIDTH")) {
  676.         tag.GetParamAsInt("WIDTH", &width);
  677.         size.SetWidth(width);
  678.         }
  679.     if (tag.HasParam("HEIGHT")) {
  680.         tag.GetParamAsInt("HEIGHT", &height);
  681.         size.SetHeight(height);
  682.         }
  683.  
  684.     // Parse the applet alignment from the tag
  685.     al = wxHTML_ALIGN_BOTTOM;
  686.     if (tag.HasParam(wxT("ALIGN"))) {
  687.         wxString alstr = tag.GetParam(wxT("ALIGN"));
  688.         alstr.MakeUpper();  // for the case alignment was in ".."
  689.         if (alstr == wxT("TEXTTOP") || alstr == wxT("TOP"))
  690.             al = wxHTML_ALIGN_TOP;
  691.         else if ((alstr == wxT("CENTER")) || (alstr == wxT("ABSCENTER")))
  692.             al = wxHTML_ALIGN_CENTER;
  693.         }
  694.  
  695.     // Create the applet based on it's class
  696.     if (tag.HasParam("CLASSID")) {
  697.         classId = tag.GetParam("CLASSID");
  698.         if (classId.IsNull() || classId.Len() == 0) {
  699.             wxMessageBox("wxApplet tag error: CLASSID is NULL or empty.","Error",wxICON_ERROR);
  700.             return false;
  701.             }
  702.         if (tag.HasParam("NAME"))
  703.             name = tag.GetParam("NAME");
  704.  
  705.         // If the name is NULL or len is zero then we assume that the html guy
  706.         // didn't include the name param which is optional.
  707.         if (name.IsNull() || name.Len() == 0)
  708.             name = classId;
  709.  
  710.         // We got all the params and can now create the applet
  711.         if ((applet = appletWindow->CreateApplet(classId, name, tag , size)) != NULL) {
  712.             applet->Show(true);
  713.             m_WParser->OpenContainer()->InsertCell(new wxHtmlAppletCell(applet,al));
  714.             }
  715.         else
  716.             wxMessageBox("wxApplet error: Could not create:" + classId + "," + name);
  717.         }
  718.     else {
  719.         wxMessageBox("wxApplet tag error: Can not find CLASSID param.","Error",wxICON_ERROR);
  720.         return false;
  721.         }
  722.  
  723.     // Add more param parsing here. If or when spec changes.
  724.     // For now we'll ignore any other params those HTML guys
  725.     // might put in our tag.
  726.     return true;
  727. }
  728.  
  729. TAG_HANDLER_END(wxApplet)
  730.  
  731. TAGS_MODULE_BEGIN(wxApplet)
  732.     TAGS_MODULE_ADD(wxApplet)
  733. TAGS_MODULE_END(wxApplet)
  734.  
  735. /****************************************************************************
  736. REMARKS:
  737. Constructor for the HTML cell class to store our wxApplet windows in
  738. the HTML page to be rendered by wxHTML.
  739. ****************************************************************************/
  740. wxHtmlAppletCell::wxHtmlAppletCell(
  741.     wxWindow *wnd,
  742.     int align)
  743.     : wxHtmlCell()
  744. {
  745.     int sx, sy;
  746.     m_Wnd = wnd;
  747.     m_Wnd->GetSize(&sx, &sy);
  748.     m_Width = sx, m_Height = sy;
  749.     switch (align) {
  750.         case wxHTML_ALIGN_TOP :
  751.             m_Descent = m_Height;
  752.             break;
  753.         case wxHTML_ALIGN_CENTER :
  754.             m_Descent = m_Height / 2;
  755.             break;
  756.         case wxHTML_ALIGN_BOTTOM :
  757.         default :
  758.             m_Descent = 0;
  759.             break;
  760.         }
  761.     SetCanLiveOnPagebreak(FALSE);
  762. }
  763.  
  764. /****************************************************************************
  765. REMARKS:
  766. Implementation for the HTML cell class to store our wxApplet windows in
  767. the HTML page to be rendered by wxHTML.
  768. ****************************************************************************/
  769. wxHtmlAppletCell::~wxHtmlAppletCell()
  770. {
  771.     delete m_Wnd;
  772. }
  773.  
  774. /****************************************************************************
  775. REMARKS:
  776. Code to draw the html applet cell
  777. ****************************************************************************/
  778. void wxHtmlAppletCell::Draw(
  779.     wxDC& WXUNUSED(dc),
  780.     int WXUNUSED(x),
  781.     int WXUNUSED(y),
  782.     int WXUNUSED(view_y1),
  783.     int WXUNUSED(view_y2))
  784. {
  785.     int         absx = 0, absy = 0, stx, sty;
  786.     wxHtmlCell  *c = this;
  787.  
  788.     while (c) {
  789.         absx += c->GetPosX();
  790.         absy += c->GetPosY();
  791.         c = c->GetParent();
  792.         }
  793.     ((wxScrolledWindow*)(m_Wnd->GetParent()))->GetViewStart(&stx, &sty);
  794.     m_Wnd->Move(absx - wxHTML_SCROLL_STEP * stx, absy  - wxHTML_SCROLL_STEP * sty);
  795. }
  796.  
  797. /****************************************************************************
  798. REMARKS:
  799. Code to draw the html applet cell invisibly
  800. ****************************************************************************/
  801. void wxHtmlAppletCell::DrawInvisible(
  802.     wxDC& WXUNUSED(dc),
  803.     int WXUNUSED(x),
  804.     int WXUNUSED(y))
  805. {
  806.     int         absx = 0, absy = 0, stx, sty;
  807.     wxHtmlCell  *c = this;
  808.  
  809.     while (c) {
  810.         absx += c->GetPosX();
  811.         absy += c->GetPosY();
  812.         c = c->GetParent();
  813.         }
  814.     ((wxScrolledWindow*)(m_Wnd->GetParent()))->GetViewStart(&stx, &sty);
  815.     m_Wnd->Move(absx - wxHTML_SCROLL_STEP * stx, absy  - wxHTML_SCROLL_STEP * sty);
  816. }
  817.  
  818. /****************************************************************************
  819. REMARKS:
  820. Code to layout the html applet cell.
  821. ****************************************************************************/
  822. void wxHtmlAppletCell::Layout(
  823.     int w)
  824. {
  825.     int sx, sy;
  826.     m_Wnd->GetSize(&sx, &sy);
  827.     m_Width = sx, m_Height = sy;
  828.     wxHtmlCell::Layout(w);
  829. }
  830.  
  831. // This is our little forcelink hack.
  832. FORCE_LINK(loadpage)
  833.  
  834.