From: Rudolf Polzer <rpolzer@grawp.(none)>
Date: Sun, 28 Mar 2010 17:14:14 +0000 (+0200)
Subject: changes from OSXnetradiant
X-Git-Tag: xonotic-v0.5.0~277^2~1
X-Git-Url: https://git.rm.cloudns.org/?a=commitdiff_plain;h=7dd945e36a13a7659bb14a2484e0ad5698280884;p=xonotic%2Fnetradiant.git

changes from OSXnetradiant
---

diff --git a/Makefile b/Makefile
index a6a09ac9..14cfac91 100644
--- a/Makefile
+++ b/Makefile
@@ -184,13 +184,16 @@ ifeq ($(OS),Darwin)
 	CFLAGS_COMMON += -fPIC
 	CXXFLAGS_COMMON += -fno-exceptions -fno-rtti
 	CPPFLAGS_COMMON += -I/sw/include -I/usr/X11R6/include
-	LDFLAGS_COMMON += -L/sw/lib -L/usr/lib -L/usr/X11R6/lib
+	LDFLAGS_COMMON += -L/sw/lib  -L/usr/X11R6/lib
+	#LDFLAGS_COMMON += -L/sw/lib -L/usr/lib -L/usr/X11R6/lib
 	LDFLAGS_DLL += -dynamiclib -ldl
 	EXE ?= ppc
+	MACLIBDIR ?= /sw/lib
 	A = a
 	DLL = dylib
 	MWINDOWS =
-
+	MACVERSION ?= 16
+	CPPFLAGS += -DMACVERSION="$(MACVERSION)"
 	# workaround for weird prints
 	ECHO_NOLF = /bin/echo -n
 
@@ -374,6 +377,7 @@ endif
 %.o: %.c $(if $(findstring $(DEPEND_ON_MAKEFILE),yes),$(wildcard Makefile*),)
 	$(CC) $< $(CFLAGS) $(CFLAGS_COMMON) $(CPPFLAGS_EXTRA) $(CPPFLAGS_COMMON) $(CPPFLAGS) $(TARGET_ARCH) -c -o $@
 
+
 $(INSTALLDIR)/q3map2.$(EXE): LIBS_EXTRA := $(LIBS_XML) $(LIBS_GLIB) $(LIBS_PNG) $(LIBS_ZLIB)
 $(INSTALLDIR)/q3map2.$(EXE): CPPFLAGS_EXTRA := $(CPPFLAGS_XML) $(CPPFLAGS_GLIB) $(CPPFLAGS_PNG) -Itools/quake3/common -Ilibs -Iinclude
 $(INSTALLDIR)/q3map2.$(EXE): \
@@ -969,6 +973,8 @@ install-data: binaries
 	$(ECHO) $(RADIANT_MINOR_VERSION) > $(INSTALLDIR)/RADIANT_MINOR
 	$(ECHO) $(RADIANT_MAJOR_VERSION) > $(INSTALLDIR)/RADIANT_MAJOR
 	$(CP_R) setup/data/tools/* $(INSTALLDIR)/
+	$(MKDIR) $(INSTALLDIR)/docs
+	$(CP_R) docs/* $(INSTALLDIR)/docs/
 	$(FIND) $(INSTALLDIR_BASE)/ -name .svn -exec $(RM_R) {} \; -prune
 
 .PHONY: install-dll
@@ -978,7 +984,7 @@ install-dll: binaries
 else
 ifeq ($(OS),Darwin)
 install-dll: binaries
-	CP="$(CP)" OTOOL="$(OTOOL)" INSTALLDIR="$(INSTALLDIR)" $(SH) install-dylibs.sh
+	EXE="$(EXE)" MACLIBDIR="$(MACLIBDIR)" CP="$(CP)" OTOOL="$(OTOOL)" INSTALLDIR="$(INSTALLDIR)" $(SH) install-dylibs.sh
 else
 install-dll: binaries
 	@$(ECHO) No DLL inclusion implemented for this target.
diff --git a/Makefile.conf b/Makefile.conf
index 0f5fa924..ef1d5bfc 100644
--- a/Makefile.conf
+++ b/Makefile.conf
@@ -1 +1,20 @@
-# empty Makefile.conf template
+# Makefile.conf template
+
+## OS X:
+BUILD=debug
+RADIANT_ABOUTMSG=OSX NetRadiant Custom build
+EXE=ub
+### Snow Leopard 16, Leopard 15, Tiger 14, Panther 13
+MACVERSION=16
+#
+## MacPorts:
+CPPFLAGS=-I/opt/local/include/ -I/usr/X11R6/include/ 
+LDFLAGS=-L/opt/local/lib -L/usr/X11R6/lib
+MACLIBDIR=/opt/local/lib
+
+## Fink
+## (-arch ppc can combined with -arch 386, I read somewhere. However does work fine like this on OSX 10.6) 
+# LDFLAGS=-arch i386
+# CFLAGS=-arch i386
+# TARGET_ARCH=-arch i386
+# MACLIBDIR=/sw/lib
diff --git a/contrib/bobtoolz/DBobView.cpp b/contrib/bobtoolz/DBobView.cpp
index 688dd7e4..aef76088 100644
--- a/contrib/bobtoolz/DBobView.cpp
+++ b/contrib/bobtoolz/DBobView.cpp
@@ -212,6 +212,7 @@ void DBobView::Begin(const char* trigger, const char *target, float multiplier,
 		globalErrorStream() << "Initialization Failure in DBobView::Begin";
 		delete this;
 	}
+	globalOutputStream() << "Initialization of Path Plotter succeeded.";
 }
 
 bool DBobView::UpdatePath()
@@ -243,35 +244,38 @@ void DBobView_setEntity(Entity& entity, float multiplier, int points, float varG
 			DEPair* target_ep = trigger.FindEPairByKey("target");
 			if(target_ep)
 			{
-        const scene::Path* entTarget = FindEntityFromTargetname(target_ep->value);
+				const scene::Path* entTarget = FindEntityFromTargetname(target_ep->value);
 				if(entTarget)
 				{
 					if(g_PathView)
 						delete g_PathView;
 					g_PathView = new DBobView;
 
-          Entity* target = Node_getEntity(entTarget->top());
-          if(target != 0)
-          {
-            if(!bNoUpdate)
-            {
-              g_PathView->trigger = &entity;
-              entity.attach(*g_PathView);
-              g_PathView->target = target;
-              target->attach(*g_PathView);
-            }
+					Entity* target = Node_getEntity(entTarget->top());
+					if(target != 0)
+					{
+						if(!bNoUpdate)
+						{
+							g_PathView->trigger = &entity;
+							entity.attach(*g_PathView);
+							g_PathView->target = target;
+							target->attach(*g_PathView);
+						}
 					  g_PathView->Begin(trigger_ep->value, target_ep->value, multiplier, points, varGravity, bNoUpdate, bShowExtra);
-          }
+					}
+					else
+						globalErrorStream() << "bobToolz PathPlotter: trigger_push ARGH\n";
 				}
 				else
-					DoMessageBox("trigger_push target could not be found.", "Error", eMB_OK);
+					globalErrorStream() << "bobToolz PathPlotter: trigger_push target could not be found..\n";
 			}
 			else
-				DoMessageBox("trigger_push has no target.", "Error", eMB_OK);
+				globalErrorStream() << "bobToolz PathPlotter: trigger_push has no target..\n";
 		}
 		else
-			DoMessageBox("You must select a 'trigger_push' entity.", "Error", eMB_OK);
+			globalErrorStream() << "bobToolz PathPlotter: You must select a 'trigger_push' entity..\n";
 	}	
 	else
-		DoMessageBox("Entity must have a targetname", "Error", eMB_OK);
+		globalErrorStream() << "bobToolz PathPlotter: Entity must have a targetname.\n";
+	return;
 }
\ No newline at end of file
diff --git a/contrib/bobtoolz/DPatch.cpp b/contrib/bobtoolz/DPatch.cpp
index 30bb5c60..3bfc6a34 100644
--- a/contrib/bobtoolz/DPatch.cpp
+++ b/contrib/bobtoolz/DPatch.cpp
@@ -307,29 +307,30 @@ DPatch* DPatch::MergePatches(patch_merge_t merge_info, DPatch *p1, DPatch *p2)
 		if(merge_info.pos2 < 0)
 			merge_info.pos2 += 3;
 	}
+	//
 
-	int newHeight = p1->height + p2->height - 1;
+	int newHeight = p1->height + p2->height - 1; 
 	if(newHeight > MAX_PATCH_HEIGHT)
+		return false;
+/*	int newWidth = p1->width + p2->width - 1;
+	if(newWidth > MAX_PATCH_WIDTH)
 		return NULL;
-
+*/	
 	DPatch* newPatch = new DPatch();
-
-	newPatch->height	= newHeight;
-	newPatch->width		= p1->width;
+	//switched..
+	newPatch->height	= p1->width;
+	newPatch->width		= newHeight;
 	newPatch->SetTexture(p1->texture);
 
-	int y = 0;
-	int i;
-	for(i = 0; i < p1->height; i++, y++)
+	for(int y = 0; y < p1->height; y++)
 		for(int x = 0; x < p1->width; x++)
-			newPatch->points[x][y] = p1->points[x][i];
-
-	for(i = 1; i < p2->height; i++, y++)
+			newPatch->points[x][y] = p1->points[x][y];
+	
+	for(int y = 1; y < p2->height; y++)
 		for(int x = 0; x < p2->width; x++)
-			newPatch->points[x][y] = p2->points[x][i];
-
+			newPatch->points[x][(y + p1->height - 1)] = p2->points[x][y];
+	
 //	newPatch->Invert();
-
 	return newPatch;
 }
 
@@ -396,13 +397,13 @@ void DPatch::Transpose()
 	Invert();
 }
 
-std::list<DPatch> DPatch::Split(bool rows, bool cols)
+std::list<DPatch> DPatch::SplitRows()
 {
 	std::list<DPatch> patchList;
 	int i;
 	int x, y;
 
-	if(rows && height >= 5)
+	if(height >= 5)
 	{
 		for(i = 0; i < (height-1)/2; i++)
 		{
@@ -411,53 +412,162 @@ std::list<DPatch> DPatch::Split(bool rows, bool cols)
 			p.width = width;
 			p.height = 3;
 			p.SetTexture(texture);
+			for(x = 0; x < 3; x++)
+			{
+				for(y = 0; y < p.width; y++)
+				{
+					p.points[x][y] = points[(i*2)+x][y];
+				}
+			}			
+			patchList.push_back(p);
+		}
+	} else {
+		//This returns exactly what comes in.. I don't know better :/
+		//If nothing is returned, the Patch in Radiant is just deleted - I suppose for evil follow up erros.
+		DPatch p;
+		
+		p.height = height;
+		p.width = width;
+		p.SetTexture(texture);
+		
+		for(x = 0; x < p.height; x++)
+		{
+			for(y = 0; y < p.width; y++)
+			{
+				p.points[x][y] = points[x][y];
+			}
+		}
+		patchList.push_back(p);
+	}
+	return patchList;
+}
 
