--- sapphire-0.15.8.orig/menulex.hh
+++ sapphire-0.15.8/menulex.hh
@@ -1,64 +1,65 @@
-/*
- * Copyright (C) 1999,2000,2001 Frank Hale
- * frankhale@yahoo.com
- * http://sapphire.sourceforge.net/
- *
- * Updated: 3 Nov 2001
- *
- * 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 any later version.
- *
- * 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.
- */
-
-
-#ifndef _MENULEX_HH_
-#define _MENULEX_HH_
-
-class MenuLex : public Scanner
-{
-private: /* variables */
-
-	char* name;	// Name displayed in menu title
-	char* exe;	
-	
-	RootMenu *root;
-
-	LinkedList<BaseMenu> *menulist;
-
-	int submenus;
-
-	bool error;
-
-public: /* Constructor, Destructor and Member functions */
-	MenuLex(char *filename, RootMenu *menu);
-	~MenuLex();
-	
-	void parse();
-
-private: /* Member functions */
-	bool menu(bool validate);
-	bool exec(BaseMenu *sub, bool validate);
-	bool theme(BaseMenu *sub, bool validate);
-	bool submenu(BaseMenu *sub, bool validate);
-	bool separator(BaseMenu *sub, bool validate);
-	bool exit(BaseMenu* sub, bool validate);
-	bool restart(BaseMenu* sub, bool validate);
-	bool reconfigure(BaseMenu* sub, bool validate);
-	
-	BaseMenu* getMenu(int index);	
-	BaseMenu* getLastMenu();
-	
-	bool statement(BaseMenu *sub, bool validate);
-};
-
-#endif
+/*
+ * Copyright (C) 1999,2000,2001 Frank Hale
+ * frankhale@yahoo.com
+ * http://sapphire.sourceforge.net/
+ *
+ * Updated: 3 Nov 2001
+ *
+ * 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 any later version.
+ *
+ * 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.
+ */
+
+
+#ifndef _MENULEX_HH_
+#define _MENULEX_HH_
+
+class MenuLex : public Scanner
+{
+private: /* variables */
+
+	char* name;	// Name displayed in menu title
+	char* exe;	
+	
+	RootMenu *root;
+
+	LinkedList<BaseMenu> *menulist;
+
+	int submenus;
+
+	bool error;
+
+public: /* Constructor, Destructor and Member functions */
+	MenuLex(char *filename, RootMenu *menu);
+	~MenuLex();
+	
+	void parse();
+
+private: /* Member functions */
+	bool menu(bool validate);
+	bool exec(BaseMenu *sub, bool validate);
+	bool wmexec(BaseMenu *sub, bool validate);
+	bool theme(BaseMenu *sub, bool validate);
+	bool submenu(BaseMenu *sub, bool validate);
+	bool separator(BaseMenu *sub, bool validate);
+	bool exit(BaseMenu* sub, bool validate);
+	bool restart(BaseMenu* sub, bool validate);
+	bool reconfigure(BaseMenu* sub, bool validate);
+	
+	BaseMenu* getMenu(int index);	
+	BaseMenu* getLastMenu();
+	
+	bool statement(BaseMenu *sub, bool validate);
+};
+
+#endif
--- sapphire-0.15.8.orig/basemenu.cc
+++ sapphire-0.15.8/basemenu.cc
@@ -1,1085 +1,1085 @@
-/*
- * Copyright (C) 1999,2000,2001 Frank Hale
- * frankhale@yahoo.com
- * http://sapphire.sourceforge.net/
- *
- * Updated: 3 Nov 2001
- *
- * 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 any later version.
- *
- * 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.
- */
-
-
-#include "sapphire.hh"
-
-BaseMenu::BaseMenu() {
-
-	menu_pix=None;
-	select_pix=None;
-	title_pix=None;
-
-	select_gc = None;
-	menu_gc = None;
-	back_gc = None;
-
-	mi = new LinkedList<BaseMenuItem>;
-	
-	menu.menuTitle="Sapphire Menu";
-
-	menu.hasTitle=False;
-
-	bottom_edge=False;
-	right_edge=False;
-
-	counter=0;
-
-	extra_width=0;
-
-	font = XLoadQueryFont(wm->getDisplay(), wm->getTheme()->getMenuFont());
-	
-  	create_mask = CWBackPixmap       | 
-		      CWBackPixel        | 
-		      CWBorderPixel      |
-	    	      CWOverrideRedirect |
-		      CWEventMask; 
-		      
-  	attrib.background_pixmap = None;
-  	attrib.background_pixel = wm->getBackgroundColor().pixel;
-  	attrib.border_pixel = wm->getBorderColor().pixel;
-  	attrib.override_redirect = True;
-  	attrib.event_mask = ButtonPressMask   |
-	                    ButtonReleaseMask | 
-			    PointerMotionMask |
-    			    ExposureMask      |
-			    EnterWindowMask   |
-			    LeaveWindowMask;
-
-
-	//gv.background = wm->getBackgroundColor().pixel;	
-	//select_gc = XCreateGC(wm->getDisplay(), wm->getRootWindow(),  GCTile , &gv);
-	//back_gc = XCreateGC(wm->getDisplay(), wm->getRootWindow(),  GCTile, &gv);
-
-	menu.x = 1;
-  	menu.y = 1;
-	menu.x_move = 1;
-  	menu.y_move = 1;
-	menu.height=1;
-	menu.width=1;
-    
-	menu.total_item_height=1;
-    
-    	item_width = menu.width;
-	item_height = font->ascent + font->descent + 8;
-	
-	menu.window =
-    		XCreateWindow(wm->getDisplay(), wm->getRootWindow(), menu.x, menu.y,
-		  menu.width, menu.height, 1, DefaultDepth(wm->getDisplay(), wm->getScreen()),
-		  InputOutput, DefaultVisual(wm->getDisplay(), wm->getScreen()), create_mask, &attrib);
-
-	menu.title =
-    		XCreateWindow(wm->getDisplay(), menu.window, 0, 0,
-		  menu.width, item_height, 0, DefaultDepth(wm->getDisplay(), wm->getScreen()),
-		  InputOutput, DefaultVisual(wm->getDisplay(), wm->getScreen()), create_mask, &attrib);
-	
-	menu.item_window =	
-    		XCreateWindow(wm->getDisplay(), menu.window, 0, item_height - 2,
-		  menu.width, menu.height-item_height, 0, DefaultDepth(wm->getDisplay(), wm->getScreen()),
-		  InputOutput, DefaultVisual(wm->getDisplay(), wm->getScreen()), create_mask, &attrib);
-
-	curs = XDefineCursor(wm->getDisplay(), menu.window, XCreateFontCursor(wm->getDisplay(), XC_left_ptr));
-
-	
-	menu.isVisible = False;
-	
-	curr = new BaseMenuItem();
-	
-	curr = None;
-	
-	enterOnce = True;
-}
-
-BaseMenu::~BaseMenu() {			
-	mi->removeAll();
-
-	XDestroyWindow(wm->getDisplay(), menu.title);
-	XDestroyWindow(wm->getDisplay(), menu.item_window);
-	XDestroyWindow(wm->getDisplay(), menu.window);
-
-	XFreeGC(wm->getDisplay(), menu_gc);
-	XFreeGC(wm->getDisplay(), select_gc);
-	XFreeGC(wm->getDisplay(), back_gc);
-	
-	wm->getImageControl()->removeImage(title_pix);
-	wm->getImageControl()->removeImage(menu_pix);
-	wm->getImageControl()->removeImage(select_pix);
-	wm->getImageControl()->removeImage(menufont_pix);
-	
-	delete mi;
-	delete curr;
-}
-
-// This updates all graphics contexts, gradient pixmaps and determines placement of all menu items.
-void BaseMenu::update_all()
-{
-	LinkedListIterator<BaseMenuItem> it(mi);
-	
-	int temp_width=0;
-	int temp_ascent=0;
-	int temp_descent=0;
-	
-	unsigned int count=0;
-	unsigned int char_count=0;
-
-	menu.total_item_height=1;
-
-	// If menu is created with no items lets make a few defaults
-	// so things work out nice.
-	
-	if (mi->count() == 0)
-	{
-		char_count = strlen(menu.menuTitle);
-
-		menu.width = XTextWidth(wm->getXFont(), menu.menuTitle, strlen(menu.menuTitle));
-
-		XTextExtents(font, menu.menuTitle , char_count, &direction, &ascent, 
-		           &descent, &overall);	
-
-		temp_width  = overall.width;
-		temp_ascent = overall.ascent;
-		temp_descent= overall.descent;
-
-		menu.width = temp_width + 40;
-		item_width  = temp_ascent + temp_descent + 8;
-		menu.height = item_height;
-
-		menu.total_item_height = item_height+3;
-	
-	} else {
-
-	//=============================================================
-
-	for(; it.current(); it++)
-	{
-		char_count = strlen(it.current()->name);
-
-    		XTextExtents(font, it.current()->name , char_count, &direction, &ascent, 
-            		&descent, &overall);		
-
-		if (char_count < strlen(menu.menuTitle)) {
-		
-			char_count = strlen(menu.menuTitle);
-			
-			XTextExtents(font, menu.menuTitle , char_count, &direction, &ascent, 
-		           &descent, &overall);		
-		}
-	
-		if (char_count > count) {
-			count = char_count; 
-			temp_width  = overall.width;
-			temp_ascent = overall.ascent;
-			temp_descent= overall.descent;
-		}
-		
-		menu.width = temp_width + 40;
-		item_width  = temp_ascent + temp_descent + 8;
-		menu.height = item_height * mi->count();
-		
-		it.current()->item_x = item_width/2+4;
-		it.current()->item_y = item_height/2+4+menu.total_item_height;
-		
-		menu.total_item_height += item_height;
-	}
-
-	menu.total_item_height += item_height;
-	
-	}
-	
-	menu.width+=extra_width;
-
-	setTitleVisible(menu.hasTitle);	
-
-	createMenuImage();
-	createMenuSelectImage();
-	createMenuTitleImage();
-	createMenuFontImage();
-	
-	XClearWindow(wm->getDisplay(), menu.title);
-	XClearWindow(wm->getDisplay(), menu.item_window);
-			
-	XGCValues gv;
-	gv.tile = select_pix;
-	select_gc = XCreateGC(wm->getDisplay(), wm->getRootWindow(),  GCTile , &gv);
-	XSetFillStyle(wm->getDisplay(), select_gc, FillTiled);	
-	
-	gv.tile = menu_pix;
-	back_gc = XCreateGC(wm->getDisplay(), wm->getRootWindow(),  GCTile, &gv);
-	XSetFillStyle(wm->getDisplay(), back_gc, FillTiled);
-
-	gv.font = font->fid;
-	gv.tile = menufont_pix;
-	menu_gc = XCreateGC(wm->getDisplay(), wm->getRootWindow(),  GCTile | GCFont, &gv);
-	XSetFillStyle(wm->getDisplay(), menu_gc, FillTiled);
-	
-	testMenuEdgeDetect(this);
-	
-	if (menu.y + menu.height >= wm->getYRes()) 
-	{
-		bottom_edge=True;
- 	}else {
-				
-		bottom_edge=False;
-	}
-	
-	if(bottom_edge)
-	{
-		XMoveWindow(wm->getDisplay(), menu.window, menu.x, wm->getYRes() - menu.height - item_height - 4);
-	}
-}
-
-// This updates all graphics contexts, gradient pixmaps and determines placement of all menu items.
-void BaseMenu::update_menu()
-{
-	LinkedListIterator<BaseMenuItem> it(mi);
-	
-	int temp_width=0;
-	int temp_ascent=0;
-	int temp_descent=0;
-	
-	unsigned int count=0;
-	unsigned int char_count=0;
-
-	menu.total_item_height=1;
-
-	// If menu is created with no items lets make a few defaults
-	// so things work out nice.
-	
-	if (mi->count() == 0)
-	{
-		char_count = strlen(menu.menuTitle);
-
-		menu.width = XTextWidth(wm->getXFont(), menu.menuTitle, strlen(menu.menuTitle));
-
-		XTextExtents(font, menu.menuTitle , char_count, &direction, &ascent, 
-		           &descent, &overall);	
-
-		temp_width  = overall.width;
-		temp_ascent = overall.ascent;
-		temp_descent= overall.descent;
-
-		menu.width = temp_width + 40;
-		item_width  = temp_ascent + temp_descent + 8;
-		menu.height = item_height;
-
-		menu.total_item_height = item_height+3;
-	
-	} else {
-
-	//=============================================================
-
-	for(; it.current(); it++)
-	{
-		char_count = strlen(it.current()->name);
-
-    		XTextExtents(font, it.current()->name , char_count, &direction, &ascent, 
-            		&descent, &overall);		
-
-		if (char_count < strlen(menu.menuTitle)) {
-		
-			char_count = strlen(menu.menuTitle);
-			
-			XTextExtents(font, menu.menuTitle , char_count, &direction, &ascent, 
-		           &descent, &overall);		
-		}
-	
-		if (char_count > count) {
-			count = char_count; 
-			temp_width  = overall.width;
-			temp_ascent = overall.ascent;
-			temp_descent= overall.descent;
-		}
-		
-		menu.width = temp_width + 40;
-		item_width  = temp_ascent + temp_descent + 8;
-		menu.height = item_height * mi->count();
-		
-		it.current()->item_x = item_width/2+4;
-		it.current()->item_y = item_height/2+4+menu.total_item_height;
-		
-		menu.total_item_height += item_height;
-	}
-
-	menu.total_item_height += item_height;
-	
-	}
-
-	menu.width+=extra_width;
-	
-	setTitleVisible(menu.hasTitle);
-}
-
-void BaseMenu::hide()
-{
-	XUnmapWindow(wm->getDisplay(), menu.window);
-}
-
-void BaseMenu::setTitleVisible(bool s) 
-{ 	
-	menu.hasTitle=s; 
-		
-	if(menu.hasTitle)
-	{
-		XResizeWindow(wm->getDisplay(), menu.window, menu.width, menu.total_item_height);
-		XResizeWindow(wm->getDisplay(), menu.title, menu.width, item_height);
-		XMoveResizeWindow(wm->getDisplay(), menu.item_window, 
-				0,
-				item_height,
-				menu.width, 
-				menu.total_item_height);
-	
-	} else {
-		XResizeWindow(wm->getDisplay(), menu.window, menu.width, menu.total_item_height - item_height);
-		XResizeWindow(wm->getDisplay(), menu.title, menu.width, item_height);
-		XMoveResizeWindow(wm->getDisplay(), menu.item_window, 
-				0, 0,
-				menu.width, 	
-				menu.total_item_height);	
-	}
-}
-
-void BaseMenu::reconfigure()
-{	
-	XGCValues gv;
-
-	XFreeFont(wm->getDisplay(), font);
-	font = XLoadQueryFont(wm->getDisplay(),  wm->getTheme()->getMenuFont());
-	update_menu();
-	
-	XFreePixmap(wm->getDisplay(), title_pix);
-	XFreePixmap(wm->getDisplay(), menu_pix);
-	XFreePixmap(wm->getDisplay(), select_pix);
-	XFreePixmap(wm->getDisplay(), menufont_pix);
-
-	createMenuImage();
-	createMenuSelectImage();
-	createMenuTitleImage();
-	createMenuFontImage();
-	
-	XClearWindow(wm->getDisplay(), menu.title);
-	XClearWindow(wm->getDisplay(), menu.item_window);
-		
-	XFreeGC(wm->getDisplay(), menu_gc);
-	XFreeGC(wm->getDisplay(), select_gc);
-	XFreeGC(wm->getDisplay(), back_gc);
-		
-	gv.tile = select_pix;
-	select_gc = XCreateGC(wm->getDisplay(), wm->getRootWindow(),  GCTile , &gv);
-	XSetFillStyle(wm->getDisplay(), select_gc, FillTiled);	
-	
-	gv.tile = menu_pix;
-	back_gc = XCreateGC(wm->getDisplay(), wm->getRootWindow(),  GCTile, &gv);
-	XSetFillStyle(wm->getDisplay(), back_gc, FillTiled);
-
-	gv.font = font->fid;
-	gv.tile = menufont_pix;
-	menu_gc = XCreateGC(wm->getDisplay(), wm->getRootWindow(),  GCTile | GCFont, &gv);
-	XSetFillStyle(wm->getDisplay(), menu_gc, FillTiled);
-		
-	redraw();
-}
-
-// Redraws the entire contents of the menu.
-void BaseMenu::redraw()
-{
-	//int text_width=0;
-	
-	// We need an Iterator for our menu items. This lets us traverse through
-	// the list and paint each menu item.
-	LinkedListIterator<BaseMenuItem> it(mi);
-	
-	for(; it.current(); it++)
-	{	  				
-		if(strcmp(it.current()->name, "separator")==0) 
-		{
-			XDrawLine(wm->getDisplay(), menu.item_window, menu_gc, it.current()->item_x - 14, it.current()->item_y-5, menu.width-1, it.current()->item_y-5);	
-			XDrawLine(wm->getDisplay(), menu.item_window, menu_gc, it.current()->item_x - 14, it.current()->item_y-6, menu.width-1, it.current()->item_y-6);	
-		} else {
-		
-			XDrawString(wm->getDisplay(), menu.item_window, menu_gc, it.current()->item_x, 
-			it.current()->item_y + 2, it.current()->name, strlen(it.current()->name));
-			
-			if(it.current()->sub)
-			{
-				XDrawRectangle(wm->getDisplay(), menu.item_window, menu_gc, 
-					it.current()->item_x + menu.width - 35, 
-					it.current()->item_y - 7, 
-					8,
-					8);
-			}
-		}
-		
-		// Draws a bounding box around each menu item. This helped me figure out the algorithm to test which item the 
-		// pointer was over.
-		//
-		//XDrawRectangle(wm->getDisplay(), menu.item_window, menu_gc, it.current()->item_x - 14, it.current()->item_y - 14, menu.width-1, it.current()->item_y + item_height - 15);
-	
-	}
-	
-	XDrawString(wm->getDisplay(), menu.title, menu_gc, 
-   	   8, 16 , menu.menuTitle, strlen(menu.menuTitle));
-	
-	//text_width=XTextWidth(wm->font, menu.menuTitle, strlen(menu.menuTitle));
-
-	//XDrawString(wm->getDisplay(), menu.title, menu_gc, 
-   	//   menu.width/2 - text_width/2, 
-	//   14 , 
-	//   menu.menuTitle, strlen(menu.menuTitle));
-}
-
-// Redraws a single menu item on the menu.
-void BaseMenu::redraw(BaseMenuItem *i)
-{
-	if(strcmp(i->name, "separator")==0) 
-	{
-		XDrawLine(wm->getDisplay(), menu.item_window, menu_gc, i->item_x - 14, i->item_y-5, menu.width-1, i->item_y-5);
-		XDrawLine(wm->getDisplay(), menu.item_window, menu_gc, i->item_x - 14, i->item_y-6, menu.width-1, i->item_y-6);				
-	} else {
-	
-		XDrawString(wm->getDisplay(), menu.item_window, menu_gc, 
-		i->item_x, i->item_y + 2, i->name, strlen(i->name));
-		
-		if(i->sub)
-		{
-			XDrawRectangle(wm->getDisplay(), menu.item_window, menu_gc, 
-					i->item_x + menu.width - 35, 
-					i->item_y - 7, 
-					8, 
-					8);	
-		}
-		
-	}
-	
-	// Draws a bounding box around each menu item. This helped me figure out the algorithm to test which item the 
-	// pointer was over.
-	//
-	//XDrawRectangle(wm->getDisplay(), menu.item_window, menu_gc, it.current()->item_x - 14, it.current()->item_y - 14, menu.width-1, it.current()->item_y + item_height - 15);
-
-}
-
-void BaseMenu::insert(char *n, BaseMenu *sub)
-{
-	BaseMenuItem *item = new BaseMenuItem();
-		
-	item->name = new char[strlen(n)+1];	
-	strcpy(item->name, n);
-	
-	item->sub  = sub;
-
-	// defaults
-	item->isSelected=False;
-	item->exec = "";
-	item->function = 0;
-	item->item_x = item->item_y = 0;
-
-	mi->insert(item);
-}
-
-void BaseMenu::insert(char *n, char *exec, int func)
-{
-	BaseMenuItem *item = new BaseMenuItem();
-	
-	char *buffer = new char[100];
-        if (exec[0] == '~') 
-	{
-		sprintf(buffer, "%s%s", getenv("HOME"), exec+1);
-		strcpy(exec, buffer);
-	}
-	delete [] buffer;
-	
-	item->exec = new char[strlen(exec)+1];
-	strcpy(item->exec, exec);
-	
-	item->name = new char[strlen(n)+1];	
-	strcpy(item->name, n);
-	
-	item->function = func;
-
-	// defaults
-	item->isSelected=False;
-	item->sub  = None;
-	item->item_x = item->item_y = 0;
-
-	mi->insert(item);
-}
-
-
-void BaseMenu::insert(char *n, char *exec, BaseMenu *sub, int func)
-{
-	BaseMenuItem *item = new BaseMenuItem();
-	
-	char *buffer = new char[100];
-        if (exec[0] == '~') 
-	{
-		sprintf(buffer, "%s%s", getenv("HOME"), exec+1);
-		strcpy(exec, buffer);
-	}
-	delete [] buffer;
-	
-	item->exec = new char[strlen(exec)+1];
-	strcpy(item->exec, exec);
-	
-	item->name = new char[strlen(n)+1];	
-	strcpy(item->name, n);
-	
-	item->isSelected=False;
-	item->sub  = sub;
-	item->function = func;
-	item->item_x = item->item_y = 0;
-	
-	mi->insert(item);
-}
-
-int BaseMenu::remove(BaseMenuItem* element)
-{
-	mi->remove(element);
-
-	return mi->count();
-}
-
-void BaseMenu::removeAll()
-{
-	mi->removeAll();
-	
-	update_all();
-}
-
-void BaseMenu::execute(char *s)
-{
-	char command[strlen(s)+8];
-	
-	sprintf(command, "exec %s &", s);
-	system(command);
-}
-
-void BaseMenu::show()
-{	
-	int mouse_x=0;
-	int mouse_y=0;
-	
-	// Gets the coordinates of the mouse
-	getMousePosition(&mouse_x, &mouse_y);
-		
-	// Check to make sure menu will be displayed on the screen.
- 	if (mouse_x + menu.width > wm->getXRes()) {
- 		menu.x = wm->getXRes() - menu.width - 1;
-		
-		right_edge=True;
- 	} else {
-		menu.x = mouse_x;
-		
-		right_edge=False;
-	}
-	
-	if (mouse_y + menu.height > wm->getYRes()) {
-		menu.y = wm->getYRes() - menu.height - item_height - 4;
-		
-		bottom_edge=True;
- 	}else {
-		
-		menu.y = mouse_y;
-		
-		bottom_edge=False;
-	}
-	
-	// Move the menu to the position of the mouse pointer
-	XMoveWindow(wm->getDisplay(), menu.window, menu.x, menu.y);
-	
-	// Show the menu windows
-	XMapRaised(wm->getDisplay(), menu.window);
-	XMapSubwindows(wm->getDisplay(),menu.window);
-	
-	menu.isVisible=True;
-}
-
-void BaseMenu::getMousePosition(int *x, int *y)
-{
-	Window dw1=None;
-	Window dw2=None;
-	int t1=0;
-	int t2=0;
-	unsigned int t3=0;
-
-	XQueryPointer(wm->getDisplay(), wm->getRootWindow(), &dw1, &dw2, x, y, &t1, &t2, &t3);
-}
-
-void BaseMenu::show(int x, int y)
-{	
-	menu.x = x;
-	menu.y = y;
-
-	XMoveWindow(wm->getDisplay(), menu.window, x, y);
-	
-	// Show the menu windows
-	XMapSubwindows(wm->getDisplay(),menu.window);
-	XMapRaised(wm->getDisplay(), menu.window);
-
-	XClearWindow(wm->getDisplay(), menu.item_window);
-
-	menu.isVisible=True;
-}
-
-void BaseMenu::showSub(BaseMenu *sub, int x, int y)
-{
-	sub->menu.x = x;
-	sub->menu.y = y;
-	
-	XMoveWindow(wm->getDisplay(), sub->menu.window, x, y);
-		
-	// Show the menu windows
-	XMapSubwindows(wm->getDisplay(), sub->menu.window);
-	XMapRaised(wm->getDisplay(),  sub->menu.window);
-
-	sub->menu.isVisible=True;
-}
-
-void BaseMenu::hide(BaseMenu *sub)
-{
-	
-	if (sub->menu.isVisible)
-	{
-		// hide the menu windows
-		XUnmapSubwindows(wm->getDisplay(), sub->menu.window);
-		XUnmapWindow(wm->getDisplay(), sub->menu.window);
-
-		sub->menu.isVisible=False;
-	}
-	
-}
-
-BaseMenuItem *BaseMenu::findMenuItem(int x, int y)
-{
-	int item_xpos2=0;
-	int item_ypos2=0;
-	
-	if(mi->count()) 
-	{
-		LinkedListIterator<BaseMenuItem> it(mi);
-		for(; it.current(); it++)
-		{
-
-			// Draws a bounding box around each menu item. This helped me figure out the algorithm to test which item the 
-			// pointer was over.
-			//
-			//XDrawRectangle(wm->getDisplay(), menu.item_window, menu_gc, it.current()->item_x - 14, 
-			//	it.current()->item_y - 14, menu.width-1, it.current()->item_y + item_height - 15);
-
-
-			item_xpos2 = menu.width-1;
-			item_ypos2 = it.current()->item_y + item_height - 15;
-	  
-			if ( (x >= it.current()->item_x - 14) && 
-			     (x < item_xpos2) &&
-			     (y >= it.current()->item_y - 14) &&  
-			     (y < item_ypos2)
-			   ) 
-			    {
-			    	
-				    return it.current();
-			    }
-		}	
-	}
-
-	return NULL;
-}
-
-void BaseMenu::handle_button_press_event(XButtonEvent *e)
-{
-	switch (e->button) 
-	{
-			case Button1:
-			{
-				if(e->window == menu.title) move(); 
-				else if (curr) handle_button1_press(curr);
-			break;
-			}
-
-			case Button2:
-			{
-				if(curr) handle_button2_press(curr);
-			break;
-			}
-			
-			case Button3:
-			{
-				if (curr) handle_button3_press(curr);
-			break;
-			}
-	} 
-}
-
-void BaseMenu::handle_button_release_event(XButtonEvent *e)
-{
-	switch (e->button) {
-			case Button1:
-			{
-				if (curr) {
-	
-					handle_button1_release(curr);
-				
-					switch(	curr->function )
-					{
-						// function 1 is wm shutdown
-						case 1:
-						{
-							wm->quit_nicely();
-						}
-						break;
-							
-						case 2: // do nothing this is a menu separator
-						{
-						}
-						break;
-							
-						case 3: // This will start another window manager
-						{
-							//wm->start_another_windowmanager(curr->exec);
-						}
-						break;
-						
-						case 4: // restart Sapphire
-						{
-							wm->restart();
-						}
-						break;
-										
-						case 5: // reconfigure Sapphire (theme, menu)
-						{
-							wm->reconfigureMenu();
-						}
-						break;
-
-						case 6: // change theme 
-						{
-							Toolbar *t = wm->getToolbar();
-							t->setStartMenuButtonStateNotPressed();					
-							t->getToolbarMenu()->hide(t->getToolbarMenu());
-							
-							wm->getRootMenu()->hideAllVisibleSubmenus();
-							wm->changeTheme(curr->exec);
-						}
-						break;
-
-						default: // Default is to execute a command or file
-						{
-							Toolbar *t = wm->getToolbar();
-							t->setStartMenuButtonStateNotPressed();							
-							t->getToolbarMenu()->hide(t->getToolbarMenu()); 
-							wm->getRootMenu()->hideAllVisibleSubmenus();
-							execute(curr->exec);
-						}
-						break;
-					}										
-				}
-				
-			break;
-			}
-
-			case Button2:
-			{
-				if (curr) handle_button2_release(curr);
-			break;
-			}
-			
-			case Button3:
-			{
-				if(e->window == menu.title) hideAllVisibleSubmenus();
-				else if (curr) handle_button3_release(curr);
-			break;
-			}
-	} 
-}
-
-void BaseMenu::move()
-{
-	wm->setMenu(this);
-	wm->setMenuEvent(true);
-}
-
-void BaseMenu::setMenuPos(int x, int y)
-{
-	menu.x = x; 
-	menu.y = y;
-	
-	XMoveWindow(wm->getDisplay(), menu.window, x, y);
-}
-
-void BaseMenu::handle_enter_notify(XCrossingEvent *e)
-{
-	if(curr)
-	{					
-		LinkedList<BaseMenuItem> *temp_mi;
-
-		LinkedListIterator<BaseMenuItem> it(mi);
-		for(; it.current(); it++)
-		{	  	
-			if (it.current()->sub && it.current()->sub->menu.isVisible)
-			{
-				it.current()->sub->hide(it.current()->sub);
-				
-				temp_mi = it.current()->sub->mi;
-				
-				LOOP:
-				
-				LinkedListIterator<BaseMenuItem> n(temp_mi);
-				for(; n.current(); n++)
-				{
-					if(n.current()->sub && n.current()->sub->menu.isVisible)
-					{
-						n.current()->sub->hide(n.current()->sub);
-					
-						temp_mi = n.current()->sub->mi;
-						
-						goto LOOP;						
-					} 					
-				}
-			} 
-		}
-   		
-		XFillRectangle(wm->getDisplay(), menu.item_window, select_gc, 
-			0, 
-			curr->item_y - 15, 
-			item_width - item_height - 2, 
-			item_height - 1
-			);	 
-
-		if(curr->sub) 
-		{
-			testMenuEdgeDetect(curr->sub);
-			
-			if(curr->sub->right_edge) 
-			{
-				if(curr->sub->bottom_edge)
-					showSub(curr->sub,menu.x - curr->sub->menu.width - 1, wm->getYRes() - curr->sub->menu.height - 27);
-				else
-					showSub(curr->sub,menu.x - curr->sub->menu.width - 1, menu.y + curr->item_y - 15);
-			}
-			else {
-				if(curr->sub->bottom_edge)
-				{
-					showSub(curr->sub,menu.x + menu.width + 1, wm->getYRes() - curr->sub->menu.height - 27);
-				}
-				else {
-					showSub(curr->sub,menu.x + menu.width + 1, menu.y + curr->item_y - 15);
-				}
-			}
-		} 
-		redraw(curr);
-	}	
-}
-
-void BaseMenu::handle_leave_notify(XCrossingEvent *e)
-{
-	if(curr)
-	{	
-		XFillRectangle(wm->getDisplay(), menu.item_window, back_gc, 
-			0, 
-			curr->item_y -15, 
-			item_width - item_height - 2, 
-			item_height - 1);	 
-		
-		redraw(curr);
-		curr = NULL;			
-	}
-}
-
-void BaseMenu::hideAllVisibleSubmenus()
-{
-	LinkedList<BaseMenuItem> *temp_mi;
-	
-	hide(this);
-
-	LinkedListIterator<BaseMenuItem> it(mi);
-	for(; it.current(); it++)
-	{	  	
-		if (it.current()->sub && it.current()->sub->menu.isVisible)
-		{
-			it.current()->sub->hide(it.current()->sub);
-			
-			temp_mi = it.current()->sub->mi;
-			
-			LOOP: // Yuck I'm using a goto... ;-(
-				
-			LinkedListIterator<BaseMenuItem> n(temp_mi);
-			for(; n.current(); n++)
-			{
-				if(n.current()->sub && n.current()->sub->menu.isVisible)
-				{
-					n.current()->sub->hide(n.current()->sub);
-					
-					temp_mi = n.current()->sub->mi;
-						
-					goto LOOP;						
-				} 					
-			}
-		} 
-	}
-}
-
-void BaseMenu::setAllMenuTitlesVisible(BaseMenu *sub, bool s)
-{	
-	sub->setTitleVisible(s);
-
-	LinkedListIterator<BaseMenuItem> it(sub->mi);
-	for(; it.current(); it++)
-	{	  	
-		if (it.current()->sub) setAllMenuTitlesVisible(it.current()->sub, s);
-	}
-}
-
-void BaseMenu::handle_expose_event(XExposeEvent *e)
-{
-	if(e->count == 0) redraw();
-}
-
-void BaseMenu::handle_motion_notify_event(XMotionEvent *e)
-{
-	// for moving the menu.
-	menu.x_move = e->x;
-	menu.y_move = e->y;
-	
-	//----------------------
-	XEvent temp;	
-	
-	if(e->window == menu.title) { /* DO NOTHING */ }
-	else if(e->window == menu.item_window)
-	{
-		BaseMenuItem *i = findMenuItem(e->x, e->y);
-
-		if (i && enterOnce)
-		{
-			curr = i;
-
-			if(! strcmp(i->name, "separator")==0) handle_enter_notify(&temp.xcrossing);				
-
-			enterOnce=False;
-		} else {
-
-			
-			BaseMenuItem *i = findMenuItem(e->x, e->y);
-			
-			if (i != curr)
-			{
-				handle_leave_notify(&temp.xcrossing);
-			
-				curr =  i;
-				
-				enterOnce=True;
-			} 
-		}
-	}	
-}
-
-void BaseMenu::handle_config_notify_event(XConfigureEvent *e)
-{
-}
-
-void BaseMenu::createMenuImage()
-{
-	unsigned long style=0;
-
-	style = wm->getTheme()->getMenuStyle();		
-					
-	menu_pix = wm->getImageControl()->renderImage(
-			//"menu_frame",
-			menu.width, 
-			menu.height, 
-			style, 
-			wm->getTheme()->getMenuColorFrom(), 
-			wm->getTheme()->getMenuColorTo()
-			);
-	
-	XSetWindowBackgroundPixmap(wm->getDisplay(), menu.item_window, menu_pix);
-}
-
-void BaseMenu::createMenuSelectImage()
-{
-	unsigned long style=0;
-	
-	style = wm->getTheme()->getMenuSelectStyle();		
-
-	select_pix = wm->getImageControl()->renderImage(
-			//"menu_select",
-			menu.width, 
-			item_height, 
-			style, 
-			wm->getTheme()->getMenuSelectColorFrom(), 
-			wm->getTheme()->getMenuSelectColorTo()
-			);
-}
-
-void BaseMenu::createMenuFontImage()
-{
-	unsigned long style=0;
-	
-	style = wm->getTheme()->getFontStyle();		
-
-	menufont_pix = wm->getImageControl()->renderImage(
-			//"menu_font",
-			font->ascent, 
-			font->descent, 
-			style, 
-			wm->getTheme()->getMenuFontColorFrom(), 
-			wm->getTheme()->getMenuFontColorTo()
-			);
-}
-
-void BaseMenu::createMenuTitleImage()
-{
-	unsigned long style=0;
-
-	style = wm->getTheme()->getMenuTitleStyle();		
-
-	title_pix = wm->getImageControl()->renderImage(
-			//"menu_title",
-			menu.width, 
-			item_height+1, 
-			style, 
-			wm->getTheme()->getMenuTitleColorFrom(), 
-			wm->getTheme()->getMenuTitleColorTo()
-			);
-		
-	XSetWindowBackgroundPixmap(wm->getDisplay(), menu.title, title_pix);
-}
-
-void BaseMenu::testMenuEdgeDetect(BaseMenu *sub)
-{
-	int mouse_x=0;
-	int mouse_y=0;
-	
-	bool rightEdge=False;
-	bool bottomEdge=False;
-	
-	// Gets the coordinates of the mouse
-	getMousePosition(&mouse_x, &mouse_y);
-
-	rightEdge = ( ( this->menu.x + sub->menu.width + 150 ) < (wm->getXRes()) ) ? True : False;
-	
-	bottomEdge = ( mouse_y + sub->menu.height >= wm->getYRes() ) ? True : False;
-
-	// Check to make sure menu will be displayed on the screen.
-	if (rightEdge) sub->right_edge=False;
- 	else sub->right_edge=True;
-	
-	if (bottomEdge) sub->bottom_edge=True;
-	else sub->bottom_edge=False;
-}
+/*
+ * Copyright (C) 1999,2000,2001 Frank Hale
+ * frankhale@yahoo.com
+ * http://sapphire.sourceforge.net/
+ *
+ * Updated: 3 Nov 2001
+ *
+ * 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 any later version.
+ *
+ * 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.
+ */
+
+
+#include "sapphire.hh"
+
+BaseMenu::BaseMenu() {
+
+	menu_pix=None;
+	select_pix=None;
+	title_pix=None;
+
+	select_gc = None;
+	menu_gc = None;
+	back_gc = None;
+
+	mi = new LinkedList<BaseMenuItem>;
+	
+	menu.menuTitle="Sapphire Menu";
+
+	menu.hasTitle=False;
+
+	bottom_edge=False;
+	right_edge=False;
+
+	counter=0;
+
+	extra_width=0;
+
+	font = XLoadQueryFont(wm->getDisplay(), wm->getTheme()->getMenuFont());
+	
+  	create_mask = CWBackPixmap       | 
+		      CWBackPixel        | 
+		      CWBorderPixel      |
+	    	      CWOverrideRedirect |
+		      CWEventMask; 
+		      
+  	attrib.background_pixmap = None;
+  	attrib.background_pixel = wm->getBackgroundColor().pixel;
+  	attrib.border_pixel = wm->getBorderColor().pixel;
+  	attrib.override_redirect = True;
+  	attrib.event_mask = ButtonPressMask   |
+	                    ButtonReleaseMask | 
+			    PointerMotionMask |
+    			    ExposureMask      |
+			    EnterWindowMask   |
+			    LeaveWindowMask;
+
+
+	//gv.background = wm->getBackgroundColor().pixel;	
+	//select_gc = XCreateGC(wm->getDisplay(), wm->getRootWindow(),  GCTile , &gv);
+	//back_gc = XCreateGC(wm->getDisplay(), wm->getRootWindow(),  GCTile, &gv);
+
+	menu.x = 1;
+  	menu.y = 1;
+	menu.x_move = 1;
+  	menu.y_move = 1;
+	menu.height=1;
+	menu.width=1;
+    
+	menu.total_item_height=1;
+    
+    	item_width = menu.width;
+	item_height = font->ascent + font->descent + 8;
+	
+	menu.window =
+    		XCreateWindow(wm->getDisplay(), wm->getRootWindow(), menu.x, menu.y,
+		  menu.width, menu.height, 1, DefaultDepth(wm->getDisplay(), wm->getScreen()),
+		  InputOutput, DefaultVisual(wm->getDisplay(), wm->getScreen()), create_mask, &attrib);
+
+	menu.title =
+    		XCreateWindow(wm->getDisplay(), menu.window, 0, 0,
+		  menu.width, item_height, 0, DefaultDepth(wm->getDisplay(), wm->getScreen()),
+		  InputOutput, DefaultVisual(wm->getDisplay(), wm->getScreen()), create_mask, &attrib);
+	
+	menu.item_window =	
+    		XCreateWindow(wm->getDisplay(), menu.window, 0, item_height - 2,
+		  menu.width, menu.height-item_height, 0, DefaultDepth(wm->getDisplay(), wm->getScreen()),
+		  InputOutput, DefaultVisual(wm->getDisplay(), wm->getScreen()), create_mask, &attrib);
+
+	curs = XDefineCursor(wm->getDisplay(), menu.window, XCreateFontCursor(wm->getDisplay(), XC_left_ptr));
+
+	
+	menu.isVisible = False;
+	
+	curr = new BaseMenuItem();
+	
+	curr = None;
+	
+	enterOnce = True;
+}
+
+BaseMenu::~BaseMenu() {			
+	mi->removeAll();
+
+	XDestroyWindow(wm->getDisplay(), menu.title);
+	XDestroyWindow(wm->getDisplay(), menu.item_window);
+	XDestroyWindow(wm->getDisplay(), menu.window);
+
+	XFreeGC(wm->getDisplay(), menu_gc);
+	XFreeGC(wm->getDisplay(), select_gc);
+	XFreeGC(wm->getDisplay(), back_gc);
+	
+	wm->getImageControl()->removeImage(title_pix);
+	wm->getImageControl()->removeImage(menu_pix);
+	wm->getImageControl()->removeImage(select_pix);
+	wm->getImageControl()->removeImage(menufont_pix);
+	
+	delete mi;
+	delete curr;
+}
+
+// This updates all graphics contexts, gradient pixmaps and determines placement of all menu items.
+void BaseMenu::update_all()
+{
+	LinkedListIterator<BaseMenuItem> it(mi);
+	
+	int temp_width=0;
+	int temp_ascent=0;
+	int temp_descent=0;
+	
+	unsigned int count=0;
+	unsigned int char_count=0;
+
+	menu.total_item_height=1;
+
+	// If menu is created with no items lets make a few defaults
+	// so things work out nice.
+	
+	if (mi->count() == 0)
+	{
+		char_count = strlen(menu.menuTitle);
+
+		menu.width = XTextWidth(wm->getXFont(), menu.menuTitle, strlen(menu.menuTitle));
+
+		XTextExtents(font, menu.menuTitle , char_count, &direction, &ascent, 
+		           &descent, &overall);	
+
+		temp_width  = overall.width;
+		temp_ascent = overall.ascent;
+		temp_descent= overall.descent;
+
+		menu.width = temp_width + 40;
+		item_width  = temp_ascent + temp_descent + 8;
+		menu.height = item_height;
+
+		menu.total_item_height = item_height+3;
+	
+	} else {
+
+	//=============================================================
+
+	for(; it.current(); it++)
+	{
+		char_count = strlen(it.current()->name);
+
+    		XTextExtents(font, it.current()->name , char_count, &direction, &ascent, 
+            		&descent, &overall);		
+
+		if (char_count < strlen(menu.menuTitle)) {
+		
+			char_count = strlen(menu.menuTitle);
+			
+			XTextExtents(font, menu.menuTitle , char_count, &direction, &ascent, 
+		           &descent, &overall);		
+		}
+	
+		if (char_count > count) {
+			count = char_count; 
+			temp_width  = overall.width;
+			temp_ascent = overall.ascent;
+			temp_descent= overall.descent;
+		}
+		
+		menu.width = temp_width + 40;
+		item_width  = temp_ascent + temp_descent + 8;
+		menu.height = item_height * mi->count();
+		
+		it.current()->item_x = item_width/2+4;
+		it.current()->item_y = item_height/2+4+menu.total_item_height;
+		
+		menu.total_item_height += item_height;
+	}
+
+	menu.total_item_height += item_height;
+	
+	}
+	
+	menu.width+=extra_width;
+
+	setTitleVisible(menu.hasTitle);	
+
+	createMenuImage();
+	createMenuSelectImage();
+	createMenuTitleImage();
+	createMenuFontImage();
+	
+	XClearWindow(wm->getDisplay(), menu.title);
+	XClearWindow(wm->getDisplay(), menu.item_window);
+			
+	XGCValues gv;
+	gv.tile = select_pix;
+	select_gc = XCreateGC(wm->getDisplay(), wm->getRootWindow(),  GCTile , &gv);
+	XSetFillStyle(wm->getDisplay(), select_gc, FillTiled);	
+	
+	gv.tile = menu_pix;
+	back_gc = XCreateGC(wm->getDisplay(), wm->getRootWindow(),  GCTile, &gv);
+	XSetFillStyle(wm->getDisplay(), back_gc, FillTiled);
+
+	gv.font = font->fid;
+	gv.tile = menufont_pix;
+	menu_gc = XCreateGC(wm->getDisplay(), wm->getRootWindow(),  GCTile | GCFont, &gv);
+	XSetFillStyle(wm->getDisplay(), menu_gc, FillTiled);
+	
+	testMenuEdgeDetect(this);
+	
+	if (menu.y + menu.height >= wm->getYRes()) 
+	{
+		bottom_edge=True;
+ 	}else {
+				
+		bottom_edge=False;
+	}
+	
+	if(bottom_edge)
+	{
+		XMoveWindow(wm->getDisplay(), menu.window, menu.x, wm->getYRes() - menu.height - item_height - 4);
+	}
+}
+
+// This updates all graphics contexts, gradient pixmaps and determines placement of all menu items.
+void BaseMenu::update_menu()
+{
+	LinkedListIterator<BaseMenuItem> it(mi);
+	
+	int temp_width=0;
+	int temp_ascent=0;
+	int temp_descent=0;
+	
+	unsigned int count=0;
+	unsigned int char_count=0;
+
+	menu.total_item_height=1;
+
+	// If menu is created with no items lets make a few defaults
+	// so things work out nice.
+	
+	if (mi->count() == 0)
+	{
+		char_count = strlen(menu.menuTitle);
+
+		menu.width = XTextWidth(wm->getXFont(), menu.menuTitle, strlen(menu.menuTitle));
+
+		XTextExtents(font, menu.menuTitle , char_count, &direction, &ascent, 
+		           &descent, &overall);	
+
+		temp_width  = overall.width;
+		temp_ascent = overall.ascent;
+		temp_descent= overall.descent;
+
+		menu.width = temp_width + 40;
+		item_width  = temp_ascent + temp_descent + 8;
+		menu.height = item_height;
+
+		menu.total_item_height = item_height+3;
+	
+	} else {
+
+	//=============================================================
+
+	for(; it.current(); it++)
+	{
+		char_count = strlen(it.current()->name);
+
+    		XTextExtents(font, it.current()->name , char_count, &direction, &ascent, 
+            		&descent, &overall);		
+
+		if (char_count < strlen(menu.menuTitle)) {
+		
+			char_count = strlen(menu.menuTitle);
+			
+			XTextExtents(font, menu.menuTitle , char_count, &direction, &ascent, 
+		           &descent, &overall);		
+		}
+	
+		if (char_count > count) {
+			count = char_count; 
+			temp_width  = overall.width;
+			temp_ascent = overall.ascent;
+			temp_descent= overall.descent;
+		}
+		
+		menu.width = temp_width + 40;
+		item_width  = temp_ascent + temp_descent + 8;
+		menu.height = item_height * mi->count();
+		
+		it.current()->item_x = item_width/2+4;
+		it.current()->item_y = item_height/2+4+menu.total_item_height;
+		
+		menu.total_item_height += item_height;
+	}
+
+	menu.total_item_height += item_height;
+	
+	}
+
+	menu.width+=extra_width;
+	
+	setTitleVisible(menu.hasTitle);
+}
+
+void BaseMenu::hide()
+{
+	XUnmapWindow(wm->getDisplay(), menu.window);
+}
+
+void BaseMenu::setTitleVisible(bool s) 
+{ 	
+	menu.hasTitle=s; 
+		
+	if(menu.hasTitle)
+	{
+		XResizeWindow(wm->getDisplay(), menu.window, menu.width, menu.total_item_height);
+		XResizeWindow(wm->getDisplay(), menu.title, menu.width, item_height);
+		XMoveResizeWindow(wm->getDisplay(), menu.item_window, 
+				0,
+				item_height,
+				menu.width, 
+				menu.total_item_height);
+	
+	} else {
+		XResizeWindow(wm->getDisplay(), menu.window, menu.width, menu.total_item_height - item_height);
+		XResizeWindow(wm->getDisplay(), menu.title, menu.width, item_height);
+		XMoveResizeWindow(wm->getDisplay(), menu.item_window, 
+				0, 0,
+				menu.width, 	
+				menu.total_item_height);	
+	}
+}
+
+void BaseMenu::reconfigure()
+{	
+	XGCValues gv;
+
+	XFreeFont(wm->getDisplay(), font);
+	font = XLoadQueryFont(wm->getDisplay(),  wm->getTheme()->getMenuFont());
+	update_menu();
+	
+	XFreePixmap(wm->getDisplay(), title_pix);
+	XFreePixmap(wm->getDisplay(), menu_pix);
+	XFreePixmap(wm->getDisplay(), select_pix);
+	XFreePixmap(wm->getDisplay(), menufont_pix);
+
+	createMenuImage();
+	createMenuSelectImage();
+	createMenuTitleImage();
+	createMenuFontImage();
+	
+	XClearWindow(wm->getDisplay(), menu.title);
+	XClearWindow(wm->getDisplay(), menu.item_window);
+		
+	XFreeGC(wm->getDisplay(), menu_gc);
+	XFreeGC(wm->getDisplay(), select_gc);
+	XFreeGC(wm->getDisplay(), back_gc);
+		
+	gv.tile = select_pix;
+	select_gc = XCreateGC(wm->getDisplay(), wm->getRootWindow(),  GCTile , &gv);
+	XSetFillStyle(wm->getDisplay(), select_gc, FillTiled);	
+	
+	gv.tile = menu_pix;
+	back_gc = XCreateGC(wm->getDisplay(), wm->getRootWindow(),  GCTile, &gv);
+	XSetFillStyle(wm->getDisplay(), back_gc, FillTiled);
+
+	gv.font = font->fid;
+	gv.tile = menufont_pix;
+	menu_gc = XCreateGC(wm->getDisplay(), wm->getRootWindow(),  GCTile | GCFont, &gv);
+	XSetFillStyle(wm->getDisplay(), menu_gc, FillTiled);
+		
+	redraw();
+}
+
+// Redraws the entire contents of the menu.
+void BaseMenu::redraw()
+{
+	//int text_width=0;
+	
+	// We need an Iterator for our menu items. This lets us traverse through
+	// the list and paint each menu item.
+	LinkedListIterator<BaseMenuItem> it(mi);
+	
+	for(; it.current(); it++)
+	{	  				
+		if(strcmp(it.current()->name, "separator")==0) 
+		{
+			XDrawLine(wm->getDisplay(), menu.item_window, menu_gc, it.current()->item_x - 14, it.current()->item_y-5, menu.width-1, it.current()->item_y-5);	
+			XDrawLine(wm->getDisplay(), menu.item_window, menu_gc, it.current()->item_x - 14, it.current()->item_y-6, menu.width-1, it.current()->item_y-6);	
+		} else {
+		
+			XDrawString(wm->getDisplay(), menu.item_window, menu_gc, it.current()->item_x, 
+			it.current()->item_y + 2, it.current()->name, strlen(it.current()->name));
+			
+			if(it.current()->sub)
+			{
+				XDrawRectangle(wm->getDisplay(), menu.item_window, menu_gc, 
+					it.current()->item_x + menu.width - 35, 
+					it.current()->item_y - 7, 
+					8,
+					8);
+			}
+		}
+		
+		// Draws a bounding box around each menu item. This helped me figure out the algorithm to test which item the 
+		// pointer was over.
+		//
+		//XDrawRectangle(wm->getDisplay(), menu.item_window, menu_gc, it.current()->item_x - 14, it.current()->item_y - 14, menu.width-1, it.current()->item_y + item_height - 15);
+	
+	}
+	
+	XDrawString(wm->getDisplay(), menu.title, menu_gc, 
+   	   8, 16 , menu.menuTitle, strlen(menu.menuTitle));
+	
+	//text_width=XTextWidth(wm->font, menu.menuTitle, strlen(menu.menuTitle));
+
+	//XDrawString(wm->getDisplay(), menu.title, menu_gc, 
+   	//   menu.width/2 - text_width/2, 
+	//   14 , 
+	//   menu.menuTitle, strlen(menu.menuTitle));
+}
+
+// Redraws a single menu item on the menu.
+void BaseMenu::redraw(BaseMenuItem *i)
+{
+	if(strcmp(i->name, "separator")==0) 
+	{
+		XDrawLine(wm->getDisplay(), menu.item_window, menu_gc, i->item_x - 14, i->item_y-5, menu.width-1, i->item_y-5);
+		XDrawLine(wm->getDisplay(), menu.item_window, menu_gc, i->item_x - 14, i->item_y-6, menu.width-1, i->item_y-6);				
+	} else {
+	
+		XDrawString(wm->getDisplay(), menu.item_window, menu_gc, 
+		i->item_x, i->item_y + 2, i->name, strlen(i->name));
+		
+		if(i->sub)
+		{
+			XDrawRectangle(wm->getDisplay(), menu.item_window, menu_gc, 
+					i->item_x + menu.width - 35, 
+					i->item_y - 7, 
+					8, 
+					8);	
+		}
+		
+	}
+	
+	// Draws a bounding box around each menu item. This helped me figure out the algorithm to test which item the 
+	// pointer was over.
+	//
+	//XDrawRectangle(wm->getDisplay(), menu.item_window, menu_gc, it.current()->item_x - 14, it.current()->item_y - 14, menu.width-1, it.current()->item_y + item_height - 15);
+
+}
+
+void BaseMenu::insert(char *n, BaseMenu *sub)
+{
+	BaseMenuItem *item = new BaseMenuItem();
+		
+	item->name = new char[strlen(n)+1];	
+	strcpy(item->name, n);
+	
+	item->sub  = sub;
+
+	// defaults
+	item->isSelected=False;
+	item->exec = "";
+	item->function = 0;
+	item->item_x = item->item_y = 0;
+
+	mi->insert(item);
+}
+
+void BaseMenu::insert(char *n, char *exec, int func)
+{
+	BaseMenuItem *item = new BaseMenuItem();
+	
+	char *buffer = new char[100];
+        if (exec[0] == '~') 
+	{
+		sprintf(buffer, "%s%s", getenv("HOME"), exec+1);
+		strcpy(exec, buffer);
+	}
+	delete [] buffer;
+	
+	item->exec = new char[strlen(exec)+1];
+	strcpy(item->exec, exec);
+	
+	item->name = new char[strlen(n)+1];	
+	strcpy(item->name, n);
+	
+	item->function = func;
+
+	// defaults
+	item->isSelected=False;
+	item->sub  = None;
+	item->item_x = item->item_y = 0;
+
+	mi->insert(item);
+}
+
+
+void BaseMenu::insert(char *n, char *exec, BaseMenu *sub, int func)
+{
+	BaseMenuItem *item = new BaseMenuItem();
+	
+	char *buffer = new char[100];
+        if (exec[0] == '~') 
+	{
+		sprintf(buffer, "%s%s", getenv("HOME"), exec+1);
+		strcpy(exec, buffer);
+	}
+	delete [] buffer;
+	
+	item->exec = new char[strlen(exec)+1];
+	strcpy(item->exec, exec);
+	
+	item->name = new char[strlen(n)+1];	
+	strcpy(item->name, n);
+	
+	item->isSelected=False;
+	item->sub  = sub;
+	item->function = func;
+	item->item_x = item->item_y = 0;
+	
+	mi->insert(item);
+}
+
+int BaseMenu::remove(BaseMenuItem* element)
+{
+	mi->remove(element);
+
+	return mi->count();
+}
+
+void BaseMenu::removeAll()
+{
+	mi->removeAll();
+	
+	update_all();
+}
+
+void BaseMenu::execute(char *s)
+{
+	char command[strlen(s)+8];
+	
+	sprintf(command, "exec %s &", s);
+	system(command);
+}
+
+void BaseMenu::show()
+{	
+	int mouse_x=0;
+	int mouse_y=0;
+	
+	// Gets the coordinates of the mouse
+	getMousePosition(&mouse_x, &mouse_y);
+		
+	// Check to make sure menu will be displayed on the screen.
+ 	if (mouse_x + menu.width > wm->getXRes()) {
+ 		menu.x = wm->getXRes() - menu.width - 1;
+		
+		right_edge=True;
+ 	} else {
+		menu.x = mouse_x;
+		
+		right_edge=False;
+	}
+	
+	if (mouse_y + menu.height > wm->getYRes()) {
+		menu.y = wm->getYRes() - menu.height - item_height - 4;
+		
+		bottom_edge=True;
+ 	}else {
+		
+		menu.y = mouse_y;
+		
+		bottom_edge=False;
+	}
+	
+	// Move the menu to the position of the mouse pointer
+	XMoveWindow(wm->getDisplay(), menu.window, menu.x, menu.y);
+	
+	// Show the menu windows
+	XMapRaised(wm->getDisplay(), menu.window);
+	XMapSubwindows(wm->getDisplay(),menu.window);
+	
+	menu.isVisible=True;
+}
+
+void BaseMenu::getMousePosition(int *x, int *y)
+{
+	Window dw1=None;
+	Window dw2=None;
+	int t1=0;
+	int t2=0;
+	unsigned int t3=0;
+
+	XQueryPointer(wm->getDisplay(), wm->getRootWindow(), &dw1, &dw2, x, y, &t1, &t2, &t3);
+}
+
+void BaseMenu::show(int x, int y)
+{	
+	menu.x = x;
+	menu.y = y;
+
+	XMoveWindow(wm->getDisplay(), menu.window, x, y);
+	
+	// Show the menu windows
+	XMapSubwindows(wm->getDisplay(),menu.window);
+	XMapRaised(wm->getDisplay(), menu.window);
+
+	XClearWindow(wm->getDisplay(), menu.item_window);
+
+	menu.isVisible=True;
+}
+
+void BaseMenu::showSub(BaseMenu *sub, int x, int y)
+{
+	sub->menu.x = x;
+	sub->menu.y = y;
+	
+	XMoveWindow(wm->getDisplay(), sub->menu.window, x, y);
+		
+	// Show the menu windows
+	XMapSubwindows(wm->getDisplay(), sub->menu.window);
+	XMapRaised(wm->getDisplay(),  sub->menu.window);
+
+	sub->menu.isVisible=True;
+}
+
+void BaseMenu::hide(BaseMenu *sub)
+{
+	
+	if (sub->menu.isVisible)
+	{
+		// hide the menu windows
+		XUnmapSubwindows(wm->getDisplay(), sub->menu.window);
+		XUnmapWindow(wm->getDisplay(), sub->menu.window);
+
+		sub->menu.isVisible=False;
+	}
+	
+}
+
+BaseMenuItem *BaseMenu::findMenuItem(int x, int y)
+{
+	int item_xpos2=0;
+	int item_ypos2=0;
+	
+	if(mi->count()) 
+	{
+		LinkedListIterator<BaseMenuItem> it(mi);
+		for(; it.current(); it++)
+		{
+
+			// Draws a bounding box around each menu item. This helped me figure out the algorithm to test which item the 
+			// pointer was over.
+			//
+			//XDrawRectangle(wm->getDisplay(), menu.item_window, menu_gc, it.current()->item_x - 14, 
+			//	it.current()->item_y - 14, menu.width-1, it.current()->item_y + item_height - 15);
+
+
+			item_xpos2 = menu.width-1;
+			item_ypos2 = it.current()->item_y + item_height - 15;
+	  
+			if ( (x >= it.current()->item_x - 14) && 
+			     (x < item_xpos2) &&
+			     (y >= it.current()->item_y - 14) &&  
+			     (y < item_ypos2)
+			   ) 
+			    {
+			    	
+				    return it.current();
+			    }
+		}	
+	}
+
+	return NULL;
+}
+
+void BaseMenu::handle_button_press_event(XButtonEvent *e)
+{
+	switch (e->button) 
+	{
+			case Button1:
+			{
+				if(e->window == menu.title) move(); 
+				else if (curr) handle_button1_press(curr);
+			break;
+			}
+
+			case Button2:
+			{
+				if(curr) handle_button2_press(curr);
+			break;
+			}
+			
+			case Button3:
+			{
+				if (curr) handle_button3_press(curr);
+			break;
+			}
+	} 
+}
+
+void BaseMenu::handle_button_release_event(XButtonEvent *e)
+{
+	switch (e->button) {
+			case Button1:
+			{
+				if (curr) {
+	
+					handle_button1_release(curr);
+				
+					switch(	curr->function )
+					{
+						// function 1 is wm shutdown
+						case 1:
+						{
+							wm->quit_nicely();
+						}
+						break;
+							
+						case 2: // do nothing this is a menu separator
+						{
+						}
+						break;
+							
+						case 3: // This will start another window manager
+						{
+							wm->start_another_windowmanager(curr->exec);
+						}
+						break;
+						
+						case 4: // restart Sapphire
+						{
+							wm->restart();
+						}
+						break;
+										
+						case 5: // reconfigure Sapphire (theme, menu)
+						{
+							wm->reconfigureMenu();
+						}
+						break;
+
+						case 6: // change theme 
+						{
+							Toolbar *t = wm->getToolbar();
+							t->setStartMenuButtonStateNotPressed();					
+							t->getToolbarMenu()->hide(t->getToolbarMenu());
+							
+							wm->getRootMenu()->hideAllVisibleSubmenus();
+							wm->changeTheme(curr->exec);
+						}
+						break;
+
+						default: // Default is to execute a command or file
+						{
+							Toolbar *t = wm->getToolbar();
+							t->setStartMenuButtonStateNotPressed();							
+							t->getToolbarMenu()->hide(t->getToolbarMenu()); 
+							wm->getRootMenu()->hideAllVisibleSubmenus();
+							execute(curr->exec);
+						}
+						break;
+					}										
+				}
+				
+			break;
+			}
+
+			case Button2:
+			{
+				if (curr) handle_button2_release(curr);
+			break;
+			}
+			
+			case Button3:
+			{
+				if(e->window == menu.title) hideAllVisibleSubmenus();
+				else if (curr) handle_button3_release(curr);
+			break;
+			}
+	} 
+}
+
+void BaseMenu::move()
+{
+	wm->setMenu(this);
+	wm->setMenuEvent(true);
+}
+
+void BaseMenu::setMenuPos(int x, int y)
+{
+	menu.x = x; 
+	menu.y = y;
+	
+	XMoveWindow(wm->getDisplay(), menu.window, x, y);
+}
+
+void BaseMenu::handle_enter_notify(XCrossingEvent *e)
+{
+	if(curr)
+	{					
+		LinkedList<BaseMenuItem> *temp_mi;
+
+		LinkedListIterator<BaseMenuItem> it(mi);
+		for(; it.current(); it++)
+		{	  	
+			if (it.current()->sub && it.current()->sub->menu.isVisible)
+			{
+				it.current()->sub->hide(it.current()->sub);
+				
+				temp_mi = it.current()->sub->mi;
+				
+				LOOP:
+				
+				LinkedListIterator<BaseMenuItem> n(temp_mi);
+				for(; n.current(); n++)
+				{
+					if(n.current()->sub && n.current()->sub->menu.isVisible)
+					{
+						n.current()->sub->hide(n.current()->sub);
+					
+						temp_mi = n.current()->sub->mi;
+						
+						goto LOOP;						
+					} 					
+				}
+			} 
+		}
+   		
+		XFillRectangle(wm->getDisplay(), menu.item_window, select_gc, 
+			0, 
+			curr->item_y - 15, 
+			item_width - item_height - 2, 
+			item_height - 1
+			);	 
+
+		if(curr->sub) 
+		{
+			testMenuEdgeDetect(curr->sub);
+			
+			if(curr->sub->right_edge) 
+			{
+				if(curr->sub->bottom_edge)
+					showSub(curr->sub,menu.x - curr->sub->menu.width - 1, wm->getYRes() - curr->sub->menu.height - 27);
+				else
+					showSub(curr->sub,menu.x - curr->sub->menu.width - 1, menu.y + curr->item_y - 15);
+			}
+			else {
+				if(curr->sub->bottom_edge)
+				{
+					showSub(curr->sub,menu.x + menu.width + 1, wm->getYRes() - curr->sub->menu.height - 27);
+				}
+				else {
+					showSub(curr->sub,menu.x + menu.width + 1, menu.y + curr->item_y - 15);
+				}
+			}
+		} 
+		redraw(curr);
+	}	
+}
+
+void BaseMenu::handle_leave_notify(XCrossingEvent *e)
+{
+	if(curr)
+	{	
+		XFillRectangle(wm->getDisplay(), menu.item_window, back_gc, 
+			0, 
+			curr->item_y -15, 
+			item_width - item_height - 2, 
+			item_height - 1);	 
+		
+		redraw(curr);
+		curr = NULL;			
+	}
+}
+
+void BaseMenu::hideAllVisibleSubmenus()
+{
+	LinkedList<BaseMenuItem> *temp_mi;
+	
+	hide(this);
+
+	LinkedListIterator<BaseMenuItem> it(mi);
+	for(; it.current(); it++)
+	{	  	
+		if (it.current()->sub && it.current()->sub->menu.isVisible)
+		{
+			it.current()->sub->hide(it.current()->sub);
+			
+			temp_mi = it.current()->sub->mi;
+			
+			LOOP: // Yuck I'm using a goto... ;-(
+				
+			LinkedListIterator<BaseMenuItem> n(temp_mi);
+			for(; n.current(); n++)
+			{
+				if(n.current()->sub && n.current()->sub->menu.isVisible)
+				{
+					n.current()->sub->hide(n.current()->sub);
+					
+					temp_mi = n.current()->sub->mi;
+						
+					goto LOOP;						
+				} 					
+			}
+		} 
+	}
+}
+
+void BaseMenu::setAllMenuTitlesVisible(BaseMenu *sub, bool s)
+{	
+	sub->setTitleVisible(s);
+
+	LinkedListIterator<BaseMenuItem> it(sub->mi);
+	for(; it.current(); it++)
+	{	  	
+		if (it.current()->sub) setAllMenuTitlesVisible(it.current()->sub, s);
+	}
+}
+
+void BaseMenu::handle_expose_event(XExposeEvent *e)
+{
+	if(e->count == 0) redraw();
+}
+
+void BaseMenu::handle_motion_notify_event(XMotionEvent *e)
+{
+	// for moving the menu.
+	menu.x_move = e->x;
+	menu.y_move = e->y;
+	
+	//----------------------
+	XEvent temp;	
+	
+	if(e->window == menu.title) { /* DO NOTHING */ }
+	else if(e->window == menu.item_window)
+	{
+		BaseMenuItem *i = findMenuItem(e->x, e->y);
+
+		if (i && enterOnce)
+		{
+			curr = i;
+
+			if(! strcmp(i->name, "separator")==0) handle_enter_notify(&temp.xcrossing);				
+
+			enterOnce=False;
+		} else {
+
+			
+			BaseMenuItem *i = findMenuItem(e->x, e->y);
+			
+			if (i != curr)
+			{
+				handle_leave_notify(&temp.xcrossing);
+			
+				curr =  i;
+				
+				enterOnce=True;
+			} 
+		}
+	}	
+}
+
+void BaseMenu::handle_config_notify_event(XConfigureEvent *e)
+{
+}
+
+void BaseMenu::createMenuImage()
+{
+	unsigned long style=0;
+
+	style = wm->getTheme()->getMenuStyle();		
+					
+	menu_pix = wm->getImageControl()->renderImage(
+			//"menu_frame",
+			menu.width, 
+			menu.height, 
+			style, 
+			wm->getTheme()->getMenuColorFrom(), 
+			wm->getTheme()->getMenuColorTo()
+			);
+	
+	XSetWindowBackgroundPixmap(wm->getDisplay(), menu.item_window, menu_pix);
+}
+
+void BaseMenu::createMenuSelectImage()
+{
+	unsigned long style=0;
+	
+	style = wm->getTheme()->getMenuSelectStyle();		
+
+	select_pix = wm->getImageControl()->renderImage(
+			//"menu_select",
+			menu.width, 
+			item_height, 
+			style, 
+			wm->getTheme()->getMenuSelectColorFrom(), 
+			wm->getTheme()->getMenuSelectColorTo()
+			);
+}
+
+void BaseMenu::createMenuFontImage()
+{
+	unsigned long style=0;
+	
+	style = wm->getTheme()->getFontStyle();		
+
+	menufont_pix = wm->getImageControl()->renderImage(
+			//"menu_font",
+			font->ascent, 
+			font->descent, 
+			style, 
+			wm->getTheme()->getMenuFontColorFrom(), 
+			wm->getTheme()->getMenuFontColorTo()
+			);
+}
+
+void BaseMenu::createMenuTitleImage()
+{
+	unsigned long style=0;
+
+	style = wm->getTheme()->getMenuTitleStyle();		
+
+	title_pix = wm->getImageControl()->renderImage(
+			//"menu_title",
+			menu.width, 
+			item_height+1, 
+			style, 
+			wm->getTheme()->getMenuTitleColorFrom(), 
+			wm->getTheme()->getMenuTitleColorTo()
+			);
+		
+	XSetWindowBackgroundPixmap(wm->getDisplay(), menu.title, title_pix);
+}
+
+void BaseMenu::testMenuEdgeDetect(BaseMenu *sub)
+{
+	int mouse_x=0;
+	int mouse_y=0;
+	
+	bool rightEdge=False;
+	bool bottomEdge=False;
+	
+	// Gets the coordinates of the mouse
+	getMousePosition(&mouse_x, &mouse_y);
+
+	rightEdge = ( ( this->menu.x + sub->menu.width + 150 ) < (wm->getXRes()) ) ? True : False;
+	
+	bottomEdge = ( mouse_y + sub->menu.height >= wm->getYRes() ) ? True : False;
+
+	// Check to make sure menu will be displayed on the screen.
+	if (rightEdge) sub->right_edge=False;
+ 	else sub->right_edge=True;
+	
+	if (bottomEdge) sub->bottom_edge=True;
+	else sub->bottom_edge=False;
+}
--- sapphire-0.15.8.orig/windowmanager.hh
+++ sapphire-0.15.8/windowmanager.hh
@@ -1,216 +1,217 @@
-/*
- * Copyright (C) 1999,2000,2001 Frank Hale
- * frankhale@yahoo.com
- * http://sapphire.sourceforge.net/
- *
- * Updated: 3 Nov 2001
- *
- * 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 any later version.
- *
- * 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.
- */
-
-
-#ifndef _WM_HH_
-#define _WM_HH_
-
-#include "sapphire.hh"
-
-class WindowManager 
-{
-
-private: /* variables */
-
-	LinkedList<BaseMenu> *menulist;
-	LinkedList<BaseMenu> *extramenulist;
-	LinkedList<Client>   *ClientList;
-
-	Client		*head_client;	
-
-	Toolbar  	*t;
-	IconMenu 	*im;
-	RootMenu 	*rm;	
-	Theme 	 	*theme;
-	BImageControl 	*image_control;
-	BaseMenu 	*menu;
-
-	Atom		xa_wm_state;
-	Atom		xa_wm_change_state;
-	Atom		xa_wm_protos;
-        Atom		xa_wm_delete;
-	Atom		xa_wm_cmapwins;
-	Atom		xa_wm_take_focus;
-	Atom		xa_wm_motif_hints;
-
-	Window		root;
-	
-	Display		*dpy;
-	
-	Visual 		*visual;
-	
-	Pixmap		font_pix;
-		
-	XFontStruct	*xfont;	
-
-	XGCValues 	gv;
-	
-	XColor		xforeground_color;
-	XColor		xbackground_color; 
-	XColor		xborder_color;
-
-	GC		invert_gc;
-	GC		string_gc;
-	GC		border_gc;
-
-	Cursor		move_curs;
-	Cursor		resize_curs;
-	Cursor		left_arrow;
-	
-	char 		*display;
-	char 		*font;
-	char 		*menufont;
-	char 		*foreground_color;
-	char 		*background_color;
-	char 		*border_color;
-
-	int		depth;
-	int		xres;
-	int 		yres;
-	int		shape_event;
-	int 		colors_per_channel;
-	int 		toolbar_position;
-	int 		toolbar_visible;
-	int		screen;
-	int		iheight;
-	int 		font_position;
-
-	bool 		image_dither;
-	bool		shape;
-	bool 		menu_event;
-
-	// Configuration file stuff
-        char		*clock_format;
-	char		*configurationPath;
-	char		*windowmanager_conf;
-
-	static KeySym 	AltKeys[];
-public: 
-
-	// member functions below
-	
-	WindowManager(int argc, char **argv);
-	~WindowManager();
-
-	XColor 	getBorderColor()     	const { return xborder_color; }
-	XColor 	getForegroundColor() 	const { return xforeground_color; }
-	XColor 	getBackgroundColor() 	const { return xbackground_color; }
-	
-	GC 	getInvertGC() 		const { return invert_gc; }
-	GC 	getStringGC() 		const { return string_gc; }
-	GC 	getBorderGC() 		const { return border_gc; }
-	
-	int 	getIHeight() 		const { return iheight; }
-	char*  	getMenuFont() 	    	const { return menufont; }
-	
-	Cursor 	getMoveCursor() 	const { return move_curs; }
-	Cursor 	getResizeCursor() 	const { return resize_curs; }
-	Cursor 	getLeftArrowCursor() 	const { return left_arrow; }
-	
-	XFontStruct* getXFont() 	const { return xfont; }
-
-	bool getShape() 		const { return shape; }
-	
-	void setShape(bool s) { shape=s; }
-	
-	int getFontPosition() const { return font_position; }
-
-	Theme* getTheme() const { return theme; }
-
-	void changeTheme(char* themeFile);
-
-	// Client List member functions
-	void insertClient(Client *c) { ClientList->insert(c); }
-	void removeClient(Client *c) { ClientList->remove(c); }
-
-	unsigned int getClientCount() const { return ClientList->count(); }
-	LinkedList<Client>* getClientListObject() const { return ClientList; }
-
-	// Server Grab member functions	
-	void Grab() { XGrabServer(dpy); }
-	void Ungrab() { XUngrabServer(dpy); }
-	void SyncUngrab() { XSync(dpy, False); XUngrabServer(dpy); }
-
-	void addToMenuList(BaseMenu *m) { menulist->insert(m); }
-	void addToExtraMenuList(BaseMenu *m) { extramenulist->insert(m); }
-	void reconfigureMenu();
-	void removeFromMenuList(BaseMenu *m) { menulist->remove(m); }
-	LinkedList<BaseMenu>* getMenuList() { return menulist; }		
-	BaseMenu* findInMenuList(Window *w);
-		
-  	Atom getWMChangeStateAtom() const { return xa_wm_change_state; }
-  	Atom getWMStateAtom() const       { return xa_wm_state; }
-  	Atom getWMDeleteAtom() const      { return xa_wm_delete; }
- 	Atom getWMProtocolsAtom() const   { return xa_wm_protos; }
-  	Atom getWMFocusAtom() const       { return xa_wm_take_focus; }
-  	Atom getWMColormapAtom() const    { return xa_wm_cmapwins; }
-	Atom getMotifWMHintsAtom() const      { return xa_wm_motif_hints; }
-
-	int 	getDepth() const { return depth; }
-	int	getScreen() const { return screen; }
-	Visual* getVisual() const { return visual; }
-	int	getColorsPerChannel() const { return colors_per_channel; }
-	bool    getImageDither() const { return image_dither; }
-	BImageControl *getImageControl() const { return image_control; }
-
-	Display* getDisplay() const { return dpy; }
-	Window  getRootWindow() const { return root; }
-
-	RootMenu* getRootMenu() const { return rm; }
-	IconMenu* getIconMenu() const { return im; }
-	Toolbar*  getToolbar() const { return t; }
-
-	void grabPointer(Window w, unsigned int mask, Cursor curs);
-	void ungrabPointer();
-
-	void quit_nicely();
-	void restart();
-	
-	int getXRes() const { return xres; }
-	int getYRes() const { return yres; }
-
-	char* getClockFormat() const { return clock_format; }
-	//void handleKeyPress(XEvent *ev);
-
-	// desktop is from 0 to 15, inclusive (not a bit mask like in changeDesktop)
-	void goToDesktop(int desktop);
-	void goToNextDesktop();
-	void goToPreviousDesktop();
-
-	void setMenu(BaseMenu* bm) { menu=bm; }
-	void setMenuEvent(bool me) { menu_event=me; }
-
-private: /* member functions */
-	
-	int QueryShapeExtentions();
-	
-	void scan_windows();
-	void do_event_loop();	
-	void createFontPixmap();
-	void createMenuFontPixmap();
-	void saveCurrentTheme();
-	void getCurrentTheme();
-};
-
-extern WindowManager *wm;
-
-#endif
+/*
+ * Copyright (C) 1999,2000,2001 Frank Hale
+ * frankhale@yahoo.com
+ * http://sapphire.sourceforge.net/
+ *
+ * Updated: 3 Nov 2001
+ *
+ * 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 any later version.
+ *
+ * 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.
+ */
+
+
+#ifndef _WM_HH_
+#define _WM_HH_
+
+#include "sapphire.hh"
+
+class WindowManager 
+{
+
+private: /* variables */
+
+	LinkedList<BaseMenu> *menulist;
+	LinkedList<BaseMenu> *extramenulist;
+	LinkedList<Client>   *ClientList;
+
+	Client		*head_client;	
+
+	Toolbar  	*t;
+	IconMenu 	*im;
+	RootMenu 	*rm;	
+	Theme 	 	*theme;
+	BImageControl 	*image_control;
+	BaseMenu 	*menu;
+
+	Atom		xa_wm_state;
+	Atom		xa_wm_change_state;
+	Atom		xa_wm_protos;
+        Atom		xa_wm_delete;
+	Atom		xa_wm_cmapwins;
+	Atom		xa_wm_take_focus;
+	Atom		xa_wm_motif_hints;
+
+	Window		root;
+	
+	Display		*dpy;
+	
+	Visual 		*visual;
+	
+	Pixmap		font_pix;
+		
+	XFontStruct	*xfont;	
+
+	XGCValues 	gv;
+	
+	XColor		xforeground_color;
+	XColor		xbackground_color; 
+	XColor		xborder_color;
+
+	GC		invert_gc;
+	GC		string_gc;
+	GC		border_gc;
+
+	Cursor		move_curs;
+	Cursor		resize_curs;
+	Cursor		left_arrow;
+	
+	char 		*display;
+	char 		*font;
+	char 		*menufont;
+	char 		*foreground_color;
+	char 		*background_color;
+	char 		*border_color;
+
+	int		depth;
+	int		xres;
+	int 		yres;
+	int		shape_event;
+	int 		colors_per_channel;
+	int 		toolbar_position;
+	int 		toolbar_visible;
+	int		screen;
+	int		iheight;
+	int 		font_position;
+
+	bool 		image_dither;
+	bool		shape;
+	bool 		menu_event;
+
+	// Configuration file stuff
+        char		*clock_format;
+	char		*configurationPath;
+	char		*windowmanager_conf;
+
+	static KeySym 	AltKeys[];
+public: 
+
+	// member functions below
+	
+	WindowManager(int argc, char **argv);
+	~WindowManager();
+
+	XColor 	getBorderColor()     	const { return xborder_color; }
+	XColor 	getForegroundColor() 	const { return xforeground_color; }
+	XColor 	getBackgroundColor() 	const { return xbackground_color; }
+	
+	GC 	getInvertGC() 		const { return invert_gc; }
+	GC 	getStringGC() 		const { return string_gc; }
+	GC 	getBorderGC() 		const { return border_gc; }
+	
+	int 	getIHeight() 		const { return iheight; }
+	char*  	getMenuFont() 	    	const { return menufont; }
+	
+	Cursor 	getMoveCursor() 	const { return move_curs; }
+	Cursor 	getResizeCursor() 	const { return resize_curs; }
+	Cursor 	getLeftArrowCursor() 	const { return left_arrow; }
+	
+	XFontStruct* getXFont() 	const { return xfont; }
+
+	bool getShape() 		const { return shape; }
+	
+	void setShape(bool s) { shape=s; }
+	
+	int getFontPosition() const { return font_position; }
+
+	Theme* getTheme() const { return theme; }
+
+	void changeTheme(char* themeFile);
+
+	// Client List member functions
+	void insertClient(Client *c) { ClientList->insert(c); }
+	void removeClient(Client *c) { ClientList->remove(c); }
+
+	unsigned int getClientCount() const { return ClientList->count(); }
+	LinkedList<Client>* getClientListObject() const { return ClientList; }
+
+	// Server Grab member functions	
+	void Grab() { XGrabServer(dpy); }
+	void Ungrab() { XUngrabServer(dpy); }
+	void SyncUngrab() { XSync(dpy, False); XUngrabServer(dpy); }
+
+	void addToMenuList(BaseMenu *m) { menulist->insert(m); }
+	void addToExtraMenuList(BaseMenu *m) { extramenulist->insert(m); }
+	void reconfigureMenu();
+	void removeFromMenuList(BaseMenu *m) { menulist->remove(m); }
+	LinkedList<BaseMenu>* getMenuList() { return menulist; }		
+	BaseMenu* findInMenuList(Window *w);
+		
+  	Atom getWMChangeStateAtom() const { return xa_wm_change_state; }
+  	Atom getWMStateAtom() const       { return xa_wm_state; }
+  	Atom getWMDeleteAtom() const      { return xa_wm_delete; }
+ 	Atom getWMProtocolsAtom() const   { return xa_wm_protos; }
+  	Atom getWMFocusAtom() const       { return xa_wm_take_focus; }
+  	Atom getWMColormapAtom() const    { return xa_wm_cmapwins; }
+	Atom getMotifWMHintsAtom() const      { return xa_wm_motif_hints; }
+
+	int 	getDepth() const { return depth; }
+	int	getScreen() const { return screen; }
+	Visual* getVisual() const { return visual; }
+	int	getColorsPerChannel() const { return colors_per_channel; }
+	bool    getImageDither() const { return image_dither; }
+	BImageControl *getImageControl() const { return image_control; }
+
+	Display* getDisplay() const { return dpy; }
+	Window  getRootWindow() const { return root; }
+
+	RootMenu* getRootMenu() const { return rm; }
+	IconMenu* getIconMenu() const { return im; }
+	Toolbar*  getToolbar() const { return t; }
+
+	void grabPointer(Window w, unsigned int mask, Cursor curs);
+	void ungrabPointer();
+
+	void quit_nicely();
+	void restart();
+	void start_another_windowmanager(char * wmCommand);
+	
+	int getXRes() const { return xres; }
+	int getYRes() const { return yres; }
+
+	char* getClockFormat() const { return clock_format; }
+	//void handleKeyPress(XEvent *ev);
+
+	// desktop is from 0 to 15, inclusive (not a bit mask like in changeDesktop)
+	void goToDesktop(int desktop);
+	void goToNextDesktop();
+	void goToPreviousDesktop();
+
+	void setMenu(BaseMenu* bm) { menu=bm; }
+	void setMenuEvent(bool me) { menu_event=me; }
+
+private: /* member functions */
+	
+	int QueryShapeExtentions();
+	
+	void scan_windows();
+	void do_event_loop();	
+	void createFontPixmap();
+	void createMenuFontPixmap();
+	void saveCurrentTheme();
+	void getCurrentTheme();
+};
+
+extern WindowManager *wm;
+
+#endif
--- sapphire-0.15.8.orig/linkedlist.cc
+++ sapphire-0.15.8/linkedlist.cc
@@ -21,6 +21,7 @@
  */
 
 
