Changeset 25547 in webkit


Ignore:
Timestamp:
Sep 13, 2007 4:03:57 PM (17 years ago)
Author:
darin
Message:

WebCore:

Reviewed by Oliver.

  • fix <rdar://problem/5470457> REGRESSION: Input method inline hole is mishandled in text <input> elements with maxlength limit
  • editing/Editor.h: Moved MarkedTextUnderline here and renamed it CompositionUnderline. Moved the rest of the marked text API here and used the term that will be more familiar to those on platforms other than Macintosh, "composition". This helps prevent confusion with the other kinds of mark -- the emacs "mark" and spelling/grammar marks. Also cleaned up the conditionals a bit for the Macintosh-specific parts of this header.
  • editing/Editor.cpp: (WebCore::Editor::Editor): Updated for name change. (WebCore::Editor::clear): Added. To be called by FrameLoader::clear(). (WebCore::Editor::insertTextWithoutSendingTextEvent): Removed code to make inserted text replace the marked text range -- we now deal with this explicitly by not calling this function to replace marked text. Also removed unneeded code that was specific to the use of this to replace the marked text. (WebCore::Editor::selectComposition): Renamed from selectMarkedText. Updated since the composition range is not stored as a Range. (WebCore::Editor::confirmComposition): Added. To be called when changing a composition into actual text. Unlike the old code path, deletes the composition first, then inserts the text, triggering the normal insertion code path and events. This is helpful because it means the inserted text will be truncated by the <input> element, for example. (WebCore::Editor::confirmCompositionWithoutDisturbingSelection): Added. (WebCore::Editor::setComposition): Added. To be called when changing the composition. Takes parameters for the underlines and selection. Unlike the old code path, this passes a flag down that indicates the inserted text is part of a composition. This is helpful because we don't send the event that will cause the <input> element to do truncation. It's also a better API for future improvements to our input method handling. (WebCore::Editor::revealSelectionAfterEditingOperation): Updated for name change. (WebCore::Editor::setIgnoreCompositionSelectionChange): Ditto. (WebCore::Editor::compositionRange): Added. Needed now that the composition is not stored as a Range. (WebCore::Editor::getCompositionSelection): Added.
  • editing/TypingCommand.h:
  • editing/TypingCommand.cpp: (WebCore::TypingCommand::insertText): Added an insertedTextIsComposition parameter, and don't send the BeforeTextInsertedEvent if it's true.
  • loader/FrameLoader.cpp: (WebCore::FrameLoader::clear): Replaced the Macintosh-specific call to setMarkedTextRange with a call to the new Editor::clear().
  • page/Frame.h:
  • page/Frame.cpp:
  • page/FramePrivate.h:
  • page/mac/FrameMac.mm: Removed the marked text code. It was streamlined and moved to Editor, except for the Mac-specific code, which was moved into WebKit.
  • page/mac/WebCoreFrameBridge.h:
  • page/mac/WebCoreFrameBridge.mm: Removed some now-unneeded marked text code. (-[WebCoreFrameBridge markedTextNSRange]): Updated for name/API change.
  • rendering/InlineTextBox.h:
  • rendering/InlineTextBox.cpp: (WebCore::InlineTextBox::paint): Updated marked text code for name changes, and also streamlined the code a bit for the case where there is no composition. (WebCore::InlineTextBox::paintCompositionBackground): Name change. (WebCore::InlineTextBox::paintCompositionUnderline): Ditto.
  • rendering/RenderTextControl.h:
  • rendering/RenderTextControl.cpp: (WebCore::RenderTextControl::finishText): Added. Helper function shared by the (WebCore::RenderTextControl::text): (WebCore::getNextSoftBreak): (WebCore::RenderTextControl::textWithHardLineBreaks):
  • platform/CharacterNames.h: Added newlineCharacter.
  • dom/Range.h: Remove the now-unneeded version of toString that converts <br> elements into newlines.
  • dom/Range.cpp: (WebCore::Range::toString): Changed this to use a Vector<UChar> instead of a String so it will not have pathological reallocation performance, and removed the <br> feature. (WebCore::Range::pastEndNode): Made this return 0 when there is no start node. This bit of extra robustness guarantees you can't do a null dereference if the start node is 0 and the end node is not. Not sure this case really exists.
  • page/ContextMenuController.cpp: (ContextMenuController::contextMenuItemSelected): Removed a semi-bogus use of Range::toString(true). The right function to use here is plainText().
  • bridge/EditorClient.h: Removed obsolete markedTextAbandoned function.
  • WebCore.exp: Updated for above changes.

WebKit:

Reviewed by Oliver.

  • fix <rdar://problem/5470457> REGRESSION: Input method inline hole is mishandled in text <input> elements with maxlength limit
  • WebView/WebHTMLView.mm: (-[WebHTMLView _selectionChanged]): Tweaked code a bit. (-[WebHTMLView markedRange]): Simplified logic, since markedTextNSRange works when there's no composition range. (-[WebHTMLView hasMarkedText]): Call directly to Editor instead of bridge. (-[WebHTMLView unmarkText]): Call new confirmComposition to make it clear that this is confirming text, not just unmarking it to discard it. (extractUnderlines): Added. Converts directly from an NSAttributedString to the CompositionUnderline vector that's used by WebCore. (-[WebHTMLView setMarkedText:selectedRange:]): Changed to use the new setComposition. (-[WebHTMLView insertText:]): Changed to use confirmComposition when appropriate, instead of relying on special behavior of Editor::insertText. (-[WebHTMLView _updateSelectionForInputManager]): Rewrote to use getCompositionSelection and confirmCompositionWithoutDisturbingSelection.
  • WebCoreSupport/WebEditorClient.h:
  • WebCoreSupport/WebEditorClient.mm: Removed obsolete markedTextAbandoned function.

win:

Reviewed by Oliver.

  • fix <rdar://problem/5470457> REGRESSION: Input method inline hole is mishandled in text <input> elements with maxlength limit
  • WebView.cpp: (WebView::resetIME): Change to use confirmCompositionWithoutDisturbingSelection. (WebView::updateSelectionForIME): Update for name changes, and to use new functions in Editor. (WebView::onIMEStartComposition): Removed unneeded call to unmarkText. (compositionToUnderlines): Removed startOffset parameter, since setComposition now handles this. (WebView::onIMEComposition): Changed to use confirmComposition and setComposition. Logic gets a lot cleaner. (WebView::onIMEEndComposition): Removed unneeded calls to Editor. (WebView::onIMERequestCharPosition): Updated for name changes.

LayoutTests:

Reviewed by Oliver.

  • updated test results changed by change in input manager logic
  • platform/mac/editing/input/firstrectforcharacterrange-styled-expected.txt:
  • platform/mac/editing/input/text-input-controller-expected.txt:
  • platform/mac/editing/input/wrapped-line-char-rect-expected.txt: Updated. Small changes in which delegate methods are called.
Location:
trunk
Files:
32 edited

Legend:

