1 : /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
2 : /* vim: set ts=2 et sw=2 tw=80: */
3 : /* ***** BEGIN LICENSE BLOCK *****
4 : * Version: MPL 1.1/GPL 2.0/LGPL 2.1
5 : *
6 : * The contents of this file are subject to the Mozilla Public License Version
7 : * 1.1 (the "License"); you may not use this file except in compliance with
8 : * the License. You may obtain a copy of the License at
9 : * http://www.mozilla.org/MPL/
10 : *
11 : * Software distributed under the License is distributed on an "AS IS" basis,
12 : * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
13 : * for the specific language governing rights and limitations under the
14 : * License.
15 : *
16 : * The Original Code is mozilla.org code.
17 : *
18 : * The Initial Developer of the Original Code is
19 : * Sun Microsystems, Inc.
20 : * Portions created by the Initial Developer are Copyright (C) 2002
21 : * the Initial Developer. All Rights Reserved.
22 : *
23 : * Contributor(s):
24 : * Bolian Yin (bolian.yin@sun.com)
25 : * Ginn Chen (ginn.chen@sun.com)
26 : *
27 : * Alternatively, the contents of this file may be used under the terms of
28 : * either the GNU General Public License Version 2 or later (the "GPL"), or
29 : * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
30 : * in which case the provisions of the GPL or the LGPL are applicable instead
31 : * of those above. If you wish to allow use of your version of this file only
32 : * under the terms of either the GPL or the LGPL, and not to allow others to
33 : * use your version of this file under the terms of the MPL, indicate your
34 : * decision by deleting the provisions above and replace them with the notice
35 : * and other provisions required by the GPL or the LGPL. If you do not delete
36 : * the provisions above, a recipient may use your version of this file under
37 : * the terms of any one of the MPL, the GPL or the LGPL.
38 : *
39 : * ***** END LICENSE BLOCK ***** */
40 :
41 : #include "nsMaiInterfaceText.h"
42 :
43 : #include "nsHyperTextAccessible.h"
44 : #include "nsRoleMap.h"
45 :
46 : #include "nsIPersistentProperties2.h"
47 :
48 : AtkAttributeSet* ConvertToAtkAttributeSet(nsIPersistentProperties* aAttributes);
49 :
50 : void
51 0 : textInterfaceInitCB(AtkTextIface *aIface)
52 : {
53 0 : NS_ASSERTION(aIface, "Invalid aIface");
54 0 : if (!aIface)
55 0 : return;
56 :
57 0 : aIface->get_text = getTextCB;
58 0 : aIface->get_text_after_offset = getTextAfterOffsetCB;
59 0 : aIface->get_text_at_offset = getTextAtOffsetCB;
60 0 : aIface->get_character_at_offset = getCharacterAtOffsetCB;
61 0 : aIface->get_text_before_offset = getTextBeforeOffsetCB;
62 0 : aIface->get_caret_offset = getCaretOffsetCB;
63 0 : aIface->get_run_attributes = getRunAttributesCB;
64 0 : aIface->get_default_attributes = getDefaultAttributesCB;
65 0 : aIface->get_character_extents = getCharacterExtentsCB;
66 0 : aIface->get_range_extents = getRangeExtentsCB;
67 0 : aIface->get_character_count = getCharacterCountCB;
68 0 : aIface->get_offset_at_point = getOffsetAtPointCB;
69 0 : aIface->get_n_selections = getTextSelectionCountCB;
70 0 : aIface->get_selection = getTextSelectionCB;
71 :
72 : // set methods
73 0 : aIface->add_selection = addTextSelectionCB;
74 0 : aIface->remove_selection = removeTextSelectionCB;
75 0 : aIface->set_selection = setTextSelectionCB;
76 0 : aIface->set_caret_offset = setCaretOffsetCB;
77 : }
78 :
79 :
80 0 : void ConvertTexttoAsterisks(nsAccessibleWrap* accWrap, nsAString& aString)
81 : {
82 : // convert each char to "*" when it's "password text"
83 0 : PRUint32 atkRole = atkRoleMap[accWrap->NativeRole()];
84 0 : if (atkRole == ATK_ROLE_PASSWORD_TEXT) {
85 0 : for (PRUint32 i = 0; i < aString.Length(); i++)
86 0 : aString.Replace(i, 1, NS_LITERAL_STRING("*"));
87 : }
88 0 : }
89 :
90 : gchar *
91 0 : getTextCB(AtkText *aText, gint aStartOffset, gint aEndOffset)
92 : {
93 0 : nsAccessibleWrap *accWrap = GetAccessibleWrap(ATK_OBJECT(aText));
94 0 : if (!accWrap)
95 0 : return nsnull;
96 :
97 0 : nsCOMPtr<nsIAccessibleText> accText;
98 : accWrap->QueryInterface(NS_GET_IID(nsIAccessibleText),
99 0 : getter_AddRefs(accText));
100 0 : NS_ENSURE_TRUE(accText, nsnull);
101 :
102 0 : nsAutoString autoStr;
103 0 : nsresult rv = accText->GetText(aStartOffset, aEndOffset, autoStr);
104 0 : NS_ENSURE_SUCCESS(rv, nsnull);
105 :
106 0 : ConvertTexttoAsterisks(accWrap, autoStr);
107 0 : NS_ConvertUTF16toUTF8 cautoStr(autoStr);
108 :
109 : //copy and return, libspi will free it.
110 0 : return (cautoStr.get()) ? g_strdup(cautoStr.get()) : nsnull;
111 : }
112 :
113 : gchar *
114 0 : getTextAfterOffsetCB(AtkText *aText, gint aOffset,
115 : AtkTextBoundary aBoundaryType,
116 : gint *aStartOffset, gint *aEndOffset)
117 : {
118 0 : nsAccessibleWrap *accWrap = GetAccessibleWrap(ATK_OBJECT(aText));
119 0 : if (!accWrap)
120 0 : return nsnull;
121 :
122 0 : nsCOMPtr<nsIAccessibleText> accText;
123 : accWrap->QueryInterface(NS_GET_IID(nsIAccessibleText),
124 0 : getter_AddRefs(accText));
125 0 : NS_ENSURE_TRUE(accText, nsnull);
126 :
127 0 : nsAutoString autoStr;
128 0 : PRInt32 startOffset = 0, endOffset = 0;
129 : nsresult rv =
130 0 : accText->GetTextAfterOffset(aOffset, aBoundaryType,
131 0 : &startOffset, &endOffset, autoStr);
132 0 : *aStartOffset = startOffset;
133 0 : *aEndOffset = endOffset;
134 :
135 0 : NS_ENSURE_SUCCESS(rv, nsnull);
136 :
137 0 : ConvertTexttoAsterisks(accWrap, autoStr);
138 0 : NS_ConvertUTF16toUTF8 cautoStr(autoStr);
139 0 : return (cautoStr.get()) ? g_strdup(cautoStr.get()) : nsnull;
140 : }
141 :
142 : gchar *
143 0 : getTextAtOffsetCB(AtkText *aText, gint aOffset,
144 : AtkTextBoundary aBoundaryType,
145 : gint *aStartOffset, gint *aEndOffset)
146 : {
147 0 : nsAccessibleWrap *accWrap = GetAccessibleWrap(ATK_OBJECT(aText));
148 0 : if (!accWrap)
149 0 : return nsnull;
150 :
151 0 : nsCOMPtr<nsIAccessibleText> accText;
152 : accWrap->QueryInterface(NS_GET_IID(nsIAccessibleText),
153 0 : getter_AddRefs(accText));
154 0 : NS_ENSURE_TRUE(accText, nsnull);
155 :
156 0 : nsAutoString autoStr;
157 0 : PRInt32 startOffset = 0, endOffset = 0;
158 : nsresult rv =
159 0 : accText->GetTextAtOffset(aOffset, aBoundaryType,
160 0 : &startOffset, &endOffset, autoStr);
161 0 : *aStartOffset = startOffset;
162 0 : *aEndOffset = endOffset;
163 :
164 0 : NS_ENSURE_SUCCESS(rv, nsnull);
165 :
166 0 : ConvertTexttoAsterisks(accWrap, autoStr);
167 0 : NS_ConvertUTF16toUTF8 cautoStr(autoStr);
168 0 : return (cautoStr.get()) ? g_strdup(cautoStr.get()) : nsnull;
169 : }
170 :
171 : gunichar
172 0 : getCharacterAtOffsetCB(AtkText *aText, gint aOffset)
173 : {
174 0 : nsAccessibleWrap *accWrap = GetAccessibleWrap(ATK_OBJECT(aText));
175 0 : if (!accWrap)
176 0 : return 0;
177 :
178 0 : nsCOMPtr<nsIAccessibleText> accText;
179 : accWrap->QueryInterface(NS_GET_IID(nsIAccessibleText),
180 0 : getter_AddRefs(accText));
181 0 : NS_ENSURE_TRUE(accText, 0);
182 :
183 : /* PRUnichar is unsigned short in Mozilla */
184 : /* gnuichar is guint32 in glib */
185 : PRUnichar uniChar;
186 : nsresult rv =
187 0 : accText->GetCharacterAtOffset(aOffset, &uniChar);
188 :
189 : // convert char to "*" when it's "password text"
190 0 : PRUint32 atkRole = atkRoleMap[accWrap->NativeRole()];
191 0 : if (atkRole == ATK_ROLE_PASSWORD_TEXT)
192 0 : uniChar = '*';
193 :
194 0 : return (NS_FAILED(rv)) ? 0 : static_cast<gunichar>(uniChar);
195 : }
196 :
197 : gchar *
198 0 : getTextBeforeOffsetCB(AtkText *aText, gint aOffset,
199 : AtkTextBoundary aBoundaryType,
200 : gint *aStartOffset, gint *aEndOffset)
201 : {
202 0 : nsAccessibleWrap *accWrap = GetAccessibleWrap(ATK_OBJECT(aText));
203 0 : if (!accWrap)
204 0 : return nsnull;
205 :
206 0 : nsCOMPtr<nsIAccessibleText> accText;
207 : accWrap->QueryInterface(NS_GET_IID(nsIAccessibleText),
208 0 : getter_AddRefs(accText));
209 0 : NS_ENSURE_TRUE(accText, nsnull);
210 :
211 0 : nsAutoString autoStr;
212 0 : PRInt32 startOffset = 0, endOffset = 0;
213 : nsresult rv =
214 0 : accText->GetTextBeforeOffset(aOffset, aBoundaryType,
215 0 : &startOffset, &endOffset, autoStr);
216 0 : *aStartOffset = startOffset;
217 0 : *aEndOffset = endOffset;
218 :
219 0 : NS_ENSURE_SUCCESS(rv, nsnull);
220 :
221 0 : ConvertTexttoAsterisks(accWrap, autoStr);
222 0 : NS_ConvertUTF16toUTF8 cautoStr(autoStr);
223 0 : return (cautoStr.get()) ? g_strdup(cautoStr.get()) : nsnull;
224 : }
225 :
226 : gint
227 0 : getCaretOffsetCB(AtkText *aText)
228 : {
229 0 : nsAccessibleWrap *accWrap = GetAccessibleWrap(ATK_OBJECT(aText));
230 0 : if (!accWrap)
231 0 : return 0;
232 :
233 0 : nsCOMPtr<nsIAccessibleText> accText;
234 : accWrap->QueryInterface(NS_GET_IID(nsIAccessibleText),
235 0 : getter_AddRefs(accText));
236 0 : NS_ENSURE_TRUE(accText, 0);
237 :
238 : PRInt32 offset;
239 0 : nsresult rv = accText->GetCaretOffset(&offset);
240 0 : return (NS_FAILED(rv)) ? 0 : static_cast<gint>(offset);
241 : }
242 :
243 : AtkAttributeSet *
244 0 : getRunAttributesCB(AtkText *aText, gint aOffset,
245 : gint *aStartOffset,
246 : gint *aEndOffset)
247 : {
248 0 : *aStartOffset = -1;
249 0 : *aEndOffset = -1;
250 :
251 0 : nsAccessibleWrap *accWrap = GetAccessibleWrap(ATK_OBJECT(aText));
252 0 : if (!accWrap)
253 0 : return nsnull;
254 :
255 0 : nsCOMPtr<nsIAccessibleText> accText;
256 : accWrap->QueryInterface(NS_GET_IID(nsIAccessibleText),
257 0 : getter_AddRefs(accText));
258 0 : NS_ENSURE_TRUE(accText, nsnull);
259 :
260 0 : nsCOMPtr<nsIPersistentProperties> attributes;
261 0 : PRInt32 startOffset = 0, endOffset = 0;
262 0 : nsresult rv = accText->GetTextAttributes(false, aOffset,
263 : &startOffset, &endOffset,
264 0 : getter_AddRefs(attributes));
265 0 : NS_ENSURE_SUCCESS(rv, nsnull);
266 :
267 0 : *aStartOffset = startOffset;
268 0 : *aEndOffset = endOffset;
269 :
270 0 : return ConvertToAtkAttributeSet(attributes);
271 : }
272 :
273 : AtkAttributeSet *
274 0 : getDefaultAttributesCB(AtkText *aText)
275 : {
276 0 : nsAccessibleWrap *accWrap = GetAccessibleWrap(ATK_OBJECT(aText));
277 0 : if (!accWrap)
278 0 : return nsnull;
279 :
280 0 : nsCOMPtr<nsIAccessibleText> accText;
281 : accWrap->QueryInterface(NS_GET_IID(nsIAccessibleText),
282 0 : getter_AddRefs(accText));
283 0 : NS_ENSURE_TRUE(accText, nsnull);
284 :
285 0 : nsCOMPtr<nsIPersistentProperties> attributes;
286 0 : nsresult rv = accText->GetDefaultTextAttributes(getter_AddRefs(attributes));
287 0 : if (NS_FAILED(rv))
288 0 : return nsnull;
289 :
290 0 : return ConvertToAtkAttributeSet(attributes);
291 : }
292 :
293 : void
294 0 : getCharacterExtentsCB(AtkText *aText, gint aOffset,
295 : gint *aX, gint *aY,
296 : gint *aWidth, gint *aHeight,
297 : AtkCoordType aCoords)
298 : {
299 0 : nsAccessibleWrap *accWrap = GetAccessibleWrap(ATK_OBJECT(aText));
300 0 : if(!accWrap || !aX || !aY || !aWidth || !aHeight)
301 0 : return;
302 :
303 0 : nsCOMPtr<nsIAccessibleText> accText;
304 : accWrap->QueryInterface(NS_GET_IID(nsIAccessibleText),
305 0 : getter_AddRefs(accText));
306 0 : if (!accText)
307 : return;
308 :
309 0 : PRInt32 extY = 0, extX = 0;
310 0 : PRInt32 extWidth = 0, extHeight = 0;
311 :
312 : PRUint32 geckoCoordType;
313 0 : if (aCoords == ATK_XY_SCREEN)
314 0 : geckoCoordType = nsIAccessibleCoordinateType::COORDTYPE_SCREEN_RELATIVE;
315 : else
316 0 : geckoCoordType = nsIAccessibleCoordinateType::COORDTYPE_WINDOW_RELATIVE;
317 :
318 : #ifdef DEBUG
319 : nsresult rv =
320 : #endif
321 0 : accText->GetCharacterExtents(aOffset, &extX, &extY,
322 : &extWidth, &extHeight,
323 0 : geckoCoordType);
324 0 : *aX = extX;
325 0 : *aY = extY;
326 0 : *aWidth = extWidth;
327 0 : *aHeight = extHeight;
328 0 : NS_ASSERTION(NS_SUCCEEDED(rv),
329 : "MaiInterfaceText::GetCharacterExtents, failed\n");
330 : }
331 :
332 : void
333 0 : getRangeExtentsCB(AtkText *aText, gint aStartOffset, gint aEndOffset,
334 : AtkCoordType aCoords, AtkTextRectangle *aRect)
335 : {
336 0 : nsAccessibleWrap *accWrap = GetAccessibleWrap(ATK_OBJECT(aText));
337 0 : if(!accWrap || !aRect)
338 0 : return;
339 :
340 0 : nsCOMPtr<nsIAccessibleText> accText;
341 : accWrap->QueryInterface(NS_GET_IID(nsIAccessibleText),
342 0 : getter_AddRefs(accText));
343 0 : if (!accText)
344 : return;
345 :
346 0 : PRInt32 extY = 0, extX = 0;
347 0 : PRInt32 extWidth = 0, extHeight = 0;
348 :
349 : PRUint32 geckoCoordType;
350 0 : if (aCoords == ATK_XY_SCREEN)
351 0 : geckoCoordType = nsIAccessibleCoordinateType::COORDTYPE_SCREEN_RELATIVE;
352 : else
353 0 : geckoCoordType = nsIAccessibleCoordinateType::COORDTYPE_WINDOW_RELATIVE;
354 :
355 : #ifdef DEBUG
356 : nsresult rv =
357 : #endif
358 0 : accText->GetRangeExtents(aStartOffset, aEndOffset,
359 : &extX, &extY,
360 : &extWidth, &extHeight,
361 0 : geckoCoordType);
362 0 : aRect->x = extX;
363 0 : aRect->y = extY;
364 0 : aRect->width = extWidth;
365 0 : aRect->height = extHeight;
366 0 : NS_ASSERTION(NS_SUCCEEDED(rv),
367 : "MaiInterfaceText::GetRangeExtents, failed\n");
368 : }
369 :
370 : gint
371 0 : getCharacterCountCB(AtkText *aText)
372 : {
373 0 : nsAccessibleWrap *accWrap = GetAccessibleWrap(ATK_OBJECT(aText));
374 0 : if (!accWrap)
375 0 : return 0;
376 :
377 0 : nsHyperTextAccessible* textAcc = accWrap->AsHyperText();
378 0 : return textAcc->IsDefunct() ?
379 0 : 0 : static_cast<gint>(textAcc->CharacterCount());
380 : }
381 :
382 : gint
383 0 : getOffsetAtPointCB(AtkText *aText,
384 : gint aX, gint aY,
385 : AtkCoordType aCoords)
386 : {
387 0 : nsAccessibleWrap *accWrap = GetAccessibleWrap(ATK_OBJECT(aText));
388 0 : if (!accWrap)
389 0 : return -1;
390 :
391 0 : nsCOMPtr<nsIAccessibleText> accText;
392 : accWrap->QueryInterface(NS_GET_IID(nsIAccessibleText),
393 0 : getter_AddRefs(accText));
394 0 : NS_ENSURE_TRUE(accText, -1);
395 :
396 0 : PRInt32 offset = 0;
397 : PRUint32 geckoCoordType;
398 0 : if (aCoords == ATK_XY_SCREEN)
399 0 : geckoCoordType = nsIAccessibleCoordinateType::COORDTYPE_SCREEN_RELATIVE;
400 : else
401 0 : geckoCoordType = nsIAccessibleCoordinateType::COORDTYPE_WINDOW_RELATIVE;
402 :
403 0 : accText->GetOffsetAtPoint(aX, aY, geckoCoordType, &offset);
404 0 : return static_cast<gint>(offset);
405 : }
406 :
407 : gint
408 0 : getTextSelectionCountCB(AtkText *aText)
409 : {
410 0 : nsAccessibleWrap *accWrap = GetAccessibleWrap(ATK_OBJECT(aText));
411 0 : if (!accWrap)
412 0 : return nsnull;
413 :
414 0 : nsCOMPtr<nsIAccessibleText> accText;
415 : accWrap->QueryInterface(NS_GET_IID(nsIAccessibleText),
416 0 : getter_AddRefs(accText));
417 0 : NS_ENSURE_TRUE(accText, nsnull);
418 :
419 : PRInt32 selectionCount;
420 0 : nsresult rv = accText->GetSelectionCount(&selectionCount);
421 :
422 0 : return NS_FAILED(rv) ? 0 : selectionCount;
423 : }
424 :
425 : gchar *
426 0 : getTextSelectionCB(AtkText *aText, gint aSelectionNum,
427 : gint *aStartOffset, gint *aEndOffset)
428 : {
429 0 : nsAccessibleWrap *accWrap = GetAccessibleWrap(ATK_OBJECT(aText));
430 0 : if (!accWrap)
431 0 : return nsnull;
432 :
433 0 : nsCOMPtr<nsIAccessibleText> accText;
434 : accWrap->QueryInterface(NS_GET_IID(nsIAccessibleText),
435 0 : getter_AddRefs(accText));
436 0 : NS_ENSURE_TRUE(accText, nsnull);
437 :
438 0 : PRInt32 startOffset = 0, endOffset = 0;
439 0 : nsresult rv = accText->GetSelectionBounds(aSelectionNum,
440 0 : &startOffset, &endOffset);
441 :
442 0 : *aStartOffset = startOffset;
443 0 : *aEndOffset = endOffset;
444 :
445 0 : NS_ENSURE_SUCCESS(rv, nsnull);
446 :
447 0 : return getTextCB(aText, *aStartOffset, *aEndOffset);
448 : }
449 :
450 : // set methods
451 : gboolean
452 0 : addTextSelectionCB(AtkText *aText,
453 : gint aStartOffset,
454 : gint aEndOffset)
455 : {
456 0 : nsAccessibleWrap *accWrap = GetAccessibleWrap(ATK_OBJECT(aText));
457 0 : if (!accWrap)
458 0 : return FALSE;
459 :
460 0 : nsCOMPtr<nsIAccessibleText> accText;
461 : accWrap->QueryInterface(NS_GET_IID(nsIAccessibleText),
462 0 : getter_AddRefs(accText));
463 0 : NS_ENSURE_TRUE(accText, FALSE);
464 :
465 0 : nsresult rv = accText->AddSelection(aStartOffset, aEndOffset);
466 :
467 0 : return NS_SUCCEEDED(rv) ? TRUE : FALSE;
468 : }
469 :
470 : gboolean
471 0 : removeTextSelectionCB(AtkText *aText,
472 : gint aSelectionNum)
473 : {
474 0 : nsAccessibleWrap *accWrap = GetAccessibleWrap(ATK_OBJECT(aText));
475 0 : if (!accWrap)
476 0 : return FALSE;
477 :
478 0 : nsCOMPtr<nsIAccessibleText> accText;
479 : accWrap->QueryInterface(NS_GET_IID(nsIAccessibleText),
480 0 : getter_AddRefs(accText));
481 0 : NS_ENSURE_TRUE(accText, FALSE);
482 :
483 0 : nsresult rv = accText->RemoveSelection(aSelectionNum);
484 :
485 0 : return NS_SUCCEEDED(rv) ? TRUE : FALSE;
486 : }
487 :
488 : gboolean
489 0 : setTextSelectionCB(AtkText *aText, gint aSelectionNum,
490 : gint aStartOffset, gint aEndOffset)
491 : {
492 0 : nsAccessibleWrap *accWrap = GetAccessibleWrap(ATK_OBJECT(aText));
493 0 : if (!accWrap)
494 0 : return FALSE;
495 :
496 0 : nsCOMPtr<nsIAccessibleText> accText;
497 : accWrap->QueryInterface(NS_GET_IID(nsIAccessibleText),
498 0 : getter_AddRefs(accText));
499 0 : NS_ENSURE_TRUE(accText, FALSE);
500 :
501 0 : nsresult rv = accText->SetSelectionBounds(aSelectionNum,
502 0 : aStartOffset, aEndOffset);
503 0 : return NS_SUCCEEDED(rv) ? TRUE : FALSE;
504 : }
505 :
506 : gboolean
507 0 : setCaretOffsetCB(AtkText *aText, gint aOffset)
508 : {
509 0 : nsAccessibleWrap *accWrap = GetAccessibleWrap(ATK_OBJECT(aText));
510 0 : if (!accWrap)
511 0 : return FALSE;
512 :
513 0 : nsCOMPtr<nsIAccessibleText> accText;
514 : accWrap->QueryInterface(NS_GET_IID(nsIAccessibleText),
515 0 : getter_AddRefs(accText));
516 0 : NS_ENSURE_TRUE(accText, FALSE);
517 :
518 0 : nsresult rv = accText->SetCaretOffset(aOffset);
519 0 : return NS_SUCCEEDED(rv) ? TRUE : FALSE;
520 : }
|