From 13e7525152e9bd7f187bcc89adfd50c5ac4d37ff Mon Sep 17 00:00:00 2001
From: Willian Padovani Germano <wpgermano@gmail.com>
Date: Sun, 31 Oct 2004 04:09:19 +0000
Subject: [PATCH] BPython -- a few fixes:

-- fixed bug #1689:
http://projects.blender.org/tracker/?func=detail&atid=125&aid=1689&group_id=9

Reported by Tom Musgrove (thanks), the problem was that Window.QHandle was not passing events to windows that had id's below the current active window.  It was a stupid mistake (mine), the code was iterating from curarea instead of from the first area in the areabase list.

-- fixed bug #1568:
http://projects.blender.org/tracker/index.php?func=detail&aid=1568&group_id=9&atid=125

Stephen investigated the problem, reported by Gabriel Beloin, and left hints in the bug report, thanks :).  I also implemented what he suggested, now Effect.Get('objname') returns a list with all objname's effects and as before, Get('objname, position') returns the effect at position 'position'.  Ref doc already updated.

-- Allowed menu registration lines to appear commented out -- Python comments: '#', of course -- (suggested by Michael Reimpell) in scripts:
Some Python doc tools need the doc strings between triple double-quotes, so to avoid conflicts scripts writers can now comment out the registration code, it should work anyway.  Michael also provided a patch for this a few days ago, too (thanks), but to keep changes at a minimum because of proximity to a release I didn't use it.
---
 source/blender/python/BPY_menus.c             | 60 +++++++++-------
 source/blender/python/api2_2x/Effect.c        | 70 ++++++++++++++-----
 source/blender/python/api2_2x/Object.c        |  4 +-
 source/blender/python/api2_2x/Window.c        |  2 +-
 .../blender/python/api2_2x/doc/API_intro.py   | 30 +++++---
 source/blender/python/api2_2x/doc/Effect.py   | 13 ++--
 6 files changed, 116 insertions(+), 63 deletions(-)

diff --git a/source/blender/python/BPY_menus.c b/source/blender/python/BPY_menus.c
index 07ce418fc9a..5a2db4d1be2 100644
--- a/source/blender/python/BPY_menus.c
+++ b/source/blender/python/BPY_menus.c
@@ -597,15 +597,18 @@ static int bpymenu_CreateFromDir( char *dirname, int whichdir )
 	struct stat st;
 	struct dirent *dir_entry;
 	BPyMenu *pymenu;
-	char *s, *fname, str[FILE_MAXFILE + FILE_MAXDIR];
+	char *s, *fname, pathstr[FILE_MAXFILE + FILE_MAXDIR];
 	char line[100], w[100];
 	char name[100], submenu[100], subarg[100], tooltip[100];
 	int res = 0, version = 0;
 
 	dir = opendir( dirname );
 
-	if( !dir )
+	if( !dir ) {
+		if ( DEBUG )
+			printf("BPyMenus warning: could not open dir %s.\n", dirname);
 		return -1;
+	}
 
 /* we scan the dir for filenames ending with .py and starting with the
  * right 'magic number': '#!BPY'.  All others are ignored. */
@@ -621,18 +624,18 @@ static int bpymenu_CreateFromDir( char *dirname, int whichdir )
 		if( !s || *( s + 3 ) != '\0' )
 			continue;
 
-		BLI_make_file_string( "/", str, dirname, fname );
+		BLI_make_file_string( "/", pathstr, dirname, fname );
 
 		/* paranoia: check if this is really a file and not a disguised dir */
-		if( ( stat( str, &st ) == -1 ) || !S_ISREG( st.st_mode ) )
+		if( ( stat( pathstr, &st ) == -1 ) || !S_ISREG( st.st_mode ) )
 			continue;
 
-		fp = fopen( str, "rb" );
+		fp = fopen( pathstr, "rb" );
 
 		if( !fp ) {
 			if( DEBUG )
 				printf( "BPyMenus error: couldn't open %s.\n",
-					str );
+					pathstr );
 			continue;
 		}
 
