Reviewed by Maciej
[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                 // If no first child, or first visible child is a not a block, return; otherwise continue.
444                 if (!currentNode->firstChild())
445                     return Position(currentNode, 0);
446                 for (NodeImpl *child = currentNode->firstChild(); child; child = child->nextSibling()) {
447                     RenderObject *r = child->renderer();
448                     if (r && r->style()->visibility() == VISIBLE) {
449                          if (r->isBlockFlow())
450                             break; // break causes continue code below to run.
451                          else
452                             return Position(child, 0);
453                     }
454                 }
455                 continue;
456             }
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, "renderer:               %p [%p]\n", renderer, renderer ? renderer->inlineBox(offset()) : 0);
693     LOG(Editing, "thisRenderedOffset:         %d\n", thisRenderedOffset);
694     LOG(Editing, "posRenderer:            %p [%p]\n", posRenderer, posRenderer ? posRenderer->inlineBox(offset()) : 0);
695     LOG(Editing, "posRenderedOffset:      %d\n", posRenderedOffset);
696     LOG(Editing, "node min/max:           %d:%d\n", node()->caretMinOffset(), node()->caretMaxRenderedOffset());
697     LOG(Editing, "pos node min/max:       %d:%d\n", pos.node()->caretMinOffset(), pos.node()->caretMaxRenderedOffset());
698     LOG(Editing, "----------------------------------------------------------------------\n");
699
700     InlineBox *b1 = renderer ? renderer->inlineBox(offset()) : 0;
701     InlineBox *b2 = posRenderer ? posRenderer->inlineBox(pos.offset()) : 0;
702
703     if (!b1 || !b2) {
704         return false;
705     }
706
707     if (b1->root() != b2->root()) {
708         return true;
709     }
710
711     if (nextRenderedEditable(node()) == pos.node() && 
712         thisRenderedOffset == (long)node()->caretMaxRenderedOffset() && posRenderedOffset == 0) {
713         return false;
714     }
715     
716     if (previousRenderedEditable(node()) == pos.node() && 
717         thisRenderedOffset == 0 && posRenderedOffset == (long)pos.node()->caretMaxRenderedOffset()) {
718         return false;
719     }
720
721     return true;
722 }
723
724 static inline bool isWS(const QChar &c)
725 {
726     const char nonBreakingSpace = 0xA0;
727     return c.isSpace() && c != nonBreakingSpace;
728 }
729
730 Position Position::leadingWhitespacePosition() const
731 {
732     if (isNull())
733         return Position();
734     
735     if (upstream(StayInBlock).node()->id() == ID_BR)
736         return Position();
737     
738     Position prev = previousCharacterPosition();
739     if (prev != *this && prev.node()->inSameContainingBlockFlowElement(node()) && prev.node()->isTextNode()) {
740         DOMString string = static_cast<TextImpl *>(prev.node())->data();
741         if (isWS(string[prev.offset()]))
742             return prev;
743     }
744
745     return Position();
746 }
747
748 Position Position::trailingWhitespacePosition() const
749 {
750     if (isNull())
751         return Position();
752
753     if (node()->isTextNode()) {
754         TextImpl *textNode = static_cast<TextImpl *>(node());
755         if (offset() < (long)textNode->length()) {
756             DOMString string = static_cast<TextImpl *>(node())->data();
757             if (isWS(string[offset()]))
758                 return *this;
759             return Position();
760         }
761     }
762
763     if (downstream(StayInBlock).node()->id() == ID_BR)
764         return Position();
765
766     Position next = nextCharacterPosition();
767     if (next != *this && next.node()->inSameContainingBlockFlowElement(node()) && next.node()->isTextNode()) {
768         DOMString string = static_cast<TextImpl *>(next.node())->data();
769         if (isWS(string[0]))
770             return next;
771     }
772
773     return Position();
774 }
775
776 void Position::debugPosition(const char *msg) const
777 {
778     if (isNull())
779         fprintf(stderr, "Position [%s]: null\n", msg);
780     else
781         fprintf(stderr, "Position [%s]: %s [%p] at %d\n", msg, getTagName(node()->id()).string().latin1(), node(), offset());
782 }
783
784 #ifndef NDEBUG
785 #define FormatBufferSize 1024
786 void Position::formatForDebugger(char *buffer, unsigned length) const
787 {
788     DOMString result;
789     DOMString s;
790     
791     if (isNull()) {
792         result = "<null>";
793     }
794     else {
795         char s[FormatBufferSize];
796         result += "offset ";
797         result += QString::number(m_offset);
798         result += " of ";
799         m_node->formatForDebugger(s, FormatBufferSize);
800         result += s;
801     }
802           
803     strncpy(buffer, result.string().latin1(), length - 1);
804 }
805 #undef FormatBufferSize
806 #endif
807
808
809 Position startPosition(const Range &r)
810 {
811     return Position(r.startContainer().handle(), r.startOffset());
812 }
813
814 Position endPosition(const Range &r)
815 {
816     return Position(r.endContainer().handle(), r.endOffset());
817 }
818
819 } // namespace DOM