Back to index

lightning-sunbird  0.9+nobinonly
nsMaiInterfaceHypertext.cpp
Go to the documentation of this file.
00001 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
00002 /* vim:expandtab:shiftwidth=4:tabstop=4:
00003  */
00004 /* ***** BEGIN LICENSE BLOCK *****
00005  * Version: NPL 1.1/GPL 2.0/LGPL 2.1
00006  *
00007  *
00008  * The contents of this file are subject to the Mozilla Public
00009  * License Version 1.1 (the "License"); you may not use this file
00010  * except in compliance with the License. You may obtain a copy of
00011  * the License at http://www.mozilla.org/MPL/
00012  *
00013  * Software distributed under the License is distributed on an "AS
00014  * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
00015  * implied. See the License for the specific language governing
00016  * rights and limitations under the License.
00017  *
00018  * The Original Code is mozilla.org code.
00019  *
00020  * The Initial Developer of the Original Code is Sun Microsystems, Inc.
00021  * Portions created by Sun Microsystems are Copyright (C) 2002 Sun
00022  * Microsystems, Inc. All Rights Reserved.
00023  *
00024  * Original Author: Bolian Yin (bolian.yin@sun.com)
00025  *
00026  * Contributor(s):
00027  *
00028  * Alternatively, the contents of this file may be used under the terms of
00029  * either the GNU General Public License Version 2 or later (the "GPL"), or
00030  * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
00031  * in which case the provisions of the GPL or the LGPL are applicable instead
00032  * of those above. If you wish to allow use of your version of this file only
00033  * under the terms of either the GPL or the LGPL, and not to allow others to
00034  * use your version of this file under the terms of the NPL, indicate your
00035  * decision by deleting the provisions above and replace them with the notice
00036  * and other provisions required by the GPL or the LGPL. If you do not delete
00037  * the provisions above, a recipient may use your version of this file under
00038  * the terms of any one of the NPL, the GPL or the LGPL.
00039  *
00040  * ***** END LICENSE BLOCK ***** */
00041 
00042 #include "nsMaiInterfaceHypertext.h"
00043 #include "nsIAccessibleDocument.h"
00044 #include "nsPIAccessNode.h"
00045 
00046 G_BEGIN_DECLS
00047 
00048 static void interfaceInitCB(AtkHypertextIface *aIface);
00049 
00050 /* hypertext interface callbacks */
00051 static AtkHyperlink *getLinkCB(AtkHypertext *aText, gint aLinkIndex);
00052 static gint getLinkCountCB(AtkHypertext *aText);
00053 static gint getLinkIndexCB(AtkHypertext *aText, gint aCharIndex);
00054 
00055 G_END_DECLS
00056 
00057 MaiInterfaceHypertext::MaiInterfaceHypertext(nsAccessibleWrap *aAccWrap,
00058                                              nsIWeakReference* aShell):
00059     MaiInterface(aAccWrap),
00060     mWeakShell(aShell)
00061 {
00062 }
00063 
00064 MaiInterfaceHypertext::~MaiInterfaceHypertext()
00065 {
00066     mWeakShell = nsnull;
00067 }
00068 
00069 MaiInterfaceType
00070 MaiInterfaceHypertext::GetType()
00071 {
00072     return MAI_INTERFACE_HYPERTEXT;
00073 }
00074 
00075 nsresult
00076 MaiInterfaceHypertext::GetWeakShell(nsIWeakReference **aWeakShell)
00077 {
00078     nsresult rv = NS_ERROR_FAILURE;
00079     if (mWeakShell) {
00080         *aWeakShell = mWeakShell;
00081         NS_IF_ADDREF(*aWeakShell);
00082         rv = NS_OK;
00083     }
00084     else
00085         *aWeakShell = nsnull;
00086     return rv;
00087 }
00088 
00089 const GInterfaceInfo *
00090 MaiInterfaceHypertext::GetInterfaceInfo()
00091 {
00092     static const GInterfaceInfo atk_if_hypertext_info = {
00093         (GInterfaceInitFunc)interfaceInitCB,
00094         (GInterfaceFinalizeFunc) NULL,
00095         NULL
00096     };
00097     return &atk_if_hypertext_info;
00098 }
00099 
00100 /* statics */
00101 
00102 void
00103 interfaceInitCB(AtkHypertextIface *aIface)
00104 {
00105     g_return_if_fail(aIface != NULL);
00106 
00107     aIface->get_link = getLinkCB;
00108     aIface->get_n_links = getLinkCountCB;
00109     aIface->get_link_index = getLinkIndexCB;
00110 }
00111 
00112 AtkHyperlink *
00113 getLinkCB(AtkHypertext *aText, gint aLinkIndex)
00114 {
00115     nsresult rv;
00116     nsAccessibleWrap *accWrap = GetAccessibleWrap(ATK_OBJECT(aText));
00117     NS_ENSURE_TRUE(accWrap, nsnull);
00118 
00119     MaiInterfaceHypertext *maiHypertext =
00120         NS_STATIC_CAST(MaiInterfaceHypertext *,
00121                        accWrap->GetMaiInterface(MAI_INTERFACE_HYPERTEXT));
00122     NS_ENSURE_TRUE(accWrap, nsnull);
00123 
00124     nsCOMPtr<nsIWeakReference> weakShell;
00125     rv = maiHypertext->GetWeakShell(getter_AddRefs(weakShell));
00126     NS_ENSURE_SUCCESS(rv, nsnull);
00127 
00128     nsCOMPtr<nsIAccessibleHyperText> accHyperlink;
00129     accWrap->QueryInterface(NS_GET_IID(nsIAccessibleHyperText),
00130                             getter_AddRefs(accHyperlink));
00131     NS_ENSURE_TRUE(accHyperlink, nsnull);
00132 
00133     nsCOMPtr<nsIAccessibleHyperLink> hyperLink;
00134     rv = accHyperlink->GetLink(aLinkIndex, getter_AddRefs(hyperLink));
00135     if (NS_FAILED(rv) || !hyperLink)
00136         return nsnull;
00137 
00138     // The MaiHyperlink and its nsIAccessibleHyperlink are in the same cache.
00139     // we take hyperlink->get() as Id for the MaiHyperlink.
00140     // release our ref to the previous one
00141 
00142     nsCOMPtr<nsIAccessibleDocument> accessibleDoc =
00143         nsAccessNode::GetDocAccessibleFor(weakShell);
00144     if (!accessibleDoc) {
00145         NS_WARNING("No accessible document for this presshell");
00146         return nsnull;
00147     }
00148     nsCOMPtr<nsIAccessNode> maiNode;
00149     accessibleDoc->GetCachedAccessNode(NS_STATIC_CAST(void*, hyperLink.get()),
00150                                        getter_AddRefs(maiNode));
00151     // if the maiHyperlink is not in cache, create it.
00152     if (!maiNode) {
00153         maiNode = new MaiHyperlink(hyperLink, nsnull, weakShell);
00154         if (!maiNode) {
00155             NS_WARNING("OUT OF MEMORY");
00156             return nsnull;
00157         }
00158         nsCOMPtr<nsPIAccessNode> pMaiNode = do_QueryInterface(maiNode);
00159         pMaiNode->Init();  // add to cache.
00160     }
00161 
00162     // we can get AtkHyperlink from the MaiHyperlink
00163     nsIAccessNode *tmpNode = maiNode;
00164     MaiHyperlink *maiHyperlink = NS_STATIC_CAST(MaiHyperlink *, tmpNode);
00165 
00166     /* we should not addref the atkhyperlink because we are "get" not "ref" */
00167     return maiHyperlink->GetAtkHyperlink();
00168 }
00169 
00170 gint
00171 getLinkCountCB(AtkHypertext *aText)
00172 {
00173     nsAccessibleWrap *accWrap = GetAccessibleWrap(ATK_OBJECT(aText));
00174     NS_ENSURE_TRUE(accWrap, -1);
00175 
00176     nsCOMPtr<nsIAccessibleHyperText> accHyperlink;
00177     accWrap->QueryInterface(NS_GET_IID(nsIAccessibleHyperText),
00178                             getter_AddRefs(accHyperlink));
00179     NS_ENSURE_TRUE(accHyperlink, -1);
00180 
00181     PRInt32 count = -1;
00182     nsresult rv = accHyperlink->GetLinks(&count);
00183     NS_ENSURE_SUCCESS(rv, -1);
00184 
00185     return count;
00186 }
00187 
00188 gint
00189 getLinkIndexCB(AtkHypertext *aText, gint aCharIndex)
00190 {
00191     nsAccessibleWrap *accWrap = GetAccessibleWrap(ATK_OBJECT(aText));
00192     NS_ENSURE_TRUE(accWrap, -1);
00193 
00194     nsCOMPtr<nsIAccessibleHyperText> accHyperlink;
00195     accWrap->QueryInterface(NS_GET_IID(nsIAccessibleHyperText),
00196                             getter_AddRefs(accHyperlink));
00197     NS_ENSURE_TRUE(accHyperlink, -1);
00198 
00199     PRInt32 index = -1;
00200     nsresult rv = accHyperlink->GetLinkIndex(aCharIndex, &index);
00201     NS_ENSURE_SUCCESS(rv, -1);
00202 
00203     return index;
00204 }