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