b5e3b25f947f150748a141daed55efa77ecac330
[WebKit.git] / WebCore / editing / mac / EditorMac.mm
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
41 namespace WebCore {
42
43 PassRefPtr<Clipboard> Editor::newGeneralClipboard(ClipboardAccessPolicy policy, Frame* frame)
44 {
45     return ClipboardMac::create(Clipboard::CopyAndPaste, [NSPasteboard generalPasteboard], policy, frame);
46 }
47
48 void Editor::showFontPanel()
49 {
50     [[NSFontManager sharedFontManager] orderFrontFontPanel:nil];
51 }
52
53 void Editor::showStylesPanel()
54 {
55     [[NSFontManager sharedFontManager] orderFrontStylesPanel:nil];
56 }
57
58 void Editor::showColorPanel()
59 {
60     [[NSApplication sharedApplication] orderFrontColorPanel:nil];
61 }
62
63 void Editor::pasteWithPasteboard(Pasteboard* pasteboard, bool allowPlainText)
64 {
65     RefPtr<Range> range = selectedRange();
66     bool choosePlainText;
67     
68     m_frame->editor()->client()->setInsertionPasteboard([NSPasteboard generalPasteboard]);
69 #if !defined(BUILDING_ON_TIGER) && !defined(BUILDING_ON_LEOPARD) && !defined(BUILDING_ON_SNOW_LEOPARD)
70     RefPtr<DocumentFragment> fragment = pasteboard->documentFragment(m_frame, range, allowPlainText, choosePlainText);
71     if (fragment && shouldInsertFragment(fragment, range, EditorInsertActionPasted))
72         pasteAsFragment(fragment, canSmartReplaceWithPasteboard(pasteboard), false);
73 #else
74     // Mail is ignoring the frament passed to the delegate and creates a new one.
75     // We want to avoid creating the fragment twice.
76     if (applicationIsAppleMail()) {
77         if (shouldInsertFragment(NULL, range, EditorInsertActionPasted)) {
78             RefPtr<DocumentFragment> fragment = pasteboard->documentFragment(m_frame, range, allowPlainText, choosePlainText);
79             if (fragment)
80                 pasteAsFragment(fragment, canSmartReplaceWithPasteboard(pasteboard), false);
81         }        
82     } else {
83         RefPtr<DocumentFragment>fragment = pasteboard->documentFragment(m_frame, range, allowPlainText, choosePlainText);
84         if (fragment && shouldInsertFragment(fragment, range, EditorInsertActionPasted))
85             pasteAsFragment(fragment, canSmartReplaceWithPasteboard(pasteboard), false);
86     }
87 #endif
88     m_frame->editor()->client()->setInsertionPasteboard(nil);
89 }
90
91 NSDictionary* Editor::fontAttributesForSelectionStart() const
92 {
93     Node* nodeToRemove;
94     RenderStyle* style = styleForSelectionStart(nodeToRemove);
95     if (!style)
96         return nil;
97
98     NSMutableDictionary* result = [NSMutableDictionary dictionary];
99
100     if (style->visitedDependentColor(CSSPropertyBackgroundColor).isValid() && style->visitedDependentColor(CSSPropertyBackgroundColor).alpha() != 0)
101         [result setObject:nsColor(style->visitedDependentColor(CSSPropertyBackgroundColor)) forKey:NSBackgroundColorAttributeName];
102
103     if (style->font().primaryFont()->getNSFont())
104         [result setObject:style->font().primaryFont()->getNSFont() forKey:NSFontAttributeName];
105
106     if (style->visitedDependentColor(CSSPropertyColor).isValid() && style->visitedDependentColor(CSSPropertyColor) != Color::black)
107         [result setObject:nsColor(style->visitedDependentColor(CSSPropertyColor)) forKey:NSForegroundColorAttributeName];
108
109     const ShadowData* shadow = style->textShadow();
110     if (shadow) {
111         NSShadow* s = [[NSShadow alloc] init];
112         [s setShadowOffset:NSMakeSize(shadow->x(), shadow->y())];
113         [s setShadowBlurRadius:shadow->blur()];
114         [s setShadowColor:nsColor(shadow->color())];
115         [result setObject:s forKey:NSShadowAttributeName];
116     }
117
118     int decoration = style->textDecorationsInEffect();
119     if (decoration & LINE_THROUGH)
120         [result setObject:[NSNumber numberWithInt:NSUnderlineStyleSingle] forKey:NSStrikethroughStyleAttributeName];
121
122     int superscriptInt = 0;
123     switch (style->verticalAlign()) {
124         case BASELINE:
125         case BOTTOM:
126         case BASELINE_MIDDLE:
127         case LENGTH:
128         case MIDDLE:
129         case TEXT_BOTTOM:
130         case TEXT_TOP:
131         case TOP:
132             break;
133         case SUB:
134             superscriptInt = -1;
135             break;
136         case SUPER:
137             superscriptInt = 1;
138             break;
139     }
140     if (superscriptInt)
141         [result setObject:[NSNumber numberWithInt:superscriptInt] forKey:NSSuperscriptAttributeName];
142
143     if (decoration & UNDERLINE)
144         [result setObject:[NSNumber numberWithInt:NSUnderlineStyleSingle] forKey:NSUnderlineStyleAttributeName];
145
146     if (nodeToRemove) {
147         ExceptionCode ec = 0;
148         nodeToRemove->remove(ec);
149         ASSERT(ec == 0);
150     }
151
152     return result;
153 }
154
155 NSWritingDirection Editor::baseWritingDirectionForSelectionStart() const
156 {
157     NSWritingDirection result = NSWritingDirectionLeftToRight;
158
159     Position pos = m_frame->selection()->selection().visibleStart().deepEquivalent();
160     Node* node = pos.node();
161     if (!node)
162         return result;
163
164     RenderObject* renderer = node->renderer();
165     if (!renderer)
166         return result;
167
168     if (!renderer->isBlockFlow()) {
169         renderer = renderer->containingBlock();
170         if (!renderer)
171             return result;
172     }
173
174     RenderStyle* style = renderer->style();
175     if (!style)
176         return result;
177         
178     switch (style->direction()) {
179         case LTR:
180             result = NSWritingDirectionLeftToRight;
181             break;
182         case RTL:
183             result = NSWritingDirectionRightToLeft;
184             break;
185     }
186
187     return result;
188 }
189
190 } // namespace WebCore