| OLD | NEW |
| 1 /* | 1 /* |
| 2 * Copyright (C) 2007, 2009 Apple Inc. All rights reserved. | 2 * Copyright (C) 2007, 2009 Apple Inc. All rights reserved. |
| 3 * Copyright (C) 2012 Google Inc. All rights reserved. | 3 * Copyright (C) 2012 Google Inc. All rights reserved. |
| 4 * | 4 * |
| 5 * Redistribution and use in source and binary forms, with or without | 5 * Redistribution and use in source and binary forms, with or without |
| 6 * modification, are permitted provided that the following conditions | 6 * modification, are permitted provided that the following conditions |
| 7 * are met: | 7 * are met: |
| 8 * | 8 * |
| 9 * 1. Redistributions of source code must retain the above copyright | 9 * 1. Redistributions of source code must retain the above copyright |
| 10 * notice, this list of conditions and the following disclaimer. | 10 * notice, this list of conditions and the following disclaimer. |
| (...skipping 176 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 187 return "Range"; | 187 return "Range"; |
| 188 } | 188 } |
| 189 | 189 |
| 190 int DOMSelection::rangeCount() const | 190 int DOMSelection::rangeCount() const |
| 191 { | 191 { |
| 192 if (!m_frame) | 192 if (!m_frame) |
| 193 return 0; | 193 return 0; |
| 194 return m_frame->selection().isNone() ? 0 : 1; | 194 return m_frame->selection().isNone() ? 0 : 1; |
| 195 } | 195 } |
| 196 | 196 |
| 197 void DOMSelection::collapse(Node* node, int offset, ExceptionState& es) | 197 void DOMSelection::collapse(Node* node, int offset, ExceptionState& exceptionSta
te) |
| 198 { | 198 { |
| 199 if (!m_frame) | 199 if (!m_frame) |
| 200 return; | 200 return; |
| 201 | 201 |
| 202 if (offset < 0) { | 202 if (offset < 0) { |
| 203 es.throwDOMException(IndexSizeError, ExceptionMessages::failedToExecute(
"collapse", "Selection", String::number(offset) + " is not a valid offset.")); | 203 exceptionState.throwDOMException(IndexSizeError, ExceptionMessages::fail
edToExecute("collapse", "Selection", String::number(offset) + " is not a valid o
ffset.")); |
| 204 return; | 204 return; |
| 205 } | 205 } |
| 206 | 206 |
| 207 if (!isValidForPosition(node)) | 207 if (!isValidForPosition(node)) |
| 208 return; | 208 return; |
| 209 | 209 |
| 210 // FIXME: Eliminate legacy editing positions | 210 // FIXME: Eliminate legacy editing positions |
| 211 m_frame->selection().moveTo(VisiblePosition(createLegacyEditingPosition(node
, offset), DOWNSTREAM)); | 211 m_frame->selection().moveTo(VisiblePosition(createLegacyEditingPosition(node
, offset), DOWNSTREAM)); |
| 212 } | 212 } |
| 213 | 213 |
| 214 void DOMSelection::collapseToEnd(ExceptionState& es) | 214 void DOMSelection::collapseToEnd(ExceptionState& exceptionState) |
| 215 { | 215 { |
| 216 if (!m_frame) | 216 if (!m_frame) |
| 217 return; | 217 return; |
| 218 | 218 |
| 219 const VisibleSelection& selection = m_frame->selection().selection(); | 219 const VisibleSelection& selection = m_frame->selection().selection(); |
| 220 | 220 |
| 221 if (selection.isNone()) { | 221 if (selection.isNone()) { |
| 222 es.throwDOMException(InvalidStateError, ExceptionMessages::failedToExecu
te("collapseToEnd", "Selection", "there is no selection.")); | 222 exceptionState.throwDOMException(InvalidStateError, ExceptionMessages::f
ailedToExecute("collapseToEnd", "Selection", "there is no selection.")); |
| 223 return; | 223 return; |
| 224 } | 224 } |
| 225 | 225 |
| 226 m_frame->selection().moveTo(VisiblePosition(selection.end(), DOWNSTREAM)); | 226 m_frame->selection().moveTo(VisiblePosition(selection.end(), DOWNSTREAM)); |
| 227 } | 227 } |
| 228 | 228 |
| 229 void DOMSelection::collapseToStart(ExceptionState& es) | 229 void DOMSelection::collapseToStart(ExceptionState& exceptionState) |
| 230 { | 230 { |
| 231 if (!m_frame) | 231 if (!m_frame) |
| 232 return; | 232 return; |
| 233 | 233 |
| 234 const VisibleSelection& selection = m_frame->selection().selection(); | 234 const VisibleSelection& selection = m_frame->selection().selection(); |
| 235 | 235 |
| 236 if (selection.isNone()) { | 236 if (selection.isNone()) { |
| 237 es.throwDOMException(InvalidStateError, ExceptionMessages::failedToExecu
te("collapseToStart", "Selection", "there is no selection.")); | 237 exceptionState.throwDOMException(InvalidStateError, ExceptionMessages::f
ailedToExecute("collapseToStart", "Selection", "there is no selection.")); |
| 238 return; | 238 return; |
| 239 } | 239 } |
| 240 | 240 |
| 241 m_frame->selection().moveTo(VisiblePosition(selection.start(), DOWNSTREAM)); | 241 m_frame->selection().moveTo(VisiblePosition(selection.start(), DOWNSTREAM)); |
| 242 } | 242 } |
| 243 | 243 |
| 244 void DOMSelection::empty() | 244 void DOMSelection::empty() |
| 245 { | 245 { |
| 246 if (!m_frame) | 246 if (!m_frame) |
| 247 return; | 247 return; |
| 248 m_frame->selection().clear(); | 248 m_frame->selection().clear(); |
| 249 } | 249 } |
| 250 | 250 |
| 251 void DOMSelection::setBaseAndExtent(Node* baseNode, int baseOffset, Node* extent
Node, int extentOffset, ExceptionState& es) | 251 void DOMSelection::setBaseAndExtent(Node* baseNode, int baseOffset, Node* extent
Node, int extentOffset, ExceptionState& exceptionState) |
| 252 { | 252 { |
| 253 if (!m_frame) | 253 if (!m_frame) |
| 254 return; | 254 return; |
| 255 | 255 |
| 256 if (baseOffset < 0) { | 256 if (baseOffset < 0) { |
| 257 es.throwDOMException(IndexSizeError, ExceptionMessages::failedToExecute(
"setBaseAndExtent", "Selection", String::number(baseOffset) + " is not a valid b
ase offset.")); | 257 exceptionState.throwDOMException(IndexSizeError, ExceptionMessages::fail
edToExecute("setBaseAndExtent", "Selection", String::number(baseOffset) + " is n
ot a valid base offset.")); |
| 258 return; | 258 return; |
| 259 } | 259 } |
| 260 | 260 |
| 261 if (extentOffset < 0) { | 261 if (extentOffset < 0) { |
| 262 es.throwDOMException(IndexSizeError, ExceptionMessages::failedToExecute(
"setBaseAndExtent", "Selection", String::number(extentOffset) + " is not a valid
extent offset.")); | 262 exceptionState.throwDOMException(IndexSizeError, ExceptionMessages::fail
edToExecute("setBaseAndExtent", "Selection", String::number(extentOffset) + " is
not a valid extent offset.")); |
| 263 return; | 263 return; |
| 264 } | 264 } |
| 265 | 265 |
| 266 if (!isValidForPosition(baseNode) || !isValidForPosition(extentNode)) | 266 if (!isValidForPosition(baseNode) || !isValidForPosition(extentNode)) |
| 267 return; | 267 return; |
| 268 | 268 |
| 269 // FIXME: Eliminate legacy editing positions | 269 // FIXME: Eliminate legacy editing positions |
| 270 VisiblePosition visibleBase = VisiblePosition(createLegacyEditingPosition(ba
seNode, baseOffset), DOWNSTREAM); | 270 VisiblePosition visibleBase = VisiblePosition(createLegacyEditingPosition(ba
seNode, baseOffset), DOWNSTREAM); |
| 271 VisiblePosition visibleExtent = VisiblePosition(createLegacyEditingPosition(
extentNode, extentOffset), DOWNSTREAM); | 271 VisiblePosition visibleExtent = VisiblePosition(createLegacyEditingPosition(
extentNode, extentOffset), DOWNSTREAM); |
| 272 | 272 |
| 273 m_frame->selection().moveTo(visibleBase, visibleExtent); | 273 m_frame->selection().moveTo(visibleBase, visibleExtent); |
| 274 } | 274 } |
| 275 | 275 |
| 276 void DOMSelection::setPosition(Node* node, int offset, ExceptionState& es) | 276 void DOMSelection::setPosition(Node* node, int offset, ExceptionState& exception
State) |
| 277 { | 277 { |
| 278 if (!m_frame) | 278 if (!m_frame) |
| 279 return; | 279 return; |
| 280 if (offset < 0) { | 280 if (offset < 0) { |
| 281 es.throwDOMException(IndexSizeError, ExceptionMessages::failedToExecute(
"setPosition", "Selection", String::number(offset) + " is not a valid offset."))
; | 281 exceptionState.throwDOMException(IndexSizeError, ExceptionMessages::fail
edToExecute("setPosition", "Selection", String::number(offset) + " is not a vali
d offset.")); |
| 282 return; | 282 return; |
| 283 } | 283 } |
| 284 | 284 |
| 285 if (!isValidForPosition(node)) | 285 if (!isValidForPosition(node)) |
| 286 return; | 286 return; |
| 287 | 287 |
| 288 // FIXME: Eliminate legacy editing positions | 288 // FIXME: Eliminate legacy editing positions |
| 289 m_frame->selection().moveTo(VisiblePosition(createLegacyEditingPosition(node
, offset), DOWNSTREAM)); | 289 m_frame->selection().moveTo(VisiblePosition(createLegacyEditingPosition(node
, offset), DOWNSTREAM)); |
| 290 } | 290 } |
| 291 | 291 |
| (...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 332 else if (equalIgnoringCase(granularityString, "paragraphboundary")) | 332 else if (equalIgnoringCase(granularityString, "paragraphboundary")) |
| 333 granularity = ParagraphBoundary; | 333 granularity = ParagraphBoundary; |
| 334 else if (equalIgnoringCase(granularityString, "documentboundary")) | 334 else if (equalIgnoringCase(granularityString, "documentboundary")) |
| 335 granularity = DocumentBoundary; | 335 granularity = DocumentBoundary; |
| 336 else | 336 else |
| 337 return; | 337 return; |
| 338 | 338 |
| 339 m_frame->selection().modify(alter, direction, granularity); | 339 m_frame->selection().modify(alter, direction, granularity); |
| 340 } | 340 } |
| 341 | 341 |
| 342 void DOMSelection::extend(Node* node, int offset, ExceptionState& es) | 342 void DOMSelection::extend(Node* node, int offset, ExceptionState& exceptionState
) |
| 343 { | 343 { |
| 344 if (!m_frame) | 344 if (!m_frame) |
| 345 return; | 345 return; |
| 346 | 346 |
| 347 if (!node) { | 347 if (!node) { |
| 348 es.throwDOMException(TypeMismatchError, ExceptionMessages::failedToExecu
te("extend", "Selection", "The node provided is invalid.")); | 348 exceptionState.throwDOMException(TypeMismatchError, ExceptionMessages::f
ailedToExecute("extend", "Selection", "The node provided is invalid.")); |
| 349 return; | 349 return; |
| 350 } | 350 } |
| 351 | 351 |
| 352 if (offset < 0) { | 352 if (offset < 0) { |
| 353 es.throwDOMException(IndexSizeError, ExceptionMessages::failedToExecute(
"extend", "Selection", String::number(offset) + " is not a valid offset.")); | 353 exceptionState.throwDOMException(IndexSizeError, ExceptionMessages::fail
edToExecute("extend", "Selection", String::number(offset) + " is not a valid off
set.")); |
| 354 return; | 354 return; |
| 355 } | 355 } |
| 356 if (offset > (node->offsetInCharacters() ? caretMaxOffset(node) : (int)node-
>childNodeCount())) { | 356 if (offset > (node->offsetInCharacters() ? caretMaxOffset(node) : (int)node-
>childNodeCount())) { |
| 357 es.throwDOMException(IndexSizeError, ExceptionMessages::failedToExecute(
"extend", "Selection", String::number(offset) + " is larger than the given node'
s length.")); | 357 exceptionState.throwDOMException(IndexSizeError, ExceptionMessages::fail
edToExecute("extend", "Selection", String::number(offset) + " is larger than the
given node's length.")); |
| 358 return; | 358 return; |
| 359 } | 359 } |
| 360 | 360 |
| 361 if (!isValidForPosition(node)) | 361 if (!isValidForPosition(node)) |
| 362 return; | 362 return; |
| 363 | 363 |
| 364 // FIXME: Eliminate legacy editing positions | 364 // FIXME: Eliminate legacy editing positions |
| 365 m_frame->selection().setExtent(VisiblePosition(createLegacyEditingPosition(n
ode, offset), DOWNSTREAM)); | 365 m_frame->selection().setExtent(VisiblePosition(createLegacyEditingPosition(n
ode, offset), DOWNSTREAM)); |
| 366 } | 366 } |
| 367 | 367 |
| 368 PassRefPtr<Range> DOMSelection::getRangeAt(int index, ExceptionState& es) | 368 PassRefPtr<Range> DOMSelection::getRangeAt(int index, ExceptionState& exceptionS
tate) |
| 369 { | 369 { |
| 370 if (!m_frame) | 370 if (!m_frame) |
| 371 return 0; | 371 return 0; |
| 372 | 372 |
| 373 if (index < 0 || index >= rangeCount()) { | 373 if (index < 0 || index >= rangeCount()) { |
| 374 es.throwDOMException(IndexSizeError, ExceptionMessages::failedToExecute(
"getRangeAt", "Selection", String::number(index) + " is not a valid index.")); | 374 exceptionState.throwDOMException(IndexSizeError, ExceptionMessages::fail
edToExecute("getRangeAt", "Selection", String::number(index) + " is not a valid
index.")); |
| 375 return 0; | 375 return 0; |
| 376 } | 376 } |
| 377 | 377 |
| 378 // If you're hitting this, you've added broken multi-range selection support | 378 // If you're hitting this, you've added broken multi-range selection support |
| 379 ASSERT(rangeCount() == 1); | 379 ASSERT(rangeCount() == 1); |
| 380 | 380 |
| 381 if (Node* shadowAncestor = selectionShadowAncestor(m_frame)) { | 381 if (Node* shadowAncestor = selectionShadowAncestor(m_frame)) { |
| 382 ContainerNode* container = shadowAncestor->parentNodeGuaranteedHostFree(
); | 382 ContainerNode* container = shadowAncestor->parentNodeGuaranteedHostFree(
); |
| 383 int offset = shadowAncestor->nodeIndex(); | 383 int offset = shadowAncestor->nodeIndex(); |
| 384 return Range::create(shadowAncestor->document(), container, offset, cont
ainer, offset); | 384 return Range::create(shadowAncestor->document(), container, offset, cont
ainer, offset); |
| (...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 416 if (r->compareBoundaryPoints(Range::END_TO_END, range.get(), IGNORE_
EXCEPTION) == -1) { | 416 if (r->compareBoundaryPoints(Range::END_TO_END, range.get(), IGNORE_
EXCEPTION) == -1) { |
| 417 // The original range and r intersect. | 417 // The original range and r intersect. |
| 418 selection.setSelection(VisibleSelection(r->startPosition(), rang
e->endPosition(), DOWNSTREAM)); | 418 selection.setSelection(VisibleSelection(r->startPosition(), rang
e->endPosition(), DOWNSTREAM)); |
| 419 } else { | 419 } else { |
| 420 // r contains the original range. | 420 // r contains the original range. |
| 421 selection.setSelection(VisibleSelection(r)); | 421 selection.setSelection(VisibleSelection(r)); |
| 422 } | 422 } |
| 423 } | 423 } |
| 424 } else { | 424 } else { |
| 425 // We don't support discontiguous selection. We don't do anything if r a
nd range don't intersect. | 425 // We don't support discontiguous selection. We don't do anything if r a
nd range don't intersect. |
| 426 TrackExceptionState es; | 426 TrackExceptionState exceptionState; |
| 427 if (r->compareBoundaryPoints(Range::END_TO_START, range.get(), es) < 1 &
& !es.hadException()) { | 427 if (r->compareBoundaryPoints(Range::END_TO_START, range.get(), exception
State) < 1 && !exceptionState.hadException()) { |
| 428 if (r->compareBoundaryPoints(Range::END_TO_END, range.get(), IGNORE_
EXCEPTION) == -1) { | 428 if (r->compareBoundaryPoints(Range::END_TO_END, range.get(), IGNORE_
EXCEPTION) == -1) { |
| 429 // The original range contains r. | 429 // The original range contains r. |
| 430 selection.setSelection(VisibleSelection(range.get())); | 430 selection.setSelection(VisibleSelection(range.get())); |
| 431 } else { | 431 } else { |
| 432 // The original range and r intersect. | 432 // The original range and r intersect. |
| 433 selection.setSelection(VisibleSelection(range->startPosition(),
r->endPosition(), DOWNSTREAM)); | 433 selection.setSelection(VisibleSelection(range->startPosition(),
r->endPosition(), DOWNSTREAM)); |
| 434 } | 434 } |
| 435 } | 435 } |
| 436 } | 436 } |
| 437 } | 437 } |
| (...skipping 30 matching lines...) Expand all Loading... |
| 468 if (!n || m_frame->document() != n->document() || selection.isNone()) | 468 if (!n || m_frame->document() != n->document() || selection.isNone()) |
| 469 return false; | 469 return false; |
| 470 | 470 |
| 471 unsigned nodeIndex = n->nodeIndex(); | 471 unsigned nodeIndex = n->nodeIndex(); |
| 472 RefPtr<Range> selectedRange = selection.selection().toNormalizedRange(); | 472 RefPtr<Range> selectedRange = selection.selection().toNormalizedRange(); |
| 473 | 473 |
| 474 ContainerNode* parentNode = n->parentNode(); | 474 ContainerNode* parentNode = n->parentNode(); |
| 475 if (!parentNode) | 475 if (!parentNode) |
| 476 return false; | 476 return false; |
| 477 | 477 |
| 478 TrackExceptionState es; | 478 TrackExceptionState exceptionState; |
| 479 bool nodeFullySelected = Range::compareBoundaryPoints(parentNode, nodeIndex,
selectedRange->startContainer(), selectedRange->startOffset(), es) >= 0 && !es.
hadException() | 479 bool nodeFullySelected = Range::compareBoundaryPoints(parentNode, nodeIndex,
selectedRange->startContainer(), selectedRange->startOffset(), exceptionState)
>= 0 && !exceptionState.hadException() |
| 480 && Range::compareBoundaryPoints(parentNode, nodeIndex + 1, selectedRange
->endContainer(), selectedRange->endOffset(), es) <= 0 && !es.hadException(); | 480 && Range::compareBoundaryPoints(parentNode, nodeIndex + 1, selectedRange
->endContainer(), selectedRange->endOffset(), exceptionState) <= 0 && !exception
State.hadException(); |
| 481 ASSERT(!es.hadException()); | 481 ASSERT(!exceptionState.hadException()); |
| 482 if (nodeFullySelected) | 482 if (nodeFullySelected) |
| 483 return true; | 483 return true; |
| 484 | 484 |
| 485 bool nodeFullyUnselected = (Range::compareBoundaryPoints(parentNode, nodeInd
ex, selectedRange->endContainer(), selectedRange->endOffset(), es) > 0 && !es.ha
dException()) | 485 bool nodeFullyUnselected = (Range::compareBoundaryPoints(parentNode, nodeInd
ex, selectedRange->endContainer(), selectedRange->endOffset(), exceptionState) >
0 && !exceptionState.hadException()) |
| 486 || (Range::compareBoundaryPoints(parentNode, nodeIndex + 1, selectedRang
e->startContainer(), selectedRange->startOffset(), es) < 0 && !es.hadException()
); | 486 || (Range::compareBoundaryPoints(parentNode, nodeIndex + 1, selectedRang
e->startContainer(), selectedRange->startOffset(), exceptionState) < 0 && !excep
tionState.hadException()); |
| 487 ASSERT(!es.hadException()); | 487 ASSERT(!exceptionState.hadException()); |
| 488 if (nodeFullyUnselected) | 488 if (nodeFullyUnselected) |
| 489 return false; | 489 return false; |
| 490 | 490 |
| 491 return allowPartial || n->isTextNode(); | 491 return allowPartial || n->isTextNode(); |
| 492 } | 492 } |
| 493 | 493 |
| 494 void DOMSelection::selectAllChildren(Node* n, ExceptionState& es) | 494 void DOMSelection::selectAllChildren(Node* n, ExceptionState& exceptionState) |
| 495 { | 495 { |
| 496 if (!n) | 496 if (!n) |
| 497 return; | 497 return; |
| 498 | 498 |
| 499 // This doesn't (and shouldn't) select text node characters. | 499 // This doesn't (and shouldn't) select text node characters. |
| 500 setBaseAndExtent(n, 0, n, n->childNodeCount(), es); | 500 setBaseAndExtent(n, 0, n, n->childNodeCount(), exceptionState); |
| 501 } | 501 } |
| 502 | 502 |
| 503 String DOMSelection::toString() | 503 String DOMSelection::toString() |
| 504 { | 504 { |
| 505 if (!m_frame) | 505 if (!m_frame) |
| 506 return String(); | 506 return String(); |
| 507 | 507 |
| 508 return plainText(m_frame->selection().selection().toNormalizedRange().get())
; | 508 return plainText(m_frame->selection().selection().toNormalizedRange().get())
; |
| 509 } | 509 } |
| 510 | 510 |
| (...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 544 | 544 |
| 545 bool DOMSelection::isValidForPosition(Node* node) const | 545 bool DOMSelection::isValidForPosition(Node* node) const |
| 546 { | 546 { |
| 547 ASSERT(m_frame); | 547 ASSERT(m_frame); |
| 548 if (!node) | 548 if (!node) |
| 549 return true; | 549 return true; |
| 550 return node->document() == m_frame->document(); | 550 return node->document() == m_frame->document(); |
| 551 } | 551 } |
| 552 | 552 |
| 553 } // namespace WebCore | 553 } // namespace WebCore |
| OLD | NEW |