Reviewed by John
[WebKit-https.git] / WebCore / khtml / xml / dom_position.cpp
1 /*
2  * Copyright (C) 2004 Apple Computer, 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  * 1. Redistributions of source code must retain the above copyright
8  *    notice, this list of conditions and the following disclaimer.
9  * 2. Redistributions in binary form must reproduce the above copyright
10  *    notice, this list of conditions and the following disclaimer in the
11  *    documentation and/or other materials provided with the distribution.
12  *
13  * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY
14  * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
15  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
16  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE COMPUTER, INC. OR
17  * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
18  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
19  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
20  * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
21  * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
22  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
23  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 
24  */
25
26 #include "dom_position.h"
27
28 #include <qstring.h>
29
30 #include "css_computedstyle.h"
31 #include "css_valueimpl.h"
32 #include "dom_elementimpl.h"
33 #include "dom_nodeimpl.h"
34 #include "dom_positioniterator.h"
35 #include "dom2_range.h"
36 #include "dom2_viewsimpl.h"
37 #include "helper.h"
38 #include "htmltags.h"
39 #include "text_affinity.h"
40 #include "rendering/render_block.h"
41 #include "rendering/render_flow.h"
42 #include "rendering/render_line.h"
43 #include "rendering/render_style.h"
44 #include "rendering/render_text.h"
45
46 #if APPLE_CHANGES
47 #include "KWQAssertions.h"
48 #include "KWQLogging.h"
49 #else
50 #define ASSERT(assertion) assert(assertion)
51 #define LOG(channel, formatAndArgs...) ((void)0)
52 #endif
53
54 using khtml::EAffinity;
55 using khtml::InlineBox;
56 using khtml::InlineTextBox;
57 using khtml::RenderBlock;
58 using khtml::RenderFlow;
59 using khtml::RenderObject;
60 using khtml::RenderText;
61 using khtml::RootInlineBox;
62 using khtml::VISIBLE;
63
64 namespace DOM {
65
66 static bool renderersOnDifferentLine(RenderObject *r1, long o1, RenderObject *r2, long o2)
67 {
68     InlineBox *b1 = r1 ? r1->inlineBox(o1) : 0;
69     InlineBox *b2 = r2 ? r2->inlineBox(o2) : 0;
70     return (b1 && b2 && b1->root() != b2->root());
71 }
72
73 static NodeImpl *nextRenderedEditable(NodeImpl *node)
74 {
75     while (1) {
76         node = node->nextEditable();
77         if (!node)
78             return 0;
79         if (!node->renderer())
80             continue;
81         if (node->renderer()->inlineBox(0))
82             return node;
83     }
84     return 0;
85 }
86
87 static NodeImpl *previousRenderedEditable(NodeImpl *node)
88 {
89     while (1) {
90         node = node->previousEditable();
91         if (!node)
92             return 0;
93         if (!node->renderer())
94             continue;
95         if (node->renderer()->inlineBox(0))
96             return node;
97     }
98     return 0;
99 }
100
101
102 Position::Position(NodeImpl *node, long offset) 
103     : m_node(node), m_offset(offset) 
104
105     if (node) {
106         node->ref();
107     }
108 }
109
110 Position::Position(const Position &o)
111     : m_node(o.m_node), m_offset(o.m_offset) 
112 {
113     if (m_node) {
114         m_node->ref();
115     }
116 }
117
118 Position::~Position()
119 {
120     if (m_node) {
121         m_node->deref();
122     }
123 }
124
125 Position &Position::operator=(const Position &o)
126 {
127     if (m_node) {
128         m_node->deref();
129     }
130     m_node = o.m_node;
131     if (m_node) {
132         m_node->ref();
133     }
134
135     m_offset = o.m_offset;
136     
137     return *this;
138 }
139
140 void Position::clear()
141 {
142     if (m_node) {
143         m_node->deref();
144         m_node = 0;
145     }
146     m_offset = 0;
147 }
148
149 ElementImpl *Position::element() const
150 {
151     NodeImpl *n;
152     for (n = node(); n && !n->isElementNode(); n = n->parentNode())
153         ; // empty loop body
154     return static_cast<ElementImpl *>(n);
155 }
156
157 CSSComputedStyleDeclarationImpl *Position::computedStyle() const
158 {
159     ElementImpl *elem = element();
160     if (!elem)
161         return 0;
162     return new CSSComputedStyleDeclarationImpl(elem);
163 }
164
165 long Position::renderedOffset() const
166 {
167     if (!node()->isTextNode())
168         return offset();
169    
170     if (!node()->renderer())
171         return offset();
172                     
173     long result = 0;
174     RenderText *textRenderer = static_cast<RenderText *>(node()->renderer());
175     for (InlineTextBox *box = textRenderer->firstTextBox(); box; box = box->nextTextBox()) {
176         long start = box->m_start;
177         long end = box->m_start + box->m_len;
178         if (offset() < start)
179             return result;
180         if (offset() <= end) {
181             result += offset() - start;
182             return result;
183         }
184         result += box->m_len;
185     }
186     return result;
187 }
188
189 Position Position::previousCharacterPosition() const
190 {
191     if (isNull())
192         return Position();
193
194     NodeImpl *fromRootEditableElement = node()->rootEditableElement();
195     PositionIterator it(*this);
196
197     bool atStartOfLine = isFirstRenderedPositionOnLine();
198     bool rendered = inRenderedContent();
199     
200     while (!it.atStart()) {
201         Position pos = it.previous();
202
203         if (pos.node()->rootEditableElement() != fromRootEditableElement)
204             return *this;
205
206         if (atStartOfLine || !rendered) {
207             if (pos.inRenderedContent())
208                 return pos;
209         }
210         else if (rendersInDifferentPosition(pos))
211             return pos;
212     }
213     
214     return *this;
215 }
216
217 Position Position::nextCharacterPosition() const
218 {
219     if (isNull())
220         return Position();
221
222     NodeImpl *fromRootEditableElement = node()->rootEditableElement();
223     PositionIterator it(*this);
224
225     bool atEndOfLine = isLastRenderedPositionOnLine();
226     bool rendered = inRenderedContent();
227     
228     while (!it.atEnd()) {
229         Position pos = it.next();
230
231         if (pos.node()->rootEditableElement() != fromRootEditableElement)
232             return *this;
233
234         if (atEndOfLine || !rendered) {
235             if (pos.inRenderedContent())
236                 return pos;
237         }
238         else if (rendersInDifferentPosition(pos))
239             return pos;
240     }
241     
242     return *this;
243 }
244
245 Position Position::previousLinePosition(int x, EAffinity affinity) const
246 {
247     if (!node())
248         return Position();
249
250     if (!node()->renderer())
251         return *this;
252
253     RenderBlock *containingBlock = 0;
254     RootInlineBox *root = 0;
255     InlineBox *box = node()->renderer()->inlineBox(offset(), affinity);
256     if (box) {
257         root = box->root()->prevRootBox();
258         if (root)
259             containingBlock = node()->renderer()->containingBlock();
260     }
261
262     if (!root) {
263         // This containing editable block does not have a previous line.
264         // Need to move back to previous containing editable block in this root editable
265         // block and find the last root line box in that block.
266         NodeImpl *startBlock = node()->enclosingBlockFlowElement();
267         NodeImpl *n = node()->previousEditable();
268         while (n && startBlock == n->enclosingBlockFlowElement())
269             n = n->previousEditable();
270         while (n) {
271             if (!n->inSameRootEditableElement(node()))
272                 break;
273             Position pos(n, n->caretMinOffset());
274             if (pos.inRenderedContent()) {
275                 ASSERT(n->renderer());
276                 box = n->renderer()->inlineBox(n->caretMaxOffset());
277                 if (box) {
278                     // previous root line box found
279                     root = box->root();
280                     containingBlock = n->renderer()->containingBlock();
281                     break;
282                 }
283                 else {
284                     return pos;
285                 }
286             }
287             n = n->previousEditable();
288         }
289     }
290     
291     if (root) {
292         int absx, absy;
293         containingBlock->absolutePosition(absx, absy);
294         RenderObject *renderer = root->closestLeafChildForXPos(x, absx)->object();
295         return renderer->positionForCoordinates(x, absy + root->topOverflow());
296     }
297     
298     // Could not find a previous line. This means we must already be on the first line.
299     // Move to the start of the content in this block, which effectively moves us
300     // to the start of the line we're on.
301     return Position(node()->rootEditableElement(), 0);
302 }
303
304 Position Position::nextLinePosition(int x, EAffinity affinity) const
305 {
306     if (!node())
307         return Position();
308
309     if (!node()->renderer())
310         return *this;
311
312     RenderBlock *containingBlock = 0;
313     RootInlineBox *root = 0;
314     InlineBox *box = node()->renderer()->inlineBox(offset(), affinity);
315     if (box) {
316         root = box->root()->nextRootBox();
317         if (root)
318             containingBlock = node()->renderer()->containingBlock();
319     }
320
321     if (!root) {
322         // This containing editable block does not have a next line.
323         // Need to move forward to next containing editable block in this root editable
324         // block and find the first root line box in that block.
325         NodeImpl *startBlock = node()->enclosingBlockFlowElement();
326         NodeImpl *n = node()->nextEditable();
327         while (n && startBlock == n->enclosingBlockFlowElement())
328             n = n->nextEditable();
329         while (n) {
330             if (!n->inSameRootEditableElement(node()))
331                 break;
332             Position pos(n, n->caretMinOffset());
333             if (pos.inRenderedContent()) {
334                 ASSERT(n->renderer());
335                 box = n->renderer()->inlineBox(n->caretMinOffset());
336                 if (box) {
337                     // next root line box found
338                     root = box->root();
339                     containingBlock = n->renderer()->containingBlock();
340                     break;
341                 }
342                 else {
343                     return pos;
344                 }
345             }
346             n = n->nextEditable();
347         }
348     }
349     
350     if (root) {
351         int absx, absy;
352         containingBlock->absolutePosition(absx, absy);
353         RenderObject *renderer = root->closestLeafChildForXPos(x, absx)->object();
354         return renderer->positionForCoordinates(x, absy + root->topOverflow());
355     }    
356
357     // Could not find a next line. This means we must already be on the last line.
358     // Move to the end of the content in this block, which effectively moves us
359     // to the end of the line we're on.
360     ElementImpl *rootElement = node()->rootEditableElement();
361     return Position(rootElement, rootElement ? rootElement->childNodeCount() : 0);
362 }
363
364 Position Position::upstream(EStayInBlock stayInBlock) const
365 {
366     Position start = equivalentDeepPosition();
367     NodeImpl *startNode = start.node();
368     if (!startNode)
369         return Position();
370
371     NodeImpl *block = startNode->enclosingBlockFlowElement();
372     
373     PositionIterator it(start);
374     for (; !it.atStart(); it.previous()) {
375         NodeImpl *currentNode = it.current().node();
376
377         if (stayInBlock) {
378             NodeImpl *currentBlock = currentNode->enclosingBlockFlowElement();
379             if (block != currentBlock)
380                 return it.next();
381         }
382
383         RenderObject *renderer = currentNode->renderer();
384         if (!renderer)
385             continue;
386
387         if (renderer->style()->visibility() != VISIBLE)
388             continue;
389
390         if (renderer->isReplaced() || renderer->isBR()) {
391             if (it.current().offset() >= renderer->caretMaxOffset())
392                 return Position(currentNode, renderer->caretMaxOffset());
393             else
394                 continue;
395         }
396
397         if (renderer->isText() && static_cast<RenderText *>(renderer)->firstTextBox()) {
398             if (currentNode != startNode)
399                 return Position(currentNode, renderer->caretMaxOffset());
400
401             if (it.current().offset() < 0)
402                 continue;
403             uint textOffset = it.current().offset();
404
405             RenderText *textRenderer = static_cast<RenderText *>(renderer);
406             for (InlineTextBox *box = textRenderer->firstTextBox(); box; box = box->nextTextBox()) {
407                 if (textOffset > box->start() && textOffset <= box->start() + box->len())
408                     return it.current();
409                 else if (box != textRenderer->lastTextBox() && 
410                          !box->nextOnLine() && 
411                          textOffset == box->start() + box->len() + 1)
412                     return it.current();
413             }
414         }
415     }
416     
417     return it.current();
418 }
419
420 Position Position::downstream(EStayInBlock stayInBlock) const
421 {
422     Position start = equivalentDeepPosition();
423     NodeImpl *startNode = start.node();
424     if (!startNode)
425         return Position();
426
427     NodeImpl *block = startNode->enclosingBlockFlowElement();
428     
429     PositionIterator it(start);            
430     for (; !it.atEnd(); it.next()) {   
431         NodeImpl *currentNode = it.current().node();
432
433         if (stayInBlock) {
434             NodeImpl *currentBlock = currentNode->enclosingBlockFlowElement();
435             if (block != currentBlock)
436                 return it.previous();
437         }
438
439         RenderObject *renderer = currentNode->renderer();
440         if (!renderer)
441             continue;
442
443         if (renderer->style()->visibility() != VISIBLE)
444             continue;
445
446         if (currentNode != startNode && renderer->isBlockFlow()) {
447             if (it.current().offset() == 0) {
448                 NodeImpl *node = currentNode;
449                 while (NodeImpl *firstChild = node->firstChild()) {
450                     if (node->renderer()->style()->visibility() == VISIBLE && node->renderer()->isBlockFlow())
451                         node = firstChild;
452                 }
453                 return Position(node, 0);
454             }
455             else
456                 continue;
457         }
458
459         if (renderer->isReplaced() || renderer->isBR()) {
460             if (it.current().offset() <= renderer->caretMinOffset())
461                 return Position(currentNode, renderer->caretMinOffset());
462             else
463                 continue;
464         }
465
466         if (renderer->isText() && static_cast<RenderText *>(renderer)->firstTextBox()) {
467             if (currentNode != node())
468                 return Position(currentNode, renderer->caretMinOffset());
469
470             if (it.current().offset() < 0)
471                 continue;
472             uint textOffset = it.current().offset();
473
474             RenderText *textRenderer = static_cast<RenderText *>(renderer);
475             for (InlineTextBox *box = textRenderer->firstTextBox(); box; box = box->nextTextBox()) {
476                 if (textOffset >= box->start() && textOffset <= box->end())
477                     return it.current();
478                 else if (box != textRenderer->lastTextBox() && 
479                          !box->nextOnLine() && 
480                          textOffset == box->start() + box->len())
481                     return it.current();
482             }
483         }
484     }
485     
486     return it.current();
487 }
488
489 Position Position::equivalentRangeCompliantPosition() const
490 {
491     if (isNull())
492         return Position();
493
494     // Make sure that 0 <= constrainedOffset <= num kids, otherwise using this Position
495     // in DOM calls can result in exceptions.
496     long maxOffset = node()->isTextNode() ? static_cast<TextImpl *>(node())->length(): node()->childNodeCount();
497     long constrainedOffset = offset() <= 0 ? 0 : kMin(maxOffset, offset());
498
499     if (!node()->parentNode())
500         return Position(node(), constrainedOffset);
501
502     RenderObject *renderer = node()->renderer();
503     if (!renderer)
504         return Position(node(), constrainedOffset);
505         
506     if (!renderer->isReplaced() && !renderer->isBR())
507         return Position(node(), constrainedOffset);
508     
509     long o = offset();
510     const NodeImpl *n = node();
511     while ((n = n->previousSibling()))
512         o++;
513     
514     // Make sure that 0 <= constrainedOffset <= num kids, as above.
515     NodeImpl *parent = node()->parentNode();
516     maxOffset = parent->isTextNode() ? static_cast<TextImpl *>(parent)->length(): parent->childNodeCount();
517     constrainedOffset = o <= 0 ? 0 : kMin(maxOffset, o);
518     return Position(parent, constrainedOffset);
519 }
520
521 Position Position::equivalentDeepPosition() const
522 {
523     if (isNull() || node()->isAtomicNode())
524         return *this;
525
526     NodeImpl *child = 0;
527     Position pos(*this);
528     if (offset() >= (int)node()->childNodeCount()) {
529         child = node()->lastChild();
530         pos = Position(child, child->caretMaxOffset());
531         ASSERT(child);
532         while (!child->isAtomicNode() && pos.node()->hasChildNodes()) {
533             child = pos.node()->lastChild();
534             ASSERT(child);
535             pos = Position(child, child->caretMaxOffset());
536         }
537     }
538     else {
539         child = node()->childNode(offset());
540         ASSERT(child);
541         pos = Position(child, 0);
542         while (!child->isAtomicNode() && pos.node()->hasChildNodes()) {
543             child = pos.node()->firstChild();
544             ASSERT(child);
545             pos = Position(child, 0);
546         }
547     }
548     return pos;
549 }
550
551 bool Position::inRenderedContent() const
552 {
553     if (isNull())
554         return false;
555         
556     RenderObject *renderer = node()->renderer();
557     if (!renderer)
558         return false;
559     
560     if (renderer->style()->visibility() != VISIBLE)
561         return false;
562
563     // FIXME: This check returns false for a <br> at the end of a line!
564     if (renderer->isBR() && static_cast<RenderText *>(renderer)->firstTextBox()) {
565         return offset() == 0;
566     }
567     else if (renderer->isText()) {
568         RenderText *textRenderer = static_cast<RenderText *>(renderer);
569         for (InlineTextBox *box = textRenderer->firstTextBox(); box; box = box->nextTextBox()) {
570             if (offset() >= box->m_start && offset() <= box->m_start + box->m_len) {
571                 return true;
572             }
573             else if (offset() < box->m_start) {
574                 // The offset we're looking for is before this node
575                 // this means the offset must be in content that is
576                 // not rendered. Return false.
577                 return false;
578             }
579         }
580     }
581     else if (offset() >= renderer->caretMinOffset() && offset() <= renderer->caretMaxOffset()) {
582         // return true for replaced elements, for inline flows if they have a line box
583         // and for blocks if they are empty
584         if (renderer->isReplaced() ||
585             (renderer->isInlineFlow() && static_cast<RenderFlow *>(renderer)->firstLineBox()) ||
586             (renderer->isBlockFlow() && !renderer->firstChild() && renderer->height()))
587             return true;
588     }
589     
590     return false;
591 }
592
593 bool Position::inRenderedText() const
594 {
595     if (isNull() || !node()->isTextNode())
596         return false;
597         
598     RenderObject *renderer = node()->renderer();
599     if (!renderer)
600         return false;
601     
602     RenderText *textRenderer = static_cast<RenderText *>(renderer);
603     for (InlineTextBox *box = textRenderer->firstTextBox(); box; box = box->nextTextBox()) {
604         if (offset() < box->m_start) {
605             // The offset we're looking for is before this node
606             // this means the offset must be in content that is
607             // not rendered. Return false.
608             return false;
609         }
610         if (offset() >= box->m_start && offset() <= box->m_start + box->m_len)
611             return true;
612     }
613     
614     return false;
615 }
616
617 bool Position::isRenderedCharacter() const
618 {
619     if (isNull() || !node()->isTextNode())
620         return false;
621         
622     RenderObject *renderer = node()->renderer();
623     if (!renderer)
624         return false;
625     
626     RenderText *textRenderer = static_cast<RenderText *>(renderer);
627     for (InlineTextBox *box = textRenderer->firstTextBox(); box; box = box->nextTextBox()) {
628         if (offset() < box->m_start) {
629             // The offset we're looking for is before this node
630             // this means the offset must be in content that is
631             // not rendered. Return false.
632             return false;
633         }
634         if (offset() >= box->m_start && offset() < box->m_start + box->m_len)
635             return true;
636     }
637     
638     return false;
639 }
640
641 bool Position::rendersInDifferentPosition(const Position &pos) const
642 {
643     if (isNull() || pos.isNull())
644         return false;
645
646     RenderObject *renderer = node()->renderer();
647     if (!renderer)
648         return false;
649     
650     RenderObject *posRenderer = pos.node()->renderer();
651     if (!posRenderer)
652         return false;
653
654     if (renderer->style()->visibility() != VISIBLE ||
655         posRenderer->style()->visibility() != VISIBLE)
656         return false;
657     
658     if (node() == pos.node()) {
659         if (node()->id() == ID_BR)
660             return false;
661
662         if (offset() == pos.offset())
663             return false;
664             
665         if (!node()->isTextNode() && !pos.node()->isTextNode()) {
666             if (offset() != pos.offset())
667                 return true;
668         }
669     }
670     
671     if (node()->id() == ID_BR && pos.inRenderedContent())
672         return true;
673                 
674     if (pos.node()->id() == ID_BR && inRenderedContent())
675         return true;
676                 
677     if (node()->enclosingBlockFlowElement() != pos.node()->enclosingBlockFlowElement())
678         return true;
679
680     if (node()->isTextNode() && !inRenderedText())
681         return false;
682
683     if (pos.node()->isTextNode() && !pos.inRenderedText())
684         return false;
685
686     long thisRenderedOffset = renderedOffset();
687     long posRenderedOffset = pos.renderedOffset();
688
689     if (renderer == posRenderer && thisRenderedOffset == posRenderedOffset)
690         return false;
691
692     LOG(Editing, "onDifferentLine:        %s\n", renderersOnDifferentLine(renderer, offset(), posRenderer, pos.offset()) ? "YES" : "NO");
693     LOG(Editing, "renderer:               %p [%p]\n", renderer, renderer ? renderer->inlineBox(offset()) : 0);
694     LOG(Editing, "thisRenderedOffset:         %d\n", thisRenderedOffset);
695     LOG(Editing, "posRenderer:            %p [%p]\n", posRenderer, posRenderer ? posRenderer->inlineBox(offset()) : 0);
696     LOG(Editing, "posRenderedOffset:      %d\n", posRenderedOffset);
697     LOG(Editing, "node min/max:           %d:%d\n", node()->caretMinOffset(), node()->caretMaxRenderedOffset());
698     LOG(Editing, "pos node min/max:       %d:%d\n", pos.node()->caretMinOffset(), pos.node()->caretMaxRenderedOffset());
699     LOG(Editing, "----------------------------------------------------------------------\n");
700
701     InlineBox *b1 = renderer ? renderer->inlineBox(offset()) : 0;
702     InlineBox *b2 = posRenderer ? posRenderer->inlineBox(pos.offset()) : 0;
703
704     if (!b1 || !b2) {
705         return false;
706     }
707
708     if (b1->root() != b2->root()) {
709         return true;
710     }
711
712     if (nextRenderedEditable(node()) == pos.node() && 
713         thisRenderedOffset == (long)node()->caretMaxRenderedOffset() && posRenderedOffset == 0) {
714         return false;
715     }
716     
717     if (previousRenderedEditable(node()) == pos.node() && 
718         thisRenderedOffset == 0 && posRenderedOffset == (long)pos.node()->caretMaxRenderedOffset()) {
719         return false;
720     }
721
722     return true;
723 }
724
725 bool Position::isFirstRenderedPositionOnLine() const
726 {
727     if (isNull())
728         return false;
729
730     RenderObject *renderer = node()->renderer();
731     if (!renderer)
732         return false;
733
734     if (renderer->style()->visibility() != VISIBLE)
735         return false;
736     
737     if (!inRenderedContent())
738         return false;
739
740     PositionIterator it(*this);
741     while (!it.atStart()) {
742         it.previous();
743         RenderObject *currentRenderer = it.current().node()->renderer();
744         if (!currentRenderer || currentRenderer->firstChild())
745             // we want a leaf for this check
746             continue;
747         if (it.current().inRenderedContent())
748             return renderersOnDifferentLine(renderer, offset(), currentRenderer, it.current().offset());
749     }
750     
751     return true;
752 }
753
754 bool Position::isLastRenderedPositionOnLine() const
755 {
756     if (isNull())
757         return false;
758
759     RenderObject *renderer = node()->renderer();
760     if (!renderer)
761         return false;
762
763     if (renderer->style()->visibility() != VISIBLE)
764         return false;
765     
766     if (!inRenderedContent())
767         return false;
768     
769     if (node()->id() == ID_BR)
770         return true;
771     
772     PositionIterator it(*this);
773     while (!it.atEnd()) {
774         it.next();
775         RenderObject *currentRenderer = it.current().node()->renderer();
776         if (!currentRenderer || currentRenderer->firstChild())
777             // we want a leaf for this check
778             continue;
779         if (it.current().inRenderedContent())
780             return renderersOnDifferentLine(renderer, offset(), currentRenderer, it.current().offset());
781     }
782     
783     return true;
784 }
785
786 bool Position::inFirstEditableInRootEditableElement() const
787 {
788     if (isNull() || !inRenderedContent())
789         return false;
790
791     PositionIterator it(*this);
792     while (!it.atStart()) {
793         it.previous();
794         RenderObject *currentRenderer = it.current().node()->renderer();
795         if (!currentRenderer || currentRenderer->firstChild())
796             // we want a leaf for this check
797             continue;
798         if (it.current().inRenderedContent())
799             return false;
800     }
801
802     return true;
803 }
804
805 static inline bool isWS(const QChar &c)
806 {
807     const char nonBreakingSpace = 0xA0;
808     return c.isSpace() && c != nonBreakingSpace;
809 }
810
811 Position Position::leadingWhitespacePosition() const
812 {
813     if (isNull())
814         return Position();
815     
816     if (upstream(StayInBlock).node()->id() == ID_BR)
817         return Position();
818     
819     Position prev = previousCharacterPosition();
820     if (prev != *this && prev.node()->inSameContainingBlockFlowElement(node()) && prev.node()->isTextNode()) {
821         DOMString string = static_cast<TextImpl *>(prev.node())->data();
822         if (isWS(string[prev.offset()]))
823             return prev;
824     }
825
826     return Position();
827 }
828
829 Position Position::trailingWhitespacePosition() const
830 {
831     if (isNull())
832         return Position();
833
834     if (node()->isTextNode()) {
835         TextImpl *textNode = static_cast<TextImpl *>(node());
836         if (offset() < (long)textNode->length()) {
837             DOMString string = static_cast<TextImpl *>(node())->data();
838             if (isWS(string[offset()]))
839                 return *this;
840             return Position();
841         }
842     }
843
844     if (downstream(StayInBlock).node()->id() == ID_BR)
845         return Position();
846
847     Position next = nextCharacterPosition();
848     if (next != *this && next.node()->inSameContainingBlockFlowElement(node()) && next.node()->isTextNode()) {
849         DOMString string = static_cast<TextImpl *>(next.node())->data();
850         if (isWS(string[0]))
851             return next;
852     }
853
854     return Position();
855 }
856
857 void Position::debugPosition(const char *msg) const
858 {
859     if (isNull())
860         fprintf(stderr, "Position [%s]: null\n", msg);
861     else
862         fprintf(stderr, "Position [%s]: %s [%p] at %d\n", msg, getTagName(node()->id()).string().latin1(), node(), offset());
863 }
864
865 #ifndef NDEBUG
866 #define FormatBufferSize 1024
867 void Position::formatForDebugger(char *buffer, unsigned length) const
868 {
869     DOMString result;
870     DOMString s;
871     
872     if (isNull()) {
873         result = "<null>";
874     }
875     else {
876         char s[FormatBufferSize];
877         result += "offset ";
878         result += QString::number(m_offset);
879         result += " of ";
880         m_node->formatForDebugger(s, FormatBufferSize);
881         result += s;
882     }
883           
884     strncpy(buffer, result.string().latin1(), length - 1);
885 }
886 #undef FormatBufferSize
887 #endif
888
889
890 Position startPosition(const Range &r)
891 {
892     return Position(r.startContainer().handle(), r.startOffset());
893 }
894
895 Position endPosition(const Range &r)
896 {
897     return Position(r.endContainer().handle(), r.endOffset());
898 }
899
900 } // namespace DOM