-			for(y = 0; y < 3; y++)
+std::list<DPatch> DPatch::SplitCols()
+{
+	std::list<DPatch> patchList;
+	int i;
+	int x, y;
+	
+	if(width >= 5)
+	{
+		for(i = 0; i < (width-1)/2; i++)
+		{
+			DPatch p;
+			
+			p.width = 3;
+			p.height = height;
+			p.SetTexture(texture);
+			
+			for(x = 0; x < p.height; x++)
 			{
-				for(x = 0; x < p.width; x++)
+				for(y = 0; y < 3; y++)
 				{
 					p.points[x][y] = points[x][(i*2)+y];
 				}
 			}
 			patchList.push_back(p);
 		}
-
-		if(cols && width >= 5)
+	} else 
+	{
+		//This returns exactly what comes in.. I don't know better :/
+		//If nothing is returned, the Patch in Radiant is just deleted - I suppose for evil follow up erros.
+		DPatch p;
+		
+		p.height = height;
+		p.width = width;
+		p.SetTexture(texture);
+		
+		for(x = 0; x < p.height; x++)
 		{
-			std::list<DPatch> patchList2;
-
-			for(std::list<DPatch>::iterator patches = patchList.begin(); patches != patchList.end(); patches++)
+			for(y = 0; y < p.width; y++)
 			{
-				std::list<DPatch> patchList3 = (*patches).Split(false, true);
-				
-				for(std::list<DPatch>::iterator patches2 = patchList3.begin(); patches2 != patchList3.end(); patches2++)
-					patchList2.push_front(*patches2);
+				p.points[x][y] = points[x][y];
 			}
-
-			return patchList2;
 		}
+		patchList.push_back(p);
 	}
-	else if(cols && width >= 5)
+	return patchList;
+}
+
+std::list<DPatch> DPatch::Split()
+{
+	std::list<DPatch> patchList;
+	int i;
+	int x, y;
+	
+	if(width >= 5)
 	{
 		for(i = 0; i < (width-1)/2; i++)
 		{
 			DPatch p;
-
-			p.height = height;
+			
 			p.width = 3;
+			p.height = height;
+			p.SetTexture(texture);
+			
+			for(x = 0; x < p.height; x++)
+			{
+				for(y = 0; y < 3; y++)
+				{
+					p.points[x][y] = points[x][(i*2)+y];
+				}
+			}
+			patchList.push_back(p);
+		}
+		std::list<DPatch> patchList2;
+		for(std::list<DPatch>::iterator patches = patchList.begin(); patches != patchList.end(); patches++)
+		{
+			std::list<DPatch> patchList3 = (*patches).SplitRows();
+			for(std::list<DPatch>::iterator patches2 = patchList3.begin(); patches2 != patchList3.end(); patches2++)
+				patchList2.push_front(*patches2);
+		}
+		return patchList2;
+		
+	} else 	if(height >= 5) 
+	{
+		for(i = 0; i < (height-1)/2; i++)
+		{
+			DPatch p;
+			
+			p.width = width;
+			p.height = 3;
 			p.SetTexture(texture);
-
 			for(x = 0; x < 3; x++)
 			{
-				for(y = 0; y < p.height; y++)
+				for(y = 0; y < p.width; y++)
 				{
 					p.points[x][y] = points[(i*2)+x][y];
 				}
-			}
-
+			}			
 			patchList.push_back(p);
+		}		
+		std::list<DPatch> patchList2;
+		for(std::list<DPatch>::iterator patches = patchList.begin(); patches != patchList.end(); patches++)
+		{
+			std::list<DPatch> patchList3 = (*patches).SplitCols();
+			for(std::list<DPatch>::iterator patches2 = patchList3.begin(); patches2 != patchList3.end(); patches2++)
+				patchList2.push_front(*patches2);
 		}
+		return patchList2;
+		
+	} else 
+	{
+		//This returns exactly what comes in.. I don't know better :/
+		//If nothing is returned, the Patch in Radiant is just deleted - I suppose for evil follow up erros.
+		DPatch p;
+		
+		p.height = height;
+		p.width = width;
+		p.SetTexture(texture);
+		
+		for(x = 0; x < p.height; x++)
+		{
+			for(y = 0; y < p.width; y++)
+			{
+				p.points[x][y] = points[x][y];
+			}
+		}
+		patchList.push_back(p);		
 	}
-
 	return patchList;
 }
diff --git a/contrib/bobtoolz/DPatch.h b/contrib/bobtoolz/DPatch.h
index 32439189..5a956f92 100644
--- a/contrib/bobtoolz/DPatch.h
+++ b/contrib/bobtoolz/DPatch.h
@@ -46,15 +46,17 @@ namespace scene
   class Instance;
 }
 
