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