0b06bb475c761fb55965c2ebceb11eb48f61c53a
[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 };
88
89 KWQSlot::KWQSlot(QObject *object, const char *member)
90 {
91     #define CASE(function, parameters, type) \
92         if (KWQNamesMatch(member, "SLOT:" #function #parameters)) { \
93             ASSERT(dynamic_cast<type *>(object)); \
94             m_function = function; \
95         } else
96     
97     CASE(slotClicked, (), RenderFormElement)
98     CASE(slotChildCompleted, (), KHTMLPart)
99     CASE(slotChildStarted, (KIO::Job *), KHTMLPart)
100     CASE(slotEndLifeSupport, (), KHTMLPart)
101     CASE(slotFinishedParsing, (), KHTMLPart)
102     CASE(slotLoaderRequestDone, (khtml::DocLoader *, khtml::CachedObject *), KHTMLPart)
103     CASE(slotLoaderRequestStarted, (khtml::DocLoader *, khtml::CachedObject *), KHTMLPart)
104     CASE(slotParentCompleted, (), KHTMLPart)
105     CASE(slotPerformSearch, (), RenderLineEdit)
106     CASE(slotRedirect, (), KHTMLPart)
107     CASE(slotReturnPressed, (), RenderLineEdit)
108     CASE(slotSelected, (int), RenderSelect)
109     CASE(slotSelectionChanged, (), RenderSelect)
110     CASE(slotSliderValueChanged, (), RenderSlider)
111     CASE(slotStateChanged, (int), RenderCheckBox)
112     CASE(slotTextChanged, (), RenderTextArea)
113     CASE(slotValueChanged, (int), RenderScrollMediator)
114     CASE(slotWidgetDestructed, (), RenderWidget)
115        
116     #undef CASE
117
118     if (KWQNamesMatch(member, SIGNAL(finishedParsing()))) {
119         ASSERT(dynamic_cast<DocumentImpl *>(object));
120         m_function = signalFinishedParsing;
121     } else if (KWQNamesMatch(member, SLOT(slotChildCompleted(bool)))) {
122         ASSERT(dynamic_cast<KHTMLPart *>(object));
123         m_function = slotChildCompletedWithBool;
124     } else if (KWQNamesMatch(member, SLOT(parentDestroyed()))) {
125         ASSERT(dynamic_cast<WindowQObject *>(object));
126         m_function = slotParentDestroyed;
127     } else if (KWQNamesMatch(member, SLOT(submitFormAgain()))) {
128         ASSERT(dynamic_cast<KHTMLPart *>(object));
129         m_function = slotSubmitFormAgain;
130     } else if (KWQNamesMatch(member, SLOT(slotTextChanged(const QString &)))) {
131         ASSERT(dynamic_cast<RenderLineEdit *>(object) || dynamic_cast<RenderFileButton *>(object));
132         if (dynamic_cast<RenderLineEdit *>(object)) {
133             m_function = slotTextChangedWithString_RenderLineEdit;
134         } else {
135             m_function = slotTextChangedWithString_RenderFileButton;
136         }
137     } else if (KWQNamesMatch(member, SLOT(slotData(KIO::Job *, const char *, int)))) {
138         ASSERT(dynamic_cast<Loader *>(object) || dynamic_cast<XMLHttpRequestQObject *>(object));
139         if (dynamic_cast<Loader *>(object)) {
140             m_function = slotData_Loader;
141         } else {
142             m_function = slotData_XMLHttpRequest;
143         }
144     } else if (KWQNamesMatch(member, SLOT(slotRedirection(KIO::Job *, const KURL&)))) {
145         ASSERT(dynamic_cast<KHTMLPart *>(object) || dynamic_cast<XMLHttpRequestQObject *>(object));
146         if (dynamic_cast<KHTMLPart *>(object)) {
147             m_function = slotRedirection_KHTMLPart;
148         } else {
149             m_function = slotRedirection_XMLHttpRequest;
150         }
151     } else if (KWQNamesMatch(member, SLOT(slotFinished(KIO::Job *)))) {
152         ASSERT(dynamic_cast<khtml::Loader *>(object) || dynamic_cast<KHTMLPart *>(object) || dynamic_cast<XMLHttpRequestQObject *>(object));
153         if (dynamic_cast<khtml::Loader *>(object)) {
154             m_function = slotFinished_Loader;
155         } else if (dynamic_cast<KHTMLPart *>(object)) {
156             m_function = slotFinished_KHTMLPart;
157         } else {
158             m_function = slotFinished_XMLHttpRequest;
159         }
160     } else if (KWQNamesMatch(member, SLOT(slotReceivedResponse(KIO::Job *, void *)))) {
161         ASSERT(dynamic_cast<khtml::Loader *>(object));
162         m_function = slotReceivedResponse;
163     } else {
164         ERROR("trying to create a slot for unknown member %s", member);
165         return;
166     }
167     
168     m_object = object;
169 }
170     
171 void KWQSlot::call() const
172 {
173     if (m_object.isNull()) {
174         return;
175     }
176     
177     #define CASE(member, type, function) \
178         case member: \
179             static_cast<type *>(m_object.pointer())->function(); \
180             return;
181     
182     switch (m_function) {
183         CASE(signalFinishedParsing, DocumentImpl, m_finishedParsing.call)
184         CASE(slotChildCompleted, KHTMLPart, slotChildCompleted)
185         CASE(slotClicked, RenderFormElement, slotClicked)
186         CASE(slotEndLifeSupport, KHTMLPart, slotEndLifeSupport)
187         CASE(slotFinishedParsing, KHTMLPart, slotFinishedParsing)
188         CASE(slotParentCompleted, KHTMLPart, slotParentCompleted)
189         CASE(slotParentDestroyed, WindowQObject, parentDestroyed)
190         CASE(slotPerformSearch, RenderLineEdit, slotPerformSearch)
191         CASE(slotRedirect, KHTMLPart, slotRedirect)
192         CASE(slotReturnPressed, RenderLineEdit, slotReturnPressed)
193         CASE(slotSelectionChanged, RenderSelect, slotSelectionChanged)
194         CASE(slotSliderValueChanged, RenderSlider, slotSliderValueChanged)
195         CASE(slotSubmitFormAgain, KHTMLPart, submitFormAgain)
196         CASE(slotTextChanged, RenderTextArea, slotTextChanged)
197         CASE(slotWidgetDestructed, RenderWidget, slotWidgetDestructed)
198     }
199     
200     #undef CASE
201 }
202
203 void KWQSlot::call(bool b) const
204 {
205     if (m_object.isNull()) {
206         return;
207     }
208     
209     #define CASE(member, type, function) \
210         case member: \
211             static_cast<type *>(m_object.pointer())->function(b); \
212             return;
213     
214     switch (m_function) {
215         CASE(slotChildCompletedWithBool, KHTMLPart, slotChildCompleted)
216     }
217     
218     #undef CASE
219     
220     call();
221 }
222
223 void KWQSlot::call(int i) const
224 {
225     if (m_object.isNull()) {
226         return;
227     }
228     
229     switch (m_function) {
230         case slotStateChanged:
231             static_cast<RenderCheckBox *>(m_object.pointer())->slotStateChanged(i);
232             return;
233         case slotSelected:
234             static_cast<RenderSelect *>(m_object.pointer())->slotSelected(i);
235             return;
236         case slotValueChanged:
237             static_cast<RenderScrollMediator *>(m_object.pointer())->slotValueChanged(i);
238             return;
239     }
240     
241     call();
242 }
243
244 void KWQSlot::call(const QString &string) const
245 {
246     if (m_object.isNull()) {
247         return;
248     }
249     
250     switch (m_function) {
251         case slotTextChangedWithString_RenderLineEdit:
252             static_cast<RenderLineEdit *>(m_object.pointer())->slotTextChanged(string);
253             return;
254         case slotTextChangedWithString_RenderFileButton:
255             static_cast<RenderFileButton *>(m_object.pointer())->slotTextChanged(string);
256             return;
257     }
258     
259     call();
260 }
261
262 void KWQSlot::call(Job *job) const
263 {
264     if (m_object.isNull()) {
265         return;
266     }
267     
268     switch (m_function) {
269         case slotChildStarted:
270             static_cast<KHTMLPart *>(m_object.pointer())->slotChildStarted(job);
271             return;
272         case slotFinished_KHTMLPart:
273             static_cast<KHTMLPart *>(m_object.pointer())->slotFinished(job);
274             return;
275         case slotFinished_Loader:
276             static_cast<Loader *>(m_object.pointer())->slotFinished(job);
277             return;
278         case slotFinished_XMLHttpRequest:
279             static_cast<XMLHttpRequestQObject *>(m_object.pointer())->slotFinished(job);
280             return;
281     }
282     
283     call();
284 }
285
286 void KWQSlot::call(Job *job, const char *data, int size) const
287 {
288     if (m_object.isNull()) {
289         return;
290     }
291     
292     switch (m_function) {
293         case slotData_Loader:
294             static_cast<Loader *>(m_object.pointer())->slotData(job, data, size);
295             return;
296         case slotData_XMLHttpRequest:
297             static_cast<XMLHttpRequestQObject *>(m_object.pointer())->slotData(job, data, size);
298             return;
299     }
300
301     call();
302 }
303
304 void KWQSlot::call(Job *job, const KURL &url) const
305 {
306     if (m_object.isNull()) {
307         return;
308     }
309     
310     switch (m_function) {
311         case slotRedirection_KHTMLPart:
312             static_cast<KHTMLPart *>(m_object.pointer())->slotRedirection(job, url);
313             return;
314         case slotRedirection_XMLHttpRequest:
315             static_cast<XMLHttpRequestQObject *>(m_object.pointer())->slotRedirection(job, url);
316             return;
317     }
318
319     call();
320 }
321
322 void KWQSlot::call(KIO::Job *job, void *response) const
323 {
324     if (m_object.isNull()) {
325         return;
326     }
327     
328     switch (m_function) {
329         case slotReceivedResponse:
330             static_cast<Loader *>(m_object.pointer())->slotReceivedResponse(job, response);
331             return;
332     }
333
334     call();
335 }
336
337 void KWQSlot::call(DocLoader *loader, CachedObject *cachedObject) const
338 {
339     if (m_object.isNull()) {
340         return;
341     }
342     
343     switch (m_function) {
344         case slotLoaderRequestDone:
345             static_cast<KHTMLPart *>(m_object.pointer())->slotLoaderRequestDone(loader, cachedObject);
346             return;
347         case slotLoaderRequestStarted:
348             static_cast<KHTMLPart *>(m_object.pointer())->slotLoaderRequestStarted(loader, cachedObject);
349             return;
350     }
351     
352     call();
353 }
354
355 bool operator==(const KWQSlot &a, const KWQSlot &b)
356 {
357     return a.m_object == b.m_object && (a.m_object == 0 || a.m_function == b.m_function);
358 }
359
360 bool KWQNamesMatch(const char *a, const char *b)
361 {
362     char ca = *a;
363     char cb = *b;
364     
365     for (;;) {
366         while (ca == ' ') {
367             ca = *++a;
368         }
369         while (cb == ' ') {
370             cb = *++b;
371         }
372         
373         if (ca != cb) {
374             return false;
375         }
376         if (ca == 0) {
377             return true;
378         }
379         
380         ca = *++a;
381         cb = *++b;
382     }
383 }