Unmodified
Added
Removed
  • trunk/LayoutTests/ChangeLog

    r25545 r25547  
     12007-09-13  Darin Adler  <darin@apple.com>
     2
     3        Reviewed by Oliver.
     4
     5        - updated test results changed by change in input manager logic
     6
     7        * platform/mac/editing/input/firstrectforcharacterrange-styled-expected.txt:
     8        * platform/mac/editing/input/text-input-controller-expected.txt:
     9        * platform/mac/editing/input/wrapped-line-char-rect-expected.txt:
     10        Updated. Small changes in which delegate methods are called.
     11
    1122007-09-13  Kevin McCullough  <kmccullough@apple.com>
    213
    3         Reviewed by Geof, Sam, Adam, Hyatt, Darin.
     14        Reviewed by Geoff, Sam, Adam, Hyatt, Darin.
    415
    516        - <rdar://problem/5480234> JS setTimeout function requires a second argument
  • trunk/LayoutTests/platform/mac/editing/input/firstrectforcharacterrange-styled-expected.txt

    r25367 r25547  
    22EDITING DELEGATE: webViewDidBeginEditing:WebViewDidBeginEditingNotification
    33EDITING DELEGATE: webViewDidChangeSelection:WebViewDidChangeSelectionNotification
     4EDITING DELEGATE: webViewDidChange:WebViewDidChangeNotification
    45EDITING DELEGATE: shouldChangeSelectedDOMRange:range from 1 of #text > I > B > BODY > HTML > #document to 1 of #text > I > B > BODY > HTML > #document toDOMRange:range from 1 of #text > I > B > BODY > HTML > #document to 3 of #text > I > B > BODY > HTML > #document affinity:NSSelectionAffinityDownstream stillSelecting:FALSE
    56EDITING DELEGATE: webViewDidChangeSelection:WebViewDidChangeSelectionNotification
  • trunk/LayoutTests/platform/mac/editing/input/text-input-controller-expected.txt

    r25367 r25547  
    1515EDITING DELEGATE: webViewDidChangeSelection:WebViewDidChangeSelectionNotification
    1616EDITING DELEGATE: webViewDidChange:WebViewDidChangeNotification
     17EDITING DELEGATE: webViewDidChange:WebViewDidChangeNotification
    1718EDITING DELEGATE: webViewDidChangeSelection:WebViewDidChangeSelectionNotification
    1819EDITING DELEGATE: shouldChangeSelectedDOMRange:(null) toDOMRange:range from 0 of #text > DIV > BODY > HTML > #document to 7 of #text > DIV > BODY > HTML > #document affinity:NSSelectionAffinityDownstream stillSelecting:FALSE
    1920EDITING DELEGATE: webViewDidChangeSelection:WebViewDidChangeSelectionNotification
    2021EDITING DELEGATE: webViewDidChange:WebViewDidChangeNotification
    21 EDITING DELEGATE: shouldDeleteDOMRange:range from 0 of #text > DIV > BODY > HTML > #document to 7 of #text > DIV > BODY > HTML > #document
    2222EDITING DELEGATE: webViewDidChangeSelection:WebViewDidChangeSelectionNotification
    2323EDITING DELEGATE: shouldChangeSelectedDOMRange:(null) toDOMRange:range from 0 of DIV > BODY > HTML > #document to 0 of DIV > BODY > HTML > #document affinity:NSSelectionAffinityDownstream stillSelecting:FALSE
     
    2828EDITING DELEGATE: webViewDidChangeSelection:WebViewDidChangeSelectionNotification
    2929EDITING DELEGATE: webViewDidChange:WebViewDidChangeNotification
    30 EDITING DELEGATE: shouldChangeSelectedDOMRange:range from 0 of #text > DIV > BODY > HTML > #document to 7 of #text > DIV > BODY > HTML > #document toDOMRange:range from 0 of #text > DIV > BODY > HTML > #document to 7 of #text > DIV > BODY > HTML > #document affinity:NSSelectionAffinityDownstream stillSelecting:FALSE
     30EDITING DELEGATE: webViewDidChangeSelection:WebViewDidChangeSelectionNotification
     31EDITING DELEGATE: shouldChangeSelectedDOMRange:(null) toDOMRange:range from 0 of DIV > BODY > HTML > #document to 0 of DIV > BODY > HTML > #document affinity:NSSelectionAffinityDownstream stillSelecting:FALSE
     32EDITING DELEGATE: webViewDidChangeSelection:WebViewDidChangeSelectionNotification
     33EDITING DELEGATE: webViewDidChange:WebViewDidChangeNotification
     34EDITING DELEGATE: shouldInsertText:Success replacingDOMRange:range from 0 of DIV > BODY > HTML > #document to 0 of DIV > BODY > HTML > #document givenAction:WebViewInsertActionTyped
     35EDITING DELEGATE: webViewDidChangeSelection:WebViewDidChangeSelectionNotification
     36EDITING DELEGATE: shouldChangeSelectedDOMRange:(null) toDOMRange:range from 7 of #text > DIV > BODY > HTML > #document to 7 of #text > DIV > BODY > HTML > #document affinity:NSSelectionAffinityDownstream stillSelecting:FALSE
     37EDITING DELEGATE: webViewDidChangeSelection:WebViewDidChangeSelectionNotification
     38EDITING DELEGATE: webViewDidChange:WebViewDidChangeNotification
     39EDITING DELEGATE: shouldChangeSelectedDOMRange:range from 7 of #text > DIV > BODY > HTML > #document to 7 of #text > DIV > BODY > HTML > #document toDOMRange:range from 0 of #text > DIV > BODY > HTML > #document to 7 of #text > DIV > BODY > HTML > #document affinity:NSSelectionAffinityDownstream stillSelecting:FALSE
     40EDITING DELEGATE: webViewDidChangeSelection:WebViewDidChangeSelectionNotification
    3141Success
  • trunk/LayoutTests/platform/mac/editing/input/wrapped-line-char-rect-expected.txt

    r25367 r25547  
    22EDITING DELEGATE: webViewDidBeginEditing:WebViewDidBeginEditingNotification
    33EDITING DELEGATE: webViewDidChangeSelection:WebViewDidChangeSelectionNotification
     4EDITING DELEGATE: webViewDidChange:WebViewDidChangeNotification
    45EDITING DELEGATE: shouldChangeSelectedDOMRange:range from 0 of P > BODY > HTML > #document to 0 of P > BODY > HTML > #document toDOMRange:range from 0 of #text > P > BODY > HTML > #document to 20 of #text > P > BODY > HTML > #document affinity:NSSelectionAffinityDownstream stillSelecting:FALSE
    56EDITING DELEGATE: webViewDidChangeSelection:WebViewDidChangeSelectionNotification
  • trunk/WebCore/ChangeLog

    r25546 r25547  
     12007-09-13  Darin Adler  <darin@apple.com>
     2
     3        Reviewed by Oliver.
     4
     5        - fix <rdar://problem/5470457> REGRESSION: Input method inline hole is mishandled in text
     6          <input> elements with maxlength limit
     7
     8        * editing/Editor.h: Moved MarkedTextUnderline here and renamed it CompositionUnderline.
     9        Moved the rest of the marked text API here and used the term that will be more familiar
     10        to those on platforms other than Macintosh, "composition". This helps prevent confusion
     11        with the other kinds of mark -- the emacs "mark" and spelling/grammar marks. Also
     12        cleaned up the conditionals a bit for the Macintosh-specific parts of this header.
     13
     14        * editing/Editor.cpp:
     15        (WebCore::Editor::Editor): Updated for name change.
     16        (WebCore::Editor::clear): Added. To be called by FrameLoader::clear().
     17        (WebCore::Editor::insertTextWithoutSendingTextEvent): Removed code to make inserted
     18        text replace the marked text range -- we now deal with this explicitly by not
     19        calling this function to replace marked text. Also removed unneeded code that was
     20        specific to the use of this to replace the marked text.
     21        (WebCore::Editor::selectComposition): Renamed from selectMarkedText. Updated since
     22        the composition range is not stored as a Range.
     23        (WebCore::Editor::confirmComposition): Added. To be called when changing a composition
     24        into actual text. Unlike the old code path, deletes the composition first, then inserts
     25        the text, triggering the normal insertion code path and events. This is helpful because
     26        it means the inserted text will be truncated by the <input> element, for example.
     27        (WebCore::Editor::confirmCompositionWithoutDisturbingSelection): Added.
     28        (WebCore::Editor::setComposition): Added. To be called when changing the composition.
     29        Takes parameters for the underlines and selection. Unlike the old code path, this passes
     30        a flag down that indicates the inserted text is part of a composition. This is helpful
     31        because we don't send the event that will cause the <input> element to do truncation.
     32        It's also a better API for future improvements to our input method handling.
     33        (WebCore::Editor::revealSelectionAfterEditingOperation): Updated for name change.
     34        (WebCore::Editor::setIgnoreCompositionSelectionChange): Ditto.
     35        (WebCore::Editor::compositionRange): Added. Needed now that the composition is not
     36        stored as a Range.
     37        (WebCore::Editor::getCompositionSelection): Added.
     38
     39        * editing/TypingCommand.h:
     40        * editing/TypingCommand.cpp: (WebCore::TypingCommand::insertText):
     41        Added an insertedTextIsComposition parameter, and don't send the BeforeTextInsertedEvent
     42        if it's true.
     43
     44        * loader/FrameLoader.cpp: (WebCore::FrameLoader::clear): Replaced the Macintosh-specific
     45        call to setMarkedTextRange with a call to the new Editor::clear().
     46
     47        * page/Frame.h:
     48        * page/Frame.cpp:
     49        * page/FramePrivate.h:
     50        * page/mac/FrameMac.mm:
     51        Removed the marked text code. It was streamlined and moved to Editor, except for the
     52        Mac-specific code, which was moved into WebKit.
     53
     54        * page/mac/WebCoreFrameBridge.h:
     55        * page/mac/WebCoreFrameBridge.mm: Removed some now-unneeded marked text code.
     56        (-[WebCoreFrameBridge markedTextNSRange]): Updated for name/API change.
     57
     58        * rendering/InlineTextBox.h:
     59        * rendering/InlineTextBox.cpp:
     60        (WebCore::InlineTextBox::paint): Updated marked text code for name changes, and also
     61        streamlined the code a bit for the case where there is no composition.
     62        (WebCore::InlineTextBox::paintCompositionBackground): Name change.
     63        (WebCore::InlineTextBox::paintCompositionUnderline): Ditto.
     64
     65        * rendering/RenderTextControl.h:
     66        * rendering/RenderTextControl.cpp:
     67        (WebCore::RenderTextControl::finishText): Added. Helper function shared by the
     68        (WebCore::RenderTextControl::text):
     69        (WebCore::getNextSoftBreak):
     70        (WebCore::RenderTextControl::textWithHardLineBreaks):
     71
     72        * platform/CharacterNames.h: Added newlineCharacter.
     73
     74        * dom/Range.h: Remove the now-unneeded version of toString that converts <br>
     75        elements into newlines.
     76        * dom/Range.cpp:
     77        (WebCore::Range::toString): Changed this to use a Vector<UChar> instead of
     78        a String so it will not have pathological reallocation performance, and removed
     79        the <br> feature.
     80        (WebCore::Range::pastEndNode): Made this return 0 when there is no start node.
     81        This bit of extra robustness guarantees you can't do a null dereference if the
     82        start node is 0 and the end node is not. Not sure this case really exists.
     83
     84        * page/ContextMenuController.cpp: (ContextMenuController::contextMenuItemSelected):
     85        Removed a semi-bogus use of Range::toString(true). The right function to use here
     86        is plainText().
     87
     88        * bridge/EditorClient.h: Removed obsolete markedTextAbandoned function.
     89
     90        * WebCore.exp: Updated for above changes.
     91
    1922007-09-13  Anders Carlsson  <andersca@apple.com>
    293
  • trunk/WebCore/WebCore.exp

    r25439 r25547  
    311311__ZN7WebCore16NavigationActionC1ERKNS_4KURLENS_14NavigationTypeE
    312312__ZN7WebCore16NavigationActionC1Ev
     313__ZN7WebCore16colorFromNSColorEP7NSColor
    313314__ZN7WebCore18PlatformMouseEventC1EP7NSEvent
    314315__ZN7WebCore19InspectorController16setWindowVisibleEb
     
    374375__ZN7WebCore5Frame20windowScriptNPObjectEv
    375376__ZN7WebCore5Frame21setProhibitsScrollingEb
    376 __ZN7WebCore5Frame23selectRangeInMarkedTextEjj
    377377__ZN7WebCore5Frame26dashboardRegionsDictionaryEv
    378378__ZN7WebCore5Frame29cleanupScriptObjectsForPluginEPv
     
    390390__ZN7WebCore6Editor10applyStyleEPNS_19CSSStyleDeclarationENS_10EditActionE
    391391__ZN7WebCore6Editor10insertTextERKNS_6StringEPNS_5EventE
    392 __ZN7WebCore6Editor10unmarkTextEv
    393392__ZN7WebCore6Editor11canDHTMLCutEv
    394393__ZN7WebCore6Editor11deleteRangeEPNS_5RangeEbbbNS_18EditorDeleteActionENS_15TextGranularityE
     
    401400__ZN7WebCore6Editor13rangeForPointERKNS_8IntPointE
    402401__ZN7WebCore6Editor13tryDHTMLPasteEv
     402__ZN7WebCore6Editor14setCompositionERKNS_6StringERKN3WTF6VectorINS_20CompositionUnderlineELm0EEEjj
    403403__ZN7WebCore6Editor16pasteAsPlainTextEv
    404 __ZN7WebCore6Editor16selectMarkedTextEv
    405 __ZN7WebCore6Editor17discardMarkedTextEv
    406404__ZN7WebCore6Editor17insertOrderedListEv
    407 __ZN7WebCore6Editor17replaceMarkedTextERKNS_6StringE
     405__ZN7WebCore6Editor18confirmCompositionERKNS_6StringE
     406__ZN7WebCore6Editor18confirmCompositionEv
    408407__ZN7WebCore6Editor19deleteWithDirectionENS_19SelectionController10EDirectionENS_15TextGranularityEbb
    409408__ZN7WebCore6Editor19insertUnorderedListEv
     
    421420__ZN7WebCore6Editor33increaseSelectionListLevelOrderedEv
    422421__ZN7WebCore6Editor33insertTextWithoutSendingTextEventERKNS_6StringEbPNS_5EventE
    423 __ZN7WebCore6Editor34setIgnoreMarkedTextSelectionChangeEb
    424422__ZN7WebCore6Editor35increaseSelectionListLevelUnorderedEv
     423__ZN7WebCore6Editor35setIgnoreCompositionSelectionChangeEb
    425424__ZN7WebCore6Editor3cutEv
     425__ZN7WebCore6Editor44confirmCompositionWithoutDisturbingSelectionEv
    426426__ZN7WebCore6Editor4copyEv
    427427__ZN7WebCore6Editor5pasteEv
     
    649649__ZNK7WebCore6Editor17shouldDeleteRangeEPNS_5RangeE
    650650__ZNK7WebCore6Editor22selectionStartHasStyleEPNS_19CSSStyleDeclarationE
     651__ZNK7WebCore6Editor23getCompositionSelectionERjS1_
    651652__ZNK7WebCore6Editor6canCutEv
    652653__ZNK7WebCore6Editor7canCopyEv
  • trunk/WebCore/bridge/EditorClient.h

    r25345 r25547  
    120120
    121121#if PLATFORM(MAC)
    122     virtual void markedTextAbandoned(Frame*) = 0;
    123 
    124122    // FIXME: This should become SelectionController::toWebArchive()
    125123    virtual NSData* dataForArchivedSelection(Frame*) = 0;
  • trunk/WebCore/dom/Range.cpp

    r24041 r25547  
    11/**
    2  * This file is part of the DOM implementation for KDE.
    3  *
    42 * (C) 1999 Lars Knoll (knoll@kde.org)
    53 * (C) 2000 Gunnstein Lye (gunnstein@netcom.no)
    64 * (C) 2000 Frederik Holljen (frederik.holljen@hig.no)
    75 * (C) 2001 Peter Kelly (pmk@post.com)
    8  * Copyright (C) 2004 Apple Computer, Inc.
     6 * Copyright (C) 2004, 2005, 2006, 2007 Apple Inc. All rights reserved.
    97 *
    108 * This library is free software; you can redistribute it and/or
     
    4240namespace WebCore {
    4341
     42using namespace std;
    4443using namespace HTMLNames;
    4544
     
    10321031String Range::toString(ExceptionCode& ec) const
    10331032{
    1034     return toString(false, ec);
    1035 }
    1036 
    1037 String Range::toString(bool convertBRsToNewlines, ExceptionCode& ec) const
    1038 {
    10391033    if (m_detached) {
    10401034        ec = INVALID_STATE_ERR;
     
    10421036    }
    10431037
    1044     String text = "";
    1045     Node *pastEnd = pastEndNode();
    1046     for (Node *n = startNode(); n != pastEnd; n = n->traverseNextNode()) {
     1038    Vector<UChar> result;
     1039
     1040    Node* pastEnd = pastEndNode();
     1041    for (Node* n = startNode(); n != pastEnd; n = n->traverseNextNode()) {
    10471042        if (n->nodeType() == Node::TEXT_NODE || n->nodeType() == Node::CDATA_SECTION_NODE) {
    1048             String str = static_cast<Text *>(n)->data().copy();
    1049             if (n == m_endContainer)
    1050                 str.truncate(m_endOffset);
    1051             if (n == m_startContainer)
    1052                 str.remove(0, m_startOffset);
    1053             text += str;
    1054         }
    1055         if (n->hasTagName(brTag) && convertBRsToNewlines)
    1056             text += "\n";
    1057     }
    1058     return text;
     1043            String data = static_cast<CharacterData*>(n)->data();
     1044            unsigned length = data.length();
     1045            unsigned start = (n == m_startContainer) ? min(m_startOffset, length) : 0;
     1046            unsigned end = (n == m_endContainer) ? min(max(start, m_endOffset), length) : length;
     1047            result.append(data.characters() + start, end - start);
     1048        }
     1049    }
     1050
     1051    return String::adopt(result);
    10591052}
    10601053
     
    15311524Node *Range::pastEndNode() const
    15321525{
    1533     if (!m_endContainer)
     1526    if (!m_startContainer || !m_endContainer)
    15341527        return 0;
    15351528    if (m_endContainer->offsetInCharacters())
  • trunk/WebCore/dom/Range.h

    r24041 r25547  
    8080    void insertNode(PassRefPtr<Node>, ExceptionCode&);
    8181    String toString(ExceptionCode&) const;
    82     String toString(bool convertBRsToNewlines, ExceptionCode&) const;
    8382
    8483    String toHTML() const;
  • trunk/WebCore/editing/Editor.cpp

    r25305 r25547  
    6565#include "SelectionController.h"
    6666#include "Sound.h"
     67#include "Text.h"
    6768#include "TextIterator.h"
    6869#include "TypingCommand.h"
     
    7475
    7576class FontData;
     77
     78using namespace std;
    7679using namespace EventNames;
    7780using namespace HTMLNames;
     
    13551358    : m_frame(frame)
    13561359    , m_deleteButtonController(new DeleteButtonController(frame))
    1357     , m_ignoreMarkedTextSelectionChange(false)
     1360    , m_ignoreCompositionSelectionChange(false)
    13581361{
    13591362}
     
    13611364Editor::~Editor()
    13621365{
     1366}
     1367
     1368void Editor::clear()
     1369{
     1370    m_compositionNode = 0;
     1371    m_customCompositionUnderlines.clear();
    13631372}
    13641373
     
    13961405        return false;
    13971406
    1398     RefPtr<Range> range = m_frame->markedTextRange();
    1399     if (!range) {
    1400         Selection selection = selectionForEvent(m_frame, triggeringEvent);
    1401         if (!selection.isContentEditable())
    1402             return false;
    1403         range = selection.toRange();
    1404     }
    1405 
    1406     if (!shouldInsertText(text, range.get(), EditorInsertActionTyped)) {
    1407         discardMarkedText();
     1407    Selection selection = selectionForEvent(m_frame, triggeringEvent);
     1408    if (!selection.isContentEditable())
     1409        return false;
     1410    RefPtr<Range> range = selection.toRange();
     1411
     1412    if (!shouldInsertText(text, range.get(), EditorInsertActionTyped))
    14081413        return true;
    1409     }
    1410 
    1411     setIgnoreMarkedTextSelectionChange(true);
    1412 
    1413     // If we had marked text, replace that instead of the selection/caret.
    1414     selectMarkedText();
    14151414
    14161415    // Get the selection to use for the event that triggered this insertText.
    14171416    // If the event handler changed the selection, we may want to use a different selection
    14181417    // that is contained in the event target.
    1419     Selection selection = selectionForEvent(m_frame, triggeringEvent);
     1418    selection = selectionForEvent(m_frame, triggeringEvent);
    14201419    if (selection.isContentEditable()) {
    14211420        if (Node* selectionStart = selection.start().node()) {
     
    14311430        }
    14321431    }
    1433 
    1434     setIgnoreMarkedTextSelectionChange(false);
    1435 
    1436     // Inserting unmarks any marked text.
    1437     unmarkText();
    14381432
    14391433    return true;
     
    16651659}
    16661660
    1667 void Editor::selectMarkedText()
    1668 {
    1669     Range* range = m_frame->markedTextRange();
     1661void Editor::selectComposition()
     1662{
     1663    RefPtr<Range> range = compositionRange();
    16701664    if (!range)
    16711665        return;
    16721666    ExceptionCode ec = 0;
    1673     m_frame->selectionController()->setSelectedRange(m_frame->markedTextRange(), DOWNSTREAM, false, ec);
    1674 }
    1675 
    1676 void Editor::discardMarkedText()
    1677 {
    1678     if (!m_frame->markedTextRange())
    1679         return;
    1680 
    1681     setIgnoreMarkedTextSelectionChange(true);
    1682 
    1683     selectMarkedText();
    1684     unmarkText();
    1685 #if PLATFORM(MAC)
    1686     if (EditorClient* c = client())
    1687         c->markedTextAbandoned(m_frame);
    1688 #endif
     1667    m_frame->selectionController()->setSelectedRange(range.get(), DOWNSTREAM, false, ec);
     1668}
     1669
     1670void Editor::confirmComposition()
     1671{
     1672    if (!m_compositionNode)
     1673        return;
     1674    confirmComposition(m_compositionNode->data().substring(m_compositionStart, m_compositionEnd - m_compositionStart), false);
     1675}
     1676
     1677void Editor::confirmCompositionWithoutDisturbingSelection()
     1678{
     1679    if (!m_compositionNode)
     1680        return;
     1681    confirmComposition(m_compositionNode->data().substring(m_compositionStart, m_compositionEnd - m_compositionStart), true);
     1682}
     1683
     1684void Editor::confirmComposition(const String& text)
     1685{
     1686    confirmComposition(text, false);
     1687}
     1688
     1689void Editor::confirmComposition(const String& text, bool preserveSelection)
     1690{
     1691    setIgnoreCompositionSelectionChange(true);
     1692
     1693    Selection oldSelection = m_frame->selectionController()->selection();
     1694
     1695    selectComposition();
     1696
     1697    if (m_frame->selectionController()->isNone()) {
     1698        setIgnoreCompositionSelectionChange(false);
     1699        return;
     1700    }
     1701
    16891702    deleteSelectionWithSmartDelete(false);
    16901703
    1691     setIgnoreMarkedTextSelectionChange(false);
    1692 }
    1693 
    1694 void Editor::unmarkText()
    1695 {
    1696     Vector<MarkedTextUnderline> underlines;
    1697     m_frame->setMarkedTextRange(0, underlines);
    1698 }
    1699 
    1700 void Editor::replaceMarkedText(const String& text)
    1701 {
    1702     if (m_frame->selectionController()->isNone())
    1703         return;
    1704    
    1705     int exception = 0;
    1706    
    1707     Range *markedTextRange = m_frame->markedTextRange();
    1708     if (markedTextRange && !markedTextRange->collapsed(exception))
    1709         TypingCommand::deleteKeyPressed(m_frame->document(), false);
    1710    
    1711     if (!text.isEmpty())
    1712         TypingCommand::insertText(m_frame->document(), text, true);
    1713    
    1714     revealSelectionAfterEditingOperation();
     1704    m_compositionNode = 0;
     1705    m_customCompositionUnderlines.clear();
     1706
     1707    insertText(text, 0);
     1708
     1709    if (preserveSelection)
     1710        m_frame->selectionController()->setSelection(oldSelection, false, false);
     1711
     1712    setIgnoreCompositionSelectionChange(false);
     1713}
     1714
     1715void Editor::setComposition(const String& text, const Vector<CompositionUnderline>& underlines, unsigned selectionStart, unsigned selectionEnd)
     1716{
     1717    setIgnoreCompositionSelectionChange(true);
     1718
     1719    selectComposition();
     1720
     1721    if (m_frame->selectionController()->isNone()) {
     1722        setIgnoreCompositionSelectionChange(false);
     1723        return;
     1724    }
     1725
     1726    deleteSelectionWithSmartDelete(false);
     1727
     1728    if (!text.isEmpty()) {
     1729        TypingCommand::insertText(m_frame->document(), text, true, true);
     1730
     1731        Node* baseNode = m_frame->selectionController()->baseNode();
     1732        unsigned baseOffset = m_frame->selectionController()->base().offset();
     1733        Node* extentNode = m_frame->selectionController()->extentNode();
     1734        unsigned extentOffset = m_frame->selectionController()->extent().offset();
     1735
     1736        if (baseNode && baseNode == extentNode && baseNode->isTextNode() && baseOffset + text.length() == extentOffset) {
     1737            m_compositionNode = static_cast<Text*>(baseNode);
     1738            m_compositionStart = baseOffset;
     1739            m_compositionEnd = extentOffset;
     1740            m_customCompositionUnderlines = underlines;
     1741            size_t numUnderlines = m_customCompositionUnderlines.size();
     1742            for (size_t i = 0; i < numUnderlines; ++i) {
     1743                m_customCompositionUnderlines[i].startOffset += baseOffset;
     1744                m_customCompositionUnderlines[i].endOffset += baseOffset;
     1745            }
     1746            if (baseNode->renderer())
     1747                baseNode->renderer()->repaint();
     1748
     1749            unsigned start = min(baseOffset + selectionStart, extentOffset);
     1750            unsigned end = min(max(start, baseOffset + selectionEnd), extentOffset);
     1751            RefPtr<Range> selectedRange = new Range(baseNode->document(), baseNode, start, baseNode, end);               
     1752            ExceptionCode ec = 0;
     1753            m_frame->selectionController()->setSelectedRange(selectedRange.get(), DOWNSTREAM, false, ec);
     1754        }
     1755    }
     1756
     1757    setIgnoreCompositionSelectionChange(false);
    17151758}
    17161759
     
    22702313#endif
    22712314}
    2272    
    2273    
     2315
    22742316PassRefPtr<Range> Editor::rangeForPoint(const IntPoint& windowPoint)
    22752317{
     
    22902332void Editor::revealSelectionAfterEditingOperation()
    22912333{
    2292     if (m_ignoreMarkedTextSelectionChange)
     2334    if (m_ignoreCompositionSelectionChange)
    22932335        return;
    22942336
     
    22962338}
    22972339
    2298 void Editor::setIgnoreMarkedTextSelectionChange(bool ignore)
    2299 {
    2300     if (m_ignoreMarkedTextSelectionChange == ignore)
    2301         return;
    2302 
    2303     m_ignoreMarkedTextSelectionChange = ignore;
     2340void Editor::setIgnoreCompositionSelectionChange(bool ignore)
     2341{
     2342    if (m_ignoreCompositionSelectionChange == ignore)
     2343        return;
     2344
     2345    m_ignoreCompositionSelectionChange = ignore;
    23042346    if (!ignore)
    23052347        revealSelectionAfterEditingOperation();
    23062348}
    23072349
     2350PassRefPtr<Range> Editor::compositionRange() const
     2351{
     2352    if (!m_compositionNode)
     2353        return 0;
     2354    unsigned length = m_compositionNode->length();
     2355    unsigned start = min(m_compositionStart, length);
     2356    unsigned end = min(max(start, m_compositionEnd), length);
     2357    if (start >= end)
     2358        return 0;
     2359    return new Range(m_compositionNode->document(), m_compositionNode.get(), start, m_compositionNode.get(), end);
     2360}
     2361
     2362bool Editor::getCompositionSelection(unsigned& selectionStart, unsigned& selectionEnd) const
     2363{
     2364    if (!m_compositionNode)
     2365        return false;
     2366    Position start = m_frame->selectionController()->start();
     2367    if (start.node() != m_compositionNode)
     2368        return false;
     2369    Position end = m_frame->selectionController()->end();
     2370    if (end.node() != m_compositionNode)
     2371        return false;
     2372
     2373    if (static_cast<unsigned>(start.offset()) < m_compositionStart)
     2374        return false;
     2375    if (static_cast<unsigned>(end.offset()) > m_compositionEnd)
     2376        return false;
     2377
     2378    selectionStart = start.offset() - m_compositionStart;
     2379    selectionEnd = start.offset() - m_compositionEnd;
     2380    return true;
     2381}
     2382
    23082383} // namespace WebCore
  • trunk/WebCore/editing/Editor.h

    r25027 r25547  
    5757class Selection;
    5858
     59struct CompositionUnderline {
     60    CompositionUnderline()
     61        : startOffset(0), endOffset(0), thick(false) { }
     62    CompositionUnderline(unsigned s, unsigned e, const Color& c, bool t)
     63        : startOffset(s), endOffset(e), color(c), thick(t) { }
     64    unsigned startOffset;
     65    unsigned endOffset;
     66    Color color;
     67    bool thick;
     68};
     69
    5970class Editor {
    6071public:
     
    194205    bool smartInsertDeleteEnabled();
    195206   
    196     void selectMarkedText();
    197     void unmarkText();
    198     void discardMarkedText();
    199     void replaceMarkedText(const String&);
    200 
    201     bool ignoreMarkedTextSelectionChange() const { return m_ignoreMarkedTextSelectionChange; }
    202     void setIgnoreMarkedTextSelectionChange(bool ignore);
     207    // international text input composition
     208    bool hasComposition() const { return m_compositionNode; }
     209    void setComposition(const String&, const Vector<CompositionUnderline>&, unsigned selectionStart, unsigned selectionEnd);
     210    void confirmComposition();
     211    void confirmComposition(const String&); // if no existing composition, replaces selection
     212    void confirmCompositionWithoutDisturbingSelection();
     213    PassRefPtr<Range> compositionRange() const;
     214    bool getCompositionSelection(unsigned& selectionStart, unsigned& selectionEnd) const;
     215
     216    // getting international text input composition state (for use by InlineTextBox)
     217    Text* compositionNode() const { return m_compositionNode.get(); }
     218    unsigned compositionStart() const { return m_compositionStart; }
     219    unsigned compositionEnd() const { return m_compositionEnd; }
     220    bool compositionUsesCustomUnderlines() const { return !m_customCompositionUnderlines.isEmpty(); }
     221    const Vector<CompositionUnderline>& customCompositionUnderlines() const { return m_customCompositionUnderlines; }
     222
     223    bool ignoreCompositionSelectionChange() const { return m_ignoreCompositionSelectionChange; }
     224
     225    void setStartNewKillRingSequence(bool);
    203226
    204227#if PLATFORM(MAC)
    205228    NSString* userVisibleString(NSURL*);
    206     void setStartNewKillRingSequence(bool flag) { m_startNewKillRingSequence = flag; }
    207 #else
    208     void setStartNewKillRingSequence(bool) { }
    209229#endif
    210230
    211231    PassRefPtr<Range> rangeForPoint(const IntPoint& windowPoint);
     232
     233    void clear();
    212234
    213235private:
     
    216238    RefPtr<EditCommand> m_lastEditCommand;
    217239    RefPtr<Node> m_removedAnchor;
    218     bool m_ignoreMarkedTextSelectionChange;
     240
     241    RefPtr<Text> m_compositionNode;
     242    unsigned m_compositionStart;
     243    unsigned m_compositionEnd;
     244    Vector<CompositionUnderline> m_customCompositionUnderlines;
     245    bool m_ignoreCompositionSelectionChange;
    219246
    220247    bool canDeleteRange(Range*) const;
     
    230257    void revealSelectionAfterEditingOperation();
    231258
    232 #if PLATFORM(MAC)
     259    void selectComposition();
     260    void confirmComposition(const String&, bool preserveSelection);
     261    void setIgnoreCompositionSelectionChange(bool ignore);
     262
    233263    void addToKillRing(Range*, bool prepend);
     264
     265#if PLATFORM(MAC)
    234266    bool m_startNewKillRingSequence;
     267#endif
     268};
     269
     270#if PLATFORM(MAC)
     271
     272inline void Editor::setStartNewKillRingSequence(bool flag)
     273{
     274    m_startNewKillRingSequence = flag;
     275}
     276
    235277#else
    236     void addToKillRing(Range*, bool) { }
    237 #endif
    238 
    239 };
     278
     279inline void Editor::setStartNewKillRingSequence(bool) { }
     280inline void Editor::addToKillRing(Range*, bool) { }
     281
     282#endif
    240283
    241284} // namespace WebCore
  • trunk/WebCore/editing/TypingCommand.cpp

    r25115 r25547  
    9494}
    9595
    96 void TypingCommand::insertText(Document* document, const String& text, bool selectInsertedText)
     96void TypingCommand::insertText(Document* document, const String& text, bool selectInsertedText, bool insertedTextIsComposition)
    9797{
    9898    ASSERT(document);
     
    101101    ASSERT(frame);
    102102
    103     insertText(document, text, frame->selectionController()->selection(), selectInsertedText);
    104 }
    105 
    106 void TypingCommand::insertText(Document* document, const String& text, const Selection& selectionForInsertion, bool selectInsertedText)
     103    insertText(document, text, frame->selectionController()->selection(), selectInsertedText, insertedTextIsComposition);
     104}
     105
     106void TypingCommand::insertText(Document* document, const String& text, const Selection& selectionForInsertion, bool selectInsertedText, bool insertedTextIsComposition)
    107107{
    108108    ASSERT(document);
     
    117117    Node* startNode = selectionForInsertion.start().node();
    118118   
    119     if (startNode && startNode->rootEditableElement()) {       
     119    if (startNode && startNode->rootEditableElement() && !insertedTextIsComposition) {       
    120120        // Send BeforeTextInsertedEvent. The event handler will update text if necessary.
    121121        ExceptionCode ec = 0;
  • trunk/WebCore/editing/TypingCommand.h

    r25115 r25547  
    4646    static void deleteKeyPressed(Document*, bool smartDelete = false, TextGranularity = CharacterGranularity);
    4747    static void forwardDeleteKeyPressed(Document*, bool smartDelete = false, TextGranularity = CharacterGranularity);
    48     static void insertText(Document*, const String&, bool selectInsertedText = false);
    49     static void insertText(Document*, const String&, const Selection&, bool selectInsertedText = false);
     48    static void insertText(Document*, const String&, bool selectInsertedText = false, bool insertedTextIsComposition = false);
     49    static void insertText(Document*, const String&, const Selection&, bool selectInsertedText = false, bool insertedTextIsComposition = false);
    5050    static void insertLineBreak(Document*);
    5151    static void insertParagraphSeparator(Document*);
  • trunk/WebCore/loader/FrameLoader.cpp

    r25439 r25547  
    774774    // urlsBridgeKnowsAbout.clear();
    775775
    776 #if PLATFORM(MAC)
    777     m_frame->setMarkedTextRange(0, nil, nil);
    778 #endif
     776    m_frame->editor()->clear();
    779777
    780778    if (!m_needsClear)
  • trunk/WebCore/page/ContextMenuController.cpp

    r24422 r25547  
    5454#include "SelectionController.h"
    5555#include "Settings.h"
     56#include "TextIterator.h"
    5657#include "markup.h"
    5758
     
    231232                selectedRange->selectNode(document->documentElement(), ec);
    232233            }
    233             m_client->speak(selectedRange->toString(true, ec));
     234            m_client->speak(plainText(selectedRange.get()));
    234235            break;
    235236        }
  • trunk/WebCore/page/Frame.cpp

    r25397 r25547  
    308308}
    309309
    310 Range* Frame::markedTextRange() const
    311 {
    312     return d->m_markedTextRange.get();
    313 }
    314 
    315 
    316310IntRect Frame::firstRectForRange(Range* range) const
    317311{
     
    338332                   startCaretRect.width() + extraWidthToEndOfLine,
    339333                   startCaretRect.height());
    340 }
    341 
    342 void Frame::setMarkedTextRange(Range* range, Vector<MarkedTextUnderline>& markedRangeDecorations)
    343 {
    344     int exception = 0;
    345    
    346     ASSERT(!range || range->startContainer(exception) == range->endContainer(exception));
    347     ASSERT(!range || range->collapsed(exception) || range->startContainer(exception)->isTextNode());
    348    
    349     d->m_markedTextUnderlines.clear();
    350     if (markedRangeDecorations.size()) {
    351         d->m_markedTextUsesUnderlines = true;
    352         d->m_markedTextUnderlines = markedRangeDecorations;
    353     } else
    354         d->m_markedTextUsesUnderlines = false;
    355    
    356     if (d->m_markedTextRange.get() && document() && d->m_markedTextRange->startContainer(exception)->renderer())
    357         d->m_markedTextRange->startContainer(exception)->renderer()->repaint();
    358    
    359     if (range && range->collapsed(exception))
    360         d->m_markedTextRange = 0;
    361     else
    362         d->m_markedTextRange = range;
    363    
    364     if (d->m_markedTextRange.get() && document() && d->m_markedTextRange->startContainer(exception)->renderer())
    365         d->m_markedTextRange->startContainer(exception)->renderer()->repaint();   
    366 }
    367 
    368 void Frame::selectRangeInMarkedText(unsigned selOffset, unsigned selLength)
    369 {
    370     ExceptionCode ec = 0;
    371    
    372     RefPtr<Range> selectedRange = document()->createRange();
    373     Range* markedTextRange = this->markedTextRange();
    374    
    375     ASSERT(markedTextRange->startContainer(ec) == markedTextRange->endContainer(ec));
    376     ASSERT(!ec);
    377     unsigned selectionStart = markedTextRange->startOffset(ec) + selOffset;
    378     unsigned selectionEnd = selectionStart + selLength;
    379     ASSERT(!ec);
    380    
    381     selectedRange->setStart(markedTextRange->startContainer(ec), selectionStart, ec);
    382     ASSERT(!ec);
    383     selectedRange->setEnd(markedTextRange->startContainer(ec), selectionEnd, ec);
    384     ASSERT(!ec);
    385    
    386     selectionController()->setSelectedRange(selectedRange.get(), DOWNSTREAM, false, ec);
    387334}
    388335
     
    16591606}
    16601607
    1661 bool Frame::markedTextUsesUnderlines() const
    1662 {
    1663     return d->m_markedTextUsesUnderlines;
    1664 }
    1665 
    1666 const Vector<MarkedTextUnderline>& Frame::markedTextUnderlines() const
    1667 {
    1668     return d->m_markedTextUnderlines;
    1669 }
    1670 
    16711608static bool isInShadowTree(Node* node)
    16721609{
     
    20161953    , m_userStyleSheetLoader(0)
    20171954    , m_paintRestriction(PaintRestrictionNone)
    2018     , m_markedTextUsesUnderlines(false)
    20191955    , m_highlightTextMatches(false)
    20201956    , m_windowHasFocus(false)
  • trunk/WebCore/page/Frame.h

    r25000 r25547  
    108108template <typename T> class Timer;
    109109
    110 struct MarkedTextUnderline {
    111     MarkedTextUnderline()
    112         : startOffset(0), endOffset(0), thick(false) { }
    113     MarkedTextUnderline(unsigned s, unsigned e, const Color& c, bool t)
    114         : startOffset(s), endOffset(e), color(c), thick(t) { }
    115     unsigned startOffset;
    116     unsigned endOffset;
    117     Color color;
    118     bool thick;
    119 };
    120 
    121110class Frame : public Shared<Frame> {
    122111public:
     
    281270    void removeEditingStyleFromElement(Element*) const;
    282271
    283     Range* markedTextRange() const;
    284272    IntRect firstRectForRange(Range*) const;
    285273   
     
    293281    RenderStyle* styleForSelectionStart(Node*& nodeToRemove) const;
    294282
    295     const Vector<MarkedTextUnderline>& markedTextUnderlines() const; 
    296     bool markedTextUsesUnderlines() const;
    297     void setMarkedTextRange(Range* , Vector<MarkedTextUnderline>&);
    298     void selectRangeInMarkedText(unsigned selOffset, unsigned selLength);
    299  
    300283    unsigned markAllMatchesForText(const String&, bool caseFlag, unsigned limit);
    301284    bool markedTextMatchesAreHighlighted() const;
     
    391374    NSWritingDirection baseWritingDirectionForSelectionStart() const;
    392375
    393     void setMarkedTextRange(Range* , NSArray* attributes, NSArray* ranges);
    394 
    395376#endif
    396377
  • trunk/WebCore/page/FramePrivate.h

    r24878 r25547  
    111111        PaintRestriction m_paintRestriction;
    112112       
    113         bool m_markedTextUsesUnderlines;
    114         Vector<MarkedTextUnderline> m_markedTextUnderlines;
    115113        bool m_highlightTextMatches;
    116114        bool m_windowHasFocus;
     
    121119
    122120        bool m_prohibitsScrolling;
    123 
    124         RefPtr<Range> m_markedTextRange;
    125121
    126122        // The root object used for objects bound outside the context of a plugin.
  • trunk/WebCore/page/mac/FrameMac.mm

    r25383 r25547  
    527527}
    528528
    529 static void convertAttributesToUnderlines(Vector<MarkedTextUnderline>& result, const Range* markedTextRange, NSArray* attributes, NSArray* ranges)
    530 {
    531     int exception = 0;
    532     int baseOffset = markedTextRange->startOffset(exception);
    533 
    534     unsigned length = [attributes count];
    535     ASSERT([ranges count] == length);
    536 
    537     for (unsigned i = 0; i < length; i++) {
    538         NSNumber* style = [[attributes objectAtIndex:i] objectForKey:NSUnderlineStyleAttributeName];
    539         if (!style)
    540             continue;
    541         NSRange range = [[ranges objectAtIndex:i] rangeValue];
    542         NSColor* color = [[attributes objectAtIndex:i] objectForKey:NSUnderlineColorAttributeName];
    543         Color qColor = Color::black;
    544         if (color)
    545             qColor = colorFromNSColor([color colorUsingColorSpaceName:NSDeviceRGBColorSpace]);
    546 
    547         result.append(MarkedTextUnderline(range.location + baseOffset,
    548                                           range.location + baseOffset + range.length,
    549                                           qColor,
    550                                           [style intValue] > 1));
    551     }
    552 }
    553 
    554 void Frame::setMarkedTextRange(Range* range, NSArray* attributes, NSArray* ranges)
    555 {
    556     int exception;
    557     exception = 0;
    558 
    559     ASSERT(!range || range->startContainer(exception) == range->endContainer(exception));
    560     ASSERT(!range || range->collapsed(exception) || range->startContainer(exception)->isTextNode());
    561 
    562     Vector<MarkedTextUnderline> decorations;
    563     if (attributes)
    564         convertAttributesToUnderlines(decorations, range, attributes, ranges);
    565    
    566     setMarkedTextRange(range, decorations);
    567 }
    568 
    569529NSMutableDictionary* Frame::dashboardRegionsDictionary()
    570530{
  • trunk/WebCore/page/mac/WebCoreFrameBridge.h

    r25283 r25547  
    169169- (DOMRange *)markDOMRange;
    170170
    171 // international text input "marked text"
    172 - (void)setMarkedTextDOMRange:(DOMRange *)range customAttributes:(NSArray *)attributes ranges:(NSArray *)ranges;
    173 - (DOMRange *)markedTextDOMRange;
    174 
    175171- (NSFont *)fontForSelection:(BOOL *)hasMultipleFonts;
    176172- (NSWritingDirection)baseWritingDirectionForSelectionStart;
  • trunk/WebCore/page/mac/WebCoreFrameBridge.mm

    r25169 r25547  
    7777#import "SubresourceLoader.h"
    7878#import "SystemTime.h"
     79#import "Text.h"
    7980#import "TextEncoding.h"
    8081#import "TextIterator.h"
     
    936937}
    937938
    938 - (void)setMarkedTextDOMRange:(DOMRange *)range customAttributes:(NSArray *)attributes ranges:(NSArray *)ranges
    939 {
    940     m_frame->setMarkedTextRange([range _range], attributes, ranges);
    941 }
    942 
    943 - (DOMRange *)markedTextDOMRange
    944 {
    945     return [DOMRange _wrapRange:m_frame->markedTextRange()];
    946 }
    947 
    948939- (NSRange)markedTextNSRange
    949940{
    950     return [self convertToNSRange:m_frame->markedTextRange()];
     941    return [self convertToNSRange:m_frame->editor()->compositionRange().get()];
    951942}
    952943
  • trunk/WebCore/platform/CharacterNames.h

    r24740 r25547  
    4242    const UChar leftToRightMark = 0x200E;
    4343    const UChar leftToRightOverride = 0x202D;
     44    const UChar newlineCharacter = 0x000A;
    4445    const UChar noBreakSpace = 0x00A0;
    4546    const UChar objectReplacementCharacter = 0xFFFC;
  • trunk/WebCore/rendering/InlineTextBox.cpp

    r24887 r25547  
    2525
    2626#include "Document.h"
     27#include "Editor.h"
    2728#include "Frame.h"
    2829#include "GraphicsContext.h"
    2930#include "HitTestResult.h"
    30 #include "Range.h"
    3131#include "RenderArena.h"
    3232#include "RenderBlock.h"
     33#include "Text.h"
    3334#include "TextStyle.h"
    3435#include "break_lines.h"
     
    252253        return;
    253254
    254     // Determine whether or not we have marked text.
    255     Range* markedTextRange = object()->document()->frame()->markedTextRange();
    256     int exception = 0;
    257     bool haveMarkedText = markedTextRange && markedTextRange->startContainer(exception) == object()->node();
    258     bool markedTextUsesUnderlines = object()->document()->frame()->markedTextUsesUnderlines();
     255    // Determine whether or not we have composition underlines to draw.
     256    bool containsComposition = object()->document()->frame()->editor()->compositionNode() == object()->node();
     257    bool useCustomUnderlines = containsComposition && object()->document()->frame()->editor()->compositionUsesCustomUnderlines();
    259258
    260259    // Set our font.
     
    265264        paintInfo.context->setFont(*font);
    266265
    267     // 1. Paint backgrounds behind text if needed.  Examples of such backgrounds include selection
    268     // and marked text.
     266    // 1. Paint backgrounds behind text if needed. Examples of such backgrounds include selection
     267    // and composition underlines.
    269268    if (paintInfo.phase != PaintPhaseSelection && !isPrinting) {
    270269#if PLATFORM(MAC)
     
    274273#endif
    275274
    276         if (haveMarkedText  && !markedTextUsesUnderlines)
    277             paintMarkedTextBackground(paintInfo.context, tx, ty, styleToUse, font, markedTextRange->startOffset(exception), markedTextRange->endOffset(exception));
     275        if (containsComposition && !useCustomUnderlines)
     276            paintCompositionBackground(paintInfo.context, tx, ty, styleToUse, font,
     277                object()->document()->frame()->editor()->compositionStart(),
     278                object()->document()->frame()->editor()->compositionEnd());
    278279
    279280        paintDocumentMarkers(paintInfo.context, tx, ty, styleToUse, font, true);
    280281
    281         if (haveSelection && !markedTextUsesUnderlines)
     282        if (haveSelection && !useCustomUnderlines)
    282283            paintSelection(paintInfo.context, tx, ty, styleToUse, font);
    283284    }
     
    286287    if (m_len <= 0)
    287288        return;
    288 
    289     const Vector<MarkedTextUnderline>* underlines = 0;
    290     size_t numUnderlines = 0;
    291     if (haveMarkedText && markedTextUsesUnderlines) {
    292         underlines = &object()->document()->frame()->markedTextUnderlines();
    293         numUnderlines = underlines->size();
    294     }
    295289
    296290    Color textFillColor;
     
    433427        paintDocumentMarkers(paintInfo.context, tx, ty, styleToUse, font, false);
    434428
    435         for (size_t index = 0; index < numUnderlines; ++index) {
    436             const MarkedTextUnderline& underline = (*underlines)[index];
    437 
    438             if (underline.endOffset <= start())
    439                 // underline is completely before this run.  This might be an underline that sits
    440                 // before the first run we draw, or underlines that were within runs we skipped
    441                 // due to truncation.
    442                 continue;
    443            
    444             if (underline.startOffset <= end()) {
    445                 // underline intersects this run.  Paint it.
    446                 paintMarkedTextUnderline(paintInfo.context, tx, ty, underline);
    447                 if (underline.endOffset > end() + 1)
    448                     // underline also runs into the next run. Bail now, no more marker advancement.
     429        if (useCustomUnderlines) {
     430            const Vector<CompositionUnderline>& underlines = object()->document()->frame()->editor()->customCompositionUnderlines();
     431            size_t numUnderlines = underlines.size();
     432
     433            for (size_t index = 0; index < numUnderlines; ++index) {
     434                const CompositionUnderline& underline = underlines[index];
     435
     436                if (underline.endOffset <= start())
     437                    // underline is completely before this run.  This might be an underline that sits
     438                    // before the first run we draw, or underlines that were within runs we skipped
     439                    // due to truncation.
     440                    continue;
     441               
     442                if (underline.startOffset <= end()) {
     443                    // underline intersects this run.  Paint it.
     444                    paintCompositionUnderline(paintInfo.context, tx, ty, underline);
     445                    if (underline.endOffset > end() + 1)
     446                        // underline also runs into the next run. Bail now, no more marker advancement.
     447                        break;
     448                } else
     449                    // underline is completely after this run, bail.  A later run will paint it.
    449450                    break;
    450             } else
    451                 // underline is completely after this run, bail.  A later run will paint it.
    452                 break;
     451            }
    453452        }
    454453    }
     
    508507}
    509508
    510 void InlineTextBox::paintMarkedTextBackground(GraphicsContext* p, int tx, int ty, RenderStyle* style, const Font* f, int startPos, int endPos)
     509void InlineTextBox::paintCompositionBackground(GraphicsContext* p, int tx, int ty, RenderStyle* style, const Font* f, int startPos, int endPos)
    511510{
    512511    int offset = m_start;
     
    727726
    728727
    729 void InlineTextBox::paintMarkedTextUnderline(GraphicsContext* ctx, int tx, int ty, const MarkedTextUnderline& underline)
     728void InlineTextBox::paintCompositionUnderline(GraphicsContext* ctx, int tx, int ty, const CompositionUnderline& underline)
    730729{
    731730    tx += m_x;
  • trunk/WebCore/rendering/InlineTextBox.h

    r24887 r25547  
    3737class String;
    3838class StringImpl;
    39 class MarkedTextUnderline;
    4039class HitTestResult;
    4140class Position;
     41
     42struct CompositionUnderline;
    4243
    4344class InlineTextBox : public InlineRunBox {
     
    9596    void paintDecoration(GraphicsContext*, int tx, int ty, int decoration);
    9697    void paintSelection(GraphicsContext*, int tx, int ty, RenderStyle*, const Font*);
    97     void paintMarkedTextBackground(GraphicsContext*, int tx, int ty, RenderStyle*, const Font*, int startPos, int endPos);
     98    void paintCompositionBackground(GraphicsContext*, int tx, int ty, RenderStyle*, const Font*, int startPos, int endPos);
    9899    void paintDocumentMarkers(GraphicsContext*, int tx, int ty, RenderStyle*, const Font*, bool background);
    99100    void paintSpellingOrGrammarMarker(GraphicsContext*, int tx, int ty, DocumentMarker, RenderStyle*, const Font*, bool grammar);
    100101    void paintTextMatchMarker(GraphicsContext*, int tx, int ty, DocumentMarker, RenderStyle*, const Font*);
    101     void paintMarkedTextUnderline(GraphicsContext*, int tx, int ty, const MarkedTextUnderline&);
     102    void paintCompositionUnderline(GraphicsContext*, int tx, int ty, const CompositionUnderline&);
    102103#if PLATFORM(MAC)
    103104    void paintCustomHighlight(int tx, int ty, const AtomicString& type);
  • trunk/WebCore/rendering/RenderTextControl.cpp

    r25245 r25547  
    11/**
    2  * Copyright (C) 2006, 2007 Apple Inc.
     2 * Copyright (C) 2006, 2007 Apple Inc. All rights reserved.
    33 *
    44 * This library is free software; you can redistribute it and/or
     
    2222#include "RenderTextControl.h"
    2323
     24#include "CharacterNames.h"
    2425#include "Document.h"
    2526#include "Editor.h"
     
    4142#include "SelectionController.h"
    4243#include "Settings.h"
     44#include "Text.h"
    4345#include "TextIterator.h"
    4446#include "TextStyle.h"
     
    547549}
    548550
     551String RenderTextControl::finishText(Vector<UChar>& result) const
     552{
     553    UChar symbol = backslashAsCurrencySymbol();
     554    if (symbol != '\\') {
     555        size_t size = result.size();
     556        for (size_t i = 0; i < size; ++i)
     557            if (result[i] == '\\')
     558                result[i] = symbol;
     559    }
     560
     561    return String::adopt(result);
     562}
     563
    549564String RenderTextControl::text()
    550565{
    551     if (m_innerText)
    552         return m_innerText->textContent().replace('\\', backslashAsCurrencySymbol());
    553     return String();
     566    if (!m_innerText)
     567        return "";
     568 
     569    Frame* frame = document()->frame();
     570    Text* compositionNode = frame ? frame->editor()->compositionNode() : 0;
     571
     572    Vector<UChar> result;
     573
     574    for (Node* n = m_innerText.get(); n; n = n->traverseNextNode(m_innerText.get())) {
     575        if (n->isTextNode()) {
     576            Text* text = static_cast<Text*>(n);
     577            String data = text->data();
     578            unsigned length = data.length();
     579            if (text != compositionNode)
     580                result.append(data.characters(), length);
     581            else {
     582                unsigned compositionStart = min(frame->editor()->compositionStart(), length);
     583                unsigned compositionEnd = min(max(compositionStart, frame->editor()->compositionEnd()), length);
     584                result.append(data.characters(), compositionStart);
     585                result.append(data.characters() + compositionEnd, length - compositionEnd);
     586            }
     587        }
     588    }
     589
     590    return finishText(result);
     591}
     592
     593static void getNextSoftBreak(RootInlineBox*& line, Node*& breakNode, unsigned& breakOffset)
     594{
     595    RootInlineBox* next;
     596    for (; line; line = next) {
     597        next = line->nextRootBox();
     598        if (next && !line->endsWithBreak()) {
     599            ASSERT(line->lineBreakObj());
     600            breakNode = line->lineBreakObj()->node();
     601            breakOffset = line->lineBreakPos();
     602            line = next;
     603            return;
     604        }
     605    }
     606    breakNode = 0;
    554607}
    555608
    556609String RenderTextControl::textWithHardLineBreaks()
    557610{
    558     String s("");
    559 
    560     if (!m_innerText || !m_innerText->firstChild())
    561         return s;
     611    if (!m_innerText)
     612        return "";
     613    Node* firstChild = m_innerText->firstChild();
     614    if (!firstChild)
     615        return "";
    562616
    563617    document()->updateLayout();
    564618
    565     RenderObject* renderer = m_innerText->firstChild()->renderer();
     619    RenderObject* renderer = firstChild->renderer();
    566620    if (!renderer)
    567         return s;
     621        return "";
    568622
    569623    InlineBox* box = renderer->inlineBox(0, DOWNSTREAM);
    570624    if (!box)
    571         return s;
    572 
    573     ExceptionCode ec = 0;
    574     RefPtr<Range> range = new Range(document());
    575     range->selectNodeContents(m_innerText.get(), ec);
    576     for (RootInlineBox* line = box->root(); line; line = line->nextRootBox()) {
    577         // If we're at a soft wrap, then insert the hard line break here
    578         if (!line->endsWithBreak() && line->nextRootBox()) {
    579             // Update range so it ends before this wrap
    580             ASSERT(line->lineBreakObj());
    581             range->setEnd(line->lineBreakObj()->node(), line->lineBreakPos(), ec);
    582 
    583             s.append(range->toString(true, ec));
    584             s.append("\n");
    585 
    586             // Update range so it starts after this wrap
    587             range->setEnd(m_innerText.get(), maxDeepOffset(m_innerText.get()), ec);
    588             range->setStart(line->lineBreakObj()->node(), line->lineBreakPos(), ec);
     625        return "";
     626
     627    Frame* frame = document()->frame();
     628    Text* compositionNode = frame ? frame->editor()->compositionNode() : 0;
     629
     630    Node* breakNode;
     631    unsigned breakOffset;
     632    RootInlineBox* line = box->root();
     633    getNextSoftBreak(line, breakNode, breakOffset);
     634
     635    Vector<UChar> result;
     636
     637    for (Node* n = firstChild; n; n = n->traverseNextNode(m_innerText.get())) {
     638        if (n->hasTagName(brTag))
     639            result.append(&newlineCharacter, 1);
     640        else if (n->isTextNode()) {
     641            Text* text = static_cast<Text*>(n);
     642            String data = text->data();
     643            unsigned length = data.length();
     644            unsigned compositionStart = (text == compositionNode)
     645                ? min(frame->editor()->compositionStart(), length) : 0;
     646            unsigned compositionEnd = (text == compositionNode)
     647                ? min(max(compositionStart, frame->editor()->compositionEnd()), length) : 0;
     648            unsigned position = 0;
     649            while (breakNode == n && breakOffset < compositionStart) {
     650                result.append(data.characters() + position, breakOffset - position);
     651                position = breakOffset;
     652                result.append(&newlineCharacter, 1);
     653                getNextSoftBreak(line, breakNode, breakOffset);
     654            }
     655            result.append(data.characters() + position, compositionStart - position);
     656            position = compositionEnd;
     657            while (breakNode == n && breakOffset <= length) {
     658                if (breakOffset > position) {
     659                    result.append(data.characters() + position, breakOffset - position);
     660                    position = breakOffset;
     661                    result.append(&newlineCharacter, 1);
     662                }
     663                getNextSoftBreak(line, breakNode, breakOffset);
     664            }
     665            result.append(data.characters() + position, length - position);
    589666        }
    590     }
    591     s.append(range->toString(true, ec));
    592     ASSERT(!ec);
    593 
    594     return s.replace('\\', backslashAsCurrencySymbol());
     667        while (breakNode == n)
     668            getNextSoftBreak(line, breakNode, breakOffset);
     669    }
     670
     671    return finishText(result);
    595672}
    596673
  • trunk/WebCore/rendering/RenderTextControl.h

    r25245 r25547  
    134134    void startSearchEventTimer();
    135135    void searchEventTimerFired(Timer<RenderTextControl>*);
     136    String finishText(Vector<UChar>&) const;
    136137
    137138    RefPtr<HTMLTextFieldInnerElement> m_innerBlock;
  • trunk/WebKit/ChangeLog

    r25519 r25547  
     12007-09-13  Darin Adler  <darin@apple.com>
     2
     3        Reviewed by Oliver.
     4
     5        - fix <rdar://problem/5470457> REGRESSION: Input method inline hole is mishandled in text
     6          <input> elements with maxlength limit
     7
     8        * WebView/WebHTMLView.mm:
     9        (-[WebHTMLView _selectionChanged]): Tweaked code a bit.
     10        (-[WebHTMLView markedRange]): Simplified logic, since markedTextNSRange works when there's
     11        no composition range.
     12        (-[WebHTMLView hasMarkedText]): Call directly to Editor instead of bridge.
     13        (-[WebHTMLView unmarkText]): Call new confirmComposition to make it clear that this is
     14        confirming text, not just unmarking it to discard it.
     15        (extractUnderlines): Added. Converts directly from an NSAttributedString to the
     16        CompositionUnderline vector that's used by WebCore.
     17        (-[WebHTMLView setMarkedText:selectedRange:]): Changed to use the new setComposition.
     18        (-[WebHTMLView insertText:]): Changed to use confirmComposition when appropriate, instead
     19        of relying on special behavior of Editor::insertText.
     20        (-[WebHTMLView _updateSelectionForInputManager]): Rewrote to use getCompositionSelection
     21        and confirmCompositionWithoutDisturbingSelection.
     22
     23        * WebCoreSupport/WebEditorClient.h:
     24        * WebCoreSupport/WebEditorClient.mm:
     25        Removed obsolete markedTextAbandoned function.
     26 
    1272007-09-12  David Kilzer  <ddkilzer@apple.com>
    228
  • trunk/WebKit/WebCoreSupport/WebEditorClient.h

    r25345 r25547  
    9191    virtual void handleInputMethodKeypress(WebCore::KeyboardEvent*);
    9292
    93     virtual void markedTextAbandoned(WebCore::Frame*);
    94 
    9593    virtual void textFieldDidBeginEditing(WebCore::Element*);
    9694    virtual void textFieldDidEndEditing(WebCore::Element*);
  • trunk/WebKit/WebCoreSupport/WebEditorClient.mm

    r25396 r25547  
    447447}
    448448
    449 void WebEditorClient::markedTextAbandoned(Frame* frame)
    450 {
    451     WebHTMLView *webHTMLView = [[kit(frame) frameView] documentView];
    452     [[NSInputManager currentInputManager] markedTextAbandoned:webHTMLView];
    453 }
    454 
    455449#define FormDelegateLog(ctrl)  LOG(FormDelegate, "control=%@", ctrl)
    456450
  • trunk/WebKit/WebView/WebHTMLView.mm

    r25493 r25547  
    7676#import <WebCore/CachedImage.h>
    7777#import <WebCore/CachedResourceClient.h>
     78#import <WebCore/ColorMac.h>
    7879#import <WebCore/ContextMenu.h>
    7980#import <WebCore/ContextMenuController.h>
     
    102103#import <WebCore/SelectionController.h>
    103104#import <WebCore/SharedBuffer.h>
     105#import <WebCore/Text.h>
    104106#import <WebCore/WebCoreObjCExtras.h>
    105107#import <WebCore/WebCoreTextRenderer.h>
     
    49474949    [self _updateSelectionForInputManager];
    49484950    [self _updateFontPanel];
    4949     if (core([self _frame]))
    4950         core([self _frame])->editor()->setStartNewKillRingSequence(true);
     4951    if (Frame* coreFrame = core([self _frame]))
     4952        coreFrame->editor()->setStartNewKillRingSequence(true);
    49514953}
    49524954
     
    53545356    NSAttributedString *result = [self attributedSubstringFromRange:NSMakeRange(0, UINT_MAX)];
    53555357   
    5356     LOG(TextInput, "textStorage -> \"%s\"", result ? [[result string] UTF8String] : "");
     5358    LOG(TextInput, "textStorage -> \"%@\"", result ? [result string] : @"");
    53575359   
    53585360    // We have to return an empty string rather than null to prevent TSM from calling -string
     
    54245426- (NSRange)markedRange
    54255427{
    5426     if (![self hasMarkedText]) {
    5427         LOG(TextInput, "markedRange -> (NSNotFound, 0)");
    5428         return NSMakeRange(NSNotFound, 0);
    5429     }
    54305428    NSRange result = [[self _bridge] markedTextNSRange];
    5431 
    54325429    LOG(TextInput, "markedRange -> (%u, %u)", result.location, result.length);
    54335430    return result;
     
    54575454        result = [result attributedSubstringFromRange:NSMakeRange(0, nsRange.length)];
    54585455    }
    5459     LOG(TextInput, "attributedSubstringFromRange:(%u, %u) -> \"%s\"", nsRange.location, nsRange.length, [[result string] UTF8String]);
     5456    LOG(TextInput, "attributedSubstringFromRange:(%u, %u) -> \"%@\"", nsRange.location, nsRange.length, [result string]);
    54605457    return result;
    54615458}
     
    54765473- (BOOL)hasMarkedText
    54775474{
    5478     BOOL result = [[self _bridge] markedTextDOMRange] != nil;
    5479 
     5475    Frame* coreFrame = core([self _frame]);
     5476    BOOL result = coreFrame && coreFrame->editor()->hasComposition();
    54805477    LOG(TextInput, "hasMarkedText -> %u", result);
    54815478    return result;
     
    54965493   
    54975494    if (Frame* coreFrame = core([self _frame]))
    5498         coreFrame->editor()->unmarkText();
    5499 }
    5500 
    5501 - (void)_extractAttributes:(NSArray **)a ranges:(NSArray **)r fromAttributedString:(NSAttributedString *)string
     5495        coreFrame->editor()->confirmComposition();
     5496}
     5497
     5498static void extractUnderlines(NSAttributedString *string, Vector<CompositionUnderline>& result)
    55025499{
    55035500    int length = [[string string] length];
     5501
    55045502    int i = 0;
    5505     NSMutableArray *attributes = [NSMutableArray array];
    5506     NSMutableArray *ranges = [NSMutableArray array];
    55075503    while (i < length) {
    5508         NSRange effectiveRange;
    5509         NSDictionary *attrs = [string attributesAtIndex:i longestEffectiveRange:&effectiveRange inRange:NSMakeRange(i,length - i)];
    5510         [attributes addObject:attrs];
    5511         [ranges addObject:[NSValue valueWithRange:effectiveRange]];
    5512         i = effectiveRange.location + effectiveRange.length;
    5513     }
    5514     *a = attributes;
    5515     *r = ranges;
     5504        NSRange range;
     5505        NSDictionary *attrs = [string attributesAtIndex:i longestEffectiveRange:&range inRange:NSMakeRange(i, length - i)];
     5506
     5507        if (NSNumber *style = [attrs objectForKey:NSUnderlineStyleAttributeName]) {
     5508            Color color = Color::black;
     5509            if (NSColor *colorAttr = [attrs objectForKey:NSUnderlineColorAttributeName])
     5510                color = colorFromNSColor([colorAttr colorUsingColorSpaceName:NSDeviceRGBColorSpace]);
     5511            result.append(CompositionUnderline(range.location, NSMaxRange(range), color, [style intValue] > 1));
     5512        }
     5513
     5514        i = range.location + range.length;
     5515    }
    55165516}
    55175517
     
    55205520    BOOL isAttributedString = [string isKindOfClass:[NSAttributedString class]]; // Otherwise, NSString
    55215521
    5522     LOG(TextInput, "setMarkedText:\"%s\" selectedRange:(%u, %u)", isAttributedString ? [[string string] UTF8String] : [string UTF8String], newSelRange.location, newSelRange.length);
     5522    LOG(TextInput, "setMarkedText:\"%@\" selectedRange:(%u, %u)", isAttributedString ? [string string] : string, newSelRange.location, newSelRange.length);
    55235523
    55245524    // Use pointer to get parameters passed to us by the caller of interpretKeyEvents.
     
    55355535        return;
    55365536
    5537     WebFrameBridge *bridge = [self _bridge];
    5538 
    55395537    if (![self _isEditable])
    55405538        return;
     5539
     5540    Vector<CompositionUnderline> underlines;
     5541    NSString *text = string;
    55415542
    55425543    if (isAttributedString) {
    55435544        unsigned markedTextLength = [(NSString *)string length];
    55445545        NSString *rangeString = [string attribute:NSTextInputReplacementRangeAttributeName atIndex:0 longestEffectiveRange:NULL inRange:NSMakeRange(0, markedTextLength)];
    5545         LOG(TextInput, "    ReplacementRange: %s", [rangeString UTF8String]);
    5546         // The AppKit adds a 'secret' property to the string that contains the replacement
    5547         // range.  The replacement range is the range of the the text that should be replaced
    5548         // with the new string.
     5546        LOG(TextInput, "    ReplacementRange: %@", rangeString);
     5547        // The AppKit adds a 'secret' property to the string that contains the replacement range.
     5548        // The replacement range is the range of the the text that should be replaced with the new string.
    55495549        if (rangeString)
    55505550            [[self _bridge] selectNSRange:NSRangeFromString(rangeString)];
    5551     }
    5552 
    5553     coreFrame->editor()->setIgnoreMarkedTextSelectionChange(true);
    5554 
    5555     // if we had marked text already, we need to make sure to replace
    5556     // that, instead of the selection/caret
    5557     coreFrame->editor()->selectMarkedText();
    5558 
    5559     NSString *text = string;
    5560     NSArray *attributes = nil;
    5561     NSArray *ranges = nil;
    5562     if (isAttributedString) {
     5551
    55635552        text = [string string];
    5564         [self _extractAttributes:&attributes ranges:&ranges fromAttributedString:string];
    5565     }
    5566 
    5567     coreFrame->editor()->replaceMarkedText(text);
    5568     [bridge setMarkedTextDOMRange:[self _selectedRange] customAttributes:attributes ranges:ranges];
    5569     if ([self hasMarkedText])
    5570         coreFrame->selectRangeInMarkedText(newSelRange.location, newSelRange.length);
    5571 
    5572     coreFrame->editor()->setIgnoreMarkedTextSelectionChange(false);
     5553        extractUnderlines(string, underlines);
     5554    }
     5555
     5556    coreFrame->editor()->setComposition(text, underlines, newSelRange.location, NSMaxRange(newSelRange));
    55735557}
    55745558
     
    56325616    BOOL isAttributedString = [string isKindOfClass:[NSAttributedString class]]; // Otherwise, NSString
    56335617
    5634     LOG(TextInput, "insertText:\"%s\"", isAttributedString ? [[string string] UTF8String] : [string UTF8String]);
     5618    LOG(TextInput, "insertText:\"%@\"", isAttributedString ? [string string] : string);
    56355619
    56365620    WebHTMLViewInterpretKeyEventsParameters* parameters = _private->interpretKeyEventsParameters;
     
    56405624
    56415625    // We don't support inserting an attributed string but input methods don't appear to require this.
     5626    Frame* coreFrame = core([self _frame]);
    56425627    NSString *text;
    5643     bool isFromInputMethod = [self hasMarkedText];
     5628    bool isFromInputMethod = coreFrame->editor()->hasComposition();
    56445629    if (isAttributedString) {
    56455630        text = [string string];
     
    56495634        // NSAttributedString
    56505635        NSString *rangeString = [string attribute:NSTextInputReplacementRangeAttributeName atIndex:0 longestEffectiveRange:NULL inRange:NSMakeRange(0, [text length])];
    5651         LOG(TextInput, "    ReplacementRange: %s", [rangeString UTF8String]);
     5636        LOG(TextInput, "    ReplacementRange: %@", rangeString);
    56525637        if (rangeString) {
    56535638            [[self _bridge] selectNSRange:NSRangeFromString(rangeString)];
     
    56755660        }
    56765661       
    5677         Frame* coreFrame = core([self _frame]);
    56785662        String eventText = text;
    56795663        eventText.replace(NSBackTabCharacter, NSTabCharacter); // same thing is done in KeyEventMac.mm in WebCore
    5680         eventHandled = coreFrame && coreFrame->editor()->insertText(eventText, event);
     5664        if (coreFrame) {
     5665            if (!coreFrame->editor()->hasComposition())
     5666                eventHandled = coreFrame->editor()->insertText(eventText, event);
     5667            else {
     5668                eventHandled = true;
     5669                coreFrame->editor()->confirmComposition(eventText);
     5670            }
     5671        }
    56815672    }
    56825673   
     
    56945685}
    56955686
    5696 - (BOOL)_selectionIsInsideMarkedText
    5697 {
    5698     WebFrameBridge *bridge = [self _bridge];
    5699     DOMRange *selection = [self _selectedRange];
    5700     DOMRange *markedTextRange = [bridge markedTextDOMRange];
    5701 
    5702     ASSERT([markedTextRange startContainer] == [markedTextRange endContainer]);
    5703 
    5704     if ([selection startContainer] != [markedTextRange startContainer])
    5705         return NO;
    5706 
    5707     if ([selection endContainer] != [markedTextRange startContainer])
    5708         return NO;
    5709 
    5710     if ([selection startOffset] < [markedTextRange startOffset])
    5711         return NO;
    5712 
    5713     if ([selection endOffset] > [markedTextRange endOffset])
    5714         return NO;
    5715 
    5716     return YES;
    5717 }
    5718 
    57195687- (void)_updateSelectionForInputManager
    57205688{
    5721     if (![self hasMarkedText])
    5722         return;
    5723 
    57245689    Frame* coreFrame = core([self _frame]);
    57255690    if (!coreFrame)
    57265691        return;
    57275692
    5728     if (coreFrame->editor()->ignoreMarkedTextSelectionChange())
    5729         return;
    5730 
    5731     if ([self _selectionIsInsideMarkedText]) {
    5732         DOMRange *selection = [self _selectedRange];
    5733         DOMRange *markedTextDOMRange = [[self _bridge] markedTextDOMRange];
    5734 
    5735         unsigned markedSelectionStart = [selection startOffset] - [markedTextDOMRange startOffset];
    5736         unsigned markedSelectionLength = [selection endOffset] - [selection startOffset];
    5737         NSRange newSelectionRange = NSMakeRange(markedSelectionStart, markedSelectionLength);
    5738 
    5739         [[NSInputManager currentInputManager] markedTextSelectionChanged:newSelectionRange client:self];
    5740     } else {
    5741         [self unmarkText];
     5693    if (!coreFrame->editor()->hasComposition())
     5694        return;
     5695
     5696    if (coreFrame->editor()->ignoreCompositionSelectionChange())
     5697        return;
     5698
     5699    unsigned start;
     5700    unsigned end;
     5701    if (coreFrame->editor()->getCompositionSelection(start, end))
     5702        [[NSInputManager currentInputManager] markedTextSelectionChanged:NSMakeRange(start, end - start) client:self];
     5703    else {
     5704        coreFrame->editor()->confirmCompositionWithoutDisturbingSelection();
    57425705        [[NSInputManager currentInputManager] markedTextAbandoned:self];
    57435706    }
  • trunk/WebKit/win/ChangeLog

    r25530 r25547  
     12007-09-13  Darin Adler  <darin@apple.com>
     2
     3        Reviewed by Oliver.
     4
     5        - fix <rdar://problem/5470457> REGRESSION: Input method inline hole is mishandled in text
     6          <input> elements with maxlength limit
     7
     8        * WebView.cpp:
     9        (WebView::resetIME): Change to use confirmCompositionWithoutDisturbingSelection.
     10        (WebView::updateSelectionForIME): Update for name changes, and to use new functions
     11        in Editor.
     12        (WebView::onIMEStartComposition): Removed unneeded call to unmarkText.
     13        (compositionToUnderlines): Removed startOffset parameter, since setComposition now
     14        handles this.
     15        (WebView::onIMEComposition): Changed to use confirmComposition and setComposition.
     16        Logic gets a lot cleaner.
     17        (WebView::onIMEEndComposition): Removed unneeded calls to Editor.
     18        (WebView::onIMERequestCharPosition): Updated for name changes.
     19
    1202007-09-12  Oliver Hunt  <oliver@apple.com>
    221
  • trunk/WebKit/win/WebView.cpp

    r25523 r25547  
    37903790}
    37913791
    3792 static bool markedTextContainsSelection(Range* markedTextRange, Range* selection)
    3793 {
    3794     ExceptionCode ec = 0;
    3795 
    3796     ASSERT(markedTextRange->startContainer(ec) == markedTextRange->endContainer(ec));
    3797 
    3798     if (selection->startContainer(ec) != markedTextRange->startContainer(ec))
    3799         return false;
    3800 
    3801     if (selection->endContainer(ec) != markedTextRange->endContainer(ec))
    3802         return false;
    3803 
    3804     if (selection->startOffset(ec) < markedTextRange->startOffset(ec))
    3805         return false;
    3806 
    3807     if (selection->endOffset(ec) > markedTextRange->endOffset(ec))
    3808         return false;
    3809 
    3810     return true;
    3811 }
    3812 
    3813 static void setSelectionToEndOfRange(Frame* targetFrame, Range* sourceRange)
    3814 {
    3815     ExceptionCode ec = 0;
    3816     Node* caretContainer = sourceRange->endContainer(ec);
    3817     unsigned caretOffset = sourceRange->endOffset(ec);
    3818     RefPtr<Range> range = targetFrame->document()->createRange();
    3819     range->setStart(caretContainer, caretOffset, ec);
    3820     range->setEnd(caretContainer, caretOffset, ec);
    3821     targetFrame->editor()->unmarkText();
    3822     targetFrame->selectionController()->setSelectedRange(range.get(), WebCore::DOWNSTREAM, true, ec);
    3823 }
    3824 
    38253792void WebView::resetIME(Frame* targetFrame)
    38263793{
    38273794    if (targetFrame)
    3828         targetFrame->editor()->unmarkText();
     3795        targetFrame->editor()->confirmCompositionWithoutDisturbingSelection();
    38293796
    38303797    if (HIMC hInputContext = getIMMContext()) {
     
    38373804{
    38383805    Frame* targetFrame = m_page->focusController()->focusedOrMainFrame();
    3839     if (!targetFrame || !targetFrame->markedTextRange())
     3806    if (!targetFrame || !targetFrame->editor()->hasComposition())
    38403807        return;
    38413808   
    3842     if (targetFrame->editor()->ignoreMarkedTextSelectionChange())
     3809    if (targetFrame->editor()->ignoreCompositionSelectionChange())
    38433810        return;
    38443811
    3845     RefPtr<Range> selectionRange = targetFrame->selectionController()->selection().toRange();
    3846     if (!selectionRange || !markedTextContainsSelection(targetFrame->markedTextRange(), selectionRange.get()))
     3812    unsigned start;
     3813    unsigned end;
     3814    if (!targetFrame->editor()->getCompositionSelection(start, end))
    38473815        resetIME(targetFrame);
    38483816}
     
    38643832    if (!targetFrame)
    38653833        return true;
    3866 
    3867     //Tidy up in case the last IME composition was not correctly terminated
    3868     targetFrame->editor()->unmarkText();
    38693834
    38703835    HIMC hInputContext = getIMMContext();
     
    38873852}
    38883853
    3889 static void compositionToUnderlines(const Vector<DWORD>& clauses, const Vector<BYTE>& attributes,
    3890                                     unsigned startOffset, Vector<MarkedTextUnderline>& underlines)
    3891 {
    3892     if (!clauses.size())
     3854static void compositionToUnderlines(const Vector<DWORD>& clauses, const Vector<BYTE>& attributes, Vector<CompositionUnderline>& underlines)
     3855{
     3856    if (clauses.isEmpty()) {
     3857        underlines.clear();
    38933858        return;
     3859    }
    38943860 
    38953861    const size_t numBoundaries = clauses.size() - 1;
    38963862    underlines.resize(numBoundaries);
    38973863    for (unsigned i = 0; i < numBoundaries; i++) {
    3898         underlines[i].startOffset = startOffset + clauses[i];
    3899         underlines[i].endOffset = startOffset + clauses[i + 1];
     3864        underlines[i].startOffset = clauses[i];
     3865        underlines[i].endOffset = clauses[i + 1];
    39003866        BYTE attribute = attributes[clauses[i]];
    39013867        underlines[i].thick = attribute == ATTR_TARGET_CONVERTED || attribute == ATTR_TARGET_NOTCONVERTED;
     
    39153881
    39163882    prepareCandidateWindow(targetFrame, hInputContext);
    3917     targetFrame->editor()->setIgnoreMarkedTextSelectionChange(true);
    3918 
    3919     // if we had marked text already, we need to make sure to replace
    3920     // that, instead of the selection/caret
    3921     targetFrame->editor()->selectMarkedText();
    39223883
    39233884    if (lparam & GCS_RESULTSTR || !lparam) {
    39243885        String compositionString;
    39253886        if (!getCompositionString(hInputContext, GCS_RESULTSTR, compositionString) && lparam)
    3926             goto cleanup;
     3887            return true;
    39273888       
    3928         targetFrame->editor()->replaceMarkedText(compositionString);
    3929         RefPtr<Range> sourceRange = targetFrame->selectionController()->selection().toRange();
    3930         setSelectionToEndOfRange(targetFrame, sourceRange.get());
    3931     } else if (lparam) {
     3889        targetFrame->editor()->confirmComposition(compositionString);
     3890    } else {
    39323891        String compositionString;
    39333892        if (!getCompositionString(hInputContext, GCS_COMPSTR, compositionString))
    3934             goto cleanup;
     3893            return true;
    39353894       
    3936         targetFrame->editor()->replaceMarkedText(compositionString);
    3937 
    3938         ExceptionCode ec = 0;
    3939         RefPtr<Range> sourceRange = targetFrame->selectionController()->selection().toRange();
    3940         if (!sourceRange)
    3941             goto cleanup;
    3942 
    3943         Node* startContainer = sourceRange->startContainer(ec);
    3944         const String& str = startContainer->textContent();
    3945         for (unsigned i = 0; i < str.length(); i++)
    3946             ASSERT(str[i]);
    3947 
    3948         unsigned startOffset = sourceRange->startOffset(ec);
    3949         RefPtr<Range> range = targetFrame->document()->createRange();
    3950         range->setStart(startContainer, startOffset, ec);
    3951         range->setEnd(startContainer, startOffset + compositionString.length(), ec);
    3952 
    39533895        // Composition string attributes
    39543896        int numAttributes = IMMDict::dict().getCompositionString(hInputContext, GCS_COMPATTR, 0, 0);
     
    39603902        Vector<DWORD> clauses(numClauses / sizeof(DWORD));
    39613903        IMMDict::dict().getCompositionString(hInputContext, GCS_COMPCLAUSE, clauses.data(), numClauses);
    3962         Vector<MarkedTextUnderline> underlines;
    3963         compositionToUnderlines(clauses, attributes, startOffset, underlines);
    3964         targetFrame->setMarkedTextRange(range.get(), underlines);
    3965         if (targetFrame->markedTextRange())
    3966             targetFrame->selectRangeInMarkedText(LOWORD(IMMDict::dict().getCompositionString(hInputContext, GCS_CURSORPOS, 0, 0)), 0);
    3967     }
    3968 cleanup:
    3969     targetFrame->editor()->setIgnoreMarkedTextSelectionChange(false);
     3904
     3905        Vector<CompositionUnderline> underlines;
     3906        compositionToUnderlines(clauses, attributes, underlines);
     3907
     3908        int cursorPosition = LOWORD(IMMDict::dict().getCompositionString(hInputContext, GCS_CURSORPOS, 0, 0));
     3909
     3910        targetFrame->editor()->setComposition(compositionString, underlines, cursorPosition, 0);
     3911    }
     3912
    39703913    return true;
    39713914}
     
    39753918    if (m_inIMEComposition)
    39763919        m_inIMEComposition--;
    3977     Frame* targetFrame = m_page->focusController()->focusedOrMainFrame();
    3978     if (!targetFrame)
    3979         return true;
    3980     targetFrame->editor()->unmarkText();
    39813920    return true;
    39823921}
     
    39953934{
    39963935    IntRect caret;
    3997     ASSERT(charPos->dwCharPos == 0 || targetFrame->markedTextRange());
    3998     if (RefPtr<Range> range = targetFrame->markedTextRange() ? targetFrame->markedTextRange() : targetFrame->selectionController()->selection().toRange()) {
     3936    ASSERT(charPos->dwCharPos == 0 || targetFrame->editor()->hasComposition());
     3937    if (RefPtr<Range> range = targetFrame->editor()->hasComposition() ? targetFrame->editor()->compositionRange() : targetFrame->selectionController()->selection().toRange()) {
    39993938        ExceptionCode ec = 0;
    40003939        RefPtr<Range> tempRange = range->cloneRange(ec);
Note: See TracChangeset for help on using the changeset viewer.