?? selection.cpp
字號:
/*
* Copyright (C) 2004 Apple Computer, Inc. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
* OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include "selection.h"
#include <qevent.h>
#include <qpainter.h>
#include <qrect.h>
#include "dom/dom_node.h"
#include "dom/dom_string.h"
#include "khtml_part.h"
#include "khtmlview.h"
#include "misc/htmltags.h"
#include "rendering/render_object.h"
#include "rendering/render_style.h"
#include "rendering/render_text.h"
#include "visible_position.h"
#include "visible_units.h"
#include "xml/dom_docimpl.h"
#include "xml/dom_elementimpl.h"
#include "xml/dom_nodeimpl.h"
#include "xml/dom_positioniterator.h"
#include "xml/dom_textimpl.h"
#include "xml/dom2_rangeimpl.h"
#if APPLE_CHANGES
#include "KWQAssertions.h"
#else
#define ASSERT(assertion) assert(assertion)
#endif
#define EDIT_DEBUG 0
using DOM::DOMString;
using DOM::ElementImpl;
using DOM::Node;
using DOM::NodeImpl;
using DOM::Position;
using DOM::Range;
using DOM::RangeImpl;
using DOM::StayInBlock;
namespace khtml {
Selection::Selection()
{
init(DOWNSTREAM);
}
Selection::Selection(const Position &pos, EAffinity affinity)
: m_base(pos), m_extent(pos)
{
init(affinity);
validate();
}
Selection::Selection(const Range &r, EAffinity baseAffinity, EAffinity extentAffinity)
: m_base(startPosition(r)), m_extent(endPosition(r))
{
init(baseAffinity);
validate();
}
Selection::Selection(const Position &base, EAffinity baseAffinity, const Position &extent, EAffinity extentAffinity)
: m_base(base), m_extent(extent)
{
init(baseAffinity);
validate();
}
Selection::Selection(const VisiblePosition &visiblePos)
: m_base(visiblePos.position()), m_extent(visiblePos.position())
{
init(visiblePos.affinity());
validate();
}
Selection::Selection(const VisiblePosition &base, const VisiblePosition &extent)
: m_base(base.position()), m_extent(extent.position())
{
init(base.affinity());
validate();
}
Selection::Selection(const Selection &o)
: m_base(o.m_base), m_extent(o.m_extent)
, m_start(o.m_start), m_end(o.m_end)
, m_state(o.m_state), m_affinity(o.m_affinity)
, m_baseIsStart(o.m_baseIsStart)
, m_needsLayout(o.m_needsLayout)
, m_modifyBiasSet(o.m_modifyBiasSet)
{
// Only copy the coordinates over if the other object
// has had a layout, otherwise keep the current
// coordinates. This prevents drawing artifacts from
// remaining when the caret is painted and then moves,
// and the old rectangle needs to be repainted.
if (!m_needsLayout) {
m_caretRect = o.m_caretRect;
m_expectedVisibleRect = o.m_expectedVisibleRect;
}
}
void Selection::init(EAffinity affinity)
{
// FIXME: set extentAffinity
m_state = NONE;
m_baseIsStart = true;
m_affinity = affinity;
m_needsLayout = true;
m_modifyBiasSet = false;
}
Selection &Selection::operator=(const Selection &o)
{
m_base = o.m_base;
m_extent = o.m_extent;
m_start = o.m_start;
m_end = o.m_end;
m_state = o.m_state;
m_affinity = o.m_affinity;
m_baseIsStart = o.m_baseIsStart;
m_needsLayout = o.m_needsLayout;
m_modifyBiasSet = o.m_modifyBiasSet;
// Only copy the coordinates over if the other object
// has had a layout, otherwise keep the current
// coordinates. This prevents drawing artifacts from
// remaining when the caret is painted and then moves,
// and the old rectangle needs to be repainted.
if (!m_needsLayout) {
m_caretRect = o.m_caretRect;
m_expectedVisibleRect = o.m_expectedVisibleRect;
}
return *this;
}
void Selection::moveTo(const VisiblePosition &pos)
{
// FIXME: use extentAffinity
m_affinity = pos.affinity();
m_base = pos.deepEquivalent();
m_extent = pos.deepEquivalent();
validate();
}
void Selection::moveTo(const VisiblePosition &base, const VisiblePosition &extent)
{
// FIXME: use extentAffinity
m_affinity = base.affinity();
m_base = base.deepEquivalent();
m_extent = extent.deepEquivalent();
validate();
}
void Selection::moveTo(const Selection &o)
{
// FIXME: copy extentAffinity
m_affinity = o.m_affinity;
m_base = o.m_start;
m_extent = o.m_end;
validate();
}
void Selection::moveTo(const Position &pos, EAffinity affinity)
{
// FIXME: use extentAffinity
m_affinity = affinity;
m_base = pos;
m_extent = pos;
validate();
}
void Selection::moveTo(const Range &r, EAffinity baseAffinity, EAffinity extentAffinity)
{
// FIXME: use extentAffinity
m_affinity = baseAffinity;
m_base = startPosition(r);
m_extent = endPosition(r);
validate();
}
void Selection::moveTo(const Position &base, EAffinity baseAffinity, const Position &extent, EAffinity extentAffinity)
{
// FIXME: use extentAffinity
m_affinity = baseAffinity;
m_base = base;
m_extent = extent;
validate();
}
void Selection::setModifyBias(EAlter alter, EDirection direction)
{
switch (alter) {
case MOVE:
m_modifyBiasSet = false;
break;
case EXTEND:
if (!m_modifyBiasSet) {
m_modifyBiasSet = true;
switch (direction) {
// FIXME: right for bidi?
case RIGHT:
case FORWARD:
m_base = m_start;
m_extent = m_end;
break;
case LEFT:
case BACKWARD:
m_base = m_end;
m_extent = m_start;
break;
}
}
break;
}
}
VisiblePosition Selection::modifyExtendingRightForward(ETextGranularity granularity)
{
VisiblePosition pos(m_extent, m_affinity);
switch (granularity) {
case CHARACTER:
pos = pos.next();
break;
case WORD:
pos = nextWordPosition(pos);
break;
case PARAGRAPH:
pos = nextParagraphPosition(pos, xPosForVerticalArrowNavigation(EXTENT));
break;
case LINE:
pos = nextLinePosition(pos, xPosForVerticalArrowNavigation(EXTENT));
break;
case LINE_BOUNDARY:
pos = endOfLine(VisiblePosition(m_end, m_affinity));
break;
case PARAGRAPH_BOUNDARY:
pos = endOfParagraph(VisiblePosition(m_end, m_affinity));
break;
case DOCUMENT_BOUNDARY:
pos = endOfDocument(pos);
break;
}
return pos;
}
VisiblePosition Selection::modifyMovingRightForward(ETextGranularity granularity)
{
VisiblePosition pos;
switch (granularity) {
case CHARACTER:
if (isRange())
pos = VisiblePosition(m_end, m_affinity);
else
pos = VisiblePosition(m_extent, m_affinity).next();
break;
case WORD:
pos = nextWordPosition(VisiblePosition(m_extent, m_affinity));
break;
case PARAGRAPH:
pos = nextParagraphPosition(VisiblePosition(m_end, m_affinity), xPosForVerticalArrowNavigation(END, isRange()));
break;
case LINE: {
// down-arrowing from a range selection that ends at the start of a line needs
// to leave the selection at that line start (no need to call nextLinePosition!)
pos = VisiblePosition(m_end, m_affinity);
if (!isRange() || !isStartOfLine(pos))
pos = nextLinePosition(pos, xPosForVerticalArrowNavigation(END, isRange()));
break;
}
case LINE_BOUNDARY:
pos = endOfLine(VisiblePosition(m_end, m_affinity));
break;
case PARAGRAPH_BOUNDARY:
pos = endOfParagraph(VisiblePosition(m_end, m_affinity));
break;
case DOCUMENT_BOUNDARY:
pos = endOfDocument(VisiblePosition(m_end, m_affinity));
break;
}
return pos;
}
VisiblePosition Selection::modifyExtendingLeftBackward(ETextGranularity granularity)
{
VisiblePosition pos(m_extent, m_affinity);
switch (granularity) {
case CHARACTER:
pos = pos.previous();
break;
case WORD:
pos = previousWordPosition(pos);
break;
case PARAGRAPH:
pos = previousParagraphPosition(pos, xPosForVerticalArrowNavigation(EXTENT));
break;
case LINE:
pos = previousLinePosition(pos, xPosForVerticalArrowNavigation(EXTENT));
break;
case LINE_BOUNDARY:
pos = startOfLine(VisiblePosition(m_start, m_affinity));
break;
case PARAGRAPH_BOUNDARY:
pos = startOfParagraph(VisiblePosition(m_start, m_affinity));
break;
case DOCUMENT_BOUNDARY:
pos = startOfDocument(pos);
break;
}
return pos;
}
VisiblePosition Selection::modifyMovingLeftBackward(ETextGranularity granularity)
{
VisiblePosition pos;
switch (granularity) {
case CHARACTER:
if (isRange())
pos = VisiblePosition(m_start, m_affinity);
else
pos = VisiblePosition(m_extent, m_affinity).previous();
break;
case WORD:
pos = previousWordPosition(VisiblePosition(m_extent, m_affinity));
break;
case PARAGRAPH:
pos = previousParagraphPosition(VisiblePosition(m_start, m_affinity), xPosForVerticalArrowNavigation(START, isRange()));
break;
case LINE:
pos = previousLinePosition(VisiblePosition(m_start, m_affinity), xPosForVerticalArrowNavigation(START, isRange()));
break;
case LINE_BOUNDARY:
pos = startOfLine(VisiblePosition(m_start, m_affinity));
break;
case PARAGRAPH_BOUNDARY:
pos = startOfParagraph(VisiblePosition(m_start, m_affinity));
break;
case DOCUMENT_BOUNDARY:
pos = startOfDocument(VisiblePosition(m_start, m_affinity));
break;
}
return pos;
}
bool Selection::modify(EAlter alter, EDirection dir, ETextGranularity granularity)
{
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -