diff --git a/release/scripts/save_theme.py b/release/scripts/save_theme.py
new file mode 100644
index 0000000000000000000000000000000000000000..73c23087cec234af30150a0184ee069ccbf10608
--- /dev/null
+++ b/release/scripts/save_theme.py
@@ -0,0 +1,75 @@
+#!BPY
+
+"""
+Name: 'Save Current Theme'
+Blender: 234
+Group: 'Help'
+Tooltip: 'Save current theme as a bpython script'
+"""
+
+# $Id$
+#
+# --------------------------------------------------------------------------
+# save_theme version 2.34 Sep 20, 2004
+# Copyright (C) 2004: Willian P. Germano, wgermano _at_ ig.com.br
+# --------------------------------------------------------------------------
+# Released under the Blender Artistic License (BAL):
+#   http://download.blender.org/documentation/html/x21254.html
+#
+# The scripts generated by this script are put under Public Domain by
+# default, but you are free to edit the ones you generate with this script
+# and change their license to another one of your choice.
+# --------------------------------------------------------------------------
+
+import Blender
+from Blender.Window import Theme, FileSelector
+
+theme = Theme.Get()[0] # get current theme
+
+# default filename: theme's name + '_theme.py' in user's scripts dir:
+default_fname = Blender.Get("scriptsdir")
+default_fname = Blender.sys.join(default_fname, theme.name + '_theme.py')
+
+def write_theme(filename):
+	"Write the current theme as a bpython script"
+
+	if filename.find('.py', -3) <= 0: filename += '.py'
+
+	fout = file(filename, "w")
+
+	fout.write("""#!BPY
+
+\"\"\"
+Name: '%s'
+Blender: 234
+Group: 'Theme'
+Tooltip: 'Change current theme'
+\"\"\"
+
+# This script was automatically generated by the save_theme.py bpython script.
+# By default, these generated scripts are released as Public Domain, but you
+# are free to change the license of the scripts you generate with
+# save_theme.py before releasing them.
+
+import Blender
+from Blender.Window import Theme
+
+theme = Theme.New('%s')
+""" % (theme.name, theme.name))
+
+	for tsp in theme.get(): # 
+		command = "\n%s = theme.get('%s')" % (tsp, tsp)
+		fout.write(command + "\n")
+		exec(command)
+		exec("vars = dir(%s)" % tsp)
+		vars.remove('theme')
+
+		for var in vars:
+			v = "%s.%s" % (tsp, var)
+			exec("value = %s" % v)
+			fout.write("%s = %s\n" % (v, value))
+
+	fout.write('\nBlender.Redraw(-1)')
+	fout.close()
+
+FileSelector(write_theme, "Save Current Theme", default_fname)
diff --git a/source/blender/python/SConscript b/source/blender/python/SConscript
index 9e6d7a057fca7d2dd0288b64493d52c82f277920..0b7a62d44c05fa118ec78e82f91e8db055ddeb30 100644
--- a/source/blender/python/SConscript
+++ b/source/blender/python/SConscript
@@ -7,54 +7,56 @@ python_env = library_env.Copy ()
 
 source_files = ['BPY_interface.c',
                 'BPY_menus.c',
+                'api2_2x/Armature.c',
+                'api2_2x/BezTriple.c',
+                'api2_2x/BGL.c',
                 'api2_2x/Blender.c',
-                'api2_2x/Sys.c',
-                'api2_2x/Registry.c',
-                'api2_2x/Scene.c',
-                'api2_2x/Types.c',
-                'api2_2x/Object.c',
-                'api2_2x/NMesh.c',
-                'api2_2x/Material.c',
+                'api2_2x/Bone.c',
+                'api2_2x/Build.c',
                 'api2_2x/Camera.c',
-                'api2_2x/World.c',
-                'api2_2x/Lamp.c',
-                'api2_2x/Lattice.c',
-                'api2_2x/Library.c',
                 'api2_2x/CurNurb.c',
                 'api2_2x/Curve.c',
-                'api2_2x/Armature.c',
-                'api2_2x/Bone.c',
-                'api2_2x/Ipo.c',
+                'api2_2x/Draw.c',
+                'api2_2x/Effect.c',
+                'api2_2x/EXPP_interface.c',
                 'api2_2x/Ipocurve.c',
-                'api2_2x/BezTriple.c',
+                'api2_2x/Ipo.c',
+                'api2_2x/Lamp.c',
+                'api2_2x/Lattice.c',
+                'api2_2x/Library.c',
+                'api2_2x/MTex.c',
+                'api2_2x/Material.c',
+                'api2_2x/Mathutils.c',
                 'api2_2x/Metaball.c',
                 'api2_2x/NLA.c',
-                'api2_2x/Effect.c',
+                'api2_2x/Noise.c',
+                'api2_2x/NMesh.c',
+                'api2_2x/Object.c',
                 'api2_2x/Particle.c',
+                'api2_2x/Registry.c',
+                'api2_2x/Scene.c',
+                'api2_2x/Sound.c',
+                'api2_2x/Sys.c',
+                'api2_2x/Types.c',
                 'api2_2x/Wave.c',
-                'api2_2x/Build.c',
-                'api2_2x/Image.c',
                 'api2_2x/Window.c',
-                'api2_2x/Draw.c',
-                'api2_2x/BGL.c',
+                'api2_2x/World.c',
+                'api2_2x/Image.c',
                 'api2_2x/Text.c',
                 'api2_2x/Texture.c',
-                'api2_2x/MTex.c',
                 'api2_2x/Noise.c',
-                'api2_2x/vector.c',
+                'api2_2x/charRGBA.c',
                 'api2_2x/constant.c',
+                'api2_2x/euler.c',
+                'api2_2x/gen_utils.c',
                 'api2_2x/logic.c',
                 'api2_2x/matrix.c',
-                'api2_2x/euler.c',
                 'api2_2x/quat.c',
-                'api2_2x/Mathutils.c',
                 'api2_2x/rgbTuple.c',
-                'api2_2x/gen_utils.c',
                 'api2_2x/sceneRender.c',
                 'api2_2x/sceneRadio.c',
-                'api2_2x/EXPP_interface.c',
-                'api2_2x/Noise.c',
-                'api2_2x/Sound.c']
+                'api2_2x/vector.c',
+                'api2_2x/windowTheme.c']
 
 python_env.Append (CPPPATH = ['api2_2x',
                               '../blenkernel',
diff --git a/source/blender/python/api2_2x/Blender.c b/source/blender/python/api2_2x/Blender.c
index c4ca58ceed3a29dd257b45368a693187ce01993f..0cb848fc76b447d7db58097d95d372ef2ce0e911 100644
--- a/source/blender/python/api2_2x/Blender.c
+++ b/source/blender/python/api2_2x/Blender.c
@@ -99,6 +99,7 @@ static char Blender_Get_doc[] =
 	'endframe'	- Returns the end frame of the animation\n\
 	'filename'	- Returns the name of the last file read or written\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\
 	'version'	- Returns the Blender version number";
 
 static char Blender_Redraw_doc[] = "() - Redraw all 3D windows";
@@ -236,6 +237,13 @@ static PyObject *Blender_Get (PyObject *self, PyObject *args)
 			if (BLI_exists(datadir)) return PyString_FromString(datadir);
 			else return EXPP_incr_ret (Py_None);
 		}
+		if (StringEqual (str, "scriptsdir"))
+		{
+			char scriptsdir[FILE_MAXDIR];
+			BLI_make_file_string("/", scriptsdir, bpy_gethome(), "scripts/");
+			if (BLI_exists(scriptsdir)) return PyString_FromString(scriptsdir);
+			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/Image.c b/source/blender/python/api2_2x/Image.c
index 80ca8a38bd7fe2988f2d03bbfd21735770acca81..2ef745c8f9b7682e5d9ee2aa000bb58027817608 100644
--- a/source/blender/python/api2_2x/Image.c
+++ b/source/blender/python/api2_2x/Image.c
@@ -37,6 +37,7 @@
 #include <BIF_drawimage.h>
 #include <BLI_blenlib.h>
 #include <IMB_imbuf_types.h> /* for the IB_rect define */
+#include <BIF_gl.h>
 #include "gen_utils.h"
 
 #include "Image.h"
@@ -237,6 +238,7 @@ static PyObject *Image_setName(BPy_Image *self, PyObject *args);
 static PyObject *Image_setXRep(BPy_Image *self, PyObject *args);
 static PyObject *Image_setYRep(BPy_Image *self, PyObject *args);
 static PyObject *Image_reload(BPy_Image *self); /* by Campbell */
+static PyObject *Image_glLoad(BPy_Image *self);
 
 /*****************************************************************************/
 /* Python BPy_Image methods table:																					 */
@@ -259,6 +261,9 @@ static PyMethodDef BPy_Image_methods[] = {
 			"() - Return Image object's bind code value"},											
 	{"reload", (PyCFunction)Image_reload, METH_NOARGS,
 			"() - Reload the image from the filesystem"},
+	{"glLoad", (PyCFunction)Image_glLoad, METH_NOARGS,
+			"() - Load the image data in OpenGL texture memory.\n\
+	The bindcode (int) is returned."},
 	{"setName", (PyCFunction)Image_setName, METH_VARARGS,
 					"(str) - Change Image object name"},
 	{"setXRep", (PyCFunction)Image_setXRep, METH_VARARGS,
@@ -460,6 +465,37 @@ static PyObject *Image_reload(BPy_Image *self)
 	return Py_None;
 }
 
+static PyObject *Image_glLoad(BPy_Image *self)
+{
+	Image *img = self->image;
+	unsigned int *bind = &img->bindcode;
+
+	if (*bind == 0) {
+
+		if (!img->ibuf) /* if no image data is available */
+			load_image(img, IB_rect, "", 0); /* loading it */
+
+		if (!img->ibuf) /* didn't work */
+			return EXPP_ReturnPyObjError (PyExc_RuntimeError,
+				"couldn't load image data in Blender");
+
+		glGenTextures(1, (GLuint *)bind);
+		glBindTexture(GL_TEXTURE_2D, *bind);
+
+		gluBuild2DMipmaps(GL_TEXTURE_2D, GL_RGBA, img->ibuf->x, img->ibuf->y,
+			GL_RGBA, GL_UNSIGNED_BYTE, img->ibuf->rect);
+		glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER,
+			GL_LINEAR_MIPMAP_NEAREST);
+		glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
+		glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
+
+		glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, img->ibuf->x, img->ibuf->y, 0,
+			GL_RGBA, GL_UNSIGNED_BYTE, img->ibuf->rect);
+	}
+
+	return PyLong_FromUnsignedLong (img->bindcode);
+}
+
 static PyObject *Image_setName(BPy_Image *self, PyObject *args)
 {
 	char *name;
diff --git a/source/blender/python/api2_2x/Object.c b/source/blender/python/api2_2x/Object.c
index 7ba96b91458f91c8fe0d4dac84f832b3e14d7837..23153f51731b47586fb19b2de32724b73dc25f1c 100644
--- a/source/blender/python/api2_2x/Object.c
+++ b/source/blender/python/api2_2x/Object.c
@@ -188,7 +188,9 @@ hierarchy (faster)"},
 	"(i = 0) - Returns list of materials assigned to the object.\n\
 if i is nonzero, empty slots are not ignored: they are returned as None's."},
   {"getMatrix", (PyCFunction)Object_getMatrix, METH_VARARGS,
-	"Returns the object matrix - worlspace or localspace (default)"},
+	"(str = 'localspace') - Returns the object matrix.\n\
+(str = 'localspace') - the wanted matrix: worldspace, localspace (default)\n\
+or oldlocal (not updated, it was the only choice before Blender 2.34)."},
   {"getName", (PyCFunction)Object_getName, METH_NOARGS,
 	"Returns the name of the object"},
   {"getParent", (PyCFunction)Object_getParent, METH_NOARGS,
@@ -947,13 +949,18 @@ static PyObject *Object_getMatrix (BPy_Object *self, PyObject *args)
 	matrix = newMatrixObject(NULL, 4, 4);
 
 	if (BLI_streq(space, "worldspace")){  	/* Worldspace matrix */
+		disable_where_script(1);
 		where_is_object(self->object);
+		disable_where_script(0);
 		Mat4CpyMat4(*((MatrixObject*)matrix)->matrix, self->object->obmat);
 	} else if (BLI_streq(space, "localspace")) { /* Localspace matrix*/
 		object_to_mat4(self->object, *((MatrixObject*)matrix)->matrix);
+	} else if (BLI_streq(space, "oldlocal")) { /* old behavior, prior to 2.34 */
+		Mat4CpyMat4(*((MatrixObject *)matrix)->matrix, self->object->obmat);
 	} else {
 		return (EXPP_ReturnPyObjError (PyExc_RuntimeError, 
-			"correct spaces are 'worldspace' and 'localspace', none defaults to 'localspace'"));
+			"wrong parameter, expected nothing or either 'localspace' (default),\n\
+'worldspace' or 'oldlocal'"));
 	}
 	return matrix;
 }
