~oif-team/ubuntu/natty/qt4-x11/xi2.1

« back to all changes in this revision

Viewing changes to src/3rdparty/webkit/WebCore/editing/VisiblePosition.cpp

  • Committer: Bazaar Package Importer
  • Author(s): Alessandro Ghersi
  • Date: 2009-11-02 18:30:08 UTC
  • mfrom: (1.2.2 upstream)
  • mto: (15.2.5 experimental)
  • mto: This revision was merged to the branch mainline in revision 88.
  • Revision ID: james.westby@ubuntu.com-20091102183008-b6a4gcs128mvfb3m
Tags: upstream-4.6.0~beta1
ImportĀ upstreamĀ versionĀ 4.6.0~beta1

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
1
/*
2
 
 * Copyright (C) 2004 Apple Computer, Inc.  All rights reserved.
 
2
 * Copyright (C) 2004, 2005, 2006, 2007, 2008, 2009 Apple Inc. All rights reserved.
3
3
 *
4
4
 * Redistribution and use in source and binary forms, with or without
5
5
 * modification, are permitted provided that the following conditions
28
28
 
29
29
#include "CString.h"
30
30
#include "Document.h"
31
 
#include "Element.h"
32
 
#include "FloatRect.h"
 
31
#include "FloatQuad.h"
 
32
#include "HTMLElement.h"
33
33
#include "HTMLNames.h"
34
34
#include "InlineTextBox.h"
35
35
#include "Logging.h"
81
81
    Position pos = previousVisuallyDistinctCandidate(m_deepPosition);
82
82
    
83
83
    // return null visible position if there is no previous visible position
84
 
    if (pos.atStart())
 
84
    if (pos.atStartOfTree())
85
85
        return VisiblePosition();
86
86
        
87
87
    VisiblePosition prev = VisiblePosition(pos, DOWNSTREAM);
125
125
        if (!box)
126
126
            return primaryDirection == LTR ? previousVisuallyDistinctCandidate(m_deepPosition) : nextVisuallyDistinctCandidate(m_deepPosition);
127
127
 
128
 
        RenderObject* renderer = box->object();
 
128
        RenderObject* renderer = box->renderer();
129
129
 
130
130
        while (true) {
131
131
            if ((renderer->isReplaced() || renderer->isBR()) && offset == box->caretRightmostOffset())
147
147
 
148
148
                // Reposition at the other logical position corresponding to our edge's visual position and go for another round.
149
149
                box = prevBox;
150
 
                renderer = box->object();
 
150
                renderer = box->renderer();
151
151
                offset = prevBox->caretRightmostOffset();
152
152
                continue;
153
153
            }
176
176
                        break;
177
177
                    box = prevBox;
178
178
                }
179
 
                renderer = box->object();
 
179
                renderer = box->renderer();
180
180
                offset = box->caretRightmostOffset();
181
181
                if (box->direction() == primaryDirection)
182
182
                    break;
185
185
 
186
186
            if (prevBox) {
187
187
                box = prevBox;
188
 
                renderer = box->object();
 
188
                renderer = box->renderer();
189
189
                offset = box->caretRightmostOffset();
190
190
                if (box->bidiLevel() > level) {
191
191
                    do {
215
215
                        break;
216
216
                    level = box->bidiLevel();
217
217
                }
218
 
                renderer = box->object();
 
218
                renderer = box->renderer();
219
219
                offset = primaryDirection == LTR ? box->caretMinOffset() : box->caretMaxOffset();
220
220
            }
221
221
            break;
222
222
        }
223
223
 
224
 
        p = Position(renderer->element(), offset);
 
224
        p = Position(renderer->node(), offset);
225
225
 
226
 
        if (p.isCandidate() && p.downstream() != downstreamStart || p.atStart() || p.atEnd())
 
226
        if ((p.isCandidate() && p.downstream() != downstreamStart) || p.atStartOfTree() || p.atEndOfTree())
227
227
            return p;
228
228
    }
229
229
}
231
231
VisiblePosition VisiblePosition::left(bool stayInEditableContent) const
232
232
{
233
233
    Position pos = leftVisuallyDistinctCandidate();
234
 
    if (pos.atStart() || pos.atEnd())
 
234
    // FIXME: Why can't we move left from the last position in a tree?
 
235
    if (pos.atStartOfTree() || pos.atEndOfTree())
235
236
        return VisiblePosition();
236
237
 
237
238
    VisiblePosition left = VisiblePosition(pos, DOWNSTREAM);
266
267
        if (!box)
267
268
            return primaryDirection == LTR ? nextVisuallyDistinctCandidate(m_deepPosition) : previousVisuallyDistinctCandidate(m_deepPosition);
268
269
 
269
 
        RenderObject* renderer = box->object();
 
270
        RenderObject* renderer = box->renderer();
270
271
 
271
272
        while (true) {
272
273
            if ((renderer->isReplaced() || renderer->isBR()) && offset == box->caretLeftmostOffset())
288
289
 
289
290
                // Reposition at the other logical position corresponding to our edge's visual position and go for another round.
290
291
                box = nextBox;
291
 
                renderer = box->object();
 
292
                renderer = box->renderer();
292
293
                offset = nextBox->caretLeftmostOffset();
293
294
                continue;
294
295
            }
318
319
                        break;
319
320
                    box = nextBox;
320
321
                }
321
 
                renderer = box->object();
 
322
                renderer = box->renderer();
322
323
                offset = box->caretLeftmostOffset();
323
324
                if (box->direction() == primaryDirection)
324
325
                    break;
327
328
 
328
329
            if (nextBox) {
329
330
                box = nextBox;
330
 
                renderer = box->object();
 
331
                renderer = box->renderer();
331
332
                offset = box->caretLeftmostOffset();
332
333
                if (box->bidiLevel() > level) {
333
334
                    do {
357
358
                        break;
358
359
                    level = box->bidiLevel();
359
360
                }
360
 
                renderer = box->object();
 
361
                renderer = box->renderer();
361
362
                offset = primaryDirection == LTR ? box->caretMaxOffset() : box->caretMinOffset();
362
363
            }
363
364
            break;
364
365
        }
365
366
 
366
 
        p = Position(renderer->element(), offset);
 
367
        p = Position(renderer->node(), offset);
367
368
 
368
 
        if (p.isCandidate() && p.downstream() != downstreamStart || p.atStart() || p.atEnd())
 
369
        if ((p.isCandidate() && p.downstream() != downstreamStart) || p.atStartOfTree() || p.atEndOfTree())
369
370
            return p;
370
371
    }
371
372
}
373
374
VisiblePosition VisiblePosition::right(bool stayInEditableContent) const
374
375
{
375
376
    Position pos = rightVisuallyDistinctCandidate();
376
 
    if (pos.atStart() || pos.atEnd())
 
377
    // FIXME: Why can't we move left from the last position in a tree?
 
378
    if (pos.atStartOfTree() || pos.atEndOfTree())
377
379
        return VisiblePosition();
378
380
 
379
381
    VisiblePosition right = VisiblePosition(pos, DOWNSTREAM);
399
401
        
400
402
    // Return pos itself if the two are from the very same editable region, or both are non-editable
401
403
    // FIXME: In the non-editable case, just because the new position is non-editable doesn't mean movement
402
 
    // to it is allowed.  Selection::adjustForEditableContent has this problem too.
 
404
    // to it is allowed.  VisibleSelection::adjustForEditableContent has this problem too.
403
405
    if (highestEditableRoot(pos.deepEquivalent()) == highestRoot)
404
406
        return pos;
405
407
  
425
427
    
426
428
    // Return pos itself if the two are from the very same editable region, or both are non-editable
427
429
    // FIXME: In the non-editable case, just because the new position is non-editable doesn't mean movement
428
 
    // to it is allowed.  Selection::adjustForEditableContent has this problem too.
 
430
    // to it is allowed.  VisibleSelection::adjustForEditableContent has this problem too.
429
431
    if (highestEditableRoot(pos.deepEquivalent()) == highestRoot)
430
432
        return pos;
431
433
 
438
440
    return firstEditablePositionAfterPositionInRoot(pos.deepEquivalent(), highestRoot);
439
441
}
440
442
 
441
 
Position canonicalizeCandidate(const Position& candidate)
 
443
static Position canonicalizeCandidate(const Position& candidate)
442
444
{
443
445
    if (candidate.isNull())
444
446
        return Position();
478
480
 
479
481
    // The new position must be in the same editable element. Enforce that first.
480
482
    // Unless the descent is from a non-editable html element to an editable body.
481
 
    if (node->hasTagName(htmlTag) && !node->isContentEditable())
 
483
    if (node->hasTagName(htmlTag) && !node->isContentEditable() && node->document()->body() && node->document()->body()->isContentEditable())
482
484
        return next.isNotNull() ? next : prev;
483
485
 
484
486
    Node* editingRoot = editableRootForPosition(position);
485
487
        
486
488
    // If the html element is editable, descending into its body will look like a descent 
487
489
    // from non-editable to editable content since rootEditableElement() always stops at the body.
488
 
    if (editingRoot && editingRoot->hasTagName(htmlTag) || position.node()->isDocumentNode())
 
490
    if ((editingRoot && editingRoot->hasTagName(htmlTag)) || position.node()->isDocumentNode())
489
491
        return next.isNotNull() ? next : prev;
490
492
        
491
493
    bool prevIsInSameEditableElement = prevNode && editableRootForPosition(prev) == editingRoot;
492
494
    bool nextIsInSameEditableElement = nextNode && editableRootForPosition(next) == editingRoot;
493
495
    if (prevIsInSameEditableElement && !nextIsInSameEditableElement)
494
496
        return prev;
495
 
        
 
497
 
496
498
    if (nextIsInSameEditableElement && !prevIsInSameEditableElement)
497
499
        return next;
498
 
        
 
500
 
499
501
    if (!nextIsInSameEditableElement && !prevIsInSameEditableElement)
500
502
        return Position();
501
503
 
509
511
    return next;
510
512
}
511
513
 
512
 
UChar VisiblePosition::characterAfter() const
 
514
UChar32 VisiblePosition::characterAfter() const
513
515
{
514
516
    // We canonicalize to the first of two equivalent candidates, but the second of the two candidates
515
517
    // is the one that will be inside the text node containing the character after this visible position.
518
520
    if (!node || !node->isTextNode())
519
521
        return 0;
520
522
    Text* textNode = static_cast<Text*>(pos.node());
521
 
    int offset = pos.offset();
522
 
    if ((unsigned)offset >= textNode->length())
 
523
    unsigned offset = pos.deprecatedEditingOffset();
 
524
    unsigned length = textNode->length();
 
525
    if (offset >= length)
523
526
        return 0;
524
 
    return textNode->data()[offset];
 
527
 
 
528
    UChar32 ch;
 
529
    const UChar* characters = textNode->data().characters();
 
530
    U16_NEXT(characters, offset, length, ch);
 
531
    return ch;
525
532
}
526
533
 
527
534
IntRect VisiblePosition::localCaretRect(RenderObject*& renderer) const
541
548
    getInlineBoxAndOffset(inlineBox, caretOffset);
542
549
 
543
550
    if (inlineBox)
544
 
        renderer = inlineBox->object();
 
551
        renderer = inlineBox->renderer();
545
552
 
546
553
    return renderer->localCaretRect(inlineBox, caretOffset);
547
554
}
574
581
    if (isNull())
575
582
        fprintf(stderr, "Position [%s]: null\n", msg);
576
583
    else
577
 
        fprintf(stderr, "Position [%s]: %s [%p] at %d\n", msg, m_deepPosition.node()->nodeName().utf8().data(), m_deepPosition.node(), m_deepPosition.offset());
 
584
        fprintf(stderr, "Position [%s]: %s [%p] at %d\n", msg, m_deepPosition.node()->nodeName().utf8().data(), m_deepPosition.node(), m_deepPosition.deprecatedEditingOffset());
578
585
}
579
586
 
580
587
#ifndef NDEBUG
593
600
 
594
601
PassRefPtr<Range> makeRange(const VisiblePosition &start, const VisiblePosition &end)
595
602
{
 
603
    if (start.isNull() || end.isNull())
 
604
        return 0;
 
605
    
596
606
    Position s = rangeCompliantEquivalent(start);
597
607
    Position e = rangeCompliantEquivalent(end);
598
 
    return Range::create(s.node()->document(), s.node(), s.offset(), e.node(), e.offset());
 
608
    return Range::create(s.node()->document(), s.node(), s.deprecatedEditingOffset(), e.node(), e.deprecatedEditingOffset());
599
609
}
600
610
 
601
611
VisiblePosition startVisiblePosition(const Range *r, EAffinity affinity)
616
626
        return false;
617
627
    Position p = rangeCompliantEquivalent(visiblePosition);
618
628
    int code = 0;
619
 
    r->setStart(p.node(), p.offset(), code);
 
629
    r->setStart(p.node(), p.deprecatedEditingOffset(), code);
620
630
    return code == 0;
621
631
}
622
632
 
626
636
        return false;
627
637
    Position p = rangeCompliantEquivalent(visiblePosition);
628
638
    int code = 0;
629
 
    r->setEnd(p.node(), p.offset(), code);
 
639
    r->setEnd(p.node(), p.deprecatedEditingOffset(), code);
630
640
    return code == 0;
631
641
}
632
642