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