diff --git a/source/blender/python/api2_2x/Window.c b/source/blender/python/api2_2x/Window.c
index 4dd0d2881e095c1ad4bf9610c576ad236d6c9d9d..90ac7ecec41576d91dff8ceeb588083c615f3ecb 100644
--- a/source/blender/python/api2_2x/Window.c
+++ b/source/blender/python/api2_2x/Window.c
@@ -1180,10 +1180,13 @@ static PyObject *M_Window_GetScreenInfo(PyObject *self, PyObject *args,
 /*****************************************************************************/
 PyObject *Window_Init (void)
 {
-	PyObject	*submodule, *Types, *Qual;
+	PyObject	*submodule, *Types, *Qual, *dict;
 
 	submodule = Py_InitModule3("Blender.Window", M_Window_methods, M_Window_doc);
 
+	dict = PyModule_GetDict(submodule);
+	if (dict) PyDict_SetItemString(dict, "Theme", Theme_Init());
+
 	Types = M_constant_New();
 	Qual = M_constant_New();
 
diff --git a/source/blender/python/api2_2x/charRGBA.c b/source/blender/python/api2_2x/charRGBA.c
new file mode 100644
index 0000000000000000000000000000000000000000..032df56920ce81aaaedb104c31c01d0ecfdfef0d
--- /dev/null
+++ b/source/blender/python/api2_2x/charRGBA.c
@@ -0,0 +1,398 @@
+/* 
+ * $Id$
+ *
+ * ***** BEGIN GPL/BL DUAL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version. The Blender
+ * Foundation also sells licenses for use in proprietary software under
+ * the Blender License.  See http://www.blender.org/BL/ for information
+ * about this.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA	02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
+ * All rights reserved.
+ *
+ * This is a new part of Blender.
+ *
+ * Contributor(s): Willian P. Germano
+ *
+ * ***** END GPL/BL DUAL LICENSE BLOCK *****
+*/
+
+#include "charRGBA.h"
+
+/* This file is heavily based on the old bpython Constant object code in
+	 Blender */
+
+/*****************************************************************************/
+/* Python charRGBA_Type callback function prototypes:												 */
+/*****************************************************************************/
+static void charRGBA_dealloc (BPy_charRGBA *self);
+static PyObject *charRGBA_getAttr (BPy_charRGBA *self, char *name);
+static int charRGBA_setAttr (BPy_charRGBA *self, char *name, PyObject *v);
+static PyObject *charRGBA_repr (BPy_charRGBA *self);
+
+static int charRGBALength(BPy_charRGBA *self);
+
+static PyObject *charRGBASubscript(BPy_charRGBA *self, PyObject *key);
+static int charRGBAAssSubscript(BPy_charRGBA *self, PyObject *who,
+	PyObject *cares);
+
+static PyObject *charRGBAItem(BPy_charRGBA *self, int i);
+static int charRGBAAssItem(BPy_charRGBA *self, int i, PyObject *ob);
+static PyObject *charRGBASlice(BPy_charRGBA *self, int begin, int end);
+static int charRGBAAssSlice(BPy_charRGBA *self, int begin, int end,
+	PyObject *seq);
+
+/*****************************************************************************/
+/* Python charRGBA_Type Mapping Methods table:															 */
+/*****************************************************************************/
+static PyMappingMethods charRGBAAsMapping =
+{
+	(inquiry)charRGBALength,						 /* mp_length				 */
+	(binaryfunc)charRGBASubscript,			 /* mp_subscript		 */
+	(objobjargproc)charRGBAAssSubscript, /* mp_ass_subscript */
+};
+
+/*****************************************************************************/
+/* Python charRGBA_Type Sequence Methods table:															 */
+/*****************************************************************************/
+static PySequenceMethods charRGBAAsSequence =
+{
+	(inquiry)			charRGBALength, /* sq_length */
+	(binaryfunc)		0, /* sq_concat */
+	(intargfunc)		0, /* sq_repeat */
+	(intargfunc)		charRGBAItem, /* sq_item */
+	(intintargfunc)		charRGBASlice, /* sq_slice */
+	(intobjargproc)		charRGBAAssItem, /* sq_ass_item */
+	(intintobjargproc)	charRGBAAssSlice, /* sq_ass_slice	*/
+};
+
+/*****************************************************************************/
+/* Python charRGBA_Type structure definition:																 */
+/*****************************************************************************/
+PyTypeObject charRGBA_Type =
+{
+	PyObject_HEAD_INIT(NULL)
+	0, /* ob_size */
+	"charRGBA", /* tp_name */
+	sizeof (BPy_charRGBA), /* tp_basicsize */
+	0, /* tp_itemsize */
+	/* methods */
+	(destructor)charRGBA_dealloc, /* tp_dealloc */
+	0, /* tp_print */
+	(getattrfunc)charRGBA_getAttr, /* tp_getattr */
+	(setattrfunc)charRGBA_setAttr, /* tp_setattr */
+	0, /* tp_compare */
+	(reprfunc)charRGBA_repr, /* tp_repr */
+	0, /* tp_as_number */
+	&charRGBAAsSequence, /* tp_as_sequence */
+	&charRGBAAsMapping, /* tp_as_mapping */
+	0, /* tp_as_hash */
+	0,0,0,0,0,0,
+	0, /* tp_doc */ 
+	0,0,0,0,0,0,
+	0, /* tp_methods */
+	0, /* tp_members */
+};
+
+/*****************************************************************************/
+/* Function:							charRGBA_New																			 */
+/*****************************************************************************/
+PyObject *charRGBA_New(char *rgba)
+{
+	BPy_charRGBA *charRGBA;
+
+	charRGBA_Type.ob_type = &PyType_Type;
+
+	charRGBA = (BPy_charRGBA *)PyObject_NEW(BPy_charRGBA, &charRGBA_Type);
+
+	if (charRGBA == NULL)
+		return EXPP_ReturnPyObjError (PyExc_MemoryError,
+			"couldn't create charRGBA object");
+
+	/* rgba is a pointer to the first item of a char[4] array */
+	charRGBA->rgba[0] = &rgba[0];
+	charRGBA->rgba[1] = &rgba[1];
+	charRGBA->rgba[2] = &rgba[2];
+	charRGBA->rgba[3] = &rgba[3];
+
+	return (PyObject *)charRGBA;
+}
+
+/*****************************************************************************/
+/* Functions:			 charRGBA_getCol and charRGBA_setCol											 */
+/* Description:		 These functions get/set rgba color triplet values.	The		 */
+/*								 get function returns a tuple, the set one accepts three	 */
+/*								 chars (separated or in a tuple) as arguments.						*/
+/*****************************************************************************/
+PyObject *charRGBA_getCol (BPy_charRGBA *self)
+{
+	PyObject *list = PyList_New (4);
+
+	if (!list) return EXPP_ReturnPyObjError (PyExc_MemoryError,
+		"couldn't create PyList");
+
+	PyList_SET_ITEM (list, 0, Py_BuildValue ("b", *(self->rgba[0]) ));
+	PyList_SET_ITEM (list, 1, Py_BuildValue ("b", *(self->rgba[1]) ));
+	PyList_SET_ITEM (list, 2, Py_BuildValue ("b", *(self->rgba[2]) ));
+	PyList_SET_ITEM (list, 3, Py_BuildValue ("b", *(self->rgba[3]) ));
+
+	return list;
+}
+
+PyObject *charRGBA_setCol (BPy_charRGBA *self, PyObject *args)
+{
+	int ok;
+	char r = 0, g = 0, b = 0, a = 0;
+
+	if (PyObject_Length (args) == 4)
+		ok = PyArg_ParseTuple (args, "bbbb", &r, &g, &b, &a);
+
+	else ok = PyArg_ParseTuple (args, "|(bbbb)", &r, &g, &b, &a);
+
+	if (!ok) 
+		return EXPP_ReturnPyObjError (PyExc_TypeError,
+			"expected 1-byte ints [b,b,b,b] or b,b,b,b as arguments (or nothing)");
+
+	*(self->rgba[0]) = EXPP_ClampInt (r, 0, 255);
+	*(self->rgba[1]) = EXPP_ClampInt (g, 0, 255);
+	*(self->rgba[2]) = EXPP_ClampInt (b, 0, 255);
+	*(self->rgba[3]) = EXPP_ClampInt (a, 0, 255);
+
+	return EXPP_incr_ret (Py_None);
+}
+
+/*****************************************************************************/
+/* Function:		charRGBA_dealloc																						 */
+/* Description: This is a callback function for the BPy_charRGBA type. It is */
+/*							the destructor function.																		 */
+/*****************************************************************************/
+static void charRGBA_dealloc (BPy_charRGBA *self)
+{
+	PyObject_DEL (self);
+}
+
+/*****************************************************************************/
+/* Function:		charRGBA_getAttr																						 */
+/* Description: This is a callback function for the BPy_charRGBA type. It is */
+/*							the function that accesses BPy_charRGBA member variables and */
+/*							methods.																										 */
+/*****************************************************************************/
+static PyObject* charRGBA_getAttr (BPy_charRGBA *self, char *name)
+{
+	int i;
+
+	if (strcmp(name, "__members__") == 0)
+		return Py_BuildValue("[s,s,s,s]", "R", "G", "B", "A");
+
+	else if (!strcmp(name, "R") || !strcmp(name, "r")) i = 0;
+	else if (!strcmp(name, "G") || !strcmp(name, "g")) i = 1;
+	else if (!strcmp(name, "B") || !strcmp(name, "b")) i = 2;
+	else if (!strcmp(name, "A") || !strcmp(name, "a")) i = 3;
+	else
+		return (EXPP_ReturnPyObjError (PyExc_AttributeError,
+			"attribute not found"));
+
+	return Py_BuildValue("b", *(self->rgba[i]));
+}
+
+/*****************************************************************************/
+/* Function:		charRGBA_setAttr																						 */
+/* Description: This is a callback function for the BPy_charRGBA type. It is */
+/*							the function that changes BPy_charRGBA member variables.		 */
+/*****************************************************************************/
+static int charRGBA_setAttr (BPy_charRGBA *self, char *name, PyObject *v)
+{
+	char value;
+
+	if (!PyArg_Parse (v, "b", &value))
+		return EXPP_ReturnIntError (PyExc_TypeError,
+			"expected char argument");
+
+	value = EXPP_ClampInt(value, 0, 255);
+
+	if (!strcmp(name, "R") || !strcmp(name, "r"))
+		*(self->rgba[0]) = value;
+
+	else if (!strcmp(name, "G") || !strcmp(name, "g"))
+		*(self->rgba[1]) = value;
+
+	else if (!strcmp(name, "B") || !strcmp(name, "b"))
+		*(self->rgba[2]) = value;
+
+	else if (!strcmp(name, "A") || !strcmp(name, "a"))
+		*(self->rgba[3]) = value;
+
+	else return (EXPP_ReturnIntError (PyExc_AttributeError,
+		"attribute not found"));
+
+	return 0;
+}
+
+/*****************************************************************************/
+/* Section:		 charRGBA as Mapping																					 */
+/*						 These functions provide code to access charRGBA objects as		 */
+/*						 mappings.																										 */
+/*****************************************************************************/
+static int charRGBALength(BPy_charRGBA *self)
+{
+	return 4;
+}
+
+static PyObject *charRGBASubscript(BPy_charRGBA *self, PyObject *key)
+{
+	char *name = NULL;
+	int i;
+
+	if (PyNumber_Check(key)) return charRGBAItem(self, (int)PyInt_AsLong(key));
+
+	if (!PyArg_ParseTuple(key, "s", &name))
+		return EXPP_ReturnPyObjError (PyExc_TypeError,
+			"expected int or string argument");
+
+	if (!strcmp(name, "R") || !strcmp(name, "r"))			 i = 0;
+	else if (!strcmp(name, "G") || !strcmp(name, "g")) i = 1; 
+	else if (!strcmp(name, "B") || !strcmp(name, "b")) i = 2; 
+	else if (!strcmp(name, "A") || !strcmp(name, "a")) i = 3; 
+	else
+		return EXPP_ReturnPyObjError (PyExc_AttributeError, name);
+
+	return Py_BuildValue("b", *(self->rgba[i]));
+}
+
+static int charRGBAAssSubscript(BPy_charRGBA *self, PyObject *key, PyObject *v)
+{
+	char *name = NULL;
+	int i;
+
+	if (!PyNumber_Check(v)) return EXPP_ReturnIntError(PyExc_TypeError,
+		"value to assign must be a number");
+
+	if (PyNumber_Check(key))
+		return charRGBAAssItem(self, (int)PyInt_AsLong(key), v);
+
+	if (!PyArg_Parse(key, "s", &name))
+		return EXPP_ReturnIntError (PyExc_TypeError,
+			"expected int or string argument");
+
+	if (!strcmp(name, "R") || !strcmp(name, "r"))			 i = 0;
+	else if (!strcmp(name, "G") || !strcmp(name, "g")) i = 1; 
+	else if (!strcmp(name, "B") || !strcmp(name, "b")) i = 2; 
+	else if (!strcmp(name, "A") || !strcmp(name, "a")) i = 3; 
+	else
+		return EXPP_ReturnIntError (PyExc_AttributeError, name);
+
+	*(self->rgba[i]) = EXPP_ClampInt(PyInt_AsLong(v), 0, 255);
+
+	return 0;
+}
+
+/*****************************************************************************/
+/* Section:		 charRGBA as Sequence																					 */
+/*						 These functions provide code to access charRGBA objects as		 */
+/*						 sequences.																										 */
+/*****************************************************************************/
+static PyObject *charRGBAItem(BPy_charRGBA *self, int i)
+{
+	if (i < 0 || i >= 4)
+		return EXPP_ReturnPyObjError (PyExc_IndexError,
+			"array index out of range");
+
+	return Py_BuildValue("b", *(self->rgba[i]));
+}
+
+static PyObject *charRGBASlice(BPy_charRGBA *self, int begin, int end)
+{
+	PyObject *list;
+	int count;
+
+	if (begin < 0) begin = 0;
+	if (end > 4) end = 4;
+	if (begin > end) begin = end;
+
+	list = PyList_New(end - begin);
+
+	for (count = begin; count < end; count++)
+		PyList_SetItem(list, count - begin,
+			PyInt_FromLong(*(self->rgba[count])));
+
+	return list;
+}
+
+static int charRGBAAssItem(BPy_charRGBA *self, int i, PyObject *ob)
+{
+	if (i < 0 || i >= 4)
+		return EXPP_ReturnIntError(PyExc_IndexError,
+			"array assignment index out of range");
+
+	if (!PyNumber_Check(ob))
+		return EXPP_ReturnIntError(PyExc_IndexError,
+			"color component must be a number");
+
+	*(self->rgba[i]) = EXPP_ClampInt(PyInt_AsLong(ob), 0, 255);
+
+	return 0;
+}
+
+static int charRGBAAssSlice(BPy_charRGBA *self, int begin, int end,
+	PyObject *seq)
+{
+	int count;
+	
+	if (begin < 0) begin = 0;
+	if (end > 4) end = 4;
+	if (begin > end) begin = end;
+
+	if (!PySequence_Check(seq))
+		return EXPP_ReturnIntError(PyExc_TypeError,
+			"illegal argument type for built-in operation");
+
+	if (PySequence_Length(seq) != (end - begin))
+		return EXPP_ReturnIntError(PyExc_TypeError,
+			"size mismatch in slice assignment");
+
+	for (count = begin; count < end; count++) {
+		char value;
+		PyObject *ob = PySequence_GetItem(seq, count);
+
+		if (!PyArg_Parse(ob, "b", &value)) {
+			Py_DECREF(ob);
+			return -1;
+		}
+
+		*(self->rgba[count]) = EXPP_ClampInt(value, 0, 255);
+
+		Py_DECREF(ob);
+	}
+
+	return 0;
+}
+
+/*****************************************************************************/
+/* Function:		charRGBA_repr																								 */
+/* Description: This is a callback function for the BPy_charRGBA type. It		 */
+/*							builds a meaninful string to represent charRGBA objects.		 */
+/*****************************************************************************/
+static PyObject *charRGBA_repr (BPy_charRGBA *self)
+{
+	char r, g, b, a;
+
+	r = *(self->rgba[0]);
+	g = *(self->rgba[1]);
+	b = *(self->rgba[2]);
+	a = *(self->rgba[3]);
+
+	return PyString_FromFormat("[%d, %d, %d, %d]", r, g, b, a);
+}
diff --git a/source/blender/python/api2_2x/charRGBA.h b/source/blender/python/api2_2x/charRGBA.h
new file mode 100644
index 0000000000000000000000000000000000000000..d6d39439721a2b9dc3ea5f343ddf6d7b8f5d8ddb
--- /dev/null
+++ b/source/blender/python/api2_2x/charRGBA.h
@@ -0,0 +1,60 @@
+/* 
+ * $Id$
+ *
+ * ***** BEGIN GPL/BL DUAL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version. The Blender
+ * Foundation also sells licenses for use in proprietary software under
+ * the Blender License.  See http://www.blender.org/BL/ for information
+ * about this.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
+ * All rights reserved.
+ *
+ * This is a new part of Blender.
+ *
+ * Contributor(s): Willian P. Germano
+ *
+ * ***** END GPL/BL DUAL LICENSE BLOCK *****
+*/
+
+#ifndef EXPP_charRGBA_H
+#define EXPP_charRGBA_H
+
+#include <Python.h>
+#include <stdio.h>
+
+#include "gen_utils.h"
+
+/* Objects of <type 'charRGBA'> are used inside other Blender Python
+ * objects, so this header file must contain only 'public' declarations */
+/* there's also rgbTuple, for rgb floats and a color obj in NMesh, messy! */
+
+/* Python BPy_charRGBA structure definition: */
+
+typedef struct {
+  PyObject_HEAD
+	char *rgba[4]; /* array of four pointers to chars */
+
+} BPy_charRGBA;
+
+/*****************************************************************************/
+/* Python API function prototypes for the charRGBA helper module.            */
+/*****************************************************************************/
+PyObject *charRGBA_New (char *rgba);
+PyObject *charRGBA_getCol (BPy_charRGBA *self);
+PyObject *charRGBA_setCol (BPy_charRGBA *self, PyObject *args);
+
+#endif /* EXPP_charRGBA_H */
diff --git a/source/blender/python/api2_2x/doc/API_intro.py b/source/blender/python/api2_2x/doc/API_intro.py
index 70ecd37b00d2286f7cf9b9fb20209b87d3480903..94f583211fc6b41c23c80b00cd21e102a16a673b 100644
--- a/source/blender/python/api2_2x/doc/API_intro.py
+++ b/source/blender/python/api2_2x/doc/API_intro.py
@@ -7,7 +7,7 @@ The Blender Python API Reference
  Top Module:
  -----------
 
-  - L{Blender}
+  - L{Blender} (*)
 
  Submodules:
  -----------
@@ -29,9 +29,9 @@ The Blender Python API Reference
   - L{Metaball}
   - L{NMesh}
   - L{Noise}
-  - L{Object}
+  - L{Object} (*)
   - L{Registry}
-  - L{Scene}
+  - L{Scene} (*)
      - L{Radio}
      - L{Render}
   - L{Text}
diff --git a/source/blender/python/api2_2x/doc/Blender.py b/source/blender/python/api2_2x/doc/Blender.py
index 73fe2baa288611db8000e498edb3f60f45ac5e2f..c6bb41a3d6d74501a112438f26f58709cb0f40e8 100644
--- a/source/blender/python/api2_2x/doc/Blender.py
+++ b/source/blender/python/api2_2x/doc/Blender.py
@@ -2,17 +2,16 @@
 
 # The module files in this folder are used to create the API documentation.
 # Doc system used: epydoc - http://epydoc.sf.net
-# command line:
-
+# pseudo command line (check the epy_docgen.sh file):
 # epydoc -o BPY_API_23x --url "http://www.blender.org" -t Blender.py \
 # -n "Blender" --no-private --no-frames Blender.py \
-# Types.py Scene.py Object.py NMesh.py Material.py Camera.py Lamp.py \
-# Armature.py Metaball.py Effect.py Curve.py Ipo.py World.py BGL.py Window.py \
-# Draw.py Image.py Text.py Lattice.py Texture.py Registry.py Sys.py Mathutils.py
+# Types.py Scene.py Object.py [ ... etc]
 
 """
 The main Blender module.
 
+B{New}: 'scriptsdir' parameter in L{Get}.
+
 Blender
 =======
 """
@@ -40,6 +39,8 @@ def Get (request):
       - '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).
       - 'version' : the Blender version number
   @return: The requested data.
   """
diff --git a/source/blender/python/api2_2x/doc/Object.py b/source/blender/python/api2_2x/doc/Object.py
index 29b6cd79200ae00b4afc52daab286f27d96e037b..07c674b9dbea57d14e317d2b20b18dfbf2369daf 100644
--- a/source/blender/python/api2_2x/doc/Object.py
+++ b/source/blender/python/api2_2x/doc/Object.py
@@ -3,7 +3,7 @@
 """
 The Blender.Object submodule
 
-B{New}: L{Object.makeTrack}, scriptLink methods: L{Object.getScriptLinks}, ...
+B{New}: 'oldlocal' parameter in L{Object.Object.getMatrix}. 
 
 Object
 ======
@@ -290,16 +290,17 @@ class Object:
   def getMatrix(space = 'localspace'):
     """
     Returns the object matrix.
-    Use getMatrix() or getMatrix('localspace') to get the matrix relative to the objects parent.
-    Somtimes the absolute matrix of the object is required (taking into account vertex parents, tracking and ipo's)
-    in this case use getMatrix('worldspace')
-    @type space: string. Values are:
-    @param space: possible values are:
-      - localspace (default)
-      - worldspace
+    @type space: string
+    @param space: The desired matrix:
+      - localspace (default): relative to the object's parent;
+      - worldspace: absolute, taking vertex parents, tracking and ipo's into
+          account;
+      - oldlocal: old behavior, prior to Blender 2.34, where eventual changes
+          made by the script itself were not taken into account until the
+          script finished executing.
     Returns the object matrix.
     @rtype: Py_Matrix
-    @return: a python matrix 4x4
+    @return: a python 4x4 matrix object
     """
 
   def getName():
diff --git a/source/blender/python/api2_2x/gen_utils.c b/source/blender/python/api2_2x/gen_utils.c
index b10b6e1d0bb64a7cb0b92c7615896dacc5b09f5f..4cbdbc90ea0f66158b73c511ebda9891d7d406c0 100644
--- a/source/blender/python/api2_2x/gen_utils.c
+++ b/source/blender/python/api2_2x/gen_utils.c
@@ -25,17 +25,18 @@
  *
  * This is a new part of Blender.
  *
- * Contributor(s): Michel Selten, Willian P. Germano
+ * Contributor(s): Michel Selten, Willian P. Germano, Alex Mole
  *
  * ***** END GPL/BL DUAL LICENSE BLOCK *****
 */
 
-#include "gen_utils.h"
-#include "constant.h"
-
+#include <strings.h> /*for strcasecmp */
 #include <DNA_text_types.h>
 #include <MEM_guardedalloc.h>
 
+#include "gen_utils.h"
+#include "constant.h"
+
 /*****************************************************************************/
 /* Description: This function clamps an int to the given interval						 */
 /*							[min, max].																									 */
@@ -205,6 +206,22 @@ int EXPP_map_getIntVal (const EXPP_map_pair *map, const char *sval, int *ival)
 		return 0;
 }
 
+/* same as above, but string case is ignored */
+int EXPP_map_case_getIntVal (const EXPP_map_pair *map, const char *sval,
+	int *ival)
+{
+		while (map->sval)
+		{
+				if (!strcasecmp(sval, map->sval))
+				{
+						*ival = map->ival;
+						return 1;
+				}
+				++map;
+		}
+		return 0;
+}
+
 /****************************************************************************/
 /* Description: searches through a map for a pair with a given name. If the */
 /*							pair is present, its ival is stored in *ival and nonzero is */
diff --git a/source/blender/python/api2_2x/gen_utils.h b/source/blender/python/api2_2x/gen_utils.h
index cb17d4bb05e672f9dd443b42a8dfb38c7cbc4c88..8ef41114ffbbddba1c52f5153b7f960fdfa53ef0 100644
--- a/source/blender/python/api2_2x/gen_utils.h
+++ b/source/blender/python/api2_2x/gen_utils.h
@@ -60,7 +60,7 @@ PyObject *PythonIncRef (PyObject *object);
 char * event_to_name (short event);
 
 float EXPP_ClampFloat (float value, float min, float max);
-int		EXPP_ClampInt (int value, int min, int max);
+int	EXPP_ClampInt (int value, int min, int max);
 
 PyObject *EXPP_incr_ret (PyObject *object);
 PyObject *EXPP_ReturnPyObjError (PyObject * type, char * error_msg);
@@ -71,17 +71,19 @@ PyObject *EXPP_tuple_repr(PyObject *self, int size);
 
 /* mapping utilities - see Texture.c for an example of how to use these */
 typedef struct {
-		const char *sval;
-		int ival;
+	const char *sval;
+	int ival;
 } EXPP_map_pair;
 
 /* maps must end with a pair that has NULL as sval */
 int EXPP_map_getIntVal (const EXPP_map_pair *map, 
-																				const char *sval, int *ival);
+	const char *sval, int *ival);
+int EXPP_map_case_getIntVal (const EXPP_map_pair *map, 
+	const char *sval, int *ival);
 int EXPP_map_getShortVal (const EXPP_map_pair *map, 
-																				const char *sval, short *ival);
+	const char *sval, short *ival);
 int EXPP_map_getStrVal (const EXPP_map_pair *map,
-																				int ival, const char **sval);
+	int ival, const char **sval);
 
 /* scriplinks-related: */
 PyObject *EXPP_getScriptLinks (ScriptLink *slink, PyObject *args, int is_scene);
