Back to index

lightning-sunbird  0.9+nobinonly
nsHTMLAreaElement.cpp
Go to the documentation of this file.
00001 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
00002 /* vim:set tw=80 expandtab softtabstop=2 ts=2 sw=2: */
00003 /* ***** BEGIN LICENSE BLOCK *****
00004  * Version: MPL 1.1/GPL 2.0/LGPL 2.1
00005  *
00006  * The contents of this file are subject to the Mozilla Public License Version
00007  * 1.1 (the "License"); you may not use this file except in compliance with
00008  * the License. You may obtain a copy of the License at
00009  * http://www.mozilla.org/MPL/
00010  *
00011  * Software distributed under the License is distributed on an "AS IS" basis,
00012  * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
00013  * for the specific language governing rights and limitations under the
00014  * License.
00015  *
00016  * The Original Code is Mozilla Communicator client code.
00017  *
00018  * The Initial Developer of the Original Code is
00019  * Netscape Communications Corporation.
00020  * Portions created by the Initial Developer are Copyright (C) 1998
00021  * the Initial Developer. All Rights Reserved.
00022  *
00023  * Contributor(s):
00024  *
00025  * Alternatively, the contents of this file may be used under the terms of
00026  * either of the GNU General Public License Version 2 or later (the "GPL"),
00027  * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
00028  * in which case the provisions of the GPL or the LGPL are applicable instead
00029  * of those above. If you wish to allow use of your version of this file only
00030  * under the terms of either the GPL or the LGPL, and not to allow others to
00031  * use your version of this file under the terms of the MPL, indicate your
00032  * decision by deleting the provisions above and replace them with the notice
00033  * and other provisions required by the GPL or the LGPL. If you do not delete
00034  * the provisions above, a recipient may use your version of this file under
00035  * the terms of any one of the MPL, the GPL or the LGPL.
00036  *
00037  * ***** END LICENSE BLOCK ***** */
00038 #include "nsIDOMHTMLAreaElement.h"
00039 #include "nsIDOMNSHTMLAreaElement.h"
00040 #include "nsIDOMEventReceiver.h"
00041 #include "nsGenericHTMLElement.h"
00042 #include "nsILink.h"
00043 #include "nsIPresShell.h"
00044 #include "nsHTMLAtoms.h"
00045 #include "nsStyleConsts.h"
00046 #include "nsPresContext.h"
00047 #include "nsIEventStateManager.h"
00048 #include "nsIURL.h"
00049 #include "nsNetUtil.h"
00050 #include "nsReadableUtils.h"
00051 #include "nsIDocument.h"
00052 
00053 class nsHTMLAreaElement : public nsGenericHTMLElement,
00054                           public nsIDOMHTMLAreaElement,
00055                           public nsIDOMNSHTMLAreaElement,
00056                           public nsILink
00057 {
00058 public:
00059   nsHTMLAreaElement(nsINodeInfo *aNodeInfo);
00060   virtual ~nsHTMLAreaElement();
00061 
00062   // nsISupports
00063   NS_DECL_ISUPPORTS_INHERITED
00064 
00065   // nsIDOMNode
00066   NS_FORWARD_NSIDOMNODE_NO_CLONENODE(nsGenericHTMLElement::)
00067 
00068   // nsIDOMElement
00069   NS_FORWARD_NSIDOMELEMENT(nsGenericHTMLElement::)
00070 
00071   // nsIDOMHTMLElement
00072   NS_FORWARD_NSIDOMHTMLELEMENT(nsGenericHTMLElement::)
00073 
00074   // nsIDOMHTMLAreaElement
00075   NS_DECL_NSIDOMHTMLAREAELEMENT
00076 
00077   // nsIDOMNSHTMLAreaElement
00078   NS_DECL_NSIDOMNSHTMLAREAELEMENT
00079 
00080   // nsILink
00081   NS_IMETHOD GetLinkState(nsLinkState &aState);
00082   NS_IMETHOD SetLinkState(nsLinkState aState);
00083   NS_IMETHOD GetHrefURI(nsIURI** aURI);
00084   NS_IMETHOD LinkAdded() { return NS_OK; }
00085   NS_IMETHOD LinkRemoved() { return NS_OK; }
00086 
00087   virtual nsresult HandleDOMEvent(nsPresContext* aPresContext,
00088                                   nsEvent* aEvent, nsIDOMEvent** aDOMEvent,
00089                                   PRUint32 aFlags,
00090                                   nsEventStatus* aEventStatus);
00091   virtual void SetFocus(nsPresContext* aPresContext);
00092 
00093   virtual nsresult BindToTree(nsIDocument* aDocument, nsIContent* aParent,
00094                               nsIContent* aBindingParent,
00095                               PRBool aCompileEventHandlers);
00096   virtual void UnbindFromTree(PRBool aDeep = PR_TRUE,
00097                               PRBool aNullParent = PR_TRUE);
00098   nsresult SetAttr(PRInt32 aNameSpaceID, nsIAtom* aName,
00099                    const nsAString& aValue, PRBool aNotify)
00100   {
00101     return SetAttr(aNameSpaceID, aName, nsnull, aValue, aNotify);
00102   }
00103   virtual nsresult SetAttr(PRInt32 aNameSpaceID, nsIAtom* aName,
00104                            nsIAtom* aPrefix, const nsAString& aValue,
00105                            PRBool aNotify);
00106   virtual nsresult UnsetAttr(PRInt32 aNameSpaceID, nsIAtom* aAttribute,
00107                              PRBool aNotify);
00108 
00109 protected:
00110   // The cached visited state
00111   nsLinkState mLinkState;
00112 };
00113 
00114 
00115 NS_IMPL_NS_NEW_HTML_ELEMENT(Area)
00116 
00117 
00118 nsHTMLAreaElement::nsHTMLAreaElement(nsINodeInfo *aNodeInfo)
00119   : nsGenericHTMLElement(aNodeInfo),
00120     mLinkState(eLinkState_Unknown)
00121 {
00122 }
00123 
00124 nsHTMLAreaElement::~nsHTMLAreaElement()
00125 {
00126 }
00127 
00128 NS_IMPL_ADDREF_INHERITED(nsHTMLAreaElement, nsGenericElement) 
00129 NS_IMPL_RELEASE_INHERITED(nsHTMLAreaElement, nsGenericElement) 
00130 
00131 
00132 // QueryInterface implementation for nsHTMLAreaElement
00133 NS_HTML_CONTENT_INTERFACE_MAP_BEGIN(nsHTMLAreaElement, nsGenericHTMLElement)
00134   NS_INTERFACE_MAP_ENTRY(nsIDOMHTMLAreaElement)
00135   NS_INTERFACE_MAP_ENTRY(nsIDOMNSHTMLAreaElement)
00136   NS_INTERFACE_MAP_ENTRY(nsILink)
00137   NS_INTERFACE_MAP_ENTRY_CONTENT_CLASSINFO(HTMLAreaElement)
00138 NS_HTML_CONTENT_INTERFACE_MAP_END
00139 
00140 
00141 NS_IMPL_DOM_CLONENODE(nsHTMLAreaElement)
00142 
00143 
00144 NS_IMPL_STRING_ATTR(nsHTMLAreaElement, AccessKey, accesskey)
00145 NS_IMPL_STRING_ATTR(nsHTMLAreaElement, Alt, alt)
00146 NS_IMPL_STRING_ATTR(nsHTMLAreaElement, Coords, coords)
00147 NS_IMPL_URI_ATTR(nsHTMLAreaElement, Href, href)
00148 NS_IMPL_BOOL_ATTR(nsHTMLAreaElement, NoHref, nohref)
00149 NS_IMPL_STRING_ATTR(nsHTMLAreaElement, Shape, shape)
00150 NS_IMPL_INT_ATTR_DEFAULT_VALUE(nsHTMLAreaElement, TabIndex, tabindex, 0)
00151 
00152 NS_IMETHODIMP
00153 nsHTMLAreaElement::GetTarget(nsAString& aValue)
00154 {
00155   aValue.Truncate();
00156 
00157   nsresult rv;
00158   rv = GetAttr(kNameSpaceID_None, nsHTMLAtoms::target, aValue);
00159   if (rv == NS_CONTENT_ATTR_NOT_THERE) {
00160     GetBaseTarget(aValue);
00161   }
00162   return NS_OK;
00163 }
00164 
00165 NS_IMETHODIMP
00166 nsHTMLAreaElement::SetTarget(const nsAString& aValue)
00167 {
00168   return SetAttr(kNameSpaceID_None, nsHTMLAtoms::target, aValue, PR_TRUE);
00169 }
00170 
00171 nsresult
00172 nsHTMLAreaElement::HandleDOMEvent(nsPresContext* aPresContext,
00173                                   nsEvent* aEvent,
00174                                   nsIDOMEvent** aDOMEvent,
00175                                   PRUint32 aFlags,
00176                                   nsEventStatus* aEventStatus)
00177 {
00178   return HandleDOMEventForAnchors(aPresContext, aEvent, aDOMEvent, 
00179                                   aFlags, aEventStatus);
00180 }
00181 
00182 void
00183 nsHTMLAreaElement::SetFocus(nsPresContext* aPresContext)
00184 {
00185   if (!aPresContext)
00186     return;
00187 
00188   aPresContext->EventStateManager()->SetContentState(this,
00189                                                      NS_EVENT_STATE_FOCUS);
00190     
00191   // Make sure the presentation is up-to-date
00192   nsIDocument* doc = GetCurrentDoc();
00193   if (doc) {
00194     doc->FlushPendingNotifications(Flush_Layout);
00195   }
00196 
00197   nsIPresShell *presShell = aPresContext->GetPresShell();
00198 
00199   if (presShell) {
00200     nsIFrame* frame = nsnull;
00201     presShell->GetPrimaryFrameFor(this, &frame);
00202     if (frame) {
00203       presShell->ScrollFrameIntoView(frame, NS_PRESSHELL_SCROLL_ANYWHERE,
00204                                      NS_PRESSHELL_SCROLL_ANYWHERE);
00205     }
00206   }
00207 }
00208 
00209 nsresult
00210 nsHTMLAreaElement::BindToTree(nsIDocument* aDocument, nsIContent* aParent,
00211                               nsIContent* aBindingParent,
00212                               PRBool aCompileEventHandlers)
00213 {
00214   nsresult rv = nsGenericHTMLElement::BindToTree(aDocument, aParent,
00215                                                  aBindingParent,
00216                                                  aCompileEventHandlers);
00217   NS_ENSURE_SUCCESS(rv, rv);
00218 
00219   if (aDocument) {
00220     RegUnRegAccessKey(PR_TRUE);
00221   }
00222 
00223   return rv;
00224 }
00225 
00226 void
00227 nsHTMLAreaElement::UnbindFromTree(PRBool aDeep, PRBool aNullParent)
00228 {
00229   if (IsInDoc()) {
00230     RegUnRegAccessKey(PR_FALSE);
00231     GetCurrentDoc()->ForgetLink(this);
00232     // If this link is ever reinserted into a document, it might
00233     // be under a different xml:base, so forget the cached state now
00234     mLinkState = eLinkState_Unknown;
00235   }
00236 
00237   nsGenericHTMLElement::UnbindFromTree(aDeep, aNullParent);
00238 }
00239 
00240 nsresult
00241 nsHTMLAreaElement::SetAttr(PRInt32 aNameSpaceID, nsIAtom* aName,
00242                            nsIAtom* aPrefix, const nsAString& aValue,
00243                            PRBool aNotify)
00244 {
00245   if (aName == nsHTMLAtoms::accesskey && aNameSpaceID == kNameSpaceID_None) {
00246     RegUnRegAccessKey(PR_FALSE);
00247   }
00248 
00249   if (aName == nsHTMLAtoms::href && aNameSpaceID == kNameSpaceID_None) {
00250     nsIDocument* doc = GetCurrentDoc();
00251     if (doc) {
00252       doc->ForgetLink(this);
00253       // The change to 'href' will cause style reresolution which will
00254       // eventually recompute the link state and re-add this element
00255       // to the link map if necessary.
00256     }
00257     SetLinkState(eLinkState_Unknown);
00258   }
00259 
00260   nsresult rv =
00261     nsGenericHTMLElement::SetAttr(aNameSpaceID, aName, aPrefix, aValue, aNotify);
00262 
00263   if (aName == nsHTMLAtoms::accesskey && aNameSpaceID == kNameSpaceID_None &&
00264       !aValue.IsEmpty()) {
00265     RegUnRegAccessKey(PR_TRUE);
00266   }
00267 
00268   return rv;
00269 }
00270 
00271 nsresult
00272 nsHTMLAreaElement::UnsetAttr(PRInt32 aNameSpaceID, nsIAtom* aAttribute,
00273                              PRBool aNotify)
00274 {
00275   if (aAttribute == nsHTMLAtoms::accesskey &&
00276       aNameSpaceID == kNameSpaceID_None) {
00277     RegUnRegAccessKey(PR_FALSE);
00278   }
00279 
00280   return nsGenericHTMLElement::UnsetAttr(aNameSpaceID, aAttribute, aNotify);
00281 }
00282 
00283 NS_IMETHODIMP    
00284 nsHTMLAreaElement::GetProtocol(nsAString& aProtocol)
00285 {
00286   nsAutoString href;
00287   
00288   nsresult rv = GetHref(href);
00289   if (NS_FAILED(rv))
00290     return rv;
00291 
00292   // XXX this should really use GetHrefURI and not do so much string stuff
00293   return GetProtocolFromHrefString(href, aProtocol, GetOwnerDoc());
00294 }
00295 
00296 NS_IMETHODIMP
00297 nsHTMLAreaElement::SetProtocol(const nsAString& aProtocol)
00298 {
00299   nsAutoString href, new_href;
00300   nsresult rv = GetHref(href);
00301   if (NS_FAILED(rv))
00302     return rv;
00303   
00304   rv = SetProtocolInHrefString(href, aProtocol, new_href);
00305   if (NS_FAILED(rv))
00306     // Ignore failures to be compatible with NS4
00307     return NS_OK;
00308 
00309   return SetHref(new_href);
00310 }
00311 
00312 NS_IMETHODIMP    
00313 nsHTMLAreaElement::GetHost(nsAString& aHost)
00314 {
00315   nsAutoString href;
00316   
00317   nsresult rv = GetHref(href);
00318   if (NS_FAILED(rv))
00319     return rv;
00320 
00321   return GetHostFromHrefString(href, aHost);
00322 }
00323 
00324 NS_IMETHODIMP
00325 nsHTMLAreaElement::SetHost(const nsAString& aHost)
00326 {
00327   nsAutoString href, new_href;
00328   nsresult rv = GetHref(href);
00329   if (NS_FAILED(rv))
00330     return rv;
00331 
00332   rv = SetHostInHrefString(href, aHost, new_href);
00333   if (NS_FAILED(rv))
00334     // Ignore failures to be compatible with NS4
00335     return NS_OK;
00336 
00337   return SetHref(new_href);
00338 }
00339 
00340 NS_IMETHODIMP    
00341 nsHTMLAreaElement::GetHostname(nsAString& aHostname)
00342 {
00343   nsAutoString href;
00344   nsresult rv = GetHref(href);
00345   if (NS_FAILED(rv))
00346     return rv;
00347 
00348   return GetHostnameFromHrefString(href, aHostname);
00349 }
00350 
00351 NS_IMETHODIMP
00352 nsHTMLAreaElement::SetHostname(const nsAString& aHostname)
00353 {
00354   nsAutoString href, new_href;
00355   nsresult rv = GetHref(href);
00356   if (NS_FAILED(rv))
00357     return rv;
00358 
00359   rv = SetHostnameInHrefString(href, aHostname, new_href);
00360   if (NS_FAILED(rv))
00361     // Ignore failures to be compatible with NS4
00362     return NS_OK;
00363   
00364   return SetHref(new_href);
00365 }
00366 
00367 NS_IMETHODIMP    
00368 nsHTMLAreaElement::GetPathname(nsAString& aPathname)
00369 {
00370   nsAutoString href;
00371  
00372   nsresult rv = GetHref(href);
00373   if (NS_FAILED(rv))
00374     return rv;
00375 
00376   return GetPathnameFromHrefString(href, aPathname);
00377 }
00378 
00379 NS_IMETHODIMP
00380 nsHTMLAreaElement::SetPathname(const nsAString& aPathname)
00381 {
00382   nsAutoString href, new_href;
00383   nsresult rv = GetHref(href);
00384   if (NS_FAILED(rv))
00385     return rv;
00386 
00387   rv = SetPathnameInHrefString(href, aPathname, new_href);
00388   if (NS_FAILED(rv))
00389     // Ignore failures to be compatible with NS4
00390     return NS_OK;
00391 
00392   return SetHref(new_href);
00393 }
00394 
00395 NS_IMETHODIMP    
00396 nsHTMLAreaElement::GetSearch(nsAString& aSearch)
00397 {
00398   nsAutoString href;
00399 
00400   nsresult rv = GetHref(href);
00401   if (NS_FAILED(rv))
00402     return rv;
00403 
00404   return GetSearchFromHrefString(href, aSearch);
00405 }
00406 
00407 NS_IMETHODIMP
00408 nsHTMLAreaElement::SetSearch(const nsAString& aSearch)
00409 {
00410   nsAutoString href, new_href;
00411   nsresult rv = GetHref(href);
00412 
00413   if (NS_FAILED(rv))
00414     return rv;
00415 
00416   rv = SetSearchInHrefString(href, aSearch, new_href);
00417   if (NS_FAILED(rv))
00418     // Ignore failures to be compatible with NS4
00419     return NS_OK;
00420 
00421   return SetHref(new_href);
00422 }
00423 
00424 NS_IMETHODIMP
00425 nsHTMLAreaElement::GetPort(nsAString& aPort)
00426 {
00427   nsAutoString href;
00428   
00429   nsresult rv = GetHref(href);
00430   if (NS_FAILED(rv))
00431     return rv;
00432 
00433   return GetPortFromHrefString(href, aPort);
00434 }
00435 
00436 NS_IMETHODIMP
00437 nsHTMLAreaElement::SetPort(const nsAString& aPort)
00438 {
00439   nsAutoString href, new_href;
00440   nsresult rv = GetHref(href);
00441 
00442   if (NS_FAILED(rv))
00443     return rv;
00444 
00445   rv = SetPortInHrefString(href, aPort, new_href);
00446   if (NS_FAILED(rv))
00447     // Ignore failures to be compatible with NS4
00448     return NS_OK;
00449   
00450   return SetHref(new_href);
00451 }
00452 
00453 NS_IMETHODIMP    
00454 nsHTMLAreaElement::GetHash(nsAString& aHash)
00455 {
00456   nsAutoString href;
00457 
00458   nsresult rv = GetHref(href);
00459   if (NS_FAILED(rv))
00460     return rv;
00461 
00462   return GetHashFromHrefString(href, aHash);
00463 }
00464 
00465 NS_IMETHODIMP
00466 nsHTMLAreaElement::SetHash(const nsAString& aHash)
00467 {
00468   nsAutoString href, new_href;
00469   nsresult rv = GetHref(href);
00470 
00471   if (NS_FAILED(rv))
00472     return rv;
00473 
00474   rv = SetHashInHrefString(href, aHash, new_href);
00475   if (NS_FAILED(rv))
00476     // Ignore failures to be compatible with NS4
00477     return NS_OK;
00478 
00479   return SetHref(new_href);
00480 }
00481 
00482 NS_IMETHODIMP
00483 nsHTMLAreaElement::ToString(nsAString& aSource)
00484 {
00485   return GetHref(aSource);
00486 }
00487 
00488 NS_IMETHODIMP
00489 nsHTMLAreaElement::GetLinkState(nsLinkState &aState)
00490 {
00491   aState = mLinkState;
00492   return NS_OK;
00493 }
00494 
00495 NS_IMETHODIMP
00496 nsHTMLAreaElement::SetLinkState(nsLinkState aState)
00497 {
00498   mLinkState = aState;
00499   return NS_OK;
00500 }
00501 
00502 NS_IMETHODIMP
00503 nsHTMLAreaElement::GetHrefURI(nsIURI** aURI)
00504 {
00505   return GetHrefURIForAnchors(aURI);
00506 }