OLD | NEW |
1 /* | 1 /* |
2 * Copyright (C) 1999 Lars Knoll (knoll@kde.org) | 2 * Copyright (C) 1999 Lars Knoll (knoll@kde.org) |
3 * (C) 1999 Antti Koivisto (koivisto@kde.org) | 3 * (C) 1999 Antti Koivisto (koivisto@kde.org) |
4 * (C) 2001 Dirk Mueller (mueller@kde.org) | 4 * (C) 2001 Dirk Mueller (mueller@kde.org) |
5 * Copyright (C) 2004, 2005, 2006, 2007 Apple Inc. All rights reserved. | 5 * Copyright (C) 2004, 2005, 2006, 2007 Apple Inc. All rights reserved. |
6 * (C) 2006 Alexey Proskuryakov (ap@nypop.com) | 6 * (C) 2006 Alexey Proskuryakov (ap@nypop.com) |
7 * | 7 * |
8 * This library is free software; you can redistribute it and/or | 8 * This library is free software; you can redistribute it and/or |
9 * modify it under the terms of the GNU Library General Public | 9 * modify it under the terms of the GNU Library General Public |
10 * License as published by the Free Software Foundation; either | 10 * License as published by the Free Software Foundation; either |
(...skipping 122 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
133 const AtomicString& attributeValue = fastGetAttribute(placeholderAttr); | 133 const AtomicString& attributeValue = fastGetAttribute(placeholderAttr); |
134 return attributeValue.string().find(isNotLineBreak) == notFound; | 134 return attributeValue.string().find(isNotLineBreak) == notFound; |
135 } | 135 } |
136 | 136 |
137 bool HTMLTextFormControlElement::placeholderShouldBeVisible() const | 137 bool HTMLTextFormControlElement::placeholderShouldBeVisible() const |
138 { | 138 { |
139 return supportsPlaceholder() | 139 return supportsPlaceholder() |
140 && isEmptyValue() | 140 && isEmptyValue() |
141 && isEmptySuggestedValue() | 141 && isEmptySuggestedValue() |
142 && !isPlaceholderEmpty() | 142 && !isPlaceholderEmpty() |
143 && (document()->focusedElement() != this || (RenderTheme::theme().should
ShowPlaceholderWhenFocused())) | 143 && (document().focusedElement() != this || (RenderTheme::theme().shouldS
howPlaceholderWhenFocused())) |
144 && (!renderer() || renderer()->style()->visibility() == VISIBLE); | 144 && (!renderer() || renderer()->style()->visibility() == VISIBLE); |
145 } | 145 } |
146 | 146 |
147 void HTMLTextFormControlElement::updatePlaceholderVisibility(bool placeholderVal
ueChanged) | 147 void HTMLTextFormControlElement::updatePlaceholderVisibility(bool placeholderVal
ueChanged) |
148 { | 148 { |
149 if (!supportsPlaceholder()) | 149 if (!supportsPlaceholder()) |
150 return; | 150 return; |
151 if (!placeholderElement() || placeholderValueChanged) | 151 if (!placeholderElement() || placeholderValueChanged) |
152 updatePlaceholderText(); | 152 updatePlaceholderText(); |
153 HTMLElement* placeholder = placeholderElement(); | 153 HTMLElement* placeholder = placeholderElement(); |
(...skipping 110 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
264 if (directionString == "forward") | 264 if (directionString == "forward") |
265 direction = SelectionHasForwardDirection; | 265 direction = SelectionHasForwardDirection; |
266 else if (directionString == "backward") | 266 else if (directionString == "backward") |
267 direction = SelectionHasBackwardDirection; | 267 direction = SelectionHasBackwardDirection; |
268 | 268 |
269 return setSelectionRange(start, end, direction); | 269 return setSelectionRange(start, end, direction); |
270 } | 270 } |
271 | 271 |
272 void HTMLTextFormControlElement::setSelectionRange(int start, int end, TextField
SelectionDirection direction) | 272 void HTMLTextFormControlElement::setSelectionRange(int start, int end, TextField
SelectionDirection direction) |
273 { | 273 { |
274 document()->updateLayoutIgnorePendingStylesheets(); | 274 document().updateLayoutIgnorePendingStylesheets(); |
275 | 275 |
276 if (!renderer() || !renderer()->isTextControl()) | 276 if (!renderer() || !renderer()->isTextControl()) |
277 return; | 277 return; |
278 | 278 |
279 end = max(end, 0); | 279 end = max(end, 0); |
280 start = min(max(start, 0), end); | 280 start = min(max(start, 0), end); |
281 | 281 |
282 if (!hasVisibleTextArea(renderer(), innerTextElement())) { | 282 if (!hasVisibleTextArea(renderer(), innerTextElement())) { |
283 cacheSelection(start, end, direction); | 283 cacheSelection(start, end, direction); |
284 return; | 284 return; |
(...skipping 11 matching lines...) Expand all Loading... |
296 ASSERT(startPosition.deepEquivalent().deprecatedNode()->shadowHost() ==
this | 296 ASSERT(startPosition.deepEquivalent().deprecatedNode()->shadowHost() ==
this |
297 && endPosition.deepEquivalent().deprecatedNode()->shadowHost() == th
is); | 297 && endPosition.deepEquivalent().deprecatedNode()->shadowHost() == th
is); |
298 } | 298 } |
299 VisibleSelection newSelection; | 299 VisibleSelection newSelection; |
300 if (direction == SelectionHasBackwardDirection) | 300 if (direction == SelectionHasBackwardDirection) |
301 newSelection = VisibleSelection(endPosition, startPosition); | 301 newSelection = VisibleSelection(endPosition, startPosition); |
302 else | 302 else |
303 newSelection = VisibleSelection(startPosition, endPosition); | 303 newSelection = VisibleSelection(startPosition, endPosition); |
304 newSelection.setIsDirectional(direction != SelectionHasNoDirection); | 304 newSelection.setIsDirectional(direction != SelectionHasNoDirection); |
305 | 305 |
306 if (Frame* frame = document()->frame()) | 306 if (Frame* frame = document().frame()) |
307 frame->selection()->setSelection(newSelection); | 307 frame->selection()->setSelection(newSelection); |
308 } | 308 } |
309 | 309 |
310 VisiblePosition HTMLTextFormControlElement::visiblePositionForIndex(int index) c
onst | 310 VisiblePosition HTMLTextFormControlElement::visiblePositionForIndex(int index) c
onst |
311 { | 311 { |
312 if (index <= 0) | 312 if (index <= 0) |
313 return VisiblePosition(firstPositionInNode(innerTextElement()), DOWNSTRE
AM); | 313 return VisiblePosition(firstPositionInNode(innerTextElement()), DOWNSTRE
AM); |
314 RefPtr<Range> range = Range::create(document()); | 314 RefPtr<Range> range = Range::create(&document()); |
315 range->selectNodeContents(innerTextElement(), ASSERT_NO_EXCEPTION); | 315 range->selectNodeContents(innerTextElement(), ASSERT_NO_EXCEPTION); |
316 CharacterIterator it(range.get()); | 316 CharacterIterator it(range.get()); |
317 it.advance(index - 1); | 317 it.advance(index - 1); |
318 return VisiblePosition(it.range()->endPosition(), UPSTREAM); | 318 return VisiblePosition(it.range()->endPosition(), UPSTREAM); |
319 } | 319 } |
320 | 320 |
321 int HTMLTextFormControlElement::indexForVisiblePosition(const VisiblePosition& p
os) const | 321 int HTMLTextFormControlElement::indexForVisiblePosition(const VisiblePosition& p
os) const |
322 { | 322 { |
323 Position indexPosition = pos.deepEquivalent().parentAnchoredEquivalent(); | 323 Position indexPosition = pos.deepEquivalent().parentAnchoredEquivalent(); |
324 if (enclosingTextFormControl(indexPosition) != this) | 324 if (enclosingTextFormControl(indexPosition) != this) |
325 return 0; | 325 return 0; |
326 RefPtr<Range> range = Range::create(indexPosition.document()); | 326 RefPtr<Range> range = Range::create(indexPosition.document()); |
327 range->setStart(innerTextElement(), 0, ASSERT_NO_EXCEPTION); | 327 range->setStart(innerTextElement(), 0, ASSERT_NO_EXCEPTION); |
328 range->setEnd(indexPosition.containerNode(), indexPosition.offsetInContainer
Node(), ASSERT_NO_EXCEPTION); | 328 range->setEnd(indexPosition.containerNode(), indexPosition.offsetInContainer
Node(), ASSERT_NO_EXCEPTION); |
329 return TextIterator::rangeLength(range.get()); | 329 return TextIterator::rangeLength(range.get()); |
330 } | 330 } |
331 | 331 |
332 int HTMLTextFormControlElement::selectionStart() const | 332 int HTMLTextFormControlElement::selectionStart() const |
333 { | 333 { |
334 if (!isTextFormControl()) | 334 if (!isTextFormControl()) |
335 return 0; | 335 return 0; |
336 if (document()->focusedElement() != this && hasCachedSelection()) | 336 if (document().focusedElement() != this && hasCachedSelection()) |
337 return m_cachedSelectionStart; | 337 return m_cachedSelectionStart; |
338 | 338 |
339 return computeSelectionStart(); | 339 return computeSelectionStart(); |
340 } | 340 } |
341 | 341 |
342 int HTMLTextFormControlElement::computeSelectionStart() const | 342 int HTMLTextFormControlElement::computeSelectionStart() const |
343 { | 343 { |
344 ASSERT(isTextFormControl()); | 344 ASSERT(isTextFormControl()); |
345 Frame* frame = document()->frame(); | 345 Frame* frame = document().frame(); |
346 if (!frame) | 346 if (!frame) |
347 return 0; | 347 return 0; |
348 | 348 |
349 return indexForVisiblePosition(frame->selection()->start()); | 349 return indexForVisiblePosition(frame->selection()->start()); |
350 } | 350 } |
351 | 351 |
352 int HTMLTextFormControlElement::selectionEnd() const | 352 int HTMLTextFormControlElement::selectionEnd() const |
353 { | 353 { |
354 if (!isTextFormControl()) | 354 if (!isTextFormControl()) |
355 return 0; | 355 return 0; |
356 if (document()->focusedElement() != this && hasCachedSelection()) | 356 if (document().focusedElement() != this && hasCachedSelection()) |
357 return m_cachedSelectionEnd; | 357 return m_cachedSelectionEnd; |
358 return computeSelectionEnd(); | 358 return computeSelectionEnd(); |
359 } | 359 } |
360 | 360 |
361 int HTMLTextFormControlElement::computeSelectionEnd() const | 361 int HTMLTextFormControlElement::computeSelectionEnd() const |
362 { | 362 { |
363 ASSERT(isTextFormControl()); | 363 ASSERT(isTextFormControl()); |
364 Frame* frame = document()->frame(); | 364 Frame* frame = document().frame(); |
365 if (!frame) | 365 if (!frame) |
366 return 0; | 366 return 0; |
367 | 367 |
368 return indexForVisiblePosition(frame->selection()->end()); | 368 return indexForVisiblePosition(frame->selection()->end()); |
369 } | 369 } |
370 | 370 |
371 static const AtomicString& directionString(TextFieldSelectionDirection direction
) | 371 static const AtomicString& directionString(TextFieldSelectionDirection direction
) |
372 { | 372 { |
373 DEFINE_STATIC_LOCAL(const AtomicString, none, ("none", AtomicString::Constru
ctFromLiteral)); | 373 DEFINE_STATIC_LOCAL(const AtomicString, none, ("none", AtomicString::Constru
ctFromLiteral)); |
374 DEFINE_STATIC_LOCAL(const AtomicString, forward, ("forward", AtomicString::C
onstructFromLiteral)); | 374 DEFINE_STATIC_LOCAL(const AtomicString, forward, ("forward", AtomicString::C
onstructFromLiteral)); |
375 DEFINE_STATIC_LOCAL(const AtomicString, backward, ("backward", AtomicString:
:ConstructFromLiteral)); | 375 DEFINE_STATIC_LOCAL(const AtomicString, backward, ("backward", AtomicString:
:ConstructFromLiteral)); |
376 | 376 |
377 switch (direction) { | 377 switch (direction) { |
378 case SelectionHasNoDirection: | 378 case SelectionHasNoDirection: |
379 return none; | 379 return none; |
380 case SelectionHasForwardDirection: | 380 case SelectionHasForwardDirection: |
381 return forward; | 381 return forward; |
382 case SelectionHasBackwardDirection: | 382 case SelectionHasBackwardDirection: |
383 return backward; | 383 return backward; |
384 } | 384 } |
385 | 385 |
386 ASSERT_NOT_REACHED(); | 386 ASSERT_NOT_REACHED(); |
387 return none; | 387 return none; |
388 } | 388 } |
389 | 389 |
390 const AtomicString& HTMLTextFormControlElement::selectionDirection() const | 390 const AtomicString& HTMLTextFormControlElement::selectionDirection() const |
391 { | 391 { |
392 if (!isTextFormControl()) | 392 if (!isTextFormControl()) |
393 return directionString(SelectionHasNoDirection); | 393 return directionString(SelectionHasNoDirection); |
394 if (document()->focusedElement() != this && hasCachedSelection()) | 394 if (document().focusedElement() != this && hasCachedSelection()) |
395 return directionString(m_cachedSelectionDirection); | 395 return directionString(m_cachedSelectionDirection); |
396 | 396 |
397 return directionString(computeSelectionDirection()); | 397 return directionString(computeSelectionDirection()); |
398 } | 398 } |
399 | 399 |
400 TextFieldSelectionDirection HTMLTextFormControlElement::computeSelectionDirectio
n() const | 400 TextFieldSelectionDirection HTMLTextFormControlElement::computeSelectionDirectio
n() const |
401 { | 401 { |
402 ASSERT(isTextFormControl()); | 402 ASSERT(isTextFormControl()); |
403 Frame* frame = document()->frame(); | 403 Frame* frame = document().frame(); |
404 if (!frame) | 404 if (!frame) |
405 return SelectionHasNoDirection; | 405 return SelectionHasNoDirection; |
406 | 406 |
407 const VisibleSelection& selection = frame->selection()->selection(); | 407 const VisibleSelection& selection = frame->selection()->selection(); |
408 return selection.isDirectional() ? (selection.isBaseFirst() ? SelectionHasFo
rwardDirection : SelectionHasBackwardDirection) : SelectionHasNoDirection; | 408 return selection.isDirectional() ? (selection.isBaseFirst() ? SelectionHasFo
rwardDirection : SelectionHasBackwardDirection) : SelectionHasNoDirection; |
409 } | 409 } |
410 | 410 |
411 static inline void setContainerAndOffsetForRange(Node* node, int offset, Node*&
containerNode, int& offsetInContainer) | 411 static inline void setContainerAndOffsetForRange(Node* node, int offset, Node*&
containerNode, int& offsetInContainer) |
412 { | 412 { |
413 if (node->isTextNode()) { | 413 if (node->isTextNode()) { |
(...skipping 12 matching lines...) Expand all Loading... |
426 | 426 |
427 int start = m_cachedSelectionStart; | 427 int start = m_cachedSelectionStart; |
428 int end = m_cachedSelectionEnd; | 428 int end = m_cachedSelectionEnd; |
429 | 429 |
430 ASSERT(start <= end); | 430 ASSERT(start <= end); |
431 HTMLElement* innerText = innerTextElement(); | 431 HTMLElement* innerText = innerTextElement(); |
432 if (!innerText) | 432 if (!innerText) |
433 return 0; | 433 return 0; |
434 | 434 |
435 if (!innerText->firstChild()) | 435 if (!innerText->firstChild()) |
436 return Range::create(document(), innerText, 0, innerText, 0); | 436 return Range::create(&document(), innerText, 0, innerText, 0); |
437 | 437 |
438 int offset = 0; | 438 int offset = 0; |
439 Node* startNode = 0; | 439 Node* startNode = 0; |
440 Node* endNode = 0; | 440 Node* endNode = 0; |
441 for (Node* node = innerText->firstChild(); node; node = NodeTraversal::next(
node, innerText)) { | 441 for (Node* node = innerText->firstChild(); node; node = NodeTraversal::next(
node, innerText)) { |
442 ASSERT(!node->firstChild()); | 442 ASSERT(!node->firstChild()); |
443 ASSERT(node->isTextNode() || node->hasTagName(brTag)); | 443 ASSERT(node->isTextNode() || node->hasTagName(brTag)); |
444 int length = node->isTextNode() ? lastOffsetInNode(node) : 1; | 444 int length = node->isTextNode() ? lastOffsetInNode(node) : 1; |
445 | 445 |
446 if (offset <= start && start <= offset + length) | 446 if (offset <= start && start <= offset + length) |
447 setContainerAndOffsetForRange(node, start - offset, startNode, start
); | 447 setContainerAndOffsetForRange(node, start - offset, startNode, start
); |
448 | 448 |
449 if (offset <= end && end <= offset + length) { | 449 if (offset <= end && end <= offset + length) { |
450 setContainerAndOffsetForRange(node, end - offset, endNode, end); | 450 setContainerAndOffsetForRange(node, end - offset, endNode, end); |
451 break; | 451 break; |
452 } | 452 } |
453 | 453 |
454 offset += length; | 454 offset += length; |
455 } | 455 } |
456 | 456 |
457 if (!startNode || !endNode) | 457 if (!startNode || !endNode) |
458 return 0; | 458 return 0; |
459 | 459 |
460 return Range::create(document(), startNode, start, endNode, end); | 460 return Range::create(&document(), startNode, start, endNode, end); |
461 } | 461 } |
462 | 462 |
463 void HTMLTextFormControlElement::restoreCachedSelection() | 463 void HTMLTextFormControlElement::restoreCachedSelection() |
464 { | 464 { |
465 setSelectionRange(m_cachedSelectionStart, m_cachedSelectionEnd, m_cachedSele
ctionDirection); | 465 setSelectionRange(m_cachedSelectionStart, m_cachedSelectionEnd, m_cachedSele
ctionDirection); |
466 } | 466 } |
467 | 467 |
468 void HTMLTextFormControlElement::selectionChanged(bool userTriggered) | 468 void HTMLTextFormControlElement::selectionChanged(bool userTriggered) |
469 { | 469 { |
470 if (!renderer() || !isTextFormControl()) | 470 if (!renderer() || !isTextFormControl()) |
471 return; | 471 return; |
472 | 472 |
473 // selectionStart() or selectionEnd() will return cached selection when this
node doesn't have focus | 473 // selectionStart() or selectionEnd() will return cached selection when this
node doesn't have focus |
474 cacheSelection(computeSelectionStart(), computeSelectionEnd(), computeSelect
ionDirection()); | 474 cacheSelection(computeSelectionStart(), computeSelectionEnd(), computeSelect
ionDirection()); |
475 | 475 |
476 if (Frame* frame = document()->frame()) { | 476 if (Frame* frame = document().frame()) { |
477 if (frame->selection()->isRange() && userTriggered) | 477 if (frame->selection()->isRange() && userTriggered) |
478 dispatchEvent(Event::createBubble(eventNames().selectEvent)); | 478 dispatchEvent(Event::createBubble(eventNames().selectEvent)); |
479 } | 479 } |
480 } | 480 } |
481 | 481 |
482 void HTMLTextFormControlElement::parseAttribute(const QualifiedName& name, const
AtomicString& value) | 482 void HTMLTextFormControlElement::parseAttribute(const QualifiedName& name, const
AtomicString& value) |
483 { | 483 { |
484 if (name == placeholderAttr) { | 484 if (name == placeholderAttr) { |
485 updatePlaceholderVisibility(true); | 485 updatePlaceholderVisibility(true); |
486 UseCounter::count(document(), UseCounter::PlaceholderAttribute); | 486 UseCounter::count(&document(), UseCounter::PlaceholderAttribute); |
487 } else | 487 } else |
488 HTMLFormControlElementWithState::parseAttribute(name, value); | 488 HTMLFormControlElementWithState::parseAttribute(name, value); |
489 } | 489 } |
490 | 490 |
491 bool HTMLTextFormControlElement::lastChangeWasUserEdit() const | 491 bool HTMLTextFormControlElement::lastChangeWasUserEdit() const |
492 { | 492 { |
493 if (!isTextFormControl()) | 493 if (!isTextFormControl()) |
494 return false; | 494 return false; |
495 return m_lastChangeWasUserEdit; | 495 return m_lastChangeWasUserEdit; |
496 } | 496 } |
497 | 497 |
498 void HTMLTextFormControlElement::setInnerTextValue(const String& value) | 498 void HTMLTextFormControlElement::setInnerTextValue(const String& value) |
499 { | 499 { |
500 if (!isTextFormControl()) | 500 if (!isTextFormControl()) |
501 return; | 501 return; |
502 | 502 |
503 bool textIsChanged = value != innerTextValue(); | 503 bool textIsChanged = value != innerTextValue(); |
504 if (textIsChanged || !innerTextElement()->hasChildNodes()) { | 504 if (textIsChanged || !innerTextElement()->hasChildNodes()) { |
505 if (textIsChanged && document() && renderer()) { | 505 if (textIsChanged && renderer()) { |
506 if (AXObjectCache* cache = document()->existingAXObjectCache()) | 506 if (AXObjectCache* cache = document().existingAXObjectCache()) |
507 cache->postNotification(this, AXObjectCache::AXValueChanged, fal
se); | 507 cache->postNotification(this, AXObjectCache::AXValueChanged, fal
se); |
508 } | 508 } |
509 innerTextElement()->setInnerText(value, ASSERT_NO_EXCEPTION); | 509 innerTextElement()->setInnerText(value, ASSERT_NO_EXCEPTION); |
510 | 510 |
511 if (value.endsWith('\n') || value.endsWith('\r')) | 511 if (value.endsWith('\n') || value.endsWith('\r')) |
512 innerTextElement()->appendChild(HTMLBRElement::create(document())); | 512 innerTextElement()->appendChild(HTMLBRElement::create(&document())); |
513 } | 513 } |
514 | 514 |
515 setFormControlValueMatchesRenderer(true); | 515 setFormControlValueMatchesRenderer(true); |
516 } | 516 } |
517 | 517 |
518 static String finishText(StringBuilder& result) | 518 static String finishText(StringBuilder& result) |
519 { | 519 { |
520 // Remove one trailing newline; there's always one that's collapsed out by r
endering. | 520 // Remove one trailing newline; there's always one that's collapsed out by r
endering. |
521 size_t size = result.length(); | 521 size_t size = result.length(); |
522 if (size && result[size - 1] == '\n') | 522 if (size && result[size - 1] == '\n') |
(...skipping 115 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
638 bool isAuto; | 638 bool isAuto; |
639 TextDirection textDirection = static_cast<const HTMLElement*>(elemen
t)->directionalityIfhasDirAutoAttribute(isAuto); | 639 TextDirection textDirection = static_cast<const HTMLElement*>(elemen
t)->directionalityIfhasDirAutoAttribute(isAuto); |
640 return textDirection == RTL ? "rtl" : "ltr"; | 640 return textDirection == RTL ? "rtl" : "ltr"; |
641 } | 641 } |
642 } | 642 } |
643 | 643 |
644 return "ltr"; | 644 return "ltr"; |
645 } | 645 } |
646 | 646 |
647 } // namespace Webcore | 647 } // namespace Webcore |
OLD | NEW |