1 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
2 /* ***** BEGIN LICENSE BLOCK *****
3 * Version: MPL 1.1/GPL 2.0/LGPL 2.1
5 * The contents of this file are subject to the Mozilla Public License Version
6 * 1.1 (the "License"); you may not use this file except in compliance with
7 * the License. You may obtain a copy of the License at
8 * http://www.mozilla.org/MPL/
10 * Software distributed under the License is distributed on an "AS IS" basis,
11 * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
12 * for the specific language governing rights and limitations under the
15 * The Original Code is mozilla.org code.
17 * The Initial Developer of the Original Code is
19 * Portions created by the Initial Developer are Copyright (C) 2003
20 * the Initial Developer. All Rights Reserved.
25 * Alternatively, the contents of this file may be used under the terms of
26 * either the GNU General Public License Version 2 or later (the "GPL"), or
27 * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
28 * in which case the provisions of the GPL or the LGPL are applicable instead
29 * of those above. If you wish to allow use of your version of this file only
30 * under the terms of either the GPL or the LGPL, and not to allow others to
31 * use your version of this file under the terms of the MPL, indicate your
32 * decision by deleting the provisions above and replace them with the notice
33 * and other provisions required by the GPL or the LGPL. If you do not delete
34 * the provisions above, a recipient may use your version of this file under
35 * the terms of any one of the MPL, the GPL or the LGPL.
37 * ***** END LICENSE BLOCK ***** */
39 // NOTE: alphabetically ordered
40 #include "nsTextAccessibleWrap.h"
41 #include "ISimpleDOMText_i.c"
42 #include "nsIAccessibleDocument.h"
43 #include "nsIFontMetrics.h"
45 #include "nsPresContext.h"
46 #include "nsIPresShell.h"
47 #include "nsIRenderingContext.h"
48 #include "nsIWidget.h"
49 #include "nsIComponentManager.h"
51 // --------------------------------------------------------
52 // nsTextAccessibleWrap Accessible
53 // --------------------------------------------------------
55 nsTextAccessibleWrap::nsTextAccessibleWrap(nsIDOMNode
* aDOMNode
, nsIWeakReference
* aShell
):
56 nsTextAccessible(aDOMNode
, aShell
)
60 STDMETHODIMP_(ULONG
) nsTextAccessibleWrap::AddRef()
62 return nsAccessNode::AddRef();
65 STDMETHODIMP_(ULONG
) nsTextAccessibleWrap::Release()
67 return nsAccessNode::Release();
70 STDMETHODIMP
nsTextAccessibleWrap::QueryInterface(REFIID iid
, void** ppv
)
74 if (IID_IUnknown
== iid
|| IID_ISimpleDOMText
== iid
)
75 *ppv
= static_cast<ISimpleDOMText
*>(this);
78 return nsAccessibleWrap::QueryInterface(iid
, ppv
);
80 (reinterpret_cast<IUnknown
*>(*ppv
))->AddRef();
84 STDMETHODIMP
nsTextAccessibleWrap::get_domText(
85 /* [retval][out] */ BSTR __RPC_FAR
*aDomText
)
91 return E_FAIL
; // Node already shut down
93 nsAutoString nodeValue
;
95 mDOMNode
->GetNodeValue(nodeValue
);
96 if (nodeValue
.IsEmpty())
99 *aDomText
= ::SysAllocStringLen(nodeValue
.get(), nodeValue
.Length());
101 return E_OUTOFMEMORY
;
103 } __except(FilterA11yExceptions(::GetExceptionCode(), GetExceptionInformation())) { }
108 STDMETHODIMP
nsTextAccessibleWrap::get_clippedSubstringBounds(
109 /* [in] */ unsigned int aStartIndex
,
110 /* [in] */ unsigned int aEndIndex
,
111 /* [out] */ int __RPC_FAR
*aX
,
112 /* [out] */ int __RPC_FAR
*aY
,
113 /* [out] */ int __RPC_FAR
*aWidth
,
114 /* [out] */ int __RPC_FAR
*aHeight
)
117 *aX
= *aY
= *aWidth
= *aHeight
= 0;
118 nscoord x
, y
, width
, height
, docX
, docY
, docWidth
, docHeight
;
119 HRESULT rv
= get_unclippedSubstringBounds(aStartIndex
, aEndIndex
, &x
, &y
, &width
, &height
);
124 nsCOMPtr
<nsIAccessibleDocument
> docAccessible(GetDocAccessible());
125 nsCOMPtr
<nsIAccessible
> accessible(do_QueryInterface(docAccessible
));
126 NS_ASSERTION(accessible
, "There must always be a doc accessible, but there isn't");
128 accessible
->GetBounds(&docX
, &docY
, &docWidth
, &docHeight
);
130 nsRect
unclippedRect(x
, y
, width
, height
);
131 nsRect
docRect(docX
, docY
, docWidth
, docHeight
);
134 clippedRect
.IntersectRect(unclippedRect
, docRect
);
138 *aWidth
= clippedRect
.width
;
139 *aHeight
= clippedRect
.height
;
140 } __except(FilterA11yExceptions(::GetExceptionCode(), GetExceptionInformation())) { }
145 STDMETHODIMP
nsTextAccessibleWrap::get_unclippedSubstringBounds(
146 /* [in] */ unsigned int aStartIndex
,
147 /* [in] */ unsigned int aEndIndex
,
148 /* [out] */ int __RPC_FAR
*aX
,
149 /* [out] */ int __RPC_FAR
*aY
,
150 /* [out] */ int __RPC_FAR
*aWidth
,
151 /* [out] */ int __RPC_FAR
*aHeight
)
154 *aX
= *aY
= *aWidth
= *aHeight
= 0;
157 return E_FAIL
; // Node already shut down
160 if (NS_FAILED(GetCharacterExtents(aStartIndex
, aEndIndex
,
161 aX
, aY
, aWidth
, aHeight
))) {
162 return NS_ERROR_FAILURE
;
164 } __except(FilterA11yExceptions(::GetExceptionCode(), GetExceptionInformation())) { }
170 STDMETHODIMP
nsTextAccessibleWrap::scrollToSubstring(
171 /* [in] */ unsigned int aStartIndex
,
172 /* [in] */ unsigned int aEndIndex
)
175 nsresult rv
= nsAccUtils::ScrollSubstringTo(GetFrame(), mDOMNode
, aStartIndex
,
177 nsIAccessibleScrollType::SCROLL_TYPE_ANYWHERE
);
180 } __except(FilterA11yExceptions(::GetExceptionCode(), GetExceptionInformation())) { }
184 nsIFrame
* nsTextAccessibleWrap::GetPointFromOffset(nsIFrame
*aContainingFrame
,
189 nsIFrame
*textFrame
= nsnull
;
191 aContainingFrame
->GetChildFrameContainingOffset(aOffset
, aPreferNext
, &outOffset
, &textFrame
);
196 textFrame
->GetPointFromOffset(aOffset
, &aOutPoint
);
201 * Given an offset, the x, y, width, and height values are filled appropriately.
203 nsresult
nsTextAccessibleWrap::GetCharacterExtents(PRInt32 aStartOffset
, PRInt32 aEndOffset
,
204 PRInt32
* aX
, PRInt32
* aY
,
205 PRInt32
* aWidth
, PRInt32
* aHeight
)
207 *aX
= *aY
= *aWidth
= *aHeight
= 0;
208 nsPresContext
*presContext
= GetPresContext();
209 NS_ENSURE_TRUE(presContext
, NS_ERROR_FAILURE
);
211 nsIFrame
*frame
= GetFrame();
212 NS_ENSURE_TRUE(frame
, NS_ERROR_FAILURE
);
214 nsIWidget
*widget
= frame
->GetWindow();
215 NS_ENSURE_TRUE(widget
, NS_ERROR_FAILURE
);
217 nsPoint startPoint
, endPoint
;
218 nsIFrame
*startFrame
= GetPointFromOffset(frame
, aStartOffset
, PR_TRUE
, startPoint
);
219 nsIFrame
*endFrame
= GetPointFromOffset(frame
, aEndOffset
, PR_FALSE
, endPoint
);
220 if (!startFrame
|| !endFrame
) {
224 nsRect
sum(0, 0, 0, 0);
225 nsIFrame
*iter
= startFrame
;
226 nsIFrame
*stopLoopFrame
= endFrame
->GetNextContinuation();
227 for (; iter
!= stopLoopFrame
; iter
= iter
->GetNextContinuation()) {
228 nsRect rect
= iter
->GetScreenRectExternal();
229 nscoord start
= (iter
== startFrame
) ? presContext
->AppUnitsToDevPixels(startPoint
.x
) : 0;
230 nscoord end
= (iter
== endFrame
) ? presContext
->AppUnitsToDevPixels(endPoint
.x
) :
233 rect
.width
= end
- start
;
234 sum
.UnionRect(sum
, rect
);
240 *aHeight
= sum
.height
;
245 STDMETHODIMP
nsTextAccessibleWrap::get_fontFamily(
246 /* [retval][out] */ BSTR __RPC_FAR
*aFontFamily
)
251 nsIFrame
*frame
= GetFrame();
252 nsCOMPtr
<nsIPresShell
> presShell
= GetPresShell();
253 if (!frame
|| !presShell
) {
257 nsCOMPtr
<nsIRenderingContext
> rc
;
258 presShell
->CreateRenderingContext(frame
, getter_AddRefs(rc
));
263 const nsStyleFont
*font
= frame
->GetStyleFont();
265 const nsStyleVisibility
*visibility
= frame
->GetStyleVisibility();
267 if (NS_FAILED(rc
->SetFont(font
->mFont
, visibility
->mLangGroup
))) {
271 nsCOMPtr
<nsIDeviceContext
> deviceContext
;
272 rc
->GetDeviceContext(*getter_AddRefs(deviceContext
));
273 if (!deviceContext
) {
278 rc
->GetFontMetrics(fm
);
283 nsAutoString fontFamily
;
284 deviceContext
->FirstExistingFont(fm
->Font(), fontFamily
);
285 if (fontFamily
.IsEmpty())
288 *aFontFamily
= ::SysAllocStringLen(fontFamily
.get(), fontFamily
.Length());
290 return E_OUTOFMEMORY
;
292 } __except(FilterA11yExceptions(::GetExceptionCode(), GetExceptionInformation())) { }