529d428692b5dd01d5b445e1805e72abea2d9beb
[blender.git] / source / blender / python / BPY_interface.c
1 /* 
2  * $Id$
3  *
4  * ***** BEGIN GPL/BL DUAL LICENSE BLOCK *****
5  *
6  * This program is free software; you can redistribute it and/or
7  * modify it under the terms of the GNU General Public License
8  * as published by the Free Software Foundation; either version 2
9  * of the License, or (at your option) any later version. The Blender
10  * Foundation also sells licenses for use in proprietary software under
11  * the Blender License.  See http://www.blender.org/BL/ for information
12  * about this.
13  *
14  * This program is distributed in the hope that it will be useful,
15  * but WITHOUT ANY WARRANTY; without even the implied warranty of
16  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17  * GNU General Public License for more details.
18  *
19  * You should have received a copy of the GNU General Public License
20  * along with this program; if not, write to the Free Software Foundation,
21  * Inc., 59 Temple Place - Suite 330, Boston, MA        02111-1307, USA.
22  *
23  * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
24  * All rights reserved.
25  *
26  * This is a new part of Blender.
27  *
28  * Contributor(s): Michel Selten, Willian P. Germano, Stephen Swaney,
29  * Chris Keith, Chris Want, Ken Hughes
30  *
31  * ***** END GPL/BL DUAL LICENSE BLOCK *****
32 */
33
34 #include <Python.h>
35
36 #include "compile.h"            /* for the PyCodeObject */
37 #include "eval.h"               /* for PyEval_EvalCode */
38 #include "BLI_blenlib.h"        /* for BLI_last_slash() */
39 #include "BIF_interface.h"      /* for pupmenu() */
40 #include "BIF_space.h"
41 #include "BIF_screen.h"
42 #include "BIF_toolbox.h"
43 #include "BKE_library.h"
44 #include "BKE_object.h"         /* during_scriptlink() */
45 #include "BKE_text.h"
46 #include "DNA_screen_types.h"
47 #include "DNA_userdef_types.h"  /* for U.pythondir */
48 #include "MEM_guardedalloc.h"
49 #include "BPY_extern.h"
50 #include "BPY_menus.h"
51 #include "BPI_script.h"
52 #include "BKE_global.h"
53 #include "BKE_main.h"
54 #include "api2_2x/EXPP_interface.h"
55 #include "api2_2x/constant.h"
56 #include "api2_2x/gen_utils.h"
57 #include "api2_2x/BGL.h" 
58 #include "api2_2x/Blender.h"
59 #include "api2_2x/Camera.h"
60 #include "api2_2x/Draw.h"
61 #include "api2_2x/Lamp.h"
62 #include "api2_2x/NMesh.h"
63 #include "api2_2x/Object.h"
64 #include "api2_2x/Registry.h"
65 #include "api2_2x/Scene.h"
66 #include "api2_2x/World.h"
67
68 /* bpy_registryDict is declared in api2_2x/Registry.h and defined
69  * in api2_2x/Registry.c
70  * This Python dictionary will be used to store data that scripts
71  * choose to preserve after they are executed, so user changes can be
72  * restored next time the script is used.  Check the Blender.Registry module. 
73  */
74 //#include "api2_2x/Registry.h"
75
76 /*Declares the modules and their initialization functions
77 *These are TOP-LEVEL modules e.g. import `module` - there is no
78 *support for packages here e.g. import `package.module` */
79 static struct _inittab BPy_Inittab_Modules[] = {
80         {"Blender", M_Blender_Init},
81         {NULL, NULL}
82 };
83
84 /*************************************************************************
85 * Structure definitions 
86 **************************************************************************/
87 #define FILENAME_LENGTH 24
88 typedef struct _ScriptError {
89         char filename[FILENAME_LENGTH];
90         int lineno;
91 } ScriptError;
92
93 /****************************************************************************
94 * Global variables 
95 ****************************************************************************/
96 ScriptError g_script_error;
97
98 /***************************************************************************
99 * Function prototypes 
100 ***************************************************************************/
101 PyObject *RunPython( Text * text, PyObject * globaldict );
102 char *GetName( Text * text );
103 PyObject *CreateGlobalDictionary( void );
104 void ReleaseGlobalDictionary( PyObject * dict );
105 void DoAllScriptsFromList( ListBase * list, short event );
106 PyObject *importText( char *name );
107 void init_ourImport( void );
108 void init_ourReload( void );
109 PyObject *blender_import( PyObject * self, PyObject * args );
110
111 int BPY_txt_do_python_Text( struct Text *text );
112 void BPY_Err_Handle( char *script_name );
113 PyObject *traceback_getFilename( PyObject * tb );
114
115 void BPY_free_screen_spacehandlers(struct bScreen *sc);
116
117 /****************************************************************************
118 * Description: This function will start the interpreter and load all modules
119 * as well as search for a python installation.
120 ****************************************************************************/
121 void BPY_start_python( int argc, char **argv )
122 {
123         static int argc_copy = 0;
124         static char **argv_copy = NULL;
125         int first_time = argc;
126
127         /* we keep a copy of the values of argc and argv so that the game engine
128          * can call BPY_start_python(0, NULL) whenever a game ends, without having
129          * to know argc and argv there (in source/blender/src/space.c) */
130         if( first_time ) {
131                 argc_copy = argc;
132                 argv_copy = argv;
133         }
134
135         //stuff for Registry module
136         bpy_registryDict = PyDict_New(  );/* check comment at start of this file */
137         if( !bpy_registryDict )
138                 printf( "Error: Couldn't create the Registry Python Dictionary!" );
139         Py_SetProgramName( "blender" );
140
141         /* Py_Initialize() will attempt to import the site module and
142          * print an error if not found.  See init_syspath() for the
143          * rest of our init msgs.
144          */
145         // Py_GetVersion() returns a ptr to astatic string
146         printf( "Using Python version %.3s\n", Py_GetVersion() );
147
148         //Initialize the TOP-LEVEL modules
149         PyImport_ExtendInittab(BPy_Inittab_Modules);
150         
151         //Start the interpreter
152         Py_Initialize(  );
153         PySys_SetArgv( argc_copy, argv_copy );
154
155         //Overrides __import__
156         init_ourImport(  );
157         init_ourReload(  );
158
159         //init a global dictionary
160         g_blenderdict = NULL;
161
162         //Look for a python installation
163         init_syspath( first_time ); /* not first_time: some msgs are suppressed */
164
165         return;
166 }
167
168 /*****************************************************************************/
169 /* Description: This function will terminate the Python interpreter          */
170 /*****************************************************************************/
171 void BPY_end_python( void )
172 {
173         if( bpy_registryDict ) {
174                 Py_DECREF( bpy_registryDict );
175                 bpy_registryDict = NULL;
176         }
177
178         Py_Finalize(  );
179
180         BPyMenu_RemoveAllEntries(  );   /* freeing bpymenu mem */
181
182         /* a script might've opened a .blend file but didn't close it, so: */
183         EXPP_Library_Close(  );
184
185         return;
186 }
187
188 void syspath_append( char *dirname )
189 {
190         PyObject *mod_sys, *dict, *path, *dir;
191
192         PyErr_Clear(  );
193
194         dir = Py_BuildValue( "s", dirname );
195
196         mod_sys = PyImport_ImportModule( "sys" );       /* new ref */
197         dict = PyModule_GetDict( mod_sys );     /* borrowed ref */
198         path = PyDict_GetItemString( dict, "path" );    /* borrowed ref */
199
200         if( !PyList_Check( path ) )
201                 return;
202
203         PyList_Append( path, dir );
204
205         if( PyErr_Occurred(  ) )
206                 Py_FatalError( "could not build sys.path" );
207
208         Py_DECREF( mod_sys );
209 }
210
211 void init_syspath( int first_time )
212 {
213         PyObject *path;
214         PyObject *mod, *d;
215         char *progname;
216         char execdir[FILE_MAXDIR];      /*defines from DNA_space_types.h */
217
218         int n;
219
220         path = Py_BuildValue( "s", bprogname );
221
222         mod = PyImport_ImportModule( "Blender.sys" );
223
224         if( mod ) {
225                 d = PyModule_GetDict( mod );
226                 EXPP_dict_set_item_str( d, "progname", path );
227                 Py_DECREF( mod );
228         } else
229                 printf( "Warning: could not set Blender.sys.progname\n" );
230
231         progname = BLI_last_slash( bprogname ); /* looks for the last dir separator */
232
233 #ifdef SETSYSPATH
234         {
235                 char *c; 
236                 c = Py_GetPath(  );     /* get python system path */
237                 PySys_SetPath( c );     /* initialize */
238         }
239 #endif
240
241         n = progname - bprogname;
242         if( n > 0 ) {
243                 strncpy( execdir, bprogname, n );
244                 if( execdir[n - 1] == '.' )
245                         n--;    /*fix for when run as ./blender */
246                 execdir[n] = '\0';
247
248                 syspath_append( execdir );      /* append to module search path */
249
250                 /* set Blender.sys.progname */
251         } else
252                 printf( "Warning: could not determine argv[0] path\n" );
253
254 #ifdef SETSYSPATH
255         /* 
256          * bring in the site module so we can add 
257          * site-package dirs to sys.path 
258          */
259
260         mod = PyImport_ImportModule( "site" );  /* new ref */
261
262         if( mod ) {
263                 PyObject *item;
264                 int size = 0;
265                 int index;
266                 PyObject *p;
267
268                 /* get the value of 'sitedirs' from the module */
269
270                 /* the ref man says GetDict() never fails!!! */
271                 d = PyModule_GetDict( mod );    /* borrowed ref */
272                 p = PyDict_GetItemString( d, "sitedirs" );      /* borrowed ref */
273
274                 if( p ) {       /* we got our string */
275                         /* append each item in sitedirs list to path */
276                         size = PyList_Size( p );
277
278                         for( index = 0; index < size; index++ ) {
279                                 item = PySequence_GetItem( p, index );  /* new ref */
280                                 if( item )
281                                         syspath_append( PyString_AsString
282                                                         ( item ) );
283                         }
284                 }
285                 Py_DECREF( mod );
286         } else {                /* import 'site' failed */
287                 PyErr_Clear(  );
288                 if( first_time ) {
289                         printf( "No installed Python found.\n" );
290                         printf( "Only built-in modules are available.  Some scripts may not run.\n" );
291                         printf( "Continuing happily.\n" );
292                 }
293         }
294 #endif
295
296         /* 
297          * initialize the sys module
298          * set sys.executable to the Blender exe 
299          */
300
301         mod = PyImport_ImportModule( "sys" );   /* new ref */
302
303         if( mod ) {
304                 d = PyModule_GetDict( mod );    /* borrowed ref */
305                 EXPP_dict_set_item_str( d, "executable",
306                                       Py_BuildValue( "s", bprogname ) );
307                 Py_DECREF( mod );
308         }
309 }
310
311 /****************************************************************************
312 * Description: This function finishes Python initialization in Blender.  
313
314 Because U.pythondir (user defined dir for scripts) isn't         
315 initialized when BPY_start_Python needs to be executed, we       
316 postpone adding U.pythondir to sys.path and also BPyMenus         
317 (mechanism to register scripts in Blender menus) for when  
318 that dir info is available.   
319 ****************************************************************************/
320 void BPY_post_start_python( void )
321 {
322         char dirpath[FILE_MAXDIR];
323         char *sdir = NULL;
324
325         if(U.pythondir[0] != '\0' ) {
326                 char modpath[FILE_MAXDIR];
327                 int upyslen = strlen(U.pythondir);
328
329                 /* check if user pydir ends with a slash and, if so, remove the slash
330                  * (for eventual implementations of c library's stat function that might
331                  * not like it) */
332                 if (upyslen > 2) { /* avoids doing anything if dir == '//' */
333                         char ending = U.pythondir[upyslen - 1];
334
335                         if (ending == '/' || ending == '\\')
336                                 U.pythondir[upyslen - 1] = '\0';
337                 }
338
339                 BLI_strncpy(dirpath, U.pythondir, FILE_MAXDIR);
340                 BLI_convertstringcode(dirpath, G.sce, 0);
341                 syspath_append(dirpath);        /* append to module search path */
342
343                 BLI_make_file_string("/", modpath, dirpath, "bpymodules");
344                 if (BLI_exists(modpath)) syspath_append(modpath);
345         }
346
347         sdir = bpy_gethome(1);
348         if (sdir) {
349
350                 syspath_append(sdir);
351
352                 BLI_make_file_string("/", dirpath, sdir, "bpymodules");
353                 if (BLI_exists(dirpath)) syspath_append(dirpath);
354         }
355
356         BPyMenu_Init( 0 );      /* get dynamic menus (registered scripts) data */
357
358         return;
359 }
360
361 /****************************************************************************
362 * Description: This function will return the linenumber on which an error  
363 *               has occurred in the Python script.                      
364 ****************************************************************************/
365 int BPY_Err_getLinenumber( void )
366 {
367         return g_script_error.lineno;
368 }
369
370 /*****************************************************************************/
371 /* Description: This function will return the filename of the python script. */
372 /*****************************************************************************/
373 const char *BPY_Err_getFilename( void )
374 {
375         return g_script_error.filename;
376 }
377
378 /*****************************************************************************/
379 /* Description: Return PyString filename from a traceback object            */
380 /*****************************************************************************/
381 PyObject *traceback_getFilename( PyObject * tb )
382 {
383         PyObject *v = NULL;
384
385 /* co_filename is in f_code, which is in tb_frame, which is in tb */
386
387         v = PyObject_GetAttrString( tb, "tb_frame" );
388         if (v) {
389                 Py_DECREF( v );
390                 v = PyObject_GetAttrString( v, "f_code" );
391                 if (v) {
392                         Py_DECREF( v );
393                         v = PyObject_GetAttrString( v, "co_filename" );
394                 }
395         }
396
397         if (v) return v;
398         else return PyString_FromString("unknown");
399 }
400
401 /****************************************************************************
402 * Description: Blender Python error handler. This catches the error and 
403 * stores filename and line number in a global  
404 *****************************************************************************/
405 void BPY_Err_Handle( char *script_name )
406 {
407         PyObject *exception, *err, *tb, *v;
408
409         if( !script_name ) {
410                 printf( "Error: script has NULL name\n" );
411                 return;
412         }
413
414         PyErr_Fetch( &exception, &err, &tb );
415
416         if( !exception && !tb ) {
417                 printf( "FATAL: spurious exception\n" );
418                 return;
419         }
420
421         strcpy( g_script_error.filename, script_name );
422
423         if( exception
424             && PyErr_GivenExceptionMatches( exception, PyExc_SyntaxError ) ) {
425                 /* no traceback available when SyntaxError */
426                 PyErr_Restore( exception, err, tb );    /* takes away reference! */
427                 PyErr_Print(  );
428                 v = PyObject_GetAttrString( err, "lineno" );
429                 if( v ) {
430                         g_script_error.lineno = PyInt_AsLong( v );
431                         Py_DECREF( v );
432                 } else {
433                         g_script_error.lineno = -1;
434                 }
435                 /* this avoids an abort in Python 2.3's garbage collecting: */
436                 PyErr_Clear(  );
437                 return;
438         } else {
439                 PyErr_NormalizeException( &exception, &err, &tb );
440                 PyErr_Restore( exception, err, tb );    /* takes away reference! */
441                 PyErr_Print(  );
442                 tb = PySys_GetObject( "last_traceback" );
443
444                 if( !tb ) {
445                         printf( "\nCan't get traceback\n" );
446                         return;
447                 }
448
449                 Py_INCREF( tb );
450
451 /* From old bpython BPY_main.c:
452  * 'check traceback objects and look for last traceback in the
453  *      same text file. This is used to jump to the line of where the
454  *      error occured. "If the error occured in another text file or module,
455  *      the last frame in the current file is adressed."' 
456  */
457
458                 for(;;) {
459                         v = PyObject_GetAttrString( tb, "tb_next" );
460
461                         if( !v || v == Py_None ||
462                                 strcmp(PyString_AsString(traceback_getFilename(v)), script_name)) {
463                                 break;
464                         }
465
466                         Py_DECREF( tb );
467                         tb = v;
468                 }
469
470                 v = PyObject_GetAttrString( tb, "tb_lineno" );
471                 if (v) {
472                         g_script_error.lineno = PyInt_AsLong(v);
473                         Py_DECREF(v);
474                 }
475                 v = traceback_getFilename( tb );
476                 if (v) {
477                         strncpy( g_script_error.filename, PyString_AsString( v ),
478                                 FILENAME_LENGTH );
479                         Py_DECREF(v);
480                 }
481                 Py_DECREF( tb );
482         }
483
484         return;
485 }
486
487 /****************************************************************************
488 * Description: This function executes the script passed by st.          
489 * Notes:        It is called by blender/src/drawtext.c when a Blender user  
490 *               presses ALT+PKEY in the script's text window. 
491 *****************************************************************************/
492 int BPY_txt_do_python_Text( struct Text *text )
493 {
494         PyObject *py_dict, *py_result;
495         BPy_constant *info;
496         char textname[24];
497         Script *script = G.main->script.first;
498
499         if( !text )
500                 return 0;
501
502         /* check if this text is already running */
503         while( script ) {
504                 if( !strcmp( script->id.name + 2, text->id.name + 2 ) ) {
505                         /* if this text is already a running script, 
506                          * just move to it: */
507                         SpaceScript *sc;
508                         newspace( curarea, SPACE_SCRIPT );
509                         sc = curarea->spacedata.first;
510                         sc->script = script;
511                         return 1;
512                 }
513                 script = script->id.next;
514         }
515
516         /* Create a new script structure and initialize it: */
517         script = alloc_libblock( &G.main->script, ID_SCRIPT, GetName( text ) );
518
519         if( !script ) {
520                 printf( "couldn't allocate memory for Script struct!" );
521                 return 0;
522         }
523
524         /* if in the script Blender.Load(blendfile) is not the last command,
525          * an error after it will call BPY_Err_Handle below, but the text struct
526          * will have been deallocated already, so we need to copy its name here.
527          */
528         BLI_strncpy( textname, GetName( text ),
529                      strlen( GetName( text ) ) + 1 );
530
531         script->id.us = 1;
532         script->flags = SCRIPT_RUNNING;
533         script->py_draw = NULL;
534         script->py_event = NULL;
535         script->py_button = NULL;
536         script->py_browsercallback = NULL;
537
538         py_dict = CreateGlobalDictionary(  );
539
540         script->py_globaldict = py_dict;
541
542         info = ( BPy_constant * ) PyConstant_New(  );
543         if( info ) {
544                 PyConstant_Insert( info, "name",
545                                  PyString_FromString( script->id.name + 2 ) );
546                 Py_INCREF( Py_None );
547                 PyConstant_Insert( info, "arg", Py_None );
548                 EXPP_dict_set_item_str( py_dict, "__script__",
549                                       ( PyObject * ) info );
550         }
551
552         py_result = RunPython( text, py_dict ); /* Run the script */
553
554         if( !py_result ) {      /* Failed execution of the script */
555
556                 BPY_Err_Handle( textname );
557                 ReleaseGlobalDictionary( py_dict );
558                 script->py_globaldict = NULL;
559                 if( G.main->script.first )
560                         free_libblock( &G.main->script, script );
561
562                 return 0;
563         } else {
564                 Py_DECREF( py_result );
565                 script->flags &= ~SCRIPT_RUNNING;
566                 if( !script->flags ) {
567                         ReleaseGlobalDictionary( py_dict );
568                         script->py_globaldict = NULL;
569                         free_libblock( &G.main->script, script );
570                 }
571         }
572
573         return 1;               /* normal return */
574 }
575
576 /****************************************************************************
577 * Description: Called from command line to run a Python script
578 * automatically. The script can be a file or a Blender Text in the current 
579 * .blend.
580 ****************************************************************************/
581 void BPY_run_python_script( char *fn )
582 {
583         Text *text = NULL;
584         int is_blender_text = 0;
585
586         if (!BLI_exists(fn)) {  /* if there's no such filename ... */
587                 text = G.main->text.first;      /* try an already existing Blender Text */
588
589                 while (text) {
590                         if (!strcmp(fn, text->id.name + 2)) break;
591                         text = text->id.next;
592                 }
593
594                 if (text == NULL) {
595                         printf("\nError: no such file or Blender text -- %s.\n", fn);
596                         return;
597                 }
598                 else is_blender_text = 1;       /* fn is already a Blender Text */
599         }
600
601         else {
602                 text = add_text(fn);
603
604                 if (text == NULL) {
605                         printf("\nError in BPY_run_python_script:\n"
606                                 "couldn't create Blender text from %s\n", fn);
607                 /* Chris: On Windows if I continue I just get a segmentation
608                  * violation.  To get a baseline file I exit here. */
609                 exit(2);
610                 /* return; */
611                 }
612         }
613
614         if (BPY_txt_do_python_Text(text) != 1) {
615                 printf("\nError executing Python script from command-line:\n"
616                         "%s (at line %d).\n", fn, BPY_Err_getLinenumber());
617         }
618
619         if (!is_blender_text) {
620                 /* We can't simply free the text, since the script might have called
621                  * Blender.Load() to load a new .blend, freeing previous data.
622                  * So we check if the pointer is still valid. */
623                 Text *txtptr = G.main->text.first;
624                 while (txtptr) {
625                         if (txtptr == text) {
626                                 free_libblock(&G.main->text, text);
627                                 break;
628                         }
629                         txtptr = txtptr->id.next;
630                 }
631         }
632 }
633
634 /****************************************************************************
635 * Description: This function executes the script chosen from a menu.
636 * Notes:        It is called by the ui code in src/header_???.c when a user  
637 *               clicks on a menu entry that refers to a script.
638 *               Scripts are searched in the BPyMenuTable, using the given
639 *               menutype and event values to know which one was chosen. 
640 *****************************************************************************/
641 int BPY_menu_do_python( short menutype, int event )
642 {
643         PyObject *py_dict, *py_res, *pyarg = NULL;
644         BPy_constant *info;
645         BPyMenu *pym;
646         BPySubMenu *pysm;
647         FILE *fp = NULL;
648         char *buffer, *s;
649         char filestr[FILE_MAXDIR + FILE_MAXFILE];
650         char scriptname[21];
651         Script *script = NULL;
652         int len;
653
654         pym = BPyMenu_GetEntry( menutype, ( short ) event );
655
656         if( !pym )
657                 return 0;
658
659         if( pym->version > G.version )
660                 notice( "Version mismatch: script was written for Blender %d. "
661                         "It may fail with yours: %d.", pym->version,
662                         G.version );
663
664 /* if there are submenus, let the user choose one from a pupmenu that we
665  * create here.*/
666         pysm = pym->submenus;
667         if( pysm ) {
668                 char *pupstr;
669                 int arg;
670
671                 pupstr = BPyMenu_CreatePupmenuStr( pym, menutype );
672
673                 if( pupstr ) {
674                         arg = pupmenu( pupstr );
675                         MEM_freeN( pupstr );
676
677                         if( arg >= 0 ) {
678                                 while( arg-- )
679                                         pysm = pysm->next;
680                                 pyarg = PyString_FromString( pysm->arg );
681                         } else
682                                 return 0;
683                 }
684         }
685
686         if( !pyarg ) { /* no submenus */
687                 Py_INCREF( Py_None );
688                 pyarg = Py_None;
689         }
690
691         if( pym->dir ) { /* script is in U.pythondir */
692                 char upythondir[FILE_MAXDIR];
693
694                 /* dirs in Blender can be "//", which has a special meaning */
695                 BLI_strncpy(upythondir, U.pythondir, FILE_MAXDIR);
696                 BLI_convertstringcode(upythondir, G.sce, 0); /* if so, this expands it */
697                 BLI_make_file_string( "/", filestr, upythondir, pym->filename );
698         }
699         else { /* script is in default scripts dir */
700                 char *scriptsdir = bpy_gethome(1);
701
702                 if (!scriptsdir) {
703                         printf("Error loading script: can't find default scripts dir!");
704                         return 0;
705                 }
706
707                 BLI_make_file_string( "/", filestr, scriptsdir, pym->filename );
708         }
709
710         fp = fopen( filestr, "rb" );
711         if( !fp ) {
712                 printf( "Error loading script: couldn't open file %s\n",
713                         filestr );
714                 return 0;
715         }
716
717         BLI_strncpy(scriptname, pym->name, 21);
718         len = strlen(scriptname) - 1;
719         /* by convention, scripts that open the file browser or have submenus
720          * display '...'.  Here we remove them from the datablock name */
721         while ((len > 0) && scriptname[len] == '.') {
722                 scriptname[len] = '\0';
723                 len--;
724         }
725         
726         /* Create a new script structure and initialize it: */
727         script = alloc_libblock( &G.main->script, ID_SCRIPT, scriptname );
728
729         if( !script ) {
730                 printf( "couldn't allocate memory for Script struct!" );
731                 fclose( fp );
732                 return 0;
733         }
734
735         /* let's find a proper area for an eventual script gui:
736          * (still experimenting here, need definition on which win
737          * each group will be put to code this properly) */
738         switch ( menutype ) {
739
740         case PYMENU_IMPORT:     /* first 4 were handled in header_info.c */
741         case PYMENU_EXPORT:
742         case PYMENU_HELP:
743         case PYMENU_RENDER:
744         case PYMENU_WIZARDS:
745                 break;
746
747         default:
748                 if( curarea->spacetype != SPACE_SCRIPT ) {
749                         ScrArea *sa = NULL;
750
751                         sa = find_biggest_area_of_type( SPACE_BUTS );
752                         if( sa ) {
753                                 if( ( 1.5 * sa->winx ) < sa->winy )
754                                         sa = NULL;      /* too narrow? */
755                         }
756
757                         if( !sa )
758                                 sa = find_biggest_area_of_type( SPACE_SCRIPT );
759                         if( !sa )
760                                 sa = find_biggest_area_of_type( SPACE_TEXT );
761                         if( !sa )
762                                 sa = find_biggest_area_of_type( SPACE_IMAGE );  /* group UV */
763                         if( !sa )
764                                 sa = find_biggest_area_of_type( SPACE_VIEW3D );
765
766                         if( !sa )
767                                 sa = find_biggest_area(  );
768
769                         areawinset( sa->win );
770                 }
771                 break;
772         }
773
774         script->id.us = 1;
775         script->flags = SCRIPT_RUNNING;
776         script->py_draw = NULL;
777         script->py_event = NULL;
778         script->py_button = NULL;
779         script->py_browsercallback = NULL;
780
781         py_dict = CreateGlobalDictionary(  );
782
783         script->py_globaldict = py_dict;
784
785         info = ( BPy_constant * ) PyConstant_New(  );
786         if( info ) {
787                 PyConstant_Insert( info, "name",
788                                  PyString_FromString( script->id.name + 2 ) );
789                 PyConstant_Insert( info, "arg", pyarg );
790                 EXPP_dict_set_item_str( py_dict, "__script__",
791                                       ( PyObject * ) info );
792         }
793
794         /* Previously we used PyRun_File to run directly the code on a FILE 
795          * object, but as written in the Python/C API Ref Manual, chapter 2,
796          * 'FILE structs for different C libraries can be different and 
797          * incompatible'.
798          * So now we load the script file data to a buffer */
799
800         fseek( fp, 0L, SEEK_END );
801         len = ftell( fp );
802         fseek( fp, 0L, SEEK_SET );
803
804         buffer = MEM_mallocN( len + 2, "pyfilebuf" );   /* len+2 to add '\n\0' */
805         len = fread( buffer, 1, len, fp );
806
807         buffer[len] = '\n';     /* fix syntax error in files w/o eol */
808         buffer[len + 1] = '\0';
809
810         /* fast clean-up of dos cr/lf line endings: change '\r' to space */
811
812         /* we also have to check for line splitters: '\\' */
813         /* to avoid possible syntax errors on dos files on win */
814          /**/
815                 /* but first make sure we won't disturb memory below &buffer[0]: */
816                 if( *buffer == '\r' )
817                 *buffer = ' ';
818
819         /* now handle the whole buffer */
820         for( s = buffer + 1; *s != '\0'; s++ ) {
821                 if( *s == '\r' ) {
822                         if( *( s - 1 ) == '\\' ) {      /* special case: long lines split with '\': */
823                                 *( s - 1 ) = ' ';       /* we write ' \', because '\ ' is a syntax error */
824                                 *s = '\\';
825                         } else
826                                 *s = ' ';       /* not a split line, just replace '\r' with ' ' */
827                 }
828         }
829
830         fclose( fp );
831
832         /* run the string buffer */
833
834         py_res = PyRun_String( buffer, Py_file_input, py_dict, py_dict );
835
836         MEM_freeN( buffer );
837
838         if( !py_res ) {         /* Failed execution of the script */
839
840                 BPY_Err_Handle( script->id.name + 2 );
841                 ReleaseGlobalDictionary( py_dict );
842                 script->py_globaldict = NULL;
843                 if( G.main->script.first )
844                         free_libblock( &G.main->script, script );
845                 error( "Python script error: check console" );
846
847                 return 0;
848         } else {
849                 Py_DECREF( py_res );
850                 script->flags &= ~SCRIPT_RUNNING;
851
852                 if( !script->flags ) {
853                         ReleaseGlobalDictionary( py_dict );
854                         script->py_globaldict = NULL;
855                         free_libblock( &G.main->script, script );
856
857                         /* special case: called from the menu in the Scripts window
858                          * we have to change sc->script pointer, since it'll be freed here.*/
859                         if( curarea->spacetype == SPACE_SCRIPT ) {
860                                 SpaceScript *sc = curarea->spacedata.first;
861                                 sc->script = G.main->script.first;      /* can be null, which is ok ... */
862                                 /* ... meaning no other script is running right now. */
863                         }
864
865                 }
866         }
867
868         return 1;               /* normal return */
869 }
870
871 /*****************************************************************************
872 * Description:  
873 * Notes:
874 *****************************************************************************/
875 void BPY_free_compiled_text( struct Text *text )
876 {
877         if( !text->compiled )
878                 return;
879         Py_DECREF( ( PyObject * ) text->compiled );
880         text->compiled = NULL;
881
882         return;
883 }
884
885 /*****************************************************************************
886 * Description: This function frees a finished (flags == 0) script.
887 *****************************************************************************/
888 void BPY_free_finished_script( Script * script )
889 {
890         if( !script )
891                 return;
892
893         if( PyErr_Occurred(  ) ) {      /* if script ended after filesel */
894                 PyErr_Print(  );        /* eventual errors are handled now */
895                 error( "Python script error: check console" );
896         }
897
898         free_libblock( &G.main->script, script );
899         return;
900 }
901
902 static void unlink_script( Script * script )
903 {       /* copied from unlink_text in drawtext.c */
904         bScreen *scr;
905         ScrArea *area;
906         SpaceLink *sl;
907
908         for( scr = G.main->screen.first; scr; scr = scr->id.next ) {
909                 for( area = scr->areabase.first; area; area = area->next ) {
910                         for( sl = area->spacedata.first; sl; sl = sl->next ) {
911                                 if( sl->spacetype == SPACE_SCRIPT ) {
912                                         SpaceScript *sc = ( SpaceScript * ) sl;
913
914                                         if( sc->script == script ) {
915                                                 sc->script = NULL;
916
917                                                 if( sc ==
918                                                     area->spacedata.first ) {
919                                                         scrarea_queue_redraw
920                                                                 ( area );
921                                                 }
922                                         }
923                                 }
924                         }
925                 }
926         }
927 }
928
929 void BPY_clear_script( Script * script )
930 {
931         PyObject *dict;
932
933         if( !script )
934                 return;
935
936         Py_XDECREF( ( PyObject * ) script->py_draw );
937         Py_XDECREF( ( PyObject * ) script->py_event );
938         Py_XDECREF( ( PyObject * ) script->py_button );
939         Py_XDECREF( ( PyObject * ) script->py_browsercallback );
940
941         dict = script->py_globaldict;
942
943         if( dict ) {
944                 PyDict_Clear( dict );
945                 Py_DECREF( dict );      /* Release dictionary. */
946                 script->py_globaldict = NULL;
947         }
948
949         unlink_script( script );
950 }
951
952 /*****************************************************************************/
953 /* ScriptLinks                                                        */
954 /*****************************************************************************/
955
956 /*****************************************************************************/
957 /* Description:                                                          */
958 /* Notes:                               Not implemented yet      */
959 /*****************************************************************************/
960 void BPY_clear_bad_scriptlinks( struct Text *byebye )
961 {
962 /*
963         BPY_clear_bad_scriptlist(getObjectList(), byebye);
964         BPY_clear_bad_scriptlist(getLampList(), byebye);
965         BPY_clear_bad_scriptlist(getCameraList(), byebye);
966         BPY_clear_bad_scriptlist(getMaterialList(), byebye);
967         BPY_clear_bad_scriptlist(getWorldList(),        byebye);
968         BPY_clear_bad_scriptlink(&scene_getCurrent()->id, byebye);
969
970         allqueue(REDRAWBUTSSCRIPT, 0);
971 */
972         return;
973 }
974
975 /*****************************************************************************
976 * Description: Loop through all scripts of a list of object types, and 
977 *       execute these scripts.  
978 *       For the scene, only the current active scene the scripts are 
979 *       executed (if any).
980 *****************************************************************************/
981 void BPY_do_all_scripts( short event )
982 {
983         DoAllScriptsFromList( &( G.main->object ), event );
984         DoAllScriptsFromList( &( G.main->lamp ), event );
985         DoAllScriptsFromList( &( G.main->camera ), event );
986         DoAllScriptsFromList( &( G.main->mat ), event );
987         DoAllScriptsFromList( &( G.main->world ), event );
988
989         BPY_do_pyscript( &( G.scene->id ), event );
990
991         return;
992 }
993
994 /*****************************************************************************
995 * Description: Execute a Python script when an event occurs. The following  
996 *               events are possible: frame changed, load script and redraw.  
997 *               Only events happening to one of the following object types   
998 *               are handled: Object, Lamp, Camera, Material, World and      
999 *               Scene.                  
1000 *****************************************************************************/
1001
1002 static ScriptLink *ID_getScriptlink( ID * id )
1003 {
1004         switch ( MAKE_ID2( id->name[0], id->name[1] ) ) {
1005         case ID_OB:
1006                 return &( ( Object * ) id )->scriptlink;
1007         case ID_LA:
1008                 return &( ( Lamp * ) id )->scriptlink;
1009         case ID_CA:
1010                 return &( ( Camera * ) id )->scriptlink;
1011         case ID_MA:
1012                 return &( ( Material * ) id )->scriptlink;
1013         case ID_WO:
1014                 return &( ( World * ) id )->scriptlink;
1015         case ID_SCE:
1016                 return &( ( Scene * ) id )->scriptlink;
1017         default:
1018                 return NULL;
1019         }
1020 }
1021
1022 static PyObject *ID_asPyObject( ID * id )
1023 {
1024         switch ( MAKE_ID2( id->name[0], id->name[1] ) ) {
1025         case ID_OB:
1026                 return Object_CreatePyObject( ( Object * ) id );
1027         case ID_LA:
1028                 return Lamp_CreatePyObject( ( Lamp * ) id );
1029         case ID_CA:
1030                 return Camera_CreatePyObject( ( Camera * ) id );
1031         case ID_MA:
1032                 return Material_CreatePyObject( ( Material * ) id );
1033         case ID_WO:
1034                 return World_CreatePyObject( ( World * ) id );
1035         case ID_SCE:
1036                 return Scene_CreatePyObject( ( Scene * ) id );
1037         default:
1038                 Py_INCREF( Py_None );
1039                 return Py_None;
1040         }
1041 }
1042
1043 int BPY_has_onload_script( void )
1044 {
1045         ScriptLink *slink = &G.scene->scriptlink;
1046         int i;
1047
1048         if( !slink || !slink->totscript )
1049                 return 0;
1050
1051         for( i = 0; i < slink->totscript; i++ ) {
1052                 if( ( slink->flag[i] == SCRIPT_ONLOAD )
1053                     && ( slink->scripts[i] != NULL ) )
1054                         return 1;
1055         }
1056
1057         return 0;
1058 }
1059
1060 void BPY_do_pyscript( ID * id, short event )
1061 {
1062         ScriptLink *scriptlink;
1063
1064         if( !id ) return;
1065
1066         scriptlink = ID_getScriptlink( id );
1067
1068         if( scriptlink && scriptlink->totscript ) {
1069                 PyObject *dict;
1070                 PyObject *ret;
1071                 int index, during_slink = during_scriptlink(  );
1072
1073                 /* invalid scriptlinks (new .blend was just loaded), return */
1074                 if( during_slink < 0 )
1075                         return;
1076
1077                 /* tell we're running a scriptlink.  The sum also tells if this script
1078                  * is running nested inside another.  Blender.Load needs this info to
1079                  * avoid trouble with invalid slink pointers. */
1080                 during_slink++;
1081                 disable_where_scriptlink( (short)during_slink );
1082
1083                 /* set globals in Blender module to identify scriptlink */
1084                 EXPP_dict_set_item_str( g_blenderdict, "bylink", EXPP_incr_ret_True() );
1085                 EXPP_dict_set_item_str( g_blenderdict, "link",
1086                                       ID_asPyObject( id ) );
1087                 EXPP_dict_set_item_str( g_blenderdict, "event",
1088                                       PyString_FromString( event_to_name
1089                                                            ( event ) ) );
1090
1091                 if (event == SCRIPT_POSTRENDER) event = SCRIPT_RENDER;
1092
1093                 for( index = 0; index < scriptlink->totscript; index++ ) {
1094                         if( ( scriptlink->flag[index] == event ) &&
1095                             ( scriptlink->scripts[index] != NULL ) ) {
1096                                 dict = CreateGlobalDictionary(  );
1097                                 ret = RunPython( ( Text * ) scriptlink->
1098                                                  scripts[index], dict );
1099                                 ReleaseGlobalDictionary( dict );
1100
1101                                 if( !ret ) {
1102                                         /* Failed execution of the script */
1103                                         BPY_Err_Handle( scriptlink->
1104                                                         scripts[index]->name +
1105                                                         2 );
1106                                         //BPY_end_python ();
1107                                         //BPY_start_python ();
1108                                 } else {
1109                                         Py_DECREF( ret );
1110                                 }
1111                                 /* If a scriptlink has just loaded a new .blend file, the
1112                                  * scriptlink pointer became invalid (see api2_2x/Blender.c),
1113                                  * so we stop here. */
1114                                 if( during_scriptlink(  ) == -1 ) {
1115                                         during_slink = 1;
1116                                         break;
1117                                 }
1118                         }
1119                 }
1120
1121                 disable_where_scriptlink( (short)(during_slink - 1) );
1122
1123                 /* cleanup bylink flag and clear link so PyObject
1124                  * can be released 
1125                  */
1126                 EXPP_dict_set_item_str( g_blenderdict, "bylink", EXPP_incr_ret_False() );
1127                 PyDict_SetItemString( g_blenderdict, "link", Py_None );
1128                 EXPP_dict_set_item_str( g_blenderdict, "event",
1129                                       PyString_FromString( "" ) );
1130         }
1131 }
1132
1133 /* SPACE HANDLERS */
1134
1135 /* These are special script links that can be assigned to ScrArea's to
1136  * (EVENT type) receive events sent to a given space (and use or ignore them) or
1137  * (DRAW type) be called after the space is drawn, to draw anything on top of
1138  * the space area. */
1139
1140 /* How to add space handlers to other spaces:
1141  * - add the space event defines to DNA_scriptlink_types.h, as done for
1142  *   3d view: SPACEHANDLER_VIEW3D_EVENT, for example;
1143  * - add the new defines to Blender.SpaceHandler dictionary in Blender.c;
1144  * - check space.c for how to call the event handlers;
1145  * - check drawview.c for how to call the draw handlers;
1146  * - check header_view3d.c for how to add the "Space Handler Scripts" menu.
1147  * Note: DRAW handlers should be called with 'event = 0', chech drawview.c */
1148
1149 int BPY_has_spacehandler(Text *text, ScrArea *sa)
1150 {
1151         ScriptLink *slink;
1152         int index;
1153
1154         if (!sa || !text) return 0;
1155
1156         slink = &sa->scriptlink;
1157
1158         for (index = 0; index < slink->totscript; index++) {
1159                 if (slink->scripts[index] && (slink->scripts[index] == (ID *)text))
1160                         return 1;
1161         }
1162
1163         return 0;       
1164 }
1165
1166 int BPY_is_spacehandler(Text *text, char spacetype)
1167 {
1168         TextLine *tline = text->lines.first;
1169         unsigned short type = 0;
1170
1171         if (tline && (tline->len > 10)) {
1172                 char *line = tline->line;
1173
1174                 /* Expected format: # SPACEHANDLER.SPACE.TYPE
1175                  * Ex: # SPACEHANDLER.VIEW3D.DRAW
1176                  * The actual checks are forgiving, so slight variations also work. */
1177                 if (line && line[0] == '#' && strstr(line, "HANDLER")) {
1178                         line++; /* skip '#' */
1179
1180                         /* only done for 3D View right now, trivial to add for others: */
1181                         switch (spacetype) {
1182                                 case SPACE_VIEW3D:
1183                                         if (strstr(line, "3D")) { /* VIEW3D, 3DVIEW */
1184                                                 if (strstr(line, "DRAW")) type = SPACEHANDLER_VIEW3D_DRAW;
1185                                                 else if (strstr(line, "EVENT")) type = SPACEHANDLER_VIEW3D_EVENT;
1186                                         }
1187                                         break;
1188                         }
1189                 }
1190         }
1191         return type; /* 0 if not a space handler */
1192 }
1193
1194 int BPY_del_spacehandler(Text *text, ScrArea *sa)
1195 {
1196         ScriptLink *slink;
1197         int i, j;
1198
1199         if (!sa || !text) return -1;
1200
1201         slink = &sa->scriptlink;
1202         if (slink->totscript < 1) return -1;
1203
1204         for (i = 0; i < slink->totscript; i++) {
1205                 if (text == (Text *)slink->scripts[i]) {
1206
1207                         for (j = i; j < slink->totscript - 1; j++) {
1208                                 slink->flag[j] = slink->flag[j+1];
1209                                 slink->scripts[j] = slink->scripts[j+1];
1210                         }
1211                         slink->totscript--;
1212                         /* like done in buttons_script.c we just free memory
1213                          * if all slinks have been removed -- less fragmentation,
1214                          * these should be quite small arrays */
1215                         if (slink->totscript == 0) {
1216                                 if (slink->scripts) MEM_freeN(slink->scripts);
1217                                 if (slink->flag) MEM_freeN(slink->flag);
1218                                 break;
1219                         }
1220                 }
1221         }
1222         return 0;
1223 }
1224
1225 int BPY_add_spacehandler(Text *text, ScrArea *sa, char spacetype)
1226 {
1227         unsigned short handlertype;
1228
1229         if (!sa || !text) return -1;
1230
1231         handlertype = (unsigned short)BPY_is_spacehandler(text, spacetype);
1232
1233         if (handlertype) {
1234                 ScriptLink *slink = &sa->scriptlink;
1235                 void *stmp, *ftmp;
1236                 unsigned short space_event = SPACEHANDLER_VIEW3D_EVENT;
1237
1238                 /* extend slink */
1239
1240                 stmp= slink->scripts;           
1241                 slink->scripts= MEM_mallocN(sizeof(ID*)*(slink->totscript+1),
1242                         "spacehandlerscripts");
1243         
1244                 ftmp= slink->flag;              
1245                 slink->flag= MEM_mallocN(sizeof(short*)*(slink->totscript+1),
1246                         "spacehandlerflags");
1247         
1248                 if (slink->totscript) {
1249                         memcpy(slink->scripts, stmp, sizeof(ID*)*(slink->totscript));
1250                         MEM_freeN(stmp);
1251
1252                         memcpy(slink->flag, ftmp, sizeof(short)*(slink->totscript));
1253                         MEM_freeN(ftmp);
1254                 }
1255
1256                 switch (spacetype) {
1257                         case SPACE_VIEW3D:
1258                                 if (handlertype == 1) space_event = SPACEHANDLER_VIEW3D_EVENT;
1259                                 else space_event = SPACEHANDLER_VIEW3D_DRAW;
1260                                 break;
1261                         default:
1262                                 break;
1263                 }
1264
1265                 slink->scripts[slink->totscript] = (ID *)text;
1266                 slink->flag[slink->totscript]= space_event;
1267
1268                 slink->totscript++;
1269                 slink->actscript = slink->totscript;
1270
1271         }
1272         return 0;
1273 }
1274
1275 int BPY_do_spacehandlers( ScrArea *sa, unsigned short event,
1276         unsigned short space_event )
1277 {
1278         ScriptLink *scriptlink;
1279         int retval = 0;
1280
1281         if (!sa) return 0;
1282
1283         scriptlink = &sa->scriptlink;
1284
1285         if (scriptlink->totscript > 0) {
1286                 PyObject *dict;
1287                 PyObject *ret;
1288                 int index, during_slink = during_scriptlink();
1289
1290                 /* invalid scriptlinks (new .blend was just loaded), return */
1291                 if (during_slink < 0) return 0;
1292
1293                 /* tell we're running a scriptlink.  The sum also tells if this script
1294                  * is running nested inside another.  Blender.Load needs this info to
1295                  * avoid trouble with invalid slink pointers.
1296                  * Update (test): allow EVENT space handlers to call file/image selectors,
1297                  * still disabled for DRAW space handlers: */
1298                 if (event == 0) { /* event = 0: DRAW space handler */
1299                         during_slink++;
1300                         disable_where_scriptlink( (short)during_slink );
1301                 }
1302
1303                 /* set globals in Blender module to identify space handler scriptlink */
1304                 EXPP_dict_set_item_str(g_blenderdict, "bylink", EXPP_incr_ret_True());
1305                 /* unlike normal scriptlinks, here Blender.link is int (space event type) */
1306                 EXPP_dict_set_item_str(g_blenderdict, "link", PyInt_FromLong(space_event));
1307                 /* note: DRAW space_events set event to 0 */
1308                 EXPP_dict_set_item_str(g_blenderdict, "event", PyInt_FromLong(event));
1309
1310                 /* now run all assigned space handlers for this space and space_event */
1311                 for( index = 0; index < scriptlink->totscript; index++ ) {
1312
1313                         /* for DRAW handlers: */
1314                         if (event == 0) {
1315                                 glPushAttrib(GL_ALL_ATTRIB_BITS);
1316                                 glMatrixMode(GL_PROJECTION);
1317                                 glPushMatrix();
1318                                 glMatrixMode(GL_MODELVIEW);
1319                                 glPushMatrix();
1320                         }
1321
1322                         if( ( scriptlink->flag[index] == space_event ) &&
1323                             ( scriptlink->scripts[index] != NULL ) ) {
1324                                 dict = CreateGlobalDictionary();
1325                                 ret = RunPython( ( Text * ) scriptlink->scripts[index], dict );
1326                                 ReleaseGlobalDictionary( dict );
1327
1328                                 if (!ret) { /* Failed execution of the script */
1329                                         BPY_Err_Handle( scriptlink->scripts[index]->name+2 );
1330                                 } else {
1331                                         Py_DECREF(ret);
1332
1333                                         /* an EVENT type (event != 0) script can either accept an event or
1334                                          * ignore it:
1335                                          * if the script sets Blender.event to None it accepted it;
1336                                          * otherwise the space's event handling callback that called us
1337                                          * can go on processing the event */
1338                                         if (event && (PyDict_GetItemString(g_blenderdict,"event") == Py_None))
1339                                                 retval = 1; /* event was swallowed */
1340                                 }
1341
1342                                 /* If a scriptlink has just loaded a new .blend file, the
1343                                  * scriptlink pointer became invalid (see api2_2x/Blender.c),
1344                                  * so we stop here. */
1345                                 if( during_scriptlink(  ) == -1 ) {
1346                                         during_slink = 1;
1347                                         if (event == 0) glPopAttrib();
1348                                         break;
1349                                 }
1350                         }
1351
1352                         /* for DRAW handlers: */
1353                         if (event == 0) {
1354                                 glMatrixMode(GL_PROJECTION);
1355                                 glPopMatrix();
1356                                 glMatrixMode(GL_MODELVIEW);
1357                                 glPopMatrix();
1358                                 glPopAttrib();
1359                                 disable_where_scriptlink( (short)(during_slink - 1) );
1360                         }
1361
1362                 }
1363
1364                 EXPP_dict_set_item_str(g_blenderdict, "bylink", EXPP_incr_ret_False());
1365                 PyDict_SetItemString(g_blenderdict, "link", Py_None );
1366                 EXPP_dict_set_item_str(g_blenderdict, "event", PyString_FromString(""));
1367         }
1368         
1369         /* retval:
1370          * space_event is of type EVENT:
1371          * 0 - event was returned,
1372          * 1 - event was processed;
1373          * space_event is of type DRAW:
1374          * 0 always */
1375
1376         return retval;
1377 }
1378
1379 /*****************************************************************************
1380 * Description:  
1381 * Notes:
1382 *****************************************************************************/
1383 void BPY_free_scriptlink( struct ScriptLink *slink )
1384 {
1385         if( slink->totscript ) {
1386                 if( slink->flag )
1387                         MEM_freeN( slink->flag );
1388                 if( slink->scripts )
1389                         MEM_freeN( slink->scripts );
1390         }
1391
1392         return;
1393 }
1394
1395 void BPY_free_screen_spacehandlers(struct bScreen *sc)
1396 {
1397         ScrArea *sa;
1398
1399         for (sa = sc->areabase.first; sa; sa = sa->next)
1400                 BPY_free_scriptlink(&sa->scriptlink);
1401 }
1402
1403 static int CheckAllSpaceHandlers(Text *text)
1404 {
1405         bScreen *screen;
1406         ScrArea *sa;
1407         ScriptLink *slink;
1408         int fixed = 0;
1409
1410         for (screen = G.main->screen.first; screen; screen = screen->id.next) {
1411                 for (sa = screen->areabase.first; sa; sa = sa->next) {
1412                         slink = &sa->scriptlink;
1413                         if (!slink->totscript) continue;
1414                         if (BPY_del_spacehandler(text, sa) == 0) fixed++;
1415                 }
1416         }
1417         return fixed;
1418 }
1419
1420 static int CheckAllScriptsFromList( ListBase * list, Text * text )
1421 {
1422         ID *id;
1423         ScriptLink *scriptlink;
1424         int index;
1425         int fixed = 0;
1426
1427         id = list->first;
1428
1429         while( id != NULL ) {
1430                 scriptlink = ID_getScriptlink( id );
1431                 if( scriptlink && scriptlink->totscript ) {
1432                         for( index = 0; index < scriptlink->totscript; index++) {
1433                                 if ((Text *)scriptlink->scripts[index] == text) {
1434                                         scriptlink->scripts[index] = NULL;
1435                                         fixed++;
1436                                 }
1437                         }
1438                 }
1439                 id = id->next;
1440         }
1441
1442         return fixed;
1443 }
1444
1445 /* When a Text is deleted, we need to unlink it from eventual scriptlinks */
1446 int BPY_check_all_scriptlinks( Text * text )
1447 {
1448         int fixed = 0;
1449         fixed += CheckAllScriptsFromList( &( G.main->object ), text );
1450         fixed += CheckAllScriptsFromList( &( G.main->lamp ), text );
1451         fixed += CheckAllScriptsFromList( &( G.main->camera ), text );
1452         fixed += CheckAllScriptsFromList( &( G.main->mat ), text );
1453         fixed += CheckAllScriptsFromList( &( G.main->world ), text );
1454         fixed += CheckAllScriptsFromList( &( G.main->scene ), text );
1455         fixed += CheckAllSpaceHandlers(text);
1456
1457         return fixed;
1458 }
1459
1460 /*****************************************************************************
1461 * Description: 
1462 * Notes:
1463 *****************************************************************************/
1464 void BPY_copy_scriptlink( struct ScriptLink *scriptlink )
1465 {
1466         void *tmp;
1467
1468         if( scriptlink->totscript ) {
1469
1470                 tmp = scriptlink->scripts;
1471                 scriptlink->scripts =
1472                         MEM_mallocN( sizeof( ID * ) * scriptlink->totscript,
1473                                      "scriptlistL" );
1474                 memcpy( scriptlink->scripts, tmp,
1475                         sizeof( ID * ) * scriptlink->totscript );
1476
1477                 tmp = scriptlink->flag;
1478                 scriptlink->flag =
1479                         MEM_mallocN( sizeof( short ) * scriptlink->totscript,
1480                                      "scriptlistF" );
1481                 memcpy( scriptlink->flag, tmp,
1482                         sizeof( short ) * scriptlink->totscript );
1483         }
1484
1485         return;
1486 }
1487
1488 /****************************************************************************
1489 * Description:
1490 * Notes:                Not implemented yet
1491 *****************************************************************************/
1492 int BPY_call_importloader( char *name )
1493 {                       /* XXX Should this function go away from Blender? */
1494         printf( "In BPY_call_importloader(name=%s)\n", name );
1495         return ( 0 );
1496 }
1497
1498 /*****************************************************************************
1499 * Private functions
1500 *****************************************************************************/
1501
1502 /*****************************************************************************
1503 * Description: This function executes the python script passed by text. 
1504 *               The Python dictionary containing global variables needs to
1505 *               be passed in globaldict.
1506 *****************************************************************************/
1507 PyObject *RunPython( Text * text, PyObject * globaldict )
1508 {
1509         char *buf = NULL;
1510
1511 /* The script text is compiled to Python bytecode and saved at text->compiled
1512  * to speed-up execution if the user executes the script multiple times */
1513
1514         if( !text->compiled ) { /* if it wasn't already compiled, do it now */
1515                 buf = txt_to_buf( text );
1516
1517                 text->compiled =
1518                         Py_CompileString( buf, GetName( text ),
1519                                           Py_file_input );
1520
1521                 MEM_freeN( buf );
1522
1523                 if( PyErr_Occurred(  ) ) {
1524                         BPY_free_compiled_text( text );
1525                         return NULL;
1526                 }
1527
1528         }
1529
1530         return PyEval_EvalCode( text->compiled, globaldict, globaldict );
1531 }
1532
1533 /*****************************************************************************
1534 * Description: This function returns the value of the name field of the 
1535 *       given Text struct.
1536 *****************************************************************************/
1537 char *GetName( Text * text )
1538 {
1539         return ( text->id.name + 2 );
1540 }
1541
1542 /*****************************************************************************
1543 * Description: This function creates a new Python dictionary object.
1544 *****************************************************************************/
1545 PyObject *CreateGlobalDictionary( void )
1546 {
1547         PyObject *dict = PyDict_New(  );
1548
1549         PyDict_SetItemString( dict, "__builtins__", PyEval_GetBuiltins(  ) );
1550         EXPP_dict_set_item_str( dict, "__name__",
1551                               PyString_FromString( "__main__" ) );
1552
1553         return dict;
1554 }
1555
1556 /*****************************************************************************
1557 * Description: This function deletes a given Python dictionary object.
1558 *****************************************************************************/
1559 void ReleaseGlobalDictionary( PyObject * dict )
1560 {
1561         PyDict_Clear( dict );
1562         Py_DECREF( dict );      /* Release dictionary. */
1563
1564         return;
1565 }
1566
1567 /***************************************************************************
1568 * Description: This function runs all scripts (if any) present in the
1569 *               list argument. The event by which the function has been 
1570 *               called, is passed in the event argument.
1571 *****************************************************************************/
1572 void DoAllScriptsFromList( ListBase * list, short event )
1573 {
1574         ID *id;
1575
1576         id = list->first;
1577
1578         while( id != NULL ) {
1579                 BPY_do_pyscript( id, event );
1580                 id = id->next;
1581         }
1582
1583         return;
1584 }
1585
1586 PyObject *importText( char *name )
1587 {
1588         Text *text;
1589         char *txtname;
1590         char *buf = NULL;
1591         int namelen = strlen( name );
1592
1593         txtname = malloc( namelen + 3 + 1 );
1594         if( !txtname )
1595                 return NULL;
1596
1597         memcpy( txtname, name, namelen );
1598         memcpy( &txtname[namelen], ".py", 4 );
1599
1600         text = ( Text * ) & ( G.main->text.first );
1601
1602         while( text ) {
1603                 if( !strcmp( txtname, GetName( text ) ) )
1604                         break;
1605                 text = text->id.next;
1606         }
1607
1608         if( !text ) {
1609                 free( txtname );
1610                 return NULL;
1611         }
1612
1613         if( !text->compiled ) {
1614                 buf = txt_to_buf( text );
1615                 text->compiled =
1616                         Py_CompileString( buf, GetName( text ),
1617                                           Py_file_input );
1618                 MEM_freeN( buf );
1619
1620                 if( PyErr_Occurred(  ) ) {
1621                         PyErr_Print(  );
1622                         BPY_free_compiled_text( text );
1623                         free( txtname );
1624                         return NULL;
1625                 }
1626         }
1627
1628         free( txtname );
1629         return PyImport_ExecCodeModule( name, text->compiled );
1630 }
1631
1632 static PyMethodDef bimport[] = {
1633         {"blimport", blender_import, METH_VARARGS, "our own import"}
1634 };
1635
1636 PyObject *blender_import( PyObject * self, PyObject * args )
1637 {
1638         PyObject *exception, *err, *tb;
1639         char *name;
1640         PyObject *globals = NULL, *locals = NULL, *fromlist = NULL;
1641         PyObject *m;
1642
1643         if( !PyArg_ParseTuple( args, "s|OOO:bimport",
1644                                &name, &globals, &locals, &fromlist ) )
1645                 return NULL;
1646
1647         m = PyImport_ImportModuleEx( name, globals, locals, fromlist );
1648
1649         if( m )
1650                 return m;
1651         else
1652                 PyErr_Fetch( &exception, &err, &tb );   /*restore for probable later use */
1653
1654         m = importText( name );
1655         if( m ) {               /* found module, ignore above exception */
1656                 PyErr_Clear(  );
1657                 Py_XDECREF( exception );
1658                 Py_XDECREF( err );
1659                 Py_XDECREF( tb );
1660                 printf( "imported from text buffer...\n" );
1661         } else {
1662                 PyErr_Restore( exception, err, tb );
1663         }
1664         return m;
1665 }
1666
1667 void init_ourImport( void )
1668 {
1669         PyObject *m, *d;
1670         PyObject *import = PyCFunction_New( bimport, NULL );
1671
1672         m = PyImport_AddModule( "__builtin__" );
1673         d = PyModule_GetDict( m );
1674         EXPP_dict_set_item_str( d, "__import__", import );
1675 }
1676
1677 /*
1678  * find in-memory module and recompile
1679  */
1680
1681 static PyObject *reimportText( PyObject *module )
1682 {
1683         Text *text;
1684         char *txtname;
1685         char *name;
1686         char *buf = NULL;
1687
1688         /* get name, filename from the module itself */
1689
1690         txtname = PyModule_GetFilename( module );
1691         name = PyModule_GetName( module );
1692         if( !txtname || !name)
1693                 return NULL;
1694
1695         /* look up the text object */
1696         text = ( Text * ) & ( G.main->text.first );
1697         while( text ) {
1698                 if( !strcmp( txtname, GetName( text ) ) )
1699                         break;
1700                 text = text->id.next;
1701         }
1702
1703         /* uh-oh.... didn't find it */
1704         if( !text )
1705                 return NULL;
1706
1707         /* if previously compiled, free the object */
1708         /* (can't see how could be NULL, but check just in case) */ 
1709         if( text->compiled ){
1710                 Py_DECREF( (PyObject *)text->compiled );
1711         }
1712
1713         /* compile the buffer */
1714         buf = txt_to_buf( text );
1715         text->compiled = Py_CompileString( buf, GetName( text ),
1716                         Py_file_input );
1717         MEM_freeN( buf );
1718
1719         /* if compile failed.... return this error */
1720         if( PyErr_Occurred(  ) ) {
1721                 PyErr_Print(  );
1722                 BPY_free_compiled_text( text );
1723                 return NULL;
1724         }
1725
1726         /* make into a module */
1727         return PyImport_ExecCodeModule( name, text->compiled );
1728 }
1729
1730 /*
1731  * our reload() module, to handle reloading in-memory scripts
1732  */
1733
1734 static PyObject *blender_reload( PyObject * self, PyObject * args )
1735 {
1736         PyObject *exception, *err, *tb;
1737         PyObject *module = NULL;
1738         PyObject *newmodule = NULL;
1739
1740         /* check for a module arg */
1741         if( !PyArg_ParseTuple( args, "O:breload", &module ) )
1742                 return NULL;
1743
1744         /* try reimporting from file */
1745         newmodule = PyImport_ReloadModule( module );
1746         if( newmodule )
1747                 return newmodule;
1748
1749         /* no file, try importing from memory */
1750         PyErr_Fetch( &exception, &err, &tb );   /*restore for probable later use */
1751
1752         newmodule = reimportText( module );
1753         if( newmodule ) {               /* found module, ignore above exception */
1754                 PyErr_Clear(  );
1755                 Py_XDECREF( exception );
1756                 Py_XDECREF( err );
1757                 Py_XDECREF( tb );
1758         } else
1759                 PyErr_Restore( exception, err, tb );
1760
1761         return newmodule;
1762 }
1763
1764 static PyMethodDef breload[] = {
1765         {"blreload", blender_reload, METH_VARARGS, "our own reload"}
1766 };
1767
1768 void init_ourReload( void )
1769 {
1770         PyObject *m, *d;
1771         PyObject *reload = PyCFunction_New( breload, NULL );
1772
1773         m = PyImport_AddModule( "__builtin__" );
1774         d = PyModule_GetDict( m );
1775         EXPP_dict_set_item_str( d, "reload", reload );
1776 }