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