]> git.saurik.com Git - wxWidgets.git/blame - wxPython/src/helpers.cpp
Added patch to wxPoint_LIST_helper from Tim Hochberg that should make
[wxWidgets.git] / wxPython / src / helpers.cpp
CommitLineData
7bf85405
RD
1/////////////////////////////////////////////////////////////////////////////
2// Name: helpers.cpp
03e9bead 3// Purpose: Helper functions/classes for the wxPython extension module
7bf85405
RD
4//
5// Author: Robin Dunn
6//
7// Created: 7/1/97
8// RCS-ID: $Id$
9// Copyright: (c) 1998 by Total Control Software
10// Licence: wxWindows license
11/////////////////////////////////////////////////////////////////////////////
12
694759cf 13#include <stdio.h> // get the correct definition of NULL
08127323 14
7bf85405
RD
15#undef DEBUG
16#include <Python.h>
17#include "helpers.h"
694759cf 18
af309447
RD
19#ifdef __WXMSW__
20#include <wx/msw/private.h>
21#undef FindWindow
22#undef GetCharWidth
23#undef LoadAccelerators
24#undef GetClassInfo
25#undef GetClassName
26#endif
694759cf
RD
27
28#ifdef __WXGTK__
29#include <gtk/gtk.h>
54b96882
RD
30#include <gdk/gdkprivate.h>
31#include <wx/gtk/win_gtk.h>
32//#include <gdk/gdk.h>
33//#include <gdk/gdkx.h>
34//#include <gtk/gtkwindow.h>
7ff49f0c 35
f6bcfd97 36//extern GtkWidget *wxRootWindow;
7ff49f0c 37
694759cf 38#endif
7bf85405 39
cf694132 40
7bf85405
RD
41
42
21f4bf45 43#ifdef __WXMSW__ // If building for win32...
21f4bf45
RD
44//----------------------------------------------------------------------
45// This gets run when the DLL is loaded. We just need to save a handle.
46//----------------------------------------------------------------------
9c039d08 47
21f4bf45
RD
48BOOL WINAPI DllMain(
49 HINSTANCE hinstDLL, // handle to DLL module
50 DWORD fdwReason, // reason for calling function
51 LPVOID lpvReserved // reserved
52 )
53{
af309447 54 wxSetInstance(hinstDLL);
21f4bf45
RD
55 return 1;
56}
57#endif
58
7bf85405
RD
59//----------------------------------------------------------------------
60// Class for implementing the wxp main application shell.
61//----------------------------------------------------------------------
62
63wxPyApp *wxPythonApp = NULL; // Global instance of application object
64
65
cf694132
RD
66wxPyApp::wxPyApp() {
67// printf("**** ctor\n");
68}
69
70wxPyApp::~wxPyApp() {
71// printf("**** dtor\n");
72}
73
74
7bf85405
RD
75// This one isn't acutally called... See __wxStart()
76bool wxPyApp::OnInit(void) {
6999b0d8 77 return FALSE;
7bf85405
RD
78}
79
80int wxPyApp::MainLoop(void) {
7ff49f0c 81 int retval = 0;
af309447 82
7ff49f0c
RD
83 DeletePendingObjects();
84#ifdef __WXGTK__
85 m_initialized = wxTopLevelWindows.GetCount() != 0;
86#endif
7bf85405 87
7ff49f0c
RD
88 if (Initialized()) {
89 retval = wxApp::MainLoop();
90 wxPythonApp->OnExit();
91 }
92 return retval;
93}
7bf85405
RD
94
95
fb5e0af0 96//---------------------------------------------------------------------
7bf85405
RD
97//----------------------------------------------------------------------
98
de20db99
RD
99#ifdef __WXMSW__
100#include "wx/msw/msvcrt.h"
101#endif
102
103
7ece89c6
RD
104int WXDLLEXPORT wxEntryStart( int argc, char** argv );
105int WXDLLEXPORT wxEntryInitGui();
106void WXDLLEXPORT wxEntryCleanup();
7ff49f0c 107
7bf85405 108
f6bcfd97
BP
109#ifdef WXP_WITH_THREAD
110PyThreadState* wxPyEventThreadState = NULL;
111#endif
f6bcfd97
BP
112
113
0d6f9504 114// This is where we pick up the first part of the wxEntry functionality...
f6bcfd97 115// The rest is in __wxStart and __wxCleanup. This function is called when
8bf5d46e 116// wxcmodule is imported. (Before there is a wxApp object.)
0d6f9504 117void __wxPreStart()
7bf85405 118{
de20db99
RD
119
120#ifdef __WXMSW__
121// wxCrtSetDbgFlag(_CRTDBG_LEAK_CHECK_DF);
122#endif
123
9d8bd15f 124#ifdef WXP_WITH_THREAD
1112b0c6 125#if 0 // OLD THREAD STUFF
9d8bd15f 126 PyEval_InitThreads();
f6bcfd97 127 wxPyEventThreadState = PyThreadState_Get();
1112b0c6
RD
128#else
129 PyEval_InitThreads();
130 wxPyEventThreadState = PyThreadState_New(PyThreadState_Get()->interp);
131#endif
9d8bd15f
RD
132#endif
133
0d6f9504
RD
134 // Bail out if there is already windows created. This means that the
135 // toolkit has already been initialized, as in embedding wxPython in
136 // a C++ wxWindows app.
137 if (wxTopLevelWindows.Number() > 0)
138 return;
7bf85405 139
7ff49f0c
RD
140
141 PyObject* sysargv = PySys_GetObject("argv");
142 int argc = PyList_Size(sysargv);
143 char** argv = new char*[argc+1];
144 int x;
145 for(x=0; x<argc; x++)
146 argv[x] = PyString_AsString(PyList_GetItem(sysargv, x));
147 argv[argc] = NULL;
7bf85405 148
7ff49f0c 149 wxEntryStart(argc, argv);
f6bcfd97 150 delete [] argv;
0d6f9504
RD
151}
152
153
7ff49f0c 154
0d6f9504
RD
155// Start the user application, user App's OnInit method is a parameter here
156PyObject* __wxStart(PyObject* /* self */, PyObject* args)
157{
158 PyObject* onInitFunc = NULL;
159 PyObject* arglist;
160 PyObject* result;
161 long bResult;
162
0d6f9504
RD
163 if (!PyArg_ParseTuple(args, "O", &onInitFunc))
164 return NULL;
165
83b18bab 166#if 0 // Try it out without this check, see how it does...
0d6f9504
RD
167 if (wxTopLevelWindows.Number() > 0) {
168 PyErr_SetString(PyExc_TypeError, "Only 1 wxApp per process!");
169 return NULL;
170 }
de20db99 171#endif
0d6f9504
RD
172
173 // This is the next part of the wxEntry functionality...
f6bcfd97
BP
174 PyObject* sysargv = PySys_GetObject("argv");
175 int argc = PyList_Size(sysargv);
176 char** argv = new char*[argc+1];
177 int x;
178 for(x=0; x<argc; x++)
c368d904 179 argv[x] = copystring(PyString_AsString(PyList_GetItem(sysargv, x)));
f6bcfd97
BP
180 argv[argc] = NULL;
181
182 wxPythonApp->argc = argc;
183 wxPythonApp->argv = argv;
0d6f9504 184
7ff49f0c 185 wxEntryInitGui();
7bf85405
RD
186
187 // Call the Python App's OnInit function
188 arglist = PyTuple_New(0);
189 result = PyEval_CallObject(onInitFunc, arglist);
8bf5d46e
RD
190 if (!result) { // an exception was raised.
191 return NULL;
7bf85405
RD
192 }
193
194 if (! PyInt_Check(result)) {
195 PyErr_SetString(PyExc_TypeError, "OnInit should return a boolean value");
196 return NULL;
197 }
198 bResult = PyInt_AS_LONG(result);
199 if (! bResult) {
194fa2ac 200 PyErr_SetString(PyExc_SystemExit, "OnInit returned FALSE, exiting...");
7bf85405
RD
201 return NULL;
202 }
203
13dfc243 204#ifdef __WXGTK__
7ff49f0c 205 wxTheApp->m_initialized = (wxTopLevelWindows.GetCount() > 0);
13dfc243 206#endif
fb5e0af0 207
7bf85405
RD
208 Py_INCREF(Py_None);
209 return Py_None;
210}
211
7ff49f0c
RD
212void __wxCleanup() {
213 wxEntryCleanup();
214}
7bf85405
RD
215
216
217
218PyObject* wxPython_dict;
219PyObject* __wxSetDictionary(PyObject* /* self */, PyObject* args)
220{
221
222 if (!PyArg_ParseTuple(args, "O", &wxPython_dict))
223 return NULL;
224
225 if (!PyDict_Check(wxPython_dict)) {
226 PyErr_SetString(PyExc_TypeError, "_wxSetDictionary must have dictionary object!");
227 return NULL;
228 }
229#ifdef __WXMOTIF__
21f4bf45
RD
230#define wxPlatform "__WXMOTIF__"
231#endif
232#ifdef __WXQT__
233#define wxPlatform "__WXQT__"
7bf85405
RD
234#endif
235#ifdef __WXGTK__
21f4bf45 236#define wxPlatform "__WXGTK__"
7bf85405
RD
237#endif
238#if defined(__WIN32__) || defined(__WXMSW__)
fb5e0af0 239#define wxPlatform "__WXMSW__"
7bf85405
RD
240#endif
241#ifdef __WXMAC__
21f4bf45 242#define wxPlatform "__WXMAC__"
7bf85405
RD
243#endif
244
245 PyDict_SetItemString(wxPython_dict, "wxPlatform", PyString_FromString(wxPlatform));
246
247 Py_INCREF(Py_None);
248 return Py_None;
249}
250
251
252//---------------------------------------------------------------------------
253
c368d904 254PyObject* wxPyConstructObject(void* ptr,
1e7ecb7b
RD
255 const char* className,
256 int setThisOwn) {
33510773
RD
257 PyObject* obj;
258 PyObject* arg;
259
260 if (!ptr) {
261 Py_INCREF(Py_None);
262 return Py_None;
263 }
264
9c039d08 265 char buff[64]; // should always be big enough...
7bf85405
RD
266 char swigptr[64];
267
268 sprintf(buff, "_%s_p", className);
269 SWIG_MakePtr(swigptr, ptr, buff);
270
271 sprintf(buff, "%sPtr", className);
272 PyObject* classobj = PyDict_GetItemString(wxPython_dict, buff);
273 if (! classobj) {
33510773
RD
274 //Py_INCREF(Py_None);
275 //return Py_None;
276 char temp[128];
277 sprintf(temp,
278 "*** Unknown class name %s, tell Robin about it please ***",
279 buff);
280 obj = PyString_FromString(temp);
281 return obj;
7bf85405
RD
282 }
283
33510773
RD
284 arg = Py_BuildValue("(s)", swigptr);
285 obj = PyInstance_New(classobj, arg, NULL);
7bf85405
RD
286 Py_DECREF(arg);
287
c368d904 288 if (setThisOwn) {
de20db99
RD
289 PyObject* one = PyInt_FromLong(1);
290 PyObject_SetAttrString(obj, "thisown", one);
291 Py_DECREF(one);
c368d904
RD
292 }
293
7bf85405
RD
294 return obj;
295}
296
d559219f 297//---------------------------------------------------------------------------
7bf85405 298
99a49d3e
RD
299static PyThreadState* myPyThreadState_Get() {
300 PyThreadState* current;
301 current = PyThreadState_Swap(NULL);
302 PyThreadState_Swap(current);
303 return current;
304}
d559219f 305
99a49d3e 306
bdb9373a 307bool wxPyRestoreThread() {
d559219f
RD
308 // NOTE: The Python API docs state that if a thread already has the
309 // interpreter lock and calls PyEval_RestoreThread again a deadlock
99a49d3e
RD
310 // occurs, so I put in this code as a guard condition since there are
311 // many possibilites for nested events and callbacks in wxPython. If
312 // The current thread is our thread, then we can assume that we
2abc0a0f 313 // already have the lock. (I hope!)
d559219f 314 //
cf694132 315#ifdef WXP_WITH_THREAD
1112b0c6 316#if 0 // OLD THREAD STUFF
99a49d3e
RD
317 if (wxPyEventThreadState != myPyThreadState_Get()) {
318 PyEval_RestoreThread(wxPyEventThreadState);
319 return TRUE;
320 }
321 else
1112b0c6
RD
322#else
323 if (wxPyEventThreadState != myPyThreadState_Get()) {
324 PyEval_AcquireThread(wxPyEventThreadState);
325 return TRUE;
326 }
327 else
328#endif
cf694132 329#endif
d559219f
RD
330 return FALSE;
331}
cf694132 332
cf694132 333
bdb9373a 334void wxPySaveThread(bool doSave) {
cf694132 335#ifdef WXP_WITH_THREAD
1112b0c6 336#if 0 // OLD THREAD STUFF
99a49d3e 337 if (doSave) {
9d8bd15f 338 wxPyEventThreadState = PyEval_SaveThread();
99a49d3e 339 }
1112b0c6
RD
340#else
341 if (doSave) {
342 PyEval_ReleaseThread(wxPyEventThreadState);
343 }
344#endif
cf694132
RD
345#endif
346}
347
d559219f
RD
348//---------------------------------------------------------------------------
349
350
2f90df85
RD
351IMPLEMENT_ABSTRACT_CLASS(wxPyCallback, wxObject);
352
d559219f
RD
353wxPyCallback::wxPyCallback(PyObject* func) {
354 m_func = func;
355 Py_INCREF(m_func);
356}
357
2f90df85
RD
358wxPyCallback::wxPyCallback(const wxPyCallback& other) {
359 m_func = other.m_func;
360 Py_INCREF(m_func);
361}
362
d559219f
RD
363wxPyCallback::~wxPyCallback() {
364 bool doSave = wxPyRestoreThread();
365 Py_DECREF(m_func);
366 wxPySaveThread(doSave);
367}
368
cf694132
RD
369
370
7bf85405
RD
371// This function is used for all events destined for Python event handlers.
372void wxPyCallback::EventThunker(wxEvent& event) {
373 wxPyCallback* cb = (wxPyCallback*)event.m_callbackUserData;
374 PyObject* func = cb->m_func;
375 PyObject* result;
376 PyObject* arg;
377 PyObject* tuple;
378
cf694132 379
d559219f 380 bool doSave = wxPyRestoreThread();
65dd82cb
RD
381 wxString className = event.GetClassInfo()->GetClassName();
382
383 if (className == "wxPyEvent")
384 arg = ((wxPyEvent*)&event)->GetSelf();
385 else if (className == "wxPyCommandEvent")
386 arg = ((wxPyCommandEvent*)&event)->GetSelf();
387 else
388 arg = wxPyConstructObject((void*)&event, className);
7bf85405
RD
389
390 tuple = PyTuple_New(1);
391 PyTuple_SET_ITEM(tuple, 0, arg);
392 result = PyEval_CallObject(func, tuple);
7bf85405
RD
393 Py_DECREF(tuple);
394 if (result) {
395 Py_DECREF(result);
396 PyErr_Clear();
397 } else {
398 PyErr_Print();
399 }
d559219f 400 wxPySaveThread(doSave);
7bf85405
RD
401}
402
403
d559219f 404//----------------------------------------------------------------------
7bf85405 405
2f90df85
RD
406wxPyCallbackHelper::wxPyCallbackHelper(const wxPyCallbackHelper& other) {
407 m_lastFound = NULL;
408 m_self = other.m_self;
f6bcfd97
BP
409 m_class = other.m_class;
410 if (m_self) {
2f90df85 411 Py_INCREF(m_self);
f6bcfd97
BP
412 Py_INCREF(m_class);
413 }
2f90df85
RD
414}
415
416
33510773 417void wxPyCallbackHelper::setSelf(PyObject* self, PyObject* klass, int incref) {
d559219f 418 m_self = self;
33510773 419 m_class = klass;
b7312675 420 m_incRef = incref;
f6bcfd97 421 if (incref) {
2f90df85 422 Py_INCREF(m_self);
f6bcfd97
BP
423 Py_INCREF(m_class);
424 }
d559219f 425}
8bf5d46e 426
8bf5d46e 427
f6bcfd97
BP
428// If the object (m_self) has an attibute of the given name, and if that
429// attribute is a method, and if that method's class is not from a base class,
430// then we'll save a pointer to the method so callCallback can call it.
de20db99 431bool wxPyCallbackHelper::findCallback(const char* name) const {
f6bcfd97
BP
432 wxPyCallbackHelper* self = (wxPyCallbackHelper*)this; // cast away const
433 self->m_lastFound = NULL;
de20db99 434 if (m_self && PyObject_HasAttrString(m_self, (char*)name)) {
f6bcfd97 435 PyObject* method;
de20db99 436 method = PyObject_GetAttrString(m_self, (char*)name);
f6bcfd97
BP
437
438 if (PyMethod_Check(method) &&
439 ((PyMethod_GET_CLASS(method) == m_class) ||
440 PyClass_IsSubclass(PyMethod_GET_CLASS(method), m_class))) {
8bf5d46e 441
f6bcfd97
BP
442 self->m_lastFound = method;
443 }
de20db99
RD
444 else {
445 Py_DECREF(method);
446 }
f6bcfd97 447 }
d559219f
RD
448 return m_lastFound != NULL;
449}
8bf5d46e 450
d559219f 451
f6bcfd97 452int wxPyCallbackHelper::callCallback(PyObject* argTuple) const {
d559219f
RD
453 PyObject* result;
454 int retval = FALSE;
455
456 result = callCallbackObj(argTuple);
457 if (result) { // Assumes an integer return type...
458 retval = PyInt_AsLong(result);
459 Py_DECREF(result);
460 PyErr_Clear(); // forget about it if it's not...
461 }
462 return retval;
463}
464
465// Invoke the Python callable object, returning the raw PyObject return
466// value. Caller should DECREF the return value and also call PyEval_SaveThread.
f6bcfd97 467PyObject* wxPyCallbackHelper::callCallbackObj(PyObject* argTuple) const {
de20db99 468 PyObject* result;
d559219f 469
de20db99
RD
470 // Save a copy of the pointer in case the callback generates another
471 // callback. In that case m_lastFound will have a different value when
472 // it gets back here...
473 PyObject* method = m_lastFound;
474
475 result = PyEval_CallObject(method, argTuple);
d559219f 476 Py_DECREF(argTuple);
de20db99 477 Py_DECREF(method);
d559219f
RD
478 if (!result) {
479 PyErr_Print();
480 }
481 return result;
482}
714e6a9e 483
7bf85405 484
1e7ecb7b
RD
485void wxPyCBH_setSelf(wxPyCallbackHelper& cbh, PyObject* self, PyObject* klass, int incref) {
486 cbh.setSelf(self, klass, incref);
487}
488
489bool wxPyCBH_findCallback(const wxPyCallbackHelper& cbh, const char* name) {
490 return cbh.findCallback(name);
491}
492
493int wxPyCBH_callCallback(const wxPyCallbackHelper& cbh, PyObject* argTuple) {
494 return cbh.callCallback(argTuple);
495}
496
497PyObject* wxPyCBH_callCallbackObj(const wxPyCallbackHelper& cbh, PyObject* argTuple) {
498 return cbh.callCallbackObj(argTuple);
499}
500
501
502void wxPyCBH_delete(wxPyCallbackHelper* cbh) {
503 bool doSave = wxPyRestoreThread();
504 if (cbh->m_incRef) {
505 Py_XDECREF(cbh->m_self);
506 Py_XDECREF(cbh->m_class);
507 }
508 wxPySaveThread(doSave);
509}
d559219f 510
65dd82cb
RD
511//---------------------------------------------------------------------------
512//---------------------------------------------------------------------------
513// These classes can be derived from in Python and passed through the event
c368d904 514// system without losing anything. They do this by keeping a reference to
65dd82cb
RD
515// themselves and some special case handling in wxPyCallback::EventThunker.
516
517
e19b7164 518wxPyEvtSelfRef::wxPyEvtSelfRef() {
65dd82cb
RD
519 //m_self = Py_None; // **** We don't do normal ref counting to prevent
520 //Py_INCREF(m_self); // circular loops...
194fa2ac 521 m_cloned = FALSE;
65dd82cb
RD
522}
523
e19b7164 524wxPyEvtSelfRef::~wxPyEvtSelfRef() {
65dd82cb
RD
525 bool doSave = wxPyRestoreThread();
526 if (m_cloned)
527 Py_DECREF(m_self);
528 wxPySaveThread(doSave);
529}
530
e19b7164 531void wxPyEvtSelfRef::SetSelf(PyObject* self, bool clone) {
65dd82cb
RD
532 bool doSave = wxPyRestoreThread();
533 if (m_cloned)
534 Py_DECREF(m_self);
535 m_self = self;
536 if (clone) {
537 Py_INCREF(m_self);
538 m_cloned = TRUE;
539 }
540 wxPySaveThread(doSave);
541}
542
e19b7164 543PyObject* wxPyEvtSelfRef::GetSelf() const {
65dd82cb
RD
544 Py_INCREF(m_self);
545 return m_self;
546}
547
548
549wxPyEvent::wxPyEvent(int id)
550 : wxEvent(id) {
551}
552
553wxPyEvent::~wxPyEvent() {
554}
555
556// This one is so the event object can be Cloned...
557void wxPyEvent::CopyObject(wxObject& dest) const {
558 wxEvent::CopyObject(dest);
559 ((wxPyEvent*)&dest)->SetSelf(m_self, TRUE);
560}
561
562
563IMPLEMENT_DYNAMIC_CLASS(wxPyEvent, wxEvent);
564
565
566wxPyCommandEvent::wxPyCommandEvent(wxEventType commandType, int id)
567 : wxCommandEvent(commandType, id) {
568}
569
570wxPyCommandEvent::~wxPyCommandEvent() {
571}
572
573void wxPyCommandEvent::CopyObject(wxObject& dest) const {
574 wxCommandEvent::CopyObject(dest);
575 ((wxPyCommandEvent*)&dest)->SetSelf(m_self, TRUE);
576}
577
578
579IMPLEMENT_DYNAMIC_CLASS(wxPyCommandEvent, wxCommandEvent);
580
581
582
d559219f 583//---------------------------------------------------------------------------
7bf85405
RD
584//---------------------------------------------------------------------------
585
d559219f 586
7bf85405
RD
587wxPyTimer::wxPyTimer(PyObject* callback) {
588 func = callback;
589 Py_INCREF(func);
590}
591
592wxPyTimer::~wxPyTimer() {
d559219f 593 bool doSave = wxPyRestoreThread();
7bf85405 594 Py_DECREF(func);
d559219f 595 wxPySaveThread(doSave);
7bf85405
RD
596}
597
598void wxPyTimer::Notify() {
185d7c3e
RD
599 if (!func || func == Py_None) {
600 wxTimer::Notify();
601 }
602 else {
603 bool doSave = wxPyRestoreThread();
604
605 PyObject* result;
606 PyObject* args = Py_BuildValue("()");
607
608 result = PyEval_CallObject(func, args);
609 Py_DECREF(args);
610 if (result) {
611 Py_DECREF(result);
612 PyErr_Clear();
613 } else {
614 PyErr_Print();
615 }
7bf85405 616
185d7c3e 617 wxPySaveThread(doSave);
7bf85405
RD
618 }
619}
620
621
cf694132 622
2f90df85 623//---------------------------------------------------------------------------
389c5527
RD
624//---------------------------------------------------------------------------
625// Convert a wxList to a Python List
626
65dd82cb 627PyObject* wxPy_ConvertList(wxListBase* list, const char* className) {
389c5527
RD
628 PyObject* pyList;
629 PyObject* pyObj;
630 wxObject* wxObj;
631 wxNode* node = list->First();
632
633 bool doSave = wxPyRestoreThread();
634 pyList = PyList_New(0);
635 while (node) {
636 wxObj = node->Data();
637 pyObj = wxPyConstructObject(wxObj, className);
638 PyList_Append(pyList, pyObj);
639 node = node->Next();
640 }
641 wxPySaveThread(doSave);
642 return pyList;
643}
644
54b96882
RD
645//----------------------------------------------------------------------
646
647long wxPyGetWinHandle(wxWindow* win) {
648#ifdef __WXMSW__
649 return (long)win->GetHandle();
650#endif
651
652 // Find and return the actual X-Window.
653#ifdef __WXGTK__
654 if (win->m_wxwindow) {
655 GdkWindowPrivate* bwin = (GdkWindowPrivate*)GTK_PIZZA(win->m_wxwindow)->bin_window;
656 if (bwin) {
657 return (long)bwin->xwindow;
658 }
659 }
660#endif
661 return 0;
662}
663
7bf85405
RD
664//----------------------------------------------------------------------
665// Some helper functions for typemaps in my_typemaps.i, so they won't be
389c5527 666// included in every file...
7bf85405
RD
667
668
2f90df85 669byte* byte_LIST_helper(PyObject* source) {
b639c3c5
RD
670 if (!PyList_Check(source)) {
671 PyErr_SetString(PyExc_TypeError, "Expected a list object.");
672 return NULL;
673 }
674 int count = PyList_Size(source);
675 byte* temp = new byte[count];
676 if (! temp) {
677 PyErr_SetString(PyExc_MemoryError, "Unable to allocate temporary array");
678 return NULL;
679 }
680 for (int x=0; x<count; x++) {
681 PyObject* o = PyList_GetItem(source, x);
682 if (! PyInt_Check(o)) {
683 PyErr_SetString(PyExc_TypeError, "Expected a list of integers.");
684 return NULL;
685 }
686 temp[x] = (byte)PyInt_AsLong(o);
687 }
688 return temp;
689}
690
691
2f90df85 692int* int_LIST_helper(PyObject* source) {
7bf85405
RD
693 if (!PyList_Check(source)) {
694 PyErr_SetString(PyExc_TypeError, "Expected a list object.");
695 return NULL;
696 }
697 int count = PyList_Size(source);
698 int* temp = new int[count];
699 if (! temp) {
700 PyErr_SetString(PyExc_MemoryError, "Unable to allocate temporary array");
701 return NULL;
702 }
703 for (int x=0; x<count; x++) {
704 PyObject* o = PyList_GetItem(source, x);
705 if (! PyInt_Check(o)) {
706 PyErr_SetString(PyExc_TypeError, "Expected a list of integers.");
707 return NULL;
708 }
709 temp[x] = PyInt_AsLong(o);
710 }
711 return temp;
712}
713
714
2f90df85 715long* long_LIST_helper(PyObject* source) {
7bf85405
RD
716 if (!PyList_Check(source)) {
717 PyErr_SetString(PyExc_TypeError, "Expected a list object.");
718 return NULL;
719 }
720 int count = PyList_Size(source);
721 long* temp = new long[count];
722 if (! temp) {
723 PyErr_SetString(PyExc_MemoryError, "Unable to allocate temporary array");
724 return NULL;
725 }
726 for (int x=0; x<count; x++) {
727 PyObject* o = PyList_GetItem(source, x);
728 if (! PyInt_Check(o)) {
729 PyErr_SetString(PyExc_TypeError, "Expected a list of integers.");
730 return NULL;
731 }
732 temp[x] = PyInt_AsLong(o);
733 }
734 return temp;
735}
736
737
2f90df85 738char** string_LIST_helper(PyObject* source) {
7bf85405
RD
739 if (!PyList_Check(source)) {
740 PyErr_SetString(PyExc_TypeError, "Expected a list object.");
741 return NULL;
742 }
743 int count = PyList_Size(source);
744 char** temp = new char*[count];
745 if (! temp) {
746 PyErr_SetString(PyExc_MemoryError, "Unable to allocate temporary array");
747 return NULL;
748 }
749 for (int x=0; x<count; x++) {
750 PyObject* o = PyList_GetItem(source, x);
751 if (! PyString_Check(o)) {
752 PyErr_SetString(PyExc_TypeError, "Expected a list of strings.");
753 return NULL;
754 }
755 temp[x] = PyString_AsString(o);
756 }
757 return temp;
758}
759
e0672e2f
RD
760//--------------------------------
761// Part of patch from Tim Hochberg
762static inline bool wxPointFromObjects(PyObject* o1, PyObject* o2, wxPoint* point) {
763 if (PyInt_Check(o1) && PyInt_Check(o2)) {
764 point->x = PyInt_AS_LONG(o1);
765 point->y = PyInt_AS_LONG(o2);
766 return true;
767 }
768 if (PyFloat_Check(o1) && PyFloat_Check(o2)) {
769 point->x = (int)PyFloat_AS_DOUBLE(o1);
770 point->y = (int)PyFloat_AS_DOUBLE(o2);
771 return true;
772 }
773 if (PyInstance_Check(o1) || PyInstance_Check(o2)) {
774 // Disallow instances because they can cause havok
775 return false;
776 }
777 if (PyNumber_Check(o1) && PyNumber_Check(o2)) {
778 // I believe this excludes instances, so this should be safe without INCREFFing o1 and o2
779 point->x = PyInt_AsLong(o1);
780 point->y = PyInt_AsLong(o2);
781 return true;
782 }
783 return false;
784}
7bf85405
RD
785
786
e0672e2f
RD
787wxPoint* wxPoint_LIST_helper(PyObject* source, int *count) {
788 // Putting all of the declarations here allows
789 // us to put the error handling all in one place.
790 int x;
791 wxPoint* temp;
792 PyObject *o, *o1, *o2;
793 int isFast = PyList_Check(source) || PyTuple_Check(source);
794
795 // The length of the sequence is returned in count.
796 if (!PySequence_Check(source)) {
797 goto error0;
7bf85405 798 }
e0672e2f
RD
799 *count = PySequence_Length(source);
800 if (*count < 0) {
801 goto error0;
802 }
803
804 temp = new wxPoint[*count];
805 if (!temp) {
7bf85405
RD
806 PyErr_SetString(PyExc_MemoryError, "Unable to allocate temporary array");
807 return NULL;
808 }
e0672e2f
RD
809 for (x=0; x<*count; x++) {
810 // Get an item: try fast way first.
811 if (isFast) {
812 o = PySequence_Fast_GET_ITEM(source, x);
813 }
814 else {
815 o = PySequence_GetItem(source, x);
816 if (o == NULL) {
817 goto error1;
818 }
819 }
7bf85405 820
e0672e2f
RD
821 // Convert o to wxPoint.
822 if ((PyTuple_Check(o) && PyTuple_GET_SIZE(o) == 2) ||
823 (PyList_Check(o) && PyList_GET_SIZE(o) == 2)) {
824 o1 = PySequence_Fast_GET_ITEM(o, 0);
825 o2 = PySequence_Fast_GET_ITEM(o, 1);
826 if (!wxPointFromObjects(o1, o2, &temp[x])) {
827 goto error2;
828 }
7bf85405 829 }
d559219f
RD
830 else if (PyInstance_Check(o)) {
831 wxPoint* pt;
e0672e2f
RD
832 if (SWIG_GetPtrObj(o, (void **)&pt, "_wxPoint_p")) {
833 goto error2;
d559219f
RD
834 }
835 temp[x] = *pt;
836 }
e0672e2f
RD
837 else if (PySequence_Check(o) && PySequence_Length(o) == 2) {
838 o1 = PySequence_GetItem(o, 0);
839 o2 = PySequence_GetItem(o, 1);
840 if (!wxPointFromObjects(o1, o2, &temp[x])) {
841 goto error3;
842 }
843 Py_DECREF(o1);
844 Py_DECREF(o2);
845 }
7bf85405 846 else {
e0672e2f 847 goto error2;
7bf85405 848 }
e0672e2f
RD
849 // Clean up.
850 if (!isFast)
851 Py_DECREF(o);
7bf85405
RD
852 }
853 return temp;
e0672e2f
RD
854
855error3:
856 Py_DECREF(o1);
857 Py_DECREF(o2);
858error2:
859 if (!isFast)
860 Py_DECREF(o);
861error1:
862 delete temp;
863error0:
864 PyErr_SetString(PyExc_TypeError, "Expected a sequence of length-2 sequences or wxPoints.");
865 return NULL;
7bf85405 866}
e0672e2f
RD
867// end of patch
868//------------------------------
7bf85405
RD
869
870
2f90df85 871wxBitmap** wxBitmap_LIST_helper(PyObject* source) {
7bf85405
RD
872 if (!PyList_Check(source)) {
873 PyErr_SetString(PyExc_TypeError, "Expected a list object.");
874 return NULL;
875 }
876 int count = PyList_Size(source);
877 wxBitmap** temp = new wxBitmap*[count];
878 if (! temp) {
879 PyErr_SetString(PyExc_MemoryError, "Unable to allocate temporary array");
880 return NULL;
881 }
882 for (int x=0; x<count; x++) {
883 PyObject* o = PyList_GetItem(source, x);
e166644c 884 if (PyInstance_Check(o)) {
7bf85405 885 wxBitmap* pt;
e166644c 886 if (SWIG_GetPtrObj(o, (void **) &pt,"_wxBitmap_p")) {
7bf85405
RD
887 PyErr_SetString(PyExc_TypeError,"Expected _wxBitmap_p.");
888 return NULL;
889 }
890 temp[x] = pt;
891 }
892 else {
893 PyErr_SetString(PyExc_TypeError, "Expected a list of wxBitmaps.");
894 return NULL;
895 }
896 }
897 return temp;
898}
899
900
901
2f90df85 902wxString* wxString_LIST_helper(PyObject* source) {
7bf85405
RD
903 if (!PyList_Check(source)) {
904 PyErr_SetString(PyExc_TypeError, "Expected a list object.");
905 return NULL;
906 }
907 int count = PyList_Size(source);
908 wxString* temp = new wxString[count];
909 if (! temp) {
910 PyErr_SetString(PyExc_MemoryError, "Unable to allocate temporary array");
911 return NULL;
912 }
913 for (int x=0; x<count; x++) {
914 PyObject* o = PyList_GetItem(source, x);
915 if (! PyString_Check(o)) {
916 PyErr_SetString(PyExc_TypeError, "Expected a list of strings.");
917 return NULL;
918 }
919 temp[x] = PyString_AsString(o);
920 }
921 return temp;
922}
923
924
2f90df85 925wxAcceleratorEntry* wxAcceleratorEntry_LIST_helper(PyObject* source) {
7bf85405
RD
926 if (!PyList_Check(source)) {
927 PyErr_SetString(PyExc_TypeError, "Expected a list object.");
928 return NULL;
929 }
930 int count = PyList_Size(source);
931 wxAcceleratorEntry* temp = new wxAcceleratorEntry[count];
932 if (! temp) {
933 PyErr_SetString(PyExc_MemoryError, "Unable to allocate temporary array");
934 return NULL;
935 }
936 for (int x=0; x<count; x++) {
937 PyObject* o = PyList_GetItem(source, x);
e166644c 938 if (PyInstance_Check(o)) {
7bf85405 939 wxAcceleratorEntry* ae;
e166644c 940 if (SWIG_GetPtrObj(o, (void **) &ae,"_wxAcceleratorEntry_p")) {
7bf85405
RD
941 PyErr_SetString(PyExc_TypeError,"Expected _wxAcceleratorEntry_p.");
942 return NULL;
943 }
944 temp[x] = *ae;
945 }
946 else if (PyTuple_Check(o)) {
947 PyObject* o1 = PyTuple_GetItem(o, 0);
948 PyObject* o2 = PyTuple_GetItem(o, 1);
949 PyObject* o3 = PyTuple_GetItem(o, 2);
950
951 temp[x].m_flags = PyInt_AsLong(o1);
952 temp[x].m_keyCode = PyInt_AsLong(o2);
953 temp[x].m_command = PyInt_AsLong(o3);
954 }
955 else {
956 PyErr_SetString(PyExc_TypeError, "Expected a list of 3-tuples or wxAcceleratorEntry objects.");
957 return NULL;
958 }
959 }
960 return temp;
961}
962
bb0054cd
RD
963
964
965//----------------------------------------------------------------------
bb0054cd 966
2f90df85
RD
967bool wxSize_helper(PyObject* source, wxSize** obj) {
968
969 // If source is an object instance then it may already be the right type
970 if (PyInstance_Check(source)) {
971 wxSize* ptr;
972 if (SWIG_GetPtrObj(source, (void **)&ptr, "_wxSize_p"))
973 goto error;
974 *obj = ptr;
975 return TRUE;
976 }
977 // otherwise a 2-tuple of integers is expected
978 else if (PySequence_Check(source) && PyObject_Length(source) == 2) {
979 PyObject* o1 = PySequence_GetItem(source, 0);
980 PyObject* o2 = PySequence_GetItem(source, 1);
981 **obj = wxSize(PyInt_AsLong(o1), PyInt_AsLong(o2));
982 return TRUE;
983 }
984
985 error:
986 PyErr_SetString(PyExc_TypeError, "Expected a 2-tuple of integers or a wxSize object.");
987 return FALSE;
988}
989
990bool wxPoint_helper(PyObject* source, wxPoint** obj) {
991
992 // If source is an object instance then it may already be the right type
993 if (PyInstance_Check(source)) {
994 wxPoint* ptr;
995 if (SWIG_GetPtrObj(source, (void **)&ptr, "_wxPoint_p"))
996 goto error;
997 *obj = ptr;
998 return TRUE;
999 }
e0672e2f
RD
1000 // otherwise a length-2 sequence of integers is expected
1001 if (PySequence_Check(source) && PySequence_Length(source) == 2) {
2f90df85
RD
1002 PyObject* o1 = PySequence_GetItem(source, 0);
1003 PyObject* o2 = PySequence_GetItem(source, 1);
e0672e2f
RD
1004 // This should really check for integers, not numbers -- but that would break code.
1005 if (!PyNumber_Check(o1) || !PyNumber_Check(o2)) {
1006 Py_DECREF(o1);
1007 Py_DECREF(o2);
1008 goto error;
1009 }
1010 **obj = wxPoint(PyInt_AsLong(o1), PyInt_AsLong(o2));
1011 Py_DECREF(o1);
1012 Py_DECREF(o2);
2f90df85
RD
1013 return TRUE;
1014 }
2f90df85
RD
1015 error:
1016 PyErr_SetString(PyExc_TypeError, "Expected a 2-tuple of integers or a wxPoint object.");
1017 return FALSE;
1018}
1019
1020
1021
1022bool wxRealPoint_helper(PyObject* source, wxRealPoint** obj) {
1023
1024 // If source is an object instance then it may already be the right type
1025 if (PyInstance_Check(source)) {
1026 wxRealPoint* ptr;
1027 if (SWIG_GetPtrObj(source, (void **)&ptr, "_wxRealPoint_p"))
1028 goto error;
1029 *obj = ptr;
1030 return TRUE;
1031 }
1032 // otherwise a 2-tuple of floats is expected
1033 else if (PySequence_Check(source) && PyObject_Length(source) == 2) {
1034 PyObject* o1 = PySequence_GetItem(source, 0);
1035 PyObject* o2 = PySequence_GetItem(source, 1);
1036 **obj = wxRealPoint(PyFloat_AsDouble(o1), PyFloat_AsDouble(o2));
1037 return TRUE;
1038 }
1039
1040 error:
1041 PyErr_SetString(PyExc_TypeError, "Expected a 2-tuple of floats or a wxRealPoint object.");
1042 return FALSE;
1043}
1044
1045
1046
1047
1048bool wxRect_helper(PyObject* source, wxRect** obj) {
1049
1050 // If source is an object instance then it may already be the right type
1051 if (PyInstance_Check(source)) {
1052 wxRect* ptr;
1053 if (SWIG_GetPtrObj(source, (void **)&ptr, "_wxRect_p"))
1054 goto error;
1055 *obj = ptr;
1056 return TRUE;
1057 }
1058 // otherwise a 4-tuple of integers is expected
1059 else if (PySequence_Check(source) && PyObject_Length(source) == 4) {
1060 PyObject* o1 = PySequence_GetItem(source, 0);
1061 PyObject* o2 = PySequence_GetItem(source, 1);
1062 PyObject* o3 = PySequence_GetItem(source, 2);
1063 PyObject* o4 = PySequence_GetItem(source, 3);
1064 **obj = wxRect(PyInt_AsLong(o1), PyInt_AsLong(o2),
1065 PyInt_AsLong(o3), PyInt_AsLong(o4));
1066 return TRUE;
1067 }
1068
1069 error:
1070 PyErr_SetString(PyExc_TypeError, "Expected a 4-tuple of integers or a wxRect object.");
1071 return FALSE;
1072}
1073
1074
1075
f6bcfd97
BP
1076bool wxColour_helper(PyObject* source, wxColour** obj) {
1077
1078 // If source is an object instance then it may already be the right type
1079 if (PyInstance_Check(source)) {
1080 wxColour* ptr;
1081 if (SWIG_GetPtrObj(source, (void **)&ptr, "_wxColour_p"))
1082 goto error;
1083 *obj = ptr;
1084 return TRUE;
1085 }
1086 // otherwise a string is expected
1087 else if (PyString_Check(source)) {
1088 wxString spec = PyString_AS_STRING(source);
1112b0c6 1089 if (spec[0U] == '#' && spec.Length() == 7) { // It's #RRGGBB
f6bcfd97
BP
1090 char* junk;
1091 int red = strtol(spec.Mid(1,2), &junk, 16);
1092 int green = strtol(spec.Mid(3,2), &junk, 16);
1093 int blue = strtol(spec.Mid(5,2), &junk, 16);
1094 **obj = wxColour(red, green, blue);
1095 return TRUE;
1096 }
1097 else { // it's a colour name
1098 **obj = wxColour(spec);
1099 return TRUE;
1100 }
1101 }
1102
1103 error:
de20db99 1104 PyErr_SetString(PyExc_TypeError, "Expected a wxColour object or a string containing a colour name or '#RRGGBB'.");
f6bcfd97
BP
1105 return FALSE;
1106}
1107
1108
bb0054cd
RD
1109//----------------------------------------------------------------------
1110//----------------------------------------------------------------------
7bf85405 1111//----------------------------------------------------------------------
7bf85405 1112
7bf85405 1113
7bf85405 1114
de20db99 1115