+#include <stdlib.h>
 #include <iostream>
 #include "linkedlist.hh"
 using namespace std;
--- sapphire-0.15.8.orig/menulex.cc
+++ sapphire-0.15.8/menulex.cc
@@ -1,427 +1,487 @@
-/*
- * Copyright (C) 1999,2000,2001 Frank Hale
- * frankhale@yahoo.com
- * http://sapphire.sourceforge.net/
- *
- * Updated: 3 Nov 2001
- *
- * 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 any later version.
- *
- * 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.
- */
-
-
-#include "sapphire.hh"
-
-MenuLex::MenuLex(char *filename, RootMenu *menu) : Scanner(filename) 
-{ 
-	root = menu;
-	
-	menulist = wm->getMenuList();
-		
-	error=false;
-	
-	submenus=1;
-	
-	name=new char[255];
-	exe=new char[255];
-}
-
-MenuLex::~MenuLex()
-{	
-	delete [] name;
-	delete [] exe;
-}
-
-BaseMenu* MenuLex::getLastMenu()
-{
-	if(menulist->count())
-		return menulist->last();
-
-	return NULL;
-}
-
-BaseMenu* MenuLex::getMenu(int index)
-{
-	int counter=0;
-	
-	if(index==0) return root;
-	
-	LinkedListIterator<BaseMenu> it(menulist);
-	for(; it.current(); it++)
-	{	
-		if(counter==index) return it.current();
-		
-		counter++;
-	}
-	
-	return NULL;
-}
-
-
-void MenuLex::parse()
-{
-	// Check to see if this menu file is gramatically correct.
-	do {
-	
-		getNextToken();
-	
-	} while(menu(true));
-
-	// If we didn't get any errors when we validated the menu
-	// then lets build the menu.
-	if(!error) {
-	
-		rewind();
-		
-		do {
-	
-			getNextToken();
-	
-		} while(menu(false));
-	
-		LinkedListIterator<BaseMenu> it(menulist);
-		for(; it.current(); it++)
-		{	
-			it.current()->update_all();
-		}
-	}
-	else {
-		
-		// If there was an error use the default menu.
-		
-		root->defaultMenu();
-	}
-	
-}
-
-bool MenuLex::menu(bool validate)
-{
-	if(match("menu"))
-	{
-		getNextToken();		
-		
-		if(match("("))
-		{
-			clearToken();
-			getNextToken(true);
-			strcpy(name, currentToken());
-			//printf("name = %s\n", currentToken());
-
-			if(! validate)
-				root->setMenuTitle(name);
-	
-			getNextToken();
-			if(match(")"))
-			{
-				getNextToken();
-				
-				if(match("{"))
-				{
-					getNextToken();
-						
-					if(match("}"))
-					{
-						printf("There was an error parsing your menu configuration file, I have to use the default menu because of this problem.\n");
-						error = true;
-						return true;
-					} else
-					{
-												
-						while(statement(root, validate)) {
-							getNextToken();
-						} 
-							
-						if(match("}"))
-						{
-							return true;
-						} else {
-							printf("missing } near (%s)\n", name);
-							error = true;
-							return false;
-						}
-	
-					}
-				} else {
-					printf("missing { near menu\n");
-					error = true;
-					return false;
-				}
-			
-			} else {
-				printf("missing ) near menu\n");
-				error = true;
-				return false;
-			}
-		
-		} else {
-			printf("missing ( near menu\n");
-			error = true;
-			return false;
-		}
-	}
-	
-	return false;
-}
-
-bool MenuLex::submenu(BaseMenu *sub, bool validate)
-{
+/*
+ * Copyright (C) 1999,2000,2001 Frank Hale
+ * frankhale@yahoo.com
+ * http://sapphire.sourceforge.net/
+ *
+ * Updated: 3 Nov 2001
+ *
+ * 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 any later version.
+ *
+ * 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.
+ */
+
+
+#include "sapphire.hh"
+
+MenuLex::MenuLex(char *filename, RootMenu *menu) : Scanner(filename) 
+{ 
+	root = menu;
+	
+	menulist = wm->getMenuList();
+		
+	error=false;
+	
+	submenus=1;
+	
+	name=new char[255];
+	exe=new char[255];
+}
+
+MenuLex::~MenuLex()
+{	
+	delete [] name;
+	delete [] exe;
+}
+
+BaseMenu* MenuLex::getLastMenu()
+{
+	if(menulist->count())
+		return menulist->last();
+
+	return NULL;
+}
+
+BaseMenu* MenuLex::getMenu(int index)
+{
+	int counter=0;
+	
+	if(index==0) return root;
+	
+	LinkedListIterator<BaseMenu> it(menulist);
+	for(; it.current(); it++)
+	{	
+		if(counter==index) return it.current();
+		
+		counter++;
+	}
+	
+	return NULL;
+}
+
+
+void MenuLex::parse()
+{
+	// Check to see if this menu file is gramatically correct.
+	do {
+	
+		getNextToken();
+	
+	} while(menu(true));
+
+	// If we didn't get any errors when we validated the menu
+	// then lets build the menu.
+	if(!error) {
+	
+		rewind();
+		
+		do {
+	
+			getNextToken();
+	
+		} while(menu(false));
+	
+		LinkedListIterator<BaseMenu> it(menulist);
+		for(; it.current(); it++)
+		{	
+			it.current()->update_all();
+		}
+	}
+	else {
+		
+		// If there was an error use the default menu.
+		
+		root->defaultMenu();
+	}
+	
+}
+
+bool MenuLex::menu(bool validate)
+{
+	if(match("menu"))
+	{
+		getNextToken();		
+		
+		if(match("("))
+		{
+			clearToken();
+			getNextToken(true);
+			strcpy(name, currentToken());
+			//printf("name = %s\n", currentToken());
+
+			if(! validate)
+				root->setMenuTitle(name);
+	
+			getNextToken();
+			if(match(")"))
+			{
+				getNextToken();
+				
+				if(match("{"))
+				{
+					getNextToken();
+						
+					if(match("}"))
+					{
+						printf("There was an error parsing your menu configuration file, I have to use the default menu because of this problem.\n");
+						error = true;
+						return true;
+					} else
+					{
+												
+						while(statement(root, validate)) {
+							getNextToken();
+						} 
+							
+						if(match("}"))
+						{
+							return true;
+						} else {
+							printf("missing } near (%s)\n", name);
+							error = true;
+							return false;
+						}
+	
+					}
+				} else {
+					printf("missing { near menu\n");
+					error = true;
+					return false;
+				}
+			
+			} else {
+				printf("missing ) near menu\n");
+				error = true;
+				return false;
+			}
+		
+		} else {
+			printf("missing ( near menu\n");
+			error = true;
+			return false;
+		}
+	}
+	
+	return false;
+}
+
+bool MenuLex::submenu(BaseMenu *sub, bool validate)
+{
 	BaseMenu *child=NULL;
-	if(match("submenu"))
-	{
-		getNextToken();		
-		
-		if(match("("))
-		{
-			clearToken();
-			getNextToken(true);
-			strcpy(name, currentToken());
-			
-			getNextToken();
-			if(match(")"))
-			{
-				getNextToken();
-				
-				if(match("{"))
-				{
-					getNextToken();
-												
-					if(! validate)
-					{
+	if(match("submenu"))
+	{
+		getNextToken();		
+		
+		if(match("("))
+		{
+			clearToken();
+			getNextToken(true);
+			strcpy(name, currentToken());
+			
+			getNextToken();
+			if(match(")"))
+			{
+				getNextToken();
+				
+				if(match("{"))
+				{
+					getNextToken();
+												
+					if(! validate)
+					{
 						child = new BaseMenu();
 						child->setMenuTitle(name);
 						menulist->insert(child);
 						sub->insert(name, child);
-					}
-						
-					while(statement(child, validate)) {
-						getNextToken();
-					} 
-							
-					if(match("}"))
-					{
-						if(! validate)
-						{
-							submenus=0;
-						}
-
-						return true;
-					} 
-	
-				} else {
-					printf("missing { near submenu\n");
-					error = true;
-					return false;
-				}
-			
-			} else {
-				printf("missing ) near submenu\n");
-				error = true;
-				return false;
-			}
-		
-		} else {
-			printf("missing ( near submenu\n");
-			error = true;
-			return false;
-		}
-	}
-	
-	return false;
-}
-
-bool MenuLex::separator(BaseMenu *sub, bool validate)
-{
-	if(match("separator"))
-	{
-		if(! validate)
-			sub->insert("separator", "", 2);
-				
-		return true;
-	}
-	
-	return false;
-}
-
-bool MenuLex::exit(BaseMenu* sub, bool validate)
-{
-	if(match("exit"))
-	{
-		if(! validate)
-			sub->insert("exit", "", 1);
-		
-		return true;
-	}
-	
-	return false;
-}
-
-bool MenuLex::restart(BaseMenu* sub, bool validate)
-{
-	if(match("restart"))
-	{
-		if(! validate)
-			sub->insert("restart", "", 4);
-		
-		return true;
-	}
-	
-	return false;
-}
-
-bool MenuLex::reconfigure(BaseMenu* sub, bool validate)
-{
-	if(match("reconfigure"))
-	{
-		if(! validate)
-			sub->insert("reconfigure", "", 5);
-		
-		return true;
-	}
-	
-	return false;
-}
-
-bool MenuLex::exec(BaseMenu *sub, bool validate)
-{
-	if(match("exec"))
-	{
-		getNextToken();		
-		
-		if(match("("))
-		{
-			clearToken();
-			getNextToken(true);
-			strcpy(name, currentToken());
-			//printf("name = %s\n", name);
-
-			getNextToken();
-			if(match(")"))
-			{
-				getNextToken();
-				
-				if(match("{"))
-				{
-					clearToken();
-					getNextToken(true);
-					
-					strcpy(exe, currentToken());
-					//printf("exec: %s\n", currentToken());
-						
-					if(! validate)
-					{
-						//printf("sub1's name = %s | inserting %s\n", sub1->getMenuTitle(), name);
-						sub->insert(name, exe, 0);
-					}
-						
-					getNextToken();
-							
-					if(match("}"))
-						return true;
-					
-				} else {
-					printf("missing { near exec\n");
-					error = true;
-					return false;
-				}
-			
-			} else {
-				printf("missing ) near exec\n");
-				error = true;
-				return false;
-			}
-		
-		} else {
-			printf("missing ( near exec\n");
-			error = true;
-			return false;
-		}
-	}
-	
-	return false;
-}
-
-bool MenuLex::theme(BaseMenu *sub, bool validate)
-{
-	if(match("theme"))
-	{
-		getNextToken();		
-		
-		if(match("("))
-		{
-			clearToken();
-			getNextToken(true);
-			strcpy(name, currentToken());
-			//printf("theme name = %s\n", name);
-
-			getNextToken();
-			if(match(")"))
-			{
-				getNextToken();
-				
-				if(match("{"))
-				{
-					clearToken();
-					getNextToken(true);
-						
-					
-					strcpy(exe, currentToken());
-					//printf("theme patch: %s\n", currentToken());
-						
-					if(! validate)
-					{
-						//printf("sub1's name = %s | inserting %s\n", sub1->getMenuTitle(), name);
-						sub->insert(name, exe, 6);
-					}
-						
-					getNextToken();
-							
-					if(match("}"))
-						return true;
-					
-				} else {
-					printf("missing { near theme\n");
-					error = true;
-					return false;
-				}
-			
-			} else {
-				printf("missing ) near theme\n");
-				error = true;
-				return false;
-			}
-		
-		} else {
-			printf("missing ( near theme\n");
-			error = true;
-			return false;
-		}
-	}
-	
-	return false;
-}
-
-bool MenuLex::statement(BaseMenu *sub, bool validate)
-{
-	// This dispatches each statement function.
-	
-	if(submenu(sub, validate)) 	return true; 
-	if(exec(sub, validate)) 	return true;
-	if(theme(sub, validate)) 	return true;
-	if(separator(sub, validate)) 	return true;
-	if(exit(sub, validate)) 	return true;
-	if(restart(sub, validate)) 	return true;
-	if(reconfigure(sub, validate)) 	return true;
-	
-	return false;
-}
+					}
+						
+					while(statement(child, validate)) {
+						getNextToken();
+					} 
+							
+					if(match("}"))
+					{
+						if(! validate)
+						{
+							submenus=0;
+						}
+
+						return true;
+					} 
+	
+				} else {
+					printf("missing { near submenu\n");
+					error = true;
+					return false;
+				}
+			
+			} else {
+				printf("missing ) near submenu\n");
+				error = true;
+				return false;
+			}
+		
+		} else {
+			printf("missing ( near submenu\n");
+			error = true;
+			return false;
+		}
+	}
+	
+	return false;
+}
+
+bool MenuLex::separator(BaseMenu *sub, bool validate)
+{
+	if(match("separator"))
+	{
+		if(! validate)
+			sub->insert("separator", "", 2);
+				
+		return true;
+	}
+	
+	return false;
+}
+
+bool MenuLex::exit(BaseMenu* sub, bool validate)
+{
+	if(match("exit"))
+	{
+		if(! validate)
+			sub->insert("exit", "", 1);
+		
+		return true;
+	}
+	
+	return false;
+}
+
+bool MenuLex::restart(BaseMenu* sub, bool validate)
+{
+	if(match("restart"))
+	{
+		if(! validate)
+			sub->insert("restart", "", 4);
+		
+		return true;
+	}
+	
+	return false;
+}
+
+bool MenuLex::reconfigure(BaseMenu* sub, bool validate)
+{
+	if(match("reconfigure"))
+	{
+		if(! validate)
+			sub->insert("reconfigure", "", 5);
+		
+		return true;
+	}
+	
+	return false;
+}
+
+bool MenuLex::exec(BaseMenu *sub, bool validate)
+{
+	if(match("exec"))
+	{
+		getNextToken();		
+		
+		if(match("("))
+		{
+			clearToken();
+			getNextToken(true);
+			strcpy(name, currentToken());
+			//printf("name = %s\n", name);
+
+			getNextToken();
+			if(match(")"))
+			{
+				getNextToken();
+				
+				if(match("{"))
+				{
+					clearToken();
+					getNextToken(true);
+					
+					strcpy(exe, currentToken());
+					//printf("exec: %s\n", currentToken());
+						
+					if(! validate)
+					{
+						//printf("sub1's name = %s | inserting %s\n", sub1->getMenuTitle(), name);
+						sub->insert(name, exe, 0);
+					}
+						
+					getNextToken();
+							
+					if(match("}"))
+						return true;
+					
+				} else {
+					printf("missing { near exec\n");
+					error = true;
+					return false;
+				}
+			
+			} else {
+				printf("missing ) near exec\n");
+				error = true;
+				return false;
+			}
+		
+		} else {
+			printf("missing ( near exec\n");
+			error = true;
+			return false;
+		}
+	}
+	
+	return false;
+}
+
+bool MenuLex::wmexec(BaseMenu *sub, bool validate)
+{
+	if(match("wmexec"))
+	{
+		getNextToken();		
+		
+		if(match("("))
+		{
+			clearToken();
+			getNextToken(true);
+			strcpy(name, currentToken());
+			//printf("name = %s\n", name);
+
+			getNextToken();
+			if(match(")"))
+			{
+				getNextToken();
+				
+				if(match("{"))
+				{
+					clearToken();
+					getNextToken(true);
+					
+					strcpy(exe, currentToken());
+					//printf("wmexec: %s\n", currentToken());
+						
+					if(! validate)
+					{
+						//printf("sub1's name = %s | inserting %s\n", sub1->getMenuTitle(), name);
+						sub->insert(name, exe, 3);
+					}
+						
+					getNextToken();
+							
+					if(match("}"))
+						return true;
+					
+				} else {
+					printf("missing { near wmexec\n");
+					error = true;
+					return false;
+				}
+			
+			} else {
+				printf("missing ) near wmexec\n");
+				error = true;
+				return false;
+			}
+		
+		} else {
+			printf("missing ( near wmexec\n");
+			error = true;
+			return false;
+		}
+	}
+	
+	return false;
+}
+
+bool MenuLex::theme(BaseMenu *sub, bool validate)
+{
+	if(match("theme"))
+	{
+		getNextToken();		
+		
+		if(match("("))
+		{
+			clearToken();
+			getNextToken(true);
+			strcpy(name, currentToken());
+			//printf("theme name = %s\n", name);
+
+			getNextToken();
+			if(match(")"))
+			{
+				getNextToken();
+				
+				if(match("{"))
+				{
+					clearToken();
+					getNextToken(true);
+						
+					
+					strcpy(exe, currentToken());
+					//printf("theme patch: %s\n", currentToken());
+						
+					if(! validate)
+					{
+						//printf("sub1's name = %s | inserting %s\n", sub1->getMenuTitle(), name);
+						sub->insert(name, exe, 6);
+					}
+						
+					getNextToken();
+							
+					if(match("}"))
+						return true;
+					
+				} else {
+					printf("missing { near theme\n");
+					error = true;
+					return false;
+				}
+			
+			} else {
+				printf("missing ) near theme\n");
+				error = true;
+				return false;
+			}
+		
+		} else {
+			printf("missing ( near theme\n");
+			error = true;
+			return false;
+		}
+	}
+	
+	return false;
+}
+
+bool MenuLex::statement(BaseMenu *sub, bool validate)
+{
+	// This dispatches each statement function.
+	
+	if(submenu(sub, validate)) 	return true; 
+	if(exec(sub, validate)) 	return true;
+	if(wmexec(sub, validate)) 	return true;
+	if(theme(sub, validate)) 	return true;
+	if(separator(sub, validate)) 	return true;
+	if(exit(sub, validate)) 	return true;
+	if(restart(sub, validate)) 	return true;
+	if(reconfigure(sub, validate)) 	return true;
+	
+	return false;
+}
--- sapphire-0.15.8.orig/Makefile
+++ sapphire-0.15.8/Makefile
@@ -14,7 +14,9 @@
 LIBS     = -lXext -lX11
 
 # If you change this, remember to change it in windowmanager.cc (line 34),
