Reviewed by Dave Hyatt.
authorharrison <harrison@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Thu, 6 Jan 2005 18:20:51 +0000 (18:20 +0000)
committerharrison <harrison@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Thu, 6 Jan 2005 18:20:51 +0000 (18:20 +0000)
        <rdar://problem/3776056> AX: Editable HTML should not be viewed as AXStaticText
        <rdar://problem/3588548> AX: tabbing does not work correctly with the screen reader and a focused link; need AXFocusedUIElement to work

        Many more AX attributes supported.  Numerous fixes to previous AX work.

        * khtml/editing/visible_units.cpp:
        (khtml::startSentenceBoundary):
        (khtml::startOfSentence):
        (khtml::endSentenceBoundary):
        (khtml::endOfSentence):
        (khtml::previousSentencePositionBoundary):
        (khtml::previousSentencePosition):
        (khtml::nextSentencePositionBoundary):
        (khtml::nextSentencePosition):
        * khtml/editing/visible_units.h:
        * khtml/khtmlview.cpp:
        (KHTMLView::layout):
        * khtml/misc/helper.cpp:
        (khtml::findSentenceBoundary):
        (khtml::nextSentenceFromIndex):
        * khtml/misc/helper.h:
        * khtml/misc/htmltags.c:
        (hash_tag):
        (findTag):
        * khtml/rendering/render_container.cpp:
        (RenderContainer::removeChildNode):
        (RenderContainer::appendChildNode):
        (RenderContainer::insertChildNode):
        * khtml/rendering/render_object.cpp:
        (RenderObject::remove):
        * khtml/xml/dom_docimpl.cpp:
        (DocumentImpl::getAccObjectCache):
        (DocumentImpl::updateSelection):
        (DocumentImpl::close):
        (DocumentImpl::setFocusNode):
        (DocumentImpl::parentDocument):
        (DocumentImpl::topDocument):
        * khtml/xml/dom_docimpl.h:
        * kwq/KWQAccObject.mm:
        (-[KWQAccObject accessibilityShouldUseUniqueId]):
        (-[KWQAccObject detach]):
        (-[KWQAccObject anchorElement]):
        (-[KWQAccObject firstChild]):
        (-[KWQAccObject lastChild]):
        (-[KWQAccObject previousSibling]):
        (-[KWQAccObject nextSibling]):
        (-[KWQAccObject parentObject]):
        (-[KWQAccObject value]):
        (-[KWQAccObject accessibilityAttributeNames]):
        (-[KWQAccObject accessibilityPerformAction:]):
        (-[KWQAccObject textMarkerForVisiblePosition:]):
        (-[KWQAccObject visiblePositionForTextMarker:]):
        (-[KWQAccObject textMarkerRangeFromVisiblePositions:andEndPos:]):
        (-[KWQAccObject topDocument]):
        (-[KWQAccObject topRenderer]):
        (-[KWQAccObject topView]):
        (-[KWQAccObject accessibilityAttributeValue:]):
        (-[KWQAccObject accessibilityParameterizedAttributeNames]):
        (-[KWQAccObject doAXLineForTextMarker:]):
        (-[KWQAccObject doAXTextMarkerRangeForLine:]):
        (-[KWQAccObject doAXStringForTextMarkerRange:]):
        (-[KWQAccObject doAXTextMarkerForPosition:]):
        (-[KWQAccObject doAXBoundsForTextMarkerRange:]):
        (-[KWQAccObject doAXAttributedStringForTextMarkerRange:]):
        (-[KWQAccObject doAXTextMarkerRangeForUnorderedTextMarkers:]):
        (-[KWQAccObject doAXNextTextMarkerForTextMarker:]):
        (-[KWQAccObject doAXPreviousTextMarkerForTextMarker:]):
        (-[KWQAccObject doAXLeftWordTextMarkerRangeForTextMarker:]):
        (-[KWQAccObject doAXRightWordTextMarkerRangeForTextMarker:]):
        (-[KWQAccObject doAXLeftLineTextMarkerRangeForTextMarker:]):
        (-[KWQAccObject doAXRightLineTextMarkerRangeForTextMarker:]):
        (-[KWQAccObject doAXSentenceTextMarkerRangeForTextMarker:]):
        (-[KWQAccObject doAXParagraphTextMarkerRangeForTextMarker:]):
        (-[KWQAccObject doAXNextWordEndTextMarkerForTextMarker:]):
        (-[KWQAccObject doAXPreviousWordStartTextMarkerForTextMarker:]):
        (-[KWQAccObject doAXNextLineEndTextMarkerForTextMarker:]):
        (-[KWQAccObject doAXPreviousLineStartTextMarkerForTextMarker:]):
        (-[KWQAccObject doAXNextSentenceEndTextMarkerForTextMarker:]):
        (-[KWQAccObject doAXPreviousSentenceStartTextMarkerForTextMarker:]):
        (-[KWQAccObject doAXNextParagraphEndTextMarkerForTextMarker:]):
        (-[KWQAccObject doAXPreviousParagraphStartTextMarkerForTextMarker:]):
        (-[KWQAccObject doAXLengthForTextMarkerRange:]):
        (-[KWQAccObject accessibilityAttributeValue:forParameter:]):
        (-[KWQAccObject accessibilityHitTest:]):
        (-[KWQAccObject accessibilityFocusedUIElement]):
        (-[KWQAccObject accessibilityIsAttributeSettable:]):
        (-[KWQAccObject doSetAXSelectedTextMarkerRange:]):
        (-[KWQAccObject setAccObjectID:]):
        (-[KWQAccObject removeAccObjectID]):
        * kwq/KWQAccObjectCache.h:
        * kwq/KWQAccObjectCache.mm:
        (KWQAccObjectCache::setAccObject):
        (KWQAccObjectCache::removeAccObject):
        (KWQAccObjectCache::visiblePositionForTextMarker):
        (KWQAccObjectCache::postNotificationToTopWebArea):
        (KWQAccObjectCache::postNotification):
        (KWQAccObjectCache::handleFocusedUIElementChanged):
        * kwq/KWQKHTMLPart.mm:
        (KWQKHTMLPart::respondToChangedContents):
        * kwq/KWQTextUtilities.h:
        * kwq/KWQTextUtilities.mm:
        (KWQFindNextWordFromIndex):
        (KWQFindSentenceBoundary):
        (KWQFindNextSentenceFromIndex):
        * kwq/WebCoreBridge.mm:
        (-[WebCoreBridge accessibilityTree]):

git-svn-id: https://svn.webkit.org/repository/webkit/trunk@8309 268f45cc-cd09-0410-ab3c-d52691b4dbfc

17 files changed:
WebCore/ChangeLog-2005-08-23
WebCore/khtml/editing/visible_units.cpp
WebCore/khtml/editing/visible_units.h
WebCore/khtml/khtmlview.cpp
WebCore/khtml/misc/helper.cpp
WebCore/khtml/misc/helper.h
WebCore/khtml/rendering/render_container.cpp
WebCore/khtml/rendering/render_object.cpp
WebCore/khtml/xml/dom_docimpl.cpp
WebCore/khtml/xml/dom_docimpl.h
WebCore/kwq/KWQAccObject.mm
WebCore/kwq/KWQAccObjectCache.h
WebCore/kwq/KWQAccObjectCache.mm
WebCore/kwq/KWQKHTMLPart.mm
WebCore/kwq/KWQTextUtilities.h
WebCore/kwq/KWQTextUtilities.mm
WebCore/kwq/WebCoreBridge.mm

index dbd55faf0dffa4ee9969aa0a33c46fa695335b68..99d3bd125e48217f513d0eaa1637528220fc6114 100644 (file)
@@ -1,3 +1,114 @@
+2005-01-06  David Harrison  <harrison@apple.com>
+
+        Reviewed by Dave Hyatt.
+
+        <rdar://problem/3776056> AX: Editable HTML should not be viewed as AXStaticText
+        <rdar://problem/3588548> AX: tabbing does not work correctly with the screen reader and a focused link; need AXFocusedUIElement to work
+        
+        Many more AX attributes supported.  Numerous fixes to previous AX work.
+        
+        * khtml/editing/visible_units.cpp:
+        (khtml::startSentenceBoundary):
+        (khtml::startOfSentence):
+        (khtml::endSentenceBoundary):
+        (khtml::endOfSentence):
+        (khtml::previousSentencePositionBoundary):
+        (khtml::previousSentencePosition):
+        (khtml::nextSentencePositionBoundary):
+        (khtml::nextSentencePosition):
+        * khtml/editing/visible_units.h:
+        * khtml/khtmlview.cpp:
+        (KHTMLView::layout):
+        * khtml/misc/helper.cpp:
+        (khtml::findSentenceBoundary):
+        (khtml::nextSentenceFromIndex):
+        * khtml/misc/helper.h:
+        * khtml/misc/htmltags.c:
+        (hash_tag):
+        (findTag):
+        * khtml/rendering/render_container.cpp:
+        (RenderContainer::removeChildNode):
+        (RenderContainer::appendChildNode):
+        (RenderContainer::insertChildNode):
+        * khtml/rendering/render_object.cpp:
+        (RenderObject::remove):
+        * khtml/xml/dom_docimpl.cpp:
+        (DocumentImpl::getAccObjectCache):
+        (DocumentImpl::updateSelection):
+        (DocumentImpl::close):
+        (DocumentImpl::setFocusNode):
+        (DocumentImpl::parentDocument):
+        (DocumentImpl::topDocument):
+        * khtml/xml/dom_docimpl.h:
+        * kwq/KWQAccObject.mm:
+        (-[KWQAccObject accessibilityShouldUseUniqueId]):
+        (-[KWQAccObject detach]):
+        (-[KWQAccObject anchorElement]):
+        (-[KWQAccObject firstChild]):
+        (-[KWQAccObject lastChild]):
+        (-[KWQAccObject previousSibling]):
+        (-[KWQAccObject nextSibling]):
+        (-[KWQAccObject parentObject]):
+        (-[KWQAccObject value]):
+        (-[KWQAccObject accessibilityAttributeNames]):
+        (-[KWQAccObject accessibilityPerformAction:]):
+        (-[KWQAccObject textMarkerForVisiblePosition:]):
+        (-[KWQAccObject visiblePositionForTextMarker:]):
+        (-[KWQAccObject textMarkerRangeFromVisiblePositions:andEndPos:]):
+        (-[KWQAccObject topDocument]):
+        (-[KWQAccObject topRenderer]):
+        (-[KWQAccObject topView]):
+        (-[KWQAccObject accessibilityAttributeValue:]):
+        (-[KWQAccObject accessibilityParameterizedAttributeNames]):
+        (-[KWQAccObject doAXLineForTextMarker:]):
+        (-[KWQAccObject doAXTextMarkerRangeForLine:]):
+        (-[KWQAccObject doAXStringForTextMarkerRange:]):
+        (-[KWQAccObject doAXTextMarkerForPosition:]):
+        (-[KWQAccObject doAXBoundsForTextMarkerRange:]):
+        (-[KWQAccObject doAXAttributedStringForTextMarkerRange:]):
+        (-[KWQAccObject doAXTextMarkerRangeForUnorderedTextMarkers:]):
+        (-[KWQAccObject doAXNextTextMarkerForTextMarker:]):
+        (-[KWQAccObject doAXPreviousTextMarkerForTextMarker:]):
+        (-[KWQAccObject doAXLeftWordTextMarkerRangeForTextMarker:]):
+        (-[KWQAccObject doAXRightWordTextMarkerRangeForTextMarker:]):
+        (-[KWQAccObject doAXLeftLineTextMarkerRangeForTextMarker:]):
+        (-[KWQAccObject doAXRightLineTextMarkerRangeForTextMarker:]):
+        (-[KWQAccObject doAXSentenceTextMarkerRangeForTextMarker:]):
+        (-[KWQAccObject doAXParagraphTextMarkerRangeForTextMarker:]):
+        (-[KWQAccObject doAXNextWordEndTextMarkerForTextMarker:]):
+        (-[KWQAccObject doAXPreviousWordStartTextMarkerForTextMarker:]):
+        (-[KWQAccObject doAXNextLineEndTextMarkerForTextMarker:]):
+        (-[KWQAccObject doAXPreviousLineStartTextMarkerForTextMarker:]):
+        (-[KWQAccObject doAXNextSentenceEndTextMarkerForTextMarker:]):
+        (-[KWQAccObject doAXPreviousSentenceStartTextMarkerForTextMarker:]):
+        (-[KWQAccObject doAXNextParagraphEndTextMarkerForTextMarker:]):
+        (-[KWQAccObject doAXPreviousParagraphStartTextMarkerForTextMarker:]):
+        (-[KWQAccObject doAXLengthForTextMarkerRange:]):
+        (-[KWQAccObject accessibilityAttributeValue:forParameter:]):
+        (-[KWQAccObject accessibilityHitTest:]):
+        (-[KWQAccObject accessibilityFocusedUIElement]):
+        (-[KWQAccObject accessibilityIsAttributeSettable:]):
+        (-[KWQAccObject doSetAXSelectedTextMarkerRange:]):
+        (-[KWQAccObject setAccObjectID:]):
+        (-[KWQAccObject removeAccObjectID]):
+        * kwq/KWQAccObjectCache.h:
+        * kwq/KWQAccObjectCache.mm:
+        (KWQAccObjectCache::setAccObject):
+        (KWQAccObjectCache::removeAccObject):
+        (KWQAccObjectCache::visiblePositionForTextMarker):
+        (KWQAccObjectCache::postNotificationToTopWebArea):
+        (KWQAccObjectCache::postNotification):
+        (KWQAccObjectCache::handleFocusedUIElementChanged):
+        * kwq/KWQKHTMLPart.mm:
+        (KWQKHTMLPart::respondToChangedContents):
+        * kwq/KWQTextUtilities.h:
+        * kwq/KWQTextUtilities.mm:
+        (KWQFindNextWordFromIndex):
+        (KWQFindSentenceBoundary):
+        (KWQFindNextSentenceFromIndex):
+        * kwq/WebCoreBridge.mm:
+        (-[WebCoreBridge accessibilityTree]):
+
 2005-01-05  Darin Adler  <darin@apple.com>
 
         Reviewed by Ken.
