webengine/wmlengine/src/xhtml/src/Hypertext/XHTMLAElementHandler.cpp
changeset 74 91031d3aab7d
parent 68 92a765b5b3e7
child 85 e358f2276d3f
equal deleted inserted replaced
68:92a765b5b3e7 74:91031d3aab7d
     1 /*
       
     2 * Copyright (c) 2000 - 2001 Nokia Corporation and/or its subsidiary(-ies).
       
     3 * All rights reserved.
       
     4 * This component and the accompanying materials are made available
       
     5 * under the terms of the License "Eclipse Public License v1.0"
       
     6 * which accompanies this distribution, and is available
       
     7 * at the URL "http://www.eclipse.org/legal/epl-v10.html".
       
     8 *
       
     9 * Initial Contributors:
       
    10 * Nokia Corporation - initial contribution.
       
    11 *
       
    12 * Contributors:
       
    13 *
       
    14 * Description: 
       
    15 *
       
    16 */
       
    17 
       
    18 
       
    19 #include "nw_hypertext_aelementhandleri.h"
       
    20 
       
    21 #include "nw_xhtml_xhtmlcontenthandler.h"
       
    22 #include "nw_hed_hedeventhandler.h"
       
    23 #include "nw_hed_documentroot.h"
       
    24 #include "nw_lmgr_activecontainerbox.h"
       
    25 #include "nw_lmgr_textbox.h"
       
    26 #include "nw_evt_activateevent.h"
       
    27 #include "nw_evt_accesskeyevent.h"
       
    28 #include "nw_xhtml_savetophonebkevent.h"
       
    29 #include "nw_evt_focusevent.h"
       
    30 #include "nw_xhtml_xhtml_1_0_tokens.h"
       
    31 #include "nw_xhtml_telephonyservices.h"
       
    32 #include "nw_xhtml_textelementhandler.h"
       
    33 #include "nw_image_imgelementhandler.h"
       
    34 #include "nw_wmlscriptch_wmlscriptcontenthandler.h"  /* to run Wml Scripts */
       
    35 #include "nwx_url_utils.h"
       
    36 #include "nwx_http_defs.h"
       
    37 //#include "nw_ecma_contenthandler.h"
       
    38 #include "BrsrStatusCodes.h"
       
    39 #include "nwx_logger.h"
       
    40 
       
    41 /* ------------------------------------------------------------------------- */
       
    42 static  
       
    43 NW_LMgr_Box_t*
       
    44 NW_XHTML_aElementHandler_ImodeCreateBox(const NW_XHTML_ElementHandler_t* elementHandler,
       
    45                                         NW_XHTML_ContentHandler_t* contentHandler,
       
    46                                         NW_DOM_ElementNode_t* elementNode)
       
    47     {
       
    48     NW_Text_t* ctiVal = NULL;
       
    49     NW_Text_t* hrefVal = NULL;
       
    50     NW_Text_t* nameVal = NULL;
       
    51     NW_LMgr_ActiveContainerBox_t* box = NULL;
       
    52     NW_Bool validNumber = NW_FALSE;
       
    53     NW_Ucs2* storage = NULL;
       
    54     NW_Uint8 freeNeeded = NW_FALSE;
       
    55     NW_Text_Length_t charCount;
       
    56     NW_XHTML_TelephonyServices_t* telServices = NULL;
       
    57     NW_HED_EventHandler_t* eventHandler = NULL;
       
    58     NW_Ucs2* newUrl = NULL;
       
    59     NW_Ucs2 *chReturns = NULL;
       
    60     NW_Bool createBox = NW_FALSE;
       
    61     NW_LMgr_ActiveContainerBox_ActionType_t actionType = NW_LMgr_ActionType_OpenLink;
       
    62     
       
    63     NW_REQUIRED_PARAM(elementHandler);
       
    64     
       
    65     telServices = (NW_XHTML_TelephonyServices_t*)(&NW_XHTML_TelephonyServices);
       
    66 
       
    67     // Find the 'name' attribute and get its string value. The name is used below
       
    68     // if HREF is not specified and it is also used for ECMA script processing.
       
    69     NW_XHTML_GetDOMAttribute (contentHandler, elementNode, NW_XHTML_AttributeToken_name, &nameVal);
       
    70     
       
    71     /* find the 'cti' attribute and get its string value */
       
    72     NW_XHTML_GetDOMAttribute(contentHandler, elementNode,
       
    73                              NW_XHTML_AttributeToken_cti, &ctiVal);
       
    74     if (ctiVal)
       
    75         {
       
    76         storage = (NW_Ucs2*) NW_Text_GetUCS2Buffer(ctiVal, NW_Text_Flags_Aligned,&charCount,
       
    77                                                    &freeNeeded);
       
    78         if (!storage)
       
    79             {
       
    80             goto cleanup;
       
    81             }
       
    82         
       
    83         validNumber = NW_XHTML_TelephonyServices_ParseNumber(telServices, storage, NW_TRUE);
       
    84 
       
    85         if (storage && freeNeeded)
       
    86             {
       
    87             NW_Str_Delete(storage);
       
    88             storage = NULL;
       
    89             }
       
    90 
       
    91         if (validNumber)
       
    92             {
       
    93             eventHandler = NW_HED_EventHandler_New(NW_HED_DocumentNodeOf (contentHandler), elementNode);
       
    94             box = NW_LMgr_ActiveContainerBox_New(0, NW_LMgr_EventHandlerOf (eventHandler), NW_LMgr_ActionType_DialNumber);
       
    95             if (box)
       
    96                 {
       
    97                 NW_LMgr_ActiveContainerBox_SetName(box, nameVal, NW_TRUE);
       
    98                 nameVal = NULL; // ownership of name object was transferred to box
       
    99                 }
       
   100             goto cleanup;
       
   101             }
       
   102         }
       
   103 
       
   104     /* find the 'href' attribute and get its string value */
       
   105     NW_XHTML_GetDOMAttribute (contentHandler, elementNode, NW_XHTML_AttributeToken_href, &hrefVal);
       
   106     if (hrefVal == NULL)
       
   107         {
       
   108         /* if href is not specified in <a>, use base tag url, unless a name attribute is specified. 
       
   109         Because if a name tag is specifed but not an href, this <a> element means to be only a fragment
       
   110         identifier. */
       
   111         if (nameVal == NULL)
       
   112             {
       
   113             NW_XHTML_aElementHandler_getBaseTagUrl (contentHandler, &hrefVal);
       
   114             }
       
   115         }
       
   116 
       
   117     if (hrefVal)
       
   118         {
       
   119         NW_Url_Schema_t scheme = NW_SCHEMA_INVALID;
       
   120         NW_Ucs2* number;
       
   121 
       
   122         storage = (NW_Ucs2*) NW_Text_GetUCS2Buffer(hrefVal, NW_Text_Flags_Aligned, &charCount,
       
   123                                                    &freeNeeded);
       
   124         if (!storage)
       
   125             {
       
   126             goto cleanup;
       
   127             }
       
   128         
       
   129         /* At this point, only interested if a scheme is present, not if the URL 
       
   130         complies with RFC2396.  If there is a problem with the URL, it will be 
       
   131         caught later, when the anchor is selected.  The philosophy is to present
       
   132         everything to the user, except scheme=NW_SCHEMA_INVALID for TEL: and MAILTO:
       
   133         */
       
   134         NW_Url_GetSchemeNoValidation(storage, &scheme);
       
   135 
       
   136         // remove cariage return and new line from url
       
   137         chReturns = NW_Str_New (2);
       
   138         chReturns[0] = 0x0D;
       
   139         chReturns[1] = 0x0A;
       
   140         chReturns[2] = '\0';
       
   141 
       
   142         NW_LOG1( NW_LOG_OFF, "before removing, storage: %s", storage );
       
   143         newUrl = NW_Str_New(NW_Url_RemoveCharsLen(storage, chReturns));
       
   144         if (!newUrl)
       
   145             {
       
   146             goto cleanup;
       
   147             }
       
   148         NW_Url_RemoveChars(storage, newUrl, chReturns);
       
   149 
       
   150         // Validate the TEL:, WTAI:, MAILTO: schemes, all other schemes just get created.
       
   151         // Also, set the corresponding action type for the shemes.
       
   152         if (scheme == NW_SCHEMA_TEL)
       
   153             {
       
   154             // For "TEL:" scheme, verify the number, i.e. "TEL:8005551234"
       
   155             number = newUrl + 4;
       
   156             validNumber = NW_XHTML_TelephonyServices_ParseNumber(telServices, number, NW_FALSE);
       
   157             actionType = NW_LMgr_ActionType_DialNumber;
       
   158             // Create box for the anchor <a> link if and only if "TEL:" number format is valid.
       
   159             createBox = validNumber;
       
   160             }
       
   161         else if (scheme == NW_SCHEMA_WTAI)
       
   162             {
       
   163             // For "WTAI:" scheme, verify the number, i.e. "WTAI://wp/mc;8005551234"
       
   164             number = newUrl + 13;
       
   165             validNumber = NW_XHTML_TelephonyServices_ParseNumber(telServices, number, NW_FALSE);
       
   166             actionType = NW_LMgr_ActionType_DialNumber;
       
   167             // Create the box for the anchor <a> link if and only if "WTAI://wp/mc" number format is valid.
       
   168             createBox = validNumber;
       
   169             }
       
   170         else if (scheme == NW_SCHEMA_MAILTO)
       
   171             {
       
   172             // For "MAILTO" scheme, no verification. Assume it is valid.
       
   173             actionType = NW_LMgr_ActionType_SendMail;
       
   174             // Since there is no validation, always create the box. 
       
   175             createBox = NW_TRUE;
       
   176             }
       
   177         else
       
   178             {
       
   179             // Create an anchor for all other schemas (http, https, file,
       
   180             // etc...), including:
       
   181             //  NW_SCHEMA_UNKNOWN - Unknown schemes contain a colon, but aren't
       
   182             //      in the limited supported list. They need to be displayed
       
   183             //      anyhow, because some application might support it (plugin,
       
   184             //      sms, mms, etc...).
       
   185             //  NW_SCHEMA_INVALID - Probably a relative link.
       
   186             actionType = NW_LMgr_ActionType_OpenLink;
       
   187             // Always create the box.
       
   188             createBox = NW_TRUE;
       
   189             }
       
   190 
       
   191         if (createBox)
       
   192             {
       
   193             // Create the box for the anchor <a> link.
       
   194             eventHandler = NW_HED_EventHandler_New (NW_HED_DocumentNodeOf (contentHandler), elementNode);
       
   195             box = NW_LMgr_ActiveContainerBox_New(0, NW_LMgr_EventHandlerOf (eventHandler), actionType);
       
   196             if (box)
       
   197                 {
       
   198                 NW_LMgr_ActiveContainerBox_SetName(box, nameVal, NW_TRUE);
       
   199                 nameVal = NULL; // ownership of name object was transferred to box
       
   200                 }
       
   201             }
       
   202 
       
   203         }   // end of if (hrefVal)
       
   204         
       
   205       if (box)
       
   206         {
       
   207         box->hrefAttr = NW_Text_New( HTTP_iso_10646_ucs_2, (void*)newUrl, NW_Str_Strlen(newUrl), 
       
   208                                      NW_Text_Flags_NullTerminated | NW_Text_Flags_Aligned | NW_Text_Flags_Copy );
       
   209         if (!box->hrefAttr)
       
   210             {
       
   211             NW_Object_Delete(box);
       
   212             box = NULL;
       
   213             }
       
   214         }
       
   215 
       
   216 cleanup:
       
   217         if (hrefVal)
       
   218             {
       
   219             NW_Object_Delete(hrefVal);      
       
   220             }
       
   221         if (storage && freeNeeded)
       
   222             {
       
   223             NW_Str_Delete(storage);
       
   224             }
       
   225         if (newUrl)
       
   226             {
       
   227             NW_Str_Delete(newUrl);
       
   228             }        
       
   229         if (chReturns)
       
   230             {
       
   231             NW_Str_Delete(chReturns);
       
   232             }
       
   233         if (nameVal)
       
   234             {
       
   235             NW_Object_Delete(nameVal);
       
   236             }
       
   237         if (ctiVal)
       
   238             {
       
   239             NW_Object_Delete(ctiVal);
       
   240             }
       
   241 
       
   242         return (box) ? NW_LMgr_BoxOf(box) : NULL;
       
   243 }
       
   244 
       
   245 /* -------------------------------------------------------------------------
       
   246   ------------------------------------------------------------------------- */
       
   247 static  
       
   248 NW_LMgr_Box_t*
       
   249 NW_XHTML_aElementHandler_CreateBox(const NW_XHTML_ElementHandler_t* elementHandler,
       
   250                                    NW_XHTML_ContentHandler_t* contentHandler,
       
   251                                    NW_DOM_ElementNode_t* elementNode)
       
   252 {
       
   253   NW_Text_t* hrefVal = NULL;
       
   254   NW_Text_t* nameVal = NULL;
       
   255   NW_LMgr_ActiveContainerBox_t* box = NULL;
       
   256   NW_HED_EventHandler_t* eventHandler = NULL;
       
   257   NW_Ucs2* storage = NULL;
       
   258   NW_Uint8 freeNeeded = NW_FALSE;
       
   259 
       
   260   NW_REQUIRED_PARAM(elementHandler);
       
   261 
       
   262   // find the 'name' attribute.
       
   263   NW_XHTML_GetDOMAttribute (contentHandler, elementNode,
       
   264                             NW_XHTML_AttributeToken_name, &nameVal);
       
   265   
       
   266   /* find the 'href' attribute. */
       
   267   NW_XHTML_GetDOMAttribute (contentHandler, elementNode, 
       
   268                             NW_XHTML_AttributeToken_href, &hrefVal);
       
   269   if (hrefVal == NULL)
       
   270   {
       
   271     NW_XHTML_aElementHandler_getBaseTagUrl(contentHandler, &hrefVal);
       
   272   }
       
   273   if (hrefVal != NULL)
       
   274   {
       
   275     NW_Url_Schema_t scheme = NW_SCHEMA_INVALID;
       
   276     TBrowserStatusCode schemeStatus = KBrsrSuccess;
       
   277     NW_Text_Length_t charCount;
       
   278   
       
   279     /* There is an href attribute, so make it an active box. */
       
   280 
       
   281     storage = (NW_Ucs2*)
       
   282       NW_Text_GetUCS2Buffer (hrefVal, NW_Text_Flags_Aligned, &charCount,
       
   283                              &freeNeeded);
       
   284     if (!storage)
       
   285     {
       
   286       goto cleanup;
       
   287     }
       
   288 
       
   289     /* At this point, only interested if a scheme is present, not that the URL does not
       
   290        comply with RFC2396.  If there is a problem with the URL, it will be caught later
       
   291        when the anchor is selected/used.  The philosophy is to present everything to the user. */
       
   292     schemeStatus = NW_Url_GetScheme(storage, &scheme);
       
   293 
       
   294     if (scheme == NW_SCHEMA_INVALID && schemeStatus == KBrsrMalformedUrl)
       
   295     {
       
   296       goto cleanup;
       
   297     }
       
   298 
       
   299     eventHandler = 
       
   300         NW_HED_EventHandler_New (NW_HED_DocumentNodeOf (contentHandler), elementNode);
       
   301     box = NW_LMgr_ActiveContainerBox_New(0, 
       
   302                                          NW_LMgr_EventHandlerOf(eventHandler),
       
   303                                          NW_LMgr_ActionType_OpenLink);
       
   304     if (box)
       
   305     {
       
   306       NW_LMgr_ActiveContainerBox_SetName(box, nameVal, NW_TRUE);
       
   307       nameVal = NULL; // ownership of name object was transferred to box
       
   308     }
       
   309   }
       
   310 
       
   311 cleanup:
       
   312     if (hrefVal)
       
   313         {
       
   314         NW_Object_Delete(hrefVal);      
       
   315         }
       
   316     if (storage && freeNeeded)
       
   317         {
       
   318         NW_Str_Delete(storage);
       
   319         }
       
   320     if (nameVal)
       
   321         {
       
   322         NW_Object_Delete(nameVal);
       
   323         }
       
   324 
       
   325     return (box) ? NW_LMgr_BoxOf(box) : NULL;
       
   326 }
       
   327 
       
   328 /* -------------------------------------------------------------------------
       
   329 NW_XHTML_aElementHandler_HandleIModeEvents
       
   330 ------------------------------------------------------------------------- */
       
   331 static  
       
   332 NW_Uint8
       
   333 NW_XHTML_aElementHandler_HandleIModeEvents(const NW_XHTML_ElementHandler_t* elementHandler,
       
   334                                            NW_XHTML_ContentHandler_t* contentHandler,
       
   335                                            NW_DOM_ElementNode_t* elementNode,
       
   336                                            NW_Evt_Event_t* event)
       
   337     {
       
   338     NW_Text_t* url = NULL;
       
   339     NW_Text_t* cti = NULL;
       
   340     NW_Bool isCti = NW_FALSE;
       
   341     TBrowserStatusCode status = KBrsrFailure;
       
   342     NW_Url_Schema_t scheme = NW_SCHEMA_INVALID;
       
   343     NW_Ucs2* storage = NULL;
       
   344     NW_Uint8 freeNeeded = 0;
       
   345     NW_Text_Length_t charCount = 0;
       
   346     NW_XHTML_TelephonyServices_t* telServices;
       
   347     
       
   348     NW_REQUIRED_PARAM(elementHandler);
       
   349     
       
   350     telServices = (NW_XHTML_TelephonyServices_t*)(&NW_XHTML_TelephonyServices);
       
   351     
       
   352     /* find the 'cti' attribute and get its string value */
       
   353     NW_XHTML_GetDOMAttribute (contentHandler, elementNode, 
       
   354                               NW_XHTML_AttributeToken_cti, &cti);
       
   355     
       
   356     /*In models that support this function, the cti attribute takes
       
   357     precedence over the href attribute. Models that do not support this
       
   358     tag will not understand the cti attribute and will therefore use the
       
   359     href attribute. */
       
   360     if (cti == NULL)
       
   361         {
       
   362         /* find the 'href' attribute and get its string value */
       
   363         NW_XHTML_GetDOMAttribute (contentHandler, elementNode, 
       
   364                                   NW_XHTML_AttributeToken_href, &url);
       
   365         if (url == NULL)
       
   366             {
       
   367             NW_XHTML_aElementHandler_getBaseTagUrl(contentHandler, &url);
       
   368             }
       
   369         if (url == NULL)
       
   370             {
       
   371             return NW_LMgr_EventAbsorbed;
       
   372             }
       
   373         storage = (NW_Ucs2*)NW_Text_GetUCS2Buffer(url, NW_Text_Flags_Aligned,
       
   374                                                   &charCount, &freeNeeded);
       
   375         NW_Url_GetSchemeNoValidation(storage, &scheme);
       
   376         }
       
   377     
       
   378     /* handle Save To Phonebook event */
       
   379     if (NW_Object_Core_GetClass (event) == &NW_XHTML_SaveToPhoneBkEvent_Class)
       
   380         {
       
   381         if (scheme == NW_SCHEMA_MAILTO)
       
   382             {
       
   383             NW_Text_t* email = NULL;
       
   384             NW_Text_t* name = NULL;
       
   385             NW_XHTML_GetDOMAttribute (contentHandler, elementNode, 
       
   386                                       NW_XHTML_AttributeToken_email, &email);
       
   387             NW_XHTML_GetDOMAttribute (contentHandler, elementNode, 
       
   388                                       NW_XHTML_AttributeToken_memoryname, &name);
       
   389             
       
   390             if (email == NULL)
       
   391                 {
       
   392                 status = NW_XHTML_TelephonyServices_Mailto_SaveToPhoneBook(telServices, contentHandler,
       
   393                                                                            url, name, NW_FALSE);
       
   394                 }
       
   395             else
       
   396                 {
       
   397                 status = NW_XHTML_TelephonyServices_Mailto_SaveToPhoneBook(telServices, contentHandler,
       
   398                                                                            email, name, NW_TRUE);
       
   399                 }
       
   400             NW_Object_Delete(url);
       
   401             NW_Object_Delete(email);
       
   402             NW_Object_Delete(name);
       
   403 
       
   404             return NW_LMgr_EventAbsorbed;
       
   405             }
       
   406         else
       
   407             /*if (NW_Object_Core_GetClass (event) == &NW_XHTML_SaveToPhoneBkEvent_Class)*/
       
   408             {
       
   409             NW_Text_t* name = NULL;
       
   410             NW_Text_t* email = NULL;
       
   411             
       
   412             status = NW_XHTML_GetDOMAttribute(contentHandler, elementNode, 
       
   413                                               NW_XHTML_AttributeToken_telbook, &name);
       
   414             
       
   415             if (status != KBrsrSuccess) 
       
   416                 {
       
   417                 NW_XHTML_GetDOMAttribute(contentHandler, elementNode, 
       
   418                                          NW_XHTML_AttributeToken_memoryname, &name);
       
   419                 }
       
   420             
       
   421             NW_XHTML_GetDOMAttribute(contentHandler, elementNode, 
       
   422                                      NW_XHTML_AttributeToken_email, &email);
       
   423             if (cti != NULL)
       
   424                 {
       
   425                 isCti = NW_TRUE;
       
   426                 status = NW_XHTML_TelephonyServices_SaveToPhoneBook(telServices, contentHandler,
       
   427                                                                     cti, name, email, isCti);
       
   428                 }
       
   429             else
       
   430                 {
       
   431                 status = NW_XHTML_TelephonyServices_SaveToPhoneBook(telServices, contentHandler,
       
   432                                                                     url, name, email, isCti);
       
   433                 }
       
   434             
       
   435             NW_Object_Delete(cti);
       
   436             NW_Object_Delete(url);
       
   437             NW_Object_Delete(name);
       
   438             NW_Object_Delete(email);
       
   439 
       
   440             return NW_LMgr_EventAbsorbed;
       
   441             }
       
   442         }
       
   443     
       
   444     if (freeNeeded) 
       
   445         {
       
   446         NW_Str_Delete(storage);
       
   447         }
       
   448     
       
   449     /* handle ActiveEvent/AccessKeyEvent */
       
   450     if (cti != NULL) /* if cti attribute is specified use cti to make call */
       
   451         {
       
   452         NW_Object_Delete(url);   /* cti will be used.  url is not needed. */
       
   453         url = NULL;
       
   454         
       
   455         status = NW_XHTML_TelephonyServices_MakeCall(telServices, contentHandler, cti, NW_TRUE);
       
   456         if (status != KBrsrSuccess) 
       
   457             {
       
   458             NW_HED_DocumentNode_HandleError(contentHandler,
       
   459                                             NW_HED_ContentHandler_GetUrlRequest(contentHandler), 
       
   460                                             BRSR_STAT_CLASS_GENERAL, (NW_WaeError_t)status);                                  
       
   461             }
       
   462         NW_Object_Delete(cti);
       
   463 
       
   464         return NW_LMgr_EventAbsorbed;
       
   465         }
       
   466     
       
   467     /* handle tel:// scheme */
       
   468     if (scheme == NW_SCHEMA_TEL)
       
   469         {
       
   470         status = NW_XHTML_TelephonyServices_MakeCall(telServices, contentHandler, url, NW_FALSE);
       
   471         if (status != KBrsrSuccess)
       
   472             {
       
   473             NW_HED_DocumentNode_HandleError(contentHandler,
       
   474                                             NW_HED_ContentHandler_GetUrlRequest(contentHandler), 
       
   475                                             BRSR_STAT_CLASS_GENERAL, (NW_WaeError_t)status);                                  
       
   476             }
       
   477         NW_Object_Delete(url);
       
   478 
       
   479         return NW_LMgr_EventAbsorbed;
       
   480         }
       
   481     
       
   482     NW_Object_Delete(url);
       
   483 
       
   484     return NW_LMgr_EventNotAbsorbed;
       
   485 }
       
   486 
       
   487 /* ------------------------------------------------------------------------- *
       
   488    class definition
       
   489  * ------------------------------------------------------------------------- */
       
   490 
       
   491 /* ------------------------------------------------------------------------- */
       
   492 const
       
   493 NW_XHTML_aElementHandler_Class_t NW_XHTML_aElementHandler_Class = {
       
   494   { /* NW_Object_Core              */
       
   495     /* super                       */ &NW_XHTML_ElementHandler_Class,
       
   496     /* queryInterface              */ _NW_Object_Core_QueryInterface
       
   497   },
       
   498   { /* NW_XHTML_ElementHandler     */
       
   499     /* initialize                  */ _NW_XHTML_aElementHandler_Initialize,
       
   500     /* createBoxTree               */ _NW_XHTML_aElementHandler_CreateBoxTree,
       
   501     /* processEvent                */ _NW_XHTML_aElementHandler_ProcessEvent
       
   502   },
       
   503   { /* NW_XHTML_aElementHandler    */
       
   504     /* unused                      */ NW_Object_Unused
       
   505   }
       
   506 };
       
   507 
       
   508 /* ------------------------------------------------------------------------- *
       
   509    singleton definition
       
   510  * ------------------------------------------------------------------------- */
       
   511 
       
   512 /* ------------------------------------------------------------------------- */
       
   513 const NW_XHTML_aElementHandler_t NW_XHTML_aElementHandler = {
       
   514   { { &NW_XHTML_aElementHandler_Class } }
       
   515 };
       
   516 
       
   517 /* ------------------------------------------------------------------------- *
       
   518    virtual methods
       
   519  * ------------------------------------------------------------------------- */
       
   520 
       
   521 /* ------------------------------------------------------------------------- */
       
   522 TBrowserStatusCode
       
   523 _NW_XHTML_aElementHandler_Initialize (const NW_XHTML_ElementHandler_t* elementHandler,
       
   524                                           NW_XHTML_ContentHandler_t* contentHandler,
       
   525                                           NW_DOM_ElementNode_t* elementNode)
       
   526 {
       
   527   NW_REQUIRED_PARAM(elementHandler);
       
   528 
       
   529   // special handling if a is the last part of the chunk: 
       
   530   // leave select to be processed in the next chunk
       
   531   // in case this is the last chunk, we need to process a in this chunk
       
   532   NW_XHTML_ElementHandler_NextSiblingExists (contentHandler, elementNode, NW_TRUE);
       
   533 
       
   534   return KBrsrSuccess;
       
   535 }
       
   536 
       
   537 /* ------------------------------------------------------------------------- */
       
   538 TBrowserStatusCode
       
   539 _NW_XHTML_aElementHandler_CreateBoxTree (const NW_XHTML_ElementHandler_t* elementHandler,
       
   540                                          NW_XHTML_ContentHandler_t* contentHandler,
       
   541                                          NW_DOM_ElementNode_t* elementNode,
       
   542                                          NW_LMgr_ContainerBox_t* parentBox)
       
   543 {
       
   544   NW_LMgr_Box_t* box = NULL;
       
   545   NW_Text_t* url = NULL;
       
   546   NW_LMgr_TextBox_t* textBox = NULL;
       
   547 
       
   548   NW_TRY (status) 
       
   549   {
       
   550     // special handling if a is the last node of the chunck: 
       
   551     // leave it to be processed in the next chunck
       
   552     if (!NW_XHTML_ElementHandler_NextSiblingExists (contentHandler, elementNode, NW_FALSE))
       
   553     {
       
   554       NW_THROW_SUCCESS (status);
       
   555     }
       
   556     
       
   557     if ( NW_XHTML_ContentHandler_GetHtmlSubset(contentHandler) == 
       
   558         NW_XHTML_CONTENTHANDLER_IMODEHTMLEXT)
       
   559     {
       
   560       box = NW_XHTML_aElementHandler_ImodeCreateBox(elementHandler, contentHandler,
       
   561                                                     elementNode);
       
   562     }
       
   563     else
       
   564     {
       
   565       box = NW_XHTML_aElementHandler_CreateBox(elementHandler, contentHandler,
       
   566                         elementNode);
       
   567     }
       
   568     if (box == NULL)
       
   569     {
       
   570       /* either tel was invalid or there was no href attribute */
       
   571       box = (NW_LMgr_Box_t*)NW_LMgr_ContainerBox_New(0);
       
   572       NW_THROW_OOM_ON_NULL (box, status);
       
   573     }
       
   574 
       
   575       /* Add the box to the tree */
       
   576     status = NW_LMgr_ContainerBox_AddChild (parentBox, box);
       
   577     _NW_THROW_ON_ERROR (status);
       
   578 
       
   579     /* apply common attributes and styles */
       
   580     status = NW_XHTML_ElementHandler_ApplyStyles (elementHandler, contentHandler, elementNode, &box, NULL);
       
   581 
       
   582     NW_THROW_ON (status, KBrsrOutOfMemory);
       
   583 
       
   584     // Apply Styles will take care of replacing container box if display was block, list-item or marquee.
       
   585     // In case of 'display:none' or an error it removes the container box. That's why we check box
       
   586     if (box == NULL)
       
   587     {
       
   588       NW_THROW_SUCCESS (status);
       
   589     }
       
   590 
       
   591     parentBox = NW_LMgr_ContainerBoxOf (box);
       
   592 
       
   593     /* invoke our superclass for completion */
       
   594     status = _NW_XHTML_ElementHandler_CreateBoxTree(elementHandler, contentHandler, elementNode, parentBox);
       
   595 
       
   596     // if the <a href="foo.html"></a> is empty, then add the href as link text.
       
   597     if( parentBox && NW_Object_IsInstanceOf( parentBox, &NW_LMgr_ActiveContainerBox_Class ) )
       
   598       {
       
   599       // child count = 0 means that we have not added any textbox to this container yet. add the href then.
       
   600       if( NW_LMgr_ContainerBox_GetChildCount( parentBox ) == 0 && NW_LMgr_ActiveContainerBoxOf( parentBox )->hrefAttr )
       
   601         {
       
   602         url = NW_Text_Copy( NW_LMgr_ActiveContainerBoxOf( parentBox )->hrefAttr, NW_TRUE );
       
   603         NW_THROW_OOM_ON_NULL( url, status );
       
   604         //
       
   605         // create the TextBox and insert it into our parent 
       
   606         textBox = (NW_LMgr_TextBox_t*)NW_LMgr_TextBox_New( 0, url );
       
   607         NW_THROW_OOM_ON_NULL( textBox, status );
       
   608         url = NULL;
       
   609 
       
   610         status = NW_LMgr_ContainerBox_AddChild( parentBox, NW_LMgr_BoxOf( textBox ) );
       
   611         _NW_THROW_ON_ERROR( status );
       
   612         textBox = NULL;
       
   613         }
       
   614       }
       
   615     }
       
   616   NW_CATCH (status) 
       
   617   {
       
   618     if(box) 
       
   619     {
       
   620       NW_Object_Delete(box);
       
   621     }
       
   622     NW_Object_Delete( url );
       
   623     NW_Object_Delete( textBox );
       
   624   }
       
   625   NW_FINALLY 
       
   626   {
       
   627    return status;
       
   628   } NW_END_TRY
       
   629 }
       
   630 
       
   631 /* ------------------------------------------------------------------------- */
       
   632 
       
   633 NW_Uint8
       
   634 _NW_XHTML_aElementHandler_ProcessEvent (const NW_XHTML_ElementHandler_t* elementHandler,
       
   635                                         NW_XHTML_ContentHandler_t* contentHandler,
       
   636                                         NW_DOM_ElementNode_t* elementNode,
       
   637                                         NW_LMgr_Box_t* box,
       
   638                                         NW_Evt_Event_t* event)
       
   639 {
       
   640   NW_Text_t* url = NULL;
       
   641   TBrowserStatusCode status = KBrsrNotFound;
       
   642   NW_HED_DocumentRoot_t* documentRoot = 
       
   643     (NW_HED_DocumentRoot_t*)NW_HED_DocumentNode_GetRootNode (contentHandler);
       
   644 
       
   645   NW_REQUIRED_PARAM(box);
       
   646 
       
   647   /* we are really only interested in the following list of events */
       
   648   if ((NW_Object_Core_GetClass (event) != &NW_Evt_ActivateEvent_Class) &&
       
   649       (NW_Object_Core_GetClass (event) != &NW_Evt_AccessKeyEvent_Class) &&
       
   650       (NW_Object_Core_GetClass (event) != &NW_Evt_FocusEvent_Class) &&
       
   651       (NW_Object_Core_GetClass (event) != &NW_XHTML_SaveToPhoneBkEvent_Class))
       
   652   {
       
   653     return NW_LMgr_EventNotAbsorbed;
       
   654   }
       
   655 
       
   656   if(NW_Object_Core_GetClass (event) == &NW_Evt_FocusEvent_Class) {
       
   657     return NW_LMgr_EventAbsorbed;
       
   658   }
       
   659 
       
   660   /* Process IMODE events */
       
   661   if (NW_XHTML_ContentHandler_GetHtmlSubset(contentHandler) == 
       
   662        NW_XHTML_CONTENTHANDLER_IMODEHTMLEXT)
       
   663   {
       
   664     if(NW_XHTML_aElementHandler_HandleIModeEvents(elementHandler, contentHandler, 
       
   665                                                elementNode, event) == NW_LMgr_EventAbsorbed)
       
   666       return NW_LMgr_EventAbsorbed;
       
   667   }
       
   668 
       
   669   if(NW_LMgr_ActiveContainerBoxOf(box)->hrefAttr != NULL)
       
   670   {
       
   671     url = NW_Text_Copy(NW_LMgr_ActiveContainerBoxOf(box)->hrefAttr, NW_TRUE);
       
   672   }
       
   673   else
       
   674   {
       
   675     /* find the 'href' attribute and get its string value */
       
   676     NW_XHTML_GetDOMAttribute (contentHandler, 
       
   677                                   elementNode, 
       
   678                                   NW_XHTML_AttributeToken_href, &url);
       
   679   }
       
   680 
       
   681   if (url == NULL)
       
   682   {
       
   683     NW_XHTML_aElementHandler_getBaseTagUrl(contentHandler, &url);
       
   684   }
       
   685   if (url == NULL) {
       
   686     return NW_LMgr_EventAbsorbed;
       
   687   }
       
   688 
       
   689 
       
   690   if(status == KBrsrNotFound)
       
   691   {
       
   692     // if the url starts with javascript: then delegate the activate event to ecmaengine
       
   693     if(NW_Str_Strnicmp((const NW_Ucs2*) url->storage, (const NW_Ucs2*) NW_STR("javascript:"), 11) == 0)     {
       
   694       NW_Bool urlTextFreeNeeded;
       
   695       NW_Text_Length_t urlTextLength;
       
   696       NW_Ucs2* urlStorage;
       
   697       urlStorage = NW_Text_GetUCS2Buffer (url, 0, &urlTextLength, &urlTextFreeNeeded);
       
   698       if(urlTextFreeNeeded){
       
   699         NW_Mem_Free ((NW_Ucs2*) urlStorage);
       
   700       }                       
       
   701     }
       
   702     else
       
   703         {
       
   704 #if !defined(__SERIES60_28__) && !defined(__SERIES60_27__)
       
   705         NW_Text_t* target = NULL;
       
   706         NW_XHTML_GetDOMAttribute (contentHandler, elementNode, NW_XHTML_AttributeToken_target, &target);
       
   707         TBool newWindow = EFalse;
       
   708 		if (target != NULL && target->characterCount == 0)
       
   709         	{
       
   710         	NW_Object_Delete(target);
       
   711         	target = NULL;
       
   712         	}
       
   713         if (target == NULL)
       
   714         	{
       
   715         	NW_XHTML_ContentHandler_GetBaseTagTarget (contentHandler, &target);
       
   716         	}
       
   717         if (target != NULL)
       
   718             {
       
   719             // If the target attribute exists, and it is not an empty string, and 
       
   720             // it is not "_self", open the url in a new window
       
   721             NW_Bool targetTextFreeNeeded = NW_FALSE;;
       
   722             NW_Ucs2* targetStorage;
       
   723             NW_Text_Length_t targetTextLength;
       
   724             _LIT(KSelf, "_self");
       
   725             targetStorage = NW_Text_GetUCS2Buffer (target, NW_Text_Flags_NullTerminated,
       
   726                 &targetTextLength, &targetTextFreeNeeded);
       
   727             // Check that the target attribute is not empty
       
   728             TPtrC targetPtr(targetStorage, targetTextLength);
       
   729             if (targetTextLength > 0 && targetPtr.CompareF(KSelf) != 0)
       
   730                 {
       
   731                 status = NW_XHTML_ContentHandler_WindowOpen(contentHandler, url, target);
       
   732                 newWindow = ETrue;
       
   733                 }
       
   734             if (targetTextFreeNeeded)
       
   735                 {
       
   736                 NW_Mem_Free(targetStorage);
       
   737                 }
       
   738             NW_Object_Delete(target);
       
   739             }
       
   740         if (!newWindow)
       
   741 #endif
       
   742             {
       
   743               // copy the Url on to the content handler 
       
   744               NW_XHTML_ContentHandler_SetReferrerUrl(contentHandler);
       
   745               // mailto and wtai scheme are now being processed by the default scheme dispatcher
       
   746               /* load the content */
       
   747               status = NW_XHTML_ContentHandler_StartLoad (contentHandler, NW_TextOf (url), 
       
   748               NW_HED_UrlRequest_Reason_DocLoad, (void *) &NW_WmlScript_ContentHandler_Class, 
       
   749               NW_UrlRequest_Type_Any);
       
   750             }
       
   751         }
       
   752   }
       
   753 
       
   754   NW_Object_Delete(url);
       
   755 
       
   756   if (status != KBrsrSuccess && status != KBrsrHedContentDispatched) {
       
   757     NW_HED_DocumentNode_HandleError (contentHandler,
       
   758         NW_HED_ContentHandler_GetUrlRequest (contentHandler), 
       
   759         BRSR_STAT_CLASS_GENERAL, (NW_WaeError_t) status);
       
   760   }
       
   761 
       
   762   /* we absorbed the event! */
       
   763   return NW_LMgr_EventAbsorbed;
       
   764 }
       
   765 
       
   766 /*
       
   767  Get the URL in base tag defined in header, this value can be used to combine with 
       
   768  relative URL to figure out the absolute URL. 
       
   769 */
       
   770 TBrowserStatusCode
       
   771 NW_XHTML_aElementHandler_getBaseTagUrl (NW_XHTML_ContentHandler_t* contentHandler,
       
   772                                           NW_Text_t** hrefVal)
       
   773 {
       
   774   NW_DOM_Node_t* baseElement;
       
   775   NW_String_t href;
       
   776 
       
   777   NW_ASSERT (hrefVal);
       
   778   
       
   779   /* get the base url as found in the "base" element */
       
   780   baseElement = NW_HED_DomHelper_FindElement (&contentHandler->domHelper, NW_HED_DomTree_GetRootNode (
       
   781     contentHandler->domTree), 3, NW_XHTML_ElementToken_base, 0, NULL);
       
   782   
       
   783   if (baseElement != NULL) {
       
   784     TBrowserStatusCode status = NW_HED_DomHelper_GetAttributeValue (&contentHandler->domHelper, baseElement, 
       
   785       NW_XHTML_AttributeToken_href, &href);
       
   786     
       
   787     if (status == KBrsrSuccess) {
       
   788       *hrefVal = (NW_Text_t*) NW_Text_UCS2_New (href.storage, 0, NW_Text_Flags_TakeOwnership);
       
   789     }
       
   790   } 
       
   791   return KBrsrSuccess;
       
   792 }