]> git.saurik.com Git - wxWidgets.git/blob - utils/wxPython/src/helpers.cpp
e0840d7b2b6be727c64217ba8be6e719ed176167
[wxWidgets.git] / utils / wxPython / src / helpers.cpp
1 /////////////////////////////////////////////////////////////////////////////
2 // Name: helpers.cpp
3 // Purpose: Helper functions/classes for the wxPython extension module
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
13 #ifdef __WXMSW__
14 #include <windows.h>
15 #undef FindWindow
16 #undef GetCharWidth
17 #undef LoadAccelerators
18 #endif
19
20 #undef DEBUG
21 #include <Python.h>
22 #include "helpers.h"
23
24 #ifdef __WXGTK__
25 #ifdef USE_GDK_IMLIB
26 #include "gdk_imlib/gdk_imlib.h"
27 #endif
28 #endif
29
30 //---------------------------------------------------------------------------
31
32 //wxHashTable* wxPyWindows = NULL;
33
34
35 wxPoint wxPyDefaultPosition; //wxDefaultPosition);
36 wxSize wxPyDefaultSize; //wxDefaultSize);
37 wxString wxPyEmptyStr("");
38
39
40
41 #ifdef __WXMSW__ // If building for win32...
42 extern HINSTANCE wxhInstance;
43
44 //----------------------------------------------------------------------
45 // This gets run when the DLL is loaded. We just need to save a handle.
46 //----------------------------------------------------------------------
47 BOOL WINAPI DllMain(
48 HINSTANCE hinstDLL, // handle to DLL module
49 DWORD fdwReason, // reason for calling function
50 LPVOID lpvReserved // reserved
51 )
52 {
53 wxhInstance = hinstDLL;
54 return 1;
55 }
56 #endif
57
58 //----------------------------------------------------------------------
59 // Class for implementing the wxp main application shell.
60 //----------------------------------------------------------------------
61
62 wxPyApp *wxPythonApp = NULL; // Global instance of application object
63
64
65 // This one isn't acutally called... See __wxStart()
66 bool wxPyApp::OnInit(void) {
67 return false;
68 }
69
70 int wxPyApp::MainLoop(void) {
71 int retval = wxApp::MainLoop();
72 AfterMainLoop();
73 return retval;
74 }
75
76 void wxPyApp::AfterMainLoop(void) {
77 // more stuff from wxEntry...
78 if (wxPythonApp->GetTopWindow()) {
79 // Forcibly delete the window.
80 if (wxPythonApp->GetTopWindow()->IsKindOf(CLASSINFO(wxFrame)) ||
81 wxPythonApp->GetTopWindow()->IsKindOf(CLASSINFO(wxDialog))) {
82
83 wxPythonApp->GetTopWindow()->Close(TRUE);
84 wxPythonApp->DeletePendingObjects();
85 }
86 else {
87 delete wxPythonApp->GetTopWindow();
88 wxPythonApp->SetTopWindow(NULL);
89 }
90 }
91
92 wxPythonApp->OnExit();
93 #ifdef __WXMSW__
94 wxApp::CleanUp();
95 #endif
96 #ifdef __WXGTK__
97 wxApp::CommonCleanUp();
98 #endif
99 delete wxPythonApp;
100 }
101
102
103 //---------------------------------------------------------------------
104 // a few native methods to add to the module
105 //----------------------------------------------------------------------
106
107
108
109 // Start the user application, user App's OnInit method is a parameter here
110 PyObject* __wxStart(PyObject* /* self */, PyObject* args)
111 {
112 PyObject* onInitFunc = NULL;
113 PyObject* arglist;
114 PyObject* result;
115 long bResult;
116
117 if (!PyArg_ParseTuple(args, "O", &onInitFunc))
118 return NULL;
119
120 // This is where we pick up one part of the wxEntry functionality...
121 // the rest is in AfterMainLoop.
122 #ifdef __WXMSW__
123 wxApp::Initialize((WXHINSTANCE)wxhInstance);
124
125 wxPythonApp->argc = 0;
126 wxPythonApp->argv = NULL;
127 wxPythonApp->OnInitGui();
128 #endif
129 #ifdef __WXGTK__
130 wxClassInfo::InitializeClasses();
131
132 PyObject* sysargv = PySys_GetObject("argv");
133 int argc = PyList_Size(sysargv);
134 char** argv = new char*[argc+1];
135 int x;
136 for(x=0; x<argc; x++)
137 argv[x] = PyString_AsString(PyList_GetItem(sysargv, x));
138 argv[argc] = NULL;
139
140
141 wxPythonApp->argc = argc;
142 wxPythonApp->argv = argv;
143
144 gtk_init( &wxPythonApp->argc, &wxPythonApp->argv );
145
146 #ifdef USE_GDK_IMLIB
147 gdk_imlib_init();
148 gtk_widget_push_visual(gdk_imlib_get_visual());
149 gtk_widget_push_colormap(gdk_imlib_get_colormap());
150 #endif
151
152 wxApp::CommonInit();
153 wxTheApp->OnInitGui();
154
155 #endif
156
157
158 // Call the Python App's OnInit function
159 arglist = PyTuple_New(0);
160 result = PyEval_CallObject(onInitFunc, arglist);
161 if (!result) {
162 PyErr_Print();
163 exit(1);
164 }
165
166 if (! PyInt_Check(result)) {
167 PyErr_SetString(PyExc_TypeError, "OnInit should return a boolean value");
168 return NULL;
169 }
170 bResult = PyInt_AS_LONG(result);
171 if (! bResult) {
172 wxPythonApp->DeletePendingObjects();
173 wxPythonApp->OnExit();
174 #ifdef __WXMSW__
175 wxApp::CleanUp();
176 #endif
177 #ifdef __WXGTK__
178 wxApp::CommonCleanUp();
179 #endif
180 PyErr_SetString(PyExc_SystemExit, "OnInit returned false, exiting...");
181 return NULL;
182 }
183
184 #ifdef __WXGTK__
185 wxTheApp->m_initialized = (wxTopLevelWindows.Number() > 0);
186 #endif
187
188 Py_INCREF(Py_None);
189 return Py_None;
190 }
191
192
193
194
195
196 PyObject* wxPython_dict;
197 PyObject* __wxSetDictionary(PyObject* /* self */, PyObject* args)
198 {
199
200 if (!PyArg_ParseTuple(args, "O", &wxPython_dict))
201 return NULL;
202
203 if (!PyDict_Check(wxPython_dict)) {
204 PyErr_SetString(PyExc_TypeError, "_wxSetDictionary must have dictionary object!");
205 return NULL;
206 }
207 #ifdef __WXMOTIF__
208 #define wxPlatform "__WXMOTIF__"
209 #endif
210 #ifdef __WXQT__
211 #define wxPlatform "__WXQT__"
212 #endif
213 #ifdef __WXGTK__
214 #define wxPlatform "__WXGTK__"
215 #endif
216 #if defined(__WIN32__) || defined(__WXMSW__)
217 #define wxPlatform "__WXMSW__"
218 #endif
219 #ifdef __WXMAC__
220 #define wxPlatform "__WXMAC__"
221 #endif
222
223 PyDict_SetItemString(wxPython_dict, "wxPlatform", PyString_FromString(wxPlatform));
224
225 Py_INCREF(Py_None);
226 return Py_None;
227 }
228
229
230 //---------------------------------------------------------------------------
231
232
233 static
234 PyObject* wxPyConstructObject(void* ptr, char* className)
235 {
236 char buff[64]; // should be big enough...
237 char swigptr[64];
238
239 sprintf(buff, "_%s_p", className);
240 SWIG_MakePtr(swigptr, ptr, buff);
241
242 sprintf(buff, "%sPtr", className);
243 PyObject* classobj = PyDict_GetItemString(wxPython_dict, buff);
244 if (! classobj) {
245 Py_INCREF(Py_None);
246 return Py_None;
247 }
248
249 PyObject* arg = Py_BuildValue("(s)", swigptr);
250 PyObject* obj = PyInstance_New(classobj, arg, NULL);
251 Py_DECREF(arg);
252
253 return obj;
254 }
255
256
257 // This function is used for all events destined for Python event handlers.
258 void wxPyCallback::EventThunker(wxEvent& event) {
259 wxPyCallback* cb = (wxPyCallback*)event.m_callbackUserData;
260 PyObject* func = cb->m_func;
261 PyObject* result;
262 PyObject* arg;
263 PyObject* tuple;
264
265 arg = wxPyConstructObject((void*)&event, event.GetClassInfo()->GetClassName());
266
267 tuple = PyTuple_New(1);
268 PyTuple_SET_ITEM(tuple, 0, arg);
269 result = PyEval_CallObject(func, tuple);
270 Py_DECREF(arg);
271 Py_DECREF(tuple);
272 if (result) {
273 Py_DECREF(result);
274 PyErr_Clear();
275 } else {
276 PyErr_Print();
277 }
278 }
279
280
281 //---------------------------------------------------------------------------
282
283 wxPyMenu::wxPyMenu(const wxString& title, PyObject* _func)
284 : wxMenu(title, (wxFunction)(func ? MenuCallback : NULL)), func(0) {
285
286 if (_func) {
287 func = _func;
288 Py_INCREF(func);
289 }
290 }
291
292 wxPyMenu::~wxPyMenu() {
293 if (func)
294 Py_DECREF(func);
295 }
296
297
298 void wxPyMenu::MenuCallback(wxMenu& menu, wxCommandEvent& evt) {
299 PyObject* evtobj = wxPyConstructObject((void*)&evt, "wxCommandEvent");
300 PyObject* menuobj = wxPyConstructObject((void*)&menu, "wxMenu");
301 if (PyErr_Occurred()) {
302 // bail out if a problem
303 PyErr_Print();
304 return;
305 }
306 // Now call the callback...
307 PyObject* func = ((wxPyMenu*)&menu)->func;
308 PyObject* args = Py_BuildValue("(OO)", menuobj, evtobj);
309 PyObject* res = PyEval_CallObject(func, args);
310 Py_DECREF(args);
311 Py_DECREF(res);
312 Py_DECREF(evtobj);
313 Py_DECREF(menuobj);
314 }
315
316
317 //---------------------------------------------------------------------------
318
319 wxPyTimer::wxPyTimer(PyObject* callback) {
320 func = callback;
321 Py_INCREF(func);
322 }
323
324 wxPyTimer::~wxPyTimer() {
325 Py_DECREF(func);
326 }
327
328 void wxPyTimer::Notify() {
329 PyObject* result;
330 PyObject* args = Py_BuildValue("()");
331
332 result = PyEval_CallObject(func, args);
333 Py_DECREF(args);
334 if (result) {
335 Py_DECREF(result);
336 PyErr_Clear();
337 } else {
338 PyErr_Print();
339 }
340 }
341
342
343
344
345 //----------------------------------------------------------------------
346 //----------------------------------------------------------------------
347 // Some helper functions for typemaps in my_typemaps.i, so they won't be
348 // imcluded in every file...
349
350
351 int* int_LIST_helper(PyObject* source) {
352 if (!PyList_Check(source)) {
353 PyErr_SetString(PyExc_TypeError, "Expected a list object.");
354 return NULL;
355 }
356 int count = PyList_Size(source);
357 int* temp = new int[count];
358 if (! temp) {
359 PyErr_SetString(PyExc_MemoryError, "Unable to allocate temporary array");
360 return NULL;
361 }
362 for (int x=0; x<count; x++) {
363 PyObject* o = PyList_GetItem(source, x);
364 if (! PyInt_Check(o)) {
365 PyErr_SetString(PyExc_TypeError, "Expected a list of integers.");
366 return NULL;
367 }
368 temp[x] = PyInt_AsLong(o);
369 }
370 return temp;
371 }
372
373
374 long* long_LIST_helper(PyObject* source) {
375 if (!PyList_Check(source)) {
376 PyErr_SetString(PyExc_TypeError, "Expected a list object.");
377 return NULL;
378 }
379 int count = PyList_Size(source);
380 long* temp = new long[count];
381 if (! temp) {
382 PyErr_SetString(PyExc_MemoryError, "Unable to allocate temporary array");
383 return NULL;
384 }
385 for (int x=0; x<count; x++) {
386 PyObject* o = PyList_GetItem(source, x);
387 if (! PyInt_Check(o)) {
388 PyErr_SetString(PyExc_TypeError, "Expected a list of integers.");
389 return NULL;
390 }
391 temp[x] = PyInt_AsLong(o);
392 }
393 return temp;
394 }
395
396
397 char** string_LIST_helper(PyObject* source) {
398 if (!PyList_Check(source)) {
399 PyErr_SetString(PyExc_TypeError, "Expected a list object.");
400 return NULL;
401 }
402 int count = PyList_Size(source);
403 char** temp = new char*[count];
404 if (! temp) {
405 PyErr_SetString(PyExc_MemoryError, "Unable to allocate temporary array");
406 return NULL;
407 }
408 for (int x=0; x<count; x++) {
409 PyObject* o = PyList_GetItem(source, x);
410 if (! PyString_Check(o)) {
411 PyErr_SetString(PyExc_TypeError, "Expected a list of strings.");
412 return NULL;
413 }
414 temp[x] = PyString_AsString(o);
415 }
416 return temp;
417 }
418
419
420
421 wxPoint* wxPoint_LIST_helper(PyObject* source) {
422 if (!PyList_Check(source)) {
423 PyErr_SetString(PyExc_TypeError, "Expected a list object.");
424 return NULL;
425 }
426 int count = PyList_Size(source);
427 wxPoint* temp = new wxPoint[count];
428 if (! temp) {
429 PyErr_SetString(PyExc_MemoryError, "Unable to allocate temporary array");
430 return NULL;
431 }
432 for (int x=0; x<count; x++) {
433 PyObject* o = PyList_GetItem(source, x);
434 if (PyString_Check(o)) {
435 char* st = PyString_AsString(o);
436 wxPoint* pt;
437 if (SWIG_GetPtr(st,(void **) &pt,"_wxPoint_p")) {
438 PyErr_SetString(PyExc_TypeError,"Expected _wxPoint_p.");
439 return NULL;
440 }
441 temp[x] = *pt;
442 }
443 else if (PyTuple_Check(o)) {
444 PyObject* o1 = PyTuple_GetItem(o, 0);
445 PyObject* o2 = PyTuple_GetItem(o, 1);
446
447 temp[x].x = PyInt_AsLong(o1);
448 temp[x].y = PyInt_AsLong(o2);
449 }
450 else {
451 PyErr_SetString(PyExc_TypeError, "Expected a list of 2-tuples or wxPoints.");
452 return NULL;
453 }
454 }
455 return temp;
456 }
457
458
459 wxBitmap** wxBitmap_LIST_helper(PyObject* source) {
460 if (!PyList_Check(source)) {
461 PyErr_SetString(PyExc_TypeError, "Expected a list object.");
462 return NULL;
463 }
464 int count = PyList_Size(source);
465 wxBitmap** temp = new wxBitmap*[count];
466 if (! temp) {
467 PyErr_SetString(PyExc_MemoryError, "Unable to allocate temporary array");
468 return NULL;
469 }
470 for (int x=0; x<count; x++) {
471 PyObject* o = PyList_GetItem(source, x);
472 if (PyString_Check(o)) {
473 char* st = PyString_AsString(o);
474 wxBitmap* pt;
475 if (SWIG_GetPtr(st,(void **) &pt,"_wxBitmap_p")) {
476 PyErr_SetString(PyExc_TypeError,"Expected _wxBitmap_p.");
477 return NULL;
478 }
479 temp[x] = pt;
480 }
481 else {
482 PyErr_SetString(PyExc_TypeError, "Expected a list of wxBitmaps.");
483 return NULL;
484 }
485 }
486 return temp;
487 }
488
489
490
491 wxString* wxString_LIST_helper(PyObject* source) {
492 if (!PyList_Check(source)) {
493 PyErr_SetString(PyExc_TypeError, "Expected a list object.");
494 return NULL;
495 }
496 int count = PyList_Size(source);
497 wxString* temp = new wxString[count];
498 if (! temp) {
499 PyErr_SetString(PyExc_MemoryError, "Unable to allocate temporary array");
500 return NULL;
501 }
502 for (int x=0; x<count; x++) {
503 PyObject* o = PyList_GetItem(source, x);
504 if (! PyString_Check(o)) {
505 PyErr_SetString(PyExc_TypeError, "Expected a list of strings.");
506 return NULL;
507 }
508 temp[x] = PyString_AsString(o);
509 }
510 return temp;
511 }
512
513
514 #ifdef __WXMSW__
515 wxAcceleratorEntry* wxAcceleratorEntry_LIST_helper(PyObject* source) {
516 if (!PyList_Check(source)) {
517 PyErr_SetString(PyExc_TypeError, "Expected a list object.");
518 return NULL;
519 }
520 int count = PyList_Size(source);
521 wxAcceleratorEntry* temp = new wxAcceleratorEntry[count];
522 if (! temp) {
523 PyErr_SetString(PyExc_MemoryError, "Unable to allocate temporary array");
524 return NULL;
525 }
526 for (int x=0; x<count; x++) {
527 PyObject* o = PyList_GetItem(source, x);
528 if (PyString_Check(o)) {
529 char* st = PyString_AsString(o);
530 wxAcceleratorEntry* ae;
531 if (SWIG_GetPtr(st,(void **) &ae,"_wxAcceleratorEntry_p")) {
532 PyErr_SetString(PyExc_TypeError,"Expected _wxAcceleratorEntry_p.");
533 return NULL;
534 }
535 temp[x] = *ae;
536 }
537 else if (PyTuple_Check(o)) {
538 PyObject* o1 = PyTuple_GetItem(o, 0);
539 PyObject* o2 = PyTuple_GetItem(o, 1);
540 PyObject* o3 = PyTuple_GetItem(o, 2);
541
542 temp[x].m_flags = PyInt_AsLong(o1);
543 temp[x].m_keyCode = PyInt_AsLong(o2);
544 temp[x].m_command = PyInt_AsLong(o3);
545 }
546 else {
547 PyErr_SetString(PyExc_TypeError, "Expected a list of 3-tuples or wxAcceleratorEntry objects.");
548 return NULL;
549 }
550 }
551 return temp;
552 }
553
554 #endif
555
556 //----------------------------------------------------------------------
557 // A WinMain for when wxWindows and Python are linked together in a single
558 // application, instead of as a dynamic module
559
560
561 //#if !defined(WIN_PYD) && defined(WIN32)
562
563 //extern "C" int Py_Main(int argc, char** argv);
564
565 //int APIENTRY WinMain(HANDLE hInstance, HANDLE hPrevInstance, LPSTR m_lpCmdLine,
566 // int nCmdShow )
567 //{
568
569 // wxpCreateApp();
570
571 // // Initialize wxWindows, but don't start the main loop
572 // wxEntry(hInstance, hPrevInstance, m_lpCmdLine, nCmdShow, FALSE);
573
574 // Py_Initialize();
575 // PyObject *argvList = PyList_New(0);
576
577 // char* stderrfilename = "wxpstderr.log";
578 // int pyargc = 1;
579 // char* script = NULL;
580 // int argc = wxPythonApp->argc;
581 // char** argv = wxPythonApp->argv;
582
583 // for (int i = 1; i < argc; i++) {
584 // if (strncmp(argv[i], "wxpstderr=", 10) == 0)
585 // stderrfilename = argv[i]+10;
586 // else {
587 // PyList_Append(argvList, PyString_FromString(argv[i]));
588 // if (!script)
589 // script = argv[i];
590 // pyargc++;
591 // }
592 // }
593
594 // PySys_SetObject("argv", argvList);
595
596 //#if 1
597 // char buf[256];
598 //// //PyRun_SimpleString("import sys; sys.stdout=open('wxpstdout.log','w')");
599 // sprintf(buf, "import sys; sys.stdout=sys.stderr=open('%s','w')", stderrfilename);
600 // PyRun_SimpleString(buf);
601 //#endif
602
603 // initwxPythonc();
604
605 // if (script) {
606 // FILE *fp = fopen(script, "r");
607 // if (fp) {
608 // PyRun_SimpleFile(fp, script);// This returns after wxpApp constructor
609 // fclose(fp);
610 // }
611 // else {
612 // char msg[256];
613 // sprintf(msg, "Cannot open %s", script);
614 // wxMessageBox(msg);
615 // }
616 // }
617 // else
618 // PyRun_SimpleString("import wxpide");
619
620 // return 0;
621 //}
622
623
624 //#endif
625
626 //----------------------------------------------------------------------
627
628 /////////////////////////////////////////////////////////////////////////////
629 //
630 // $Log$
631 // Revision 1.7 1998/08/27 00:00:26 RD
632 // - more tweaks
633 // - have discovered some problems but not yet discovered solutions...
634 //
635 // Revision 1.6 1998/08/18 21:54:12 RD
636 //
637 // ifdef out some wxGTK specific code
638 //
639 // Revision 1.5 1998/08/18 19:48:17 RD
640 // more wxGTK compatibility things.
641 //
642 // It builds now but there are serious runtime problems...
643 //
644 // Revision 1.4 1998/08/16 04:31:06 RD
645 // More wxGTK work.
646 //
647 // Revision 1.3 1998/08/15 07:36:36 RD
648 // - Moved the header in the .i files out of the code that gets put into
649 // the .cpp files. It caused CVS conflicts because of the RCS ID being
650 // different each time.
651 //
652 // - A few minor fixes.
653 //
654 // Revision 1.2 1998/08/14 23:36:36 RD
655 // Beginings of wxGTK compatibility
656 //
657 // Revision 1.1 1998/08/09 08:25:51 RD
658 // Initial version
659 //
660 //