index 18d949814c6b659036ae5fb196b6d52237908ff1..91693fff6ae7c0f22e2f0af189004fb65101d9a9 100644 (file)
@@ -238,6 +238,60 @@ VisiblePosition nextLinePosition(const VisiblePosition &c, EAffinity affinity, i
     return VisiblePosition(pos.nextLinePosition(x, affinity));
 }
 
+// ---------
+
+static unsigned startSentenceBoundary(const QChar *characters, unsigned length)
+{
+    int start, end;
+    findSentenceBoundary(characters, length, length, &start, &end);
+    return start;
+}
+
+VisiblePosition startOfSentence(const VisiblePosition &c)
+{
+    return previousWordBoundary(c, startSentenceBoundary);
+}
+
+// ---------
+
+static unsigned endSentenceBoundary(const QChar *characters, unsigned length)
+{
+    int start, end;
+    findSentenceBoundary(characters, length, 0, &start, &end);
+    return end;
+}
+
+VisiblePosition endOfSentence(const VisiblePosition &c, EIncludeLineBreak includeLineBreak)
+{
+    return nextWordBoundary(c, endSentenceBoundary);
+}
+
+// ---------
+
+static unsigned previousSentencePositionBoundary(const QChar *characters, unsigned length)
+{
+    return nextSentenceFromIndex(characters, length, length, false);
+}
+
+VisiblePosition previousSentencePosition(const VisiblePosition &c, EAffinity, int x)
+{
+    return previousWordBoundary(c, previousSentencePositionBoundary);
+}
+
+// ---------
+
+static unsigned nextSentencePositionBoundary(const QChar *characters, unsigned length)
+{
+    return nextSentenceFromIndex(characters, length, 0, true);
+}
+
+VisiblePosition nextSentencePosition(const VisiblePosition &c, EAffinity, int x)
+{
+    return nextWordBoundary(c, nextSentencePositionBoundary);
+}
+
+// ---------
+
 VisiblePosition startOfParagraph(const VisiblePosition &c)
 {
     Position p = c.deepEquivalent();
index 78bab53c45a3facb33ba03ffaf0d5364dbb4658b..1ddf321595d1199d63cfe4ac9e7699ca64516655 100644 (file)
@@ -47,6 +47,12 @@ VisiblePosition endOfLine(const VisiblePosition &, EAffinity, EIncludeLineBreak
 VisiblePosition previousLinePosition(const VisiblePosition &, EAffinity, int x);
 VisiblePosition nextLinePosition(const VisiblePosition &, EAffinity, int x);
 
+// sentences
+VisiblePosition startOfSentence(const VisiblePosition &);
+VisiblePosition endOfSentence(const VisiblePosition &, EIncludeLineBreak = DoNotIncludeLineBreak);
+VisiblePosition previousSentencePosition(const VisiblePosition &, EAffinity, int x);
+VisiblePosition nextSentencePosition(const VisiblePosition &, EAffinity, int x);
+
 // paragraphs
 VisiblePosition startOfParagraph(const VisiblePosition &);
 VisiblePosition endOfParagraph(const VisiblePosition &, EIncludeLineBreak = DoNotIncludeLineBreak);
index c6659a4e79130bfbbe2a7eb4989eded83637435b..a7dadb0a73f4f41f022c9e8af01ec6f4c719dcd1 100644 (file)
@@ -709,7 +709,7 @@ void KHTMLView::layout()
     d->layoutCount++;
 #if APPLE_CHANGES
     if (KWQAccObjectCache::accessibilityEnabled())
-        root->document()->getOrCreateAccObjectCache()->postNotification(root, "AXLayoutComplete");
+        root->document()->getAccObjectCache()->postNotification(root, "AXLayoutComplete");
 #endif
 
 #if APPLE_CHANGES
index 2a709dc05ff40b6b0577b0749558f1661c931061..84c54d9542359fb6d44d80cf71e8276ee06644d2 100644 (file)
@@ -54,4 +54,22 @@ int nextWordFromIndex(const QChar *chars, int len, int position, bool forward)
 #endif
 }
 
+void findSentenceBoundary(const QChar *chars, int len, int position, int *start, int *end)
+{
+#if APPLE_CHANGES
+    KWQFindSentenceBoundary(chars, len, position, start, end);
+#else
+    // KDE implementation
+#endif
+}
+
+int nextSentenceFromIndex(const QChar *chars, int len, int position, bool forward)
+{
+#if APPLE_CHANGES
+    return KWQFindNextSentenceFromIndex(chars, len, position, forward);
+#else
+    // KDE implementation
+#endif
+}
+
 }
index 4d02dfba38c78a34608a94a2d2db30fc4f1a1bb3..125fc04525f0416646fbb3c515b8ce25374c3647 100644 (file)
@@ -43,6 +43,8 @@ namespace khtml
 
     void findWordBoundary(const QChar *chars, int len, int position, int *start, int *end);
     int nextWordFromIndex(const QChar *chars, int len, int position, bool forward);
+    void findSentenceBoundary(const QChar *chars, int len, int position, int *start, int *end);
+    int nextSentenceFromIndex(const QChar *chars, int len, int position, bool forward);
 };
 
 #endif
index 5536325bbc066aab4cccd62659d1b29c7b5df4ab..fbbd8e44da92aafd7b101dd901238be1ba96ca78 100644 (file)
@@ -198,9 +198,8 @@ RenderObject* RenderContainer::removeChildNode(RenderObject* oldChild)
     oldChild->setParent(0);
 
 #if APPLE_CHANGES
-    KWQAccObjectCache* cache = document()->getExistingAccObjectCache();
-    if (cache)
-        cache->childrenChanged(this);
+    if (KWQAccObjectCache::accessibilityEnabled())
+        document()->getAccObjectCache()->childrenChanged(this);
 #endif
     
     return oldChild;
@@ -354,9 +353,8 @@ void RenderContainer::appendChildNode(RenderObject* newChild)
         dirtyLinesFromChangedChild(newChild);
     
 #if APPLE_CHANGES
-    KWQAccObjectCache* cache = document()->getExistingAccObjectCache();
-    if (cache)
-        cache->childrenChanged(this);
+    if (KWQAccObjectCache::accessibilityEnabled())
+        document()->getAccObjectCache()->childrenChanged(this);
 #endif
 }
 
@@ -395,13 +393,11 @@ void RenderContainer::insertChildNode(RenderObject* child, RenderObject* beforeC
         dirtyLinesFromChangedChild(child);
     
 #if APPLE_CHANGES
-    KWQAccObjectCache* cache = document()->getExistingAccObjectCache();
-    if (cache)
-        cache->childrenChanged(this);
+    if (KWQAccObjectCache::accessibilityEnabled())
+        document()->getAccObjectCache()->childrenChanged(this);
 #endif    
 }
 
-
 void RenderContainer::layout()
 {
     KHTMLAssert( needsLayout() );
index 2868c9566cb4ab037a65873ec00886137833a153..7dd249240a4e7c089cb8a5f348041ed53dd2630f 100644 (file)
@@ -1813,9 +1813,7 @@ void RenderObject::remove()
 {
 #if APPLE_CHANGES
     // Delete our accessibility object if we have one.
-    KWQAccObjectCache* cache = document()->getExistingAccObjectCache();
-    if (cache)
-        cache->detach(this);
+    document()->getAccObjectCache()->detach(this);
 #endif
 
     removeFromObjectLists();
index c83c801481725add831a6f60d54e33d2792d4b2a..986f8a0df6eb6dc171ec0bfaafc5c4736b88d114 100644 (file)
@@ -1205,10 +1205,34 @@ void DocumentImpl::detach()
 }
 
 #if APPLE_CHANGES
-KWQAccObjectCache* DocumentImpl::getOrCreateAccObjectCache()
+KWQAccObjectCache* DocumentImpl::getAccObjectCache()
 {
-    if (!m_accCache)
-        m_accCache = new KWQAccObjectCache;
+    // The only document that actually has a KWQAccObjectCache is the top-level
+    // document.  This is because we need to be able to get from any KWQAccObject
+    // to any other KWQAccObject on the same page.  Using a single cache allows
+    // lookups across nested webareas (i.e. multiple documents).
+    
+    // return already known cache (assert that this is the top-level document)
+    if (m_accCache) {
+        assert(!ownerElement());
+        return m_accCache;
+    }
+    
+    // look for top-level document
+    ElementImpl *element = ownerElement();
+    if (element) {
+        DocumentImpl *doc;
+        while (element) {
+            doc = element->getDocument();
+            element = doc->ownerElement();
+        }
+        
+        // ask the top-level document for its cache
+        return doc->getAccObjectCache();
+    }
+    
+    // this is the top-level document, so install a new cache
+    m_accCache = new KWQAccObjectCache;
     return m_accCache;
 }
 #endif
@@ -1231,7 +1255,7 @@ void DocumentImpl::updateSelection()
         canvas->clearSelection();
 #if APPLE_CHANGES
         if (KWQAccObjectCache::accessibilityEnabled())
-            getOrCreateAccObjectCache()->postNotification(renderer(), "AXSelectedTextChanged");
+            getAccObjectCache()->postNotificationToTopWebArea(renderer(), "AXSelectedTextChanged");
 #endif
     }
     else {
@@ -1242,8 +1266,9 @@ void DocumentImpl::updateSelection()
             RenderObject *endRenderer = endPos.node()->renderer();
             static_cast<RenderCanvas*>(m_render)->setSelection(startRenderer, startPos.offset(), endRenderer, endPos.offset());
 #if APPLE_CHANGES
-            if (KWQAccObjectCache::accessibilityEnabled())
-                getOrCreateAccObjectCache()->postNotification(renderer(), "AXSelectedTextChanged");
+            if (KWQAccObjectCache::accessibilityEnabled()) {
+                getAccObjectCache()->postNotificationToTopWebArea(renderer(), "AXSelectedTextChanged");
+            }
 #endif
         }
     }
