resolve some compiler warnings with intel c/c++ compiler
[blender-staging.git] / source / blender / python / BPY_interface.c
index 69bff059356ef6de3fae913a960fa3b5dfc5a1b8..59b72702c504dcbfcbfd0427be95e7eff417041b 100644 (file)
@@ -100,7 +100,7 @@ PyObject *bpy_orig_syspath_List = NULL;
  *    creates list in __main__ module dict 
  */
   
-int setup_armature_weakrefs()
+static int setup_armature_weakrefs()
 {
        PyObject *maindict;
        PyObject *main_module;
@@ -159,19 +159,18 @@ ScriptError g_script_error;
 /***************************************************************************
 * Function prototypes 
 ***************************************************************************/
-PyObject *RunPython( Text * text, PyObject * globaldict );
-PyObject *CreateGlobalDictionary( void );
-void ReleaseGlobalDictionary( PyObject * dict );
-void DoAllScriptsFromList( ListBase * list, short event );
+static PyObject *RunPython( Text * text, PyObject * globaldict );
+static PyObject *CreateGlobalDictionary( void );
+static void ReleaseGlobalDictionary( PyObject * dict );
+static void DoAllScriptsFromList( ListBase * list, short event );
 static PyObject *importText( char *name );
-void init_ourImport( void );
-void init_ourReload( void );
-PyObject *blender_import( PyObject * self, PyObject * args );
-PyObject *RunPython2( Text * text, PyObject * globaldict, PyObject *localdict );
+static void init_ourImport( void );
+static void init_ourReload( void );
+static PyObject *blender_import( PyObject * self, PyObject * args );
 
 
-void BPY_Err_Handle( char *script_name );
-PyObject *traceback_getFilename( PyObject * tb );
+static void BPY_Err_Handle( char *script_name );
+static PyObject *traceback_getFilename( PyObject * tb );
 
 /****************************************************************************
 * Description: This function will start the interpreter and load all modules
@@ -292,7 +291,7 @@ void syspath_append( char *dirname )
        short ok=1;
        PyErr_Clear(  );
 
-       dir = Py_BuildValue( "s", dirname );
+       dir = PyString_FromString( dirname );
 
        mod_sys = PyImport_ImportModule( "sys" );       /* new ref */
        
@@ -308,32 +307,29 @@ void syspath_append( char *dirname )
        }
        
        if (PySequence_Contains(path, dir)==0) { /* Only add if we need to */
-               if (ok && PyList_Append( path, dir ) != 0)
+               if (ok && PyList_Append( path, dir ) != 0) /* decref below */
                        ok = 0; /* append failed */
        
                if( (ok==0) || PyErr_Occurred(  ) )
                        Py_FatalError( "could import or build sys.path, can't continue" );
        }