-#define MAX_PATCH_WIDTH 16
-#define MAX_PATCH_HEIGHT 16
+#define MAX_PATCH_WIDTH 32
+#define MAX_PATCH_HEIGHT 32
 #define MIN_PATCH_WIDTH 3
 #define MIN_PATCH_HEIGHT 3
 
 class DPatch  
 {
 public:
-	std::list<DPatch> Split(bool rows, bool cols);
+	std::list<DPatch> SplitRows();
+	std::list<DPatch> SplitCols();
+	std::list<DPatch> Split();
 	void Transpose();
 	void Invert();
 	DPatch* MergePatches(patch_merge_t merge_info, DPatch* p1, DPatch* p2);
diff --git a/contrib/bobtoolz/DTreePlanter.cpp b/contrib/bobtoolz/DTreePlanter.cpp
index 958bcf8b..6ad221be 100644
--- a/contrib/bobtoolz/DTreePlanter.cpp
+++ b/contrib/bobtoolz/DTreePlanter.cpp
@@ -217,34 +217,32 @@ void DTreePlanter::DropEntsToGround( void ) {
   Scene_forEachEntity(TreePlanterDropEntityIfSelected(*this));
 }
 
-void DTreePlanter::MakeChain( void ) {
+void DTreePlanter::MakeChain( int linkNum, const char* linkName ) {
 	char buffer[256];
 	int i;
-
-	for(i = 0; i < m_linkNum; i++) {
+	for(i = 0; i < linkNum; i++) {
 		DEntity e("info_train_spline_main");
 
-		sprintf( buffer, "%s_pt%i", m_linkName, i );
+		sprintf( buffer, "%s_pt%i", linkName, i );
 		e.AddEPair( "targetname", buffer );
 
 		sprintf( buffer, "0 %i 0", i * 64 );
 		e.AddEPair( "origin", buffer );
 
 		if(i != m_linkNum-1) {
-			sprintf( buffer, "%s_pt%i", m_linkName, i+1 );
+			sprintf( buffer, "%s_pt%i", linkName, i+1 );
 			e.AddEPair( "target", buffer );
 
-			sprintf( buffer, "%s_ctl%i", m_linkName, i );
+			sprintf( buffer, "%s_ctl%i", linkName, i );
 			e.AddEPair( "control", buffer );
 		}
-
 		e.BuildInRadiant( false );
 	}
 
-	for(i = 0; i < m_linkNum-1; i++) {
+	for(i = 0; i < linkNum-1; i++) {
 		DEntity e("info_train_spline_control");
 
-		sprintf( buffer, "%s_ctl%i", m_linkName, i );
+		sprintf( buffer, "%s_ctl%i", linkName, i );
 		e.AddEPair( "targetname", buffer );
 
 		sprintf( buffer, "0 %i 0", (i * 64) + 32);
diff --git a/contrib/bobtoolz/DTreePlanter.h b/contrib/bobtoolz/DTreePlanter.h
index 10421660..fec8910f 100644
--- a/contrib/bobtoolz/DTreePlanter.h
+++ b/contrib/bobtoolz/DTreePlanter.h
@@ -181,7 +181,7 @@ public:
 
 	bool FindDropPoint(vec3_t in, vec3_t out);
 	void DropEntsToGround( void );
-	void MakeChain( void );
+	void MakeChain( int linkNum, const char* linkName );
 	void SelectChain( void );
 
 private:
diff --git a/contrib/bobtoolz/bobToolz-GTK.cpp b/contrib/bobtoolz/bobToolz-GTK.cpp
index be4f7804..07f7dae3 100644
--- a/contrib/bobtoolz/bobToolz-GTK.cpp
+++ b/contrib/bobtoolz/bobToolz-GTK.cpp
@@ -62,7 +62,7 @@ void BobToolz_destroy()
 char* PLUGIN_NAME = "bobToolz";
 
 // commands in the menu
-static char* PLUGIN_COMMANDS = "About...,-,Reset Textures...,PitOMatic,-,Vis Viewer,Brush Cleanup,Polygon Builder,Caulk Selection,-,Tree Planter,Drop Entity,Plot Splines,-,Merge Patches,Split patches,Turn edge";
+static char* PLUGIN_COMMANDS = "About...,-,Vis Viewer,Path Plotter...,-,Stair Builder...,PitOMatic,Make Chain...,Door Builder...,-,Texture Reset...,Intersect...";
 
 // globals
 GtkWidget *g_pRadiantWnd = NULL;
@@ -90,30 +90,22 @@ extern "C" const char* QERPlug_GetCommandList() {
 extern "C" void QERPlug_Dispatch (const char *p, vec3_t vMin, vec3_t vMax, bool bSingleBrush) {
 	LoadLists();
 
-	if( string_equal_nocase( p, "brush cleanup" ) ) {
-    DoFixBrushes();
-  } else if( string_equal_nocase( p, "polygon builder" ) ) {
-    DoPolygonsTB();
-  } else if( string_equal_nocase( p, "caulk selection" ) ) {
-    DoCaulkSelection();
-  } else if( string_equal_nocase( p, "tree planter" ) ) {
-    DoTreePlanter();
-  } else if( string_equal_nocase( p, "plot splines" ) ) {
-    DoTrainPathPlot();
-  } else if( string_equal_nocase( p, "drop entity" ) ) {
-    DoDropEnts();
-  } else if( string_equal_nocase( p, "merge patches" ) ) {
-    DoMergePatches();
-  } else if( string_equal_nocase( p, "split patches" ) ) {
-    DoSplitPatch();
-  } else if( string_equal_nocase( p, "turn edge" ) ) {
-    DoFlipTerrain();
-  } else if( string_equal_nocase(p, "reset textures...") ) {
+	if( string_equal_nocase(p, "texture reset...") ) {
 		DoResetTextures();
 	} else if( string_equal_nocase(p, "pitomatic") ) {
 		DoPitBuilder();
 	} else if( string_equal_nocase(p, "vis viewer") ) {
 		DoVisAnalyse();
+	} else if( string_equal_nocase(p, "stair builder...") ) {
+		DoBuildStairs();
+	} else if( string_equal_nocase(p, "door builder...") ) {
+		DoBuildDoors();
+	} else if( string_equal_nocase(p, "intersect...") ) {
+		DoIntersect();
+	} else if( string_equal_nocase(p, "make chain...") ) {
+		DoMakeChain();
+	} else if( string_equal_nocase(p, "path plotter...") ) {
+		DoPathPlotter();
 	} else if( string_equal_nocase(p, "about...") ) {
 		DoMessageBox(PLUGIN_ABOUT, "About", eMB_OK);
 	}
@@ -125,7 +117,7 @@ const char* QERPlug_GetCommandTitleList()
 }
 
 
-#define NUM_TOOLBARBUTTONS 9
+#define NUM_TOOLBARBUTTONS 14
 
 std::size_t ToolbarButtonCount( void ) {
 	return NUM_TOOLBARBUTTONS;
@@ -137,22 +129,30 @@ public:
   virtual const char* getImage() const
   {
     switch( mIndex ) {
-      case 0: return "bobtoolz_cleanup.bmp";
-      case 1: return "bobtoolz_poly.bmp";
-      case 2: return "bobtoolz_caulk.bmp";
-      case 3: return "bobtoolz_treeplanter.bmp";
-      case 4: return "bobtoolz_trainpathplot.bmp";
-      case 5: return "bobtoolz_dropent.bmp";
-      case 6: return "bobtoolz_merge.bmp";
-      case 7: return "bobtoolz_split.bmp";
-      case 8: return "bobtoolz_turnedge.bmp";
+		case 0: return "bobtoolz_cleanup.bmp";
+		case 1: return "bobtoolz_poly.bmp";
+		case 2: return "bobtoolz_caulk.bmp";
+		case 3: return "";
+		case 4: return "bobtoolz_treeplanter.bmp";
+		case 5: return "bobtoolz_trainpathplot.bmp";
+		case 6: return "bobtoolz_dropent.bmp";
+		case 7: return "";
+		case 8: return "bobtoolz_merge.bmp";
+		case 9: return "bobtoolz_split.bmp";
+		case 10: return "bobtoolz_splitrow.bmp";
+		case 11: return "bobtoolz_splitcol.bmp";
+        case 12: return "";
+		case 13: return "bobtoolz_turnedge.bmp";
     }
     return NULL;
   }
   virtual EType getType() const
   {
     switch( mIndex ) {
-      case 3: return eToggleButton;
+		case 3: return eSpace;
+      case 4: return eToggleButton;
+		case 7: return eSpace;
+		case 12: return eSpace;
       default: return eButton;
     }    
   }
@@ -162,12 +162,14 @@ public:
       case 0: return "Cleanup";
       case 1: return "Polygons";
       case 2: return "Caulk";
-      case 3: return "Tree Planter";
-      case 4: return "Plot Splines";
-      case 5: return "Drop Entity";
-      case 6: return "Merge Patches";
-      case 7: return "Split Patches";
-      case 8: return "Flip Terrain";
+      case 4: return "Tree Planter";
+      case 5: return "Plot Splines";
+      case 6: return "Drop Entity";
+      case 8: return "Merge 2 Patches";
+      case 9: return "Split Patch";
+      case 10: return "Split Patch Rows";
+      case 11: return "Split Patch Columns";
+      case 13: return "Flip Terrain";
     }
     return NULL;
   }
@@ -177,12 +179,14 @@ public:
       case 0: return "Brush Cleanup";
       case 1: return "Polygons";
       case 2: return "Caulk selection";
-      case 3: return "Tree Planter";
-      case 4: return "Plot Splines";
-      case 5: return "Drop Entity";
-      case 6: return "Merge Patches";
-      case 7: return "Split Patches";
-      case 8: return "Flip Terrain";
+      case 4: return "Tree Planter";
+      case 5: return "Plot Splines";
+      case 6: return "Drop Entity";
+      case 8: return "Merge 2 Patches";
+      case 9: return "Split Patch";
+	  case 10: return "Split Patch Rows";
+	  case 11: return "Split Patch Columns";
+      case 13: return "Flip Terrain (Turn Edge)";
     }
     return NULL;
   }
@@ -195,12 +199,14 @@ public:
       case 0: DoFixBrushes(); break;
       case 1: DoPolygonsTB(); break;
       case 2: DoCaulkSelection(); break;
-      case 3: DoTreePlanter(); break;
-      case 4: DoTrainPathPlot(); break;
-      case 5: DoDropEnts(); break;
-      case 6: DoMergePatches(); break;
-      case 7: DoSplitPatch(); break;
-      case 8: DoFlipTerrain(); break;
+      case 4: DoTreePlanter(); break;
+      case 5: DoTrainPathPlot(); break;
+      case 6: DoDropEnts(); break;
+      case 8: DoMergePatches(); break;
+      case 9: DoSplitPatch(); break;
+	  case 10: DoSplitPatchRows(); break;
+	  case 11: DoSplitPatchCols(); break;
+      case 13: DoFlipTerrain(); break;
     }
   }
 
@@ -259,7 +265,7 @@ class BobToolzPluginModule : public TypeSystemRef
   _QERPluginTable m_plugin;
 public:
   typedef _QERPluginTable Type;
-  STRING_CONSTANT(Name, "bobtoolz");
+  STRING_CONSTANT(Name, "bobToolz");
 
   BobToolzPluginModule()
   {
@@ -291,7 +297,7 @@ class BobToolzToolbarDependencies :
 {
 public:
   BobToolzToolbarDependencies() :
-    ModuleRef<_QERPluginTable>("bobtoolz")
+    ModuleRef<_QERPluginTable>("bobToolz")
   {
   }
 };
@@ -301,7 +307,7 @@ class BobToolzToolbarModule : public TypeSystemRef
   _QERPlugToolbarTable m_table;
 public:
   typedef _QERPlugToolbarTable Type;
-  STRING_CONSTANT(Name, "bobtoolz");
+  STRING_CONSTANT(Name, "bobToolz");
 
   BobToolzToolbarModule()
   {
diff --git a/contrib/bobtoolz/dialogs/dialogs-gtk.cpp b/contrib/bobtoolz/dialogs/dialogs-gtk.cpp
index 15d9db67..927c7887 100644
--- a/contrib/bobtoolz/dialogs/dialogs-gtk.cpp
+++ b/contrib/bobtoolz/dialogs/dialogs-gtk.cpp
@@ -370,6 +370,7 @@ EMessageBoxReturn DoIntersectBox (IntersectRS* rs)
  
 	// ---- vbox ----
 
+	
 		radio1 = gtk_radio_button_new_with_label(NULL, "Use Whole Map");
 		gtk_box_pack_start (GTK_BOX (vbox), radio1, FALSE, FALSE, 2);
 		gtk_widget_show (radio1);
@@ -377,7 +378,7 @@ EMessageBoxReturn DoIntersectBox (IntersectRS* rs)
 		radio2 = gtk_radio_button_new_with_label(((GtkRadioButton*)radio1)->group, "Use Selected Brushes");
 		gtk_box_pack_start (GTK_BOX (vbox), radio2, FALSE, FALSE, 2);
 		gtk_widget_show (radio2);
-
+	
 		w = gtk_hseparator_new ();
 		gtk_box_pack_start (GTK_BOX (vbox), w, FALSE, FALSE, 2);
 		gtk_widget_show (w);
@@ -1902,3 +1903,116 @@ EMessageBoxReturn DoTrainThingBox (TrainThingRS* rs)
 
 	return ret;
 }
+// ailmanki
+// add a simple input for the MakeChain thing..
+EMessageBoxReturn DoMakeChainBox(MakeChainRS* rs)
+{
+	GtkWidget	*window, *w, *vbox, *hbox;
+	GtkWidget	*textlinkNum, *textlinkName;
+	EMessageBoxReturn ret;
+	int loop = 1;
+	
+	char	*text = "Please set a value in the boxes below and press 'OK' to make a chain";
+	
+	window = gtk_window_new( GTK_WINDOW_TOPLEVEL );
+	
+	gtk_signal_connect (GTK_OBJECT (window), "delete_event", GTK_SIGNAL_FUNC (dialog_delete_callback), NULL);
+	gtk_signal_connect (GTK_OBJECT (window), "destroy", GTK_SIGNAL_FUNC (gtk_widget_destroy), NULL);
+	
+	gtk_window_set_title( GTK_WINDOW( window ), "Make Chain" );
+	
+	gtk_container_border_width( GTK_CONTAINER( window ), 10 );
+	
+	g_object_set_data (G_OBJECT (window), "loop", &loop);
+	g_object_set_data (G_OBJECT (window), "ret", &ret);
+	
+	gtk_widget_realize (window);
+	
+	// new vbox 
+	vbox = gtk_vbox_new( FALSE, 10 );
+	gtk_container_add( GTK_CONTAINER( window ), vbox );
+	gtk_widget_show( vbox );
+	
+	hbox = gtk_hbox_new( FALSE, 10 );
+	gtk_container_add( GTK_CONTAINER( vbox ), hbox );
+	gtk_widget_show( hbox );
+	
+	// dunno if you want this text or not ...
+	w = gtk_label_new( text );
+	gtk_box_pack_start( GTK_BOX( hbox ), w, FALSE, FALSE, 0 );
+	gtk_widget_show( w );
+	
+	w = gtk_hseparator_new();
+	gtk_box_pack_start( GTK_BOX( vbox ), w, FALSE, FALSE, 0 );
+	gtk_widget_show( w );
+	
+	// ------------------------- // 
+	
+	// new hbox
+	hbox = gtk_hbox_new( FALSE, 10 );
+	gtk_box_pack_start( GTK_BOX( vbox ), hbox, FALSE, FALSE, 0 );
+	gtk_widget_show( hbox );
+	
+	textlinkNum = gtk_entry_new_with_max_length( 256 ); 
+	gtk_box_pack_start( GTK_BOX( hbox ), textlinkNum, FALSE, FALSE, 1 );
+	gtk_widget_show( textlinkNum );
+	
+	w = gtk_label_new( "Number of elements in chain" );
+	gtk_box_pack_start( GTK_BOX( hbox ), w, FALSE, FALSE, 1 );
+	gtk_widget_show( w );
+	
+	// -------------------------- //
+	
+	hbox = gtk_hbox_new( FALSE, 10 );
+	gtk_box_pack_start( GTK_BOX( vbox ), hbox, FALSE, FALSE, 0 );
+	gtk_widget_show( hbox );
+	
+	textlinkName = gtk_entry_new_with_max_length( 256 );
+	gtk_box_pack_start( GTK_BOX( hbox ), textlinkName, FALSE, FALSE, 0 );
+	gtk_widget_show( textlinkName );
+	
+	w = gtk_label_new( "Basename for chain's targetnames." );
+	gtk_box_pack_start( GTK_BOX( hbox ), w, FALSE, FALSE, 1 );
+	gtk_widget_show( w );
+	
+	
+	w = gtk_button_new_with_label( "OK" );
+	gtk_box_pack_start( GTK_BOX( hbox ), w, TRUE, TRUE, 0);
+	gtk_signal_connect( GTK_OBJECT( w ), "clicked", GTK_SIGNAL_FUNC( dialog_button_callback ), GINT_TO_POINTER( eIDOK ) );
+	GTK_WIDGET_SET_FLAGS( w, GTK_CAN_DEFAULT );
+	gtk_widget_grab_default( w );
+	gtk_widget_show( w );
+	
+	w = gtk_button_new_with_label( "Cancel" );
+	gtk_box_pack_start( GTK_BOX( hbox ), w, TRUE, TRUE, 0 );
+	gtk_signal_connect( GTK_OBJECT( w ), "clicked", GTK_SIGNAL_FUNC( dialog_button_callback ), GINT_TO_POINTER( eIDCANCEL ) );
+	gtk_widget_show( w );
+	
+	ret = eIDCANCEL;
+
+	gtk_window_set_position(GTK_WINDOW(window),GTK_WIN_POS_CENTER);
+	gtk_widget_show (window);
+	gtk_grab_add (window);
+	
+	bool dialogError = TRUE;
+	while (dialogError)
+	{
+		loop = 1;
+		while (loop)
+			gtk_main_iteration ();
+		
+		dialogError = FALSE;
+		
+		if(ret == eIDOK)
+		{
+			strcpy(rs->linkName, gtk_entry_get_text((GtkEntry*)textlinkName));
+			if(!ValidateTextInt(gtk_entry_get_text((GtkEntry*)textlinkNum), "Elements", &rs->linkNum))
+				dialogError = TRUE;
+		}
+	}
+	
+	gtk_grab_remove (window);
+	gtk_widget_destroy (window);
+	
+	return ret;
+}
\ No newline at end of file
diff --git a/contrib/bobtoolz/dialogs/dialogs-gtk.h b/contrib/bobtoolz/dialogs/dialogs-gtk.h
index bcafdae8..0ad1c6b5 100644
--- a/contrib/bobtoolz/dialogs/dialogs-gtk.h
+++ b/contrib/bobtoolz/dialogs/dialogs-gtk.h
@@ -85,6 +85,11 @@ struct PathPlotterRS{
 	bool bShowExtra;
 };
 
+struct MakeChainRS{
+	char linkName[256];
+	int linkNum;
+};
+
 typedef struct _GtkWidget GtkWidget;
 
 struct TwinWidget{
@@ -101,7 +106,7 @@ EMessageBoxReturn DoDoorsBox(DoorRS* rs);
 EMessageBoxReturn DoPathPlotterBox(PathPlotterRS* rs);
 EMessageBoxReturn DoCTFColourChangeBox();
 EMessageBoxReturn DoTrainThingBox (TrainThingRS* rs);
-
+EMessageBoxReturn DoMakeChainBox(MakeChainRS* rs);
 //GtkWidget* GetProgressWindow(char* title, GtkProgressBar* feedback);
 
 #endif
diff --git a/contrib/bobtoolz/funchandlers-GTK.cpp b/contrib/bobtoolz/funchandlers-GTK.cpp
index 5d1f16a9..8f26d714 100644
--- a/contrib/bobtoolz/funchandlers-GTK.cpp
+++ b/contrib/bobtoolz/funchandlers-GTK.cpp
@@ -102,17 +102,19 @@ void DoIntersect()
 	{
 		if( GlobalSelectionSystem().countSelected() < 2 )
 		{
-			DoMessageBox("Invalid number of brushes selected, choose at least 2", "Error", eMB_OK);
+			//DoMessageBox("Invalid number of brushes selected, choose at least 2", "Error", eMB_OK);
+			globalErrorStream() << "bobToolz Intersect: Invalid number of brushes selected, choose at least 2.\n";
 			return; 
 		}
 	}
 
 	DEntity world;
-
 	switch(rs.nBrushOptions)
 	{
 	case BRUSH_OPT_SELECTED:
 		{
+			
+			world.LoadFromEntity(GlobalRadiant().getMapWorldEntity(), false);
 			world.LoadSelectedBrushes();
 			break;
 		}
@@ -122,7 +124,6 @@ void DoIntersect()
 			break;
 		}
 	}
-
 	world.RemoveNonCheckBrushes(&exclusionList, rs.bUseDetail);
 
 	bool* pbSelectList;
@@ -132,7 +133,8 @@ void DoIntersect()
 		pbSelectList = world.BuildIntersectList();
 
 	world.SelectBrushes(pbSelectList);
-
+	int brushCount = GlobalSelectionSystem().countSelected();
+	globalOutputStream() << "bobToolz Intersect: " << brushCount << " intersecting brushes found.\n";
 	delete[] pbSelectList;
 }
 
@@ -147,12 +149,18 @@ void DoPolygons()
 	// ensure we have something selected
 	if( GlobalSelectionSystem().countSelected() != 1 )
 	{
-		DoMessageBox("Invalid number of brushes selected, choose 1 only", "Error", eMB_OK);
+		//DoMessageBox("Invalid number of brushes selected, choose 1 only", "Error", eMB_OK);
+		globalErrorStream() << "bobToolz Polygons: Invalid number of brushes selected, choose 1 only.\n";
 		return; 
 	}
 
 	PolygonRS rs;
-
+	scene::Instance& instance = GlobalSelectionSystem().ultimateSelected();
+	if( !Node_isBrush(instance.path().top()) ) {
+		//DoMessageBox("No brush selected, select ONLY one brush", "Error", eMB_OK);
+		globalErrorStream() << "bobToolz Polygons: No brush selected, select ONLY one brush.\n";
+		return; 
+	}
 	// ask user for type, size, etc....
 	if(DoPolygonBox(&rs) == eIDOK)
 	{
@@ -161,7 +169,7 @@ void DoPolygons()
     vec3_t vMin, vMax;
 
     {
-      scene::Instance& instance = GlobalSelectionSystem().ultimateSelected();
+
       VectorSubtract(instance.worldAABB().origin, instance.worldAABB().extents, vMin);
       VectorAdd(instance.worldAABB().origin, instance.worldAABB().extents, vMax);
 
@@ -191,7 +199,7 @@ void DoFixBrushes()
 
 	int count = world.FixBrushes();
 	
-	globalOutputStream() << count << " invalid/duplicate planes removed\n";
+	globalOutputStream() << "bobToolz FixBrushes: " << count << " invalid/duplicate planes removed.\n";
 }
 
 void DoResetTextures()
@@ -243,7 +251,8 @@ void DoBuildStairs()
 	// ensure we have something selected
 	if( GlobalSelectionSystem().countSelected() != 1 )
 	{
-		DoMessageBox("Invalid number of brushes selected, choose 1 only", "Error", eMB_OK);
+		//DoMessageBox("Invalid number of brushes selected, choose 1 only", "Error", eMB_OK);
+		globalErrorStream() << "bobToolz BuildStairs: Invalid number of brushes selected, choose 1 only.\n";
 		return; 
 	}
 
@@ -265,7 +274,8 @@ void DoBuildStairs()
 		if(((int)size[2] % rs.stairHeight) != 0)
 		{
 			// stairs must fit evenly into brush
-			DoMessageBox("Invalid stair height\nHeight of block must be divisable by stair height", "Error", eMB_OK);
+			//DoMessageBox("Invalid stair height\nHeight of block must be divisable by stair height", "Error", eMB_OK);
+			globalErrorStream() << "bobToolz BuildStairs: Invalid stair height. Height of block must be divisable by stair height.\n";
 		}
 		else
 		{
@@ -328,7 +338,8 @@ void DoBuildDoors()
 	// ensure we have something selected
 	if( GlobalSelectionSystem().countSelected() != 1 )
 	{
-		DoMessageBox("Invalid number of brushes selected, choose 1 only", "Error", eMB_OK);
+		//DoMessageBox("Invalid number of brushes selected, choose 1 only", "Error", eMB_OK);
+		globalErrorStream() << "bobToolz BuildDoors: Invalid number of brushes selected, choose 1 only.\n";
 		return; 
 	}
 
@@ -369,88 +380,104 @@ void DoPathPlotter()
 	}
 
 	// ensure we have something selected
-	if( GlobalSelectionSystem().countSelected() != 1 )
+	/*
+	 if( GlobalSelectionSystem().countSelected() != 1 )
 	{
-		DoMessageBox("Invalid number of brushes selected, choose 1 only", "Error", eMB_OK);
+		//DoMessageBox("Invalid number of brushes selected, choose 1 only", "Error", eMB_OK);
+		globalOutputStream() << "bobToolz PathPlotter: Invalid number of entities selected, choose 1 trigger_push entity only.\n";
 		return; 
 	}
-
+	 */
   Entity* entity = Node_getEntity(GlobalSelectionSystem().ultimateSelected().path().top());
   if(entity != 0)
   {
     DBobView_setEntity(*entity, rs.fMultiplier, rs.nPoints, rs.fGravity, rs.bNoUpdate, rs.bShowExtra);
-  }
+  } 
+  else globalErrorStream() << "bobToolz PathPlotter: No trigger_push entitity selected, select 1 only (Use list to select it).\n";
+	return;
 }
 
 void DoPitBuilder()
 {
-  UndoableCommand undo("bobToolz.pitBuilder");
+	UndoableCommand undo("bobToolz.pitBuilder");
 	// ensure we have something selected
 	if( GlobalSelectionSystem().countSelected() != 1 )
 	{
-		DoMessageBox("Invalid number of brushes selected, choose 1 only", "Error", eMB_OK);
+		//DoMessageBox("Invalid number of brushes selected, choose 1 only", "Error", eMB_OK);
+		globalErrorStream() << "bobToolz PitBuilder: Invalid number of brushes selected, choose 1 only.\n";
 		return; 
 	}
 
-  vec3_t vMin, vMax;
+	vec3_t vMin, vMax;
 
-  scene::Instance& instance = GlobalSelectionSystem().ultimateSelected();
-  VectorSubtract(instance.worldAABB().origin, instance.worldAABB().extents, vMin);
-  VectorAdd(instance.worldAABB().origin, instance.worldAABB().extents, vMax);
+	scene::Instance& instance = GlobalSelectionSystem().ultimateSelected();
+	//seems it does this also with a patch with valid dimensions.. but probably better to enforce a brush.
+	if( !Node_isBrush(instance.path().top()) ) {
+		//DoMessageBox("No brush selected, select ONLY one brush", "Error", eMB_OK);
+		globalErrorStream() << "bobToolz PitBuilder: No brush selected, select ONLY 1 brush.\n";
+		return; 
+	}
+	
+	VectorSubtract(instance.worldAABB().origin, instance.worldAABB().extents, vMin);
+	VectorAdd(instance.worldAABB().origin, instance.worldAABB().extents, vMax);
 
 	DShape pit;
 
 	if(pit.BuildPit(vMin, vMax))
 	{
 		pit.Commit();
-
-    Path_deleteTop(instance.path());
+		Path_deleteTop(instance.path());
 	}
 	else
-		DoMessageBox("Failed To Make Pit\nTry Making The Brush Bigger", "Error", eMB_OK);
+	{
+		//DoMessageBox("Failed To Make Pit\nTry Making The Brush Bigger", "Error", eMB_OK);
+		globalErrorStream() << "bobToolz PitBuilder: Failed to make Pit, try making the brush bigger.\n";
+	}
 }
 
 void DoMergePatches()
 {
-  UndoableCommand undo("bobToolz.mergePatch");
-  patch_merge_t merge_info;
-  DPatch mrgPatches[2];
-  int i;
+	UndoableCommand undo("bobToolz.mergePatches");
+	patch_merge_t merge_info;
+	DPatch mrgPatches[2];
+	int i;
 
 	// ensure we have something selected
 	if( GlobalSelectionSystem().countSelected() != 2 )
 	{
-		DoMessageBox("Invalid number of patches selected, choose 2 only", "Error", eMB_OK);
+		globalErrorStream() << "bobToolz MergePatches: Invalid number of patches selected, choose 2 only.\n";
+		//DoMessageBox("Invalid number of patches selected, choose 2 only", "Error", eMB_OK);
 		return; 
 	}
 
-  scene::Instance* patches[2];
-  patches[0] = &GlobalSelectionSystem().ultimateSelected();
-  patches[1] = &GlobalSelectionSystem().penultimateSelected();
+	scene::Instance* patches[2];
+	patches[0] = &GlobalSelectionSystem().ultimateSelected();
+	patches[1] = &GlobalSelectionSystem().penultimateSelected();
 
-  for (i = 0; i < 2; i++)
-  {
-    if (!Node_isPatch(patches[i]->path().top()))
-    {
-      DoMessageBox("You must select ONLY patches", "Error", eMB_OK);
-      return; 
-    }
+	for (i = 0; i < 2; i++)
+	{
+		if (!Node_isPatch(patches[i]->path().top()))
+		{
+			//DoMessageBox("No patches selected, select ONLY patches", "Error", eMB_OK);
+			globalErrorStream() << "bobToolz MergePatches: Invalid number of patches selected, choose ONLY 2 patches.\n";
+			return; 
+		}
 
-    mrgPatches[i].LoadFromPatch(*patches[i]);
-  }
+		mrgPatches[i].LoadFromPatch(*patches[i]);
+	}
 
   /*  mrgPatches[0].Transpose();
       mrgPatches[0].RemoveFromRadiant();
       mrgPatches[0].BuildInRadiant();*/
 
-  merge_info = mrgPatches[0].IsMergable(&mrgPatches[1]);
+	merge_info = mrgPatches[0].IsMergable(&mrgPatches[1]);
 
-  if (merge_info.mergable)
-  {
-    globalOutputStream() << merge_info.pos1 << " " <<  merge_info.pos2;
-
-    globalOutputStream() << "Patches Mergable\n";
-    DPatch* newPatch = mrgPatches[0].MergePatches(merge_info, &mrgPatches[0], &mrgPatches[1]);
+	if (merge_info.mergable)
+	{
+		globalOutputStream() << merge_info.pos1 << " " <<  merge_info.pos2;
+		//Message removed, No tools give feedback on success.
+		//globalOutputStream() << "bobToolz MergePatches: Patches Mergable.\n";
+		DPatch* newPatch = mrgPatches[0].MergePatches(merge_info, &mrgPatches[0], &mrgPatches[1]);
 
     /*                mrgPatches[0].RemoveFromRadiant();
     mrgPatches[0].BuildInRadiant();
@@ -461,21 +488,22 @@ void DoMergePatches()
         
     delete newPatch;*/
 
-    if (!newPatch)
-    {
-    } else
-    {
-      Path_deleteTop(patches[0]->path());
-      Path_deleteTop(patches[1]->path());
+		if (!newPatch)
+		{
+		} else
+		{
+			Path_deleteTop(patches[0]->path());
+			Path_deleteTop(patches[1]->path());
 
-      newPatch->BuildInRadiant();
-      delete newPatch;
-    }
-  }
-  else
-  {
-    globalOutputStream() << "bobToolz.mergePatch: the selected patches are not mergable\n";
-  }
+			newPatch->BuildInRadiant();
+			delete newPatch;
+		}
+	}
+	else
+	{
+		globalErrorStream() << "bobToolz.mergePatch: The selected patches are not mergable.\n";
+		
+	}
 }
 
 void DoSplitPatch() {
@@ -486,24 +514,88 @@ void DoSplitPatch() {
 	// ensure we have something selected
 	if( GlobalSelectionSystem().countSelected() != 1 )
 	{
-		DoMessageBox("Invalid number of patches selected, choose 1 only", "Error", eMB_OK);
+		//DoMessageBox("Invalid number of patches selected, choose 1 only", "Error", eMB_OK);
+		globalErrorStream() << "bobToolz SplitPatch: Invalid number of patches selected, choose only 1 patch.\n";
 		return; 
 	}
 
   scene::Instance& instance = GlobalSelectionSystem().ultimateSelected();
 
 	if( !Node_isPatch(instance.path().top()) ) {
-		DoMessageBox("You must select ONLY patches", "Error", eMB_OK);
+		//DoMessageBox("No patch selected, select ONLY one patch", "Error", eMB_OK);
+		globalErrorStream() << "bobToolz SplitPatch: No patch selected, select ONLY 1 patch.\n";
 		return; 
 	}
 
 	patch.LoadFromPatch(instance);
 
-	std::list<DPatch> patchList = patch.Split( true, true );
+	std::list<DPatch> patchList = patch.Split();
+	for(std::list<DPatch>::iterator patches = patchList.begin(); patches != patchList.end(); patches++) {
+		(*patches).BuildInRadiant();
+	}
+
+	Path_deleteTop(instance.path());
+}
+
+void DoSplitPatchCols() {
+	UndoableCommand undo("bobToolz.splitPatchCols");
+	
+	DPatch patch;
+	
+	// ensure we have something selected
+	if( GlobalSelectionSystem().countSelected() != 1 )
+	{
+		//DoMessageBox("Invalid number of patches selected, choose 1 only", "Error", eMB_OK);
+		globalErrorStream() << "bobToolz SplitPatchCols: Invalid number of patches selected, choose 1 only.\n";
+		return; 
+	}
+	
+	scene::Instance& instance = GlobalSelectionSystem().ultimateSelected();
+	
+	if( !Node_isPatch(instance.path().top()) ) {
+		//DoMessageBox("No patch selected, select ONLY one patch", "Error", eMB_OK);
+		globalErrorStream() << "bobToolz SplitPatchCols: No patch selected, select ONLY 1 patch.\n";
+		return; 
+	}
+	
+	patch.LoadFromPatch(instance);
+	
+	std::list<DPatch> patchList = patch.SplitCols();
 	for(std::list<DPatch>::iterator patches = patchList.begin(); patches != patchList.end(); patches++) {
 		(*patches).BuildInRadiant();
 	}
+	
+	Path_deleteTop(instance.path());
+}
 
+void DoSplitPatchRows() {
+	UndoableCommand undo("bobToolz.splitPatchRows");
+	
+	DPatch patch;
+	
+	// ensure we have something selected
+	if( GlobalSelectionSystem().countSelected() != 1 )
+	{
+		//DoMessageBox("Invalid number of patches selected, choose 1 only", "Error", eMB_OK);
+		globalErrorStream() << "bobToolz SplitPatchRows: Invalid number of patches selected, choose 1 only.\n";
+		return; 
+	}
+	
+	scene::Instance& instance = GlobalSelectionSystem().ultimateSelected();
+	
+	if( !Node_isPatch(instance.path().top()) ) {
+		//DoMessageBox("No patch selected, select ONLY one patch", "Error", eMB_OK);
+		globalErrorStream() << "bobToolz SplitPatchRows: No patch selected, select ONLY 1 patch.\n";
+		return; 
+	}
+	
+	patch.LoadFromPatch(instance);
+	
+	std::list<DPatch> patchList = patch.SplitRows();
+	for(std::list<DPatch>::iterator patches = patchList.begin(); patches != patchList.end(); patches++) {
+		(*patches).BuildInRadiant();
+	}
+	
 	Path_deleteTop(instance.path());
 }
 
@@ -513,6 +605,7 @@ void DoVisAnalyse()
 
 	if( GlobalSelectionSystem().countSelected() == 0 )
 	{
+		globalErrorStream() << "bobToolz VisAnalyse: Invalid number of objects selected, choose 1 only.\n";
 		if(g_VisView) 
 		{
 			delete g_VisView;
@@ -523,12 +616,18 @@ void DoVisAnalyse()
 	// ensure we have something selected
 	if( GlobalSelectionSystem().countSelected() != 1 )
 	{
-		DoMessageBox("Invalid number of objects selected, choose 1 only", "Error", eMB_OK);
+		//DoMessageBox("Invalid number of objects selected, choose 1 only", "Error", eMB_OK);
+		globalErrorStream() << "bobToolz VisAnalyse: Invalid number of objects selected, choose 1 only.\n";
+		return; 
+	}
+	
+	scene::Instance& brush = GlobalSelectionSystem().ultimateSelected();
+	//ensure we have a brush selected
+	if( !Node_isBrush(brush.path().top()) ) {
+		//DoMessageBox("No brush selected, select ONLY one brush", "Error", eMB_OK);
+		globalErrorStream() << "bobToolz VisAnalyse: No brush selected, select ONLY 1 brush.\n";
 		return; 
 	}
-
-  scene::Instance& brush = GlobalSelectionSystem().ultimateSelected();
-
 	DBrush orgBrush;
 	orgBrush.LoadFromBrush(brush, false);
 
@@ -542,7 +641,8 @@ void DoVisAnalyse()
   const char* rad_filename = GlobalRadiant().getMapName();
 	if(!rad_filename)
 	{
-		DoMessageBox("An Error Occurred While Trying\n To Get The Map Filename", "Error", eMB_OK);
+		//DoMessageBox("An ERROR occurred while trying\n to get the map filename", "Error", eMB_OK);
+		globalErrorStream() << "bobToolz VisAnalyse: An ERROR occurred while trying to get the map filename.\n";
 		return;
 	}
 
@@ -604,9 +704,17 @@ void DoDropEnts() {
 }
 
 void DoMakeChain() {
-  UndoableCommand undo("bobToolz.makeChain");
-	DTreePlanter pl;
-	pl.MakeChain();
+	MakeChainRS rs;
+	if(DoMakeChainBox(&rs) == eIDOK)
+	{
+		if ( rs.linkNum > 1001 ) {
+			globalErrorStream() << "bobToolz MakeChain: " << rs.linkNum << " to many Elemets, limited to 1000.\n";
+			return;
+		}
+		UndoableCommand undo("bobToolz.makeChain");
+		DTreePlanter pl;
+		pl.MakeChain(rs.linkNum,rs.linkName);
+	}
 }
 
 typedef DPoint* pntTripple[3];
@@ -621,21 +729,31 @@ void DoFlipTerrain() {
 	// ensure we have something selected
 	if( GlobalSelectionSystem().countSelected() != 2 )
 	{
-		DoMessageBox("Invalid number of objects selected, choose 2 only", "Error", eMB_OK);
+		//DoMessageBox("Invalid number of objects selected, choose 2 only", "Error", eMB_OK);
+		globalErrorStream() << "bobToolz FlipTerrain: Invalid number of objects selected, choose 2 only.\n";
 		return; 
 	}
 
   scene::Instance* brushes[2];
 	brushes[0] = &GlobalSelectionSystem().ultimateSelected();
 	brushes[1] = &GlobalSelectionSystem().penultimateSelected();
-
+	//ensure we have only Brushes selected.
+	for (i = 0; i < 2; i++)
+	{
+		if( !Node_isBrush(brushes[i]->path().top()) ) {
+			//DoMessageBox("No brushes selected, select ONLY brushes", "Error", eMB_OK);
+			globalErrorStream() << "bobToolz FlipTerrain: No brushes selected, select ONLY 2 brushes.\n";
+			return; 
+		}
+	}
 	DBrush Brushes[2];
 	DPlane* Planes[2];
 	pntTripple Points[2];
 	for( i = 0; i < 2; i++ ) {
 		Brushes[i].LoadFromBrush( *brushes[i], false );
 		if(!(Planes[i] = Brushes[i].FindPlaneWithClosestNormal( vUp )) || Brushes[i].FindPointsForPlane( Planes[i], Points[i], 3 ) != 3) {
-			DoMessageBox("Error", "Error", eMB_OK);
+			//DoMessageBox("Error", "Error", eMB_OK);
+			globalErrorStream() << "bobToolz FlipTerrain: ERROR (FindPlaneWithClosestNormal/FindPointsForPlane).\n";
 			return;
 		}
 	}
@@ -662,7 +780,8 @@ void DoFlipTerrain() {
 		found = false;
 	}
 	if(dontmatch[0] == -1) {
-		DoMessageBox("Error", "Error", eMB_OK);
+		//DoMessageBox("Error", "Error", eMB_OK);
+		globalErrorStream() << "bobToolz FlipTerrain: ERROR (dontmatch[0]).\n";
 		return;
 	}
 
@@ -680,7 +799,8 @@ void DoFlipTerrain() {
 		found = false;
 	}
 	if(dontmatch[1] == -1) {
-		DoMessageBox("Error", "Error", eMB_OK);
+		//DoMessageBox("Error", "Error", eMB_OK);
+		globalErrorStream() << "bobToolz FlipTerrain: ERROR (dontmatch[1]).\n";
 		return;
 	}
 
diff --git a/contrib/bobtoolz/funchandlers.h b/contrib/bobtoolz/funchandlers.h
index 8be283fd..3f4202ff 100644
--- a/contrib/bobtoolz/funchandlers.h
+++ b/contrib/bobtoolz/funchandlers.h
@@ -62,6 +62,8 @@ void DoPitBuilder();
 void DoCTFColourChanger();
 void DoMergePatches();
 void DoSplitPatch();
+void DoSplitPatchRows();
+void DoSplitPatchCols();
 void DoVisAnalyse();
 void DoTrainThing();
 void DoTrainPathPlot();
diff --git a/contrib/bobtoolz/shapes.cpp b/contrib/bobtoolz/shapes.cpp
index 4713ff5f..e38dd495 100644
--- a/contrib/bobtoolz/shapes.cpp
+++ b/contrib/bobtoolz/shapes.cpp
@@ -576,32 +576,43 @@ void BuildDoorsX2(vec3_t min, vec3_t max,
 
 void MakeBevel(vec3_t vMin, vec3_t vMax)
 {
-  NodeSmartReference patch(GlobalPatchCreator().createPatch());
-  PatchControlMatrix matrix = GlobalPatchCreator().Patch_getControlPoints(patch);
-
-  GlobalPatchCreator().Patch_setShader(patch, "textures/common/caulk");
-  GlobalPatchCreator().Patch_resize(patch, 3, 3);
-	
+	NodeSmartReference patch(GlobalPatchCreator().createPatch());
+    GlobalPatchCreator().Patch_resize(patch, 3, 3);
+	GlobalPatchCreator().Patch_setShader(patch, "textures/common/caulk");
+	PatchControlMatrix matrix = GlobalPatchCreator().Patch_getControlPoints(patch);
 	vec3_t x_3, y_3, z_3;
 	x_3[0] = vMin[0];	x_3[1] = vMin[0];				x_3[2] = vMax[0];
 	y_3[0] = vMin[1];	y_3[1] = vMax[1];				y_3[2] = vMax[1];
 	z_3[0] = vMin[2];	z_3[1] = (vMax[2] + vMin[2])/2;	z_3[2] = vMax[2];
-
-/*	x_3[0] = 0;		x_3[1] = 0;		x_3[2] = 64;
-	y_3[0] = 0;		y_3[1] = 64;	y_3[2] = 64;
-	z_3[0] = 0;		z_3[1] = 32;	z_3[2] = 64;*/
-
+	/*
+	 x_3[0] = 0;		x_3[1] = 0;		x_3[2] = 64;
+	 y_3[0] = 0;		y_3[1] = 64;	y_3[2] = 64;
+	 z_3[0] = 0;		z_3[1] = 32;	z_3[2] = 64;*/
 	for(int i = 0; i < 3; i++)
 	{
 		for(int j = 0; j < 3; j++)
 		{
-			matrix(i, j).m_vertex[0] = x_3[i];
-			matrix(i, j).m_vertex[1] = y_3[i];
-			matrix(i, j).m_vertex[2] = z_3[j];
+			PatchControl& p = matrix(i, j);
+			p.m_vertex[0] = x_3[i];
+			p.m_vertex[1] = y_3[i];
+			p.m_vertex[2] = z_3[j];
 		}
 	}
-
-  Node_getTraversable(GlobalRadiant().getMapWorldEntity())->insert(patch);
+	//does invert the matrix, else the patch face is on wrong side.
+	for(int i = 0 ; i < 3 ; i++ ) 
+	{
+		for(int j = 0; j < 1; j++)
+		{
+			PatchControl& p = matrix(i,2- j);
+			PatchControl& q = matrix(i, j);
+			std::swap(p.m_vertex, q.m_vertex);
+			//std::swap(p.m_texcoord, q.m_texcoord);
+		}
+	}
+	GlobalPatchCreator().Patch_controlPointsChanged(patch);
+	//TODO - the patch has textures weird, patchmanip.h has all function it needs.. lots of duplicate code.. 
+	//NaturalTexture(patch);
+	Node_getTraversable(GlobalRadiant().getMapWorldEntity())->insert(patch);
 }
 
 void BuildCornerStairs(vec3_t vMin, vec3_t vMax, int nSteps, const char* mainTexture, const char* riserTex)
@@ -609,7 +620,7 @@ void BuildCornerStairs(vec3_t vMin, vec3_t vMax, int nSteps, const char* mainTex
 	vec3_t* topPoints = new vec3_t[nSteps+1];
 	vec3_t* botPoints = new vec3_t[nSteps+1];
 
-	bool bFacesUse[6] = {true, true, false, true, false, false};
+	//bool bFacesUse[6] = {true, true, false, true, false, false};
 
 	vec3_t centre;
 	VectorCopy(vMin, centre);
@@ -644,8 +655,25 @@ void BuildCornerStairs(vec3_t vMin, vec3_t vMax, int nSteps, const char* mainTex
 
 	for(i = 0; i < nSteps; i++)
 	{
-    scene::Node& brush = Build_Get_BoundingCube_Selective(vBot, vTop, "textures/common/caulk", bFacesUse);
-
+		NodeSmartReference brush(GlobalBrushCreator().createBrush());
+		vec3_t v1, v2, v3, v5, v6, v7;
+		VectorCopy(vBot, v1);
+		VectorCopy(vBot, v2);
+		VectorCopy(vBot, v3);
+		VectorCopy(vTop, v5);
+		VectorCopy(vTop, v6);
+		VectorCopy(vTop, v7);
+		
+		v2[0] = vTop[0];
+		v3[1] = vTop[1];
+		
+		v6[0] = vBot[0];
+		v7[1] = vBot[1];
+		
+		AddFaceWithTexture(brush, v1, v2, v3, "textures/common/caulk", false);
+		AddFaceWithTexture(brush, v1, v3, v6, "textures/common/caulk", false);
+		AddFaceWithTexture(brush, v5, v6, v3, "textures/common/caulk", false);
+		
 		for(int j = 0; j < 3; j++)
 			tp[j][2] = vTop[2];
 
diff --git a/docs/index.html b/docs/index.html
new file mode 100644
index 00000000..45a168ec
--- /dev/null
+++ b/docs/index.html
@@ -0,0 +1,16 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
+<html>
+<head>
+  <meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+  <meta http-equiv="Content-Style-Type" content="text/css">
+  <title></title>
+  <meta name="Generator" content="Cocoa HTML Writer">
+  <meta name="CocoaVersion" content="1038.25">
+  <style type="text/css">
+    p.p1 {margin: 0.0px 0.0px 0.0px 0.0px; font: 12.0px Helvetica}
+  </style>
+</head>
+<body>
+<p class="p1">put here links</p>
+</body>
+</html>
diff --git a/include/igl.h b/include/igl.h
index b1753457..0662379e 100644
--- a/include/igl.h
+++ b/include/igl.h
@@ -2318,8 +2318,14 @@ struct OpenGLBinding
   void (QGL_DLLEXPORT *m_glTexGenfv)(GLenum coord, GLenum pname, const GLfloat *params);
   void (QGL_DLLEXPORT *m_glTexGeni)(GLenum coord, GLenum pname, GLint param);
   void (QGL_DLLEXPORT *m_glTexGeniv)(GLenum coord, GLenum pname, const GLint *params);
+#if defined(MACVERSION) && MACVERSION > 15
+	//Snow Leopard 16, Leopard 15, Tiger 14, Panther 13, ... 
+  void (QGL_DLLEXPORT *m_glTexImage1D)(GLenum target, GLint level, GLenum internalformat, GLsizei width, GLint border, GLenum format, GLenum type, const GLvoid *pixels);
+  void (QGL_DLLEXPORT *m_glTexImage2D)(GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLint border, GLenum format, GLenum type, const GLvoid *pixels);
+#else
   void (QGL_DLLEXPORT *m_glTexImage1D)(GLenum target, GLint level, GLint internalformat, GLsizei width, GLint border, GLenum format, GLenum type, const GLvoid *pixels);
-  void (QGL_DLLEXPORT *m_glTexImage2D)(GLenum target, GLint level, GLint internalformat, GLsizei width, GLsizei height, GLint border, GLenum format, GLenum type, const GLvoid *pixels);
+  void (QGL_DLLEXPORT *m_glTexImage2D)(GLenum target, GLint level, GLint internalformat, GLsizei width, GLsizei height, GLint border, GLenum format, GLenum type, const GLvoid *pixels);	
+#endif
   void (QGL_DLLEXPORT *m_glTexParameterf)(GLenum target, GLenum pname, GLfloat param);
   void (QGL_DLLEXPORT *m_glTexParameterfv)(GLenum target, GLenum pname, const GLfloat *params);
   void (QGL_DLLEXPORT *m_glTexParameteri)(GLenum target, GLenum pname, GLint param);
diff --git a/install-dylibs.sh b/install-dylibs.sh
index 107e477d..fd70339a 100644
--- a/install-dylibs.sh
+++ b/install-dylibs.sh
@@ -5,10 +5,14 @@ set -ex
 : ${OTOOL:=otool}
 : ${CP:=cp}
 : ${INSTALLDIR:=.}
+: ${EXE:=ppc}
+: ${MACLIBDIR:=/sw/lib}
+: ${CAT:=cat}
+
 
 finkgetdeps()
 {
-	otool -L "$1" | grep /sw/lib | while read -r LIB STUFF; do
+	otool -L "$1" | grep "$MACLIBDIR" | while read -r LIB STUFF; do
 		[ -z "${LIB##*:}" ] && continue # first line
 		[ -f "$INSTALLDIR/${LIB##*/}" ] && continue
 		cp -vL "$LIB" "$INSTALLDIR"
@@ -16,23 +20,50 @@ finkgetdeps()
 	done
 }
 
-finkgetdeps "$INSTALLDIR/radiant.ppc"
+
+finkgetdeps "$INSTALLDIR/radiant.$EXE"
 echo Warning: this only works if only ONE version of gtk-2.0 and pango is installed
 
-for LIB in /sw/lib/gtk-2.0/*/loaders/libpixbufloader-bmp.so; do
+for LIB in "$MACLIBDIR"/gtk-2.0/*/loaders/libpixbufloader-bmp.so; do
 	LAST=$LIB
 done
 cp -L "$LAST" "$INSTALLDIR"
 finkgetdeps "$LAST"
 
-for LIB in /sw/lib/pango/*/modules/pango-basic-fc.so; do
+for LIB in "$MACLIBDIR"/pango/*/modules/pango-basic-fc.so; do
 	LAST=$LIB
 done
 cp -L "$LAST" "$INSTALLDIR"
 finkgetdeps "$LAST"
 
-for LIB in /sw/lib/pango/*/modules/pango-basic-x.so; do
+for LIB in "$MACLIBDIR"/pango/*/modules/pango-basic-x.so; do
 	LAST=$LIB
 done
 cp -L "$LAST" "$INSTALLDIR"
 finkgetdeps "$LAST"
+
+cp -L "$MACLIBDIR"/../etc/fonts/fonts.conf "$INSTALLDIR"
+cp -L "$MACLIBDIR"/../etc/fonts/fonts.dtd "$INSTALLDIR"
+cp -L "$MACLIBDIR"/../etc/gtk-2.0/gdk-pixbuf.loaders "$INSTALLDIR"
+cp -L "$MACLIBDIR"/../etc/pango/pangorc "$INSTALLDIR"
+
+$CAT > $INSTALLDIR/../netradiant.sh <<EOF
+#!/bin/sh
+
+MY_DIRECTORY="\${0%/*}" # cut off the script name
+MY_DIRECTORY="\${MY_DIRECTORY%/*}" # cut off MacOS
+MY_DIRECTORY="\${MY_DIRECTORY%/*}" # cut off Contents
+
+export DYLD_LIBRARY_PATH="\$MY_DIRECTORY/Contents/MacOS/install"
+export PANGO_RC_FILE="\$MY_DIRECTORY/Contents/MacOS/install/pangorc"
+export GDK_PIXBUF_MODULE_FILE="\$MY_DIRECTORY/Contents/MacOS/install/gdk-pixbuf.loaders"
+export FONTCONFIG_FILE="\$MY_DIRECTORY/Contents/MacOS/install/fonts.conf"
+
+cd "\$MY_DIRECTORY/Contents/MacOS/install"
+if [ -x /usr/bin/open-x11 ]; then
+	env LC_ALL="en_US.UTF-8" /usr/bin/open-x11 ./radiant.$EXE "$@" &
+else
+	env LC_ALL="en_US.UTF-8" ./radiant.$EXE "$@" &
+fi
+
+EOF
diff --git a/radiant/mainframe.cpp b/radiant/mainframe.cpp
index a441e03c..05d9e52e 100644
--- a/radiant/mainframe.cpp
+++ b/radiant/mainframe.cpp
@@ -992,9 +992,9 @@ void OpenUpdateURL()
 // open the Q3Rad manual
 void OpenHelpURL()
 {
-  // at least on win32, AppPath + "Q3Rad_Manual/index.htm"
+  // at least on win32, AppPath + "docs/index.html"
   StringOutputStream help(256);
-  help << AppPath_get() << "Q3Rad_Manual/index.htm";
+  help << AppPath_get() << "docs/index.html";
   OpenURL(help.c_str());
 }
 
diff --git a/radiant/patch.cpp b/radiant/patch.cpp
index a9e452d9..ac96240f 100644
--- a/radiant/patch.cpp
+++ b/radiant/patch.cpp
@@ -776,7 +776,15 @@ void Patch::InsertPoints(EMatrixMajor mt, bool bFirst)
   std::size_t pos = 0;
   {
     PatchControl* p1 = m_ctrl.data();
-    for(std::size_t w = 0; w != width; ++w, p1 += col_stride)
+	/*
+	  if(GlobalSelectionSystem().countSelected() != 0) 
+	  {  
+		  scene::Instance& instance = GlobalSelectionSystem().ultimateSelected();
+		  PatchInstance* patch = Instance_getPatch(instance);
+		  patch->m_selectable.isSelected();
+	  }
+	*/
+	for(std::size_t w = 0; w != width; ++w, p1 += col_stride)
     {
       {
         PatchControl* p2 = p1;
@@ -831,7 +839,15 @@ void Patch::InsertPoints(EMatrixMajor mt, bool bFirst)
     ERROR_MESSAGE("neither row-major nor column-major");
     return;
   }
-
+    if(bFirst)
+    {
+		pos = height - 1;
+    }
+    else
+    {
+		pos = 2;
+    }
+	
   if(pos >= height)
   {
     if(bFirst)
@@ -978,7 +994,14 @@ void Patch::RemovePoints(EMatrixMajor mt, bool bFirst)
     ERROR_MESSAGE("neither row-major nor column-major");
     return;
   }
-
+    if(bFirst)
+    {
+		pos=height-3;
+    }
+    else
+    {
+		pos=2;
+    }
   if(pos >= height)
   {
     if(bFirst)
diff --git a/setup/data/osx/NetRadiant.app/Contents/MacOS/install/fonts.conf b/setup/data/osx/NetRadiant.app/Contents/MacOS/install/fonts.conf
new file mode 100755
index 00000000..86dc8af2
--- /dev/null
+++ b/setup/data/osx/NetRadiant.app/Contents/MacOS/install/fonts.conf
@@ -0,0 +1,150 @@
+<?xml version="1.0"?>
+<!DOCTYPE fontconfig SYSTEM "fonts.dtd">
+<!-- /etc/fonts/fonts.conf file to configure system font access -->
+<fontconfig>
+
+<!--
+	DO NOT EDIT THIS FILE.
+	IT WILL BE REPLACED WHEN FONTCONFIG IS UPDATED.
+	LOCAL CHANGES BELONG IN 'local.conf'.
+
+	The intent of this standard configuration file is to be adequate for
+	most environments.  If you have a reasonably normal environment and
+	have found problems with this configuration, they are probably
+	things that others will also want fixed.  Please submit any
+	problems to the fontconfig bugzilla system located at fontconfig.org
+
+	Note that the normal 'make install' procedure for fontconfig is to
+	replace any existing fonts.conf file with the new version.  Place
+	any local customizations in local.conf which this file references.
+
+	Keith Packard
+-->
+
+<!-- Font directory list -->
+
+	<dir>/usr/share/fonts</dir>
+	<dir>/usr/X11/lib/X11/fonts</dir> <dir>/Library/Fonts</dir> <dir>/Network/Library/Fonts</dir> <dir>/System/Library/Fonts</dir> <dir>/opt/local/share/fonts</dir>
+	<dir>~/.fonts</dir>
+
+<!--
+  Accept deprecated 'mono' alias, replacing it with 'monospace'
+-->
+	<match target="pattern">
+		<test qual="any" name="family">
+			<string>mono</string>
+		</test>
+		<edit name="family" mode="assign">
+			<string>monospace</string>
+		</edit>
+	</match>
+
+<!--
+  Accept alternate 'sans serif' spelling, replacing it with 'sans-serif'
+-->
+	<match target="pattern">
+		<test qual="any" name="family">
+			<string>sans serif</string>
+		</test>
+		<edit name="family" mode="assign">
+			<string>sans-serif</string>
+		</edit>
+	</match>
+
+<!--
+  Accept deprecated 'sans' alias, replacing it with 'sans-serif'
+-->
+	<match target="pattern">
+		<test qual="any" name="family">
+			<string>sans</string>
+		</test>
+		<edit name="family" mode="assign">
+			<string>sans-serif</string>
+		</edit>
+	</match>
+
+<!--
+  Load local system customization file
+-->
+	<include ignore_missing="yes">conf.d</include>
+
+<!-- Font cache directory list -->
+
+	<cachedir>~/.fontconfig</cachedir>
+
+	<config>
+<!--
+  These are the default Unicode chars that are expected to be blank
+  in fonts.  All other blank chars are assumed to be broken and
+  won't appear in the resulting charsets
+ -->
+		<blank>
+			<int>0x0020</int>	<!-- SPACE -->
+			<int>0x00A0</int>	<!-- NO-BREAK SPACE -->
+			<int>0x00AD</int>	<!-- SOFT HYPHEN -->
+			<int>0x034F</int>	<!-- COMBINING GRAPHEME JOINER -->
+			<int>0x0600</int>	<!-- ARABIC NUMBER SIGN -->
+			<int>0x0601</int>	<!-- ARABIC SIGN SANAH -->
+			<int>0x0602</int>	<!-- ARABIC FOOTNOTE MARKER -->
+			<int>0x0603</int>	<!-- ARABIC SIGN SAFHA -->
+			<int>0x06DD</int>	<!-- ARABIC END OF AYAH -->
+			<int>0x070F</int>	<!-- SYRIAC ABBREVIATION MARK -->
+			<int>0x115F</int>	<!-- HANGUL CHOSEONG FILLER -->
+			<int>0x1160</int>	<!-- HANGUL JUNGSEONG FILLER -->
+			<int>0x1680</int>	<!-- OGHAM SPACE MARK -->
+			<int>0x17B4</int>	<!-- KHMER VOWEL INHERENT AQ -->
+			<int>0x17B5</int>	<!-- KHMER VOWEL INHERENT AA -->
+			<int>0x180E</int>	<!-- MONGOLIAN VOWEL SEPARATOR -->
+			<int>0x2000</int>	<!-- EN QUAD -->
+			<int>0x2001</int>	<!-- EM QUAD -->
+			<int>0x2002</int>	<!-- EN SPACE -->
+			<int>0x2003</int>	<!-- EM SPACE -->
+			<int>0x2004</int>	<!-- THREE-PER-EM SPACE -->
+			<int>0x2005</int>	<!-- FOUR-PER-EM SPACE -->
+			<int>0x2006</int>	<!-- SIX-PER-EM SPACE -->
+			<int>0x2007</int>	<!-- FIGURE SPACE -->
+			<int>0x2008</int>	<!-- PUNCTUATION SPACE -->
+			<int>0x2009</int>	<!-- THIN SPACE -->
+			<int>0x200A</int>	<!-- HAIR SPACE -->
+			<int>0x200B</int>	<!-- ZERO WIDTH SPACE -->
+			<int>0x200C</int>	<!-- ZERO WIDTH NON-JOINER -->
+			<int>0x200D</int>	<!-- ZERO WIDTH JOINER -->
+			<int>0x200E</int>	<!-- LEFT-TO-RIGHT MARK -->
+			<int>0x200F</int>	<!-- RIGHT-TO-LEFT MARK -->
+			<int>0x2028</int>	<!-- LINE SEPARATOR -->
+			<int>0x2029</int>	<!-- PARAGRAPH SEPARATOR -->
+			<int>0x202A</int>	<!-- LEFT-TO-RIGHT EMBEDDING -->
+			<int>0x202B</int>	<!-- RIGHT-TO-LEFT EMBEDDING -->
+			<int>0x202C</int>	<!-- POP DIRECTIONAL FORMATTING -->
+			<int>0x202D</int>	<!-- LEFT-TO-RIGHT OVERRIDE -->
+			<int>0x202E</int>	<!-- RIGHT-TO-LEFT OVERRIDE -->
+			<int>0x202F</int>	<!-- NARROW NO-BREAK SPACE -->
+			<int>0x205F</int>	<!-- MEDIUM MATHEMATICAL SPACE -->
+			<int>0x2060</int>	<!-- WORD JOINER -->
+			<int>0x2061</int>	<!-- FUNCTION APPLICATION -->
+			<int>0x2062</int>	<!-- INVISIBLE TIMES -->
+			<int>0x2063</int>	<!-- INVISIBLE SEPARATOR -->
+			<int>0x206A</int>	<!-- INHIBIT SYMMETRIC SWAPPING -->
+			<int>0x206B</int>	<!-- ACTIVATE SYMMETRIC SWAPPING -->
+			<int>0x206C</int>	<!-- INHIBIT ARABIC FORM SHAPING -->
+			<int>0x206D</int>	<!-- ACTIVATE ARABIC FORM SHAPING -->
+			<int>0x206E</int>	<!-- NATIONAL DIGIT SHAPES -->
+			<int>0x206F</int>	<!-- NOMINAL DIGIT SHAPES -->
+			<int>0x2800</int>	<!-- BRAILLE PATTERN BLANK -->
+			<int>0x3000</int>	<!-- IDEOGRAPHIC SPACE -->
+			<int>0x3164</int>	<!-- HANGUL FILLER -->
+			<int>0xFEFF</int>	<!-- ZERO WIDTH NO-BREAK SPACE -->
+			<int>0xFFA0</int>	<!-- HALFWIDTH HANGUL FILLER -->
+			<int>0xFFF9</int>	<!-- INTERLINEAR ANNOTATION ANCHOR -->
+			<int>0xFFFA</int>	<!-- INTERLINEAR ANNOTATION SEPARATOR -->
+			<int>0xFFFB</int>	<!-- INTERLINEAR ANNOTATION TERMINATOR -->
+		</blank>
+<!--
+  Rescan configuration every 30 seconds when FcFontSetList is called
+ -->
+		<rescan>
+			<int>30</int>
+		</rescan>
+	</config>
+
+</fontconfig>
diff --git a/setup/data/osx/NetRadiant.app/Contents/MacOS/install/fonts.dtd b/setup/data/osx/NetRadiant.app/Contents/MacOS/install/fonts.dtd
new file mode 100755
index 00000000..cbdfdab3
--- /dev/null
+++ b/setup/data/osx/NetRadiant.app/Contents/MacOS/install/fonts.dtd
@@ -0,0 +1,224 @@
+<!-- This is the Document Type Definition for font configuration files -->
+<!ELEMENT fontconfig (dir | 
+		      cache | 
+		      cachedir |
+		      include | 
+		      config |
+		      selectfont |
+		      match | 
+		      alias)* >
+
+<!-- 
+    Add a directory that provides fonts
+-->
+<!ELEMENT dir (#PCDATA)>
+<!ATTLIST dir xml:space (default|preserve) 'preserve'>
+
+<!--
+    Define the per-user file that holds cache font information.
+
+    If the filename begins with '~', it is replaced with the users
+    home directory path.
+-->
+<!ELEMENT cache (#PCDATA)>
+<!ATTLIST cache xml:space (default|preserve) 'preserve'>
+
+<!--
+    Add a directory that is searched for font cache files.
+    These hold per-directory cache data and are searched in
+    order for each directory. When writing cache files, the first
+    directory which allows the cache file to be created is used.
+
+    A leading '~' in a directory name is replaced with the users
+    home directory path.
+-->
+<!ELEMENT cachedir (#PCDATA)>
+<!ATTLIST cachedir xml:space (default|preserve) 'preserve'>
+
+<!--
+    Reference another configuration file; note that this
+    is another complete font configuration file and not
+    just a file included by the XML parser.
+
+    Set 'ignore_missing' to 'yes' if errors are to be ignored.
+
+    If the filename begins with '~', it is replaced with the users
+    home directory path.
+-->
+<!ELEMENT include (#PCDATA)>
+<!ATTLIST include
+	  ignore_missing    (no|yes)		"no"
+	  xml:space	    (default|preserve)	"preserve">
+
+<!--
+    Global library configuration data
+ -->
+<!ELEMENT config (blank|rescan)*>
+
+<!--
+    Specify the set of Unicode encoding values which
+    represent glyphs that are allowed to contain no
+    data.  With this list, fontconfig can examine
+    fonts for broken glyphs and eliminate them from
+    the set of valid Unicode chars.  This idea
+    was borrowed from Mozilla
+ -->
+<!ELEMENT blank (int)*>
+
+<!--
+    Aliases are just a special case for multiple match elements
+
+    They are syntactically equivalent to:
+
+    <match>
+	<test name="family">
+	    <string value=[family]/>
+	</test>
+	<edit name="family" mode="prepend">
+	    <string value=[prefer]/>
+	    ...
+	</edit>
+	<edit name="family" mode="append">
+	    <string value=[accept]/>
+	    ...
+	</edit>
+	<edit name="family" mode="append_last">
+	    <string value=[default]/>
+	    ...
+	</edit>
+    </match>
+-->
+<!--
+    Periodically rescan the font configuration and
+    directories to synch internal state with filesystem
+ -->
+<!ELEMENT rescan (int)>
+
+<!--
+    Edit list of available fonts at startup/reload time
+ -->
+<!ELEMENT selectfont (rejectfont | acceptfont)* >
+
+<!ELEMENT rejectfont (glob | pattern)*>
+
+<!ELEMENT acceptfont (glob | pattern)*>
+
+<!ELEMENT glob (#PCDATA)>
+
+<!ELEMENT pattern (patelt)*>
+
+<!ENTITY % constant 'int|double|string|matrix|bool|charset|const'>
+
+<!ELEMENT patelt (%constant;)*>
+<!ATTLIST patelt
+	  name CDATA	#REQUIRED>
+
+<!ELEMENT alias (family*, prefer?, accept?, default?)>
+<!ATTLIST alias
+	  binding (weak|strong|same) "weak">
+<!ELEMENT prefer (family)*>
+<!ELEMENT accept (family)*>
+<!ELEMENT default (family)*>
+<!ELEMENT family (#PCDATA)>
+<!ATTLIST family xml:space (default|preserve) 'preserve'>
+
+<!ENTITY % expr 'int|double|string|matrix|bool|charset
+		|name|const
+		|or|and|eq|not_eq|less|less_eq|more|more_eq|contains|not_contains
+		|plus|minus|times|divide|not|if|floor|ceil|round|trunc'>
+
+<!--
+    Match and edit patterns.
+
+    If 'target' is 'pattern', execute the match before selecting a font.
+    if 'target' is 'font', execute the match on the result of a font
+    selection.
+-->
+<!ELEMENT match (test*, edit*)>
+<!ATTLIST match
+	  target (pattern|font|scan) "pattern">
+
+<!--
+    Match a field in a pattern
+
+    if 'qual' is 'any', then the match succeeds if any value in the field matches.
+    if 'qual' is 'all', then the match succeeds only if all values match.
+    if 'qual' is 'first', then the match succeeds only if the first value matches.
+    if 'qual' is 'not_first', then the match succeeds only if any value other than
+    	the first matches.
+    For match elements with target=font, if test 'target' is 'pattern',
+    then the test is applied to the pattern used in matching rather than
+    to the resulting font.
+
+    Match elements with target=scan are applied as fonts are scanned.
+    They edit the pattern generated from the scanned font and affect
+    what the fontconfig database contains.
+-->
+<!ELEMENT test (%expr;)*>
+<!ATTLIST test 
+	  qual (any|all|first|not_first)    "any"
+	  name CDATA	    #REQUIRED
+	  target (pattern|font|default)		"default"
+	  compare (eq|not_eq|less|less_eq|more|more_eq|contains|not_contains)	"eq">
+
+<!--
+    Edit a field in a pattern
+
+    The enclosed values are used together to edit the list of values
+    associated with 'name'.
+
+    If 'name' matches one of those used in a test element for this match element:
+	if 'mode' is 'assign', replace the matched value.
+	if 'mode' is 'assign_replace', replace all of the values
+	if 'mode' is 'prepend', insert before the matched value
+	if 'mode' is 'append', insert after the matched value
+	if 'mode' is 'prepend_first', insert before all of the values
+	if 'mode' is 'append_last', insert after all of the values
+    If 'name' doesn't match any of those used in a test element:
+	if 'mode' is 'assign' or 'assign_replace, replace all of the values
+	if 'mode' is 'prepend' or 'prepend_first', insert before all of the values
+	if 'mode' is 'append' or 'append_last', insert after all of the values
+-->
+<!ELEMENT edit (%expr;)*>
+<!ATTLIST edit
+	  name CDATA	    #REQUIRED
+	  mode (assign|assign_replace|prepend|append|prepend_first|append_last) "assign"
+	  binding (weak|strong|same) "weak">
+
+<!--
+    Elements of expressions follow
+-->
+<!ELEMENT int (#PCDATA)>
+<!ATTLIST int xml:space (default|preserve) 'preserve'>
+<!ELEMENT double (#PCDATA)>
+<!ATTLIST double xml:space (default|preserve) 'preserve'>
+<!ELEMENT string (#PCDATA)>
+<!ATTLIST string xml:space (default|preserve) 'preserve'>
+<!ELEMENT matrix (double,double,double,double)>
+<!ELEMENT bool (#PCDATA)>
+<!ELEMENT charset (#PCDATA)>
+<!ATTLIST charset xml:space (default|preserve) 'preserve'>
+<!ELEMENT name (#PCDATA)>
+<!ATTLIST name xml:space (default|preserve) 'preserve'>
+<!ELEMENT const (#PCDATA)>
+<!ATTLIST const xml:space (default|preserve) 'preserve'>
+<!ELEMENT or (%expr;)*>
+<!ELEMENT and (%expr;)*>
+<!ELEMENT eq ((%expr;), (%expr;))>
+<!ELEMENT not_eq ((%expr;), (%expr;))>
+<!ELEMENT less ((%expr;), (%expr;))>
+<!ELEMENT less_eq ((%expr;), (%expr;))>
+<!ELEMENT more ((%expr;), (%expr;))>
+<!ELEMENT more_eq ((%expr;), (%expr;))>
+<!ELEMENT contains ((%expr;), (%expr;))>
+<!ELEMENT not_contains ((%expr;), (%expr;))>
+<!ELEMENT plus (%expr;)*>
+<!ELEMENT minus (%expr;)*>
+<!ELEMENT times (%expr;)*>
+<!ELEMENT divide (%expr;)*>
+<!ELEMENT not (%expr;)>
+<!ELEMENT if ((%expr;), (%expr;), (%expr;))>
+<!ELEMENT floor (%expr;)>
+<!ELEMENT ceil (%expr;)>
+<!ELEMENT round (%expr;)>
+<!ELEMENT trunc (%expr;)>
diff --git a/setup/data/osx/NetRadiant.app/Contents/MacOS/netradiant.sh b/setup/data/osx/NetRadiant.app/Contents/MacOS/netradiant.sh
index 3df16e39..f4982522 100755
--- a/setup/data/osx/NetRadiant.app/Contents/MacOS/netradiant.sh
+++ b/setup/data/osx/NetRadiant.app/Contents/MacOS/netradiant.sh
@@ -1,16 +1 @@
-#!/bin/sh
-
-MY_DIRECTORY="${0%/*}" # cut off the script name
-MY_DIRECTORY="${MY_DIRECTORY%/*}" # cut off MacOS
-MY_DIRECTORY="${MY_DIRECTORY%/*}" # cut off Contents
-
-export DYLD_LIBRARY_PATH="$MY_DIRECTORY/Contents/MacOS/install"
-export PANGO_RC_FILE="$MY_DIRECTORY/Contents/MacOS/install/pangorc"
-export GDK_PIXBUF_MODULE_FILE="$MY_DIRECTORY/Contents/MacOS/install/gdk-pixbuf.loaders"
-
-cd "$MY_DIRECTORY/Contents/MacOS/install"
-if [ -x /usr/bin/open-x11 ]; then
-	/usr/bin/open-x11 ./radiant.ppc "$@" &
-else
-	./radiant.ppc "$@" &
-fi
+dummy for correct execute rights
\ No newline at end of file
diff --git a/setup/data/tools/plugins/bitmaps/bobtoolz_cleanup.bmp b/setup/data/tools/plugins/bitmaps/bobtoolz_cleanup.bmp
index 33cc9490..8939d5d7 100644
Binary files a/setup/data/tools/plugins/bitmaps/bobtoolz_cleanup.bmp and b/setup/data/tools/plugins/bitmaps/bobtoolz_cleanup.bmp differ
diff --git a/setup/data/tools/plugins/bitmaps/bobtoolz_merge.bmp b/setup/data/tools/plugins/bitmaps/bobtoolz_merge.bmp
index cc5e272c..2184f7a7 100644
Binary files a/setup/data/tools/plugins/bitmaps/bobtoolz_merge.bmp and b/setup/data/tools/plugins/bitmaps/bobtoolz_merge.bmp differ
diff --git a/setup/data/tools/plugins/bitmaps/bobtoolz_poly.bmp b/setup/data/tools/plugins/bitmaps/bobtoolz_poly.bmp
index ed720e90..e714f3b9 100644
Binary files a/setup/data/tools/plugins/bitmaps/bobtoolz_poly.bmp and b/setup/data/tools/plugins/bitmaps/bobtoolz_poly.bmp differ
diff --git a/setup/data/tools/plugins/bitmaps/bobtoolz_split.bmp b/setup/data/tools/plugins/bitmaps/bobtoolz_split.bmp
index fbb1571c..7e1dc72f 100644
Binary files a/setup/data/tools/plugins/bitmaps/bobtoolz_split.bmp and b/setup/data/tools/plugins/bitmaps/bobtoolz_split.bmp differ
diff --git a/setup/data/tools/plugins/bitmaps/bobtoolz_splitcol.bmp b/setup/data/tools/plugins/bitmaps/bobtoolz_splitcol.bmp
new file mode 100644
index 00000000..3d47fdcb
Binary files /dev/null and b/setup/data/tools/plugins/bitmaps/bobtoolz_splitcol.bmp differ
diff --git a/setup/data/tools/plugins/bitmaps/bobtoolz_splitrow.bmp b/setup/data/tools/plugins/bitmaps/bobtoolz_splitrow.bmp
new file mode 100644
index 00000000..03b1ae3a
Binary files /dev/null and b/setup/data/tools/plugins/bitmaps/bobtoolz_splitrow.bmp differ
diff --git a/setup/data/tools/plugins/bitmaps/bobtoolz_treeplanter.bmp b/setup/data/tools/plugins/bitmaps/bobtoolz_treeplanter.bmp
index 08f55f3c..5c967ab2 100644
Binary files a/setup/data/tools/plugins/bitmaps/bobtoolz_treeplanter.bmp and b/setup/data/tools/plugins/bitmaps/bobtoolz_treeplanter.bmp differ