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 "Editor.h" 34#import "EditorClient.h" 35#import "Frame.h" 36#import "FrameView.h" 37#import "Pasteboard.h" 38#import "RenderBlock.h" 39#import "RuntimeApplicationChecks.h" 40#import "Sound.h" 41 42namespace WebCore { 43 44PassRefPtr<Clipboard> Editor::newGeneralClipboard(ClipboardAccessPolicy policy, Frame* frame) 45{ 46 return ClipboardMac::create(Clipboard::CopyAndPaste, [NSPasteboard generalPasteboard], policy, frame); 47} 48 49void Editor::showFontPanel() 50{ 51 [[NSFontManager sharedFontManager] orderFrontFontPanel:nil]; 52} 53 54void Editor::showStylesPanel() 55{ 56 [[NSFontManager sharedFontManager] orderFrontStylesPanel:nil]; 57} 58 59void Editor::showColorPanel() 60{ 61 [[NSApplication sharedApplication] orderFrontColorPanel:nil]; 62} 63 64void Editor::pasteWithPasteboard(Pasteboard* pasteboard, bool allowPlainText) 65{ 66 RefPtr<Range> range = selectedRange(); 67 bool choosePlainText; 68 69 m_frame->editor()->client()->setInsertionPasteboard([NSPasteboard generalPasteboard]); 70#if !defined(BUILDING_ON_TIGER) && !defined(BUILDING_ON_LEOPARD) && !defined(BUILDING_ON_SNOW_LEOPARD) 71 RefPtr<DocumentFragment> fragment = pasteboard->documentFragment(m_frame, range, allowPlainText, choosePlainText); 72 if (fragment && shouldInsertFragment(fragment, range, EditorInsertActionPasted)) 73 pasteAsFragment(fragment, canSmartReplaceWithPasteboard(pasteboard), false); 74#else 75 // Mail is ignoring the frament passed to the delegate and creates a new one. 76 // We want to avoid creating the fragment twice. 77 if (applicationIsAppleMail()) { 78 if (shouldInsertFragment(NULL, range, EditorInsertActionPasted)) { 79 RefPtr<DocumentFragment> fragment = pasteboard->documentFragment(m_frame, range, allowPlainText, choosePlainText); 80 if (fragment) 81 pasteAsFragment(fragment, canSmartReplaceWithPasteboard(pasteboard), false); 82 } 83 } else { 84 RefPtr<DocumentFragment>fragment = pasteboard->documentFragment(m_frame, range, allowPlainText, choosePlainText); 85 if (fragment && shouldInsertFragment(fragment, range, EditorInsertActionPasted)) 86 pasteAsFragment(fragment, canSmartReplaceWithPasteboard(pasteboard), false); 87 } 88#endif 89 m_frame->editor()->client()->setInsertionPasteboard(nil); 90} 91 92NSDictionary* Editor::fontAttributesForSelectionStart() const 93{ 94 Node* nodeToRemove; 95 RenderStyle* style = styleForSelectionStart(nodeToRemove); 96 if (!style) 97 return nil; 98 99 NSMutableDictionary* result = [NSMutableDictionary dictionary]; 100 101 if (style->visitedDependentColor(CSSPropertyBackgroundColor).isValid() && style->visitedDependentColor(CSSPropertyBackgroundColor).alpha() != 0) 102 [result setObject:nsColor(style->visitedDependentColor(CSSPropertyBackgroundColor)) forKey:NSBackgroundColorAttributeName]; 103 104 if (style->font().primaryFont()->getNSFont()) 105 [result setObject:style->font().primaryFont()->getNSFont() forKey:NSFontAttributeName]; 106 107 if (style->visitedDependentColor(CSSPropertyColor).isValid() && style->visitedDependentColor(CSSPropertyColor) != Color::black) 108 [result setObject:nsColor(style->visitedDependentColor(CSSPropertyColor)) forKey:NSForegroundColorAttributeName]; 109 110 const ShadowData* shadow = style->textShadow(); 111 if (shadow) { 112 NSShadow* s = [[NSShadow alloc] init]; 113 [s setShadowOffset:NSMakeSize(shadow->x(), shadow->y())]; 114 [s setShadowBlurRadius:shadow->blur()]; 115 [s setShadowColor:nsColor(shadow->color())]; 116 [result setObject:s forKey:NSShadowAttributeName]; 117 } 118 119 int decoration = style->textDecorationsInEffect(); 120 if (decoration & LINE_THROUGH) 121 [result setObject:[NSNumber numberWithInt:NSUnderlineStyleSingle] forKey:NSStrikethroughStyleAttributeName]; 122 123 int superscriptInt = 0; 124 switch (style->verticalAlign()) { 125 case BASELINE: 126 case BOTTOM: 127 case BASELINE_MIDDLE: 128 case LENGTH: 129 case MIDDLE: 130 case TEXT_BOTTOM: 131 case TEXT_TOP: 132 case TOP: 133 break; 134 case SUB: 135 superscriptInt = -1; 136 break; 137 case SUPER: 138 superscriptInt = 1; 139 break; 140 } 141 if (superscriptInt) 142 [result setObject:[NSNumber numberWithInt:superscriptInt] forKey:NSSuperscriptAttributeName]; 143 144 if (decoration & UNDERLINE) 145 [result setObject:[NSNumber numberWithInt:NSUnderlineStyleSingle] forKey:NSUnderlineStyleAttributeName]; 146 147 if (nodeToRemove) { 148 ExceptionCode ec = 0; 149 nodeToRemove->remove(ec); 150 ASSERT(ec == 0); 151 } 152 153 return result; 154} 155 156NSWritingDirection Editor::baseWritingDirectionForSelectionStart() const 157{ 158 NSWritingDirection result = NSWritingDirectionLeftToRight; 159 160 Position pos = m_frame->selection()->selection().visibleStart().deepEquivalent(); 161 Node* node = pos.deprecatedNode(); 162 if (!node) 163 return result; 164 165 RenderObject* renderer = node->renderer(); 166 if (!renderer) 167 return result; 168 169 if (!renderer->isBlockFlow()) { 170 renderer = renderer->containingBlock(); 171 if (!renderer) 172 return result; 173 } 174 175 RenderStyle* style = renderer->style(); 176 if (!style) 177 return result; 178 179 switch (style->direction()) { 180 case LTR: 181 result = NSWritingDirectionLeftToRight; 182 break; 183 case RTL: 184 result = NSWritingDirectionRightToLeft; 185 break; 186 } 187 188 return result; 189} 190 191bool Editor::canCopyExcludingStandaloneImages() 192{ 193 SelectionController* selection = m_frame->selection(); 194 return selection->isRange() && !selection->isInPasswordField(); 195} 196 197void Editor::takeFindStringFromSelection() 198{ 199 if (!canCopyExcludingStandaloneImages()) { 200 systemBeep(); 201 return; 202 } 203 204 NSString *nsSelectedText = m_frame->displayStringModifiedByEncoding(selectedText()); 205 206 NSPasteboard *findPasteboard = [NSPasteboard pasteboardWithName:NSFindPboard]; 207 [findPasteboard declareTypes:[NSArray arrayWithObject:NSStringPboardType] owner:nil]; 208 [findPasteboard setString:nsSelectedText forType:NSStringPboardType]; 209} 210 211void Editor::writeSelectionToPasteboard(const String& pasteboardName, const Vector<String>& pasteboardTypes) 212{ 213 RetainPtr<NSMutableArray> types(AdoptNS, [[NSMutableArray alloc] init]); 214 for (size_t i = 0; i < pasteboardTypes.size(); ++i) 215 [types.get() addObject:pasteboardTypes[i]]; 216 Pasteboard::writeSelection([NSPasteboard pasteboardWithName:pasteboardName], types.get(), selectedRange().get(), true, m_frame); 217} 218 219void Editor::readSelectionFromPasteboard(const String& pasteboardName) 220{ 221 Pasteboard pasteboard([NSPasteboard pasteboardWithName:pasteboardName]); 222 if (m_frame->selection()->isContentRichlyEditable()) 223 pasteWithPasteboard(&pasteboard, true); 224 else 225 pasteAsPlainTextWithPasteboard(&pasteboard); 226} 227 228} // namespace WebCore 229