+       Py_DECREF( dir );
        Py_XDECREF( mod_sys );
 }
 
 void init_syspath( int first_time )
 {
-       PyObject *path;
        PyObject *mod, *d;
        char *progname;
        char execdir[FILE_MAXDIR];      /*defines from DNA_space_types.h */
 
        int n;
-       
-       
-       path = Py_BuildValue( "s", bprogname );
 
        mod = PyImport_ImportModule( "Blender.sys" );
 
        if( mod ) {
                d = PyModule_GetDict( mod );
-               EXPP_dict_set_item_str( d, "progname", path );
+               EXPP_dict_set_item_str( d, "progname", PyString_FromString( bprogname ) );
                Py_DECREF( mod );
        } else
                printf( "Warning: could not set Blender.sys.progname\n" );
@@ -510,7 +506,7 @@ const char *BPY_Err_getFilename( void )
 /*****************************************************************************/
 /* Description: Return PyString filename from a traceback object           */
 /*****************************************************************************/
-PyObject *traceback_getFilename( PyObject * tb )
+static PyObject *traceback_getFilename( PyObject * tb )
 {
        PyObject *v = NULL;
 
@@ -534,7 +530,7 @@ PyObject *traceback_getFilename( PyObject * tb )
 * Description: Blender Python error handler. This catches the error and        
 * stores filename and line number in a global  
 *****************************************************************************/
-void BPY_Err_Handle( char *script_name )
+static void BPY_Err_Handle( char *script_name )
 {
        PyObject *exception, *err, *tb, *v;
 
@@ -556,6 +552,7 @@ void BPY_Err_Handle( char *script_name )
        if( exception
            && PyErr_GivenExceptionMatches( exception, PyExc_SyntaxError ) ) {
                /* no traceback available when SyntaxError */
+               PyErr_NormalizeException( &exception, &err, &tb );
                PyErr_Restore( exception, err, tb );    /* takes away reference! */
                PyErr_Print(  );
                v = PyObject_GetAttrString( err, "lineno" );
@@ -722,13 +719,23 @@ int BPY_txt_do_python_Text( struct Text *text )
 * automatically. The script can be a file or a Blender Text in the current 
 * .blend.
 ****************************************************************************/
-void BPY_run_python_script( char *fn )
+void BPY_run_python_script( const char *fn )
 {
+       char filename[FILE_MAXDIR + FILE_MAXFILE];
        Text *text = NULL;
        int is_blender_text = 0;
-
-       if (!BLI_exists(fn)) {  /* if there's no such filename ... */
-               text = G.main->text.first;      /* try an already existing Blender Text */
+       
+       BLI_strncpy(filename, fn, FILE_MAXDIR + FILE_MAXFILE);
+       
+       if (!BLI_exists(filename))
+               BLI_convertstringcwd(filename);
+               
+       if (!BLI_exists(filename)) {    /* if there's no such filename ... */
+               /* try an already existing Blender Text.
+                * use 'fn' rather then filename for this since were looking for
+                * internal text
+                */
+               text = G.main->text.first;
 
                while (text) {
                        if (!strcmp(fn, text->id.name + 2)) break;
@@ -743,11 +750,14 @@ void BPY_run_python_script( char *fn )
        }
 
        else {
-               text = add_text(fn);
+               /* use filename here since we know it exists,
+                * 'fn' may have been a relative path
+                */
+               text = add_text(filename);
 
                if (text == NULL) {
                        printf("\nError in BPY_run_python_script:\n"
-                               "couldn't create Blender text from %s\n", fn);
+                               "couldn't create Blender text from \"%s\"\n", filename);
                /* Chris: On Windows if I continue I just get a segmentation
                 * violation.  To get a baseline file I exit here. */
                exit(2);
@@ -764,13 +774,8 @@ void BPY_run_python_script( char *fn )
                /* We can't simply free the text, since the script might have called
                 * Blender.Load() to load a new .blend, freeing previous data.
                 * So we check if the pointer is still valid. */
-               Text *txtptr = G.main->text.first;
-               while (txtptr) {
-                       if (txtptr == text) {
-                               free_libblock(&G.main->text, text);
-                               break;
-                       }
-                       txtptr = txtptr->id.next;
+               if (BLI_findindex(&G.main->text, text) != -1) {
+                       free_libblock(&G.main->text, text);
                }
        }
 }
@@ -780,9 +785,6 @@ int BPY_run_script(Script *script)
        PyObject *py_dict, *py_res, *pyarg;
        Text *text = NULL;
        BPy_constant *info;
-       int len;
-       
-       FILE *fp = NULL;
        
        PyGILState_STATE gilstate = PyGILState_Ensure();
        
@@ -827,12 +829,8 @@ int BPY_run_script(Script *script)
                Py_INCREF( Py_None );
                pyarg = Py_None;
        } else {
-               if (BLI_exists(script->scriptname)) {
-                       fp = fopen( script->scriptname, "rb" );
-               }
-               
-               if( !fp ) {
-                       printf( "Error loading script: couldn't open file %s\n", script->scriptname );
+               if (!BLI_exists(script->scriptname)) {
+                       printf( "Script does not exit %s\n", script->scriptname );
                        free_libblock( &G.main->script, script );
                        PyGILState_Release(gilstate);
                        return 0;
@@ -877,51 +875,17 @@ int BPY_run_script(Script *script)
        if (text) {
                py_res = RunPython( text, py_dict );
        } else {
+               char pystring[sizeof(script->scriptname) + 15];
+               sprintf(pystring, "execfile(r'%s')", script->scriptname);
+               py_res = PyRun_String( pystring, Py_file_input, py_dict, py_dict );
+       }
+
+       if( !py_res ) {         /* Failed execution of the script */
                /* Previously we used PyRun_File to run directly the code on a FILE 
                * object, but as written in the Python/C API Ref Manual, chapter 2,
                * 'FILE structs for different C libraries can be different and 
                * incompatible'.
                * So now we load the script file data to a buffer */
-               char *buffer=NULL, *buffer_ofs=NULL, *b_to, *b_from;
-               
-               fseek( fp, 0L, SEEK_END );
-               len = ftell( fp );
-               fseek( fp, 0L, SEEK_SET );
-       
-               buffer = buffer_ofs = MEM_mallocN( len + 2, "pyfilebuf" );      /* len+2 to add '\n\0' */
-               len = fread( buffer, 1, len, fp );
-       
-               buffer[len] = '\n';     /* fix syntax error in files w/o eol */
-               buffer[len + 1] = '\0';
-               
-               
-               /* fast clean-up of dos cr/lf line endings, remove convert '\r\n's to '\n' */
-               if (*buffer_ofs == '\r' && *(buffer_ofs+1) == '\n') {
-                       buffer_ofs++;
-               }
-               b_from = b_to = buffer_ofs;
-               
-               while(*b_from != '\0') {
-                       if (*b_from == '\r' && *( b_from+1 ) == '\n') {
-                               b_from++;
-                       }
-                       if (b_from != b_to) {
-                               *b_to = *b_from;
-                       }
-                       b_to++;
-                       b_from++;
-               }
-               *b_to = '\0';
-               /* done cleaning the string */
-               
-               fclose( fp );
-               
-               py_res = PyRun_String( buffer_ofs, Py_file_input, py_dict, py_dict );
-               MEM_freeN( buffer );
-       }
-
-       if( !py_res ) {         /* Failed execution of the script */
-
                BPY_Err_Handle( script->id.name + 2 );
                ReleaseGlobalDictionary( py_dict );
                script->py_globaldict = NULL;
@@ -965,8 +929,38 @@ int BPY_run_script(Script *script)
 *****************************************************************************/
 int BPY_menu_do_python( short menutype, int event )
 {
-       char *argstr = NULL;
        BPyMenu *pym;
+       pym = BPyMenu_GetEntry( menutype, ( short ) event );
+       return BPY_menu_invoke( pym, menutype );
+}
+       
+/****************************************************************************
+* Description: This function executes the script by its shortcut.
+* Notes:       It is called by the ui code in src/???.c when a user presses an
+*              unassigned key combination. Scripts are searched in the BPyMenuTable,
+*              using the given menutype and event values to know which one to invoke.
+*****************************************************************************/
+int BPY_menu_do_shortcut( short menutype, unsigned short key, unsigned short qual )
+{
+       BPyMenu *pym;
+       pym = BPyMenu_GetEntry( menutype, 0 );
+
+       while ( pym ) {
+               if ( pym->key && pym->key == key && pym->qual == qual ) {
+                       return BPY_menu_invoke( pym, menutype );
+               }
+               pym = pym->next;
+       }
+       
+       return 0;
+}
+
+/****************************************************************************
+* Description: This function executes the script described by a menu item.
+*****************************************************************************/
+int BPY_menu_invoke( BPyMenu *pym, short menutype )
+{
+       char *argstr = NULL;
        BPySubMenu *pysm;
        char scriptname[21];
        Script *script = NULL;
@@ -974,8 +968,6 @@ int BPY_menu_do_python( short menutype, int event )
        PyGILState_STATE gilstate;
        char filestr[FILE_MAX];
 
-       pym = BPyMenu_GetEntry( menutype, ( short ) event );
-
        if( !pym )
                return 0;
 
@@ -1059,6 +1051,7 @@ int BPY_menu_do_python( short menutype, int event )
        case PYMENU_RENDER:
        case PYMENU_WIZARDS:
        case PYMENU_SCRIPTTEMPLATE:
+       case PYMENU_TEXTPLUGIN:
        case PYMENU_MESHFACEKEY:
                break;
 
@@ -2169,8 +2162,14 @@ void BPY_clear_bad_scriptlinks( struct Text *byebye )
 *      For the scene, only the current active scene the scripts are 
 *      executed (if any).
 *****************************************************************************/
-void BPY_do_all_scripts( short event )
+void BPY_do_all_scripts( short event, short anim )
 {
+       /* during stills rendering we disable FRAMECHANGED events */
+       static char disable_frame_changed = 0;
+
+       if ((event == SCRIPT_FRAMECHANGED) && disable_frame_changed)
+               return;
+
        DoAllScriptsFromList( &( G.main->object ), event );
        DoAllScriptsFromList( &( G.main->lamp ), event );
        DoAllScriptsFromList( &( G.main->camera ), event );
@@ -2186,9 +2185,12 @@ void BPY_do_all_scripts( short event )
         * "import sys; sys.setcheckinterval(sys.maxint)" */
        if (event == SCRIPT_RENDER) {
                _Py_CheckInterval = PyInt_GetMax();
+               if (!anim)
+                       disable_frame_changed = 1;
        }
        else if (event == SCRIPT_POSTRENDER) {
                _Py_CheckInterval = 100; /* Python default */
+               disable_frame_changed = 0;
        }
 
        return;
@@ -2472,7 +2474,7 @@ int BPY_add_spacehandler(Text *text, ScrArea *sa, char spacetype)
 }
 
 int BPY_do_spacehandlers( ScrArea *sa, unsigned short event,
-       unsigned short space_event )
+       short eventValue, unsigned short space_event )
 {
        ScriptLink *scriptlink;
        int retval = 0;
@@ -2512,8 +2514,9 @@ int BPY_do_spacehandlers( ScrArea *sa, unsigned short event,
                PyDict_SetItemString(g_blenderdict, "bylink", Py_True);
                /* unlike normal scriptlinks, here Blender.link is int (space event type) */
                EXPP_dict_set_item_str(g_blenderdict, "link", PyInt_FromLong(space_event));
-               /* note: DRAW space_events set event to 0 */
+               /* note: DRAW space_events set event and val to 0 */
                EXPP_dict_set_item_str(g_blenderdict, "event", PyInt_FromLong(event));
+               EXPP_dict_set_item_str(g_blenderdict, "eventValue", PyInt_FromLong(eventValue));
                /* now run all assigned space handlers for this space and space_event */
                for( index = 0; index < scriptlink->totscript; index++ ) {
                        
@@ -2709,7 +2712,7 @@ int BPY_call_importloader( char *name )
 *              The Python dictionary containing global variables needs to
 *              be passed in globaldict.
 *****************************************************************************/
-PyObject *RunPython( Text * text, PyObject * globaldict )
+static PyObject *RunPython( Text * text, PyObject * globaldict )
 {
        char *buf = NULL;
 
@@ -2737,7 +2740,7 @@ PyObject *RunPython( Text * text, PyObject * globaldict )
 /*****************************************************************************
 * Description: This function creates a new Python dictionary object.
 *****************************************************************************/
-PyObject *CreateGlobalDictionary( void )
+static PyObject *CreateGlobalDictionary( void )
 {
        PyObject *dict = PyDict_New(  );
 
@@ -2751,7 +2754,7 @@ PyObject *CreateGlobalDictionary( void )
 /*****************************************************************************
 * Description: This function deletes a given Python dictionary object.
 *****************************************************************************/
-void ReleaseGlobalDictionary( PyObject * dict )
+static void ReleaseGlobalDictionary( PyObject * dict )
 {
        PyDict_Clear( dict );
        Py_DECREF( dict );      /* Release dictionary. */
@@ -2764,7 +2767,7 @@ void ReleaseGlobalDictionary( PyObject * dict )
 *              list argument. The event by which the function has been 
 *              called, is passed in the event argument.
 *****************************************************************************/
-void DoAllScriptsFromList( ListBase * list, short event )
+static void DoAllScriptsFromList( ListBase * list, short event )
 {
        ID *id;
 
@@ -2817,7 +2820,7 @@ static PyMethodDef bimport[] = {
        {"blimport", blender_import, METH_VARARGS, "our own import"}
 };
 
-PyObject *blender_import( PyObject * self, PyObject * args )
+static PyObject *blender_import( PyObject * self, PyObject * args )
 {
        PyObject *exception, *err, *tb;
        char *name;
@@ -2848,7 +2851,7 @@ PyObject *blender_import( PyObject * self, PyObject * args )
        return m;
 }
 
-void init_ourImport( void )
+static void init_ourImport( void )
 {
        PyObject *m, *d;
        PyObject *import = PyCFunction_New( bimport, NULL );
@@ -2949,7 +2952,7 @@ static PyMethodDef breload[] = {
        {"blreload", blender_reload, METH_VARARGS, "our own reload"}
 };
 
-void init_ourReload( void )
+static void init_ourReload( void )
 {
        PyObject *m, *d;
        PyObject *reload = PyCFunction_New( breload, NULL );