diff --git a/source/blender/python/BPY_menus.c b/source/blender/python/BPY_menus.c
index 5a2db4d1be2ca46841feab20a3fbab165660464a..6bae8fdf3e06c3ccdfbbbbce382398b6a512ffc0 100644
--- a/source/blender/python/BPY_menus.c
+++ b/source/blender/python/BPY_menus.c
@@ -25,7 +25,7 @@
  *
  * This is a new part of Blender.
  *
- * Contributor(s): Willian P. Germano
+ * Contributor(s): Willian P. Germano, Michael Reimpell
  *
  * ***** END GPL/BL DUAL LICENSE BLOCK *****
 */
@@ -583,171 +583,198 @@ void BPyMenu_PrintAllEntries( void )
 	}
 }
 
-/* bpymenu_GetDataFromDir:
- * this function scans the scripts dir looking for .py files with the
+/** Creates BPyMenu entries for scripts from directory.
+ *
+ * This function scans the scripts directory looking for .py files with the
  * right header and menu info, using that to fill the bpymenu structs.
  * whichdir defines if the script is in the default scripts dir or the
  * user defined one (U.pythondir: whichdir == 1).
  * Speed is important.
-*/
+ * <code>whichdir</code> defines if the script is in the default scripts dir
+ * or the user defined one (U.pythondir: <code>whichdir == 1</code>).
+ * <p>
+ * The first line of the script must be '<code>#!BPY</code>'.
+ * The header registration lines must appear between the first pair of
+ * '<code># \"\"\"</code>' and follow this order (the single-quotes are part of
+ * the format):
+ * <p>
+ * <code>
+ * # \"\"\"<br>
+ * # Name: 'script name for the menu'<br>
+ * # Blender: <code>short int</code> (minimal Blender version)<br>
+ * # Group: 'group name' (defines menu)<br>
+ * # Submenu: 'submenu name' related_1word_arg<br>
+ * # Tooltip: 'tooltip for the menu'<br>
+ * # \"\"\"<br>
+ * </code>
+ * <p>
+ * Notes:
+ * <ul>
+ * <li> There may be more than one submenu line, or none:
+ * Submenus and the tooltip are optional;
+ * <li> The Blender version is the same number reported by 
+ * <code>Blender.Get('version')</code> in BPython or <code>G.version</code>
+ * in C;
+ * <li> Line length must be less than 99.
+ * <li> Script headers as python documentation strings without the leading
+ * hash character (#) should no longer be used.
+ * </ul>
+ * 
+ * @param dirname Directory name to scan.
+ * @param whichdir Specifies the directory. 1 if user defined script directory, 
+ *                else default script directory.
+ * @return 0 on success.
+ */
+
 static int bpymenu_CreateFromDir( char *dirname, int whichdir )
 {
-	DIR *dir;
-	FILE *fp;
-	struct stat st;
-	struct dirent *dir_entry;
-	BPyMenu *pymenu;
-	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 ( 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. */
-
-	while( ( dir_entry = readdir( dir ) ) != NULL ) {
-		fname = dir_entry->d_name;
-		/* ignore anything starting with a dot */
-		if( fname[0] == '.' )
-			continue;	/* like . and .. */
-
-		/* also skip filenames whose extension isn't '.py' */
-		s = strstr( fname, ".py" );
-		if( !s || *( s + 3 ) != '\0' )
-			continue;
-
-		BLI_make_file_string( "/", pathstr, dirname, fname );
-
-		/* paranoia: check if this is really a file and not a disguised dir */
-		if( ( stat( pathstr, &st ) == -1 ) || !S_ISREG( st.st_mode ) )
-			continue;
-
-		fp = fopen( pathstr, "rb" );
-
-		if( !fp ) {
-			if( DEBUG )
-				printf( "BPyMenus error: couldn't open %s.\n",
-					pathstr );
-			continue;
-		}
-
-		/* finally, look for the start string '#!BPY', with
-		 * or w/o white space(s) between #! and BPY */
-		fgets( line, 100, fp );
-		if( line[0] != '#' || line[1] != '!' )
-			goto discard;
-
-		if( !strstr( line, "BPY" ) )
-			goto discard;
-
-		/* file passed the tests, look for the three double-quotes */
-		while( fgets( line, 100, fp ) ) {
-			if( strstr( line, "\"\"\"" )) {
-				res = 1;	/* found */
-				break;
+	DIR *dir;                /* directory stream object */
+	FILE *currentFile;       /* file stream object */ 
+	struct dirent *dirEntry; /* directory entry */
+	struct stat fileStatus;
+	char *fileExtension;
+	char fileName[FILE_MAXFILE + FILE_MAXDIR]; /* filename including path */
+	/* parser variables */
+	char line[100];
+	char head[100];
+	char middle[100];
+	char tail[100];
+	int nMatches;
+	int parserState;
+	/* script header variables */
+	char scriptName[100];
+	int scriptBlender;
+	int scriptGroup;
+	BPyMenu *scriptMenu = NULL;
+	/* other */
+	int scanDir = 1;
+	int returnValue = 0;
+	
+	/* open directory stream */
+	dir = opendir(dirname);
+	if (dir != NULL) {
+		/* directory stream opened */
+		while (((dirEntry = readdir(dir)) != NULL) && (scanDir == 1)) {
+			/* Check if filename does not start with a dot,
+			 * ends with '.py' and is a regular file. */
+			BLI_make_file_string("/", fileName, dirname, dirEntry->d_name);
+			fileExtension = strstr(dirEntry->d_name, ".py");
+			
+			if ((strncmp(dirEntry->d_name, ".", 1) != 0)
+				&& (fileExtension != NULL)
+				&& (*(fileExtension + 3) == '\0')
+				&& (stat(fileName, &fileStatus) == 0)
+				&& (S_ISREG(fileStatus.st_mode))) {
+				/* check file header */
+				currentFile = fopen(fileName, "rb");
+				if (currentFile != NULL) {
+					parserState = 1; /* state of parser, 0 to terminate */
+					while ((parserState != 0) && (fgets(line, 100, currentFile) != NULL)) {
+						switch (parserState) {
+							case 1: /* #!BPY */
+								if (strncmp(line, "#!BPY", 5) == 0) {
+									parserState++;
+								} else {
+									parserState = 0;
+								}
+								break;
+							case 2: /* # \"\"\" */
+								if ((strstr(line, "\"\"\""))) {
+									parserState++;
+								}
+								break;
+							case 3: /* # Name: 'script name for the menu' */
+								nMatches = sscanf(line, "%[^']'%[^']'%c", head, scriptName, tail);
+								if ((nMatches == 3) && (strstr(head, "Name:") != NULL)) {
+									parserState++;
+								} else {
+									if (DEBUG) {
+										fprintf(stderr, "BPyMenus error: Wrong 'Name' line: %s\n", fileName);
+									}
+									parserState = 0;
+								}
+								break;
+							case 4: /* # Blender: <short int> */
+								nMatches = sscanf(line, "%[^1234567890]%i%c", head, &scriptBlender, tail);
+								if (nMatches == 3) {
+									parserState++;
+								} else {
+									if (DEBUG) {
+										fprintf(stderr, "BPyMenus error: Wrong 'Blender' line: %s\n", fileName);
+									}
+									parserState = 0;
+								}
+								break;
+							case 5: /* # Group: 'group name' */
+								nMatches = sscanf(line, "%[^']'%[^']'%c", head, middle, tail);
+								if ((nMatches == 3) && (strstr(head, "Group:") != NULL)) {
+									scriptGroup = bpymenu_group_atoi(middle);
+									if (scriptGroup < 0) {
+										if (DEBUG) {
+											fprintf(stderr, "BPyMenus error: Unknown group \"%s\": %s\n", middle, fileName);
+										}
+										parserState = 0;
+									} else {
+										/* register script */
+										scriptMenu = bpymenu_AddEntry(scriptGroup, (short int) scriptBlender, scriptName,
+										                              dirEntry->d_name, whichdir, NULL);
+										if (scriptMenu == NULL) {
+											if (DEBUG) {
+												fprintf(stderr, "BPyMenus error: Couldn't create entry for: %s\n", fileName);
+											}
+											/* abort */
+											parserState = 0;
+											scanDir = 0;
+											returnValue = -2;
+										} else {
+											parserState++;
+										}
+									}
+								} else {
+									if (DEBUG) {
+										fprintf(stderr, "BPyMenus error: Wrong 'Group' line: %s\n", fileName);
+									}
+									parserState = 0;
+								}
+								break;
+							case 6: /* optional elements */
+								/* # Submenu: 'submenu name' related_1word_arg */
+								nMatches = sscanf(line, "%[^']'%[^']'%s\n", head, middle, tail);
+								if ((nMatches == 3) && (strstr(head, "Submenu:") != NULL)) {
+									bpymenu_AddSubEntry(scriptMenu, middle, tail);
+								} else {
+									/* # Tooltip: 'tooltip for the menu */
+									nMatches = sscanf(line, "%[^']'%[^']'%c", head, middle, tail);
+									if ((nMatches == 3)
+										&& ((strstr(head, "Tooltip:") != NULL) || (strstr(head, "Tip:") != NULL))) {
+										bpymenu_set_tooltip(scriptMenu, middle);
+									}
+									parserState = 0;
+								}
+								break;
+							default:
+								parserState = 0;
+								break;
+						}
+					}
+					/* close file stream */
+					fclose(currentFile);
+				} else {
+					/* open file failed */
+					if(DEBUG) {
+						fprintf(stderr, "BPyMenus error: Couldn't open %s.\n", dirEntry->d_name);
+					}
+				}
 			}
 		}
-
-		if( !res )
-			goto discard;
-
-		/* Now we're ready to get the registration info.  A little more structure
-		 * 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'
-		 * Blender: <short int> (minimal Blender version)
-		 * Group: 'group name' (defines menu)
-		 * Submenu: 'submenu name' related_1word_arg
-		 * Tooltip: 'tooltip for the menu'
-		 *
-		 * notes:
-		 * - there may be more than one submenu line, or none:
-		 * 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;
-		 * - 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 ) || !strstr(w, "Name") ) {
-			if( DEBUG )
-				printf( "BPyMenus error: wrong 'Name' line in %s.\n", pathstr );
-			goto discard;
-		}
-
-		/* minimal Blender version: */
-		res = fscanf( fp, "%s %d\n", w, &version );
-		if( ( res != 2 ) || !strstr(w, "Blender") ) {
-			if( DEBUG )
-				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 ) || !strstr(w, "Group" ) ) {
-			if( DEBUG )
-				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, pathstr );
-			goto discard;
-		}
-
-		pymenu = bpymenu_AddEntry( res, ( short ) version, name, fname,
-					   whichdir, NULL );
-		if( !pymenu ) {
-			if( DEBUG )
-				printf( "BPyMenus error: couldn't create entry for %s.\n", pathstr );
-			fclose( fp );
-			closedir( dir );
-			return -2;
-		}
-
-		/* the (optional) submenu(s): */
-		while( fgets( line, 100, fp ) ) {
-			res = sscanf( line, "%[^']'%[^'\r\n]'%s\n", w, submenu,
-				      subarg );
-			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 ) && (!strstr( w, "Tooltip") || !strstr( w, "Tip" ))) {
-			bpymenu_set_tooltip( pymenu, tooltip );
-		}
-
-	      discard:
-		fclose( fp );
-		continue;
+		/* close directory stream */
+		closedir(dir);
+	} else {
+		/* open directory stream failed */
+		fprintf(stderr, "opendir %s failed: %s\n", dirname, strerror(errno));
+		returnValue = -1;
 	}
-
-	closedir( dir );
-	return 0;
+	return returnValue;
 }
 
 static int bpymenu_GetStatMTime( char *name, int is_file, time_t * mtime )
diff --git a/source/blender/python/api2_2x/Blender.c b/source/blender/python/api2_2x/Blender.c
index d9b4151388d8b82e1aabd5cf2787c979e3f849d8..761fffabb50d2fec2c1c9f7f3ed13c6cf2d1bb3b 100644
--- a/source/blender/python/api2_2x/Blender.c
+++ b/source/blender/python/api2_2x/Blender.c
@@ -97,8 +97,10 @@ static char Blender_Get_doc[] = "(request) - Retrieve settings from Blender\n\
 	'staframe'	- Returns the start frame of the animation\n\
 	'endframe'	- Returns the end frame of the animation\n\
 	'filename'	- Returns the name of the last file read or written\n\
+	'homedir' - Returns Blender's home dir\n\
 	'datadir' - Returns the dir where scripts can save their data, if available\n\
 	'scriptsdir' - Returns the main dir where scripts are kept, if available\n\
+	'uscriptsdir' - Returns the user defined dir for scripts, if available\n\
 	'version'	- Returns the Blender version number";
 
 static char Blender_Redraw_doc[] = "() - Redraw all 3D windows";
@@ -217,6 +219,13 @@ static PyObject *Blender_Get( PyObject * self, PyObject * args )
 		if( StringEqual( str, "filename" ) ) {
 			return ( PyString_FromString( G.sce ) );
 		}
+		if( StringEqual( str, "homedir" ) ) {
+			if( BLI_exists( bpy_gethome() ))
+				return PyString_FromString( bpy_gethome() );
+			else
+				return EXPP_incr_ret( Py_None );
+		}
+
 		if( StringEqual( str, "datadir" ) ) {
 			char datadir[FILE_MAXDIR];
 			BLI_make_file_string( "/", datadir, bpy_gethome(  ),
@@ -235,6 +244,12 @@ static PyObject *Blender_Get( PyObject * self, PyObject * args )
 			else
 				return EXPP_incr_ret( Py_None );
 		}
+		if( StringEqual( str, "uscriptsdir" ) ) {
+			if( BLI_exists( U.pythondir ) )
+				return PyString_FromString( U.pythondir );
+			else
+				return EXPP_incr_ret( Py_None );
+		}
 		/* According to the old file (opy_blender.c), the following if
 		   statement is a quick hack and needs some clean up. */
 		if( StringEqual( str, "vrmloptions" ) ) {
diff --git a/source/blender/python/api2_2x/NMesh.c b/source/blender/python/api2_2x/NMesh.c
index 53bceb23cd8d96c2eb0f4801f865f19ce2e0f458..38d189e007feb083bbcea0a1344ab2ed135d5e57 100644
--- a/source/blender/python/api2_2x/NMesh.c
+++ b/source/blender/python/api2_2x/NMesh.c
@@ -1059,10 +1059,10 @@ static PyObject *NMesh_hasFaceUV( PyObject * self, PyObject * args )
 
 	switch ( flag ) {
 	case 0:
-		me->flags |= NMESH_HASFACEUV;
+		me->flags &= ~NMESH_HASFACEUV;
 		break;
 	case 1:
-		me->flags &= ~NMESH_HASFACEUV;
+		me->flags |= NMESH_HASFACEUV;
 		break;
 	default:
 		break;
diff --git a/source/blender/python/api2_2x/doc/Blender.py b/source/blender/python/api2_2x/doc/Blender.py
index c6bb41a3d6d74501a112438f26f58709cb0f40e8..a864566c4e571afb7c74179cccb2cb288cd6e3db 100644
--- a/source/blender/python/api2_2x/doc/Blender.py
+++ b/source/blender/python/api2_2x/doc/Blender.py
@@ -10,7 +10,7 @@
 """
 The main Blender module.
 
-B{New}: 'scriptsdir' parameter in L{Get}.
+B{New}: 'homedir', 'scriptsdir' and 'uscriptsdir' parameters in L{Get}.
 
 Blender
 =======
@@ -36,11 +36,15 @@ def Get (request):
       - 'staframe': the start frame of the animation
       - 'endframe': the end frame of the animation
       - 'filename': the name of the last file read or written
+      - 'homedir':  Blender's home dir
       - 'datadir' : the path to the dir where scripts should store and
             retrieve their data files, including saved configuration (can
             be None, if not found).
       - 'scriptsdir': the path to the main dir where scripts are stored
             (can be None, if not found).
+      - 'uscriptsdir': the path to the user defined dir for scripts, see
+            the paths tab in the User Preferences window in Blender
+            (can be None, if not found).
       - 'version' : the Blender version number
   @return: The requested data.
   """
diff --git a/source/blender/python/api2_2x/doc/Window.py b/source/blender/python/api2_2x/doc/Window.py
index 60f1396dbce845c4900bd83e6c60759eab9f428e..bde72cc815c9df9347b42d37ef21bdb4a6e7fb99 100644
--- a/source/blender/python/api2_2x/doc/Window.py
+++ b/source/blender/python/api2_2x/doc/Window.py
@@ -87,6 +87,13 @@ DrawProgressBar::
     - L: left mouse button
     - M: middle mouse button
     - R: right mouse button
+
+@warn: The event system in Blender needs a rewrite, though we don't know when that will happen.  Until then, event related functions here (L{QAdd}, L{QRead},
+L{QHandle}, etc.) can be used, but they are actually experimental and can be
+substituted for a better method when the rewrite happens.  In other words, use
+them at your own risk, because though they should work well and allow many
+interesting and powerful possibilities, they can be deprecated in some future
+version of Blender / Blender Python.
 """
 
 def Redraw (spacetype = '<Types.VIEW3D>'):
@@ -305,18 +312,23 @@ def QRead ():
    # let's catch all events and move the 3D Cursor when user presses
    # the left mouse button.
    from Blender import Draw, Window
+
+   v3d = Window.ScreenInfo(Window.Types.VIEW3D)
+   id = v3d[0]['id'] # get the (first) VIEW3D's id
+
    done = 0
+
    while not done:  # enter a 'get event' loop
      evt, val = Window.QRead() # catch next event
-     if evt in [Draw.ESCKEY, Draw.QKEY]: done = 1 # end loop
+     if evt in [Draw.MOUSEX, Draw.MOUSEY]:
+       continue # speeds things up, ignores mouse movement
+     elif evt in [Draw.ESCKEY, Draw.QKEY]: done = 1 # end loop
      elif evt == Draw.SPACEKEY:
        Draw.PupMenu("Hey!|What did you expect?")
      elif evt == Draw.Redraw: # catch redraw events to handle them
        Window.RedrawAll() # redraw all areas
-     elif evt == Draw.LEFTMOUSE and val: # left button pressed
-       v3d = Window.ScreenInfo(Window.Types.VIEW3D)
-       id = v3d[0]['id'] # get the (first) VIEW3D's id
-       Window.QAdd(id, evt, 1) # add the caught mouse event to it
+     elif evt == Draw.LEFTMOUSE: # left button pressed
+       Window.QAdd(id, evt, 1) # add the caught mouse event to our v3d
        # actually we should check if the event happened inside that area,
        # using Window.GetMouseCoords() and v3d[0]['vertices'] values.
        Window.QHandle(id) # process the event
@@ -328,7 +340,7 @@ def QRead ():
   @return: [event, val], where:
       - event: int - the key or mouse event (see L{Draw});
       - val: int - 1 for a key press, 0 for a release, new x or y coordinates
-          for mouse events.
+          for mouse movement events.
   """
 
 def QAdd (win, event, val, after = 0):