2008-04-02 Beth Dakin <bdakin@apple.com>
[WebKit-https.git] / WebCore / page / AccessibilityObject.cpp
1 /*
2  * Copyright (C) 2008 Apple Inc. All rights reserved.
3  *
4  * Redistribution and use in source and binary forms, with or without
5  * modification, are permitted provided that the following conditions
6  * are met:
7  *
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  * 3.  Neither the name of Apple Computer, Inc. ("Apple") nor the names of
14  *     its contributors may be used to endorse or promote products derived
15  *     from this software without specific prior written permission.
16  *
17  * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY
18  * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
19  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
20  * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY
21  * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
22  * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
23  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
24  * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
26  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27  */
28
29 #include "config.h"
30 #include "AccessibilityObject.h"
31
32 #include "AXObjectCache.h"
33 #include "CharacterNames.h"
34 #include "EventNames.h"
35 #include "FocusController.h"
36 #include "Frame.h"
37 #include "FrameLoader.h"
38 #include "HTMLAreaElement.h"
39 #include "HTMLFrameElementBase.h"
40 #include "HTMLImageElement.h"
41 #include "HTMLInputElement.h"
42 #include "HTMLLabelElement.h"
43 #include "HTMLMapElement.h"
44 #include "HTMLSelectElement.h"
45 #include "HTMLTextAreaElement.h"
46 #include "HitTestRequest.h"
47 #include "HitTestResult.h"
48 #include "NodeList.h"
49 #include "Page.h"
50 #include "RenderImage.h"
51 #include "RenderListMarker.h"
52 #include "RenderMenuList.h"
53 #include "RenderTextControl.h"
54 #include "RenderTheme.h"
55 #include "RenderView.h"
56 #include "RenderWidget.h"
57 #include "SelectionController.h"
58 #include "TextIterator.h"
59 #include "htmlediting.h"
60 #include "visible_units.h"
61
62 using namespace std;
63
64 namespace WebCore {
65
66 using namespace EventNames;
67 using namespace HTMLNames;
68
69 AccessibilityObject::AccessibilityObject(RenderObject* renderer)
70     : m_renderer(renderer)
71     , m_id(0)
72 {
73 #ifndef NDEBUG
74     m_renderer->setHasAXObject(true); 
75 #endif 
76 }
77
78 AccessibilityObject::~AccessibilityObject()
79 {
80     ASSERT(detached());
81 }
82
83 PassRefPtr<AccessibilityObject> AccessibilityObject::create(RenderObject* renderer)
84 {
85     return adoptRef(new AccessibilityObject(renderer));
86 }
87
88 void AccessibilityObject::detach()
89 {
90     removeAXObjectID();
91 #ifndef NDEBUG 
92     if (m_renderer) 
93         m_renderer->setHasAXObject(false); 
94 #endif
95     m_renderer = 0;
96     m_wrapper = 0;
97     clearChildren();
98 }
99
100 AccessibilityObject* AccessibilityObject::firstChild()
101 {
102     if (!m_renderer || !m_renderer->firstChild())
103         return 0;
104
105     return m_renderer->document()->axObjectCache()->get(m_renderer->firstChild());
106 }
107
108 AccessibilityObject* AccessibilityObject::lastChild()
109 {
110     if (!m_renderer || !m_renderer->lastChild())
111         return 0;
112
113     return m_renderer->document()->axObjectCache()->get(m_renderer->lastChild());
114 }
115
116 AccessibilityObject* AccessibilityObject::previousSibling()
117 {
118     if (!m_renderer || !m_renderer->previousSibling())
119         return 0;
120
121     return m_renderer->document()->axObjectCache()->get(m_renderer->previousSibling());
122 }
123
124 AccessibilityObject* AccessibilityObject::nextSibling()
125 {
126     if (!m_renderer || !m_renderer->nextSibling())
127         return 0;
128
129     return m_renderer->document()->axObjectCache()->get(m_renderer->nextSibling());
130 }
131
132 AccessibilityObject* AccessibilityObject::parentObject()
133 {
134     if (m_areaElement)
135         return m_renderer->document()->axObjectCache()->get(m_renderer);
136
137     if (!m_renderer || !m_renderer->parent())
138         return 0;
139
140     return m_renderer->document()->axObjectCache()->get(m_renderer->parent());
141 }
142
143 AccessibilityObject* AccessibilityObject::parentObjectUnignored()
144 {
145     AccessibilityObject* parent;
146     for (parent = parentObject(); parent && parent->accessibilityIsIgnored(); parent = parent->parentObject())
147         ;
148     return parent;
149 }
150
151 bool AccessibilityObject::isWebArea() const
152 {
153     return m_renderer->isRenderView();
154 }
155
156 bool AccessibilityObject::isImageButton() const
157 {
158     return m_renderer->isImage() && m_renderer->element() && m_renderer->element()->hasTagName(inputTag);
159 }
160
161 bool AccessibilityObject::isAnchor() const
162 {
163     return m_areaElement || (!m_renderer->isImage() && m_renderer->element() && m_renderer->element()->isLink());
164
165
166 bool AccessibilityObject::isTextControl() const
167 {
168     return m_renderer->isTextField() || m_renderer->isTextArea();
169 }
170
171 bool AccessibilityObject::isImage() const
172 {
173     return m_renderer->isImage();
174 }
175
176 bool AccessibilityObject::isAttachment() const
177 {
178     // widgets are the replaced elements that we represent to AX as attachments
179     bool isWidget = m_renderer && m_renderer->isWidget();
180     
181     // assert that a widget is a replaced element that is not an image
182     ASSERT(!isWidget || (m_renderer->isReplaced() && !m_renderer->isImage()));
183     return isWidget;
184 }
185
186 bool AccessibilityObject::isPasswordField() const
187 {
188     if (!m_renderer)
189         return 0;
190     if (!m_renderer->element())
191         return 0;
192     if (!m_renderer->element()->isHTMLElement())
193         return 0;
194     return static_cast<HTMLElement*>(m_renderer->element())->isPasswordField();
195 }
196
197 int AccessibilityObject::headingLevel(Node* node) const
198 {
199     // headings can be in block flow and non-block flow
200
201     if (!node)
202         return 0;
203     
204     if (node->hasTagName(h1Tag))
205         return 1;
206     
207     if (node->hasTagName(h2Tag))
208         return 2;
209     
210     if (node->hasTagName(h3Tag))
211         return 3;
212     
213     if (node->hasTagName(h4Tag))
214         return 4;
215     
216     if (node->hasTagName(h5Tag))
217         return 5;
218     
219     if (node->hasTagName(h6Tag))
220         return 6;
221
222     return 0;
223 }
224
225 bool AccessibilityObject::isHeading() const
226 {
227     return headingLevel(m_renderer->element()) != 0;
228 }
229
230 HTMLAnchorElement* AccessibilityObject::anchorElement()
231 {
232     // return already-known anchor for image areas
233     if (m_areaElement)
234         return m_areaElement.get();
235
236     // Search up the render tree for a RenderObject with a DOM node.  Defer to an earlier continuation, though.
237     RenderObject* currRenderer;
238     for (currRenderer = m_renderer; currRenderer && !currRenderer->element(); currRenderer = currRenderer->parent()) {
239         if (currRenderer->continuation())
240             return currRenderer->document()->axObjectCache()->get(currRenderer->continuation())->anchorElement();
241     }
242     
243     // bail if none found
244     if (!currRenderer)
245         return 0;
246     
247     // search up the DOM tree for an anchor element
248     // NOTE: this assumes that any non-image with an anchor is an HTMLAnchorElement
249     Node* node = currRenderer->node();
250     for ( ; node; node = node->parentNode()) {
251         if (node->hasTagName(aTag))
252             return static_cast<HTMLAnchorElement*>(node);
253     }
254
255     return 0;
256 }
257
258 static bool isCheckboxOrRadio(HTMLInputElement* input)
259 {
260     return (input->inputType() == HTMLInputElement::CHECKBOX ||
261             input->inputType() == HTMLInputElement::RADIO);
262 }
263
264 static bool isCheckboxOrRadio(Node* node)
265 {
266     if (!node->hasTagName(inputTag))
267         return false;
268     return isCheckboxOrRadio(static_cast<HTMLInputElement*>(node));
269 }
270
271 Element* AccessibilityObject::actionElement()
272 {
273     if (m_renderer->element() && m_renderer->element()->hasTagName(inputTag)) {
274         HTMLInputElement* input = static_cast<HTMLInputElement*>(m_renderer->element());
275         if (!input->disabled() && (isCheckboxOrRadio(input) ||
276                                    input->isTextButton()))
277             return input;
278     }
279
280     if (isImageButton())
281         return static_cast<Element*>(m_renderer->element());
282         
283     if (m_renderer->isMenuList())
284         return static_cast<RenderMenuList*>(m_renderer)->selectElement();
285
286     Element* elt = anchorElement();
287     if (!elt)
288         elt = mouseButtonListener();
289     return elt;
290 }
291
292 Element* AccessibilityObject::mouseButtonListener()
293 {
294     Node* node = m_renderer->element();
295     if (!node)
296         return 0;
297     if (!node->isEventTargetNode())
298         return 0;
299         
300     // FIXME: Do the continuation search like anchorElement does
301     for (EventTargetNode* elt = static_cast<EventTargetNode*>(node); elt; elt = static_cast<EventTargetNode*>(elt->parentNode())) {
302         if (elt->getHTMLEventListener(clickEvent) || elt->getHTMLEventListener(mousedownEvent) || elt->getHTMLEventListener(mouseupEvent))
303             return static_cast<Element*>(elt);
304     }
305
306     return 0;
307 }
308
309 String AccessibilityObject::helpText()
310 {
311     if (!m_renderer)
312         return String();
313
314     if (m_areaElement) {
315         const AtomicString& summary = m_areaElement->getAttribute(summaryAttr);
316         if (!summary.isEmpty())
317             return summary;
318         const AtomicString& title = m_areaElement->getAttribute(titleAttr);
319         if (!title.isEmpty())
320             return title;
321     }
322
323     for (RenderObject* curr = m_renderer; curr; curr = curr->parent()) {
324         if (curr->element() && curr->element()->isHTMLElement()) {
325             const AtomicString& summary = static_cast<Element*>(curr->element())->getAttribute(summaryAttr);
326             if (!summary.isEmpty())
327                 return summary;
328             const AtomicString& title = static_cast<Element*>(curr->element())->getAttribute(titleAttr);
329             if (!title.isEmpty())
330                 return title;
331         }
332     }
333
334     return String();
335 }
336
337 String AccessibilityObject::textUnderElement()
338 {
339     if (!m_renderer)
340         return String();
341
342     Node* node = m_renderer->element();
343     if (node) {
344         if (Frame* frame = node->document()->frame()) {
345             // catch stale WebCoreAXObject (see <rdar://problem/3960196>)
346             if (frame->document() != node->document())
347                 return String();
348             return plainText(rangeOfContents(node).get());
349         }
350     }
351
352     // return the null string for anonymous text because it is non-trivial to get
353     // the actual text and, so far, that is not needed
354     return String();
355 }
356
357 bool AccessibilityObject::hasIntValue()
358 {
359     if (isHeading())
360         return true;
361     
362     if (m_renderer->element() && isCheckboxOrRadio(m_renderer->element()))
363         return true;
364     
365     return false;
366 }
367
368 int AccessibilityObject::intValue()
369 {
370     if (!m_renderer || m_areaElement || isPasswordField())
371         return 0;
372
373     if (isHeading())
374         return headingLevel(m_renderer->element());
375
376     Node* node = m_renderer->element();
377     if (node && isCheckboxOrRadio(node))
378         return static_cast<HTMLInputElement*>(node)->checked();
379     
380     return 0;
381 }
382
383 String AccessibilityObject::stringValue()
384 {
385     if (!m_renderer || m_areaElement || isPasswordField())
386         return String();
387
388     if (m_renderer->isText())
389         return textUnderElement();
390     
391     if (m_renderer->isMenuList())
392         return static_cast<RenderMenuList*>(m_renderer)->text();
393     
394     if (m_renderer->isListMarker())
395         return static_cast<RenderListMarker*>(m_renderer)->text();
396
397     if (isWebArea()) {
398         if (m_renderer->document()->frame())
399             return String();
400         
401         // FIXME: should use startOfDocument and endOfDocument (or rangeForDocument?) here
402         VisiblePosition startVisiblePosition = m_renderer->positionForCoordinates(0, 0);
403         VisiblePosition endVisiblePosition = m_renderer->positionForCoordinates(INT_MAX, INT_MAX);
404         if (startVisiblePosition.isNull() || endVisiblePosition.isNull())
405             return String();
406             
407         return plainText(makeRange(startVisiblePosition, endVisiblePosition).get());
408     }    
409     
410     if (isTextControl())
411         return static_cast<RenderTextControl*>(m_renderer)->text();
412
413     // FIXME: We might need to implement a value here for more types
414     // FIXME: It would be better not to advertise a value at all for the types for which we don't implement one;
415     // this would require subclassing or making accessibilityAttributeNames do something other than return a
416     // single static array.
417     return String();
418 }
419
420 static HTMLLabelElement* labelForElement(Element* element)
421 {
422     RefPtr<NodeList> list = element->document()->getElementsByTagName("label");
423     unsigned len = list->length();
424     for (unsigned i = 0; i < len; i++) {
425         if (list->item(i)->hasTagName(labelTag)) {
426             HTMLLabelElement* label = static_cast<HTMLLabelElement*>(list->item(i));
427             if (label->correspondingControl() == element)
428                 return label;
429         }
430     }
431     
432     return 0;
433 }
434
435 String AccessibilityObject::title()
436 {
437     if (!m_renderer || m_areaElement || !m_renderer->element())
438         return String();
439     
440     if (m_renderer->element()->hasTagName(buttonTag))
441         return textUnderElement();
442         
443     if (m_renderer->element()->hasTagName(inputTag)) {
444         HTMLInputElement* input = static_cast<HTMLInputElement*>(m_renderer->element());
445         if (input->isTextButton())
446             return input->value();
447
448         HTMLLabelElement* label = labelForElement(input);
449         if (label)
450             return label->innerText();
451     }
452     
453     if (m_renderer->element()->isLink() || isHeading())
454         return textUnderElement();
455
456     return String();
457 }
458
459 String AccessibilityObject::accessibilityDescription()
460 {
461     if (!m_renderer || m_areaElement)
462         return String();
463     
464     if (m_renderer->isImage()) {
465         if (m_renderer->element() && m_renderer->element()->isHTMLElement()) {
466             const AtomicString& alt = static_cast<HTMLElement*>(m_renderer->element())->getAttribute(altAttr);
467             if (alt.isEmpty())
468                 return String();
469             return alt;
470         }
471     }
472
473     if (isWebArea()) {
474         Document *document = m_renderer->document();
475         Node* owner = document->ownerElement();
476         if (owner) {
477             if (owner->hasTagName(frameTag) || owner->hasTagName(iframeTag))
478                 return static_cast<HTMLFrameElementBase*>(owner)->name();
479             if (owner->isHTMLElement())
480                 return static_cast<HTMLElement*>(owner)->getAttribute(nameAttr);
481         } 
482         owner = document->body();
483         if (owner && owner->isHTMLElement()) 
484             return static_cast<HTMLElement*>(owner)->getAttribute(nameAttr);
485     }
486     
487     return String();
488 }
489
490 IntRect AccessibilityObject::boundingBoxRect()
491 {
492     IntRect rect;
493     RenderObject* obj = m_renderer;
494
495     if (!obj)
496         return IntRect();
497
498     if (obj->isInlineContinuation())
499         obj = obj->element()->renderer();
500     Vector<IntRect> rects;
501     int x, y;
502     obj->absolutePosition(x, y);
503     obj->absoluteRects(rects, x, y);
504     const size_t n = rects.size();
505     for (size_t i = 0; i < n; ++i) {
506         IntRect r = rects[i];
507         if (!r.isEmpty()) {
508             if (obj->style()->hasAppearance())
509                 theme()->adjustRepaintRect(obj, r);
510             rect.unite(r);
511         }
512     }
513     return rect;
514 }
515
516 IntSize AccessibilityObject::size()
517 {
518     IntRect rect = m_areaElement ? m_areaElement->getRect(m_renderer) : boundingBoxRect();
519     return rect.size();
520 }
521
522 // the closest object for an internal anchor
523 AccessibilityObject* AccessibilityObject::linkedUIElement()
524 {
525     if (!isAnchor())
526         return 0;
527     
528     HTMLAnchorElement* anchor = anchorElement();
529     if (!anchor) 
530         return 0;
531     
532     KURL linkURL = anchor->href();
533     String ref = linkURL.ref();
534     if (ref.isEmpty())
535         return 0;
536     
537     // check if URL is the same as current URL
538     linkURL.setRef("");
539     if (m_renderer->document()->url() != linkURL)
540         return 0;
541     
542     Node* linkedNode = m_renderer->document()->getElementById(ref);
543     if (!linkedNode) {
544         linkedNode = m_renderer->document()->anchors()->namedItem(ref, !m_renderer->document()->inCompatMode());
545         if (!linkedNode)
546             return 0;
547     }
548     
549     // the element we find may not be accessible, keep searching until we find a good one
550     AccessibilityObject* linkedAXElement = m_renderer->document()->axObjectCache()->get(linkedNode->renderer());
551     while (linkedAXElement && linkedAXElement->accessibilityIsIgnored()) {
552         linkedNode = linkedNode->traverseNextNode();
553         if (!linkedNode)
554             return 0;
555         linkedAXElement = m_renderer->document()->axObjectCache()->get(linkedNode->renderer());
556     }
557     
558     return linkedAXElement;    
559 }
560
561 bool AccessibilityObject::accessibilityShouldUseUniqueId()
562 {
563     return isWebArea() || isTextControl();
564 }
565
566 bool AccessibilityObject::accessibilityIsIgnored()
567 {
568     // ignore invisible element
569     if (!m_renderer || m_renderer->style()->visibility() != VISIBLE)
570         return true;
571
572     // ignore popup menu items because AppKit does
573     for (RenderObject* parent = m_renderer->parent(); parent; parent = parent->parent()) {
574         if (parent->isMenuList())
575             return true;
576     }
577     
578     // NOTE: BRs always have text boxes now, so the text box check here can be removed
579     if (m_renderer->isText())
580         return m_renderer->isBR() || !static_cast<RenderText*>(m_renderer)->firstTextBox();
581             
582     if (isHeading())
583         return false;
584     
585     if (m_areaElement || (m_renderer->element() && m_renderer->element()->isLink()))
586         return false;
587
588     // all controls are accessible
589     if (m_renderer->element() && m_renderer->element()->isControl())
590         return false;
591
592     if (m_renderer->isBlockFlow() && m_renderer->childrenInline())
593         return !static_cast<RenderBlock*>(m_renderer)->firstLineBox() && !mouseButtonListener();
594
595     // ignore images seemingly used as spacers
596     if (m_renderer->isImage()) {
597         // informal standard is to ignore images with zero-length alt strings
598         Node* node = m_renderer->element();
599         if (node && node->isElementNode()) { 
600             Element* elt = static_cast<Element*>(node);
601             const AtomicString& alt = elt->getAttribute(altAttr);
602             if (alt.isEmpty() && !alt.isNull())
603                 return true;
604         }
605         
606         // check for one-dimensional image
607         if (m_renderer->height() <= 1 || m_renderer->width() <= 1)
608             return true;
609         
610         // check whether rendered image was stretched from one-dimensional file image
611         RenderImage* image = static_cast<RenderImage*>(m_renderer);
612         if (image->cachedImage()) {
613             IntSize imageSize = image->cachedImage()->imageSize(image->view()->zoomFactor());
614             return imageSize.height() <= 1 || imageSize.width() <= 1;
615         }
616         
617         return false;
618     }
619     
620     return !m_renderer->isListMarker() && !isWebArea();
621 }
622
623 bool AccessibilityObject::loaded()
624 {
625     return !m_renderer->document()->tokenizer();
626 }
627
628 int AccessibilityObject::layoutCount()
629 {
630     return static_cast<RenderView*>(m_renderer)->frameView()->layoutCount();
631 }
632
633 int AccessibilityObject::textLength()
634 {
635     ASSERT(isTextControl());
636
637     if (isPasswordField())
638         return -1; // need to return something distinct from 0
639     
640     return static_cast<RenderTextControl*>(m_renderer)->text().length();
641 }
642
643 String AccessibilityObject::selectedText()
644 {
645     ASSERT(isTextControl());
646
647     if (isPasswordField())
648         return String(); // need to return something distinct from empty string
649
650     RenderTextControl* textControl = static_cast<RenderTextControl*>(m_renderer);
651     return textControl->text().substring(textControl->selectionStart(), textControl->selectionEnd() - textControl->selectionStart());
652 }
653
654 Selection AccessibilityObject::selection()
655 {
656     return m_renderer->document()->frame()->selectionController()->selection();
657 }
658
659 AccessibilityObject::PlainTextRange AccessibilityObject::selectedTextRange()
660 {
661     ASSERT(isTextControl());
662
663     if (isPasswordField())
664         return PlainTextRange();
665
666     RenderTextControl* textControl = static_cast<RenderTextControl*>(m_renderer);        
667     return PlainTextRange(textControl->selectionStart(), textControl->selectionEnd() - textControl->selectionStart());
668 }
669
670 void AccessibilityObject::setSelectedText(String text)
671 {
672     // TODO: set selected text (ReplaceSelectionCommand). <rdar://problem/4712125>
673 }
674
675 void AccessibilityObject::setSelectedTextRange(PlainTextRange range)
676 {
677     RenderTextControl* textControl = static_cast<RenderTextControl*>(m_renderer);
678     textControl->setSelectionRange(range.start, range.start + range.length);
679 }
680
681 void AccessibilityObject::makeRangeVisible(PlainTextRange range)
682 {
683     // TODO: make range visible (scrollRectToVisible).  <rdar://problem/4712101>
684 }
685
686 KURL AccessibilityObject::url()
687 {
688     if (isAnchor()) { 
689         if (HTMLAnchorElement* anchor = anchorElement())
690             return anchor->href();
691     }
692     if (m_renderer->isImage() && m_renderer->element() && m_renderer->element()->hasTagName(imgTag))
693         return static_cast<HTMLImageElement*>(m_renderer->element())->src();
694
695     return KURL();
696 }
697
698 bool AccessibilityObject::isVisited()
699 {
700     return m_renderer->style()->pseudoState() == PseudoVisited;
701 }
702
703 bool AccessibilityObject::isFocused()
704 {
705     return (m_renderer->element() && m_renderer->document()->focusedNode() == m_renderer->element());
706 }
707
708 void AccessibilityObject::setFocused(bool on)
709 {
710     if (!canSetFocusAttribute())
711         return;
712
713     if (!on)
714         m_renderer->document()->setFocusedNode(0);
715     else {
716         if (m_renderer->element()->isElementNode())
717             static_cast<Element*>(m_renderer->element())->focus();
718         else
719             m_renderer->document()->setFocusedNode(m_renderer->element());
720     }
721 }
722
723 void AccessibilityObject::setValue(String string)
724 {
725     if (m_renderer->isTextField()) {
726         HTMLInputElement* input = static_cast<HTMLInputElement*>(m_renderer->element());
727         input->setValue(string);
728     } else if (m_renderer->isTextArea()) {
729         HTMLTextAreaElement* textArea = static_cast<HTMLTextAreaElement*>(m_renderer->element());
730         textArea->setValue(string);
731     }
732 }
733
734 bool AccessibilityObject::isEnabled()
735 {
736     return m_renderer->element() ? m_renderer->element()->isEnabled() : true;
737 }
738
739 void AccessibilityObject::press()
740 {    
741     Element* actionElem = actionElement();
742     if (!actionElem)
743         return;
744     if (Frame* f = actionElem->document()->frame())
745         f->loader()->resetMultipleFormSubmissionProtection();
746     actionElem->accessKeyAction(true);
747 }
748
749 /*RenderObject* AccessibilityObject::renderer()
750 {
751     return m_renderer;
752 }*/
753
754 RenderObject* AccessibilityObject::topRenderer()
755 {
756     return m_renderer->document()->topDocument()->renderer();
757 }
758
759 RenderTextControl* AccessibilityObject::textControl()
760 {
761     if (!m_renderer->isTextField() && !m_renderer->isTextArea());
762         return 0;
763         
764     return static_cast<RenderTextControl*>(m_renderer);
765 }
766
767 Widget* AccessibilityObject::widget() 
768 {
769     if (!m_renderer->isWidget())
770         return 0;
771
772     return static_cast<RenderWidget*>(m_renderer)->widget();
773 }
774
775 AXObjectCache* AccessibilityObject::axObjectCache()
776 {
777     return m_renderer->document()->axObjectCache();
778 }
779
780 void AccessibilityObject::documentLinks(Vector<RefPtr<AccessibilityObject> >& result)
781 {
782     Document* document = m_renderer->document();
783     RefPtr<HTMLCollection> coll = document->links();
784     Node* curr = coll->firstItem();
785     while (curr) {
786         RenderObject* obj = curr->renderer();
787         if (obj) {
788             RefPtr<AccessibilityObject> axobj = document->axObjectCache()->get(obj);
789             ASSERT(axobj);
790             ASSERT(axobj->roleValue() == WebCoreLinkRole);
791             if (!axobj->accessibilityIsIgnored())
792                 result.append(axobj);
793         }
794         curr = coll->nextItem();
795     }
796 }
797
798 FrameView* AccessibilityObject::documentFrameView()
799 {
800     // this is the RenderObject's Document's Frame's FrameView
801     return m_renderer->document()->view();
802 }
803
804 Widget* AccessibilityObject::widgetForAttachmentView()
805 {
806     if (!isAttachment())
807         return 0;
808     return static_cast<RenderWidget*>(m_renderer)->widget();
809 }
810
811 FrameView* AccessibilityObject::frameViewIfRenderView()
812 {
813     if (!m_renderer->isRenderView())
814         return 0;
815     // this is the RenderObject's Document's renderer's FrameView
816     return m_renderer->view()->frameView();    
817 }
818
819 // This function is like a cross-platform version of - (WebCoreTextMarkerRange*)textMarkerRange. It returns 
820 // a Range that we can convert to a WebCoreTextMarkerRange in the Obj-C file
821 VisiblePositionRange AccessibilityObject::visiblePositionRange()
822 {
823     if (!m_renderer)
824         return VisiblePositionRange();
825     
826     // construct VisiblePositions for start and end
827     Node* node = m_renderer->element();
828     VisiblePosition startPos = VisiblePosition(node, 0, VP_DEFAULT_AFFINITY);
829     VisiblePosition endPos = VisiblePosition(node, maxDeepOffset(node), VP_DEFAULT_AFFINITY);
830     
831     // the VisiblePositions are equal for nodes like buttons, so adjust for that
832     if (startPos == endPos) {
833         endPos = endPos.next();
834         if (endPos.isNull())
835             endPos = startPos;
836     }
837     
838     return VisiblePositionRange(startPos, endPos);
839 }
840
841 VisiblePositionRange AccessibilityObject::doAXTextMarkerRangeForLine(unsigned lineCount)
842 {
843     if (lineCount == 0 || !m_renderer)
844         return VisiblePositionRange();
845     
846     // iterate over the lines
847     // FIXME: this is wrong when lineNumber is lineCount+1,  because nextLinePosition takes you to the
848     // last offset of the last line
849     VisiblePosition visiblePos = m_renderer->document()->renderer()->positionForCoordinates(0, 0);
850     VisiblePosition savedVisiblePos;
851     while (--lineCount != 0) {
852         savedVisiblePos = visiblePos;
853         visiblePos = nextLinePosition(visiblePos, 0);
854         if (visiblePos.isNull() || visiblePos == savedVisiblePos)
855             return VisiblePositionRange();
856     }
857     
858     // make a caret selection for the marker position, then extend it to the line
859     // NOTE: ignores results of sel.modify because it returns false when
860     // starting at an empty line.  The resulting selection in that case
861     // will be a caret at visiblePos.
862     SelectionController selectionController;
863     selectionController.setSelection(Selection(visiblePos));
864     selectionController.modify(SelectionController::EXTEND, SelectionController::RIGHT, LineBoundary);
865
866     return VisiblePositionRange(selectionController.selection().visibleStart(), selectionController.selection().visibleEnd());
867 }
868
869 VisiblePositionRange AccessibilityObject::doAXTextMarkerRangeForUnorderedTextMarkers(const VisiblePosition& visiblePos1, const VisiblePosition& visiblePos2)
870 {
871     if (visiblePos1.isNull() || visiblePos2.isNull())
872         return VisiblePositionRange();
873     
874     VisiblePosition startPos;
875     VisiblePosition endPos;
876     bool alreadyInOrder;
877     
878     // upstream is ordered before downstream for the same position
879     if (visiblePos1 == visiblePos2 && visiblePos2.affinity() == UPSTREAM) 
880         alreadyInOrder = false;
881     
882     // use selection order to see if the positions are in order
883     else 
884         alreadyInOrder = Selection(visiblePos1, visiblePos2).isBaseFirst();
885     
886     if (alreadyInOrder) {
887         startPos = visiblePos1;
888         endPos = visiblePos2;
889     } else {
890         startPos = visiblePos2;
891         endPos = visiblePos1;
892     }
893     
894     return VisiblePositionRange(startPos, endPos);
895 }
896
897 VisiblePositionRange AccessibilityObject::doAXLeftWordTextMarkerRangeForTextMarker(const VisiblePosition& visiblePos)
898 {
899     VisiblePosition startPosition = startOfWord(visiblePos, LeftWordIfOnBoundary);
900     VisiblePosition endPosition = endOfWord(startPosition);
901     return VisiblePositionRange(startPosition, endPosition);
902 }
903
904 VisiblePositionRange AccessibilityObject::doAXRightWordTextMarkerRangeForTextMarker(const VisiblePosition& visiblePos)
905 {
906     VisiblePosition startPosition = startOfWord(visiblePos, RightWordIfOnBoundary);
907     VisiblePosition endPosition = endOfWord(startPosition);
908     return VisiblePositionRange(startPosition, endPosition);
909 }
910
911 static VisiblePosition updateAXLineStartForVisiblePosition(const VisiblePosition& visiblePosition)
912 {
913     // A line in the accessibility sense should include floating objects, such as aligned image, as part of a line.
914     // So let's update the position to include that.
915     VisiblePosition tempPosition;
916     VisiblePosition startPosition = visiblePosition;
917     Position p;
918     RenderObject* renderer;
919     while (true) {
920         tempPosition = startPosition.previous();
921         if (tempPosition.isNull())
922             break;
923         p = tempPosition.deepEquivalent();
924         if (!p.node())
925             break;
926         renderer = p.node()->renderer();
927         if (!renderer || renderer->inlineBox(p.offset(), tempPosition.affinity()) || (renderer->isRenderBlock() && p.offset() == 0))
928             break;
929         startPosition = tempPosition;
930     }
931     
932     return startPosition;
933 }
934
935 VisiblePositionRange AccessibilityObject::doAXLeftLineTextMarkerRangeForTextMarker(const VisiblePosition& visiblePos)
936 {
937     if (visiblePos.isNull())
938         return VisiblePositionRange();
939     
940     // make a caret selection for the position before marker position (to make sure
941     // we move off of a line start)
942     VisiblePosition prevVisiblePos = visiblePos.previous();
943     if (prevVisiblePos.isNull())
944         return VisiblePositionRange();
945     
946     VisiblePosition startPosition = startOfLine(prevVisiblePos);
947
948     // keep searching for a valid line start position.  Unless the textmarker is at the very beginning, there should
949     // always be a valid line range.  However, startOfLine will return null for position next to a floating object, 
950     // since floating object doesn't really belong to any line.  
951     // This check will reposition the marker before the floating object, to ensure we get a line start.
952     if (startPosition.isNull()) {
953         while (startPosition.isNull() && prevVisiblePos.isNotNull()) {
954             prevVisiblePos = prevVisiblePos.previous();
955             startPosition = startOfLine(prevVisiblePos);
956         }
957     } else 
958         startPosition = updateAXLineStartForVisiblePosition(startPosition);
959     
960     VisiblePosition endPosition = endOfLine(prevVisiblePos);
961     return VisiblePositionRange(startPosition, endPosition);
962 }
963
964 VisiblePositionRange AccessibilityObject::doAXRightLineTextMarkerRangeForTextMarker(const VisiblePosition& visiblePos)
965 {
966     if (visiblePos.isNull())
967         return VisiblePositionRange();
968     
969     // make sure we move off of a line end
970     VisiblePosition nextVisiblePos = visiblePos.next();
971     if (nextVisiblePos.isNull())
972         return VisiblePositionRange();
973         
974     VisiblePosition startPosition = startOfLine(nextVisiblePos);
975     
976     // fetch for a valid line start position
977     if (startPosition.isNull() ) {
978         startPosition = visiblePos;
979         nextVisiblePos = nextVisiblePos.next();
980     } else 
981         startPosition = updateAXLineStartForVisiblePosition(startPosition);
982     
983     VisiblePosition endPosition = endOfLine(nextVisiblePos);
984
985     // as long as the position hasn't reached the end of the doc,  keep searching for a valid line end position
986     // Unless the textmarker is at the very end, there should always be a valid line range.  However, endOfLine will 
987     // return null for position by a floating object, since floating object doesn't really belong to any line.  
988     // This check will reposition the marker after the floating object, to ensure we get a line end.
989     while (endPosition.isNull() && nextVisiblePos.isNotNull()) {
990         nextVisiblePos = nextVisiblePos.next();
991         endPosition = endOfLine(nextVisiblePos);
992     }
993     
994     return VisiblePositionRange(startPosition, endPosition);
995 }
996
997 VisiblePositionRange AccessibilityObject::doAXSentenceTextMarkerRangeForTextMarker(const VisiblePosition& visiblePos)
998 {
999     // FIXME: FO 2 IMPLEMENT (currently returns incorrect answer)
1000     // Related? <rdar://problem/3927736> Text selection broken in 8A336
1001     VisiblePosition startPosition = startOfSentence(visiblePos);
1002     VisiblePosition endPosition = endOfSentence(startPosition);
1003     return VisiblePositionRange(startPosition, endPosition);
1004 }
1005
1006 VisiblePositionRange AccessibilityObject::doAXParagraphTextMarkerRangeForTextMarker(const VisiblePosition& visiblePos)
1007 {
1008     VisiblePosition startPosition = startOfParagraph(visiblePos);
1009     VisiblePosition endPosition = endOfParagraph(startPosition);
1010     return VisiblePositionRange(startPosition, endPosition);
1011 }
1012
1013 static VisiblePosition startOfStyleRange(const VisiblePosition visiblePos)
1014 {
1015     RenderObject* renderer = visiblePos.deepEquivalent().node()->renderer();
1016     RenderObject* startRenderer = renderer;
1017     RenderStyle* style = renderer->style();
1018     
1019     // traverse backward by renderer to look for style change
1020     for (RenderObject* r = renderer->previousInPreOrder(); r; r = r->previousInPreOrder()) {
1021         // skip non-leaf nodes
1022         if (r->firstChild())
1023             continue;
1024         
1025         // stop at style change
1026         if (r->style() != style)
1027             break;
1028             
1029         // remember match
1030         startRenderer = r;
1031     }
1032     
1033     return VisiblePosition(startRenderer->node(), 0, VP_DEFAULT_AFFINITY);
1034 }
1035
1036 static VisiblePosition endOfStyleRange(const VisiblePosition visiblePos)
1037 {
1038     RenderObject* renderer = visiblePos.deepEquivalent().node()->renderer();
1039     RenderObject* endRenderer = renderer;
1040     RenderStyle* style = renderer->style();
1041
1042     // traverse forward by renderer to look for style change
1043     for (RenderObject* r = renderer->nextInPreOrder(); r; r = r->nextInPreOrder()) {
1044         // skip non-leaf nodes
1045         if (r->firstChild())
1046             continue;
1047         
1048         // stop at style change
1049         if (r->style() != style)
1050             break;
1051         
1052         // remember match
1053         endRenderer = r;
1054     }
1055     
1056     return VisiblePosition(endRenderer->node(), maxDeepOffset(endRenderer->node()), VP_DEFAULT_AFFINITY);
1057 }
1058
1059 VisiblePositionRange AccessibilityObject::doAXStyleTextMarkerRangeForTextMarker(const VisiblePosition& visiblePos)
1060 {
1061     if (visiblePos.isNull())
1062         return VisiblePositionRange();
1063
1064     return VisiblePositionRange(startOfStyleRange(visiblePos), endOfStyleRange(visiblePos));
1065 }
1066
1067 // NOTE: Consider providing this utility method as AX API
1068 VisiblePositionRange AccessibilityObject::textMarkerRangeForRange(const PlainTextRange& range, RenderTextControl* textControl)
1069 {
1070     if (range.start + range.length > textControl->text().length())
1071         return VisiblePositionRange();
1072     
1073     VisiblePosition startPosition = textControl->visiblePositionForIndex(range.start);
1074     startPosition.setAffinity(DOWNSTREAM);
1075     VisiblePosition endPosition = textControl->visiblePositionForIndex(range.start + range.length);
1076     return VisiblePositionRange(startPosition, endPosition);
1077 }
1078
1079 String AccessibilityObject::stringForReplacedNode(Node* replacedNode)
1080 {
1081     // we should always be given a rendered node and a replaced node, but be safe
1082     // replaced nodes are either attachments (widgets) or images
1083     if (!replacedNode || !replacedNode->renderer() || !replacedNode->renderer()->isReplaced() || replacedNode->isTextNode()) {
1084         ASSERT_NOT_REACHED();
1085         return String();
1086     }
1087
1088     // create an AX object, but skip it if it is not supposed to be seen
1089     AccessibilityObject* object = replacedNode->renderer()->document()->axObjectCache()->get(replacedNode->renderer());
1090     if (object->accessibilityIsIgnored())
1091         return String();
1092     
1093     return String(&objectReplacementCharacter, 1);
1094 }
1095
1096 String AccessibilityObject::doAXStringForTextMarkerRange(VisiblePositionRange& visiblePositionRange)
1097 {
1098     if (visiblePositionRange.isNull())
1099         return String();
1100         
1101     String resultString;
1102     TextIterator it(makeRange(visiblePositionRange.start, visiblePositionRange.end).get());
1103     while (!it.atEnd()) {
1104         // non-zero length means textual node, zero length means replaced node (AKA "attachments" in AX)
1105         if (it.length() != 0) {
1106             resultString.append(it.characters(), it.length());
1107         } else {
1108             // locate the node and starting offset for this replaced range
1109             int exception = 0;
1110             Node* node = it.range()->startContainer(exception);
1111             ASSERT(node == it.range()->endContainer(exception));
1112             int offset = it.range()->startOffset(exception);
1113             String attachmentString = stringForReplacedNode(node->childNode(offset));
1114             
1115             // append the replacement string
1116             if (!attachmentString.isNull())
1117                 resultString.append(attachmentString);
1118         }
1119         it.advance();
1120     }
1121     
1122     return resultString.isEmpty() ? String() : resultString;
1123 }
1124
1125 IntRect AccessibilityObject::doAXBoundsForTextMarkerRange(VisiblePositionRange visiblePositionRange)
1126 {
1127     if (visiblePositionRange.isNull())
1128         return IntRect();
1129     
1130     IntRect rect1 = visiblePositionRange.start.caretRect();
1131     IntRect rect2 = visiblePositionRange.end.caretRect();
1132
1133     // readjust for position at the edge of a line.  This is to exclude line rect that doesn't need to be accounted in the range bounds 
1134     if (rect2.y() != rect1.y()) {
1135         VisiblePosition endOfFirstLine = endOfLine(visiblePositionRange.start);
1136         if (visiblePositionRange.start == endOfFirstLine) {
1137             visiblePositionRange.start.setAffinity(DOWNSTREAM);
1138             rect1 = visiblePositionRange.start.caretRect();
1139         }
1140         if (visiblePositionRange.end == endOfFirstLine) {
1141             visiblePositionRange.end.setAffinity(UPSTREAM);
1142             rect2 = visiblePositionRange.end.caretRect();
1143         }
1144     }
1145
1146     IntRect ourrect = rect1;
1147     ourrect.unite(rect2);
1148
1149     // if the rectangle spans lines and contains multiple text chars, use the range's bounding box intead
1150     if (rect1.bottom() != rect2.bottom()) {
1151         RefPtr<Range> dataRange = makeRange(visiblePositionRange.start, visiblePositionRange.end);
1152         IntRect boundingBox = dataRange->boundingBox();
1153         String rangeString = plainText(dataRange.get());
1154         if (rangeString.length() > 1 && !boundingBox.isEmpty()) 
1155             ourrect = boundingBox;
1156     }
1157
1158 #if PLATFORM(MAC)
1159     return m_renderer->document()->view()->contentsToScreen(ourrect);
1160 #else
1161     return ourrect;
1162 #endif
1163 }
1164
1165 int AccessibilityObject::doAXLengthForTextMarkerRange(VisiblePositionRange visiblePositionRange)
1166 {
1167     // FIXME: Multi-byte support
1168     String string = doAXStringForTextMarkerRange(visiblePositionRange);
1169     if (string.isEmpty())
1170         return -1;
1171
1172     return string.length();
1173 }
1174
1175 void AccessibilityObject::doSetAXSelectedTextMarkerRange(VisiblePositionRange textMarkerRange)
1176 {
1177     if (textMarkerRange.start.isNull() || textMarkerRange.end.isNull())
1178         return;
1179     
1180     // make selection and tell the document to use it
1181     Selection newSelection = Selection(textMarkerRange.start, textMarkerRange.end);
1182     m_renderer->document()->frame()->selectionController()->setSelection(newSelection);
1183 }
1184
1185 VisiblePosition AccessibilityObject::doAXTextMarkerForPosition(const IntPoint& point)
1186 {
1187     // convert absolute point to view coordinates
1188     FrameView* frameView = m_renderer->document()->topDocument()->renderer()->view()->frameView();
1189     RenderObject* renderer = topRenderer();
1190     Node* innerNode = 0;
1191     
1192     // locate the node containing the point
1193     IntPoint pointResult;
1194     while (1) {
1195         IntPoint ourpoint;
1196 #if PLATFORM(MAC)
1197         ourpoint = frameView->screenToContents(point);
1198 #else
1199         ourpoint = point;
1200 #endif
1201         HitTestRequest request(true, true);
1202         HitTestResult result(ourpoint);
1203         renderer->layer()->hitTest(request, result);
1204         innerNode = result.innerNode();
1205         if (!innerNode || !innerNode->renderer())
1206             return VisiblePosition();
1207
1208         pointResult = result.localPoint();
1209
1210         // done if hit something other than a widget
1211         renderer = innerNode->renderer();
1212         if (!renderer->isWidget())
1213             break;
1214
1215         // descend into widget (FRAME, IFRAME, OBJECT...)
1216         Widget* widget = static_cast<RenderWidget*>(renderer)->widget();
1217         if (!widget || !widget->isFrameView())
1218             break;
1219         Frame* frame = static_cast<FrameView*>(widget)->frame();
1220         if (!frame)
1221             break;
1222         Document* document = frame->document();
1223         if (!document)
1224             break;
1225         renderer = document->renderer();
1226         frameView = static_cast<FrameView*>(widget);
1227     }
1228     
1229     return innerNode->renderer()->positionForPoint(pointResult);
1230 }
1231
1232 VisiblePosition AccessibilityObject::doAXNextTextMarkerForTextMarker(const VisiblePosition& visiblePos)
1233 {
1234     return visiblePos.next();
1235 }
1236
1237 VisiblePosition AccessibilityObject::doAXPreviousTextMarkerForTextMarker(const VisiblePosition& visiblePos)
1238 {
1239     return visiblePos.previous();
1240 }
1241
1242 VisiblePosition AccessibilityObject::doAXNextWordEndTextMarkerForTextMarker(const VisiblePosition& visiblePos)
1243 {
1244     if (visiblePos.isNull())
1245         return VisiblePosition();
1246
1247     // make sure we move off of a word end
1248     VisiblePosition nextVisiblePos = visiblePos.next();
1249     if (nextVisiblePos.isNull())
1250         return VisiblePosition();
1251
1252     return endOfWord(nextVisiblePos, LeftWordIfOnBoundary);
1253 }
1254
1255 VisiblePosition AccessibilityObject::doAXPreviousWordStartTextMarkerForTextMarker(const VisiblePosition& visiblePos)
1256 {
1257     if (visiblePos.isNull())
1258         return VisiblePosition();
1259
1260     // make sure we move off of a word start
1261     VisiblePosition prevVisiblePos = visiblePos.previous();
1262     if (prevVisiblePos.isNull())
1263         return VisiblePosition();
1264     
1265     return startOfWord(prevVisiblePos, RightWordIfOnBoundary);
1266 }
1267
1268 VisiblePosition AccessibilityObject::doAXNextLineEndTextMarkerForTextMarker(const VisiblePosition& visiblePos)
1269 {
1270     if (visiblePos.isNull())
1271         return VisiblePosition();
1272     
1273     // to make sure we move off of a line end
1274     VisiblePosition nextVisiblePos = visiblePos.next();
1275     if (nextVisiblePos.isNull())
1276         return VisiblePosition();
1277         
1278     VisiblePosition endPosition = endOfLine(nextVisiblePos);
1279
1280     // as long as the position hasn't reached the end of the doc,  keep searching for a valid line end position
1281     // There are cases like when the position is next to a floating object that'll return null for end of line. This code will avoid returning null.
1282     while (endPosition.isNull() && nextVisiblePos.isNotNull()) {
1283         nextVisiblePos = nextVisiblePos.next();
1284         endPosition = endOfLine(nextVisiblePos);
1285     }
1286     
1287     return endPosition;
1288 }
1289
1290 VisiblePosition AccessibilityObject::doAXPreviousLineStartTextMarkerForTextMarker(const VisiblePosition& visiblePos)
1291 {
1292     if (visiblePos.isNull())
1293         return VisiblePosition();
1294     
1295     // make sure we move off of a line start
1296     VisiblePosition prevVisiblePos = visiblePos.previous();
1297     if (prevVisiblePos.isNull())
1298         return VisiblePosition();
1299         
1300     VisiblePosition startPosition = startOfLine(prevVisiblePos);
1301
1302     // as long as the position hasn't reached the beginning of the doc,  keep searching for a valid line start position
1303     // There are cases like when the position is next to a floating object that'll return null for start of line. This code will avoid returning null.
1304     if (startPosition.isNull()) {
1305         while (startPosition.isNull() && prevVisiblePos.isNotNull()) {
1306             prevVisiblePos = prevVisiblePos.previous();
1307             startPosition = startOfLine(prevVisiblePos);
1308         }
1309     } else 
1310         startPosition = updateAXLineStartForVisiblePosition(startPosition);
1311     
1312     return startPosition;
1313 }
1314
1315 VisiblePosition AccessibilityObject::doAXNextSentenceEndTextMarkerForTextMarker(const VisiblePosition& visiblePos)
1316 {
1317     // FIXME: FO 2 IMPLEMENT (currently returns incorrect answer)
1318     // Related? <rdar://problem/3927736> Text selection broken in 8A336
1319     if (visiblePos.isNull())
1320         return VisiblePosition();
1321     
1322     // make sure we move off of a sentence end
1323     VisiblePosition nextVisiblePos = visiblePos.next();
1324     if (nextVisiblePos.isNull())
1325         return VisiblePosition();
1326
1327     // an empty line is considered a sentence. If it's skipped, then the sentence parser will not
1328     // see this empty line.  Instead, return the end position of the empty line. 
1329     VisiblePosition endPosition;
1330     String lineString = plainText(makeRange(startOfLine(visiblePos), endOfLine(visiblePos)).get());
1331     if (lineString.isEmpty())
1332         endPosition = nextVisiblePos;
1333     else
1334         endPosition = endOfSentence(nextVisiblePos);
1335     
1336     return endPosition;
1337 }
1338
1339 VisiblePosition AccessibilityObject::doAXPreviousSentenceStartTextMarkerForTextMarker(const VisiblePosition& visiblePos)
1340 {
1341     // FIXME: FO 2 IMPLEMENT (currently returns incorrect answer)
1342     // Related? <rdar://problem/3927736> Text selection broken in 8A336
1343     if (visiblePos.isNull())
1344         return VisiblePosition();
1345
1346     // make sure we move off of a sentence start
1347     VisiblePosition previousVisiblePos = visiblePos.previous();
1348     if (previousVisiblePos.isNull())
1349         return VisiblePosition();
1350     
1351     // treat empty line as a separate sentence.  
1352     VisiblePosition startPosition;
1353     String lineString = plainText(makeRange(startOfLine(previousVisiblePos), endOfLine(previousVisiblePos)).get());
1354     if (lineString.isEmpty())
1355         startPosition = previousVisiblePos;
1356     else
1357         startPosition = startOfSentence(previousVisiblePos);
1358         
1359     return startPosition;
1360 }
1361
1362 VisiblePosition AccessibilityObject::doAXNextParagraphEndTextMarkerForTextMarker(const VisiblePosition& visiblePos)
1363 {
1364     if (visiblePos.isNull())
1365         return VisiblePosition();
1366     
1367     // make sure we move off of a paragraph end
1368     VisiblePosition nextPos = visiblePos.next();
1369     if (nextPos.isNull())
1370         return VisiblePosition();
1371
1372     return endOfParagraph(nextPos);
1373 }
1374
1375 VisiblePosition AccessibilityObject::doAXPreviousParagraphStartTextMarkerForTextMarker(const VisiblePosition& visiblePos)
1376 {
1377     if (visiblePos.isNull())
1378         return VisiblePosition();
1379     
1380     // make sure we move off of a paragraph start
1381     VisiblePosition previousPos = visiblePos.previous();
1382     if (previousPos.isNull())
1383         return VisiblePosition();
1384
1385     return startOfParagraph(previousPos);
1386 }
1387
1388 // NOTE: Consider providing this utility method as AX API
1389 VisiblePosition AccessibilityObject::textMarkerForIndex(unsigned indexValue, bool lastIndexOK)
1390 {
1391     if (!m_renderer->isTextField() && !m_renderer->isTextArea());
1392         return VisiblePosition();
1393         
1394     RenderTextControl* textControl = static_cast<RenderTextControl*>(m_renderer);
1395     
1396     // lastIndexOK specifies whether the position after the last character is acceptable
1397     if (indexValue >= textControl->text().length()) {
1398         if (!lastIndexOK || indexValue > textControl->text().length())
1399             return VisiblePosition();
1400     }
1401     VisiblePosition position = textControl->visiblePositionForIndex(indexValue);
1402     position.setAffinity(DOWNSTREAM);
1403     return position;
1404 }
1405
1406 AccessibilityObject* AccessibilityObject::doAXUIElementForTextMarker(const VisiblePosition& visiblePos)
1407 {
1408     if (visiblePos.isNull())
1409         return 0;
1410
1411     RenderObject* obj = visiblePos.deepEquivalent().node()->renderer();
1412     if (!obj)
1413         return 0;
1414     
1415     return obj->document()->axObjectCache()->get(obj);
1416 }
1417
1418 unsigned AccessibilityObject::doAXLineForTextMarker(const VisiblePosition& visiblePos)
1419 {
1420     if (visiblePos.isNull())
1421         return 0;
1422         
1423     unsigned lineCount = 0;
1424     VisiblePosition currentVisiblePos = visiblePos;
1425     VisiblePosition savedVisiblePos;
1426
1427     // move up until we get to the top
1428     // FIXME: This only takes us to the top of the rootEditableElement, not the top of the
1429     // top document.
1430     while (currentVisiblePos.isNotNull() && !(inSameLine(currentVisiblePos, savedVisiblePos))) {
1431         lineCount += 1;
1432         savedVisiblePos = currentVisiblePos;
1433         VisiblePosition prevVisiblePos = previousLinePosition(visiblePos, 0);
1434         currentVisiblePos = prevVisiblePos;
1435     }
1436     
1437     return lineCount - 1;
1438 }
1439
1440 // NOTE: Consider providing this utility method as AX API
1441 AccessibilityObject::PlainTextRange AccessibilityObject::rangeForTextMarkerRange(const VisiblePositionRange& positionRange)
1442 {
1443     int index1 = indexForTextMarker(positionRange.start);
1444     int index2 = indexForTextMarker(positionRange.end);
1445     if (index1 < 0 || index2 < 0 || index1 > index2)
1446         return PlainTextRange();
1447     
1448     return PlainTextRange(index1, index2 - index1);
1449 }
1450
1451 // NOTE: Consider providing this utility method as AX API
1452 int AccessibilityObject::indexForTextMarker(VisiblePosition position)
1453 {
1454     if (!m_renderer->isTextField() && !m_renderer->isTextArea())
1455         return -1;
1456         
1457     Node* node = position.deepEquivalent().node();
1458     if (!node)
1459         return -1;
1460     
1461     RenderTextControl* textControl = static_cast<RenderTextControl*>(m_renderer);
1462     for (RenderObject* renderer = node->renderer(); renderer && renderer->element(); renderer = renderer->parent()) {
1463         if (renderer == textControl)
1464             return textControl->indexForVisiblePosition(position);
1465     }
1466     
1467     return -1;
1468 }
1469
1470 // Given a line number, the range of characters of the text associated with this accessibility
1471 // object that contains the line number.
1472 AccessibilityObject::PlainTextRange AccessibilityObject::doAXRangeForLine(unsigned lineNumber)
1473 {
1474     if (!m_renderer->isTextField() && !m_renderer->isTextArea())
1475         return PlainTextRange();
1476
1477     // iterate to the specified line
1478     RenderTextControl* textControl = static_cast<RenderTextControl*>(m_renderer);
1479     VisiblePosition visiblePos = textControl->visiblePositionForIndex(0);
1480     VisiblePosition savedVisiblePos;
1481     for (unsigned lineCount = lineNumber; lineCount != 0; lineCount -= 1) {
1482         savedVisiblePos = visiblePos;
1483         visiblePos = nextLinePosition(visiblePos, 0);
1484         if (visiblePos.isNull() || visiblePos == savedVisiblePos)
1485             return PlainTextRange();
1486     }
1487     
1488     // make a caret selection for the marker position, then extend it to the line
1489     // NOTE: ignores results of selectionController.modify because it returns false when
1490     // starting at an empty line.  The resulting selection in that case
1491     // will be a caret at visiblePos.
1492     SelectionController selectionController;
1493     selectionController.setSelection(Selection(visiblePos));
1494     selectionController.modify(SelectionController::EXTEND, SelectionController::LEFT, LineBoundary);
1495     selectionController.modify(SelectionController::EXTEND, SelectionController::RIGHT, LineBoundary);
1496     
1497     // calculate the indices for the selection start and end
1498     VisiblePosition startPosition = selectionController.selection().visibleStart();
1499     VisiblePosition endPosition = selectionController.selection().visibleEnd();
1500     int index1 = textControl->indexForVisiblePosition(startPosition);
1501     int index2 = textControl->indexForVisiblePosition(endPosition);
1502     
1503     // add one to the end index for a line break not caused by soft line wrap (to match AppKit)
1504     if (endPosition.affinity() == DOWNSTREAM && endPosition.next().isNotNull())
1505         index2 += 1;
1506
1507     // return nil rather than an zero-length range (to match AppKit)
1508     if (index1 == index2)
1509         return PlainTextRange();
1510     
1511     return PlainTextRange(index1, index2 - index1);
1512 }
1513
1514 // The composed character range in the text associated with this accessibility object that
1515 // is specified by the given screen coordinates. This parameterized attribute returns the
1516 // complete range of characters (including surrogate pairs of multi-byte glyphs) at the given
1517 // screen coordinates.
1518 // NOTE: This varies from AppKit when the point is below the last line. AppKit returns an
1519 // an error in that case. We return textControl->text().length(), 1. Does this matter?
1520 AccessibilityObject::PlainTextRange AccessibilityObject::doAXRangeForPosition(const IntPoint& point)
1521 {
1522     int index = indexForTextMarker(doAXTextMarkerForPosition(point));
1523     if (index < 0)
1524         return PlainTextRange();
1525         
1526     return PlainTextRange(index, 1);
1527 }
1528
1529 // The composed character range in the text associated with this accessibility object that
1530 // is specified by the given index value. This parameterized attribute returns the complete
1531 // range of characters (including surrogate pairs of multi-byte glyphs) at the given index.
1532 AccessibilityObject::PlainTextRange AccessibilityObject::doAXRangeForIndex(unsigned index)
1533 {
1534     if (!m_renderer->isTextField() && !m_renderer->isTextArea())
1535         return PlainTextRange();
1536         
1537     RenderTextControl* textControl = static_cast<RenderTextControl*>(m_renderer);
1538     String text = textControl->text();
1539     if (!text.length() || index > text.length() - 1)
1540         return PlainTextRange();
1541     
1542     return PlainTextRange(index, 1);
1543 }
1544
1545 // Given a character index, the range of text associated with this accessibility object
1546 // over which the style in effect at that character index applies.
1547 AccessibilityObject::PlainTextRange AccessibilityObject::doAXStyleRangeForIndex(unsigned index)
1548 {
1549     VisiblePositionRange textMarkerRange = doAXStyleTextMarkerRangeForTextMarker(textMarkerForIndex(index, false));
1550     return rangeForTextMarkerRange(textMarkerRange);
1551 }
1552
1553 // A substring of the text associated with this accessibility object that is
1554 // specified by the given character range.
1555 String AccessibilityObject::doAXStringForRange(const PlainTextRange& range)
1556 {
1557     if (isPasswordField())
1558         return String();
1559         
1560     if (range.length == 0)
1561         return "";
1562         
1563     if (!m_renderer->isTextField() && !m_renderer->isTextArea())
1564         return String();
1565         
1566     RenderTextControl* textControl = static_cast<RenderTextControl*>(m_renderer);
1567     String text = textControl->text();
1568     if (range.start + range.length > text.length())
1569         return String();
1570         
1571     return text.substring(range.start, range.length);
1572 }
1573
1574 // The bounding rectangle of the text associated with this accessibility object that is
1575 // specified by the given range. This is the bounding rectangle a sighted user would see
1576 // on the display screen, in pixels.
1577 IntRect AccessibilityObject::doAXBoundsForRange(PlainTextRange range)
1578 {
1579     if (isTextControl())
1580         return doAXBoundsForTextMarkerRange(textMarkerRangeForRange(range, static_cast<RenderTextControl*>(m_renderer)));
1581     return IntRect();
1582 }
1583
1584 // Given an indexed character, the line number of the text associated with this accessibility
1585 // object that contains the character.
1586 unsigned AccessibilityObject::doAXLineForIndex(unsigned index)
1587 {
1588     return doAXLineForTextMarker(textMarkerForIndex(index, false));
1589 }
1590
1591 AccessibilityObject* AccessibilityObject::doAccessibilityHitTest(IntPoint point)
1592 {
1593     if (!m_renderer)
1594         return 0;
1595     
1596     HitTestRequest request(true, true);
1597     HitTestResult result = HitTestResult(point);
1598     m_renderer->layer()->hitTest(request, result);
1599     if (!result.innerNode())
1600         return 0;
1601     Node* node = result.innerNode()->shadowAncestorNode();
1602     RenderObject* obj = node->renderer();
1603     if (!obj)
1604         return 0;
1605     
1606     return obj->document()->axObjectCache()->get(obj);
1607 }
1608
1609 AccessibilityObject* AccessibilityObject::focusedUIElement()
1610 {
1611     // get the focused node in the page
1612     Page* page = m_renderer->document()->page();
1613     if (!page)
1614         return 0;
1615
1616     Document* focusedDocument = page->focusController()->focusedOrMainFrame()->document();
1617     Node* focusedNode = focusedDocument->focusedNode();
1618     if (!focusedNode || !focusedNode->renderer())
1619         focusedNode = focusedDocument;
1620
1621     AccessibilityObject* obj = focusedNode->renderer()->document()->axObjectCache()->get(focusedNode->renderer());
1622     
1623     // the HTML element, for example, is focusable but has an AX object that is ignored
1624     if (obj->accessibilityIsIgnored())
1625         obj = obj->parentObjectUnignored();
1626     
1627     return obj;
1628 }
1629
1630 AccessibilityObject* AccessibilityObject::observableObject()
1631 {
1632     for (RenderObject* renderer = m_renderer; renderer && renderer->element(); renderer = renderer->parent()) {
1633         if (renderer->isTextField() || renderer->isTextArea())
1634             return renderer->document()->axObjectCache()->get(renderer);
1635     }
1636     
1637     return 0;
1638 }
1639
1640 AccessibilityRole AccessibilityObject::roleValue()
1641 {
1642     if (!m_renderer)
1643         return UnknownRole;
1644
1645     if (m_areaElement)
1646         return WebCoreLinkRole;
1647     if (m_renderer->element() && m_renderer->element()->isLink()) {
1648         if (m_renderer->isImage())
1649             return ImageMapRole;
1650         return WebCoreLinkRole;
1651     }
1652     if (m_renderer->isListMarker())
1653         return ListMarkerRole;
1654     if (m_renderer->element() && m_renderer->element()->hasTagName(buttonTag))
1655         return ButtonRole;
1656     if (m_renderer->isText())
1657         return StaticTextRole;
1658     if (m_renderer->isImage()) {
1659         if (isImageButton())
1660             return ButtonRole;
1661         return ImageRole;
1662     }
1663     if (isWebArea())
1664         return WebAreaRole;
1665     
1666     if (m_renderer->isTextField())
1667         return TextFieldRole;
1668     
1669     if (m_renderer->isTextArea())
1670         return TextAreaRole;
1671     
1672     if (m_renderer->element() && m_renderer->element()->hasTagName(inputTag)) {
1673         HTMLInputElement* input = static_cast<HTMLInputElement*>(m_renderer->element());
1674         if (input->inputType() == HTMLInputElement::CHECKBOX)
1675             return CheckBoxRole;
1676         if (input->inputType() == HTMLInputElement::RADIO)
1677             return RadioButtonRole;
1678         if (input->isTextButton())
1679             return ButtonRole;
1680     }
1681     
1682     if (m_renderer->isMenuList())
1683         return PopUpButtonRole;
1684
1685     if (isHeading())
1686         return HeadingRole;
1687         
1688     if (m_renderer->isBlockFlow())
1689         return GroupRole;
1690
1691     return UnknownRole;
1692 }
1693
1694 bool AccessibilityObject::canSetFocusAttribute()
1695 {
1696     // NOTE: It would be more accurate to ask the document whether setFocusedNode() would 
1697     // do anything.  For example, it setFocusedNode() will do nothing if the current focused
1698     // node will not relinquish the focus.
1699     if (!m_renderer->element() || !m_renderer->element()->isEnabled())
1700         return false;
1701         
1702     switch (roleValue()) {
1703     case WebCoreLinkRole:
1704     case TextFieldRole:
1705     case TextAreaRole:
1706     case ButtonRole:
1707     case PopUpButtonRole:
1708     case CheckBoxRole:
1709     case RadioButtonRole:
1710         return true;
1711     case UnknownRole:
1712     case SliderRole:
1713     case TabGroupRole:
1714     case StaticTextRole:
1715     case ScrollAreaRole:
1716     case MenuButtonRole:
1717     case TableRole:
1718     case ApplicationRole:
1719     case GroupRole:
1720     case RadioGroupRole:
1721     case ListRole:
1722     case ScrollBarRole:
1723     case ValueIndicatorRole:
1724     case ImageRole:
1725     case MenuBarRole:
1726     case MenuRole:
1727     case MenuItemRole:
1728     case ColumnRole:
1729     case RowRole:
1730     case ToolbarRole:
1731     case BusyIndicatorRole:
1732     case ProgressIndicatorRole:
1733     case WindowRole:
1734     case DrawerRole:
1735     case SystemWideRole:
1736     case OutlineRole:
1737     case IncrementorRole:
1738     case BrowserRole:
1739     case ComboBoxRole:
1740     case SplitGroupRole:
1741     case SplitterRole:
1742     case ColorWellRole:
1743     case GrowAreaRole:
1744     case SheetRole:
1745     case HelpTagRole:
1746     case MatteRole:
1747     case RulerRole:
1748     case RulerMarkerRole:
1749     case SortButtonRole:
1750     case LinkRole:
1751     case DisclosureTriangleRole:
1752     case GridRole:
1753     case ImageMapRole:
1754     case ListMarkerRole:
1755     case WebAreaRole:
1756     case HeadingRole:
1757         return false;
1758     }
1759     ASSERT_NOT_REACHED();
1760     return false;
1761 }
1762
1763 bool AccessibilityObject::canSetValueAttribute()
1764 {
1765     return isTextControl();
1766 }
1767
1768 bool AccessibilityObject::canSetTextRangeAttributes()
1769 {
1770     return isTextControl();
1771 }
1772
1773 void AccessibilityObject::childrenChanged()
1774 {
1775     clearChildren();
1776     
1777     if (accessibilityIsIgnored())
1778         parentObject()->childrenChanged();
1779 }
1780
1781 void AccessibilityObject::clearChildren()
1782 {
1783     m_children.clear();
1784 }
1785
1786 bool AccessibilityObject::hasChildren()
1787 {
1788     return m_children.size();
1789 }
1790
1791 void AccessibilityObject::addChildren()
1792 {
1793     // nothing to add if there is no RenderObject
1794     if (!m_renderer)
1795         return;    
1796     
1797     // add all unignored acc children
1798     for (RefPtr<AccessibilityObject> obj = firstChild(); obj; obj = obj->nextSibling()) {
1799         if (obj->accessibilityIsIgnored()) {
1800             obj->addChildren();
1801             Vector<RefPtr<AccessibilityObject> >children = obj->children();
1802             unsigned length = children.size();
1803             for (unsigned i = 0; i < length; ++i)
1804                 m_children.append(children[i]);
1805         } else 
1806             m_children.append(obj);
1807     }
1808         
1809     // for a RenderImage, add the <area> elements as individual accessibility objects
1810     if (m_renderer->isImage() && !m_areaElement) {
1811         HTMLMapElement* map = static_cast<RenderImage*>(m_renderer)->imageMap();
1812         if (map) {
1813             for (Node* current = map->firstChild(); current; current = current->traverseNextNode(map)) {
1814                 // add an <area> element for this child if it has a link
1815                 // NOTE: can't cache these because they all have the same renderer, which is the cache key, right?
1816                 // plus there may be little reason to since they are being added to the handy array
1817                 if (current->isLink()) {
1818                     RefPtr<AccessibilityObject> obj = new AccessibilityObject(m_renderer);
1819                     obj->m_areaElement = static_cast<HTMLAreaElement*>(current);
1820                     m_children.append(obj);
1821                 }
1822             }
1823         }
1824     }
1825 }
1826
1827 unsigned AccessibilityObject::axObjectID()
1828 {
1829     return m_id;
1830 }
1831
1832 void AccessibilityObject::setAXObjectID(unsigned axObjectID)
1833 {
1834     m_id = axObjectID;
1835 }
1836
1837 void AccessibilityObject::removeAXObjectID()
1838 {
1839     if (!m_id)
1840         return;
1841         
1842     m_renderer->document()->axObjectCache()->removeAXID(this);
1843 }
1844
1845 } // namespace WebCore