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