@@ -1352,7 +1377,7 @@ void DocumentImpl::close()
         }
 #if APPLE_CHANGES
         if (renderer() && KWQAccObjectCache::accessibilityEnabled())
-            getOrCreateAccObjectCache()->postNotification(renderer(), "AXLoadComplete");
+            getAccObjectCache()->postNotification(renderer(), "AXLoadComplete");
 #endif
     }
 }
@@ -2436,8 +2461,8 @@ bool DocumentImpl::setFocusNode(NodeImpl *newFocusNode)
    }
 
 #if APPLE_CHANGES
-    if (!focusChangeBlocked && KWQAccObjectCache::accessibilityEnabled())
-        getOrCreateAccObjectCache()->postNotification(renderer(), "AXFocusedUIElementChanged");
+    if (!focusChangeBlocked && m_focusNode && KWQAccObjectCache::accessibilityEnabled())
+        getAccObjectCache()->handleFocusedUIElementChanged();
 #endif
 
 SetFocusNodeDone:
@@ -3142,6 +3167,18 @@ DocumentImpl *DocumentImpl::parentDocument() const
     return parent->xmlDocImpl();
 }
 
+DocumentImpl *DocumentImpl::topDocument() const
+{
+    DocumentImpl *doc = const_cast<DocumentImpl *>(this);
+    ElementImpl *element;
+    while ((element = doc->ownerElement()) != 0) {
+        doc = element->getDocument();
+        element = doc ? doc->ownerElement() : 0;
+    }
+    
+    return doc;
+}
+
 // ----------------------------------------------------------------------------
 
 DocumentFragmentImpl::DocumentFragmentImpl(DocumentPtr *doc) : NodeBaseImpl(doc)
index 021ef3397df4d6661ddf24239716e39eb43a545a..b4d159e3390e57849f58994805a8bb38474f0b74 100644 (file)
@@ -293,8 +293,7 @@ public:
     RenderArena* renderArena() { return m_renderArena; }
 
 #if APPLE_CHANGES
-    KWQAccObjectCache* getExistingAccObjectCache() { return m_accCache; }
-    KWQAccObjectCache* getOrCreateAccObjectCache();
+    KWQAccObjectCache* getAccObjectCache();
 #endif
     
     // to get visually ordered hebrew and arabic pages right
@@ -567,6 +566,7 @@ public:
     InheritedBool getDesignMode() const;
     bool inDesignMode() const;
     DocumentImpl *parentDocument() const;
+    DocumentImpl *topDocument() const;
 
 #ifdef KHTML_XSLT
     void applyXSLTransform(ProcessingInstructionImpl* pi);
index d3d97881c4f074947741ef12f1ad43b3dd19a5f1..87e5e480afcb17255c2eb03bd9c68902808d49de 100644 (file)
@@ -23,8 +23,8 @@
  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  */
 
-// need this until accesstool supports markers and marker ranges
-#define MARKER_SELF_TEST 0
+// need this until accesstool supports arrays of markers
+#define MARKERARRAY_SELF_TEST 0
 
 // for AXTextMarker support
 #import <ApplicationServices/ApplicationServicesPriv.h>
@@ -58,7 +58,9 @@ typedef AXTextMarkerRef (*TextMarkerFromTextMarkerRangeProc) (AXTextMarkerRangeR
 #import "render_list.h"
 #import "render_style.h"
 #import "render_text.h"
+#import "selection.h"
 #import "kjs_html.h"
+#import "text_granularity.h"
 #import "visible_position.h"
 #import "visible_text.h"
 #import "visible_units.h"
@@ -86,6 +88,7 @@ using khtml::RenderText;
 using khtml::RenderBlock;
 using khtml::RenderListMarker;
 using khtml::RenderImage;
+using khtml::Selection;
 using khtml::VisiblePosition;
 
 /* NSAccessibilityDescriptionAttribute is only defined on 10.4 and newer */
@@ -112,8 +115,15 @@ using khtml::VisiblePosition;
     return !m_renderer;
 }
 
+- (BOOL)accessibilityShouldUseUniqueId {
+    return m_renderer && m_renderer->isCanvas();
+}
+
+extern "C" void NSAccessibilityUnregisterUniqueIdForUIElement(id element);
 -(void)detach
 {
+    if ([self accessibilityShouldUseUniqueId])
+        NSAccessibilityUnregisterUniqueIdForUIElement(self);
     [m_data release];
     m_data = 0;
     [self removeAccObjectID];
@@ -146,7 +156,7 @@ using khtml::VisiblePosition;
     RenderObject* currRenderer;
     for (currRenderer = m_renderer; currRenderer && !currRenderer->element(); currRenderer = currRenderer->parent()) {
         if (currRenderer->continuation())
-            return [currRenderer->document()->getOrCreateAccObjectCache()->accObject(currRenderer->continuation()) anchorElement];
+            return [currRenderer->document()->getAccObjectCache()->accObject(currRenderer->continuation()) anchorElement];
     }
     
     // bail of none found
@@ -168,38 +178,38 @@ using khtml::VisiblePosition;
 {
     if (!m_renderer || !m_renderer->firstChild())
         return nil;
-    return m_renderer->document()->getOrCreateAccObjectCache()->accObject(m_renderer->firstChild());
+    return m_renderer->document()->getAccObjectCache()->accObject(m_renderer->firstChild());
 }
 
 -(KWQAccObject*)lastChild
 {
     if (!m_renderer || !m_renderer->lastChild())
         return nil;
-    return m_renderer->document()->getOrCreateAccObjectCache()->accObject(m_renderer->lastChild());
+    return m_renderer->document()->getAccObjectCache()->accObject(m_renderer->lastChild());
 }
 
 -(KWQAccObject*)previousSibling
 {
     if (!m_renderer || !m_renderer->previousSibling())
         return nil;
-    return m_renderer->document()->getOrCreateAccObjectCache()->accObject(m_renderer->previousSibling());
+    return m_renderer->document()->getAccObjectCache()->accObject(m_renderer->previousSibling());
 }
 
 -(KWQAccObject*)nextSibling
 {
     if (!m_renderer || !m_renderer->nextSibling())
         return nil;
-    return m_renderer->document()->getOrCreateAccObjectCache()->accObject(m_renderer->nextSibling());
+    return m_renderer->document()->getAccObjectCache()->accObject(m_renderer->nextSibling());
 }
 
 -(KWQAccObject*)parentObject
 {
     if (m_areaElement)
-        return m_renderer->document()->getOrCreateAccObjectCache()->accObject(m_renderer);
+        return m_renderer->document()->getAccObjectCache()->accObject(m_renderer);
 
     if (!m_renderer || !m_renderer->parent())
         return nil;
-    return m_renderer->document()->getOrCreateAccObjectCache()->accObject(m_renderer->parent());
+    return m_renderer->document()->getAccObjectCache()->accObject(m_renderer->parent());
 }
 
 -(KWQAccObject*)parentObjectUnignored
@@ -419,6 +429,17 @@ using khtml::VisiblePosition;
     if (m_renderer->isListMarker())
         return static_cast<RenderListMarker*>(m_renderer)->text().getNSString();
 
+    if (m_renderer->isCanvas()) {
+        KWQKHTMLPart *docPart = KWQ(m_renderer->document()->part());
+        if (!docPart)
+            return nil;
+        
+        Position startPos = VisiblePosition(m_renderer->positionForCoordinates (0, 0, nil)).deepEquivalent();
+        Position endPos   = VisiblePosition(m_renderer->positionForCoordinates (LONG_MAX, LONG_MAX, nil)).deepEquivalent();
+        NSAttributedString * attrString = docPart->attributedString(startPos.node(), startPos.offset(), endPos.node(), endPos.offset());
+        return [attrString string];
+    }
+        
     // FIXME: We might need to implement a value here for more types
     // FIXME: It would be better not to advertise a value at all for the types for which we don't implement one;
     // this would require subclassing or making accessibilityAttributeNames do something other than return a
@@ -540,7 +561,7 @@ static QRect boundingBoxRect(RenderObject* obj)
 // no parameterized attributes in Panther... they were introduced in Tiger
 #else
             (NSString *) kAXSelectedTextMarkerRangeAttribute,
-//          (NSString *) kAXVisibleCharacterTextMarkerRangeAttribute,     FO 4
+//          (NSString *) kAXVisibleCharacterTextMarkerRangeAttribute,    // NOTE: BUG FO 4
             (NSString *) kAXStartTextMarkerAttribute,
             (NSString *) kAXEndTextMarkerAttribute,
 #endif
@@ -564,7 +585,7 @@ static QRect boundingBoxRect(RenderObject* obj)
 // no parameterized attributes in Panther... they were introduced in Tiger
 #else
             (NSString *) kAXSelectedTextMarkerRangeAttribute,
-//          (NSString *) kAXVisibleCharacterTextMarkerRangeAttribute,     FO 4
+//          (NSString *) kAXVisibleCharacterTextMarkerRangeAttribute,     // NOTE: BUG FO 4
             (NSString *) kAXStartTextMarkerAttribute,
             (NSString *) kAXEndTextMarkerAttribute,
 #endif
@@ -590,7 +611,7 @@ static QRect boundingBoxRect(RenderObject* obj)
 // no parameterized attributes in Panther... they were introduced in Tiger
 #else
             (NSString *) kAXSelectedTextMarkerRangeAttribute,
-//          (NSString *) kAXVisibleCharacterTextMarkerRangeAttribute,     FO 4
+//          (NSString *) kAXVisibleCharacterTextMarkerRangeAttribute,     // NOTE: BUG FO 4
             (NSString *) kAXStartTextMarkerAttribute,
             (NSString *) kAXEndTextMarkerAttribute,
 #endif
@@ -631,34 +652,23 @@ static QRect boundingBoxRect(RenderObject* obj)
 - (void)accessibilityPerformAction:(NSString *)action
 {
     // We only have the one action (press).
+    if ([action isEqualToString:NSAccessibilityPressAction]) {
+        // Locate the anchor element. If it doesn't exist, just bail.
+        HTMLAnchorElementImpl* anchorElt = [self anchorElement];
+        if (!anchorElt)
+            return;
 
-    // Locate the anchor element. If it doesn't exist, just bail.
-    HTMLAnchorElementImpl* anchorElt = [self anchorElement];
-    if (!anchorElt)
-        return;
-
-    DocumentImpl* d = anchorElt->getDocument();
-    if (d) {
-       KHTMLPart* p = d->part();
-        if (p) {
-            KWQ(p)->prepareForUserAction();
+        DocumentImpl* d = anchorElt->getDocument();
+        if (d) {
+            KHTMLPart* p = d->part();
+            if (p) {
+                KWQ(p)->prepareForUserAction();
+            }
         }
-    }
-
-    anchorElt->click();
-}
-
-- (BOOL)accessibilityIsAttributeSettable:(NSString*)attributeName
-{
-    return NO;
-}
 
-#if 0
-// what we'd need to implement if accessibilityIsAttributeSettable ever returned YES
-- (void)accessibilitySetValue:(id)value forAttribute:(NSString *)attribute;
-{
+        anchorElt->click();
+    }
 }
-#endif
 
 #if OMIT_TIGER_FEATURES
 // no parameterized attributes in Panther... they were introduced in Tiger
@@ -680,14 +690,12 @@ static QRect boundingBoxRect(RenderObject* obj)
     if (visiblePos.isNull())
         return nil;
         
-    KWQAccObjectCache* cache = m_renderer->document()->getExistingAccObjectCache();
-    return cache->textMarkerForVisiblePosition(visiblePos);
+    return m_renderer->document()->getAccObjectCache()->textMarkerForVisiblePosition(visiblePos);
 }
 
 - (VisiblePosition) visiblePositionForTextMarker: (AXTextMarkerRef)textMarker
 {
-    KWQAccObjectCache* cache = m_renderer->document()->getExistingAccObjectCache();
-    return cache->visiblePositionForTextMarker(textMarker);
+    return m_renderer->document()->getAccObjectCache()->visiblePositionForTextMarker(textMarker);
 }
 
 - (AXTextMarkerRef) AXTextMarkerRangeCopyStartMarkerWrapper: (AXTextMarkerRangeRef)textMarkerRange
@@ -749,6 +757,28 @@ static QRect boundingBoxRect(RenderObject* obj)
 }
 #endif
 