@@ -647,8 +650,7 @@ static int bpymenu_CreateFromDir( char *dirname, int whichdir )
 
 		/* file passed the tests, look for the three double-quotes */
 		while( fgets( line, 100, fp ) ) {
-			if( line[0] == '"' && line[1] == '"'
-			    && line[2] == '"' ) {
+			if( strstr( line, "\"\"\"" )) {
 				res = 1;	/* found */
 				break;
 			}
@@ -658,13 +660,15 @@ static int bpymenu_CreateFromDir( char *dirname, int whichdir )
 			goto discard;
 
 		/* Now we're ready to get the registration info.  A little more structure
-		 * was imposed to their format, for speed. The registration
-		 * lines must appear between the first pair of triple double-quotes and
-		 * follow this order (the single-quotes are part of the format):
+		 * was imposed to the format, for speed. The registration lines must
+		 * appear between the first pair of triple double-quotes and
+		 * follow this order (the single-quotes are part of the format,
+		 * but as noted below, now the whole registration part can be commented
+		 * out so external Python tools can ignore them):
 		 * 
 		 * Name: 'script name for the menu'
-		 * Group: 'group name' (defines menu)
 		 * Blender: <short int> (minimal Blender version)
+		 * Group: 'group name' (defines menu)
 		 * Submenu: 'submenu name' related_1word_arg
 		 * Tooltip: 'tooltip for the menu'
 		 *
@@ -673,40 +677,42 @@ static int bpymenu_CreateFromDir( char *dirname, int whichdir )
 		 * submenus and the tooltip are optional;
 		 * - the Blender version is the same number reported by
 		 * Blender.Get('version') in BPython or G.version in C;
-		 * - only the first letter of each token is checked, both lower
-		 * and upper cases, so that's all that matters for recognition:
-		 * n 'script name' is enough for the name line, for example. */
+		 * - NEW in 2.35: Michael Reimpell suggested and even provided
+		 * a patch (read but not used to keep changes to a minimum for
+		 * now, shame on me) to make registration code also accept
+		 * commented out registration lines, so that BPython menu
+		 * registration doesn't mess with Python documentation tools. */
 
 		/* first the name: */
 		res = fscanf( fp, "%[^']'%[^'\r\n]'\n", w, name );
-		if( ( res != 2 ) || ( w[0] != 'n' && w[0] != 'N' ) ) {
+		if( ( res != 2 ) || !strstr(w, "Name") ) {
 			if( DEBUG )
-				printf( "BPyMenus error: wrong 'name' line in %s.\n", str );
+				printf( "BPyMenus error: wrong 'Name' line in %s.\n", pathstr );
 			goto discard;
 		}
 
-		line[0] = '\0';	/* used as group for this part */
-
 		/* minimal Blender version: */
 		res = fscanf( fp, "%s %d\n", w, &version );
-		if( ( res != 2 ) || ( w[0] != 'b' && w[0] != 'B' ) ) {
+		if( ( res != 2 ) || !strstr(w, "Blender") ) {
 			if( DEBUG )
-				printf( "BPyMenus error: wrong 'blender' line in %s.\n", str );
+				printf( "BPyMenus error: wrong 'Blender' line in %s.\n", pathstr );
 			goto discard;
 		}
 
+		line[0] = '\0';	/* used as group for this part */
+
 		/* the group: */
 		res = fscanf( fp, "%[^']'%[^'\r\n]'\n", w, line );
-		if( ( res != 2 ) || ( w[0] != 'g' && w[0] != 'G' ) ) {
+		if( ( res != 2 ) || !strstr(w, "Group" ) ) {
 			if( DEBUG )
-				printf( "BPyMenus error: wrong 'group' line in %s.\n", str );
+				printf( "BPyMenus error: wrong 'Group' line in %s.\n", pathstr );
 			goto discard;
 		}
 
 		res = bpymenu_group_atoi( line );
 		if( res < 0 ) {
 			if( DEBUG )
-				printf( "BPyMenus error: unknown 'group' %s in %s.\n", line, str );
+				printf( "BPyMenus error: unknown 'Group' %s in %s.\n", line, pathstr );
 			goto discard;
 		}
 
@@ -714,7 +720,7 @@ static int bpymenu_CreateFromDir( char *dirname, int whichdir )
 					   whichdir, NULL );
 		if( !pymenu ) {
 			if( DEBUG )
-				printf( "BPyMenus error: couldn't create entry for %s.\n", str );
+				printf( "BPyMenus error: couldn't create entry for %s.\n", pathstr );
 			fclose( fp );
 			closedir( dir );
 			return -2;
@@ -724,14 +730,14 @@ static int bpymenu_CreateFromDir( char *dirname, int whichdir )
 		while( fgets( line, 100, fp ) ) {
 			res = sscanf( line, "%[^']'%[^'\r\n]'%s\n", w, submenu,
 				      subarg );
-			if( ( res != 3 ) || ( w[0] != 's' && w[0] != 'S' ) )
+			if( ( res != 3 ) || !strstr( w, "Submenu" ) )
 				break;
 			bpymenu_AddSubEntry( pymenu, submenu, subarg );
 		}
 
 		/* the (optional) tooltip: */
 		res = sscanf( line, "%[^']'%[^'\r\n]'\n", w, tooltip );
-		if( ( res == 2 ) && ( w[0] == 't' || w[0] == 'T' ) ) {
+		if( ( res == 2 ) && (!strstr( w, "Tooltip") || !strstr( w, "Tip" ))) {
 			bpymenu_set_tooltip( pymenu, tooltip );
 		}
 
diff --git a/source/blender/python/api2_2x/Effect.c b/source/blender/python/api2_2x/Effect.c
index 388f93db0b9..2e3e65e2c77 100644
--- a/source/blender/python/api2_2x/Effect.c
+++ b/source/blender/python/api2_2x/Effect.c
@@ -133,41 +133,74 @@ PyObject *M_Effect_Get( PyObject * self, PyObject * args )
 {
 	/*arguments : string object name
 	   int : position of effect in the obj's effect list  */
-	char *name = 0;
+	char *name = NULL;
 	Object *object_iter;
 	Effect *eff;
 	BPy_Effect *wanted_eff;
-	int num, i;
+	int num = -1, i;
+
 	if( !PyArg_ParseTuple( args, "|si", &name, &num ) )
 		return ( EXPP_ReturnPyObjError( PyExc_AttributeError,
 						"expected string int argument" ) );
+
 	object_iter = G.main->object.first;
+
 	if( !object_iter )
 		return ( EXPP_ReturnPyObjError( PyExc_AttributeError,
 						"Scene contains no object" ) );
-	if( name ) {
+
+	if( name ) { /* (name, num = -1) - try to find the given object */
+
 		while( object_iter ) {
-			if( strcmp( name, object_iter->id.name + 2 ) ) {
-				object_iter = object_iter->id.next;
-				continue;
-			}
 
+			if( !strcmp( name, object_iter->id.name + 2 ) ) {
 
-			if( object_iter->effect.first != NULL ) {
-				eff = object_iter->effect.first;
-				for( i = 0; i < num; i++ )
-					eff = eff->next;
-				wanted_eff =
-					( BPy_Effect * )
-					PyObject_NEW( BPy_Effect,
-						      &Effect_Type );
-				wanted_eff->effect = eff;
-				return ( PyObject * ) wanted_eff;
+				eff = object_iter->effect.first; /*can be NULL: None will be returned*/
+
+				if (num >= 0) { /* return effect in given num position if available */
+
+					for( i = 0; i < num; i++ ) {
+						if (!eff) break;
+						eff = eff->next;
+					}
+
+					if (eff) {
+						wanted_eff = (BPy_Effect *)PyObject_NEW(BPy_Effect, &Effect_Type);
+						wanted_eff->effect = eff;
+						return ( PyObject * ) wanted_eff;
+					} else { /* didn't find any effect in the given position */
+						Py_INCREF(Py_None);
+						return Py_None;
+					}
+				}
+
+				else {/*return a list with all effects linked to the given object*/
+							/* this was pointed by Stephen Swaney */
+					PyObject *effectlist = PyList_New( 0 );
+
+					while (eff) {
+						BPy_Effect *found_eff = (BPy_Effect *)PyObject_NEW(BPy_Effect,
+							&Effect_Type);
+						found_eff->effect = eff;
+						PyList_Append( effectlist, ( PyObject * ) found_eff );
+						Py_DECREF((PyObject *)found_eff); /* PyList_Append incref'ed it */
+						eff = eff->next;
+					}
+					return effectlist;
+				}
 			}
+			
 			object_iter = object_iter->id.next;
 		}
-	} else {
+
+		if (!object_iter)
+			return EXPP_ReturnPyObjError (PyExc_AttributeError,
+				"no such object");
+	}
+	
+	else { /* () - return a list with all effects currently in Blender */
 		PyObject *effectlist = PyList_New( 0 );
+
 		while( object_iter ) {
 			if( object_iter->effect.first != NULL ) {
 				eff = object_iter->effect.first;
@@ -180,6 +213,7 @@ PyObject *M_Effect_Get( PyObject * self, PyObject * args )
 					PyList_Append( effectlist,
 						       ( PyObject * )
 						       found_eff );
+					Py_DECREF((PyObject *)found_eff);
 					eff = eff->next;
 				}
 			}
diff --git a/source/blender/python/api2_2x/Object.c b/source/blender/python/api2_2x/Object.c
index 6311f2be933..e9048ffad3a 100644
--- a/source/blender/python/api2_2x/Object.c
+++ b/source/blender/python/api2_2x/Object.c
@@ -197,7 +197,7 @@ hierarchy (faster)"},
 if i is nonzero, empty slots are not ignored: they are returned as None's."},
 	{"getMatrix", ( PyCFunction ) Object_getMatrix, METH_VARARGS,
 	 "(str = 'worldspace') - Returns the object matrix.\n\
-(str = 'localspace') - the wanted matrix: worldspace (default), localspace\n\
+(str = 'worldspace') - the wanted matrix: worldspace (default), localspace\n\
 or old_worldspace.\n\
 \n\
 'old_worldspace' was the only behavior before Blender 2.34.  With it the\n\
@@ -957,7 +957,7 @@ static PyObject *Object_getMaterials( BPy_Object * self, PyObject * args )
 static PyObject *Object_getMatrix( BPy_Object * self, PyObject * args )
 {
 	PyObject *matrix;
-	char *space = "worldspace";	/* default to local */
+	char *space = "worldspace";	/* default to world */
 
 	if( !PyArg_ParseTuple( args, "|s", &space ) ) {
 		return ( EXPP_ReturnPyObjError( PyExc_AttributeError,
diff --git a/source/blender/python/api2_2x/Window.c b/source/blender/python/api2_2x/Window.c
index 067bfc8d33a..1053c29e930 100644
--- a/source/blender/python/api2_2x/Window.c
+++ b/source/blender/python/api2_2x/Window.c
@@ -971,7 +971,7 @@ static PyObject *M_Window_QAdd( PyObject * self, PyObject * args )
 static PyObject *M_Window_QHandle( PyObject * self, PyObject * args )
 {
 	short win;
-	ScrArea *sa = curarea;
+	ScrArea *sa = G.curscreen->areabase.first;
 	ScrArea *oldsa = NULL;
 
 	if( !PyArg_ParseTuple( args, "h", &win ) )
diff --git a/source/blender/python/api2_2x/doc/API_intro.py b/source/blender/python/api2_2x/doc/API_intro.py
index 8f684c79144..bceef653dca 100644
--- a/source/blender/python/api2_2x/doc/API_intro.py
+++ b/source/blender/python/api2_2x/doc/API_intro.py
@@ -18,7 +18,7 @@ The Blender Python API Reference
   - L{Camera}
   - L{Curve}
   - L{Draw}
-  - L{Effect}
+  - L{Effect} (*)
   - L{Image}
   - L{Ipo}
   - L{Lamp}
@@ -97,15 +97,16 @@ Registering scripts:
  The header should be like this one (all double and single apostrophes below
  are required)::
   #!BPY
-  \"\"\"
-  Name: 'Script Name'
-  Blender: 233
-  Group: 'Export'
-  Submenu: 'All' all
-  Submenu: 'Selected' sel
-  Submenu: 'Configure (gui)' gui
-  Tooltip: 'Export to some format.'
-  \"\"\"
+
+  # \"\"\"
+  # Name: 'Script Name'
+  # Blender: 233
+  # Group: 'Export'
+  # Submenu: 'All' all
+  # Submenu: 'Selected' sel
+  # Submenu: 'Configure (gui)' gui
+  # Tooltip: 'Export to some format.'
+  # \"\"\"
 
  where:
   - B{Name} is the string that will appear in the menu;
@@ -115,6 +116,15 @@ Registering scripts:
   - B{Submenu} adds optional submenus for further control;
   - B{Tooltip} is the (short) tooltip string for the menu entry.
 
+ note:
+  - all double and single apostrophes above are required;
+  - B{*NEW*}: you can "comment out" the header above, by starting lines with
+    '#', like we did.  This is not required (except for the first line, #!BPY,
+    of course), but this way the header won't conflict with Python tools that
+    you can use to generate documentation for your script code.  Just
+    remember to keep this header above any other line with triple
+    double-quotes (\"\"\") in your script.
+
  Submenu lines are not required, use them if you want to provide extra
  options.  To see which submenu the user chose, check the "__script__"
  dictionary in your code: __script__['arg'] has the defined keyword (the word
diff --git a/source/blender/python/api2_2x/doc/Effect.py b/source/blender/python/api2_2x/doc/Effect.py
index e25310cbced..b503523d3ec 100644
--- a/source/blender/python/api2_2x/doc/Effect.py
+++ b/source/blender/python/api2_2x/doc/Effect.py
@@ -3,6 +3,8 @@
 """
 The Blender.Effect submodule
 
+B{new}: now L{Get}('objname') (without specifying second paramenter: 'position') returns a list of all effects linked to object "objname".
+
 INTRODUCTION
 
 The module effect allows you to access all the data of an effect.
@@ -39,16 +41,17 @@ def New (type):
   @return: The created Effect.
   """
 
-def Get (objname,position):
+def Get (objname, position = None):
   """
   Get an Effect from Blender.
   @type objname: string
   @param objname: The name of object to which is linked the effect.
-  @type position: string
-  @param position: The position of the effect in the list of effects liked to the object.
+  @type position: int
+  @param position: The position of the effect in the list of effects linked to the object.
   @rtype: Blender Effect or a list of Blender Effects
-  @return: It depends on the 'objname,position' parameters:
-      - (objname,position): The Effect linked to the given object at the given position;
+  @return: It depends on the 'objname, position' parameters:
+      - (objname): A list with all Effects linked to the given object (new);
+      - (objname, position): The Effect linked to the given object at the given position;
       - ():     A list with all Effects in the current scene.
   """
 
-- 
GitLab