| OLD | NEW |
| (Empty) |
| 1 /* | |
| 2 * Copyright (C) 2006, 2007, 2008 Apple Inc. All rights reserved. | |
| 3 * | |
| 4 * Redistribution and use in source and binary forms, with or without | |
| 5 * modification, are permitted provided that the following conditions | |
| 6 * are met: | |
| 7 * 1. Redistributions of source code must retain the above copyright | |
| 8 * notice, this list of conditions and the following disclaimer. | |
| 9 * 2. Redistributions in binary form must reproduce the above copyright | |
| 10 * notice, this list of conditions and the following disclaimer in the | |
| 11 * documentation and/or other materials provided with the distribution. | |
| 12 * | |
| 13 * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY | |
| 14 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE | |
| 15 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR | |
| 16 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR | |
| 17 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, | |
| 18 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, | |
| 19 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR | |
| 20 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY | |
| 21 * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | |
| 22 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE | |
| 23 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | |
| 24 */ | |
| 25 | |
| 26 #import "config.h" | |
| 27 #import "Editor.h" | |
| 28 | |
| 29 #import "ColorMac.h" | |
| 30 #import "ClipboardMac.h" | |
| 31 #import "CachedResourceLoader.h" | |
| 32 #import "DocumentFragment.h" | |
| 33 #import "DOMRangeInternal.h" | |
| 34 #import "Editor.h" | |
| 35 #import "EditorClient.h" | |
| 36 #import "Font.h" | |
| 37 #import "Frame.h" | |
| 38 #import "FrameView.h" | |
| 39 #import "HTMLConverter.h" | |
| 40 #import "HTMLNames.h" | |
| 41 #import "LegacyWebArchive.h" | |
| 42 #import "NodeTraversal.h" | |
| 43 #import "Pasteboard.h" | |
| 44 #import "PasteboardStrategy.h" | |
| 45 #import "PlatformStrategies.h" | |
| 46 #import "Range.h" | |
| 47 #import "RenderBlock.h" | |
| 48 #import "Sound.h" | |
| 49 #import "StylePropertySet.h" | |
| 50 #import "Text.h" | |
| 51 #import "TypingCommand.h" | |
| 52 #import "htmlediting.h" | |
| 53 #import "WebNSAttributedStringExtras.h" | |
| 54 | |
| 55 namespace WebCore { | |
| 56 | |
| 57 using namespace HTMLNames; | |
| 58 | |
| 59 PassRefPtr<Clipboard> Editor::newGeneralClipboard(ClipboardAccessPolicy policy,
Frame* frame) | |
| 60 { | |
| 61 return ClipboardMac::create(Clipboard::CopyAndPaste, | |
| 62 policy == ClipboardWritable ? platformStrategies()->pasteboardStrategy()
->uniqueName() : String(NSGeneralPboard), policy, ClipboardMac::CopyAndPasteGene
ric, frame); | |
| 63 } | |
| 64 | |
| 65 void Editor::showFontPanel() | |
| 66 { | |
| 67 [[NSFontManager sharedFontManager] orderFrontFontPanel:nil]; | |
| 68 } | |
| 69 | |
| 70 void Editor::showStylesPanel() | |
| 71 { | |
| 72 [[NSFontManager sharedFontManager] orderFrontStylesPanel:nil]; | |
| 73 } | |
| 74 | |
| 75 void Editor::showColorPanel() | |
| 76 { | |
| 77 [[NSApplication sharedApplication] orderFrontColorPanel:nil]; | |
| 78 } | |
| 79 | |
| 80 void Editor::pasteWithPasteboard(Pasteboard* pasteboard, bool allowPlainText) | |
| 81 { | |
| 82 RefPtr<Range> range = selectedRange(); | |
| 83 bool choosePlainText; | |
| 84 | |
| 85 m_frame->editor()->client()->setInsertionPasteboard(NSGeneralPboard); | |
| 86 RefPtr<DocumentFragment> fragment = pasteboard->documentFragment(m_frame, ra
nge, allowPlainText, choosePlainText); | |
| 87 if (fragment && shouldInsertFragment(fragment, range, EditorInsertActionPast
ed)) | |
| 88 pasteAsFragment(fragment, canSmartReplaceWithPasteboard(pasteboard), fal
se); | |
| 89 m_frame->editor()->client()->setInsertionPasteboard(String()); | |
| 90 } | |
| 91 | |
| 92 bool Editor::insertParagraphSeparatorInQuotedContent() | |
| 93 { | |
| 94 // FIXME: Why is this missing calls to canEdit, canEditRichly, etc... | |
| 95 TypingCommand::insertParagraphSeparatorInQuotedContent(m_frame->document()); | |
| 96 revealSelectionAfterEditingOperation(); | |
| 97 return true; | |
| 98 } | |
| 99 | |
| 100 static RenderStyle* styleForSelectionStart(Frame* frame, Node *&nodeToRemove) | |
| 101 { | |
| 102 nodeToRemove = 0; | |
| 103 | |
| 104 if (frame->selection()->isNone()) | |
| 105 return 0; | |
| 106 | |
| 107 Position position = frame->selection()->selection().visibleStart().deepEquiv
alent(); | |
| 108 if (!position.isCandidate() || position.isNull()) | |
| 109 return 0; | |
| 110 | |
| 111 RefPtr<EditingStyle> typingStyle = frame->selection()->typingStyle(); | |
| 112 if (!typingStyle || !typingStyle->style()) | |
| 113 return position.deprecatedNode()->renderer()->style(); | |
| 114 | |
| 115 RefPtr<Element> styleElement = frame->document()->createElement(spanTag, fal
se); | |
| 116 | |
| 117 String styleText = typingStyle->style()->asText() + " display: inline"; | |
| 118 styleElement->setAttribute(styleAttr, styleText.impl()); | |
| 119 | |
| 120 styleElement->appendChild(frame->document()->createEditingTextNode(""), ASSE
RT_NO_EXCEPTION); | |
| 121 | |
| 122 position.deprecatedNode()->parentNode()->appendChild(styleElement, ASSERT_NO
_EXCEPTION); | |
| 123 | |
| 124 nodeToRemove = styleElement.get(); | |
| 125 return styleElement->renderer() ? styleElement->renderer()->style() : 0; | |
| 126 } | |
| 127 | |
| 128 const SimpleFontData* Editor::fontForSelection(bool& hasMultipleFonts) const | |
| 129 { | |
| 130 hasMultipleFonts = false; | |
| 131 | |
| 132 if (!m_frame->selection()->isRange()) { | |
| 133 Node* nodeToRemove; | |
| 134 RenderStyle* style = styleForSelectionStart(m_frame, nodeToRemove); // s
ets nodeToRemove | |
| 135 | |
| 136 const SimpleFontData* result = 0; | |
| 137 if (style) | |
| 138 result = style->font().primaryFont(); | |
| 139 | |
| 140 if (nodeToRemove) | |
| 141 nodeToRemove->remove(ASSERT_NO_EXCEPTION); | |
| 142 | |
| 143 return result; | |
| 144 } | |
| 145 | |
| 146 const SimpleFontData* font = 0; | |
| 147 RefPtr<Range> range = m_frame->selection()->toNormalizedRange(); | |
| 148 Node* startNode = adjustedSelectionStartForStyleComputation(m_frame->selecti
on()->selection()).deprecatedNode(); | |
| 149 if (range && startNode) { | |
| 150 Node* pastEnd = range->pastLastNode(); | |
| 151 // In the loop below, n should eventually match pastEnd and not become n
il, but we've seen at least one | |
| 152 // unreproducible case where this didn't happen, so check for null also. | |
| 153 for (Node* node = startNode; node && node != pastEnd; node = NodeTravers
al::next(node)) { | |
| 154 RenderObject* renderer = node->renderer(); | |
| 155 if (!renderer) | |
| 156 continue; | |
| 157 // FIXME: Are there any node types that have renderers, but that we
should be skipping? | |
| 158 const SimpleFontData* primaryFont = renderer->style()->font().primar
yFont(); | |
| 159 if (!font) | |
| 160 font = primaryFont; | |
| 161 else if (font != primaryFont) { | |
| 162 hasMultipleFonts = true; | |
| 163 break; | |
| 164 } | |
| 165 } | |
| 166 } | |
| 167 | |
| 168 return font; | |
| 169 } | |
| 170 | |
| 171 NSDictionary* Editor::fontAttributesForSelectionStart() const | |
| 172 { | |
| 173 Node* nodeToRemove; | |
| 174 RenderStyle* style = styleForSelectionStart(m_frame, nodeToRemove); | |
| 175 if (!style) | |
| 176 return nil; | |
| 177 | |
| 178 NSMutableDictionary* result = [NSMutableDictionary dictionary]; | |
| 179 | |
| 180 if (style->visitedDependentColor(CSSPropertyBackgroundColor).isValid() && st
yle->visitedDependentColor(CSSPropertyBackgroundColor).alpha() != 0) | |
| 181 [result setObject:nsColor(style->visitedDependentColor(CSSPropertyBackgr
oundColor)) forKey:NSBackgroundColorAttributeName]; | |
| 182 | |
| 183 if (style->font().primaryFont()->getNSFont()) | |
| 184 [result setObject:style->font().primaryFont()->getNSFont() forKey:NSFont
AttributeName]; | |
| 185 | |
| 186 if (style->visitedDependentColor(CSSPropertyColor).isValid() && style->visit
edDependentColor(CSSPropertyColor) != Color::black) | |
| 187 [result setObject:nsColor(style->visitedDependentColor(CSSPropertyColor)
) forKey:NSForegroundColorAttributeName]; | |
| 188 | |
| 189 const ShadowData* shadow = style->textShadow(); | |
| 190 if (shadow) { | |
| 191 RetainPtr<NSShadow> s(AdoptNS, [[NSShadow alloc] init]); | |
| 192 [s.get() setShadowOffset:NSMakeSize(shadow->x(), shadow->y())]; | |
| 193 [s.get() setShadowBlurRadius:shadow->blur()]; | |
| 194 [s.get() setShadowColor:nsColor(shadow->color())]; | |
| 195 [result setObject:s.get() forKey:NSShadowAttributeName]; | |
| 196 } | |
| 197 | |
| 198 int decoration = style->textDecorationsInEffect(); | |
| 199 if (decoration & LINE_THROUGH) | |
| 200 [result setObject:[NSNumber numberWithInt:NSUnderlineStyleSingle] forKey
:NSStrikethroughStyleAttributeName]; | |
| 201 | |
| 202 int superscriptInt = 0; | |
| 203 switch (style->verticalAlign()) { | |
| 204 case BASELINE: | |
| 205 case BOTTOM: | |
| 206 case BASELINE_MIDDLE: | |
| 207 case LENGTH: | |
| 208 case MIDDLE: | |
| 209 case TEXT_BOTTOM: | |
| 210 case TEXT_TOP: | |
| 211 case TOP: | |
| 212 break; | |
| 213 case SUB: | |
| 214 superscriptInt = -1; | |
| 215 break; | |
| 216 case SUPER: | |
| 217 superscriptInt = 1; | |
| 218 break; | |
| 219 } | |
| 220 if (superscriptInt) | |
| 221 [result setObject:[NSNumber numberWithInt:superscriptInt] forKey:NSSuper
scriptAttributeName]; | |
| 222 | |
| 223 if (decoration & UNDERLINE) | |
| 224 [result setObject:[NSNumber numberWithInt:NSUnderlineStyleSingle] forKey
:NSUnderlineStyleAttributeName]; | |
| 225 | |
| 226 if (nodeToRemove) | |
| 227 nodeToRemove->remove(ASSERT_NO_EXCEPTION); | |
| 228 | |
| 229 return result; | |
| 230 } | |
| 231 | |
| 232 bool Editor::canCopyExcludingStandaloneImages() | |
| 233 { | |
| 234 FrameSelection* selection = m_frame->selection(); | |
| 235 return selection->isRange() && !selection->isInPasswordField(); | |
| 236 } | |
| 237 | |
| 238 void Editor::takeFindStringFromSelection() | |
| 239 { | |
| 240 if (!canCopyExcludingStandaloneImages()) { | |
| 241 systemBeep(); | |
| 242 return; | |
| 243 } | |
| 244 | |
| 245 Vector<String> types; | |
| 246 types.append(String(NSStringPboardType)); | |
| 247 platformStrategies()->pasteboardStrategy()->setTypes(types, NSFindPboard); | |
| 248 platformStrategies()->pasteboardStrategy()->setStringForType(m_frame->displa
yStringModifiedByEncoding(selectedTextForClipboard()), NSStringPboardType, NSFin
dPboard); | |
| 249 } | |
| 250 | |
| 251 void Editor::writeSelectionToPasteboard(const String& pasteboardName, const Vect
or<String>& pasteboardTypes) | |
| 252 { | |
| 253 Pasteboard pasteboard(pasteboardName); | |
| 254 pasteboard.writeSelectionForTypes(pasteboardTypes, true, m_frame, DefaultSel
ectedTextType); | |
| 255 } | |
| 256 | |
| 257 void Editor::readSelectionFromPasteboard(const String& pasteboardName) | |
| 258 { | |
| 259 Pasteboard pasteboard(pasteboardName); | |
| 260 if (m_frame->selection()->isContentRichlyEditable()) | |
| 261 pasteWithPasteboard(&pasteboard, true); | |
| 262 else | |
| 263 pasteAsPlainTextWithPasteboard(&pasteboard); | |
| 264 } | |
| 265 | |
| 266 String Editor::stringSelectionForPasteboard() | |
| 267 { | |
| 268 return Pasteboard::getStringSelection(m_frame, DefaultSelectedTextType); | |
| 269 } | |
| 270 | |
| 271 PassRefPtr<SharedBuffer> Editor::dataSelectionForPasteboard(const String& pasteb
oardType) | |
| 272 { | |
| 273 return Pasteboard::getDataSelection(m_frame, pasteboardType); | |
| 274 } | |
| 275 | |
| 276 } // namespace WebCore | |
| OLD | NEW |