-# and in data/menu/default (lines 43-47, the themes section).
+# and in data/menu/default (lines 43-47, the themes section). Sapphire no
+# longer segfaults if it can't find its menus or themes, but it will always
+# give you the defaults, and won't warn you that this has happened.
 CONFIGURATION_PATH=/usr/share/sapphire
 
 # DEBUG = Outputs debug information
@@ -55,7 +57,7 @@
 	$(CC) $(CFLAGS) $(DEFINES) $(INCLUDES) -c $< -o $@
 
 install: all
-	install -s sapphire $(DESTDIR)$(prefix)/bin/
+	install sapphire $(DESTDIR)$(prefix)/bin/
 	
 	install -d $(DESTDIR)$(CONFIGURATION_PATH)/
 	
--- sapphire-0.15.8.orig/windowmanager.cc
+++ sapphire-0.15.8/windowmanager.cc
@@ -1,860 +1,865 @@
-/*
- * Copyright (C) 1999,2000,2001 Frank Hale
- * frankhale@yahoo.com
- * http://sapphire.sourceforge.net/
- *
- * Updated: 3 Nov 2001
- *
- * 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 any later version.
- *
- * 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.
- */
-
-#include "windowmanager.hh"
-
-WindowManager *wm;
-
-char* windowmanager_author 	= "Frank Hale";
-char* windowmanager_author_email = "frankhale@yahoo.com";
-char* windowmanager_name 	= "sapphire";
-char* windowmanager_version 	= "Sapphire 0.15.7pre7 (Blackberry)";
-char* windowmanager_usage 	= "[-display <display>] [-version]\n";
-char* windowmanager_exit_message = "\nThank you for using Sapphire.\n\nPlease Send all bug reports, suggestions, ideas, patches to frankhale@yahoo.com\n";
-
-char* configuration_home = "/usr/share/sapphire";
-
-char* HOME;
-
-// This function sets up default values for variables, gets command line args,
-// sets up our signal handlers, and performs initialization of certain things
-// to get ready for the window manager to start managing windows.
-WindowManager::WindowManager(int argc, char **argv) 
-{
-	::wm = this;
-	
-	HOME = new char[strlen(getenv("HOME"))+1];
-	strcpy(HOME, getenv("HOME"));
-	
-	font_pix 		= None;
-	
-	menu_event		= false;
-	
-	clock_format		= "%m %d %H:%M";
-	toolbar_visible		= true;
-	toolbar_position	= false;
-	
-	configurationPath  	= NULL;
-	windowmanager_conf 	= NULL;
-	display		   	= NULL;
-
-	XSetWindowAttributes 	attr;
-	XColor 			dummy;
-
-	head_client = new Client();
-	
-	// Allocate memory for our linked lists.
-	ClientList    = new LinkedList<Client>;
-	menulist      = new LinkedList<BaseMenu>;
-	extramenulist = new LinkedList<BaseMenu>;
-
-	for (int i = 1; i < argc; i++) 
-	{
-		if ((strcmp(argv[i], "-display")==0) && i+1<argc)
-		{
-			display = argv[++i];
-			continue;
-		}
-		if ((strcmp(argv[i], "-version")==0) && i<argc) {
-			printf("version %s\nby: %s\nemail: %s\n", windowmanager_version, windowmanager_author, windowmanager_author_email);
-			exit(0);
-		}
-		else {
-			printf("usage: %s %s", windowmanager_name, windowmanager_usage);
-			exit(1);
-		}
-	}
-        
-	// PP: Sun Feb 20 05:36:53 CET 2000
-        // If we got the DISPLAY via a cmd line option
-        // we should now set it as an evironment variable
-        // so that programs we call have it.
-        //
-        // The other way round also applies, i.e.
-        // if there was no cmd line option we should now
-        // set the display variable to the value
-        // of the environment variable.
-	if (display)
-        	setenv("DISPLAY", display, 1);
-	else
-        	display = getenv("DISPLAY");
-	     
-	XSetErrorHandler(handle_xerror);
-	signal(SIGTERM, (void (*)(int)) signalhandler);
-	signal(SIGINT,  (void (*)(int)) signalhandler);
-	signal(SIGHUP,  (void (*)(int)) signalhandler);
-
-	dpy = XOpenDisplay(display);
-
-	if (!dpy) { 
-		err("sorry can't open display %s", display);
-		exit(1);
-	}
-
-	screen = DefaultScreen(dpy);
-	root = RootWindow(dpy, screen);
-
-	depth = DefaultDepth(dpy, screen);
-	visual = DefaultVisual(dpy, screen);
-		
-	XDefineCursor(dpy, root, XCreateFontCursor(wm->dpy, XC_left_ptr));
-
-	// Atoms			
-	xa_wm_state        = XInternAtom(dpy, "WM_STATE", False);
-	xa_wm_change_state = XInternAtom(dpy, "WM_CHANGE_STATE", False);
-	xa_wm_protos       = XInternAtom(dpy, "WM_PROTOCOLS", False);
-	xa_wm_delete       = XInternAtom(dpy, "WM_DELETE_WINDOW", False);
-	xa_wm_cmapwins     = XInternAtom(dpy, "WM_COLORMAP_WINDOWS", False);
-	xa_wm_take_focus   = XInternAtom(dpy, "WM_TAKE_FOCUS", False);
-	xa_wm_motif_hints  = XInternAtom(dpy, "_MOTIF_WM_HINTS", False);
-	
-	foreground_color = DEFAULT_FOREGROUND_COLOR;
-	background_color = DEFAULT_BACKGROUND_COLOR;
-	border_color 	 = DEFAULT_BORDER_COLOR;
-
-	// Colors
-	XAllocNamedColor(dpy, DefaultColormap(dpy, screen), foreground_color, &xforeground_color, &dummy);
-	XAllocNamedColor(dpy, DefaultColormap(dpy, screen), background_color, &xbackground_color, &dummy);
-	XAllocNamedColor(dpy, DefaultColormap(dpy, screen), border_color, &xborder_color, &dummy);
-
-	colors_per_channel = 4;
-	image_dither = True;
-
-	image_control = new BImageControl();
-  	image_control->installRootColormap(); 
-
-	theme = new Theme();
-
-	getCurrentTheme();
-
-	font 	 = theme->getFont();
-	menufont = theme->getMenuFont();
-	
-	xfont = XLoadQueryFont(dpy, font);
-	
-	if (!xfont) 
-	{ 
-		// We should really check here to see if we can 
-		// find another font just incase. Dying here without
-		// checking again is not cool!
-		
-		err("the default font was not found, aborting."); 
-		exit(-1); 
-	}
-	
-	iheight = xfont->ascent + xfont->descent + 2 * DEFAULT_SPACE;
-
-	font_position = iheight - xfont->descent;
-
-	if(! QueryShapeExtentions())
-	{
-		printf("What no shape extentions, God you must be using an old X11 release.\n\nHave a nice life\n\nBa Bye...\n\n");	
-	}
-	
-	move_curs   = XCreateFontCursor(dpy, XC_fleur);
-	resize_curs = XCreateFontCursor(dpy, XC_plus);
-	left_arrow  = XCreateFontCursor(dpy, XC_left_ptr);
-	
-	createFontPixmap();
-	
-	gv.font = xfont->fid;
-	gv.tile = font_pix;	
-	string_gc = XCreateGC(dpy, root,  GCTile | GCFont , &gv);
-	XSetFillStyle(dpy, string_gc, FillTiled);
-
-	gv.foreground = xborder_color.pixel;
-	gv.line_width = DEFAULT_BORDER_SIZE;
-	border_gc = XCreateGC(dpy, root, GCForeground | GCLineWidth, &gv);
-
-	gv.function = GXinvert;
-	gv.subwindow_mode = IncludeInferiors;
-	invert_gc = XCreateGC(dpy, root, GCFunction | GCSubwindowMode | GCLineWidth, &gv);
-
-	attr.event_mask = SubstructureRedirectMask | 
-			  SubstructureNotifyMask   | 
-			  ColormapChangeMask       | 
-	                  ButtonPressMask          | 
-			  ButtonReleaseMask        | 
-			  PropertyChangeMask       | 
-			  PointerMotionMask        | 
-			  FocusChangeMask          |
-		          KeyPressMask             |
-			  ExposureMask		   ;
-			  
-	XChangeWindowAttributes(dpy, root, CWEventMask, &attr);
-	
-	xres = WidthOfScreen(ScreenOfDisplay(wm->dpy, wm->screen));
-	yres = HeightOfScreen(ScreenOfDisplay(wm->dpy, wm->screen));
-		
-	rm = new RootMenu();
-	t = new Toolbar();
-	im = new IconMenu();
-
-	addToMenuList(rm);
-	rm->parseMenuConfigurationFile();
-
-	t->getToolbarMenu()->addMenu("icon menu", im);
-	t->getToolbarMenu()->addMenu("root menu", rm);
-	t->getToolbarMenu()->update_all();
-
-	scan_windows();
-
-	do_event_loop();
-}
-
-WindowManager::~WindowManager() 
-{
-	unsigned int i, nwins;
-	Window dw1, dw2, *wins;
-	Client *temp_client=NULL;
-
-	XQueryTree(dpy, root, &dw1, &dw2, &wins, &nwins);
-	for (i = 0; i < nwins; i++) 
-	{
-		temp_client = head_client->find_client(wins[i]);
-		
-		if(temp_client)
-		{
-			temp_client->remove_client(temp_client);
-		}
-		
-	}
-	XFree(wins);
-
-	ClientList->removeAll();		
-	
-	delete head_client;
-	delete ClientList;
-
-	image_control->removeImage(font_pix);
-
-	XFreeFont(dpy, xfont);
-	
-	XFreeGC(dpy, invert_gc);
-	XFreeGC(dpy, string_gc);
-	XFreeGC(dpy, border_gc);
-		
-	delete t;
-	delete rm;
-	delete im;
-
-	menulist->removeAll();
-
-	extramenulist->removeAll();
-
-	delete menulist;
-	delete extramenulist;
-
-	delete theme;
-
-	
-	
-	delete image_control;
-	
-	delete [] HOME;
-	delete [] windowmanager_conf;
-	delete [] configurationPath;
-}
-
-void WindowManager::getCurrentTheme()
-{
-	XrmDatabase resource_db;	
-	XrmValue value;
-	char *value_type;
-	FILE* currentTheme;
-	bool themeLoaded = false;
-
-	windowmanager_conf = new char[strlen(HOME) + 32];
-	sprintf(windowmanager_conf, "%s/.sapphire/wmconf", HOME);
-	
-	if((currentTheme = fopen(windowmanager_conf, "r"))!=NULL)
-	{
-		fclose(currentTheme);
-		
-		XrmInitialize();
-
-		resource_db = XrmGetFileDatabase(windowmanager_conf);
-
-		if (XrmGetResource(resource_db, "toolbar.visible",
-		     "Toolbar.Visible", &value_type, &value))
-		{
-			if(strcmp(value.addr, "true")==0) 
-			{
-				theme->setToolbarVisible();
-				toolbar_visible=true;
-			} else {
-				toolbar_visible=false;
-			}
-		}
-
-		if (XrmGetResource(resource_db, "toolbar.position",
-		     "Toolbar.Position", &value_type, &value))
-		{
-			if(strcmp(value.addr, "top")==0) 
-			{
-				theme->setToolbarTop();
-				toolbar_position = true;
-			} else {
-				toolbar_position = false;
-			}
-		}
-		
-		// Clock format
-		if (XrmGetResource(resource_db,"clock.format","Clock.Format",&value_type,&value))
-		  {
-		    clock_format= new char[value.size];
-		    strcpy(clock_format,value.addr);
-		  } else {
-		    clock_format="%m %d %H:%M";
-		  }
-	
-		if (XrmGetResource(resource_db, "start.theme",
-		     "Start.Theme", &value_type, &value))
-		{
-			char *buffer = new char[value.size+strlen(HOME)];
-			
-			strcpy(buffer, value.addr);
-			
-			if (value.addr[0] == '~') 
-			{
-				sprintf(buffer, "%s%s", HOME, value.addr+1);
-			}
-
-			if((currentTheme = fopen(buffer, "r"))!=NULL)
-			{
-				fclose(currentTheme);	
-				theme->parseTheme(buffer);
-				themeLoaded=true;
-			}
-			
-			delete [] buffer;
-		}
-
-		XrmDestroyDatabase(resource_db);
-		
-	}
+/*
+ * Copyright (C) 1999,2000,2001 Frank Hale
+ * frankhale@yahoo.com
+ * http://sapphire.sourceforge.net/
+ *
+ * Updated: 3 Nov 2001
+ *
+ * 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 any later version.
+ *
+ * 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.
+ */
+
+#include "windowmanager.hh"
+
+WindowManager *wm;
+
+char* windowmanager_author 	= "Frank Hale";
+char* windowmanager_author_email = "frankhale@yahoo.com";
+char* windowmanager_name 	= "sapphire";
+char* windowmanager_version 	= "Sapphire 0.15.8";
+char* windowmanager_usage 	= "[-display <display>] [-version]\n";
+char* windowmanager_exit_message = "\nThank you for using Sapphire.\n\nPlease Send all bug reports, suggestions, ideas, patches to frankhale@yahoo.com\n";
+
+char* configuration_home = "/usr/share/sapphire";
+
+char* HOME;
+
+// This function sets up default values for variables, gets command line args,
+// sets up our signal handlers, and performs initialization of certain things
+// to get ready for the window manager to start managing windows.
+WindowManager::WindowManager(int argc, char **argv) 
+{
+	::wm = this;
+	
+	HOME = new char[strlen(getenv("HOME"))+1];
+	strcpy(HOME, getenv("HOME"));
+	
+	font_pix 		= None;
+	
+	menu_event		= false;
+	
+	clock_format		= "%m %d %H:%M";
+	toolbar_visible		= true;
+	toolbar_position	= false;
+	
+	configurationPath  	= NULL;
+	windowmanager_conf 	= NULL;
+	display		   	= NULL;
+
+	XSetWindowAttributes 	attr;
+	XColor 			dummy;
+
+	head_client = new Client();
+	
+	// Allocate memory for our linked lists.
+	ClientList    = new LinkedList<Client>;
+	menulist      = new LinkedList<BaseMenu>;
+	extramenulist = new LinkedList<BaseMenu>;
+
+	for (int i = 1; i < argc; i++) 
+	{
+		if ((strcmp(argv[i], "-display")==0) && i+1<argc)
+		{
+			display = argv[++i];
+			continue;
+		}
+		if ((strcmp(argv[i], "-version")==0) && i<argc) {
+			printf("version %s\nby: %s\nemail: %s\n", windowmanager_version, windowmanager_author, windowmanager_author_email);
+			exit(0);
+		}
+		else {
+			printf("usage: %s %s", windowmanager_name, windowmanager_usage);
+			exit(1);
+		}
+	}
+        
+	// PP: Sun Feb 20 05:36:53 CET 2000
+        // If we got the DISPLAY via a cmd line option
+        // we should now set it as an evironment variable
+        // so that programs we call have it.
+        //
+        // The other way round also applies, i.e.
+        // if there was no cmd line option we should now
+        // set the display variable to the value
+        // of the environment variable.
+	if (display)
+        	setenv("DISPLAY", display, 1);
+	else
+        	display = getenv("DISPLAY");
+	     
+	XSetErrorHandler(handle_xerror);
+	signal(SIGTERM, (void (*)(int)) signalhandler);
+	signal(SIGINT,  (void (*)(int)) signalhandler);
+	signal(SIGHUP,  (void (*)(int)) signalhandler);
+
+	dpy = XOpenDisplay(display);
+
+	if (!dpy) { 
+		err("sorry can't open display %s", display);
+		exit(1);
+	}
+
+	screen = DefaultScreen(dpy);
+	root = RootWindow(dpy, screen);
+
+	depth = DefaultDepth(dpy, screen);
+	visual = DefaultVisual(dpy, screen);
+		
+	XDefineCursor(dpy, root, XCreateFontCursor(wm->dpy, XC_left_ptr));
+
+	// Atoms			
+	xa_wm_state        = XInternAtom(dpy, "WM_STATE", False);
+	xa_wm_change_state = XInternAtom(dpy, "WM_CHANGE_STATE", False);
+	xa_wm_protos       = XInternAtom(dpy, "WM_PROTOCOLS", False);
+	xa_wm_delete       = XInternAtom(dpy, "WM_DELETE_WINDOW", False);
+	xa_wm_cmapwins     = XInternAtom(dpy, "WM_COLORMAP_WINDOWS", False);
+	xa_wm_take_focus   = XInternAtom(dpy, "WM_TAKE_FOCUS", False);
+	xa_wm_motif_hints  = XInternAtom(dpy, "_MOTIF_WM_HINTS", False);
+	
+	foreground_color = DEFAULT_FOREGROUND_COLOR;
+	background_color = DEFAULT_BACKGROUND_COLOR;
+	border_color 	 = DEFAULT_BORDER_COLOR;
+
+	// Colors
+	XAllocNamedColor(dpy, DefaultColormap(dpy, screen), foreground_color, &xforeground_color, &dummy);
+	XAllocNamedColor(dpy, DefaultColormap(dpy, screen), background_color, &xbackground_color, &dummy);
+	XAllocNamedColor(dpy, DefaultColormap(dpy, screen), border_color, &xborder_color, &dummy);
+
+	colors_per_channel = 4;
+	image_dither = True;
+
+	image_control = new BImageControl();
+  	image_control->installRootColormap(); 
+
+	theme = new Theme();
+
+	getCurrentTheme();
+
+	font 	 = theme->getFont();
+	menufont = theme->getMenuFont();
+	
+	xfont = XLoadQueryFont(dpy, font);
+	
+	if (!xfont) 
+	{ 
+		// We should really check here to see if we can 
+		// find another font just incase. Dying here without
+		// checking again is not cool!
+		
+		err("the default font was not found, aborting."); 
+		exit(-1); 
+	}
+	
+	iheight = xfont->ascent + xfont->descent + 2 * DEFAULT_SPACE;
+
+	font_position = iheight - xfont->descent;
+
+	if(! QueryShapeExtentions())
+	{
+		printf("What no shape extentions, God you must be using an old X11 release.\n\nHave a nice life\n\nBa Bye...\n\n");	
+	}
+	
+	move_curs   = XCreateFontCursor(dpy, XC_fleur);
+	resize_curs = XCreateFontCursor(dpy, XC_plus);
+	left_arrow  = XCreateFontCursor(dpy, XC_left_ptr);
+	
+	createFontPixmap();
+	
+	gv.font = xfont->fid;
+	gv.tile = font_pix;	
+	string_gc = XCreateGC(dpy, root,  GCTile | GCFont , &gv);
+	XSetFillStyle(dpy, string_gc, FillTiled);
+
+	gv.foreground = xborder_color.pixel;
+	gv.line_width = DEFAULT_BORDER_SIZE;
+	border_gc = XCreateGC(dpy, root, GCForeground | GCLineWidth, &gv);
+
+	gv.function = GXinvert;
+	gv.subwindow_mode = IncludeInferiors;
+	invert_gc = XCreateGC(dpy, root, GCFunction | GCSubwindowMode | GCLineWidth, &gv);
+
+	attr.event_mask = SubstructureRedirectMask | 
+			  SubstructureNotifyMask   | 
+			  ColormapChangeMask       | 
+	                  ButtonPressMask          | 
+			  ButtonReleaseMask        | 
+			  PropertyChangeMask       | 
+			  PointerMotionMask        | 
+			  FocusChangeMask          |
+		          KeyPressMask             |
+			  ExposureMask		   ;
+			  
+	XChangeWindowAttributes(dpy, root, CWEventMask, &attr);
+	
+	xres = WidthOfScreen(ScreenOfDisplay(wm->dpy, wm->screen));
+	yres = HeightOfScreen(ScreenOfDisplay(wm->dpy, wm->screen));
+		
+	rm = new RootMenu();
+	t = new Toolbar();
+	im = new IconMenu();
+
+	addToMenuList(rm);
+	rm->parseMenuConfigurationFile();
+
+	t->getToolbarMenu()->addMenu("icon menu", im);
+	t->getToolbarMenu()->addMenu("root menu", rm);
+	t->getToolbarMenu()->update_all();
+
+	scan_windows();
+
+	do_event_loop();
+}
+
+WindowManager::~WindowManager() 
+{
+	unsigned int i, nwins;
+	Window dw1, dw2, *wins;
+	Client *temp_client=NULL;
+
+	XQueryTree(dpy, root, &dw1, &dw2, &wins, &nwins);
+	for (i = 0; i < nwins; i++) 
+	{
+		temp_client = head_client->find_client(wins[i]);
+		
+		if(temp_client)
+		{
+			temp_client->remove_client(temp_client);
+		}
+		
+	}
+	XFree(wins);
+
+	ClientList->removeAll();		
+	
+	delete head_client;
+	delete ClientList;
+
+	image_control->removeImage(font_pix);
+
+	XFreeFont(dpy, xfont);
+	
+	XFreeGC(dpy, invert_gc);
+	XFreeGC(dpy, string_gc);
+	XFreeGC(dpy, border_gc);
+		
+	delete t;
+	delete rm;
+	delete im;
+
+	menulist->removeAll();
+
+	extramenulist->removeAll();
+
+	delete menulist;
+	delete extramenulist;
+
+	delete theme;
+
+	
+	
+	delete image_control;
+	
+	delete [] HOME;
+	delete [] windowmanager_conf;
+	delete [] configurationPath;
+}
+
+void WindowManager::getCurrentTheme()
+{
+	XrmDatabase resource_db;	
+	XrmValue value;
+	char *value_type;
+	FILE* currentTheme;
+	bool themeLoaded = false;
+
+	windowmanager_conf = new char[strlen(HOME) + 32];
+	sprintf(windowmanager_conf, "%s/.sapphire/wmconf", HOME);
+	
+	if((currentTheme = fopen(windowmanager_conf, "r"))!=NULL)
+	{
+		fclose(currentTheme);
+		
+		XrmInitialize();
+
+		resource_db = XrmGetFileDatabase(windowmanager_conf);
+
+		if (XrmGetResource(resource_db, "toolbar.visible",
+		     "Toolbar.Visible", &value_type, &value))
+		{
+			if(strcmp(value.addr, "true")==0) 
+			{
+				theme->setToolbarVisible();
+				toolbar_visible=true;
+			} else {
+				toolbar_visible=false;
+			}
+		}
+
+		if (XrmGetResource(resource_db, "toolbar.position",
+		     "Toolbar.Position", &value_type, &value))
+		{
+			if(strcmp(value.addr, "top")==0) 
+			{
+				theme->setToolbarTop();
+				toolbar_position = true;
+			} else {
+				toolbar_position = false;
+			}
+		}
+		
+		// Clock format
+		if (XrmGetResource(resource_db,"clock.format","Clock.Format",&value_type,&value))
+		  {
+		    clock_format= new char[value.size];
+		    strcpy(clock_format,value.addr);
+		  } else {
+		    clock_format="%m %d %H:%M";
+		  }
+	
+		if (XrmGetResource(resource_db, "start.theme",
+		     "Start.Theme", &value_type, &value))
+		{
+			char *buffer = new char[value.size+strlen(HOME)];
+			
+			strcpy(buffer, value.addr);
+			
+			if (value.addr[0] == '~') 
+			{
+				sprintf(buffer, "%s%s", HOME, value.addr+1);
+			}
+
+			if((currentTheme = fopen(buffer, "r"))!=NULL)
+			{
+				fclose(currentTheme);	
+				theme->parseTheme(buffer);
+				themeLoaded=true;
+			}
+			
+			delete [] buffer;
+		}
+
+		XrmDestroyDatabase(resource_db);
+		
+	}
 	if (! themeLoaded) {
-		char* defaultTheme = new char[strlen(configuration_home) + 32];
-		sprintf(defaultTheme, "%s/themes/default.theme", configuration_home);
-
-		theme->parseTheme(defaultTheme);
-		theme->setToolbarVisible();
-		
-		delete [] defaultTheme;
-	}
-}
-
-void WindowManager::createFontPixmap()
-{
-	unsigned long style=0;
-	
-	style = wm->getTheme()->getFontStyle();		
-
-	font_pix = wm->getImageControl()->renderImage(
-			//"xfont",
-			xfont->ascent, 
-			xfont->descent, 
-			style, 
-			wm->getTheme()->getFontColorFrom(), 
-			wm->getTheme()->getFontColorTo()
-			);
-}
-
-// We really should have some way to check if the menu needs
-// reconfiguring. It shouldn't do anymore processing than
-// it needs to.
-void WindowManager::reconfigureMenu()
-{
-	XGrabServer(dpy);
-	
-	if(menulist->count())
-	{
-		menulist->removeAll();
-
-		rm->removeAll();		
-		addToMenuList(rm);
-		rm->parseMenuConfigurationFile();
-	}
-
-	XUngrabServer(dpy);
-}
-
-int WindowManager::QueryShapeExtentions()
-{
-	int dummy2;
-
-	return shape = XShapeQueryExtension(dpy, &shape_event, &dummy2);
-}
-
-void WindowManager::scan_windows()
-{
-	unsigned int i, nwins;
-	Window dw1, dw2, *wins;
-	XWindowAttributes attr;
-
-	XQueryTree(dpy, root, &dw1, &dw2, &wins, &nwins);
-	for (i = 0; i < nwins; i++) {
-		XGetWindowAttributes(dpy, wins[i], &attr);
-		if (!attr.override_redirect && attr.map_state == IsViewable)
-			head_client->make_new_client(wins[i]);
-	}
-	XFree(wins);
-}
-
-void WindowManager::do_event_loop()
-{
-	XEvent ev;
-
-	BaseMenu *m = None;
-
-	int xfd = ConnectionNumber(wm->dpy);
-
-	int dx=0,dy=0;
-
-	for (;;) 
-	{
-		if(XPending(wm->dpy))
-		{
-			XNextEvent(wm->dpy, &ev);
-
-			switch (ev.type) 
-			{
-				case ButtonPress:
-				{
-					head_client->handle_button_press_event(&ev.xbutton); 
-					t->do_button_press_event(&ev.xbutton);
-					
-					m = findInMenuList(&ev.xbutton.window);
-					
-					if(m)
-					{
-						m->handle_button_press_event(&ev.xbutton);	
-					} 
-									
-					switch(ev.xbutton.button)
-					{
-						case 2: {
-							if(ev.xbutton.window == root)
-					  		{
-								t->setStartMenuButtonStateNotPressed();
-
-								im->update_all();
-								im->setAllMenuTitlesVisible(im,True);
-								im->show();
-					  		}
-							
-						break;
-						}
-
-						case 3: {
-							
-							if(ev.xbutton.window == root)
-					  		{
-								t->setStartMenuButtonStateNotPressed();
-								
-								rm->hideAllVisibleSubmenus();
-								
-								reconfigureMenu();
-								
-								rm->setAllMenuTitlesVisible(rm, True);
-								rm->show();
-					  		}
-						break;	
-						}
-						
-						default:
-						{
-							if(ev.xbutton.window == root)
-					  		{
-								t->setStartMenuButtonStateNotPressed();
-
-								im->setAllMenuTitlesVisible(im, False);
-								im->hide(im);
-
-								rm->setAllMenuTitlesVisible(rm, False);
-								rm->hideAllVisibleSubmenus();
-								rm->hide(rm);
-							}
-
-						}
-						break;
-
-					}
-				break;
-				}
-			
-				case ButtonRelease:
-				{
-					m = findInMenuList(&ev.xbutton.window);
-					
-					if(m)
-						m->handle_button_release_event(&ev.xbutton);	
-										
-					switch(ev.xbutton.button)
-					{
-					        case 1:
-						case 2: 
-						case 3: 
-						default:
-						{
-							if(menu_event)
-							{
-								wm->ungrabPointer();
-								menu_event=false;
-							}
-						
-						}
-						break;
-					}
-					
-					
-				break;
-				}
-				
-				case ConfigureRequest:
-				{
-					head_client->handle_configure_request(&ev.xconfigurerequest); 
-				
-				break;
-				}
-				
-				case ConfigureNotify:
-				{
-				break;
-				}
-				
-				case DestroyNotify:
-				{
-					head_client->handle_destroy_notify(&ev.xdestroywindow);
-				break;
-				}
-				
-				case MapRequest:
-				{
-					head_client->handle_map_request(&ev.xmaprequest);
-				
-				break;
-				}
-			
-				case UnmapNotify:
-				{
-					head_client->handle_unmap_event(&ev.xunmap); 
-				break;
-				}
-			
-				case ClientMessage:
-				{
-					head_client->handle_client_message(&ev.xclient); 
-				break;
-				}
-			
-				case ColormapNotify:
-				{
-					head_client->handle_colormap_change(&ev.xcolormap); 
-				break;
-				}
-			
-				case PropertyNotify:
-				{
-					head_client->handle_property_change(&ev.xproperty); 
-				break;
-				}
-
-				case LeaveNotify:
-				{
-					m = findInMenuList(&ev.xcrossing.window);
-													
-					if(m)
-						m->handle_leave_notify(&ev.xcrossing);	
-
-				break;
-				}
-			
-				case EnterNotify:
-				{
-					head_client->handle_enter_event(&ev.xcrossing); 
-						
-					m = findInMenuList(&ev.xcrossing.window);
-										
-					if(m)
-						m->handle_enter_notify(&ev.xcrossing);	
-				break;
-				}
-
-				case MotionNotify:
-				{
-					if(menu_event)
-					{
-						grabPointer(root, ButtonReleaseMask | PointerMotionMask, move_curs);
-						dx = ev.xmotion.x_root - menu->menu.x_move;
-						dy = ev.xmotion.y_root - menu->menu.y_move;
-						menu->menu.x = dx;
-						menu->menu.y = dy;
-						XMoveWindow(dpy, menu->menu.window, dx, dy);				
-					}
-					
-					m = findInMenuList(&ev.xmotion.window);
-					
-					if(m)
-						m->handle_motion_notify_event(&ev.xmotion);
-					
-				break;
-				}
-						
-				case Expose:
-				{
-					head_client->handle_expose_event(&ev.xexpose);
-					t->handle_expose_event(&ev.xexpose); 
-				
-					rm->handle_expose_event(&ev.xexpose); 
-					
-					m = findInMenuList(&ev.xexpose.window);
-					
-					if(m)
-						m->handle_expose_event(&ev.xexpose); 
-				
-					break;
-				}
-										
-				default: 
-				{				
-					if (wm->shape && ev.type == wm->shape_event) 
-					head_client->handle_shape_change((XShapeEvent *)&ev);
-				break;		 
-				}	
-			
-			
-			}
-		
-		} else {
-
-			fd_set rfds;
-			FD_ZERO(&rfds);
-			FD_SET(xfd, &rfds);
-
-			struct timeval tv;
-			tv.tv_sec = 0;
-			tv.tv_usec = 1000;
-			
-			select(xfd + 1, &rfds, 0, 0, &tv);
-
-			t->checkClock();
-		}
-
-	}
-	
-
-}
-
-// Function:
-//
-// void WindowManager::quit_nicely()
-//
-// Purpose:
-//
-// This functions sole purpose in life is to preform clean up so that we can
-// shutdown Sapphire safely.
-//
-// Returns:
-// 
-// This function returns nothing.
-//
-void WindowManager::quit_nicely()
-{
-	saveCurrentTheme();
-	
-	this->~WindowManager();
-
-	XSetInputFocus(dpy, PointerRoot, RevertToPointerRoot, CurrentTime);
-	XInstallColormap(dpy, DefaultColormap(dpy, screen));
-	XCloseDisplay(dpy);
-	
-	printf("%s", windowmanager_exit_message);
-	
-	exit(0);
-}
-
-void WindowManager::restart()
-{
-	saveCurrentTheme();
-	
-	this->~WindowManager();
-	
-	XSetInputFocus(dpy, PointerRoot, RevertToPointerRoot, CurrentTime);
-
-	XInstallColormap(dpy, DefaultColormap(dpy, screen));
-
-	XCloseDisplay(dpy);
-		
-	execl("/bin/sh", "sh", "-c", windowmanager_name, 0);
-}
-
-BaseMenu* WindowManager::findInMenuList(Window *w)
-{
-	if(extramenulist->count())
-	{
-		LinkedListIterator<BaseMenu> mx(extramenulist);
-				
-		for(; mx.current(); mx++) 
-		{
-			if(*w == mx.current()->getMenuWindow()      || 
-			   *w == mx.current()->getMenuTitleWindow() ||
-			   *w == mx.current()->getMenuItemWindow())
-			{
-				return mx.current();
-			} 
-		}	
-	
-	} 
-
-	if(menulist->count())
-	{
-		LinkedListIterator<BaseMenu> my(menulist);
-				
-		for(; my.current(); my++) 
-		{
-			if(*w == my.current()->getMenuWindow()      || 
-			  *w == my.current()->getMenuTitleWindow() ||
-			  *w == my.current()->getMenuItemWindow())
-			{
-				return my.current();
-			} 
-		}
-	
-		
-	}
-	
-	return NULL;
-}
-
-void WindowManager::grabPointer(Window w, unsigned int mask, Cursor curs)
-{
-	if (! XGrabPointer(dpy, w, False, mask, GrabModeAsync, GrabModeAsync, None, curs, CurrentTime) == GrabSuccess ) 
-		return;	
-}
-
-void WindowManager::ungrabPointer()
-{
-	XUngrabPointer(dpy, CurrentTime);	
-}
-
-void WindowManager::changeTheme(char* themeFile)
-{	
-	image_control->removeAllImages();	
-	
-	theme->parseTheme(themeFile);
-
-	XFreeFont(dpy, xfont);
-	XFreeGC(dpy, string_gc);
-	if(font_pix) XFreePixmap(dpy, font_pix);
-	
-	xfont = XLoadQueryFont(dpy, theme->getFont());
-	
-	if(!xfont) 
-	{ 
-		err("the font specified in the current theme was not found, using default font.");
-		
-		xfont = XLoadQueryFont(dpy, font);
-	}
-	
-	font_position = iheight - xfont->descent;
-	
-	createFontPixmap();
-	
-	gv.font = xfont->fid;
-	gv.tile = font_pix;	
-	string_gc = XCreateGC(dpy, root,  GCTile | GCFont , &gv);
-	XSetFillStyle(dpy, string_gc, FillTiled);
-	
-	t->changeTheme();	
-	
-	if(ClientList->count())
-	{
-		LinkedListIterator<Client> c(ClientList);
-		for(; c.current(); c++) 
-		{
-			c.current()->themeChange(c.current());
-		}
-	}
-	
-	if(menulist->count())
-	{
-		LinkedListIterator<BaseMenu> mx(menulist);
-		for(; mx.current(); mx++) 
-		{
-			mx.current()->reconfigure();
-		}
-	}
-
-	if(extramenulist->count())
-	{
-		LinkedListIterator<BaseMenu> my(extramenulist);
-		for(; my.current(); my++) 
-		{
-			my.current()->reconfigure();
-		}
-	}
-}
-
-void WindowManager::saveCurrentTheme()
-{
-	// Hopefully I've gotten the bugs out of this function
-	// Only time will tell....
-
-	char* save_theme = theme->getCurrentTheme();
-	
-	FILE *wmconf;
-	
-	if((wmconf = fopen(windowmanager_conf, "w"))==NULL)
-	{
-		char *sapphire_config_dir = new char[strlen(HOME)+30];
-		sprintf(sapphire_config_dir, "%s/.sapphire", HOME);
-		
-		printf("sapphire_config_dir = %s\n", sapphire_config_dir);
-		
-		mkdir(sapphire_config_dir, S_IRWXU);
-
-		delete [] sapphire_config_dir;
-
-		if((wmconf = fopen(windowmanager_conf, "w"))==NULL)
-		{
-			perror("error:\n");
-			exit(-1);
-		} 
-	}
-	
-	if(toolbar_visible)
-		fprintf(wmconf, "toolbar.visible: true\n");
-	else 
-		fprintf(wmconf, "toolbar.visible: false\n");
-	
-	if(toolbar_position)
-		fprintf(wmconf, "toolbar.position: top\n");
-	else 
-		fprintf(wmconf, "toolbar.position: bottom\n");
-
-	fprintf(wmconf, "start.theme: %s\n", save_theme);		
-	fprintf(wmconf, "clock.format: %s\n", clock_format);
-	//fprintf(wmconf, "desktops.count: %d\n", max_desktops);
-
-	fclose(wmconf);
-}
+		char* defaultTheme = new char[strlen(configuration_home) + 32];
+		sprintf(defaultTheme, "%s/themes/default.theme", configuration_home);
+
+		theme->parseTheme(defaultTheme);
+		theme->setToolbarVisible();
+		
+		delete [] defaultTheme;
+	}
+}
+
+void WindowManager::createFontPixmap()
+{
+	unsigned long style=0;
+	
+	style = wm->getTheme()->getFontStyle();		
+
+	font_pix = wm->getImageControl()->renderImage(
+			//"xfont",
+			xfont->ascent, 
+			xfont->descent, 
+			style, 
+			wm->getTheme()->getFontColorFrom(), 
+			wm->getTheme()->getFontColorTo()
+			);
+}
+
+// We really should have some way to check if the menu needs
+// reconfiguring. It shouldn't do anymore processing than
+// it needs to.
+void WindowManager::reconfigureMenu()
+{
+	XGrabServer(dpy);
+	
+	if(menulist->count())
+	{
+		menulist->removeAll();
+
+		rm->removeAll();		
+		addToMenuList(rm);
+		rm->parseMenuConfigurationFile();
+	}
+
+	XUngrabServer(dpy);
+}
+
+int WindowManager::QueryShapeExtentions()
+{
+	int dummy2;
+
+	return shape = XShapeQueryExtension(dpy, &shape_event, &dummy2);
+}
+
+void WindowManager::scan_windows()
+{
+	unsigned int i, nwins;
+	Window dw1, dw2, *wins;
+	XWindowAttributes attr;
+
+	XQueryTree(dpy, root, &dw1, &dw2, &wins, &nwins);
+	for (i = 0; i < nwins; i++) {
+		XGetWindowAttributes(dpy, wins[i], &attr);
+		if (!attr.override_redirect && attr.map_state == IsViewable)
+			head_client->make_new_client(wins[i]);
+	}
+	XFree(wins);
+}
+
+void WindowManager::do_event_loop()
+{
+	XEvent ev;
+
+	BaseMenu *m = None;
+
+	int xfd = ConnectionNumber(wm->dpy);
+
+	int dx=0,dy=0;
+
+	for (;;) 
+	{
+		if(XPending(wm->dpy))
+		{
+			XNextEvent(wm->dpy, &ev);
+
+			switch (ev.type) 
+			{
+				case ButtonPress:
+				{
+					head_client->handle_button_press_event(&ev.xbutton); 
+					t->do_button_press_event(&ev.xbutton);
+					
+					m = findInMenuList(&ev.xbutton.window);
+					
+					if(m)
+					{
+						m->handle_button_press_event(&ev.xbutton);	
+					} 
+									
+					switch(ev.xbutton.button)
+					{
+						case 2: {
+							if(ev.xbutton.window == root)
+					  		{
+								t->setStartMenuButtonStateNotPressed();
+
+								im->update_all();
+								im->setAllMenuTitlesVisible(im,True);
+								im->show();
+					  		}
+							
+						break;
+						}
+
+						case 3: {
+							
+							if(ev.xbutton.window == root)
+					  		{
+								t->setStartMenuButtonStateNotPressed();
+								
+								rm->hideAllVisibleSubmenus();
+								
+								reconfigureMenu();
+								
+								rm->setAllMenuTitlesVisible(rm, True);
+								rm->show();
+					  		}
+						break;	
+						}
+						
+						default:
+						{
+							if(ev.xbutton.window == root)
+					  		{
+								t->setStartMenuButtonStateNotPressed();
+
+								im->setAllMenuTitlesVisible(im, False);
+								im->hide(im);
+
+								rm->setAllMenuTitlesVisible(rm, False);
+								rm->hideAllVisibleSubmenus();
+								rm->hide(rm);
+							}
+
+						}
+						break;
+
+					}
+				break;
+				}
+			
+				case ButtonRelease:
+				{
+					m = findInMenuList(&ev.xbutton.window);
+					
+					if(m)
+						m->handle_button_release_event(&ev.xbutton);	
+										
+					switch(ev.xbutton.button)
+					{
+					        case 1:
+						case 2: 
+						case 3: 
+						default:
+						{
+							if(menu_event)
+							{
+								wm->ungrabPointer();
+								menu_event=false;
+							}
+						
+						}
+						break;
+					}
+					
+					
+				break;
+				}
+				
+				case ConfigureRequest:
+				{
+					head_client->handle_configure_request(&ev.xconfigurerequest); 
+				
+				break;
+				}
+				
+				case ConfigureNotify:
+				{
+				break;
+				}
+				
+				case DestroyNotify:
+				{
+					head_client->handle_destroy_notify(&ev.xdestroywindow);
+				break;
+				}
+				
+				case MapRequest:
+				{
+					head_client->handle_map_request(&ev.xmaprequest);
+				
+				break;
+				}
+			
+				case UnmapNotify:
+				{
+					head_client->handle_unmap_event(&ev.xunmap); 
+				break;
+				}
+			
+				case ClientMessage:
+				{
+					head_client->handle_client_message(&ev.xclient); 
+				break;
+				}
+			
+				case ColormapNotify:
+				{
+					head_client->handle_colormap_change(&ev.xcolormap); 
+				break;
+				}
+			
+				case PropertyNotify:
+				{
+					head_client->handle_property_change(&ev.xproperty); 
+				break;
+				}
+
+				case LeaveNotify:
+				{
+					m = findInMenuList(&ev.xcrossing.window);
+													
+					if(m)
+						m->handle_leave_notify(&ev.xcrossing);	
+
+				break;
+				}
+			
+				case EnterNotify:
+				{
+					head_client->handle_enter_event(&ev.xcrossing); 
+						
+					m = findInMenuList(&ev.xcrossing.window);
+										
+					if(m)
+						m->handle_enter_notify(&ev.xcrossing);	
+				break;
+				}
+
+				case MotionNotify:
+				{
+					if(menu_event)
+					{
+						grabPointer(root, ButtonReleaseMask | PointerMotionMask, move_curs);
+						dx = ev.xmotion.x_root - menu->menu.x_move;
+						dy = ev.xmotion.y_root - menu->menu.y_move;
+						menu->menu.x = dx;
+						menu->menu.y = dy;
+						XMoveWindow(dpy, menu->menu.window, dx, dy);				
+					}
+					
+					m = findInMenuList(&ev.xmotion.window);
+					
+					if(m)
+						m->handle_motion_notify_event(&ev.xmotion);
+					
+				break;
+				}
+						
+				case Expose:
+				{
+					head_client->handle_expose_event(&ev.xexpose);
+					t->handle_expose_event(&ev.xexpose); 
+				
+					rm->handle_expose_event(&ev.xexpose); 
+					
+					m = findInMenuList(&ev.xexpose.window);
+					
+					if(m)
+						m->handle_expose_event(&ev.xexpose); 
+				
+					break;
+				}
+										
+				default: 
+				{				
+					if (wm->shape && ev.type == wm->shape_event) 
+					head_client->handle_shape_change((XShapeEvent *)&ev);
+				break;		 
+				}	
+			
+			
+			}
+		
+		} else {
+
+			fd_set rfds;
+			FD_ZERO(&rfds);
+			FD_SET(xfd, &rfds);
+
+			struct timeval tv;
+			tv.tv_sec = 0;
+			tv.tv_usec = 1000;
+			
+			select(xfd + 1, &rfds, 0, 0, &tv);
+
+			t->checkClock();
+		}
+
+	}
+	
+
+}
+
+// Function:
+//
+// void WindowManager::quit_nicely()
+//
+// Purpose:
+//
+// This functions sole purpose in life is to preform clean up so that we can
+// shutdown Sapphire safely.
+//
+// Returns:
+// 
+// This function returns nothing.
+//
+void WindowManager::quit_nicely()
+{
+	saveCurrentTheme();
+	
+	this->~WindowManager();
+
+	XSetInputFocus(dpy, PointerRoot, RevertToPointerRoot, CurrentTime);
+	XInstallColormap(dpy, DefaultColormap(dpy, screen));
+	XCloseDisplay(dpy);
+	
+	printf("%s", windowmanager_exit_message);
+	
+	exit(0);
+}
+
+void WindowManager::restart()
+{
+	start_another_windowmanager(windowmanager_name);
+}
+
+void WindowManager::start_another_windowmanager(char * wmCommand)
+{
+	saveCurrentTheme();
+	
+	this->~WindowManager();
+	
+	XSetInputFocus(dpy, PointerRoot, RevertToPointerRoot, CurrentTime);
+
+	XInstallColormap(dpy, DefaultColormap(dpy, screen));
+
+	XCloseDisplay(dpy);
+		
+	execl("/bin/sh", "sh", "-c", wmCommand, 0);
+}
+
+BaseMenu* WindowManager::findInMenuList(Window *w)
+{
+	if(extramenulist->count())
+	{
+		LinkedListIterator<BaseMenu> mx(extramenulist);
+				
+		for(; mx.current(); mx++) 
+		{
+			if(*w == mx.current()->getMenuWindow()      || 
+			   *w == mx.current()->getMenuTitleWindow() ||
+			   *w == mx.current()->getMenuItemWindow())
+			{
+				return mx.current();
+			} 
+		}	
+	
+	} 
+
+	if(menulist->count())
+	{
+		LinkedListIterator<BaseMenu> my(menulist);
+				
+		for(; my.current(); my++) 
+		{
+			if(*w == my.current()->getMenuWindow()      || 
+			  *w == my.current()->getMenuTitleWindow() ||
+			  *w == my.current()->getMenuItemWindow())
+			{
+				return my.current();
+			} 
+		}
+	
+		
+	}
+	
+	return NULL;
+}
+
+void WindowManager::grabPointer(Window w, unsigned int mask, Cursor curs)
+{
+	if (! XGrabPointer(dpy, w, False, mask, GrabModeAsync, GrabModeAsync, None, curs, CurrentTime) == GrabSuccess ) 
+		return;	
+}
+
+void WindowManager::ungrabPointer()
+{
+	XUngrabPointer(dpy, CurrentTime);	
+}
+
+void WindowManager::changeTheme(char* themeFile)
+{	
+	image_control->removeAllImages();	
+	
+	theme->parseTheme(themeFile);
+
+	XFreeFont(dpy, xfont);
+	XFreeGC(dpy, string_gc);
+	if(font_pix) XFreePixmap(dpy, font_pix);
+	
+	xfont = XLoadQueryFont(dpy, theme->getFont());
+	
+	if(!xfont) 
+	{ 
+		err("the font specified in the current theme was not found, using default font.");
+		
+		xfont = XLoadQueryFont(dpy, font);
+	}
+	
+	font_position = iheight - xfont->descent;
+	
+	createFontPixmap();
+	
+	gv.font = xfont->fid;
+	gv.tile = font_pix;	
+	string_gc = XCreateGC(dpy, root,  GCTile | GCFont , &gv);
+	XSetFillStyle(dpy, string_gc, FillTiled);
+	
+	t->changeTheme();	
+	
+	if(ClientList->count())
+	{
+		LinkedListIterator<Client> c(ClientList);
+		for(; c.current(); c++) 
+		{
+			c.current()->themeChange(c.current());
+		}
+	}
+	
+	if(menulist->count())
+	{
+		LinkedListIterator<BaseMenu> mx(menulist);
+		for(; mx.current(); mx++) 
+		{
+			mx.current()->reconfigure();
+		}
+	}
+
+	if(extramenulist->count())
+	{
+		LinkedListIterator<BaseMenu> my(extramenulist);
+		for(; my.current(); my++) 
+		{
+			my.current()->reconfigure();
+		}
+	}
+}
+
+void WindowManager::saveCurrentTheme()
+{
+	// Hopefully I've gotten the bugs out of this function
+	// Only time will tell....
+
+	char* save_theme = theme->getCurrentTheme();
+	
+	FILE *wmconf;
+	
+	if((wmconf = fopen(windowmanager_conf, "w"))==NULL)
+	{
+		char *sapphire_config_dir = new char[strlen(HOME)+30];
+		sprintf(sapphire_config_dir, "%s/.sapphire", HOME);
+		
+		printf("sapphire_config_dir = %s\n", sapphire_config_dir);
+		
+		mkdir(sapphire_config_dir, S_IRWXU);
+
+		delete [] sapphire_config_dir;
+
+		if((wmconf = fopen(windowmanager_conf, "w"))==NULL)
+		{
+			perror("error:\n");
+			exit(-1);
+		} 
+	}
+	
+	if(toolbar_visible)
+		fprintf(wmconf, "toolbar.visible: true\n");
+	else 
+		fprintf(wmconf, "toolbar.visible: false\n");
+	
+	if(toolbar_position)
+		fprintf(wmconf, "toolbar.position: top\n");
+	else 
+		fprintf(wmconf, "toolbar.position: bottom\n");
+
+	fprintf(wmconf, "start.theme: %s\n", save_theme);		
+	fprintf(wmconf, "clock.format: %s\n", clock_format);
+	//fprintf(wmconf, "desktops.count: %d\n", max_desktops);
+
+	fclose(wmconf);
+}
--- sapphire-0.15.8.orig/data/menu/default
+++ sapphire-0.15.8/data/menu/default
@@ -1,5 +1,7 @@
 menu(Sapphire 0.15.x)
 {
+include-menu-defs
+
 	submenu (terminals)
 	{
 		exec (xterm) {xterm -bg black -fg white}
