• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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