WebCore:
[WebKit-https.git] / WebCore / kwq / KWQSlot.mm
1 /*
2  * Copyright (C) 2004 Apple Computer, 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 "KWQSlot.h"
27
28 #import "KWQAssertions.h"
29
30 #import "dom_docimpl.h"
31 #import "khtml_part.h"
32 #import "kjs_window.h"
33 #import "render_form.h"
34 #import "render_layer.h"
35 #import "xmlhttprequest.h"
36
37 using DOM::DocumentImpl;
38 using khtml::CachedObject;
39 using khtml::DocLoader;
40 using khtml::Loader;
41 using khtml::RenderCheckBox;
42 using khtml::RenderFileButton;
43 using khtml::RenderFormElement;
44 using khtml::RenderLineEdit;
45 using khtml::RenderSelect;
46 using khtml::RenderSlider;
47 using khtml::RenderTextArea;
48 using khtml::RenderWidget;
49 using khtml::RenderScrollMediator;
50 using KIO::Job;
51 using KJS::WindowQObject;
52 using KJS::XMLHttpRequestQObject;
53
54 enum FunctionNumber {
55     signalFinishedParsing,
56     slotChildCompleted,
57     slotChildCompletedWithBool,
58     slotChildStarted,
59     slotClicked,
60     slotEndLifeSupport,
61     slotFinishedParsing,
62     slotLoaderRequestDone,
63     slotLoaderRequestStarted,
64     slotParentCompleted,
65     slotParentDestroyed,
66     slotPerformSearch,
67     slotRedirect,
68     slotReturnPressed,
69     slotSelected,
70     slotSelectionChanged,
71     slotSliderValueChanged,
72     slotStateChanged,
73     slotSubmitFormAgain,
74     slotTextChanged,
75     slotTextChangedWithString_RenderLineEdit,
76     slotTextChangedWithString_RenderFileButton,
77     slotValueChanged,
78     slotWidgetDestructed,
79     slotData_Loader,
80     slotData_XMLHttpRequest,
81     slotRedirection_KHTMLPart,
82     slotRedirection_XMLHttpRequest,
83     slotFinished_KHTMLPart,
84     slotFinished_Loader,
85     slotFinished_XMLHttpRequest,
86     slotReceivedResponse,
87     slotAllData
88 };
89
90 KWQSlot::KWQSlot(QObject *object, const char *member)
91 {
92     #define CASE(function, parameters, type) \
93         if (KWQNamesMatch(member, "SLOT:" #function #parameters)) { \
94             ASSERT(dynamic_cast<type *>(object)); \
95             m_function = function; \
96         } else
97     
98     CASE(slotClicked, (), RenderFormElement)
99     CASE(slotChildCompleted, (), KHTMLPart)
100     CASE(slotChildStarted, (KIO::Job *), KHTMLPart)
101     CASE(slotEndLifeSupport, (), KHTMLPart)
102     CASE(slotFinishedParsing, (), KHTMLPart)
103     CASE(slotLoaderRequestDone, (khtml::DocLoader *, khtml::CachedObject *), KHTMLPart)
104     CASE(slotLoaderRequestStarted, (khtml::DocLoader *, khtml::CachedObject *), KHTMLPart)
105     CASE(slotParentCompleted, (), KHTMLPart)
106     CASE(slotPerformSearch, (), RenderLineEdit)
107     CASE(slotRedirect, (), KHTMLPart)
108     CASE(slotReturnPressed, (), RenderLineEdit)
109     CASE(slotSelected, (int), RenderSelect)
110     CASE(slotSelectionChanged, (), RenderSelect)
111     CASE(slotSliderValueChanged, (), RenderSlider)
112     CASE(slotStateChanged, (int), RenderCheckBox)
113     CASE(slotTextChanged, (), RenderTextArea)
114     CASE(slotValueChanged, (int), RenderScrollMediator)
115     CASE(slotWidgetDestructed, (), RenderWidget)
116        
117     #undef CASE
118
119     if (KWQNamesMatch(member, SIGNAL(finishedParsing()))) {
120         ASSERT(dynamic_cast<DocumentImpl *>(object));
121         m_function = signalFinishedParsing;
122     } else if (KWQNamesMatch(member, SLOT(slotChildCompleted(bool)))) {
123         ASSERT(dynamic_cast<KHTMLPart *>(object));
124         m_function = slotChildCompletedWithBool;
125     } else if (KWQNamesMatch(member, SLOT(parentDestroyed()))) {
126         ASSERT(dynamic_cast<WindowQObject *>(object));
127         m_function = slotParentDestroyed;
128     } else if (KWQNamesMatch(member, SLOT(submitFormAgain()))) {
129         ASSERT(dynamic_cast<KHTMLPart *>(object));
130         m_function = slotSubmitFormAgain;
131     } else if (KWQNamesMatch(member, SLOT(slotTextChanged(const QString &)))) {
132         ASSERT(dynamic_cast<RenderLineEdit *>(object) || dynamic_cast<RenderFileButton *>(object));
133         if (dynamic_cast<RenderLineEdit *>(object)) {
134             m_function = slotTextChangedWithString_RenderLineEdit;
135         } else {
136             m_function = slotTextChangedWithString_RenderFileButton;
137         }
138     } else if (KWQNamesMatch(member, SLOT(slotData(KIO::Job *, const char *, int)))) {
139         ASSERT(dynamic_cast<Loader *>(object) || dynamic_cast<XMLHttpRequestQObject *>(object));
140         if (dynamic_cast<Loader *>(object)) {
141             m_function = slotData_Loader;
142         } else {
143             m_function = slotData_XMLHttpRequest;
144         }
145     } else if (KWQNamesMatch(member, SLOT(slotRedirection(KIO::Job *, const KURL&)))) {
146         ASSERT(dynamic_cast<KHTMLPart *>(object) || dynamic_cast<XMLHttpRequestQObject *>(object));
147         if (dynamic_cast<KHTMLPart *>(object)) {
148             m_function = slotRedirection_KHTMLPart;
149         } else {
150             m_function = slotRedirection_XMLHttpRequest;
151         }
152     } else if (KWQNamesMatch(member, SLOT(slotFinished(KIO::Job *)))) {
153         ASSERT(dynamic_cast<khtml::Loader *>(object) || dynamic_cast<KHTMLPart *>(object) || dynamic_cast<XMLHttpRequestQObject *>(object));
154         if (dynamic_cast<khtml::Loader *>(object)) {
155             m_function = slotFinished_Loader;
156         } else if (dynamic_cast<KHTMLPart *>(object)) {
157             m_function = slotFinished_KHTMLPart;
158         } else {
159             m_function = slotFinished_XMLHttpRequest;
160         }
161     } else if (KWQNamesMatch(member, SLOT(slotReceivedResponse(KIO::Job *, NSURLResponse *)))) {
162         ASSERT(dynamic_cast<khtml::Loader *>(object));
163         m_function = slotReceivedResponse;
164     } else if (KWQNamesMatch(member, SLOT(slotAllData(KIO::Job *, NSData *)))) {
165         ASSERT(dynamic_cast<khtml::Loader *>(object));
166         m_function = slotAllData;
167     } else {
168         ERROR("trying to create a slot for unknown member %s", member);
169         return;
170     }
171     
172     m_object = object;
173 }
174     
175 void KWQSlot::call() const
176 {
177     if (m_object.isNull()) {
178         return;
179     }
180     
181     #define CASE(member, type, function) \
182         case member: \
183             static_cast<type *>(m_object.pointer())->function(); \
184             return;
185     
186     switch (m_function) {
187         CASE(signalFinishedParsing, DocumentImpl, m_finishedParsing.call)
188         CASE(slotChildCompleted, KHTMLPart, slotChildCompleted)
189         CASE(slotClicked, RenderFormElement, slotClicked)
190         CASE(slotEndLifeSupport, KHTMLPart, slotEndLifeSupport)
191         CASE(slotFinishedParsing, KHTMLPart, slotFinishedParsing)
192         CASE(slotParentCompleted, KHTMLPart, slotParentCompleted)
193         CASE(slotParentDestroyed, WindowQObject, parentDestroyed)
194         CASE(slotPerformSearch, RenderLineEdit, slotPerformSearch)
195         CASE(slotRedirect, KHTMLPart, slotRedirect)
196         CASE(slotReturnPressed, RenderLineEdit, slotReturnPressed)
197         CASE(slotSelectionChanged, RenderSelect, slotSelectionChanged)
198         CASE(slotSliderValueChanged, RenderSlider, slotSliderValueChanged)
199         CASE(slotSubmitFormAgain, KHTMLPart, submitFormAgain)
200         CASE(slotTextChanged, RenderTextArea, slotTextChanged)
201         CASE(slotWidgetDestructed, RenderWidget, slotWidgetDestructed)
202     }
203     
204     #undef CASE
205 }
206
207 void KWQSlot::call(bool b) const
208 {
209     if (m_object.isNull()) {
210         return;
211     }
212     
213     #define CASE(member, type, function) \
214         case member: \
215             static_cast<type *>(m_object.pointer())->function(b); \
216             return;
217     
218     switch (m_function) {
219         CASE(slotChildCompletedWithBool, KHTMLPart, slotChildCompleted)
220     }
221     
222     #undef CASE
223     
224     call();
225 }
226
227 void KWQSlot::call(int i) const
228 {
229     if (m_object.isNull()) {
230         return;
231     }
232     
233     switch (m_function) {
234         case slotStateChanged:
235             static_cast<RenderCheckBox *>(m_object.pointer())->slotStateChanged(i);
236             return;
237         case slotSelected:
238             static_cast<RenderSelect *>(m_object.pointer())->slotSelected(i);
239             return;
240         case slotValueChanged:
241             static_cast<RenderScrollMediator *>(m_object.pointer())->slotValueChanged(i);
242             return;
243     }
244     
245     call();
246 }
247
248 void KWQSlot::call(const QString &string) const
249 {
250     if (m_object.isNull()) {
251         return;
252     }
253     
254     switch (m_function) {
255         case slotTextChangedWithString_RenderLineEdit:
256             static_cast<RenderLineEdit *>(m_object.pointer())->slotTextChanged(string);
257             return;
258         case slotTextChangedWithString_RenderFileButton:
259             static_cast<RenderFileButton *>(m_object.pointer())->slotTextChanged(string);
260             return;
261     }
262     
263     call();
264 }
265
266 void KWQSlot::call(Job *job) const
267 {
268     if (m_object.isNull()) {
269         return;
270     }
271     
272     switch (m_function) {
273         case slotChildStarted:
274             static_cast<KHTMLPart *>(m_object.pointer())->slotChildStarted(job);
275             return;
276         case slotFinished_KHTMLPart:
277             static_cast<KHTMLPart *>(m_object.pointer())->slotFinished(job);
278             return;
279         case slotFinished_Loader:
280             static_cast<Loader *>(m_object.pointer())->slotFinished(job);
281             return;
282         case slotFinished_XMLHttpRequest:
283             static_cast<XMLHttpRequestQObject *>(m_object.pointer())->slotFinished(job);
284             return;
285     }
286     
287     call();
288 }
289
290 void KWQSlot::call(Job *job, const char *data, int size) const
291 {
292     if (m_object.isNull()) {
293         return;
294     }
295     
296     switch (m_function) {
297         case slotData_Loader:
298             static_cast<Loader *>(m_object.pointer())->slotData(job, data, size);
299             return;
300         case slotData_XMLHttpRequest:
301             static_cast<XMLHttpRequestQObject *>(m_object.pointer())->slotData(job, data, size);
302             return;
303     }
304
305     call();
306 }
307
308 void KWQSlot::call(Job *job, const KURL &url) const
309 {
310     if (m_object.isNull()) {
311         return;
312     }
313     
314     switch (m_function) {
315         case slotRedirection_KHTMLPart:
316             static_cast<KHTMLPart *>(m_object.pointer())->slotRedirection(job, url);
317             return;
318         case slotRedirection_XMLHttpRequest:
319             static_cast<XMLHttpRequestQObject *>(m_object.pointer())->slotRedirection(job, url);
320             return;
321     }
322
323     call();
324 }
325
326 void KWQSlot::call(KIO::Job *job, NSData *data) const
327 {
328     if (m_object.isNull()) {
329         return;
330     }
331     
332     switch (m_function) {
333         case slotAllData:
334             static_cast<Loader *>(m_object.pointer())->slotAllData(job, data);
335             return;
336     }
337     
338     call();
339 }
340
341 void KWQSlot::call(KIO::Job *job, NSURLResponse *response) const
342 {
343     if (m_object.isNull()) {
344         return;
345     }
346     
347     switch (m_function) {
348         case slotReceivedResponse:
349             static_cast<Loader *>(m_object.pointer())->slotReceivedResponse(job, response);
350             return;
351     }
352     
353     call();
354 }
355
356 void KWQSlot::call(DocLoader *loader, CachedObject *cachedObject) const
357 {
358     if (m_object.isNull()) {
359         return;
360     }
361     
362     switch (m_function) {
363         case slotLoaderRequestDone:
364             static_cast<KHTMLPart *>(m_object.pointer())->slotLoaderRequestDone(loader, cachedObject);
365             return;
366         case slotLoaderRequestStarted:
367             static_cast<KHTMLPart *>(m_object.pointer())->slotLoaderRequestStarted(loader, cachedObject);
368             return;
369     }
370     
371     call();
372 }
373
374 bool operator==(const KWQSlot &a, const KWQSlot &b)
375 {
376     return a.m_object == b.m_object && (a.m_object == 0 || a.m_function == b.m_function);
377 }
378
379 bool KWQNamesMatch(const char *a, const char *b)
380 {
381     char ca = *a;
382     char cb = *b;
383     
384     for (;;) {
385         while (ca == ' ') {
386             ca = *++a;
387         }
388         while (cb == ' ') {
389             cb = *++b;
390         }
391         
392         if (ca != cb) {
393             return false;
394         }
395         if (ca == 0) {
396             return true;
397         }
398         
399         ca = *++a;
400         cb = *++b;
401     }
402 }