diff --git a/source/blender/python/api2_2x/modules.h b/source/blender/python/api2_2x/modules.h
index f6caf46eb16b1f7585ee9e59377ca5ec974b9019..08abd05d8e0109dff2203006cc0c02a6c1756a85 100644
--- a/source/blender/python/api2_2x/modules.h
+++ b/source/blender/python/api2_2x/modules.h
@@ -204,5 +204,6 @@ PyObject * Mathutils_Init (void);
 PyObject * NLA_Init (void);
 PyObject * Library_Init (void);
 PyObject * Sound_Init (void);
+PyObject * Theme_Init (void); /* Window.Theme */
 
 #endif /* EXPP_modules_h */
diff --git a/source/blender/python/api2_2x/windowTheme.c b/source/blender/python/api2_2x/windowTheme.c
new file mode 100644
index 0000000000000000000000000000000000000000..56901520fb9ac1db0dd98baa490726c8ea936ee7
--- /dev/null
+++ b/source/blender/python/api2_2x/windowTheme.c
@@ -0,0 +1,706 @@
+/* 
+ * $Id$
+ *
+ * ***** BEGIN GPL/BL DUAL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version. The Blender
+ * Foundation also sells licenses for use in proprietary software under
+ * the Blender License.  See http://www.blender.org/BL/ for information
+ * about this.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA	02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
+ * All rights reserved.
+ *
+ * This is a new part of Blender.
+ *
+ * Contributor(s): Willian P. Germano
+ *
+ * ***** END GPL/BL DUAL LICENSE BLOCK *****
+*/
+
+#include <MEM_guardedalloc.h>
+#include <BLI_blenlib.h>
+#include <DNA_screen_types.h>
+#include "windowTheme.h"
+#include "charRGBA.h"
+#include "gen_utils.h"
+
+#define EXPP_THEME_VTX_SIZE_MIN 1
+#define EXPP_THEME_VTX_SIZE_MAX 10
+#define EXPP_THEME_DRAWTYPE_MIN 1
+#define EXPP_THEME_DRAWTYPE_MAX 4
+
+#define EXPP_THEME_NUMBEROFTHEMES 14
+static const EXPP_map_pair themes_map[] = {
+	{"ui", -1},
+	{"buts", SPACE_BUTS},
+	{"view3d", SPACE_VIEW3D},
+	{"file", SPACE_FILE},
+	{"ipo", SPACE_IPO},
+	{"info", SPACE_INFO},
+	{"sound", SPACE_SOUND},
+	{"action", SPACE_ACTION},
+	{"nla", SPACE_NLA},
+	{"seq", SPACE_SEQ},
+	{"image", SPACE_IMAGE},
+	{"imasel", SPACE_IMASEL},
+	{"text", SPACE_TEXT},
+	{"oops", SPACE_OOPS},
+	{NULL, 0}
+};
+					
+static PyObject *M_Theme_New (PyObject *self, PyObject *args);
+static PyObject *M_Theme_Get (PyObject *self, PyObject *args);
+
+static char M_Theme_doc[] = "The Blender Theme module\n\n\
+This module provides access to UI Theme data in Blender";
+
+static char M_Theme_New_doc[] =
+"Theme.New (name = 'New Theme'):\n\
+	Return a new Theme Data object with the given type and name.";
+
+static char M_Theme_Get_doc[] = "Theme.Get (name = None):\n\
+	Return the theme data with the given 'name', None if not found, or\n\
+	Return a list with all Theme Data objects if no argument was given.";
+
+/*****************************************************************************/
+/* Python method structure definition for Blender.Theme module:							*/
+/*****************************************************************************/
+struct PyMethodDef M_Theme_methods[] = {
+	{"New", M_Theme_New, METH_VARARGS, M_Theme_New_doc},
+	{"Get", M_Theme_Get, METH_VARARGS, M_Theme_Get_doc},
+	{NULL, NULL, 0, NULL}
+};
+
+static void ThemeSpace_dealloc (BPy_ThemeSpace *self);
+static int ThemeSpace_compare (BPy_ThemeSpace *a, BPy_ThemeSpace *b);
+static PyObject *ThemeSpace_repr (BPy_ThemeSpace *self);
+static PyObject *ThemeSpace_getAttr (BPy_ThemeSpace *self, char *name);
+static int ThemeSpace_setAttr (BPy_ThemeSpace *self, char *name, PyObject *val);
+
+static PyMethodDef BPy_ThemeSpace_methods[] = {
+	{NULL, NULL, 0, NULL}
+};
+
+PyTypeObject ThemeSpace_Type = {
+	PyObject_HEAD_INIT (NULL) 0,	/* ob_size */
+	"Blender Space Theme",		/* tp_name */
+	sizeof (BPy_Theme),		/* tp_basicsize */
+	0,				/* tp_itemsize */
+	/* methods */
+	(destructor) ThemeSpace_dealloc,	/* tp_dealloc */
+	0,				/* tp_print */
+	(getattrfunc) ThemeSpace_getAttr,	/* tp_getattr */
+	(setattrfunc) ThemeSpace_setAttr,	/* tp_setattr */
+	(cmpfunc) ThemeSpace_compare,	/* tp_compare */
+	(reprfunc) ThemeSpace_repr,	/* tp_repr */
+	0,				/* tp_as_number */
+	0,				/* tp_as_sequence */
+	0,				/* tp_as_mapping */
+	0,				/* tp_as_hash */
+	0, 0, 0, 0, 0, 0,
+	0,				/* tp_doc */
+	0, 0, 0, 0, 0, 0,
+	0, //BPy_ThemeSpace_methods,		/* tp_methods */
+	0,				/* tp_members */
+};
+
+static void ThemeSpace_dealloc (BPy_ThemeSpace *self)
+{
+	PyObject_DEL (self);
+}
+
+#define ELSEIF_TSP_RGBA(attr)\
+	else if (!strcmp(name, #attr))\
+		attrib = charRGBA_New(&tsp->attr[0]);
+
+/* Example: ELSEIF_TSP_RGBA(outline) becomes:
+ * else if (!strcmp(name, "back")
+ * 	attr = charRGBA_New(&tsp->back[0])
+ */
+
+static PyObject *ThemeSpace_getAttr (BPy_ThemeSpace *self, char *name)
+{
+	PyObject *attrib = Py_None;
+	ThemeSpace *tsp = self->tsp;
+
+	if (!strcmp (name, "theme"))
+		attrib = PyString_FromString (self->theme->name);
+	ELSEIF_TSP_RGBA(back)
+	ELSEIF_TSP_RGBA(text)
+	ELSEIF_TSP_RGBA(text_hi)
+	ELSEIF_TSP_RGBA(header)
+	ELSEIF_TSP_RGBA(panel)
+	ELSEIF_TSP_RGBA(shade1)
+	ELSEIF_TSP_RGBA(shade2)
+	ELSEIF_TSP_RGBA(hilite)
+	ELSEIF_TSP_RGBA(grid)
+	ELSEIF_TSP_RGBA(wire)
+	ELSEIF_TSP_RGBA(select)
+	ELSEIF_TSP_RGBA(active)
+	ELSEIF_TSP_RGBA(transform)
+	ELSEIF_TSP_RGBA(vertex)
+	ELSEIF_TSP_RGBA(vertex_select)
+	ELSEIF_TSP_RGBA(edge)
+	ELSEIF_TSP_RGBA(edge_select)
+	ELSEIF_TSP_RGBA(edge_seam)
+	ELSEIF_TSP_RGBA(edge_facesel)
+	ELSEIF_TSP_RGBA(face)
+	ELSEIF_TSP_RGBA(face_select)
+	ELSEIF_TSP_RGBA(normal)
+	else if (!strcmp (name, "vertex_size"))
+		attrib = Py_BuildValue("i", tsp->vertex_size);
+	else if (!strcmp (name, "__members__"))
+		attrib = Py_BuildValue("[ssssssssssssssssssssssss]", "theme",
+			"back", "text", "text_hi", "header", "panel", "shade1", "shade2",
+			"hilite", "grid", "wire", "select", "active", "transform",
+			"vertex", "vertex_select", "edge", "edge_select", "edge_seam",
+			"edge_facesel", "face", "face_select", "normal", "vertex_size");
+
+	if (attrib != Py_None) return attrib;
+
+	return Py_FindMethod(BPy_ThemeSpace_methods, (PyObject *)self, name);
+}
+
+static int ThemeSpace_setAttr (BPy_ThemeSpace *self, char *name,
+	PyObject *value)
+{
+	PyObject *attrib = NULL;
+	ThemeSpace *tsp = self->tsp;
+	int ret = -1;
+
+	if (!strcmp (name, "back"))
+		attrib = charRGBA_New(&tsp->back[0]);
+	ELSEIF_TSP_RGBA(back)
+	ELSEIF_TSP_RGBA(text)
+	ELSEIF_TSP_RGBA(text_hi)
+	ELSEIF_TSP_RGBA(header)
+	ELSEIF_TSP_RGBA(panel)
+	ELSEIF_TSP_RGBA(shade1)
+	ELSEIF_TSP_RGBA(shade2)
+	ELSEIF_TSP_RGBA(hilite)
+	ELSEIF_TSP_RGBA(grid)
+	ELSEIF_TSP_RGBA(wire)
+	ELSEIF_TSP_RGBA(select)
+	ELSEIF_TSP_RGBA(active)
+	ELSEIF_TSP_RGBA(transform)
+	ELSEIF_TSP_RGBA(vertex)
+	ELSEIF_TSP_RGBA(vertex_select)
+	ELSEIF_TSP_RGBA(edge)
+	ELSEIF_TSP_RGBA(edge_select)
+	ELSEIF_TSP_RGBA(edge_seam)
+	ELSEIF_TSP_RGBA(edge_facesel)
+	ELSEIF_TSP_RGBA(face)
+	ELSEIF_TSP_RGBA(face_select)
+	ELSEIF_TSP_RGBA(normal)
+	else if (!strcmp (name, "vertex_size")) {
+		int val;
+
+		if (!PyInt_Check(value))
+			return EXPP_ReturnIntError (PyExc_TypeError, "expected integer value");
+
+		val = (int)PyInt_AsLong(value);
+		tsp->vertex_size = EXPP_ClampInt(val,
+			EXPP_THEME_VTX_SIZE_MIN, EXPP_THEME_VTX_SIZE_MAX);
+		ret = 0;
+	}
+	else
+		return EXPP_ReturnIntError (PyExc_AttributeError, "attribute not found");
+
+	if (attrib) {
+		PyObject *pyret = NULL;
+		PyObject *valtuple = Py_BuildValue("(O)", value);
+
+		if (!valtuple)
+			return EXPP_ReturnIntError (PyExc_MemoryError, "couldn't create tuple!");
+
+		pyret = charRGBA_setCol((BPy_charRGBA *)attrib, valtuple);
+		Py_DECREF(valtuple);
+
+		if (pyret == Py_None) {
+			Py_DECREF (Py_None); /* was increfed by charRGBA_setCol */
+			ret = 0;
+		}
+
+		Py_DECREF(attrib); /* we're done with it */
+	}
+
+	return ret; /* 0 if all went well */
+}
+
+static int ThemeSpace_compare (BPy_ThemeSpace *a, BPy_ThemeSpace *b)
+{
+	ThemeSpace *pa = a->tsp, *pb = b->tsp;
+	return (pa == pb) ? 0 : -1;
+}
+
+static PyObject *ThemeSpace_repr (BPy_ThemeSpace *self)
+{
+	return PyString_FromFormat ("[Space theme from theme \"%s\"]",
+		self->theme->name);
+}
+
+static void ThemeUI_dealloc (BPy_ThemeUI *self);
+static int ThemeUI_compare (BPy_ThemeUI *a, BPy_ThemeUI *b);
+static PyObject *ThemeUI_repr (BPy_ThemeUI *self);
+static PyObject *ThemeUI_getAttr (BPy_ThemeUI *self, char *name);
+static int ThemeUI_setAttr (BPy_ThemeUI *self, char *name, PyObject *val);
+
+static PyMethodDef BPy_ThemeUI_methods[] = {
+	{NULL, NULL, 0, NULL}
+};
+
+PyTypeObject ThemeUI_Type = {
+	PyObject_HEAD_INIT (NULL) 0,	/* ob_size */
+	"Blender UI Theme",		/* tp_name */
+	sizeof (BPy_Theme),		/* tp_basicsize */
+	0,				/* tp_itemsize */
+	/* methods */
+	(destructor) ThemeUI_dealloc,	/* tp_dealloc */
+	0,				/* tp_print */
+	(getattrfunc) ThemeUI_getAttr,	/* tp_getattr */
+	(setattrfunc) ThemeUI_setAttr,	/* tp_setattr */
+	(cmpfunc) ThemeUI_compare,	/* tp_compare */
+	(reprfunc) ThemeUI_repr,	/* tp_repr */
+	0,				/* tp_as_number */
+	0,				/* tp_as_sequence */
+	0,				/* tp_as_mapping */
+	0,				/* tp_as_hash */
+	0, 0, 0, 0, 0, 0,
+	0,				/* tp_doc */
+	0, 0, 0, 0, 0, 0,
+	0, //BPy_ThemeUI_methods,		/* tp_methods */
+	0,				/* tp_members */
+};
+
+static void ThemeUI_dealloc (BPy_ThemeUI *self)
+{
+	PyObject_DEL (self);
+}
+
+#define ELSEIF_TUI_RGBA(attr)\
+	else if (!strcmp(name, #attr))\
+		attrib = charRGBA_New(&tui->attr[0]);
+
+/* Example: ELSEIF_TUI_RGBA(outline) becomes:
+ * else if (!strcmp(name, "outline")
+ * 	attr = charRGBA_New(&tui->outline[0])
+ */
+
+static PyObject *ThemeUI_getAttr (BPy_ThemeUI *self, char *name)
+{
+	PyObject *attrib = Py_None;
+	ThemeUI *tui = self->tui;
+
+	if (!strcmp (name, "theme"))
+		attrib = PyString_FromString (self->theme->name);
+	ELSEIF_TUI_RGBA(outline)
+	ELSEIF_TUI_RGBA(neutral)
+	ELSEIF_TUI_RGBA(action)
+	ELSEIF_TUI_RGBA(setting)
+	ELSEIF_TUI_RGBA(setting1)
+	ELSEIF_TUI_RGBA(setting2)
+	ELSEIF_TUI_RGBA(num)
+	ELSEIF_TUI_RGBA(textfield)
+	ELSEIF_TUI_RGBA(popup)
+	ELSEIF_TUI_RGBA(text)
+	ELSEIF_TUI_RGBA(text_hi)
+	ELSEIF_TUI_RGBA(menu_back)
+	ELSEIF_TUI_RGBA(menu_item)
+	ELSEIF_TUI_RGBA(menu_hilite)
+	ELSEIF_TUI_RGBA(menu_text)
+	ELSEIF_TUI_RGBA(menu_text_hi)
+	else if (!strcmp (name, "drawType"))
+		attrib = PyInt_FromLong((char)tui->but_drawtype);
+	else if (!strcmp (name, "__members__"))
+		attrib = Py_BuildValue("[ssssssssssssssssss]", "theme",
+			"outline", "neutral", "action", "setting", "setting1", "setting2",
+			"num", "textfield", "popup", "text", "text_hi", "menu_back", "menu_item",
+			"menu_hilite", "menu_text", "menu_text_hi", "drawType");
+
+	if (attrib != Py_None) return attrib;
+
+	return Py_FindMethod(BPy_ThemeUI_methods, (PyObject *)self, name);
+}
+
+static int ThemeUI_setAttr (BPy_ThemeUI *self, char *name, PyObject *value)
+{
+	PyObject *attrib = NULL;
+	ThemeUI *tui = self->tui;
+	int ret = -1;
+
+	if (!strcmp (name, "outline"))
+		attrib = charRGBA_New(&tui->outline[0]);
+	ELSEIF_TUI_RGBA(neutral)
+	ELSEIF_TUI_RGBA(action)
+	ELSEIF_TUI_RGBA(setting)
+	ELSEIF_TUI_RGBA(setting1)
+	ELSEIF_TUI_RGBA(setting2)
+	ELSEIF_TUI_RGBA(num)
+	ELSEIF_TUI_RGBA(textfield)
+	ELSEIF_TUI_RGBA(popup)
+	ELSEIF_TUI_RGBA(text)
+	ELSEIF_TUI_RGBA(text_hi)
+	ELSEIF_TUI_RGBA(menu_back)
+	ELSEIF_TUI_RGBA(menu_item)
+	ELSEIF_TUI_RGBA(menu_hilite)
+	ELSEIF_TUI_RGBA(menu_text)
+	ELSEIF_TUI_RGBA(menu_text_hi)
+	else if (!strcmp (name, "drawType")) {
+		int val;
+
+		if (!PyInt_Check(value))
+			return EXPP_ReturnIntError (PyExc_TypeError, "expected integer value");
+
+		val = (int)PyInt_AsLong(value);
+		tui->but_drawtype = EXPP_ClampInt(val,
+			EXPP_THEME_DRAWTYPE_MIN, EXPP_THEME_DRAWTYPE_MAX);
+		ret = 0;
+	}
+	else
+		return EXPP_ReturnIntError (PyExc_AttributeError, "attribute not found");
+
+	if (attrib) {
+		PyObject *pyret = NULL;
+		PyObject *valtuple = Py_BuildValue("(O)", value);
+
+		if (!valtuple)
+			return EXPP_ReturnIntError (PyExc_MemoryError, "couldn't create tuple!");
+
+		pyret = charRGBA_setCol((BPy_charRGBA *)attrib, valtuple);
+		Py_DECREF(valtuple);
+
+		if (pyret == Py_None) {
+			Py_DECREF (Py_None); /* was increfed by charRGBA_setCol */
+			ret = 0;
+		}
+
+		Py_DECREF(attrib); /* we're done with it */
+	}
+
+	return ret; /* 0 if all went well */
+}
+
+
+static int ThemeUI_compare (BPy_ThemeUI *a, BPy_ThemeUI *b)
+{
+	ThemeUI *pa = a->tui, *pb = b->tui;
+	return (pa == pb) ? 0 : -1;
+}
+
+static PyObject *ThemeUI_repr (BPy_ThemeUI *self)
+{
+	return PyString_FromFormat("[UI theme from theme \"%s\"]", self->theme->name);
+}
+
+static void Theme_dealloc (BPy_Theme *self);
+static int Theme_compare (BPy_Theme *a, BPy_Theme *b);
+static PyObject *Theme_getAttr (BPy_Theme *self, char *name);
+static PyObject *Theme_repr (BPy_Theme *self);
+
+static PyObject *Theme_get(BPy_Theme *self, PyObject *args);
+static PyObject *Theme_getName(BPy_Theme *self);
+static PyObject *Theme_setName(BPy_Theme *self, PyObject *args);
+
+static PyMethodDef BPy_Theme_methods[] = {
+	{"get", (PyCFunction) Theme_get, METH_VARARGS,
+		"(param) - Return UI or Space theme object.\n\
+(param) - the chosen theme object as an int or a string:\n\
+- () - default: UI;\n\
+- (i) - int: an entry from the Blender.Window.Types dictionary;\n\
+- (s) - string: 'UI' or a space name, like 'VIEW3D', etc."},
+	{"getName", (PyCFunction) Theme_getName, METH_NOARGS,
+		"() - Return Theme name"},
+	{"setName", (PyCFunction) Theme_setName, METH_VARARGS,
+		"(s) - Set Theme name"},
+	{NULL, NULL, 0, NULL}
+};
+
+PyTypeObject Theme_Type = {
+	PyObject_HEAD_INIT (NULL) 0,	/* ob_size */
+	"Blender Theme",		/* tp_name */
+	sizeof (BPy_Theme),		/* tp_basicsize */
+	0,				/* tp_itemsize */
+	/* methods */
+	(destructor) Theme_dealloc,	/* tp_dealloc */
+	0,				/* tp_print */
+	(getattrfunc) Theme_getAttr,	/* tp_getattr */
+	0,//(setattrfunc) Theme_setAttr,	/* tp_setattr */
+	(cmpfunc) Theme_compare,	/* tp_compare */
+	(reprfunc) Theme_repr,	/* tp_repr */
+	0,				/* tp_as_number */
+	0,				/* tp_as_sequence */
+	0,				/* tp_as_mapping */
+	0,				/* tp_as_hash */
+	0, 0, 0, 0, 0, 0,
+	0,				/* tp_doc */
+	0, 0, 0, 0, 0, 0,
+	0, //BPy_Theme_methods,		/* tp_methods */
+	0,				/* tp_members */
+};
+
+static PyObject *M_Theme_New (PyObject *self, PyObject *args)
+{
+	char *name = "New Theme";
+	BPy_Theme *pytheme = NULL, *base_pytheme = NULL;
+	bTheme *btheme = NULL, *newtheme = NULL;
+
+	if (!PyArg_ParseTuple (args, "|sO!", &name, &Theme_Type, &base_pytheme))
+		return EXPP_ReturnPyObjError (PyExc_AttributeError,
+			"expected nothing or a name and optional theme object as arguments");
+
+	if (base_pytheme) btheme = base_pytheme->theme;
+	if (!btheme) btheme = U.themes.first;
+
+	newtheme = MEM_callocN(sizeof(bTheme), "theme");
+
+	if (newtheme) pytheme = PyObject_New (BPy_Theme, &Theme_Type);
+	if (!pytheme) return EXPP_ReturnPyObjError (PyExc_RuntimeError,
+		"couldn't create Theme Data in Blender");
+
+	memcpy(newtheme, btheme, sizeof(bTheme));
+	BLI_addhead(&U.themes, newtheme);
+	BLI_strncpy(newtheme->name, name, 32);
+
+	pytheme->theme = newtheme;
+
+	return (PyObject *)pytheme;
+}
+
+static PyObject *M_Theme_Get (PyObject *self, PyObject *args)
+{
+	char *name = NULL;
+	bTheme *iter;
+	PyObject *ret;
+
+	if (!PyArg_ParseTuple (args, "|s", &name))
+		return EXPP_ReturnPyObjError (PyExc_TypeError,
+			"expected string argument (or nothing)");
+
+	iter = U.themes.first;
+
+	if (name) { /* (name) - return requested theme */
+		BPy_Theme *wanted = NULL;
+
+		while (iter) {
+			if (strcmp (name, iter->name) == 0) {
+				wanted = PyObject_New(BPy_Theme, &Theme_Type);
+				wanted->theme = iter;
+				break;
+			}
+			iter = iter->next;
+		}
+
+		if (!wanted) {
+			char emsg[64];
+			PyOS_snprintf (emsg, sizeof (emsg), "Theme \"%s\" not found", name);
+			return EXPP_ReturnPyObjError (PyExc_NameError, emsg);
+		}
+
+		ret = (PyObject *)wanted;
+	}
+
+	else { /* () - return list with all themes */
+		int index = 0;
+		PyObject *list = NULL;
+		BPy_Theme *pytheme = NULL;
+
+		list = PyList_New (BLI_countlist (&(U.themes)));
+
+		if (!list)
+			return EXPP_ReturnPyObjError(PyExc_MemoryError,"couldn't create PyList");
+
+		while (iter) {
+			pytheme = PyObject_New(BPy_Theme, &Theme_Type);
+			pytheme->theme = iter;
+
+			if (!pytheme)
+				return EXPP_ReturnPyObjError (PyExc_MemoryError,
+					"couldn't create Theme PyObject");
+
+			PyList_SET_ITEM (list, index, (PyObject *)pytheme);
+
+			iter = iter->next;
+			index++;
+		}
+
+		ret = list;
+	}
+
+	return ret;
+}
+
+static PyObject *Theme_get(BPy_Theme *self, PyObject *args)
+{
+	bTheme *btheme = self->theme;
+	ThemeUI *tui = NULL;
+	ThemeSpace *tsp = NULL;
+	PyObject *pyob = NULL;
+	BPy_ThemeUI *retUI = NULL;
+	BPy_ThemeSpace *retSpc = NULL;
+	int type;
+
+	if (!PyArg_ParseTuple(args, "|O", &pyob))
+		return EXPP_ReturnPyObjError (PyExc_TypeError,
+			"expected string or int argument or nothing");
+
+	if (!pyob) { /* (): return list with all names */
+		PyObject *ret = PyList_New(EXPP_THEME_NUMBEROFTHEMES);
+
+		if (!ret)
+			return EXPP_ReturnPyObjError (PyExc_MemoryError,
+				"couldn't create pylist!");
+
+		type = 0; /* using as a counter only */
+
+		while (type < EXPP_THEME_NUMBEROFTHEMES) {
+			PyList_SET_ITEM(ret, type, PyString_FromString(themes_map[type].sval));
+			type++;
+		}
+
+		return ret;
+	}
+
+	else if (PyInt_Check(pyob)) /* (int) */
+		type = (int)PyInt_AsLong(pyob);
+	else if (PyString_Check(pyob)) { /* (str) */
+		char *str = PyString_AsString(pyob);
+		if (!EXPP_map_case_getIntVal(themes_map, str, &type))
+			return EXPP_ReturnPyObjError (PyExc_AttributeError,
+				"unknown string argument");
+	}
+	else return EXPP_ReturnPyObjError (PyExc_TypeError,
+		"expected string or int argument or nothing");
+
+	switch (type) {
+		case -1: /* UI */
+			tui = &btheme->tui;
+			break;
+		case SPACE_BUTS:
+			tsp = &btheme->tbuts;
+			break;
+		case SPACE_VIEW3D:
+			tsp = &btheme->tv3d;
+			break;
+		case SPACE_FILE:
+			tsp = &btheme->tfile;
+			break;
+		case SPACE_IPO:
+			tsp = &btheme->tipo;
+			break;
+		case SPACE_INFO:
+			tsp = &btheme->tinfo;
+			break;
+		case SPACE_SOUND:
+			tsp = &btheme->tsnd;
+			break;
+		case SPACE_ACTION:
+			tsp = &btheme->tact;
+			break;
+		case SPACE_NLA:
+			tsp = &btheme->tnla;
+			break;
+		case SPACE_SEQ:
+			tsp = &btheme->tseq;
+			break;
+		case SPACE_IMAGE:
+			tsp = &btheme->tima;
+			break;
+		case SPACE_IMASEL:
+			tsp = &btheme->timasel;
+			break;
+		case SPACE_TEXT:
+			tsp = &btheme->text;
+			break;
+		case SPACE_OOPS:
+			tsp = &btheme->toops;
+			break;
+	}
+
+	if (tui) {
+		retUI = PyObject_New(BPy_ThemeUI, &ThemeUI_Type);
+		retUI->theme = btheme;
+		retUI->tui = tui;
+		return (PyObject *)retUI;
+	}
+	else if (tsp) {
+		retSpc = PyObject_New(BPy_ThemeSpace, &ThemeSpace_Type);
+		retSpc->theme = btheme;
+		retSpc->tsp = tsp;
+		return (PyObject *)retSpc;
+	}
+	else return EXPP_ReturnPyObjError (PyExc_AttributeError,
+		"invalid parameter");
+}
+
+static PyObject *Theme_getName(BPy_Theme *self)
+{
+	return PyString_FromString (self->theme->name);
+}
+
+static PyObject *Theme_setName(BPy_Theme *self, PyObject *args)
+{
+	char *name = NULL;
+
+	if (!PyArg_ParseTuple(args, "s", &name))
+		return EXPP_ReturnPyObjError (PyExc_TypeError,
+			"expected string argument");
+
+	BLI_strncpy(self->theme->name, name, 32);
+
+	return EXPP_incr_ret (Py_None);
+}
+
+PyObject *Theme_Init (void)
+{
+	PyObject *submodule;
+
+	Theme_Type.ob_type = &PyType_Type;
+
+	submodule = Py_InitModule3 ("Blender.Window.Theme",
+		M_Theme_methods, M_Theme_doc);
+
+	return submodule;
+}
+
+static void Theme_dealloc (BPy_Theme *self)
+{
+	PyObject_DEL (self);
+}
+
+static PyObject *Theme_getAttr (BPy_Theme *self, char *name)
+{
+	PyObject *attr = Py_None;
+
+	if (!strcmp (name, "name"))
+		attr = PyString_FromString (self->theme->name);
+	else if (!strcmp (name, "__members__"))
+		attr = Py_BuildValue("[s]", "name");
+
+	if (attr != Py_None) return attr;
+
+	return Py_FindMethod(BPy_Theme_methods, (PyObject *)self, name);
+}
+
+static int Theme_compare (BPy_Theme *a, BPy_Theme *b)
+{
+	bTheme *pa = a->theme, *pb = b->theme;
+	return (pa == pb) ? 0 : -1;
+}
+
+static PyObject *Theme_repr (BPy_Theme *self)
+{
+	return PyString_FromFormat ("[Theme \"%s\"]", self->theme->name);
+}
diff --git a/source/blender/python/api2_2x/windowTheme.h b/source/blender/python/api2_2x/windowTheme.h
new file mode 100644
index 0000000000000000000000000000000000000000..b3a654c9fb7aba02b525429d20c6662de0a7480f
--- /dev/null
+++ b/source/blender/python/api2_2x/windowTheme.h
@@ -0,0 +1,60 @@
+/* 
+ * $Id$
+ *
+ * ***** BEGIN GPL/BL DUAL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version. The Blender
+ * Foundation also sells licenses for use in proprietary software under
+ * the Blender License.  See http://www.blender.org/BL/ for information
+ * about this.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
+ * All rights reserved.
+ *
+ * This is a new part of Blender.
+ *
+ * Contributor(s): Willian P. Germano
+ *
+ * ***** END GPL/BL DUAL LICENSE BLOCK *****
+*/
+
+#ifndef EXPP_WINDOWTHEME_H
+#define EXPP_WINDOWTHEME_H
+
+#include <Python.h>
+#include <DNA_listBase.h>
+#include <DNA_userdef_types.h>
+
+typedef struct {
+	PyObject_HEAD
+	struct bTheme *theme;
+	struct ThemeUI *tui;
+
+} BPy_ThemeUI;
+
+typedef struct {
+	PyObject_HEAD
+	struct bTheme *theme;
+	struct ThemeSpace *tsp;
+
+} BPy_ThemeSpace;
+
+typedef struct {
+	PyObject_HEAD
+	struct bTheme *theme;
+
+} BPy_Theme;
+
+#endif /* EXPP_WINDOWTHEME_H */
diff --git a/source/blender/src/drawview.c b/source/blender/src/drawview.c
index 02dbd8565a965d63a541bd164f249426f2bc2ada..330c32330e503046529179c025ca72a164bb47b2 100644
--- a/source/blender/src/drawview.c
+++ b/source/blender/src/drawview.c
@@ -1933,7 +1933,12 @@ void drawview3dspace(ScrArea *sa, void *spacedata)
 		G.vd->flag |= V3D_NEEDBACKBUFDRAW;
 		addafterqueue(curarea->win, BACKBUFDRAW, 1);
 	}
-	
+
+	/* scene redraw script link */
+	if(G.scene->scriptlink.totscript && !during_script()) {
+		BPY_do_pyscript((ID *)G.scene, SCRIPT_REDRAW);
+	}
+
 }