+- (AXTextMarkerRangeRef) textMarkerRangeFromVisiblePositions: (VisiblePosition) startPosition andEndPos: (VisiblePosition) endPosition
+{
+    AXTextMarkerRef startTextMarker = [self textMarkerForVisiblePosition: startPosition];
+    AXTextMarkerRef endTextMarker   = [self textMarkerForVisiblePosition: endPosition];
+    return [self textMarkerRangeFromMarkers: startTextMarker andEndMarker:endTextMarker];
+}
+
+- (DocumentImpl *)topDocument
+{
+    return m_renderer->document()->topDocument();
+}
+
+- (RenderObject *)topRenderer
+{
+    return m_renderer->document()->topDocument()->renderer();
+}
+
+- (KHTMLView *)topView
+{
+    return m_renderer->document()->topDocument()->renderer()->canvas()->view();
+}
+
 - (id)accessibilityAttributeValue:(NSString *)attributeName
 {
     if (!m_renderer)
@@ -785,7 +815,7 @@ static QRect boundingBoxRect(RenderObject* obj)
             while (!curr.isNull()) {
                 RenderObject* obj = curr.handle()->renderer();
                 if (obj)
-                    [links addObject: obj->document()->getOrCreateAccObjectCache()->accObject(obj)];
+                    [links addObject: obj->document()->getAccObjectCache()->accObject(obj)];
                 curr = coll.nextItem();
             }
             return links;
@@ -839,29 +869,32 @@ static QRect boundingBoxRect(RenderObject* obj)
 // no parameterized attributes in Panther... they were introduced in Tiger
 #else
     if ([attributeName isEqualToString: (NSString *) kAXSelectedTextMarkerRangeAttribute]) {
-        int startPos, endPos;
-
-        RenderObject*   startRenderer = m_renderer->canvas()->selectionStart();
-        RenderObject*   endRenderer = m_renderer->canvas()->selectionEnd();
-        if (!startRenderer || !endRenderer)
-            return nil;
-        m_renderer->selectionStartEnd(startPos, endPos);
+        // get the selection from the document part
+        // NOTE: BUG support nested WebAreas, like in <http://webcourses.niu.edu/>
+        // (there is a web archive of this page attached to <rdar://problem/3888973>)
+        Selection   sel = [self topView]->part()->selection();
+        if (sel.isNone()) {
+            sel = m_renderer->document()->renderer()->canvas()->view()->part()->selection();
+            if (sel.isNone())
+                return nil;
+        }
             
-        AXTextMarkerRef startTextMarker = [self textMarkerForVisiblePosition: VisiblePosition(Position(startRenderer->node(), (long) startPos))];
-        AXTextMarkerRef endTextMarker   = [self textMarkerForVisiblePosition: VisiblePosition(Position(endRenderer->node(), (long) endPos))];
-        return (id) [self textMarkerRangeFromMarkers: startTextMarker andEndMarker:endTextMarker];
+        // return a marker range for the selection start to end
+        VisiblePosition startPosition = VisiblePosition(sel.start());
+        VisiblePosition endPosition = VisiblePosition(sel.end());
+        return (id) [self textMarkerRangeFromVisiblePositions:startPosition andEndPos:endPosition];
     }
     
     if ([attributeName isEqualToString: (NSString *) kAXVisibleCharacterTextMarkerRangeAttribute]) {
-        return nil;     // IMPLEMENT FO4
+        return nil;     // NOTE: BUG FO 4
     }
     
     if ([attributeName isEqualToString: (NSString *) kAXStartTextMarkerAttribute]) {
-        return (id) [self textMarkerForVisiblePosition: VisiblePosition(m_renderer->positionForCoordinates (0, 0, nil))];
+        return (id) [self textMarkerForVisiblePosition: VisiblePosition([self topRenderer]->positionForCoordinates (0, 0, nil))];
     }
 
     if ([attributeName isEqualToString: (NSString *) kAXEndTextMarkerAttribute]) {
-        return (id) [self textMarkerForVisiblePosition: VisiblePosition(m_renderer->positionForCoordinates (LONG_MAX, LONG_MAX, nil))];
+        return (id) [self textMarkerForVisiblePosition: VisiblePosition([self topRenderer]->positionForCoordinates (LONG_MAX, LONG_MAX, nil))];
     }
 #endif
 
@@ -874,143 +907,60 @@ static QRect boundingBoxRect(RenderObject* obj)
 - (NSArray *)accessibilityParameterizedAttributeNames
 {
     static NSArray* paramAttributes = nil;
-    static NSArray* anchorParamAttrs = nil;
-    static NSArray* webAreaParamAttrs = nil;
     if (paramAttributes == nil) {
-        paramAttributes = [[NSArray alloc] initWithObjects: NSAccessibilityRoleAttribute,
-            kAXLineForTextMarkerParameterizedAttribute,
-//          kAXTextMarkerRangeForLineParameterizedAttribute,                // FO 1
-            kAXStringForTextMarkerRangeParameterizedAttribute,
-//          kAXTextMarkerForPositionParameterizedAttribute,
-//          kAXBoundsForTextMarkerRangeParameterizedAttribute,
-//          kAXStyleTextMarkerRangeForTextMarkerParameterizedAttribute,
-//          kAXAttributedStringForTextMarkerRangeParameterizedAttribute,
-//          kAXTextMarkerRangeForUnorderedTextMarkersParameterizedAttribute,
-            kAXNextTextMarkerForTextMarkerParameterizedAttribute,
-            kAXPreviousTextMarkerForTextMarkerParameterizedAttribute,
-            kAXLeftWordTextMarkerRangeForTextMarkerParameterizedAttribute,
-            kAXRightWordTextMarkerRangeForTextMarkerParameterizedAttribute,
-//          kAXLeftLineTextMarkerRangeForTextMarkerParameterizedAttribute,                // FO 1
-//          kAXRightLineTextMarkerRangeForTextMarkerParameterizedAttribute,                // FO 1
-//          kAXSentenceTextMarkerRangeForTextMarkerParameterizedAttribute,
-//          kAXParagraphTextMarkerRangeForTextMarkerParameterizedAttribute,
-//          kAXNextWordEndTextMarkerForTextMarkerParameterizedAttribute,
-//          kAXPreviousWordStartTextMarkerForTextMarkerParameterizedAttribute,
-//          kAXNextLineEndTextMarkerForTextMarkerParameterizedAttribute,
-//          kAXPreviousLineStartTextMarkerForTextMarkerParameterizedAttribute,
-//          kAXNextSentenceEndTextMarkerForTextMarkerParameterizedAttribute,
-//          kAXPreviousSentenceStartTextMarkerForTextMarkerParameterizedAttribute,
-//          kAXNextParagraphEndTextMarkerForTextMarkerParameterizedAttribute,
-//          kAXPreviousParagraphStartTextMarkerForTextMarkerParameterizedAttribute,
-//          kAXLengthForTextMarkerRangeParameterizedAttribute,
-            nil];
-    }
-    if (anchorParamAttrs == nil) {
-        anchorParamAttrs = [[NSArray alloc] initWithObjects: NSAccessibilityRoleAttribute,
-            kAXLineForTextMarkerParameterizedAttribute,
-//          kAXTextMarkerRangeForLineParameterizedAttribute,                // FO 1
+        paramAttributes = [[NSArray alloc] initWithObjects: 
+            (id) kAXLineForTextMarkerParameterizedAttribute,
+            kAXTextMarkerRangeForLineParameterizedAttribute,
             kAXStringForTextMarkerRangeParameterizedAttribute,
-//          kAXTextMarkerForPositionParameterizedAttribute,
-//          kAXBoundsForTextMarkerRangeParameterizedAttribute,
-//          kAXStyleTextMarkerRangeForTextMarkerParameterizedAttribute,
-//          kAXAttributedStringForTextMarkerRangeParameterizedAttribute,
-//          kAXTextMarkerRangeForUnorderedTextMarkersParameterizedAttribute,
+            kAXTextMarkerForPositionParameterizedAttribute,
+            kAXBoundsForTextMarkerRangeParameterizedAttribute,
+//          kAXStyleTextMarkerRangeForTextMarkerParameterizedAttribute,                 // NOTE: BUG FO 3
+//          kAXAttributedStringForTextMarkerRangeParameterizedAttribute,                // NOTE: BUG FO 2
+            kAXTextMarkerRangeForUnorderedTextMarkersParameterizedAttribute,
             kAXNextTextMarkerForTextMarkerParameterizedAttribute,
             kAXPreviousTextMarkerForTextMarkerParameterizedAttribute,
             kAXLeftWordTextMarkerRangeForTextMarkerParameterizedAttribute,
             kAXRightWordTextMarkerRangeForTextMarkerParameterizedAttribute,
-//          kAXLeftLineTextMarkerRangeForTextMarkerParameterizedAttribute,                // FO 1
-//          kAXRightLineTextMarkerRangeForTextMarkerParameterizedAttribute,                // FO 1
-//          kAXSentenceTextMarkerRangeForTextMarkerParameterizedAttribute,
-//          kAXParagraphTextMarkerRangeForTextMarkerParameterizedAttribute,
-//          kAXNextWordEndTextMarkerForTextMarkerParameterizedAttribute,
-//          kAXPreviousWordStartTextMarkerForTextMarkerParameterizedAttribute,
-//          kAXNextLineEndTextMarkerForTextMarkerParameterizedAttribute,
-//          kAXPreviousLineStartTextMarkerForTextMarkerParameterizedAttribute,
-//          kAXNextSentenceEndTextMarkerForTextMarkerParameterizedAttribute,
-//          kAXPreviousSentenceStartTextMarkerForTextMarkerParameterizedAttribute,
-//          kAXNextParagraphEndTextMarkerForTextMarkerParameterizedAttribute,
-//          kAXPreviousParagraphStartTextMarkerForTextMarkerParameterizedAttribute,
-//          kAXLengthForTextMarkerRangeParameterizedAttribute,
+            kAXLeftLineTextMarkerRangeForTextMarkerParameterizedAttribute,
+            kAXRightLineTextMarkerRangeForTextMarkerParameterizedAttribute,
+            kAXSentenceTextMarkerRangeForTextMarkerParameterizedAttribute,
+            kAXParagraphTextMarkerRangeForTextMarkerParameterizedAttribute,
+            kAXNextWordEndTextMarkerForTextMarkerParameterizedAttribute,
+            kAXPreviousWordStartTextMarkerForTextMarkerParameterizedAttribute,
+            kAXNextLineEndTextMarkerForTextMarkerParameterizedAttribute,
+            kAXPreviousLineStartTextMarkerForTextMarkerParameterizedAttribute,
+            kAXNextSentenceEndTextMarkerForTextMarkerParameterizedAttribute,
+            kAXPreviousSentenceStartTextMarkerForTextMarkerParameterizedAttribute,
+            kAXNextParagraphEndTextMarkerForTextMarkerParameterizedAttribute,
+            kAXPreviousParagraphStartTextMarkerForTextMarkerParameterizedAttribute,
+            kAXLengthForTextMarkerRangeParameterizedAttribute,
             nil];
     }
-    if (webAreaParamAttrs == nil) {
-        webAreaParamAttrs = [[NSArray alloc] initWithObjects: NSAccessibilityRoleAttribute,
-            kAXLineForTextMarkerParameterizedAttribute,
-//          kAXTextMarkerRangeForLineParameterizedAttribute,                // FO 1
-            kAXStringForTextMarkerRangeParameterizedAttribute,
-//          kAXTextMarkerForPositionParameterizedAttribute,
-//          kAXBoundsForTextMarkerRangeParameterizedAttribute,
-//          kAXStyleTextMarkerRangeForTextMarkerParameterizedAttribute,
-//          kAXAttributedStringForTextMarkerRangeParameterizedAttribute,
-//          kAXTextMarkerRangeForUnorderedTextMarkersParameterizedAttribute,
-            kAXNextTextMarkerForTextMarkerParameterizedAttribute,
-            kAXPreviousTextMarkerForTextMarkerParameterizedAttribute,
-            kAXLeftWordTextMarkerRangeForTextMarkerParameterizedAttribute,
-            kAXRightWordTextMarkerRangeForTextMarkerParameterizedAttribute,
-//          kAXLeftLineTextMarkerRangeForTextMarkerParameterizedAttribute,                // FO 1
-//          kAXRightLineTextMarkerRangeForTextMarkerParameterizedAttribute,                // FO 1
-//          kAXSentenceTextMarkerRangeForTextMarkerParameterizedAttribute,
-//          kAXParagraphTextMarkerRangeForTextMarkerParameterizedAttribute,
-//          kAXNextWordEndTextMarkerForTextMarkerParameterizedAttribute,
-//          kAXPreviousWordStartTextMarkerForTextMarkerParameterizedAttribute,
-//          kAXNextLineEndTextMarkerForTextMarkerParameterizedAttribute,
-//          kAXPreviousLineStartTextMarkerForTextMarkerParameterizedAttribute,
-//          kAXNextSentenceEndTextMarkerForTextMarkerParameterizedAttribute,
-//          kAXPreviousSentenceStartTextMarkerForTextMarkerParameterizedAttribute,
-//          kAXNextParagraphEndTextMarkerForTextMarkerParameterizedAttribute,
-//          kAXPreviousParagraphStartTextMarkerForTextMarkerParameterizedAttribute,
-//          kAXLengthForTextMarkerRangeParameterizedAttribute,
-            nil];
-    }
-    
-    if (m_renderer && m_renderer->isCanvas())
-        return webAreaParamAttrs;
-    if (m_areaElement || (m_renderer && !m_renderer->isImage() && m_renderer->element() && m_renderer->element()->hasAnchor()))
-        return anchorParamAttrs;
-    return paramAttributes;
-}
 
-- (AXTextMarkerRangeRef) textMarkerRangeFromVisiblePositions: (VisiblePosition) startPos andEndPos: (VisiblePosition) endPos
-{
-    AXTextMarkerRef startTextMarker = [self textMarkerForVisiblePosition: startPos];
-    AXTextMarkerRef endTextMarker   = [self textMarkerForVisiblePosition: endPos];
-    return [self textMarkerRangeFromMarkers: startTextMarker andEndMarker:endTextMarker];
-}
-
-- (AXTextMarkerRangeRef) getSelectedTextMarkerRange
-{
-        int startOffset, endOffset;
-
-        RenderObject*   startRenderer = m_renderer->canvas()->selectionStart();
-        RenderObject*   endRenderer = m_renderer->canvas()->selectionEnd();
-        if (!startRenderer || !endRenderer)
-            return nil;
-        m_renderer->selectionStartEnd(startOffset, endOffset);
-            
-        VisiblePosition startPosition = VisiblePosition(Position(startRenderer->node(), (long) startOffset));
-        VisiblePosition endPosition   = VisiblePosition(Position(endRenderer->node(), (long) endOffset));
-        return [self textMarkerRangeFromVisiblePositions:startPosition andEndPos:endPosition];
+    return paramAttributes;
 }
 
 - (id)doAXLineForTextMarker: (AXTextMarkerRef) textMarker
 {
-#if MARKER_SELF_TEST
-    AXTextMarkerRangeRef textMarkerRange = [self getSelectedTextMarkerRange];
-    textMarker = [self AXTextMarkerRangeCopyStartMarkerWrapper:textMarkerRange];
-#endif
-    VisiblePosition visiblePos = [self visiblePositionForTextMarker:textMarker];
     unsigned int    lineCount = 0;
-    
-    // return nil if the marker was out of date
+    VisiblePosition savedVisiblePos;
+    VisiblePosition visiblePos = [self visiblePositionForTextMarker:textMarker];
     if (visiblePos.isNull())
         return nil;
-    
+
     // move up until we get to the top
-    // NOTE: This only takes us to the top of the element, not the top of the document
-    while (visiblePos.isNotNull()) {
+    // NOTE: BUG this is not correct in non-editable elements when the position is on the
+    // first line, but not at the first offset, because previousLinePosition takes you to the
+    // first offset, the same as if you had started on the second line.  In editable elements,
+    // previousLinePosition returns nil, so the count is accurate.
+    // NOTE: BUG This only takes us to the top of the rootEditableElement, not the top of the
+    // top document.
+    // NOTE: Can we use Selection::modify(EAlter alter, int verticalDistance)?
+    while (visiblePos.isNotNull() && visiblePos != savedVisiblePos) {
         lineCount += 1;
-        visiblePos = previousLinePosition(visiblePos, khtml::UPSTREAM, 0);
+        visiblePos.debugPosition("doAXLineForTextMarker");
+        savedVisiblePos = visiblePos;
+        visiblePos = previousLinePosition(visiblePos, khtml::DOWNSTREAM, 0);
     }
     
     return [NSNumber numberWithUnsignedInt:lineCount];
@@ -1018,9 +968,31 @@ static QRect boundingBoxRect(RenderObject* obj)
 
 - (id)doAXTextMarkerRangeForLine: (NSNumber *) lineNumber
 {
-    if (!lineNumber) return nil;
+    unsigned lineCount = [lineNumber unsignedIntValue];
+    if (lineCount == 0 || !m_renderer) return nil;
     
-    return nil;     // IMPLEMENT
+    // iterate over the lines
+    // NOTE: BUG this is wrong when lineNumber is lineCount+1,  because nextLinePosition takes you to the
+    // last offset of the last line
+    VisiblePosition visiblePos = VisiblePosition([self topRenderer]->positionForCoordinates (0, 0, nil));
+    VisiblePosition savedVisiblePos;
+    while (--lineCount != 0) {
+        savedVisiblePos = visiblePos;
+        visiblePos = nextLinePosition(visiblePos, khtml::DOWNSTREAM, 0);
+        if (visiblePos.isNull() || visiblePos == savedVisiblePos)
+            return nil;
+    }
+    
+    // make a caret selection for the marker position, then extend it to the line
+    Selection sel = Selection(visiblePos, visiblePos);
+    bool worked = sel.modify(Selection::EXTEND, Selection::RIGHT, khtml::LINE_BOUNDARY);
+    if (!worked)
+        return nil;
+
+    // return a marker range for the selection start to end
+    VisiblePosition startPosition = VisiblePosition(sel.start());
+    VisiblePosition endPosition = VisiblePosition(sel.end());
+    return (id) [self textMarkerRangeFromVisiblePositions:startPosition andEndPos:endPosition];
 }
 
 - (id)doAXStringForTextMarkerRange: (AXTextMarkerRangeRef) textMarkerRange
@@ -1029,16 +1001,14 @@ static QRect boundingBoxRect(RenderObject* obj)
     Position startDeepPos, endDeepPos;
     QString qString;
     
-#if MARKER_SELF_TEST
-    textMarkerRange = [self getSelectedTextMarkerRange];
-#endif
-    
     // extract the start and end VisiblePosition
     startVisiblePosition = [self visiblePositionForStartOfTextMarkerRange: textMarkerRange];
-    if (startVisiblePosition.isNull()) return nil;
+    if (startVisiblePosition.isNull())
+        return nil;
     
     endVisiblePosition = [self visiblePositionForEndOfTextMarkerRange: textMarkerRange];
-    if (endVisiblePosition.isNull()) return nil;
+    if (endVisiblePosition.isNull())
+        return nil;
     
     // use deepEquivalent because it is what the user sees
     startDeepPos = startVisiblePosition.deepEquivalent();
@@ -1048,42 +1018,142 @@ static QRect boundingBoxRect(RenderObject* obj)
     qString = plainText(Range(startDeepPos.node(), startDeepPos.offset(), endDeepPos.node(), endDeepPos.offset()));
     if (qString == nil) return nil;
     
-    // transform it to a CFString
+    // transform it to a CFString and return that
     return (id)qString.getCFString();
 }
 
-- (id)doAXNextTextMarkerForTextMarker: (AXTextMarkerRef) textMarker
+- (id)doAXTextMarkerForPosition: (CGPoint) point
 {
-#if MARKER_SELF_TEST
-    AXTextMarkerRangeRef textMarkerRange = [self getSelectedTextMarkerRange];
-    textMarker = [self AXTextMarkerRangeCopyEndMarkerWrapper:textMarkerRange];
+    NSPoint screenpoint = NSMakePoint(point.x, point.y);
+    NSView * view = [self topView]->getView();
+    NSPoint windowpoint = [[view window] convertScreenToBase: screenpoint];
+    NSPoint ourpoint = [view convertPoint:windowpoint fromView:nil];
+
+    VisiblePosition visiblePos = VisiblePosition([self topRenderer]->positionForCoordinates ((int)ourpoint.x, (int)ourpoint.y, nil));
+    return (id) [self textMarkerForVisiblePosition:visiblePos];
+}
+
+- (id)doAXBoundsForTextMarkerRange: (AXTextMarkerRangeRef) textMarkerRange
+{
+
+    // extract the start and end VisiblePosition
+    VisiblePosition startVisiblePosition = [self visiblePositionForStartOfTextMarkerRange: textMarkerRange];
+    if (startVisiblePosition.isNull())
+        return nil;
+    
+    VisiblePosition endVisiblePosition = [self visiblePositionForEndOfTextMarkerRange: textMarkerRange];
+    if (endVisiblePosition.isNull())
+        return nil;
+    
+    // use the Selection class to help calculate the corresponding rectangle
+    // NOTE: If the selection spans lines, the rectangle is to extend across
+    // the width of the view
+    NSView * view = [self topView]->getView();
+    QRect rect1 = Selection(startVisiblePosition, startVisiblePosition).caretRect();
+    QRect rect2 = Selection(endVisiblePosition, endVisiblePosition).caretRect();
+    QRect ourrect = rect1.unite(rect2);
+    if (rect1.bottom() != rect2.bottom()) {
+        ourrect.setX((int)[view frame].origin.x);
+        ourrect.setWidth((int)[view frame].size.width);
+    }
+    // convert our rectangle to screen coordinates
+    NSRect rect = NSMakeRect(ourrect.left(), ourrect.top(), ourrect.width(), ourrect.height());
+    rect = [view convertRect:rect toView:nil];
+    rect.origin = [[view window] convertBaseToScreen:rect.origin];
+    
+    // return the converted rect
+    return [NSValue valueWithRect:rect];
+}
+
+- (id)doAXAttributedStringForTextMarkerRange: (AXTextMarkerRangeRef) textMarkerRange
+{
+    // NOTE: BUG FO 2 Needs to make AX attributed string 
+    // Patti: Get the basic done first.  Add various text attribute support incrementally,
+    // starting with attachment and hyperlink.  The rest of the attributes can be FO2/3.
+
+    // extract the start and end VisiblePosition
+    VisiblePosition startVisiblePosition = [self visiblePositionForStartOfTextMarkerRange: textMarkerRange];
+    if (startVisiblePosition.isNull())
+        return nil;
+    
+    VisiblePosition endVisiblePosition = [self visiblePositionForEndOfTextMarkerRange: textMarkerRange];
+    if (endVisiblePosition.isNull())
+        return nil;
+    
+    // get the attributed string by asking the document part
+    KWQKHTMLPart *docPart = KWQ([self topDocument]->part());
+    if (!docPart)
+        return nil;
+    
+    Position    startPos = startVisiblePosition.deepEquivalent();
+    Position    endPos   = endVisiblePosition.deepEquivalent();
+    NSAttributedString * attrString = docPart->attributedString(startPos.node(), startPos.offset(), endPos.node(), endPos.offset());
+    return attrString;
+}
+
+- (id)doAXTextMarkerRangeForUnorderedTextMarkers: (NSArray *) markers
+{
+#if MARKERARRAY_SELF_TEST
+    AXTextMarkerRangeRef tmr = [self getSelectedTextMarkerRange];
+    AXTextMarkerRef tm1 = [self AXTextMarkerRangeCopyEndMarkerWrapper:tmr];
+    AXTextMarkerRef tm2 = [self AXTextMarkerRangeCopyStartMarkerWrapper:tmr];
+    markers = [NSArray arrayWithObjects: (id) tm1, (id) tm2, nil];
 #endif
+    // get and validate the markers
+    if ([markers count] < 2)
+        return nil;
+    
+    AXTextMarkerRef textMarker1 = (AXTextMarkerRef) [markers objectAtIndex:0];
+    AXTextMarkerRef textMarker2 = (AXTextMarkerRef) [markers objectAtIndex:1];
+    if (CFGetTypeID(textMarker1) != AXTextMarkerGetTypeID() || CFGetTypeID(textMarker2) != AXTextMarkerGetTypeID())
+        return nil;
+    
+    // convert to VisiblePosition
+    VisiblePosition visiblePos1 = [self visiblePositionForTextMarker:textMarker1];
+    VisiblePosition visiblePos2 = [self visiblePositionForTextMarker:textMarker2];
+    if (visiblePos1.isNull() || visiblePos2.isNull())
+        return nil;
+    
+    // use the Selection class to do the ordering
+    // NOTE: Perhaps we could add a Selection method to indicate direction, based on m_baseIsStart
+    AXTextMarkerRef startTextMarker;
+    AXTextMarkerRef endTextMarker;
+    Selection   sel(visiblePos1, visiblePos2);
+    if (sel.base() == sel.start()) {
+        startTextMarker = textMarker1;
+        endTextMarker = textMarker2;
+    } else {
+        startTextMarker = textMarker2;
+        endTextMarker = textMarker1;
+    }
+    
+    // return a range based on the Selection verdict
+    return (id) [self textMarkerRangeFromMarkers: startTextMarker andEndMarker:endTextMarker];
+}
+
+- (id)doAXNextTextMarkerForTextMarker: (AXTextMarkerRef) textMarker
+{
     VisiblePosition visiblePos = [self visiblePositionForTextMarker:textMarker];
     VisiblePosition nextVisiblePos = visiblePos.next();
-    if (nextVisiblePos.isNull()) return nil;
+    if (nextVisiblePos.isNull())
+        return nil;
     
     return (id) [self textMarkerForVisiblePosition:nextVisiblePos];
 }
 
 - (id)doAXPreviousTextMarkerForTextMarker: (AXTextMarkerRef) textMarker
 {
-#if MARKER_SELF_TEST
-    AXTextMarkerRangeRef textMarkerRange = [self getSelectedTextMarkerRange];
-    textMarker = [self AXTextMarkerRangeCopyStartMarkerWrapper:textMarkerRange];
-#endif
     VisiblePosition visiblePos = [self visiblePositionForTextMarker:textMarker];
     VisiblePosition previousVisiblePos = visiblePos.previous();
-    if (previousVisiblePos.isNull()) return nil;
+    if (previousVisiblePos.isNull())
+        return nil;
     
     return (id) [self textMarkerForVisiblePosition:previousVisiblePos];
 }
 
 - (id)doAXLeftWordTextMarkerRangeForTextMarker: (AXTextMarkerRef) textMarker
 {
-#if MARKER_SELF_TEST
-    AXTextMarkerRangeRef textMarkerRange = [self getSelectedTextMarkerRange];
-    textMarker = [self AXTextMarkerRangeCopyStartMarkerWrapper:textMarkerRange];
-#endif
     VisiblePosition visiblePos = [self visiblePositionForTextMarker:textMarker];
     VisiblePosition startPosition = startOfWord(visiblePos, khtml::LeftWordIfOnBoundary);
     VisiblePosition endPosition = endOfWord(startPosition);
@@ -1093,10 +1163,6 @@ static QRect boundingBoxRect(RenderObject* obj)
 
 - (id)doAXRightWordTextMarkerRangeForTextMarker: (AXTextMarkerRef) textMarker
 {
-#if MARKER_SELF_TEST
-    AXTextMarkerRangeRef textMarkerRange = [self getSelectedTextMarkerRange];
-    textMarker = [self AXTextMarkerRangeCopyEndMarkerWrapper:textMarkerRange];
-#endif
     VisiblePosition visiblePos = [self visiblePositionForTextMarker:textMarker];
     VisiblePosition startPosition = startOfWord(visiblePos, khtml::RightWordIfOnBoundary);
     VisiblePosition endPosition = endOfWord(startPosition);
@@ -1106,46 +1172,217 @@ static QRect boundingBoxRect(RenderObject* obj)
 
 - (id)doAXLeftLineTextMarkerRangeForTextMarker: (AXTextMarkerRef) textMarker
 {
-#if 0
-## startOfLine and endOfLine are declared but not defined
+    // use Selection class instead of visible_units because startOfLine and endOfLine
+    // are declared but not defined
     VisiblePosition visiblePos = [self visiblePositionForTextMarker:textMarker];
-    VisiblePosition startPosition = startOfLine(visiblePos, khtml::UPSTREAM);
-    VisiblePosition endPosition = endOfLine(startPosition, khtml::DOWNSTREAM);
-
+    if (visiblePos.isNull())
+        return nil;
+    
+    // make a caret selection for the position before marker position (to make sure
+    // we move off of a line start)
+    VisiblePosition prevVisiblePos = visiblePos.previous();
+    if (prevVisiblePos.isNull())
+        return nil;
+    
+    // extend selection to the line
+    // NOTE: ignores results of sel.modify because it returns false when
+    // starting at an empty line.  The resulting selection in that case
+    // will be a caret at prevVisiblePos. 
+    Selection sel = Selection(prevVisiblePos, prevVisiblePos);
+    (void)sel.modify(Selection::MOVE, Selection::LEFT, khtml::LINE_BOUNDARY);
+    (void)sel.modify(Selection::EXTEND, Selection::RIGHT, khtml::LINE_BOUNDARY);
+
+    // return a marker range for the selection start to end
+    VisiblePosition startPosition = VisiblePosition(sel.start());
+    VisiblePosition endPosition = VisiblePosition(sel.end());
     return (id) [self textMarkerRangeFromVisiblePositions:startPosition andEndPos:endPosition];
-#else
-    // use Selection class instead
-    return nil;
-#endif
 }
 
 - (id)doAXRightLineTextMarkerRangeForTextMarker: (AXTextMarkerRef) textMarker
 {
-#if 0
-## startOfLine and endOfLine are declared but not defined
+    // use Selection class instead of visible_units because startOfLine and endOfLine
+    // are declared but not defined
     VisiblePosition visiblePos = [self visiblePositionForTextMarker:textMarker];
-    VisiblePosition startPosition = startOfLine(visiblePos, khtml::DOWNSTREAM);
-    VisiblePosition endPosition = endOfLine(startPosition, khtml::DOWNSTREAM);
+    if (visiblePos.isNull())
+        return nil;
+    
+    // make a caret selection for the marker position, then extend it to the line
+    VisiblePosition nextVisiblePos = visiblePos.next();
+    if (nextVisiblePos.isNull())
+        return nil;
+        
+    // NOTE: ignores results of sel.modify because it returns false when
+    // starting at an empty line.  The resulting selection in that case
+    // will be a caret at nextVisiblePos. 
+    Selection sel = Selection(nextVisiblePos, nextVisiblePos);
+    (void)sel.modify(Selection::MOVE, Selection::RIGHT, khtml::LINE_BOUNDARY);
+    (void)sel.modify(Selection::EXTEND, Selection::LEFT, khtml::LINE_BOUNDARY);
+
+    // return a marker range for the selection start to end
+    VisiblePosition startPosition = VisiblePosition(sel.start());
+    VisiblePosition endPosition = VisiblePosition(sel.end());
+    return (id) [self textMarkerRangeFromVisiblePositions:startPosition andEndPos:endPosition];
+}
+
+- (id)doAXSentenceTextMarkerRangeForTextMarker: (AXTextMarkerRef) textMarker
+{
+    // NOTE: BUG FO 2 IMPLEMENT (currently returns incorrect answer)
+    // Related? <rdar://problem/3927736> Text selection broken in 8A336
+    VisiblePosition visiblePos = [self visiblePositionForTextMarker:textMarker];
+    VisiblePosition startPosition = startOfSentence(visiblePos);
+    VisiblePosition endPosition = endOfSentence(startPosition);
 
     return (id) [self textMarkerRangeFromVisiblePositions:startPosition andEndPos:endPosition];
-#else
-    // use Selection class instead
-    return nil;
-#endif
+}
+
+- (id)doAXParagraphTextMarkerRangeForTextMarker: (AXTextMarkerRef) textMarker
+{
+    VisiblePosition visiblePos = [self visiblePositionForTextMarker:textMarker];
+    VisiblePosition startPosition = startOfParagraph(visiblePos);
+    VisiblePosition endPosition = endOfParagraph(startPosition);
+
+    return (id) [self textMarkerRangeFromVisiblePositions:startPosition andEndPos:endPosition];
+}
+
+- (id)doAXNextWordEndTextMarkerForTextMarker: (AXTextMarkerRef) textMarker
+{
+    VisiblePosition visiblePos = [self visiblePositionForTextMarker:textMarker];
+    if (visiblePos.isNull())
+        return nil;
+
+    VisiblePosition endPosition = endOfWord(visiblePos, khtml::RightWordIfOnBoundary);
+    return (id) [self textMarkerForVisiblePosition: endPosition];
+}
+
+- (id)doAXPreviousWordStartTextMarkerForTextMarker: (AXTextMarkerRef) textMarker
+{
+    VisiblePosition visiblePos = [self visiblePositionForTextMarker:textMarker];
+    if (visiblePos.isNull())
+        return nil;
+
+    VisiblePosition startPosition = startOfWord(visiblePos, khtml::LeftWordIfOnBoundary);
+    return (id) [self textMarkerForVisiblePosition: startPosition];
+}
+
+- (id)doAXNextLineEndTextMarkerForTextMarker: (AXTextMarkerRef) textMarker
+{
+    // use Selection class instead of visible_units because startOfLine and endOfLine
+    // are declared but not defined
+    VisiblePosition visiblePos = [self visiblePositionForTextMarker:textMarker];
+    if (visiblePos.isNull())
+        return nil;
+    
+    // make a caret selection for the marker position, then move it to the line end
+    VisiblePosition nextVisiblePos = visiblePos.next();
+    if (nextVisiblePos.isNull())
+        return nil;
+        
+    Selection sel = Selection(nextVisiblePos, nextVisiblePos);
+    bool worked = sel.modify(Selection::MOVE, Selection::RIGHT, khtml::LINE_BOUNDARY);
+    if (!worked)
+        return nil;
+
+    // return a marker for the selection end
+    VisiblePosition endPosition = VisiblePosition(sel.end());
+    return (id) [self textMarkerForVisiblePosition: endPosition];
+}
+
+- (id)doAXPreviousLineStartTextMarkerForTextMarker: (AXTextMarkerRef) textMarker
+{
+    // use Selection class instead of visible_units because startOfLine and endOfLine
+    // are declared but not defined
+    VisiblePosition visiblePos = [self visiblePositionForTextMarker:textMarker];
+    if (visiblePos.isNull())
+        return nil;
+    
+    // make a caret selection for the marker position, then move it to the line start
+    VisiblePosition prevVisiblePos = visiblePos.previous();
+    if (prevVisiblePos.isNull())
+        return nil;
+        
+    Selection sel = Selection(prevVisiblePos, prevVisiblePos);
+    bool worked = sel.modify(Selection::MOVE, Selection::LEFT, khtml::LINE_BOUNDARY);
+    if (!worked)
+        return nil;
+
+    // return a marker for the selection start
+    VisiblePosition startPosition = VisiblePosition(sel.start());
+    return (id) [self textMarkerForVisiblePosition: startPosition];
+}
+
+- (id)doAXNextSentenceEndTextMarkerForTextMarker: (AXTextMarkerRef) textMarker
+{
+    // NOTE: BUG FO 2 IMPLEMENT (currently returns incorrect answer)
+    // Related? <rdar://problem/3927736> Text selection broken in 8A336
+    VisiblePosition visiblePos = [self visiblePositionForTextMarker:textMarker];
+    if (visiblePos.isNull())
+        return nil;
+
+    VisiblePosition endPosition = endOfSentence(visiblePos);
+    return (id) [self textMarkerForVisiblePosition: endPosition];
+}
+
+- (id)doAXPreviousSentenceStartTextMarkerForTextMarker: (AXTextMarkerRef) textMarker
+{
+    // NOTE: BUG FO 2 IMPLEMENT (currently returns incorrect answer)
+    // Related? <rdar://problem/3927736> Text selection broken in 8A336
+    VisiblePosition visiblePos = [self visiblePositionForTextMarker:textMarker];
+    if (visiblePos.isNull())
+        return nil;
+
+    VisiblePosition startPosition = startOfSentence(visiblePos);
+    return (id) [self textMarkerForVisiblePosition: startPosition];
+}
+
+- (id)doAXNextParagraphEndTextMarkerForTextMarker: (AXTextMarkerRef) textMarker
+{
+    VisiblePosition visiblePos = [self visiblePositionForTextMarker:textMarker];
+    if (visiblePos.isNull())
+        return nil;
+
+    VisiblePosition endPosition = endOfParagraph(visiblePos);
+    return (id) [self textMarkerForVisiblePosition: endPosition];
+}
+
+- (id)doAXPreviousParagraphStartTextMarkerForTextMarker: (AXTextMarkerRef) textMarker
+{
+    VisiblePosition visiblePos = [self visiblePositionForTextMarker:textMarker];
+    if (visiblePos.isNull())
+        return nil;
+
+    VisiblePosition startPosition = startOfParagraph(visiblePos);
+    return (id) [self textMarkerForVisiblePosition: startPosition];
+}
+
+- (id)doAXLengthForTextMarkerRange: (AXTextMarkerRangeRef) textMarkerRange
+{
+    // NOTE: BUG Multi-byte support
+    CFStringRef string = (CFStringRef) [self doAXStringForTextMarkerRange: textMarkerRange];
+    if (!string)
+        return nil;
+
+    return [NSNumber numberWithInt:CFStringGetLength(string)];
 }
 
 - (id)accessibilityAttributeValue:(NSString *)attribute forParameter:(id)parameter
 {
     AXTextMarkerRef         textMarker = nil;
     AXTextMarkerRangeRef    textMarkerRange = nil;
+    AXValueRef              value = nil;
     NSNumber *              number = nil;
-
+    NSArray *               array = nil;
+    CGPoint                 point;
+    CGSize                  size;
+    CGRect                  rect;
+    CFRange                 range;
+    AXError                 error;
+    
     // basic parameter validation
     if (!m_renderer || !attribute || !parameter)
         return nil;
 
     // common parameter type check/casting.  Nil checks in handlers catch wrong type case.
-    // NOTE: This assumes nil is not a valid parameter, because itis indistinguishable from
+    // NOTE: This assumes nil is not a valid parameter, because it is indistinguishable from
     // a parameter of the wrong type.
     if (CFGetTypeID(parameter) == AXTextMarkerGetTypeID())
         textMarker = (AXTextMarkerRef) parameter;
@@ -1153,8 +1390,33 @@ static QRect boundingBoxRect(RenderObject* obj)
     else if (CFGetTypeID(parameter) == AXTextMarkerRangeGetTypeID())
         textMarkerRange = (AXTextMarkerRangeRef) parameter;
 
-    else if ([parameter isKindOfClass:[NSNumber self]]) {
+    else if ([parameter isKindOfClass:[NSNumber self]])
         number = parameter;
+
+    else if ([parameter isKindOfClass:[NSArray self]])
+        array = parameter;
+
+    else if (CFGetTypeID(parameter) == AXValueGetTypeID()) {
+        value = (AXValueRef) parameter;
+        switch (AXValueGetType(value)) {
+            case kAXValueCGPointType:
+                AXValueGetValue(value, kAXValueCGPointType, &point);
+                break;
+            case kAXValueCGSizeType:
+                AXValueGetValue(value, kAXValueCGSizeType, &size);
+                break;
+            case kAXValueCGRectType:
+                AXValueGetValue(value, kAXValueCGRectType, &rect);
+                break;
+            case kAXValueCFRangeType:
+                AXValueGetValue(value, kAXValueCFRangeType, &range);
+                break;
+            case kAXValueAXErrorType:
+                AXValueGetValue(value, kAXValueAXErrorType, &error);
+                break;
+            default:
+                break;
+        }
     }
   
     // dispatch
@@ -1167,6 +1429,18 @@ static QRect boundingBoxRect(RenderObject* obj)
     if ([attribute isEqualToString: (NSString *) kAXStringForTextMarkerRangeParameterizedAttribute])
         return [self doAXStringForTextMarkerRange: textMarkerRange];
 
+    if ([attribute isEqualToString: (NSString *) kAXTextMarkerForPositionParameterizedAttribute])
+        return [self doAXTextMarkerForPosition: point];
+
+    if ([attribute isEqualToString: (NSString *) kAXBoundsForTextMarkerRangeParameterizedAttribute])
+        return [self doAXBoundsForTextMarkerRange: textMarkerRange];
+
+    if ([attribute isEqualToString: (NSString *) kAXAttributedStringForTextMarkerRangeParameterizedAttribute])
+        return [self doAXAttributedStringForTextMarkerRange: textMarkerRange];
+
+    if ([attribute isEqualToString: (NSString *) kAXTextMarkerRangeForUnorderedTextMarkersParameterizedAttribute])
+        return [self doAXTextMarkerRangeForUnorderedTextMarkers: array];
+
     if ([attribute isEqualToString: (NSString *) kAXNextTextMarkerForTextMarkerParameterizedAttribute])
         return [self doAXNextTextMarkerForTextMarker: textMarker];
 
@@ -1185,10 +1459,39 @@ static QRect boundingBoxRect(RenderObject* obj)
     if ([attribute isEqualToString: (NSString *) kAXRightLineTextMarkerRangeForTextMarkerParameterizedAttribute])
         return [self doAXRightLineTextMarkerRangeForTextMarker: textMarker];
 
-#if 0
-    if ([attribute isEqualToString: (NSString *) XXXX])
-        return [self doXXXX: textMarker];
-#endif
+    if ([attribute isEqualToString: (NSString *) kAXSentenceTextMarkerRangeForTextMarkerParameterizedAttribute])
+        return [self doAXSentenceTextMarkerRangeForTextMarker: textMarker];
+
+    if ([attribute isEqualToString: (NSString *) kAXParagraphTextMarkerRangeForTextMarkerParameterizedAttribute])
+        return [self doAXParagraphTextMarkerRangeForTextMarker: textMarker];
+
+    if ([attribute isEqualToString: (NSString *) kAXNextWordEndTextMarkerForTextMarkerParameterizedAttribute])
+        return [self doAXNextWordEndTextMarkerForTextMarker: textMarker];
+
+    if ([attribute isEqualToString: (NSString *) kAXPreviousWordStartTextMarkerForTextMarkerParameterizedAttribute])
+        return [self doAXPreviousWordStartTextMarkerForTextMarker: textMarker];
+        
+    if ([attribute isEqualToString: (NSString *) kAXNextLineEndTextMarkerForTextMarkerParameterizedAttribute])
+        return [self doAXNextLineEndTextMarkerForTextMarker: textMarker];
+        
+    if ([attribute isEqualToString: (NSString *) kAXPreviousLineStartTextMarkerForTextMarkerParameterizedAttribute])
+        return [self doAXPreviousLineStartTextMarkerForTextMarker: textMarker];
+        
+    if ([attribute isEqualToString: (NSString *) kAXNextSentenceEndTextMarkerForTextMarkerParameterizedAttribute])
+        return [self doAXNextSentenceEndTextMarkerForTextMarker: textMarker];
+        
+    if ([attribute isEqualToString: (NSString *) kAXPreviousSentenceStartTextMarkerForTextMarkerParameterizedAttribute])
+        return [self doAXPreviousSentenceStartTextMarkerForTextMarker: textMarker];
+        
+    if ([attribute isEqualToString: (NSString *) kAXNextParagraphEndTextMarkerForTextMarkerParameterizedAttribute])
+        return [self doAXNextParagraphEndTextMarkerForTextMarker: textMarker];
+
+    if ([attribute isEqualToString: (NSString *) kAXPreviousParagraphStartTextMarkerForTextMarkerParameterizedAttribute])
+        return [self doAXPreviousParagraphStartTextMarkerForTextMarker: textMarker];
+        
+    if ([attribute isEqualToString: (NSString *) kAXLengthForTextMarkerRangeParameterizedAttribute])
+        return [self doAXLengthForTextMarkerRange: textMarkerRange];
+
     return nil;
 }
 
@@ -1206,16 +1509,57 @@ static QRect boundingBoxRect(RenderObject* obj)
     RenderObject* obj = nodeInfo.innerNode()->renderer();
     if (!obj)
         return self;
-    return obj->document()->getOrCreateAccObjectCache()->accObject(obj);
+    return obj->document()->getAccObjectCache()->accObject(obj);
 }
 
-#if 0
-// NOTE: why don't we override this?  Probablly because AppKit's done it for us.
 - (id)accessibilityFocusedUIElement
 {
+    // NOTE: BUG support nested WebAreas
+    NodeImpl *focusNode = m_renderer->document()->focusNode();
+    if (!focusNode || !focusNode->renderer())
+        return nil;
+
+    return focusNode->renderer()->document()->getAccObjectCache()->accObject(focusNode->renderer());
 }
 
-#endif
+- (BOOL)accessibilityIsAttributeSettable:(NSString*)attributeName
+{
+    if ([attributeName isEqualToString: (NSString *) kAXSelectedTextMarkerRangeAttribute])
+        return YES;
+        
+    return NO;
+}
+
+- (void)doSetAXSelectedTextMarkerRange: (AXTextMarkerRangeRef)textMarkerRange
+{
+    VisiblePosition startVisiblePosition, endVisiblePosition;
+    
+    // extract the start and end VisiblePosition
+    startVisiblePosition = [self visiblePositionForStartOfTextMarkerRange: textMarkerRange];
+    if (startVisiblePosition.isNull())
+        return;
+    
+    endVisiblePosition = [self visiblePositionForEndOfTextMarkerRange: textMarkerRange];
+    if (endVisiblePosition.isNull())
+        return;
+    
+    // make selection and tell the document to use it
+    // NOTE: BUG support nested WebAreas
+    Selection sel = Selection(startVisiblePosition, endVisiblePosition);
+    [self topDocument]->part()->setSelection(sel);
+}
+
+- (void)accessibilitySetValue:(id)value forAttribute:(NSString *)attributeName;
+{
+    AXTextMarkerRangeRef    textMarkerRange = nil;
+
+    if (CFGetTypeID(value) == AXTextMarkerRangeGetTypeID())
+        textMarkerRange = (AXTextMarkerRangeRef) value;
+        
+    if ([attributeName isEqualToString: (NSString *) kAXSelectedTextMarkerRangeAttribute]) {
+        [self doSetAXSelectedTextMarkerRange:textMarkerRange];
+    }
+}
 
 - (void)childrenChanged
 {
@@ -1238,14 +1582,12 @@ static QRect boundingBoxRect(RenderObject* obj)
 
 -(void)setAccObjectID:(KWQAccObjectID) accObjectID
 {
-//    ASSERT(accObjectID == 0 || m_accObjectID == 0);
     m_accObjectID = accObjectID;
 }
 
 - (void)removeAccObjectID
 {
-    KWQAccObjectCache* cache = m_renderer->document()->getExistingAccObjectCache();
-    cache->removeAccObjectID(self);
+    m_renderer->document()->getAccObjectCache()->removeAccObjectID(self);
 }
 
 @end
index f80221a19f7eb181b1596462696eea7726e56e99..d4299b1a9848be342dfb7c8e898ed938ec208ea4 100644 (file)
@@ -66,6 +66,8 @@ public:
     void childrenChanged(khtml::RenderObject* renderer);
 
     void postNotification(khtml::RenderObject* renderer, const QString& msg);
+    void postNotificationToTopWebArea(khtml::RenderObject* renderer, const QString& msg);
+    void handleFocusedUIElementChanged(void);
     
     static void enableAccessibility() { gAccessibilityEnabled = true; }
     static bool accessibilityEnabled() { return gAccessibilityEnabled; }
index 05e632c720fda6c2ccd26e86c46e699af42c7869..27b1b3c5ba622ee89ac7aae26fb61e7d9ca55c43 100644 (file)
@@ -29,6 +29,7 @@
 #include "KWQAssertions.h"
 #include "KWQFoundationExtras.h"
 #include <qstring.h>
+#include <render_object.h>
 
 using khtml::RenderObject;
 using khtml::VisiblePosition;
@@ -86,6 +87,7 @@ void KWQAccObjectCache::setAccObject(RenderObject* impl, KWQAccObject* accObject
         accCache = CFDictionaryCreateMutable(NULL, 0, NULL, NULL);
     
     CFDictionarySetValue(accCache, (const void *)impl, accObject);
+    ASSERT(!accCacheByID || CFDictionaryGetCount(accCache) >= CFDictionaryGetCount(accCacheByID));
 }
 
 void KWQAccObjectCache::removeAccObject(RenderObject* impl)
@@ -99,6 +101,8 @@ void KWQAccObjectCache::removeAccObject(RenderObject* impl)
         [obj release];
         CFDictionaryRemoveValue(accCache, impl);
     }
+
+    ASSERT(!accCacheByID || CFDictionaryGetCount(accCache) >= CFDictionaryGetCount(accCacheByID));
 }
 
 KWQAccObjectID KWQAccObjectCache::getAccObjectID(KWQAccObject* accObject)
@@ -202,7 +206,7 @@ VisiblePosition   KWQAccObjectCache::visiblePositionForTextMarker (AXTextMarkerR
     }
 
     // return empty position if the text marker is no longer valid
-    if (!CFDictionaryContainsKey(accCacheByID, (const void *)textMarkerData->accObjectID))
+    if (!accCacheByID || !CFDictionaryContainsKey(accCacheByID, (const void *)textMarkerData->accObjectID))
         return VisiblePosition();
 
     // return the position from the data we stored earlier
@@ -227,7 +231,26 @@ void KWQAccObjectCache::childrenChanged(RenderObject* renderer)
     [obj childrenChanged];
 }
 
+void KWQAccObjectCache::postNotificationToTopWebArea(RenderObject* renderer, const QString& msg)
+{
+    if (renderer) {
+        RenderObject * obj = renderer->document()->topDocument()->renderer();
+        NSAccessibilityPostNotification(accObject(obj), msg.getNSString());
+    }
+}
+
 void KWQAccObjectCache::postNotification(RenderObject* renderer, const QString& msg)
 {
-    NSAccessibilityPostNotification(accObject(renderer), msg.getNSString());
+    if (renderer)
+        NSAccessibilityPostNotification(accObject(renderer), msg.getNSString());
+}
+
+extern "C" void NSAccessibilityHandleFocusChanged(void);
+void KWQAccObjectCache::handleFocusedUIElementChanged(void)
+{
+    // This is an internal AppKit call that does a number of things in addition to
+    // sending the AXFocusedUIElementChanged notification.  It will call
+    // will call accessibilityFocusedUIElement() to determine which element
+    // to include in the notification.
+    NSAccessibilityHandleFocusChanged();
 }
index 9f8d9d547c79ef966f9af6ffeabb10e4491d63ef..00d4999341529c7a3bcd9aaa5f41c6e67dd85468 100644 (file)
 #import <JavaScriptCore/runtime_root.h>
 #import <JavaScriptCore/WebScriptObjectPrivate.h>
 
+#if APPLE_CHANGES
+#import "KWQAccObjectCache.h"
+#endif
+
 #undef _KWQ_TIMING
 
 using DOM::AtomicString;
@@ -3991,6 +3995,11 @@ void KWQKHTMLPart::respondToChangedSelection(const Selection &oldSelection, bool
 
 void KWQKHTMLPart::respondToChangedContents()
 {
+#if APPLE_CHANGES
+    if (KWQAccObjectCache::accessibilityEnabled()) {
+        renderer()->document()->getAccObjectCache()->postNotificationToTopWebArea(renderer(), "AXValueChanged");
+    }
+#endif
     [_bridge respondToChangedContents];
 }
 
index 54a99b417e40b1937cd31ec50d86495abbe6d4c5..7aff933322a0a3e09b420b66073e006197e42dec 100644 (file)
@@ -30,5 +30,7 @@ class QChar;
  
 void KWQFindWordBoundary(const QChar *chars, int len, int position, int *start, int *end);
 int KWQFindNextWordFromIndex(const QChar *chars, int len, int position, bool forward);
+void KWQFindSentenceBoundary(const QChar *chars, int len, int position, int *start, int *end);
+int KWQFindNextSentenceFromIndex(const QChar *chars, int len, int position, bool forward);
 
 #endif
\ No newline at end of file
index cedaa5bff2f95752146272f527f391eeadc91a57..372b3f1a154a466b8ed9f1c48eb8fa437e946d37 100644 (file)
@@ -27,6 +27,9 @@
 
 #import "KWQString.h"
 #import <AppKit/NSAttributedString.h>
+#import <unicode/ubrk.h>
+#import <unicode/ustring.h>
+#import <unicode/utypes.h>
 
 void KWQFindWordBoundary(const QChar *chars, int len, int position, int *start, int *end)
 {
@@ -50,3 +53,52 @@ int KWQFindNextWordFromIndex(const QChar *chars, int len, int position, bool for
     [string release];
     return result;
 }
+
+void KWQFindSentenceBoundary(const QChar *chars, int len, int position, int *start, int *end)
+{
+    int  startPos = 0;
+    int  endPos = 0;
+
+    const char *localeName = [[NSString localizedNameOfStringEncoding:NSASCIIStringEncoding] UTF8String];
+    UErrorCode status = U_ZERO_ERROR;
+    UBreakIterator *boundary = ubrk_open(UBRK_SENTENCE, localeName, const_cast<unichar *>(reinterpret_cast<const unichar *>(chars)) + position, len, &status);
+    if ( boundary && U_SUCCESS(status) ) {
+        startPos = ubrk_first(boundary);
+        if (startPos == UBRK_DONE)
+            startPos = 0;
+        endPos = ubrk_next(boundary);
+        if (endPos == UBRK_DONE)
+            endPos = 0;
+        ubrk_close(boundary);
+    }
+
+    *start = startPos;
+    *end = endPos;
+}
+
+int KWQFindNextSentenceFromIndex(const QChar *chars, int len, int position, bool forward)
+{
+    int pos = 0;
+    
+    const char *localeName = [[NSString localizedNameOfStringEncoding:NSASCIIStringEncoding] UTF8String];
+    UErrorCode status = U_ZERO_ERROR;
+    UBreakIterator *boundary = ubrk_open(UBRK_SENTENCE, localeName, const_cast<unichar *>(reinterpret_cast<const unichar *>(chars)) + position, len, &status);
+    if ( boundary && U_SUCCESS(status) ) {
+        int firstpos = ubrk_first(boundary);
+        if (forward) {
+            pos = ubrk_next(boundary);
+            if (pos == firstpos)
+                pos = ubrk_next(boundary);
+        } else {
+            pos = ubrk_previous(boundary);
+            if (pos == firstpos)
+                pos = ubrk_previous(boundary);
+        }
+        ubrk_close(boundary);
+    }
+
+    if (pos == UBRK_DONE)
+        pos = 0;
+        
+    return pos;
+}
index df78c7f4984b55b5b366e0bf5d5f0355f214b5d0..1062118100806f6ee4663db500ce84f23f84f7d7 100644 (file)
@@ -1391,7 +1391,7 @@ static HTMLFormElementImpl *formElementFromDOMElement(DOMElement *element)
     if (!_part || !_part->xmlDocImpl()) return nil;
     RenderCanvas* root = static_cast<khtml::RenderCanvas *>(_part->xmlDocImpl()->renderer());
     if (!root) return nil;
-    return _part->xmlDocImpl()->getOrCreateAccObjectCache()->accObject(root);
+    return _part->xmlDocImpl()->getAccObjectCache()->accObject(root);
 }
 
 - (void)setDrawsBackground:(BOOL)drawsBackground