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 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 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 "HTMLParserIdioms.h"
44#import "HTMLSelectElement.h"
45#import "HTMLTextAreaElement.h"
46#import "Page.h"
47#import "Range.h"
48#import "RenderTextControl.h"
49#import "Settings.h"
50#import "markup.h"
51
52#if PLATFORM(IOS)
53#import "Autocapitalize.h"
54#import "DOMHTMLElementInternal.h"
55#import "HTMLTextFormControlElement.h"
56#import "JSMainThreadExecState.h"
57#import "RenderLayer.h"
58#import "WAKWindow.h"
59#import "WebCoreThreadMessage.h"
60#endif
61
62#if PLATFORM(IOS)
63
64using namespace WebCore;
65
66@implementation DOMHTMLElement (DOMHTMLElementExtensions)
67
68- (int)scrollXOffset
69{
70    RenderObject *renderer = core(self)->renderer();
71    if (!renderer)
72        return 0;
73
74    if (!renderer->isRenderBlockFlow())
75        renderer = renderer->containingBlock();
76
77    if (!renderer->isBox() || !renderer->hasOverflowClip())
78        return 0;
79
80    RenderBox *renderBox = toRenderBox(renderer);
81    return renderBox->layer()->scrollXOffset();
82}
83
84- (int)scrollYOffset
85{
86    RenderObject *renderer = core(self)->renderer();
87    if (!renderer)
88        return 0;
89
90    if (!renderer->isRenderBlockFlow())
91        renderer = renderer->containingBlock();
92    if (!renderer->isBox() || !renderer->hasOverflowClip())
93        return 0;
94
95    RenderBox *renderBox = toRenderBox(renderer);
96    return renderBox->layer()->scrollYOffset();
97}
98
99- (void)setScrollXOffset:(int)x scrollYOffset:(int)y
100{
101    [self setScrollXOffset:x scrollYOffset:y adjustForIOSCaret:NO];
102}
103
104- (void)setScrollXOffset:(int)x scrollYOffset:(int)y adjustForIOSCaret:(BOOL)adjustForIOSCaret
105{
106    RenderObject *renderer = core(self)->renderer();
107    if (!renderer)
108        return;
109
110    if (!renderer->isRenderBlockFlow())
111        renderer = renderer->containingBlock();
112    if (!renderer->hasOverflowClip() || !renderer->isBox())
113        return;
114
115    RenderBox *renderBox = toRenderBox(renderer);
116    RenderLayer *layer = renderBox->layer();
117    if (adjustForIOSCaret)
118        layer->setAdjustForIOSCaretWhenScrolling(true);
119    layer->scrollToOffset(IntSize(x, y));
120    if (adjustForIOSCaret)
121        layer->setAdjustForIOSCaretWhenScrolling(false);
122}
123
124- (void)absolutePosition:(int *)x :(int *)y :(int *)w :(int *)h {
125    RenderBox *renderer = core(self)->renderBox();
126    if (renderer) {
127        if (w)
128            *w = renderer->width();
129        if (h)
130            *h = renderer->width();
131        if (x && y) {
132            FloatPoint floatPoint(*x, *y);
133            renderer->localToAbsolute(floatPoint);
134            IntPoint point = roundedIntPoint(floatPoint);
135            *x = point.x();
136            *y = point.y();
137        }
138    }
139}
140
141@end
142
143#endif // PLATFORM(IOS)
144
145//------------------------------------------------------------------------------------------
146// DOMHTMLDocument
147
148@implementation DOMHTMLDocument (DOMHTMLDocumentExtensions)
149
150- (DOMDocumentFragment *)createDocumentFragmentWithMarkupString:(NSString *)markupString baseURL:(NSURL *)baseURL
151{
152    return kit(createFragmentFromMarkup(*core(self), markupString, [baseURL absoluteString]).get());
153}
154
155- (DOMDocumentFragment *)createDocumentFragmentWithText:(NSString *)text
156{
157    // FIXME: Since this is not a contextual fragment, it won't handle whitespace properly.
158    return kit(createFragmentFromText(*core(self)->createRange().get(), text).get());
159}
160
161@end
162
163@implementation DOMHTMLDocument (WebPrivate)
164
165- (DOMDocumentFragment *)_createDocumentFragmentWithMarkupString:(NSString *)markupString baseURLString:(NSString *)baseURLString
166{
167    NSURL *baseURL = core(self)->completeURL(WebCore::stripLeadingAndTrailingHTMLSpaces(baseURLString));
168    return [self createDocumentFragmentWithMarkupString:markupString baseURL:baseURL];
169}
170
171- (DOMDocumentFragment *)_createDocumentFragmentWithText:(NSString *)text
172{
173    return [self createDocumentFragmentWithText:text];
174}
175
176@end
177
178@implementation DOMHTMLInputElement (FormAutoFillTransition)
179
180- (BOOL)_isTextField
181{
182    return core(self)->isTextField();
183}
184
185#if PLATFORM(IOS)
186- (BOOL)_isAutofilled
187{
188    return core(self)->isAutofilled();
189}
190
191- (void)_setAutofilled:(BOOL)filled
192{
193    // This notifies the input element that the content has been autofilled
194    // This allows WebKit to obey the -webkit-autofill pseudo style, which
195    // changes the background color.
196    core(self)->setAutofilled(filled);
197}
198#endif // PLATFORM(IOS)
199
200@end
201
202@implementation DOMHTMLSelectElement (FormAutoFillTransition)
203
204- (void)_activateItemAtIndex:(int)index
205{
206    // Use the setSelectedIndexByUser function so a change event will be fired. <rdar://problem/6760590>
207    if (WebCore::HTMLSelectElement* select = core(self))
208        select->optionSelectedByUser(index, true);
209}
210
211- (void)_activateItemAtIndex:(int)index allowMultipleSelection:(BOOL)allowMultipleSelection
212{
213    // Use the setSelectedIndexByUser function so a change event will be fired. <rdar://problem/6760590>
214    // If this is a <select multiple> the allowMultipleSelection flag will allow setting multiple
215    // selections without clearing the other selections.
216    if (WebCore::HTMLSelectElement* select = core(self))
217        select->optionSelectedByUser(index, true, allowMultipleSelection);
218}
219
220@end
221
222#if PLATFORM(IOS)
223
224@implementation DOMHTMLInputElement (FormPromptAdditions)
225
226- (BOOL)_isEdited
227{
228    return core(self)->lastChangeWasUserEdit();
229}
230
231@end
232
233@implementation DOMHTMLTextAreaElement (FormPromptAdditions)
234
235- (BOOL)_isEdited
236{
237    return core(self)->lastChangeWasUserEdit();
238}
239
240@end
241
242@implementation DOMHTMLInputElement (AutocapitalizeAdditions)
243
244- (WebAutocapitalizeType)_autocapitalizeType
245{
246    WebCore::HTMLInputElement* inputElement = core(self);
247    return static_cast<WebAutocapitalizeType>(inputElement->autocapitalizeType());
248}
249
250@end
251
252@implementation DOMHTMLTextAreaElement (AutocapitalizeAdditions)
253
254- (WebAutocapitalizeType)_autocapitalizeType
255{
256    WebCore::HTMLTextAreaElement* textareaElement = core(self);
257    return static_cast<WebAutocapitalizeType>(textareaElement->autocapitalizeType());
258}
259
260@end
261
262@implementation DOMHTMLInputElement (WebInputChangeEventAdditions)
263
264- (void)setValueWithChangeEvent:(NSString *)newValue
265{
266    WebCore::JSMainThreadNullState state;
267    core(self)->setValue(newValue, DispatchInputAndChangeEvent);
268}
269
270- (void)setValueAsNumberWithChangeEvent:(double)newValueAsNumber
271{
272    WebCore::JSMainThreadNullState state;
273    WebCore::ExceptionCode ec = 0;
274    core(self)->setValueAsNumber(newValueAsNumber, ec, DispatchInputAndChangeEvent);
275}
276
277@end
278#endif
279
280Class kitClass(WebCore::HTMLCollection* collection)
281{
282    if (collection->type() == WebCore::SelectOptions)
283        return [DOMHTMLOptionsCollection class];
284    return [DOMHTMLCollection class];
285}
286