1/*
2 * Copyright (C) 2004, 2005, 2006, 2007, 2008, 2009 Apple Inc. All rights reserved.
3 * Copyright (C) 2006 Samuel Weinig <sam.weinig@gmail.com>
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 * 1. Redistributions of source code must retain the above copyright
9 *    notice, this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright
11 *    notice, this list of conditions and the following disclaimer in the
12 *    documentation and/or other materials provided with the distribution.
13 *
14 * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY
15 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
16 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
17 * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE COMPUTER, INC. OR
18 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
19 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
20 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
21 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
22 * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
23 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
24 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
25 */
26
27#import "config.h"
28
29#import "DOMDocumentFragmentInternal.h"
30#import "DOMExtensions.h"
31#import "DOMHTMLCollectionInternal.h"
32#import "DOMHTMLDocumentInternal.h"
33#import "DOMHTMLInputElementInternal.h"
34#import "DOMHTMLSelectElementInternal.h"
35#import "DOMHTMLTextAreaElementInternal.h"
36#import "DOMNodeInternal.h"
37#import "DOMPrivate.h"
38#import "DocumentFragment.h"
39#import "FrameView.h"
40#import "HTMLCollection.h"
41#import "HTMLDocument.h"
42#import "HTMLInputElement.h"
43#import "HTMLSelectElement.h"
44#import "HTMLTextAreaElement.h"
45#import "Page.h"
46#import "Range.h"
47#import "RenderTextControl.h"
48#import "Settings.h"
49#import "markup.h"
50
51//------------------------------------------------------------------------------------------
52// DOMHTMLDocument
53
54@implementation DOMHTMLDocument (DOMHTMLDocumentExtensions)
55
56- (DOMDocumentFragment *)createDocumentFragmentWithMarkupString:(NSString *)markupString baseURL:(NSURL *)baseURL
57{
58    return kit(createFragmentFromMarkup(core(self), markupString, [baseURL absoluteString]).get());
59}
60
61- (DOMDocumentFragment *)createDocumentFragmentWithText:(NSString *)text
62{
63    // FIXME: Since this is not a contextual fragment, it won't handle whitespace properly.
64    return kit(createFragmentFromText(core(self)->createRange().get(), text).get());
65}
66
67@end
68
69@implementation DOMHTMLDocument (WebPrivate)
70
71- (DOMDocumentFragment *)_createDocumentFragmentWithMarkupString:(NSString *)markupString baseURLString:(NSString *)baseURLString
72{
73    NSURL *baseURL = core(self)->completeURL(WebCore::deprecatedParseURL(baseURLString));
74    return [self createDocumentFragmentWithMarkupString:markupString baseURL:baseURL];
75}
76
77- (DOMDocumentFragment *)_createDocumentFragmentWithText:(NSString *)text
78{
79    return [self createDocumentFragmentWithText:text];
80}
81
82@end
83
84#ifdef BUILDING_ON_TIGER
85@implementation DOMHTMLDocument (DOMHTMLDocumentOverrides)
86
87- (DOMNode *)firstChild
88{
89    WebCore::HTMLDocument* coreHTMLDocument = core(self);
90    if (!coreHTMLDocument->page() || !coreHTMLDocument->page()->settings()->needsTigerMailQuirks())
91        return kit(coreHTMLDocument->firstChild());
92
93    WebCore::Node* child = coreHTMLDocument->firstChild();
94    while (child && child->nodeType() == WebCore::Node::DOCUMENT_TYPE_NODE)
95        child = child->nextSibling();
96
97    return kit(child);
98}
99
100@end
101#endif
102
103@implementation DOMHTMLInputElement (FormAutoFillTransition)
104
105- (BOOL)_isTextField
106{
107    return core(self)->isTextField();
108}
109
110- (NSRect)_rectOnScreen
111{
112    // Returns bounding rect of text field, in screen coordinates.
113    NSRect result = [self boundingBox];
114    if (!core(self)->document()->view())
115        return result;
116
117    NSView* view = core(self)->document()->view()->documentView();
118    result = [view convertRect:result toView:nil];
119    result.origin = [[view window] convertBaseToScreen:result.origin];
120    return result;
121}
122
123- (void)_replaceCharactersInRange:(NSRange)targetRange withString:(NSString *)replacementString selectingFromIndex:(int)index
124{
125    WebCore::HTMLInputElement* inputElement = core(self);
126    if (inputElement) {
127        WebCore::String newValue = inputElement->value();
128        newValue.replace(targetRange.location, targetRange.length, replacementString);
129        inputElement->setValue(newValue);
130        inputElement->setSelectionRange(index, newValue.length());
131    }
132}
133
134- (NSRange)_selectedRange
135{
136    WebCore::HTMLInputElement* inputElement = core(self);
137    if (inputElement) {
138        int start = inputElement->selectionStart();
139        int end = inputElement->selectionEnd();
140        return NSMakeRange(start, end - start);
141    }
142    return NSMakeRange(NSNotFound, 0);
143}
144
145- (BOOL)_isAutofilled
146{
147    return core(self)->isAutofilled();
148}
149
150- (void)_setAutofilled:(BOOL)filled
151{
152    // This notifies the input element that the content has been autofilled
153    // This allows WebKit to obey the -webkit-autofill pseudo style, which
154    // changes the background color.
155    core(self)->setAutofilled(filled);
156}
157
158@end
159
160@implementation DOMHTMLSelectElement (FormAutoFillTransition)
161
162- (void)_activateItemAtIndex:(int)index
163{
164    // Use the setSelectedIndexByUser function so a change event will be fired. <rdar://problem/6760590>
165    if (WebCore::HTMLSelectElement* select = core(self))
166        select->setSelectedIndexByUser(index, true, true);
167}
168
169@end
170
171@implementation DOMHTMLInputElement (FormPromptAdditions)
172
173- (BOOL)_isEdited
174{
175    WebCore::RenderObject *renderer = core(self)->renderer();
176    return renderer && [self _isTextField] && static_cast<WebCore::RenderTextControl *>(renderer)->lastChangeWasUserEdit();
177}
178
179@end
180
181@implementation DOMHTMLTextAreaElement (FormPromptAdditions)
182
183- (BOOL)_isEdited
184{
185    WebCore::RenderObject* renderer = core(self)->renderer();
186    return renderer && static_cast<WebCore::RenderTextControl*>(renderer)->lastChangeWasUserEdit();
187}
188
189@end
190
191Class kitClass(WebCore::HTMLCollection* collection)
192{
193    if (collection->type() == WebCore::SelectOptions)
194        return [DOMHTMLOptionsCollection class];
195    return [DOMHTMLCollection class];
196}
197