9d204d4783ee47bf2150c4a8f84d62d1c51e98ae
[WebKit-https.git] / Tools / DumpRenderTree / gtk / AccessibilityUIElementGtk.cpp
1 /*
2  * Copyright (C) 2008 Apple Inc. All Rights Reserved.
3  * Copyright (C) 2009 Jan Michael Alonzo
4  *
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted provided that the following conditions
7  * are met:
8  * 1. Redistributions of source code must retain the above copyright
9  *    notice, this list of conditions and the following disclaimer.
10  * 2. Redistributions in binary form must reproduce the above copyright
11  *    notice, this list of conditions and the following disclaimer in the
12  *    documentation and/or other materials provided with the distribution.
13  *
14  * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
15  * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
16  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
17  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE INC. OR
18  * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
19  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
20  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
21  * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
22  * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
23  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
24  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 
25  */
26
27 #include "config.h"
28 #include "AccessibilityUIElement.h"
29
30 #include "WebCoreSupport/DumpRenderTreeSupportGtk.h"
31 #include <JavaScriptCore/JSStringRef.h>
32 #include <atk/atk.h>
33 #include <gtk/gtk.h>
34 #include <wtf/Assertions.h>
35 #include <wtf/gobject/GOwnPtr.h>
36 #include <wtf/gobject/GRefPtr.h>
37 #include <wtf/text/WTFString.h>
38 #include <wtf/unicode/CharacterNames.h>
39
40 static String coreAttributeToAtkAttribute(JSStringRef attribute)
41 {
42     size_t bufferSize = JSStringGetMaximumUTF8CStringSize(attribute);
43     GOwnPtr<gchar> buffer(static_cast<gchar*>(g_malloc(bufferSize)));
44     JSStringGetUTF8CString(attribute, buffer.get(), bufferSize);
45
46     String attributeString = String::fromUTF8(buffer.get());
47     if (attributeString == "AXPlaceholderValue")
48         return "placeholder-text";
49
50     return "";
51 }
52
53 static inline String roleToString(AtkRole role)
54 {
55     switch (role) {
56     case ATK_ROLE_ALERT:
57         return "AXRole: AXAlert";
58     case ATK_ROLE_CANVAS:
59         return "AXRole: AXCanvas";
60     case ATK_ROLE_CHECK_BOX:
61         return "AXRole: AXCheckBox";
62     case ATK_ROLE_COLUMN_HEADER:
63         return "AXRole: AXColumnHeader";
64     case ATK_ROLE_COMBO_BOX:
65         return "AXRole: AXComboBox";
66     case ATK_ROLE_DOCUMENT_FRAME:
67         return "AXRole: AXWebArea";
68     case ATK_ROLE_ENTRY:
69         return "AXRole: AXTextField";
70     case ATK_ROLE_FOOTER:
71         return "AXRole: AXFooter";
72     case ATK_ROLE_FORM:
73         return "AXRole: AXForm";
74     case ATK_ROLE_GROUPING:
75         return "AXRole: AXGroup";
76     case ATK_ROLE_HEADING:
77         return "AXRole: AXHeading";
78     case ATK_ROLE_IMAGE:
79         return "AXRole: AXImage";
80     case ATK_ROLE_IMAGE_MAP:
81         return "AXRole: AXImageMap";
82     case ATK_ROLE_LABEL:
83         return "AXRole: AXLabel";
84     case ATK_ROLE_LINK:
85         return "AXRole: AXLink";
86     case ATK_ROLE_LIST:
87         return "AXRole: AXList";
88     case ATK_ROLE_LIST_BOX:
89         return "AXRole: AXListBox";
90     case ATK_ROLE_LIST_ITEM:
91         return "AXRole: AXListItem";
92     case ATK_ROLE_MENU:
93         return "AXRole: AXMenu";
94     case ATK_ROLE_MENU_BAR:
95         return "AXRole: AXMenuBar";
96     case ATK_ROLE_MENU_ITEM:
97         return "AXRole: AXMenuItem";
98     case ATK_ROLE_PAGE_TAB:
99         return "AXRole: AXTab";
100     case ATK_ROLE_PAGE_TAB_LIST:
101         return "AXRole: AXTabGroup";
102     case ATK_ROLE_PANEL:
103         return "AXRole: AXGroup";
104     case ATK_ROLE_PARAGRAPH:
105         return "AXRole: AXParagraph";
106     case ATK_ROLE_PASSWORD_TEXT:
107         return "AXRole: AXPasswordField";
108     case ATK_ROLE_PUSH_BUTTON:
109         return "AXRole: AXButton";
110     case ATK_ROLE_RADIO_BUTTON:
111         return "AXRole: AXRadioButton";
112     case ATK_ROLE_ROW_HEADER:
113         return "AXRole: AXRowHeader";
114     case ATK_ROLE_RULER:
115         return "AXRole: AXRuler";
116     case ATK_ROLE_SCROLL_BAR:
117         return "AXRole: AXScrollBar";
118     case ATK_ROLE_SCROLL_PANE:
119         return "AXRole: AXScrollArea";
120     case ATK_ROLE_SECTION:
121         return "AXRole: AXDiv";
122     case ATK_ROLE_SEPARATOR:
123         return "AXRole: AXHorizontalRule";
124     case ATK_ROLE_SLIDER:
125         return "AXRole: AXSlider";
126     case ATK_ROLE_SPIN_BUTTON:
127         return "AXRole: AXSpinButton";
128     case ATK_ROLE_TABLE:
129         return "AXRole: AXTable";
130     case ATK_ROLE_TABLE_CELL:
131         return "AXRole: AXCell";
132     case ATK_ROLE_TABLE_COLUMN_HEADER:
133         return "AXRole: AXColumnHeader";
134     case ATK_ROLE_TABLE_ROW:
135         return "AXRole: AXRow";
136     case ATK_ROLE_TABLE_ROW_HEADER:
137         return "AXRole: AXRowHeader";
138     case ATK_ROLE_TOGGLE_BUTTON:
139         return "AXRole: AXToggleButton";
140     case ATK_ROLE_TOOL_BAR:
141         return "AXRole: AXToolbar";
142     case ATK_ROLE_TOOL_TIP:
143         return "AXRole: AXUserInterfaceTooltip";
144     case ATK_ROLE_TREE:
145         return "AXRole: AXTree";
146     case ATK_ROLE_TREE_TABLE:
147         return "AXRole: AXTreeGrid";
148     case ATK_ROLE_TREE_ITEM:
149         return "AXRole: AXTreeItem";
150     case ATK_ROLE_WINDOW:
151         return "AXRole: AXWindow";
152     case ATK_ROLE_UNKNOWN:
153         return "AXRole: AXUnknown";
154     default:
155         // We want to distinguish ATK_ROLE_UNKNOWN from a known AtkRole which
156         // our DRT isn't properly handling.
157         return "AXRole: FIXME not identified";
158     }
159 }
160
161 static inline gchar* replaceCharactersForResults(gchar* str)
162 {
163     String uString = String::fromUTF8(str);
164
165     // The object replacement character is passed along to ATs so we need to be
166     // able to test for their presence and do so without causing test failures.
167     uString.replace(objectReplacementCharacter, "<obj>");
168
169     // The presence of newline characters in accessible text of a single object
170     // is appropriate, but it makes test results (especially the accessible tree)
171     // harder to read.
172     uString.replace("\n", "<\\n>");
173
174     return g_strdup(uString.utf8().data());
175 }
176
177 AccessibilityUIElement::AccessibilityUIElement(PlatformUIElement element)
178     : m_element(element)
179 {
180     if (m_element)
181         g_object_ref(m_element);
182 }
183
184 AccessibilityUIElement::AccessibilityUIElement(const AccessibilityUIElement& other)
185     : m_element(other.m_element)
186 {
187     if (m_element)
188         g_object_ref(m_element);
189 }
190
191 AccessibilityUIElement::~AccessibilityUIElement()
192 {
193     if (m_element)
194         g_object_unref(m_element);
195 }
196
197 void AccessibilityUIElement::getLinkedUIElements(Vector<AccessibilityUIElement>& elements)
198 {
199     // FIXME: implement
200 }
201
202 void AccessibilityUIElement::getDocumentLinks(Vector<AccessibilityUIElement>&)
203 {
204     // FIXME: implement
205 }
206
207 void AccessibilityUIElement::getChildren(Vector<AccessibilityUIElement>& children)
208 {
209     int count = childrenCount();
210     for (int i = 0; i < count; i++) {
211         AtkObject* child = atk_object_ref_accessible_child(ATK_OBJECT(m_element), i);
212         children.append(AccessibilityUIElement(child));
213     }
214 }
215
216 void AccessibilityUIElement::getChildrenWithRange(Vector<AccessibilityUIElement>& elementVector, unsigned start, unsigned end)
217 {
218     for (unsigned i = start; i < end; i++) {
219         AtkObject* child = atk_object_ref_accessible_child(ATK_OBJECT(m_element), i);
220         elementVector.append(AccessibilityUIElement(child));
221     }
222 }
223
224 int AccessibilityUIElement::rowCount()
225 {
226     if (!m_element)
227         return 0;
228
229     ASSERT(ATK_IS_TABLE(m_element));
230
231     return atk_table_get_n_rows(ATK_TABLE(m_element));
232 }
233
234 int AccessibilityUIElement::columnCount()
235 {
236     if (!m_element)
237         return 0;
238
239     ASSERT(ATK_IS_TABLE(m_element));
240
241     return atk_table_get_n_columns(ATK_TABLE(m_element));
242 }
243
244 int AccessibilityUIElement::childrenCount()
245 {
246     if (!m_element)
247         return 0;
248
249     ASSERT(ATK_IS_OBJECT(m_element));
250
251     return atk_object_get_n_accessible_children(ATK_OBJECT(m_element));
252 }
253
254 AccessibilityUIElement AccessibilityUIElement::elementAtPoint(int x, int y)
255 {
256     if (!m_element)
257         return 0;
258
259     return AccessibilityUIElement(atk_component_ref_accessible_at_point(ATK_COMPONENT(m_element), x, y, ATK_XY_WINDOW));
260 }
261
262 AccessibilityUIElement AccessibilityUIElement::linkedUIElementAtIndex(unsigned index)
263 {
264     // FIXME: implement
265     return 0;
266 }
267
268 AccessibilityUIElement AccessibilityUIElement::getChildAtIndex(unsigned index)
269 {
270     Vector<AccessibilityUIElement> children;
271     getChildrenWithRange(children, index, index + 1);
272
273     if (children.size() == 1)
274         return children.at(0);
275
276     return 0;
277 }
278
279 unsigned AccessibilityUIElement::indexOfChild(AccessibilityUIElement* element)
280
281     // FIXME: implement
282     return 0;
283 }
284
285 gchar* attributeSetToString(AtkAttributeSet* attributeSet)
286 {
287     GString* str = g_string_new(0);
288     for (GSList* attributes = attributeSet; attributes; attributes = attributes->next) {
289         AtkAttribute* attribute = static_cast<AtkAttribute*>(attributes->data);
290         GOwnPtr<gchar> attributeData(g_strconcat(attribute->name, ":", attribute->value, NULL));
291         g_string_append(str, attributeData.get());
292         if (attributes->next)
293             g_string_append(str, ", ");
294     }
295
296     return g_string_free(str, FALSE);
297 }
298
299 JSStringRef AccessibilityUIElement::allAttributes()
300 {
301     if (!m_element)
302         return JSStringCreateWithCharacters(0, 0);
303
304     ASSERT(ATK_IS_OBJECT(m_element));
305     GOwnPtr<gchar> attributeData(attributeSetToString(atk_object_get_attributes(ATK_OBJECT(m_element))));
306     return JSStringCreateWithUTF8CString(attributeData.get());
307 }
308
309 JSStringRef AccessibilityUIElement::attributesOfLinkedUIElements()
310 {
311     // FIXME: implement
312     return JSStringCreateWithCharacters(0, 0);
313 }
314
315 JSStringRef AccessibilityUIElement::attributesOfDocumentLinks()
316 {
317     // FIXME: implement
318     return JSStringCreateWithCharacters(0, 0);
319 }
320
321 AccessibilityUIElement AccessibilityUIElement::titleUIElement()
322 {
323
324     if (!m_element)
325         return 0;
326
327     AtkRelationSet* set = atk_object_ref_relation_set(ATK_OBJECT(m_element));
328     if (!set)
329         return 0;
330
331     AtkObject* target = 0;
332     int count = atk_relation_set_get_n_relations(set);
333     for (int i = 0; i < count; i++) {
334         AtkRelation* relation = atk_relation_set_get_relation(set, i);
335         if (atk_relation_get_relation_type(relation) == ATK_RELATION_LABELLED_BY) {
336             GPtrArray* targetList = atk_relation_get_target(relation);
337             if (targetList->len)
338                 target = static_cast<AtkObject*>(g_ptr_array_index(targetList, 0));
339         }
340         g_object_unref(set);
341     }
342
343     return target ? AccessibilityUIElement(target) : 0;
344 }
345
346 AccessibilityUIElement AccessibilityUIElement::parentElement()
347 {
348     if (!m_element)
349         return 0;
350
351     ASSERT(ATK_IS_OBJECT(m_element));
352
353     AtkObject* parent =  atk_object_get_parent(ATK_OBJECT(m_element));
354     return parent ? AccessibilityUIElement(parent) : 0;
355 }
356
357 JSStringRef AccessibilityUIElement::attributesOfChildren()
358 {
359     // FIXME: implement
360     return JSStringCreateWithCharacters(0, 0);
361 }
362
363 JSStringRef AccessibilityUIElement::parameterizedAttributeNames()
364 {
365     // FIXME: implement
366     return JSStringCreateWithCharacters(0, 0);
367 }
368
369 JSStringRef AccessibilityUIElement::role()
370 {
371     AtkRole role = atk_object_get_role(ATK_OBJECT(m_element));
372     if (!role)
373         return JSStringCreateWithCharacters(0, 0);
374
375     String roleString = roleToString(role);
376     return JSStringCreateWithUTF8CString(roleString.utf8().data());
377 }
378
379 JSStringRef AccessibilityUIElement::subrole()
380 {
381     return 0;
382 }
383
384 JSStringRef AccessibilityUIElement::roleDescription()
385 {
386     return 0;
387 }
388
389 JSStringRef AccessibilityUIElement::title()
390 {
391     const gchar* name = atk_object_get_name(ATK_OBJECT(m_element));
392
393     if (!name)
394         return JSStringCreateWithCharacters(0, 0);
395
396     GOwnPtr<gchar> axTitle(g_strdup_printf("AXTitle: %s", name));
397
398     return JSStringCreateWithUTF8CString(axTitle.get());
399 }
400
401 JSStringRef AccessibilityUIElement::description()
402 {
403     const gchar* description = atk_object_get_description(ATK_OBJECT(m_element));
404
405     if (!description)
406         return JSStringCreateWithCharacters(0, 0);
407
408     GOwnPtr<gchar> axDesc(g_strdup_printf("AXDescription: %s", description));
409
410     return JSStringCreateWithUTF8CString(axDesc.get());
411 }
412
413 JSStringRef AccessibilityUIElement::stringValue()
414 {
415     if (!m_element || !ATK_IS_TEXT(m_element))
416         return JSStringCreateWithCharacters(0, 0);
417
418     gchar* text = atk_text_get_text(ATK_TEXT(m_element), 0, -1);
419     GOwnPtr<gchar> axValue(g_strdup_printf("AXValue: %s", replaceCharactersForResults(text)));
420     g_free(text);
421
422     return JSStringCreateWithUTF8CString(axValue.get());
423 }
424
425 JSStringRef AccessibilityUIElement::language()
426 {
427     // FIXME: implement
428     return JSStringCreateWithCharacters(0, 0);
429 }
430
431 JSStringRef AccessibilityUIElement::helpText() const
432 {
433     if (!m_element)
434         return JSStringCreateWithCharacters(0, 0);
435
436     ASSERT(ATK_IS_OBJECT(m_element));
437
438     CString helpText = DumpRenderTreeSupportGtk::accessibilityHelpText(ATK_OBJECT(m_element));
439     GOwnPtr<gchar> axHelpText(g_strdup_printf("AXHelp: %s", helpText.data()));
440     return JSStringCreateWithUTF8CString(axHelpText.get());
441 }
442
443 double AccessibilityUIElement::x()
444 {
445     int x, y;
446
447     atk_component_get_position(ATK_COMPONENT(m_element), &x, &y, ATK_XY_SCREEN);
448
449     return x;
450 }
451
452 double AccessibilityUIElement::y()
453 {
454     int x, y;
455
456     atk_component_get_position(ATK_COMPONENT(m_element), &x, &y, ATK_XY_SCREEN);
457
458     return y;
459 }
460
461 double AccessibilityUIElement::width()
462 {
463     int width, height;
464
465     atk_component_get_size(ATK_COMPONENT(m_element), &width, &height);
466
467     return width;
468 }
469
470 double AccessibilityUIElement::height()
471 {
472     int width, height;
473
474     atk_component_get_size(ATK_COMPONENT(m_element), &width, &height);
475
476     return height;
477 }
478
479 double AccessibilityUIElement::clickPointX()
480 {
481     return 0.f;
482 }
483
484 double AccessibilityUIElement::clickPointY()
485 {
486     return 0.f;
487 }
488
489 JSStringRef AccessibilityUIElement::orientation() const
490 {
491     return 0;
492 }
493
494 double AccessibilityUIElement::intValue() const
495 {
496     GValue value = { 0, { { 0 } } };
497
498     if (!ATK_IS_VALUE(m_element))
499         return 0.0f;
500
501     atk_value_get_current_value(ATK_VALUE(m_element), &value);
502     if (!G_VALUE_HOLDS_FLOAT(&value))
503         return 0.0f;
504     return g_value_get_float(&value);
505 }
506
507 double AccessibilityUIElement::minValue()
508 {
509     GValue value = { 0, { { 0 } } };
510
511     if (!ATK_IS_VALUE(m_element))
512         return 0.0f;
513
514     atk_value_get_minimum_value(ATK_VALUE(m_element), &value);
515     if (!G_VALUE_HOLDS_FLOAT(&value))
516         return 0.0f;
517     return g_value_get_float(&value);
518 }
519
520 double AccessibilityUIElement::maxValue()
521 {
522     GValue value = { 0, { { 0 } } };
523
524     if (!ATK_IS_VALUE(m_element))
525         return 0.0f;
526
527     atk_value_get_maximum_value(ATK_VALUE(m_element), &value);
528     if (!G_VALUE_HOLDS_FLOAT(&value))
529         return 0.0f;
530     return g_value_get_float(&value);
531 }
532
533 JSStringRef AccessibilityUIElement::valueDescription()
534 {
535     // FIXME: implement after it has been implemented in ATK.
536     // See: https://bugzilla.gnome.org/show_bug.cgi?id=684576
537     return JSStringCreateWithCharacters(0, 0);
538 }
539
540 static bool checkElementState(PlatformUIElement element, AtkStateType stateType)
541 {
542     if (!ATK_IS_OBJECT(element))
543          return false;
544
545     GRefPtr<AtkStateSet> stateSet = adoptGRef(atk_object_ref_state_set(ATK_OBJECT(element)));
546     return atk_state_set_contains_state(stateSet.get(), stateType);
547 }
548
549 bool AccessibilityUIElement::isEnabled()
550 {
551     return checkElementState(m_element, ATK_STATE_ENABLED);
552 }
553
554 int AccessibilityUIElement::insertionPointLineNumber()
555 {
556     // FIXME: implement
557     return 0;
558 }
559
560 bool AccessibilityUIElement::isActionSupported(JSStringRef action)
561 {
562     // FIXME: implement
563     return false;
564 }
565
566 bool AccessibilityUIElement::isRequired() const
567 {
568     // FIXME: implement
569     return false;
570 }
571
572 bool AccessibilityUIElement::isFocused() const
573 {
574     if (!ATK_IS_OBJECT(m_element))
575         return false;
576
577     GRefPtr<AtkStateSet> stateSet = adoptGRef(atk_object_ref_state_set(ATK_OBJECT(m_element)));
578     gboolean isFocused = atk_state_set_contains_state(stateSet.get(), ATK_STATE_FOCUSED);
579
580     return isFocused;
581 }
582
583 bool AccessibilityUIElement::isSelected() const
584 {
585     return checkElementState(m_element, ATK_STATE_SELECTED);
586 }
587
588 int AccessibilityUIElement::hierarchicalLevel() const
589 {
590     // FIXME: implement
591     return 0;
592 }
593
594 bool AccessibilityUIElement::ariaIsGrabbed() const
595 {
596     return false;
597 }
598  
599 JSStringRef AccessibilityUIElement::ariaDropEffects() const
600 {   
601     return 0; 
602 }
603
604 bool AccessibilityUIElement::isExpanded() const
605 {
606     if (!ATK_IS_OBJECT(m_element))
607         return false;
608
609     GRefPtr<AtkStateSet> stateSet = adoptGRef(atk_object_ref_state_set(ATK_OBJECT(m_element)));
610     gboolean isExpanded = atk_state_set_contains_state(stateSet.get(), ATK_STATE_EXPANDED);
611
612     return isExpanded;
613 }
614
615 bool AccessibilityUIElement::isChecked() const
616 {
617     if (!ATK_IS_OBJECT(m_element))
618         return false;
619
620     GRefPtr<AtkStateSet> stateSet = adoptGRef(atk_object_ref_state_set(ATK_OBJECT(m_element)));
621     gboolean isChecked = atk_state_set_contains_state(stateSet.get(), ATK_STATE_CHECKED);
622
623     return isChecked;
624 }
625
626 JSStringRef AccessibilityUIElement::attributesOfColumnHeaders()
627 {
628     // FIXME: implement
629     return JSStringCreateWithCharacters(0, 0);
630 }
631
632 JSStringRef AccessibilityUIElement::attributesOfRowHeaders()
633 {
634     // FIXME: implement
635     return JSStringCreateWithCharacters(0, 0);
636 }
637
638 JSStringRef AccessibilityUIElement::attributesOfColumns()
639 {
640     // FIXME: implement
641     return JSStringCreateWithCharacters(0, 0);
642 }
643
644 JSStringRef AccessibilityUIElement::attributesOfRows()
645 {
646     // FIXME: implement
647     return JSStringCreateWithCharacters(0, 0);
648 }
649
650 JSStringRef AccessibilityUIElement::attributesOfVisibleCells()
651 {
652     // FIXME: implement
653     return JSStringCreateWithCharacters(0, 0);
654 }
655
656 JSStringRef AccessibilityUIElement::attributesOfHeader()
657 {
658     // FIXME: implement
659     return JSStringCreateWithCharacters(0, 0);
660 }
661
662 int AccessibilityUIElement::indexInTable()
663 {
664     // FIXME: implement
665     return 0;
666 }
667
668 static JSStringRef indexRangeInTable(PlatformUIElement element, bool isRowRange)
669 {
670     GOwnPtr<gchar> rangeString(g_strdup("{0, 0}"));
671
672     if (!element)
673         return JSStringCreateWithUTF8CString(rangeString.get());
674
675     ASSERT(ATK_IS_OBJECT(element));
676
677     AtkObject* axTable = atk_object_get_parent(ATK_OBJECT(element));
678     if (!axTable || !ATK_IS_TABLE(axTable))
679         return JSStringCreateWithUTF8CString(rangeString.get());
680
681     // Look for the cell in the table.
682     gint indexInParent = atk_object_get_index_in_parent(ATK_OBJECT(element));
683     if (indexInParent == -1)
684         return JSStringCreateWithUTF8CString(rangeString.get());
685
686     int row = -1;
687     int column = -1;
688     row = atk_table_get_row_at_index(ATK_TABLE(axTable), indexInParent);
689     column = atk_table_get_column_at_index(ATK_TABLE(axTable), indexInParent);
690
691     // Get the actual values, if row and columns are valid values.
692     if (row != -1 && column != -1) {
693         int base = 0;
694         int length = 0;
695         if (isRowRange) {
696             base = row;
697             length = atk_table_get_row_extent_at(ATK_TABLE(axTable), row, column);
698         } else {
699             base = column;
700             length = atk_table_get_column_extent_at(ATK_TABLE(axTable), row, column);
701         }
702         rangeString.set(g_strdup_printf("{%d, %d}", base, length));
703     }
704
705     return JSStringCreateWithUTF8CString(rangeString.get());
706 }
707
708 JSStringRef AccessibilityUIElement::rowIndexRange()
709 {
710     // Range in table for rows.
711     return indexRangeInTable(m_element, true);
712 }
713
714 JSStringRef AccessibilityUIElement::columnIndexRange()
715 {
716     // Range in table for columns.
717     return indexRangeInTable(m_element, false);
718 }
719
720 int AccessibilityUIElement::lineForIndex(int)
721 {
722     // FIXME: implement
723     return 0;
724 }
725
726 JSStringRef AccessibilityUIElement::boundsForRange(unsigned location, unsigned length)
727 {
728     // FIXME: implement
729     return JSStringCreateWithCharacters(0, 0);
730 }
731
732 JSStringRef AccessibilityUIElement::stringForRange(unsigned, unsigned) 
733 {
734     // FIXME: implement
735     return JSStringCreateWithCharacters(0, 0);
736
737
738 JSStringRef AccessibilityUIElement::attributedStringForRange(unsigned, unsigned)
739 {
740     // FIXME: implement
741     return JSStringCreateWithCharacters(0, 0);
742 }
743
744 bool AccessibilityUIElement::attributedStringRangeIsMisspelled(unsigned location, unsigned length)
745 {
746     // FIXME: implement
747     return false;
748 }
749
750 AccessibilityUIElement AccessibilityUIElement::uiElementForSearchPredicate(AccessibilityUIElement* startElement, bool isDirectionNext, JSStringRef searchKey, JSStringRef searchText)
751 {
752     // FIXME: implement
753     return 0;
754 }
755
756 AccessibilityUIElement AccessibilityUIElement::cellForColumnAndRow(unsigned column, unsigned row)
757 {
758     if (!m_element)
759         return 0;
760
761     ASSERT(ATK_IS_TABLE(m_element));
762
763     AtkObject* foundCell = atk_table_ref_at(ATK_TABLE(m_element), row, column);
764     return foundCell ? AccessibilityUIElement(foundCell) : 0;
765 }
766
767 JSStringRef AccessibilityUIElement::selectedTextRange()
768 {
769     // FIXME: implement
770     return JSStringCreateWithCharacters(0, 0);
771 }
772
773 void AccessibilityUIElement::setSelectedTextRange(unsigned location, unsigned length)
774 {
775     // FIXME: implement
776 }
777
778 JSStringRef AccessibilityUIElement::stringAttributeValue(JSStringRef attribute)
779 {
780     if (!m_element)
781         return JSStringCreateWithCharacters(0, 0);
782
783     String atkAttributeName = coreAttributeToAtkAttribute(attribute);
784     if (atkAttributeName.isEmpty())
785         return JSStringCreateWithCharacters(0, 0);
786
787     for (GSList* atkAttributes = atk_object_get_attributes(ATK_OBJECT(m_element)); atkAttributes; atkAttributes = atkAttributes->next) {
788         AtkAttribute* atkAttribute = static_cast<AtkAttribute*>(atkAttributes->data);
789         if (!strcmp(atkAttribute->name, atkAttributeName.utf8().data()))
790             return JSStringCreateWithUTF8CString(atkAttribute->value);
791     }
792
793     return JSStringCreateWithCharacters(0, 0);
794 }
795
796 double AccessibilityUIElement::numberAttributeValue(JSStringRef attribute)
797 {
798     // FIXME: implement
799     return 0.0f;
800 }
801
802 bool AccessibilityUIElement::boolAttributeValue(JSStringRef attribute)
803 {
804     // FIXME: implement
805     return false;
806 }
807
808 bool AccessibilityUIElement::isAttributeSettable(JSStringRef attribute)
809 {
810     // FIXME: implement
811     return false;
812 }
813
814 bool AccessibilityUIElement::isAttributeSupported(JSStringRef attribute)
815 {
816     return false;
817 }
818
819 static void alterCurrentValue(PlatformUIElement element, int factor)
820 {
821     if (!element)
822         return;
823
824     ASSERT(ATK_IS_VALUE(element));
825
826     GValue currentValue = G_VALUE_INIT;
827     atk_value_get_current_value(ATK_VALUE(element), &currentValue);
828
829     GValue increment = G_VALUE_INIT;
830     atk_value_get_minimum_increment(ATK_VALUE(element), &increment);
831
832     GValue newValue = G_VALUE_INIT;
833     g_value_init(&newValue, G_TYPE_FLOAT);
834
835     g_value_set_float(&newValue, g_value_get_float(&currentValue) + factor * g_value_get_float(&increment));
836     atk_value_set_current_value(ATK_VALUE(element), &newValue);
837
838     g_value_unset(&newValue);
839     g_value_unset(&increment);
840     g_value_unset(&currentValue);
841 }
842
843 void AccessibilityUIElement::increment()
844 {
845     alterCurrentValue(m_element, 1);
846 }
847
848 void AccessibilityUIElement::decrement()
849 {
850     alterCurrentValue(m_element, -1);
851 }
852
853 void AccessibilityUIElement::press()
854 {
855     if (!m_element)
856         return;
857
858     ASSERT(ATK_IS_OBJECT(m_element));
859
860     if (!ATK_IS_ACTION(m_element))
861         return;
862
863     // Only one action per object is supported so far.
864     atk_action_do_action(ATK_ACTION(m_element), 0);
865 }
866
867 void AccessibilityUIElement::showMenu()
868 {
869     // FIXME: implement
870 }
871
872 AccessibilityUIElement AccessibilityUIElement::disclosedRowAtIndex(unsigned index)
873 {
874     return 0;
875 }
876
877 AccessibilityUIElement AccessibilityUIElement::ariaOwnsElementAtIndex(unsigned index)
878 {
879     return 0;
880 }
881
882 AccessibilityUIElement AccessibilityUIElement::ariaFlowToElementAtIndex(unsigned index)
883 {
884     return 0;
885 }
886
887 AccessibilityUIElement AccessibilityUIElement::selectedRowAtIndex(unsigned index)
888 {
889     return 0;
890 }
891
892 AccessibilityUIElement AccessibilityUIElement::rowAtIndex(unsigned index)
893 {
894     return 0;
895 }
896
897 AccessibilityUIElement AccessibilityUIElement::disclosedByRow()
898 {
899     return 0;
900 }
901
902 JSStringRef AccessibilityUIElement::accessibilityValue() const
903 {
904     // FIXME: implement
905     return JSStringCreateWithCharacters(0, 0);
906 }
907
908 JSStringRef AccessibilityUIElement::documentEncoding()
909 {
910     AtkRole role = atk_object_get_role(ATK_OBJECT(m_element));
911     if (role != ATK_ROLE_DOCUMENT_FRAME)
912         return JSStringCreateWithCharacters(0, 0);
913
914     return JSStringCreateWithUTF8CString(atk_document_get_attribute_value(ATK_DOCUMENT(m_element), "Encoding"));
915 }
916
917 JSStringRef AccessibilityUIElement::documentURI()
918 {
919     AtkRole role = atk_object_get_role(ATK_OBJECT(m_element));
920     if (role != ATK_ROLE_DOCUMENT_FRAME)
921         return JSStringCreateWithCharacters(0, 0);
922
923     return JSStringCreateWithUTF8CString(atk_document_get_attribute_value(ATK_DOCUMENT(m_element), "URI"));
924 }
925
926 JSStringRef AccessibilityUIElement::url()
927 {
928     // FIXME: implement
929     return JSStringCreateWithCharacters(0, 0);
930 }
931
932 bool AccessibilityUIElement::addNotificationListener(JSObjectRef functionCallback)
933 {
934     // FIXME: implement
935     return false;
936 }
937
938 void AccessibilityUIElement::removeNotificationListener()
939 {
940     // FIXME: implement
941 }
942
943 bool AccessibilityUIElement::isFocusable() const
944 {
945     if (!ATK_IS_OBJECT(m_element))
946         return false;
947
948     GRefPtr<AtkStateSet> stateSet = adoptGRef(atk_object_ref_state_set(ATK_OBJECT(m_element)));
949     gboolean isFocusable = atk_state_set_contains_state(stateSet.get(), ATK_STATE_FOCUSABLE);
950
951     return isFocusable;
952 }
953
954 bool AccessibilityUIElement::isSelectable() const
955 {
956     return checkElementState(m_element, ATK_STATE_SELECTABLE);
957 }
958
959 bool AccessibilityUIElement::isMultiSelectable() const
960 {
961     return checkElementState(m_element, ATK_STATE_MULTISELECTABLE);
962 }
963
964 bool AccessibilityUIElement::isSelectedOptionActive() const
965 {
966     // FIXME: implement
967     return false;
968 }
969
970 bool AccessibilityUIElement::isVisible() const
971 {
972     // FIXME: implement
973     return false;
974 }
975
976 bool AccessibilityUIElement::isOffScreen() const
977 {
978     // FIXME: implement
979     return false;
980 }
981
982 bool AccessibilityUIElement::isCollapsed() const
983 {
984     // FIXME: implement
985     return false;
986 }
987
988 bool AccessibilityUIElement::isIgnored() const
989 {
990     // FIXME: implement
991     return false;
992 }
993
994 bool AccessibilityUIElement::hasPopup() const
995 {
996     // FIXME: implement
997     return false;
998 }
999
1000 void AccessibilityUIElement::takeFocus()
1001 {
1002     // FIXME: implement
1003 }
1004
1005 void AccessibilityUIElement::takeSelection()
1006 {
1007     // FIXME: implement
1008 }
1009
1010 void AccessibilityUIElement::addSelection()
1011 {
1012     // FIXME: implement
1013 }
1014
1015 void AccessibilityUIElement::removeSelection()
1016 {
1017     // FIXME: implement
1018 }
1019
1020 void AccessibilityUIElement::scrollToMakeVisible()
1021 {
1022     // FIXME: implement
1023 }
1024
1025 void AccessibilityUIElement::scrollToMakeVisibleWithSubFocus(int x, int y, int width, int height)
1026 {
1027     // FIXME: implement
1028 }
1029
1030 void AccessibilityUIElement::scrollToGlobalPoint(int x, int y)
1031 {
1032     // FIXME: implement
1033 }