changeset 17:265b987cce4f ornery-orc

Traipse 'OpenRPG' {090813-00} Traipse is a distribution of OpenRPG that is designed to be easy to setup and go. Traipse also makes it easy for developers to work on code without fear of sacrifice. 'Ornery-Orc' continues the trend of 'Grumpy' and adds fixes to the code. 'Ornery-Orc''s main goal is to offer more advanced features and enhance the productivity of the user. **Announcement** Please download the location-patch.zip from http://www.assembla.com/wiki/show/traipse. The patch is ready to copy to your Traipse directory (includes files in their subfolders). The patch removes dependency on the OPENRPG_BASE system environment dictionary key. Update Summary: This update enhances the Updater tab. Player List and Game Server Menu Columns now have a minimum width and the software will refresh to that width on an update, if the column is too small. Also fixes problems with three character sheet nodes. *Arbitrary* fix to tool bar checks, docking passes tests though. Chat is now a multiline entry. CSS added to chat posts.
author sirebral
date Thu, 13 Aug 2009 13:14:10 -0500
parents 281ca8daa911
children 97265586402b
files orpg/chat/chatwnd.py orpg/gametree/nodehandlers/StarWarsd20.py orpg/gametree/nodehandlers/core.py orpg/gametree/nodehandlers/dnd35.py orpg/gametree/nodehandlers/dnd3e.py orpg/main.py orpg/mapper/miniatures_handler.py orpg/networking/gsclient.py orpg/orpg_version.py orpg/player_list.py orpg/tools/predTextCtrl.py upmana/__init__.py upmana/manifest.py upmana/updatemana.py upmana/validate.py upmana/xmltramp.py
diffstat 13 files changed, 2133 insertions(+), 2258 deletions(-) [+]
line wrap: on
line diff
--- a/orpg/chat/chatwnd.py	Sat Aug 08 00:35:09 2009 -0500
+++ b/orpg/chat/chatwnd.py	Thu Aug 13 13:14:10 2009 -0500
@@ -70,8 +70,7 @@
 try:
     import wx.webview
     NEWCHAT = True
-except:
-    pass
+except: pass
 NEWCHAT = False
 
 # Global parser for stripping HTML tags:
@@ -88,8 +87,7 @@
     def handle_starttag(self, tag, attrs):
         if tag in self.special_tags:
             self.accum += '<' + tag
-            for attrib in attrs:
-                self.accum += ' ' + attrib[0] + '="' + attrib[1] + '"'
+            for attrib in attrs: self.accum += ' ' + attrib[0] + '="' + attrib[1] + '"'
             self.accum += '>'
     def handle_charref(self, name):  # charrefs too
         self.accum += "&#" + name + ";"
@@ -111,8 +109,7 @@
         #filename = time.strftime( filename, time.localtime( time.time() ) )
         timestamp = time.ctime(time.time())
         header = '[%s] : ' % ( timestamp );
-        if settings.get_setting('TimeStampGameLog') != '1':
-            header = ''
+        if settings.get_setting('TimeStampGameLog') != '1': header = ''
         try:
             f = open( orpg.dirpath.dir_struct["user"] + filename, 'a' )
             f.write( '%s%s<br />\n' % ( header, text ) )
@@ -142,9 +139,8 @@
         self.build_menu()
         self.Bind(wx.EVT_LEFT_UP, self.LeftUp)
         self.Bind(wx.EVT_RIGHT_DOWN, self.onPopup)
-        if "gtk2" in wx.PlatformInfo:
-            self.SetStandardFonts()
-    # def __init__ - end
+        if "gtk2" in wx.PlatformInfo: self.SetStandardFonts()
+        # def __init__ - end
 
     def onPopup(self, evt):
         self.PopupMenu(self.menu)
@@ -216,7 +212,6 @@
             wx.webview.WebView.__init__(self, parent, id)
 
             self.parent = parent
-
             self.__font = wx.Font(10, wx.FONTFAMILY_ROMAN, wx.FONTSTYLE_NORMAL, wx.FONTWEIGHT_NORMAL, faceName='Ariel')
 
             self.build_menu()
@@ -239,10 +234,8 @@
 
         def SetDefaultFontAndSize(self, fontname, fontsize):
             self.__font = wx.Font(int(fontsize), wx.FONTFAMILY_ROMAN, wx.FONTSTYLE_NORMAL, wx.FONTWEIGHT_NORMAL, faceName=fontname)
-            try:
-                self.SetPageSource(self.Header() + self.StripHeader())
-            except Exception, e:
-                print e
+            try: self.SetPageSource(self.Header() + self.StripHeader())
+            except Exception, e: print e
             return (self.GetFont().GetFaceName(), self.GetFont().GetPointSize())
 
         #Events
@@ -267,9 +260,7 @@
 
         def StripHeader(self):
             tmp = self.GetPageSource().split('<BODY>')
-            if tmp[-1].find('<body>') > -1:
-                tmp = tmp[-1].split('<body>')
-
+            if tmp[-1].find('<body>') > -1: tmp = tmp[-1].split('<body>')
             return tmp[-1]
 
         def build_menu(self):
@@ -409,10 +400,8 @@
 
     def onCloseTab(self, evt):
         self.log.log("Enter chat_notebook->onCloseTab(self, evt)", ORPG_DEBUG)
-        try:
-            tabid = evt.GetSelection()
-        except:
-            tabid = self.GetSelection()
+        try: tabid = evt.GetSelection()
+        except: tabid = self.GetSelection()
 
         if self.GetPageText(tabid) == 'Main Room':
             #send no close error to chat
@@ -434,18 +423,14 @@
             self.GMChatPanel = None
             self.settings.set_setting("GMWhisperTab", "0")
         panel = self.GetPage(tabid)
-        if panel in self.whisper_tabs:
-            self.whisper_tabs.remove(panel)
-        elif panel in self.group_tabs:
-            self.group_tabs.remove(panel)
-        elif panel in self.null_tabs:
-            self.null_tabs.remove(panel)
+        if panel in self.whisper_tabs: self.whisper_tabs.remove(panel)
+        elif panel in self.group_tabs: self.group_tabs.remove(panel)
+        elif panel in self.null_tabs: self.null_tabs.remove(panel)
         self.log.log("Exit chat_notebook->onCloseTab(self, evt)", ORPG_DEBUG)
 
     def newMsg(self, tabid):
         self.log.log("Enter chat_notebook->newMsg(self, tabid)", ORPG_DEBUG)
-        if tabid != self.GetSelection():
-            self.SetPageImage(tabid, 0)
+        if tabid != self.GetSelection(): self.SetPageImage(tabid, 0)
         self.log.log("Exit chat_notebook->newMsg(self, tabid)", ORPG_DEBUG)
 
     def onPageChanging(self, event):
@@ -463,43 +448,48 @@
         #wx.CallAfter(page.set_chat_text_focus, 0)
         event.Skip()
         self.log.log("Exit chat_notebook->onPageChanged(self, event)", ORPG_DEBUG)
+
+"""
+ This class defines and builds the Chat Frame for OpenRPG
 
-# This class defines and builds the Chat Frame for OpenRPG
-#
-# Inherits: wxPanel
-#
-# Defines:
-#   __init__((self, parent, id, openrpg, sendtarget)
-#   build_ctrls(self)
-#   on_buffer_size(self,evt)
-#   set_colors(self)
-#   set_buffersize(self)
-#   set_chat_text(self,txt)
-#   OnChar(self,event)
-#   on_chat_save(self,evt)
-#   on_text_color(self,event)
-#   colorize(self, color, text)
-#   on_text_format(self,event)
-#   OnSize(self,event)
-#   scroll_down(self)
-#   InfoPost(self,s)
-#   Post(self,s="",send=False,myself=False)
-#   ParsePost(self,s,send=False,myself=False)
-#   ParseDice(self,s)
-#   ParseNodes(self,s)
-#   get_sha_checksum(self)
-#   get_color(self)
-#
+ Inherits: wxPanel
+
+ Defines:
+   __init__((self, parent, id, openrpg, sendtarget)
+   build_ctrls(self)
+   on_buffer_size(self,evt)
+   set_colors(self)
+   set_buffersize(self)
+   set_chat_text(self,txt)
+   OnChar(self,event)
+   on_chat_save(self,evt)
+   on_text_color(self,event)
+   colorize(self, color, text)
+   on_text_format(self,event)
+   OnSize(self,event)
+   scroll_down(self)
+   InfoPost(self,s)
+   Post(self,s="",send=False,myself=False)
+   ParsePost(self,s,send=False,myself=False)
+   ParseDice(self,s)
+   ParseNodes(self,s)
+   get_sha_checksum(self)
+   get_color(self)
+
+"""
 
 class chat_panel(wx.Panel):
+
+    """
+    This is the initialization subroutine
+    
+    !self : instance of self
+    !parent : parent that defines the chatframe
+    !id :
+    !openrpg :
+    !sendtarget:  who gets outbound messages: either 'all' or a playerid
+    """
 
-    # This is the initialization subroutine
-    #
-    # !self : instance of self
-    # !parent : parent that defines the chatframe
-    # !id :
-    # !openrpg :
-        # !sendtarget:  who gets outbound messages: either 'all' or a playerid
     def __init__(self, parent, id, tab_type, sendtarget):
         self.log = open_rpg.get_component("log")
         self.log.log("Enter chat_panel", ORPG_DEBUG)
@@ -543,10 +533,8 @@
         StartupFont = self.settings.get_setting("defaultfont")
         StartupFontSize = self.settings.get_setting("defaultfontsize")
         if(StartupFont != "") and (StartupFontSize != ""):
-            try:
-                self.set_default_font(StartupFont, int(StartupFontSize))
-            except:
-                pass
+            try: self.set_default_font(StartupFont, int(StartupFontSize))
+            except: pass
         self.font = self.chatwnd.GetFont().GetFaceName()
         self.fontsize = self.chatwnd.GetFont().GetPointSize()
         self.scroll_down()
@@ -555,14 +543,10 @@
     def set_default_font(self, fontname=None, fontsize=None):
         """Set all chatpanels to new default fontname/fontsize. Returns current font settings in a (fontname, fontsize) tuple."""
         self.log.log("Enter chat_panel->set_default_font(self, fontname=None, fontsize=None)", ORPG_DEBUG)
-        if (fontname is not None):
-            newfont = fontname
-        else:
-            newfont = self.font
-        if (fontsize is not None):
-            newfontsize = int(fontsize)
-        else:
-            newfontsize = int(self.fontsize)
+        if (fontname is not None): newfont = fontname
+        else: newfont = self.font
+        if (fontsize is not None): newfontsize = int(fontsize)
+        else: newfontsize = int(self.fontsize)
         self.chatwnd.SetDefaultFontAndSize(newfont, newfontsize)
         self.InfoPost("Font is now " + newfont + " point size " + `newfontsize`)
         self.font = newfont
@@ -609,65 +593,53 @@
         item = wx.MenuItem(wndmenu, wx.ID_ANY, "Show Images", "Show Images", wx.ITEM_CHECK)
         top_frame.Bind(wx.EVT_MENU, self.OnMB_ShowImages, item)
         wndmenu.AppendItem(item)
-        if self.settings.get_setting("Show_Images_In_Chat") == '1':
-            item.Check(True)
+        if self.settings.get_setting("Show_Images_In_Chat") == '1': item.Check(True)
         item = wx.MenuItem(wndmenu, wx.ID_ANY, "Strip HTML", "Strip HTML", wx.ITEM_CHECK)
         top_frame.Bind(wx.EVT_MENU, self.OnMB_StripHTML, item)
         wndmenu.AppendItem(item)
-        if self.settings.get_setting("striphtml") == '1':
-            item.Check(True)
+        if self.settings.get_setting("striphtml") == '1': item.Check(True)
         item = wx.MenuItem(wndmenu, wx.ID_ANY, "Chat Time Index", "Chat Time Index", wx.ITEM_CHECK)
         top_frame.Bind(wx.EVT_MENU, self.OnMB_ChatTimeIndex, item)
         wndmenu.AppendItem(item)
-        if self.settings.get_setting("Chat_Time_Indexing") == '1':
-            item.Check(True)
+        if self.settings.get_setting("Chat_Time_Indexing") == '1': item.Check(True)
         item = wx.MenuItem(wndmenu, wx.ID_ANY, "Chat Auto Complete", "Chat Auto Complete", wx.ITEM_CHECK)
         top_frame.Bind(wx.EVT_MENU, self.OnMB_ChatAutoComplete, item)
         wndmenu.AppendItem(item)
-        if self.settings.get_setting("SuppressChatAutoComplete") == '0':
-            item.Check(True)
+        if self.settings.get_setting("SuppressChatAutoComplete") == '0': item.Check(True)
         item = wx.MenuItem(wndmenu, wx.ID_ANY, "Show ID in Chat", "Show ID in Chat", wx.ITEM_CHECK)
         top_frame.Bind(wx.EVT_MENU, self.OnMB_ShowIDinChat, item)
         wndmenu.AppendItem(item)
-        if self.settings.get_setting("ShowIDInChat") == '1':
-            item.Check(True)
+        if self.settings.get_setting("ShowIDInChat") == '1': item.Check(True)
         item = wx.MenuItem(wndmenu, wx.ID_ANY, "Log Time Index", "Log Time Index", wx.ITEM_CHECK)
         top_frame.Bind(wx.EVT_MENU, self.OnMB_LogTimeIndex, item)
         wndmenu.AppendItem(item)
-        if self.settings.get_setting("TimeStampGameLog") == '1':
-            item.Check(True)
+        if self.settings.get_setting("TimeStampGameLog") == '1': item.Check(True)
         settingmenu.AppendMenu(wx.ID_ANY, 'Chat Window', wndmenu )
         item = wx.MenuItem(tabmenu, wx.ID_ANY, "Tabbed Whispers", "Tabbed Whispers", wx.ITEM_CHECK)
         top_frame.Bind(wx.EVT_MENU, self.OnMB_TabbedWhispers, item)
         tabmenu.AppendItem(item)
-        if self.settings.get_setting("tabbedwhispers") == '1':
-            item.Check(True)
+        if self.settings.get_setting("tabbedwhispers") == '1': item.Check(True)
         item = wx.MenuItem(tabmenu, wx.ID_ANY, "GM Tab", "GM Tab", wx.ITEM_CHECK)
         top_frame.Bind(wx.EVT_MENU, self.OnMB_GMTab, item)
         tabmenu.AppendItem(item)
-        if self.settings.get_setting("GMWhisperTab") == '1':
-            item.Check(True)
+        if self.settings.get_setting("GMWhisperTab") == '1':item.Check(True)
         item = wx.MenuItem(tabmenu, wx.ID_ANY, "Group Whisper Tabs", "Group Whisper Tabs", wx.ITEM_CHECK)
         top_frame.Bind(wx.EVT_MENU, self.OnMB_GroupWhisperTabs, item)
         tabmenu.AppendItem(item)
-        if self.settings.get_setting("GroupWhisperTab") == '1':
-            item.Check(True)
+        if self.settings.get_setting("GroupWhisperTab") == '1': item.Check(True)
         settingmenu.AppendMenu(wx.ID_ANY, 'Chat Tabs', tabmenu)
         item = wx.MenuItem(toolmenu, wx.ID_ANY, "Dice Bar", "Dice Bar", wx.ITEM_CHECK)
         top_frame.Bind(wx.EVT_MENU, self.OnMB_DiceBar, item)
         toolmenu.AppendItem(item)
-        if self.settings.get_setting("DiceButtons_On") == '1':
-            item.Check(True)
+        if self.settings.get_setting("DiceButtons_On") == '1': item.Check(True)
         item = wx.MenuItem(toolmenu, wx.ID_ANY, "Format Buttons", "Format Buttons", wx.ITEM_CHECK)
         top_frame.Bind(wx.EVT_MENU, self.OnMB_FormatButtons, item)
         toolmenu.AppendItem(item)
-        if self.settings.get_setting("FormattingButtons_On") == '1':
-            item.Check(True)
+        if self.settings.get_setting("FormattingButtons_On") == '1': item.Check(True)
         item = wx.MenuItem(toolmenu, wx.ID_ANY, "Alias Tool", "Alias Tool", wx.ITEM_CHECK)
         top_frame.Bind(wx.EVT_MENU, self.OnMB_AliasTool, item)
         toolmenu.AppendItem(item)
-        if self.settings.get_setting("AliasTool_On") == '1':
-            item.Check(True)
+        if self.settings.get_setting("AliasTool_On") == '1': item.Check(True)
         settingmenu.AppendMenu(wx.ID_ANY, 'Chat Tool Bars', toolmenu)
         menu.AppendMenu(wx.ID_ANY, 'Chat Settings', settingmenu)
         top_frame.mainmenu.Insert(2, menu, '&Chat')
@@ -676,58 +648,44 @@
     ## Settings Menu Events
     def OnMB_ShowImages(self, event):
         self.log.log("Enter chat_panel->OnMB_ShowImages(self, event)", ORPG_DEBUG)
-        if event.IsChecked():
-            self.settings.set_setting("Show_Images_In_Chat", '1')
-        else:
-            self.settings.set_setting("Show_Images_In_Chat", '0')
+        if event.IsChecked(): self.settings.set_setting("Show_Images_In_Chat", '1')
+        else: self.settings.set_setting("Show_Images_In_Chat", '0')
         self.log.log("Exit chat_panel->OnMB_ShowImages(self, event)", ORPG_DEBUG)
 
     def OnMB_StripHTML(self, event):
         self.log.log("Enter chat_panel->OnMB_StripHTML(self, event)", ORPG_DEBUG)
-        if event.IsChecked():
-            self.settings.set_setting("Sstriphtml", '1')
-        else:
-            self.settings.set_setting("striphtml", '0')
+        if event.IsChecked(): self.settings.set_setting("Sstriphtml", '1')
+        else: self.settings.set_setting("striphtml", '0')
         self.log.log("Exit chat_panel->OnMB_StripHTML(self, event)", ORPG_DEBUG)
 
     def OnMB_ChatTimeIndex(self, event):
         self.log.log("Enter chat_panel->OnMB_ChatTimeIndex(self, event)", ORPG_DEBUG)
-        if event.IsChecked():
-            self.settings.set_setting("Chat_Time_Indexing", '1')
-        else:
-            self.settings.set_setting("Chat_Time_Indexing", '0')
+        if event.IsChecked(): self.settings.set_setting("Chat_Time_Indexing", '1')
+        else: self.settings.set_setting("Chat_Time_Indexing", '0')
         self.log.log("Exit chat_panel->OnMB_ChatTimeIndex(self, event)", ORPG_DEBUG)
 
     def OnMB_ChatAutoComplete(self, event):
         self.log.log("Enter chat_panel->OnMB_ChatAutoComplete(self, event)", ORPG_DEBUG)
-        if event.IsChecked():
-            self.settings.set_setting("SuppressChatAutoComplete", '0')
-        else:
-            self.settings.set_setting("SuppressChatAutoComplete", '1')
+        if event.IsChecked(): self.settings.set_setting("SuppressChatAutoComplete", '0')
+        else: self.settings.set_setting("SuppressChatAutoComplete", '1')
         self.log.log("Exit chat_panel->OnMB_ChatAutoComplete(self, event)", ORPG_DEBUG)
 
     def OnMB_ShowIDinChat(self, event):
         self.log.log("Enter chat_panel->OnMB_ShowIDinChat(self, event)", ORPG_DEBUG)
-        if event.IsChecked():
-            self.settings.set_setting("ShowIDInChat", '1')
-        else:
-            self.settings.set_setting("ShowIDInChat", '0')
+        if event.IsChecked(): self.settings.set_setting("ShowIDInChat", '1')
+        else: self.settings.set_setting("ShowIDInChat", '0')
         self.log.log("Exit chat_panel->OnMB_ShowIDinChat(self, event)", ORPG_DEBUG)
 
     def OnMB_LogTimeIndex(self, event):
         self.log.log("Enter chat_panel->OnMB_LogTimeIndex(self, event)", ORPG_DEBUG)
-        if event.IsChecked():
-            self.settings.set_setting("TimeStampGameLog", '1')
-        else:
-            self.settings.set_setting("TimeStampGameLog", '0')
+        if event.IsChecked(): self.settings.set_setting("TimeStampGameLog", '1')
+        else: self.settings.set_setting("TimeStampGameLog", '0')
         self.log.log("Exit chat_panel->OnMB_LogTimeIndex(self, event)", ORPG_DEBUG)
 
     def OnMB_TabbedWhispers(self, event):
         self.log.log("Enter chat_panel->OnMB_TabbedWhispers(self, event)", ORPG_DEBUG)
-        if event.IsChecked():
-            self.settings.set_setting("tabbedwhispers", '1')
-        else:
-            self.settings.set_setting("tabbedwhispers", '0')
+        if event.IsChecked(): self.settings.set_setting("tabbedwhispers", '1')
+        else: self.settings.set_setting("tabbedwhispers", '0')
         self.log.log("Exit chat_panel->OnMB_TabbedWhispers(self, event)", ORPG_DEBUG)
 
     def OnMB_GMTab(self, event):
@@ -735,16 +693,13 @@
         if event.IsChecked():
             self.settings.set_setting("GMWhisperTab", '1')
             self.parent.create_gm_tab()
-        else:
-            self.settings.set_setting("GMWhisperTab", '0')
+        else: self.settings.set_setting("GMWhisperTab", '0')
         self.log.log("Exit chat_panel->OnMB_GMTab(self, event)", ORPG_DEBUG)
 
     def OnMB_GroupWhisperTabs(self, event):
         self.log.log("Enter chat_panel->OnMB_GroupWhisperTabs(self, event)", ORPG_DEBUG)
-        if event.IsChecked():
-            self.settings.set_setting("GroupWhisperTab", '1')
-        else:
-            self.settings.set_setting("GroupWhisperTab", '0')
+        if event.IsChecked(): self.settings.set_setting("GroupWhisperTab", '1')
+        else: self.settings.set_setting("GroupWhisperTab", '0')
         self.log.log("Exit chat_panel->OnMB_GroupWhisperTabs(self, event)", ORPG_DEBUG)
 
 
@@ -754,19 +709,13 @@
         if event.IsChecked():
             self.settings.set_setting("DiceButtons_On", '1')
             act = '1'
-        else:
-            self.settings.set_setting("DiceButtons_On", '0')
+        else: self.settings.set_setting("DiceButtons_On", '0')
         self.toggle_dice(act)
-        try:
-            self.parent.GMChatPanel.toggle_dice(act)
-        except:
-            pass
-        for panel in self.parent.whisper_tabs:
-            panel.toggle_dice(act)
-        for panel in self.parent.group_tabs:
-            panel.toggle_dice(act)
-        for panel in self.parent.null_tabs:
-            panel.toggle_dice(act)
+        try: self.parent.GMChatPanel.toggle_dice(act)
+        except: pass
+        for panel in self.parent.whisper_tabs: panel.toggle_dice(act)
+        for panel in self.parent.group_tabs: panel.toggle_dice(act)
+        for panel in self.parent.null_tabs: panel.toggle_dice(act)
         self.log.log("Exit chat_panel->OnMB_DiceBar(self, event)", ORPG_DEBUG)
 
     def OnMB_FormatButtons(self, event):
@@ -778,16 +727,11 @@
         else:
             self.settings.set_setting("FormattingButtons_On", '0')
         self.toggle_formating(act)
-        try:
-            self.parent.GMChatPanel.toggle_formating(act)
-        except:
-            pass
-        for panel in self.parent.whisper_tabs:
-            panel.toggle_formating(act)
-        for panel in self.parent.group_tabs:
-            panel.toggle_formating(act)
-        for panel in self.parent.null_tabs:
-            panel.toggle_formating(act)
+        try: self.parent.GMChatPanel.toggle_formating(act)
+        except: pass
+        for panel in self.parent.whisper_tabs: panel.toggle_formating(act)
+        for panel in self.parent.group_tabs: panel.toggle_formating(act)
+        for panel in self.parent.null_tabs: panel.toggle_formating(act)
         self.log.log("Exit chat_panel->OnMB_FormatButtons(self, event)", ORPG_DEBUG)
 
     def OnMB_AliasTool(self, event):
@@ -796,19 +740,13 @@
         if event.IsChecked():
             self.settings.set_setting("AliasTool_On", '1')
             act = '1'
-        else:
-            self.settings.set_setting("AliasTool_On", '0')
+        else: self.settings.set_setting("AliasTool_On", '0')
         self.toggle_alias(act)
-        try:
-            self.parent.GMChatPanel.toggle_alias(act)
-        except:
-            pass
-        for panel in self.parent.whisper_tabs:
-            panel.toggle_alias(act)
-        for panel in self.parent.group_tabs:
-            panel.toggle_alias(act)
-        for panel in self.parent.null_tabs:
-            panel.toggle_alias(act)
+        try: self.parent.GMChatPanel.toggle_alias(act)
+        except: pass
+        for panel in self.parent.whisper_tabs: panel.toggle_alias(act)
+        for panel in self.parent.group_tabs: panel.toggle_alias(act)
+        for panel in self.parent.null_tabs:panel.toggle_alias(act)
         self.log.log("Exit chat_panel->OnMB_AliasTool(self, event)", ORPG_DEBUG)
 
     def OnMB_BackgroundColor(self, event):
@@ -889,10 +827,10 @@
         if (self.sendtarget == "all"):
             wx.CallAfter(self.Post, self.colorize(self.syscolor, "<b>Welcome to <a href='http://www.openrpg.com'>OpenRPG</a> version " + self.version + "...  </b>"))
             #self.chat_cmds.on_help()
-        self.chattxt = orpg.tools.predTextCtrl.predTextCtrl(self, -1, "", style=wx.TE_PROCESS_ENTER | wx.TE_PROCESS_TAB,keyHook = self.myKeyHook, validator=None )
+        self.chattxt = orpg.tools.predTextCtrl.predTextCtrl(self, -1, "", style=wx.TE_PROCESS_ENTER |wx.TE_PROCESS_TAB|wx.TE_LINEWRAP, keyHook = self.myKeyHook, validator=None )
         self.build_bar()
         self.basesizer = wx.BoxSizer(wx.VERTICAL)
-        self.basesizer.Add( self.chatwnd,1,wx.EXPAND )
+        self.basesizer.Add( self.chatwnd, 1, wx.EXPAND )
         self.basesizer.Add( self.toolbar_sizer, 0, wx.EXPAND )
         self.basesizer.Add( self.chattxt, 0, wx.EXPAND )
         self.SetSizer(self.basesizer)
@@ -928,10 +866,8 @@
     # def build_ctrls - end
 
     def textCopy(self, event):
-        if self.chattxt.GetStringSelection() == '':
-            self.chatwnd.OnM_EditCopy(None)
-        else:
-            self.chatwnd.Copy()
+        if self.chattxt.GetStringSelection() == '': self.chatwnd.OnM_EditCopy(None)
+        else: self.chatwnd.Copy()
 
     def build_bar(self):
         self.log.log("Enter chat_panel->build_bar(self)", ORPG_DEBUG)
@@ -967,10 +903,8 @@
         self.toolbar_sizer.Add( self.aliasList,0,wx.EXPAND)
         self.toolbar_sizer.Add( self.filterButton, 0, wx.EXPAND )
         self.toolbar_sizer.Add( self.filterList,0,wx.EXPAND)
-        if self.settings.get_setting('AliasTool_On') == '0':
-            self.toggle_alias('0')
-        else:
-            self.toggle_alias('1')
+        if self.settings.get_setting('AliasTool_On') == '0': self.toggle_alias('0')
+        else: self.toggle_alias('1')
         self.log.log("Exit chat_panel->build_alias(self)", ORPG_DEBUG)
 
     def toggle_alias(self, act):
@@ -1014,10 +948,8 @@
         self.toolbar_sizer.Add( self.d20Button, 0 ,wx.EXPAND)
         self.toolbar_sizer.Add( self.d100Button, 0 ,wx.EXPAND)
         self.toolbar_sizer.Add( self.dieModText, 0, wx.ALIGN_CENTER, 5 )
-        if self.settings.get_setting('DiceButtons_On') == '0':
-            self.toggle_dice('0')
-        else:
-            self.toggle_dice('1')
+        if self.settings.get_setting('DiceButtons_On') == '0': self.toggle_dice('0')
+        else: self.toggle_dice('1')
         self.log.log("Exit chat_panel->build_dice(self)", ORPG_DEBUG)
 
     def toggle_dice(self, act):
@@ -1054,10 +986,8 @@
         self.toolbar_sizer.Add( self.boldButton, 0, wx.EXPAND )
         self.toolbar_sizer.Add( self.italicButton, 0, wx.EXPAND )
         self.toolbar_sizer.Add( self.underlineButton, 0, wx.EXPAND )
-        if self.settings.get_setting('FormattingButtons_On') == '0':
-            self.toggle_formating('0')
-        else:
-            self.toggle_formating('1')
+        if self.settings.get_setting('FormattingButtons_On') == '0': self.toggle_formating('0')
+        else: self.toggle_formating('1')
         self.log.log("Exit chat_panel->build_formating(self)", ORPG_DEBUG)
 
     def toggle_formating(self, act):
@@ -1101,10 +1031,8 @@
                 try:
                     link = lnk.GetHref()
                     self.session.set_status_url(link)
-                except:
-                    pass
-        else:
-            self.log.log("Error, self.chatwnd.GetInternalRepresentation() return None", ORPG_GENERAL)
+                except: pass
+        else: self.log.log("Error, self.chatwnd.GetInternalRepresentation() return None", ORPG_GENERAL)
         evt.Skip()
         self.log.log("Exit chat_panel->OnMotion(self, evt)", ORPG_DEBUG)
 
@@ -1139,8 +1067,7 @@
         ##############refresh_counter()##############
         for plugin_fname in self.activeplugins.keys():
             plugin = self.activeplugins[plugin_fname]
-            try:
-                plugin.refresh_counter()
+            try: plugin.refresh_counter()
             except Exception, e:
                 if str(e) != "'module' object has no attribute 'refresh_counter'":
                     self.log.log(traceback.format_exc(), ORPG_GENERAL)
@@ -1162,15 +1089,13 @@
             self.lastSend = time.time()  #  remember our send time for use in myKeyHook()
             #I think this is cleaner
             status_text = self.settings.get_setting('TypingStatusAlias')
-            if status_text == "" or status_text == None:
-                status_text = "Typing"
+            if status_text == "" or status_text == None: status_text = "Typing"
             self.session.set_text_status(status_text)
         else:
             self.lastSend = 0                            #  set lastSend to zero to indicate we're not typing
             #I think this is cleaner
             status_text = self.settings.get_setting('IdleStatusAlias')
-            if status_text == "" or status_text == None:
-                status_text = "Idle"
+            if status_text == "" or status_text == None: status_text = "Idle"
             self.session.set_text_status(status_text)
         self.log.log("Exit chat_panel->sendTyping(self, typing)", ORPG_DEBUG)
 
@@ -1263,16 +1188,13 @@
             self.histidx = -1
             self.temptext = ""
             self.history = [s] + self.history#prepended instead of appended now, so higher index = greater age
-            if not len(macroText):
-                self.chattxt.SetValue("")
+            if not len(macroText): self.chattxt.SetValue("")
             # play sound
             sound_file = self.settings.get_setting("SendSound")
-            if sound_file != '':
-                self.sound_player.play(sound_file)
+            if sound_file != '': self.sound_player.play(sound_file)
             if s[0] != "/": ## it's not a slash command
                 s = self.ParsePost( s, True, True )
-            else:
-                self.chat_cmds.docmd(s) # emote is in chatutils.py
+            else: self.chat_cmds.docmd(s) # emote is in chatutils.py
 
         ## UP KEY
         elif event.GetKeyCode() == wx.WXK_UP:
@@ -1281,8 +1203,7 @@
                 #text that's not in history but also hasn't been sent to chat gets stored in self.temptext
                 #this way if someone presses the up key, they don't lose their current message permanently
                 #(unless they also press enter at the time)
-                if self.histidx is -1:
-                    self.temptext = self.chattxt.GetValue()
+                if self.histidx is -1: self.temptext = self.chattxt.GetValue()
                 self.histidx += 1
                 self.chattxt.SetValue(self.history[self.histidx])
                 self.chattxt.SetInsertionPointEnd()
@@ -1299,11 +1220,9 @@
                 self.histidx -= 1
                 if self.histidx is -1: #remember, it just decreased
                     self.chattxt.SetValue(self.temptext)
-                else:
-                    self.chattxt.SetValue(self.history[self.histidx])
+                else: self.chattxt.SetValue(self.history[self.histidx])
                 self.chattxt.SetInsertionPointEnd()
-            else:
-                self.histidx = -1 #just in case it somehow got below -1, this should fix it
+            else: self.histidx = -1 #just in case it somehow got below -1, this should fix it
                 #self.InfoPost("**Going down? I don't think so.**")
             #print self.histidx, "in",self.history
 
@@ -1350,14 +1269,12 @@
         elif event.GetKeyCode() in (wx.WXK_PRIOR, wx.WXK_PAGEUP):
             self.log.log("event.GetKeyCode() in (wx.WXK_PRIOR, wx.WXK_PAGEUP)", ORPG_DEBUG)
             self.chatwnd.ScrollPages(-1)
-            if not self.lockscroll:
-                self.lock_scroll(0)
+            if not self.lockscroll: self.lock_scroll(0)
 
         ## PAGE DOWN
         elif event.GetKeyCode() in (wx.WXK_NEXT, wx.WXK_PAGEDOWN):
             self.log.log("event.GetKeyCode() in (wx.WXK_NEXT, wx.WXK_PAGEDOWN)", ORPG_DEBUG)
-            if not self.lockscroll:
-                self.lock_scroll(0)
+            if not self.lockscroll: self.lock_scroll(0)
             if ((self.chatwnd.GetScrollRange(1)-self.chatwnd.GetScrollPos(1)-self.chatwnd.GetScrollThumb(1) < 30) and self.lockscroll):
                 self.lock_scroll(0)
             self.chatwnd.ScrollPages(1)
@@ -1371,8 +1288,7 @@
             event.Skip()
 
         ## NOTHING
-        else:
-            event.Skip()
+        else: event.Skip()
         self.log.log("Exit chat_panel->OnChar(self, event)", ORPG_DEBUG)
     # def OnChar - end
 
@@ -1385,10 +1301,8 @@
         dieText = numDie
         # Now, apply and roll die mods based on the button that was pressed
         id = evt.GetId()
-        if self.dieIDs.has_key(id):
-            dieText += self.dieIDs[id]
-        if len(dieMod) and dieMod[0] not in "*/-+":
-            dieMod = "+" + dieMod
+        if self.dieIDs.has_key(id): dieText += self.dieIDs[id]
+        if len(dieMod) and dieMod[0] not in "*/-+": dieMod = "+" + dieMod
         dieText += dieMod
         dieText = "[" + dieText + "]"
         self.ParsePost(dieText, 1, 1)
@@ -1462,20 +1376,13 @@
         id = event.GetId()
         txt = self.chattxt.GetValue()
         (beg,end) = self.chattxt.GetSelection()
-        if beg != end:
-            sel_txt = txt[beg:end]
-        else:
-            sel_txt = txt
-        if id == self.boldButton.GetId():
-            sel_txt = "<b>" + sel_txt + "</b>"
-        elif id == self.italicButton.GetId():
-            sel_txt = "<i>" + sel_txt + "</i>"
-        elif id == self.underlineButton.GetId():
-            sel_txt = "<u>" + sel_txt + "</u>"
-        if beg != end:
-            txt = txt[:beg] + sel_txt + txt[end:]
-        else:
-            txt = sel_txt
+        if beg != end: sel_txt = txt[beg:end]
+        else: sel_txt = txt
+        if id == self.boldButton.GetId(): sel_txt = "<b>" + sel_txt + "</b>"
+        elif id == self.italicButton.GetId(): sel_txt = "<i>" + sel_txt + "</i>"
+        elif id == self.underlineButton.GetId(): sel_txt = "<u>" + sel_txt + "</u>"
+        if beg != end: txt = txt[:beg] + sel_txt + txt[end:]
+        else: txt = sel_txt
         self.chattxt.SetValue(txt)
         self.chattxt.SetInsertionPointEnd()
         self.chattxt.SetFocus()
@@ -1488,8 +1395,7 @@
             self.lockscroll = False
             self.scroll_lock.SetLabel("Scroll ON")
             if len(self.storedata) != 0:
-                for line in self.storedata:
-                    self.chatwnd.AppendToPage(line)
+                for line in self.storedata: self.chatwnd.AppendToPage(line)
             self.storedata = []
             self.scroll_down()
         else:
@@ -1547,8 +1453,7 @@
         the_gms = []
         for playerid in self.session.players:
             if len(self.session.players[playerid])>7:
-                if self.session.players[playerid][7]=="GM" and self.session.group_id != '0':
-                    the_gms += [playerid]
+                if self.session.players[playerid][7]=="GM" and self.session.group_id != '0': the_gms += [playerid]
         self.log.log("Exit chat_panel->get_gms(self)", ORPG_DEBUG)
         return the_gms
 
@@ -1571,8 +1476,7 @@
         if self.AliasLib != None:
             self.AliasLib.filter = self.filterList.GetSelection()-1;
             for rule in self.AliasLib.filterRegEx:
-                if not self.advancedFilter:
-                    text = re.sub(rule[0], rule[1], text)
+                if not self.advancedFilter: text = re.sub(rule[0], rule[1], text)
                 else:
                     for m in advregex.finditer(text):
                         match = m.group(0)
@@ -1586,20 +1490,16 @@
         text = self.NormalizeParse(text)
         text = self.colorize(self.emotecolor, text)
 
-        if self.type == MAIN_TAB and self.sendtarget == 'all':
-            self.send_chat_message(text,chat_msg.EMOTE_MESSAGE)
+        if self.type == MAIN_TAB and self.sendtarget == 'all': self.send_chat_message(text,chat_msg.EMOTE_MESSAGE)
         elif self.type == MAIN_TAB and self.sendtarget == "gm":
             msg_type = chat_msg.WHISPER_EMOTE_MESSAGE
             the_gms = self.get_gms()
-            for each_gm in the_gms:
-                self.send_chat_message(text,chat_msg.WHISPER_EMOTE_MESSAGE, str(each_gm))
+            for each_gm in the_gms: self.send_chat_message(text,chat_msg.WHISPER_EMOTE_MESSAGE, str(each_gm))
         elif self.type == GROUP_TAB and WG_LIST.has_key(self.sendtarget):
             for pid in WG_LIST[self.sendtarget]:
                 self.send_chat_message(text,chat_msg.WHISPER_EMOTE_MESSAGE, str(pid))
-        elif self.type == WHISPER_TAB:
-            self.send_chat_message(text,chat_msg.WHISPER_EMOTE_MESSAGE, str(self.sendtarget))
-        elif self.type == NULL_TAB:
-            pass
+        elif self.type == WHISPER_TAB: self.send_chat_message(text,chat_msg.WHISPER_EMOTE_MESSAGE, str(self.sendtarget))
+        elif self.type == NULL_TAB: pass
         name = self.GetName()[0]
         text = "** " + name + " " + text + " **"
         self.EmotePost(text)
@@ -1629,10 +1529,8 @@
         text = self.colorize(self.mytextcolor, text)
         for id in player_ids:
             id = id.strip()
-            if self.session.is_valid_id(id):
-                self.send_chat_message(text,chat_msg.WHISPER_MESSAGE,id)
-            else:
-                self.InfoPost(id + " Unknown!")
+            if self.session.is_valid_id(id): self.send_chat_message(text,chat_msg.WHISPER_MESSAGE,id)
+            else: self.InfoPost(id + " Unknown!")
         self.log.log("Exit chat_panel->whisper_to_players(self, text, player_ids)", ORPG_DEBUG)
 
     def send_chat_message(self, text, type=chat_msg.CHAT_MESSAGE, player_id="all"):
@@ -1641,8 +1539,7 @@
         send = 1
         for plugin_fname in self.activeplugins.keys():
             plugin = self.activeplugins[plugin_fname]
-            try:
-                text, send = plugin.send_msg(text, send)
+            try: text, send = plugin.send_msg(text, send)
             except Exception, e:
                 if str(e) != "'module' object has no attribute 'send_msg'":
                     self.log.log(traceback.format_exc(), ORPG_GENERAL)
@@ -1656,11 +1553,9 @@
             self.settings.set_setting("ShowIDInChat", "0")
         playername = self.GetName()[0]
 
-        if turnedoff:
-            self.settings.set_setting("ShowIDInChat", "1")
+        if turnedoff: self.settings.set_setting("ShowIDInChat", "1")
         msg.set_alias(playername)
-        if send:
-            self.session.send(msg.toxml(),player_id)
+        if send: self.session.send(msg.toxml(),player_id)
         del msg
         self.log.log("Exit chat_panel->send_chat_message(self, text, type, player_id)", ORPG_DEBUG)
 
@@ -1673,18 +1568,14 @@
         text = msg.get_text()
         alias = msg.get_alias()
         # who sent us the message?
-        if alias:
-            display_name = self.chat_display_name([alias, player[1], player[2]])
-        elif player:
-            display_name = self.chat_display_name(player)
-        else:
-            display_name = "Server Administrator"
+        if alias: display_name = self.chat_display_name([alias, player[1], player[2]])
+        elif player: display_name = self.chat_display_name(player)
+        else: display_name = "Server Administrator"
 
         ######### START plugin_incoming_msg() ###########
         for plugin_fname in self.activeplugins.keys():
             plugin = self.activeplugins[plugin_fname]
-            try:
-                text, type, name = plugin.plugin_incoming_msg(text, type, display_name, player)
+            try: text, type, name = plugin.plugin_incoming_msg(text, type, display_name, player)
             except Exception, e:
                 if str(e) != "'module' object has no attribute 'receive_msg'":
                     self.log.log(traceback.format_exc(), ORPG_GENERAL)
@@ -1692,8 +1583,7 @@
         #end mDuo13 added code
         #image stripping for players' names
         strip_img = self.settings.get_setting("Show_Images_In_Chat")
-        if (strip_img == "0"):
-            display_name = chat_util.strip_img_tags(display_name)
+        if (strip_img == "0"): display_name = chat_util.strip_img_tags(display_name)
         #end image stripping. --mDuo13, July 11th, 2005
         # default sound
         recvSound = "RecvSound"
@@ -1719,10 +1609,8 @@
                     #Check if whisper if from a GM
                     if player[2] in the_gms:
                         msg = name + ' (GM Whisper:) ' + text
-                        if type == chat_msg.WHISPER_MESSAGE:
-                            self.parent.GMChatPanel.Post(msg)
-                        else:
-                            self.parent.GMChatPanel.EmotePost("**" + msg + "**")
+                        if type == chat_msg.WHISPER_MESSAGE: self.parent.GMChatPanel.Post(msg)
+                        else: self.parent.GMChatPanel.EmotePost("**" + msg + "**")
                         idx = self.parent.get_tab_index(self.parent.GMChatPanel)
                         self.parent.newMsg(idx)
                         panelexists = 1
@@ -1731,10 +1619,8 @@
                     for panel in self.parent.group_tabs:
                         if WG_LIST.has_key(panel.sendtarget) and WG_LIST[panel.sendtarget].has_key(int(player[2])):
                             msg = name + text
-                            if type == chat_msg.WHISPER_MESSAGE:
-                                panel.Post(msg)
-                            else:
-                                panel.EmotePost("**" + msg + "**")
+                            if type == chat_msg.WHISPER_MESSAGE: panel.Post(msg)
+                            else: panel.EmotePost("**" + msg + "**")
                             idx = self.parent.get_tab_index(panel)
                             self.parent.newMsg(idx)
                             panelexists = 1
@@ -1744,10 +1630,8 @@
                         #check for whisper tabs as well, to save the number of loops
                         if panel.sendtarget == player[2]:
                             msg = name + whisperingstring + text
-                            if type == chat_msg.WHISPER_MESSAGE:
-                                panel.Post(msg)
-                            else:
-                                panel.EmotePost("**" + msg + "**")
+                            if type == chat_msg.WHISPER_MESSAGE: panel.Post(msg)
+                            else: panel.EmotePost("**" + msg + "**")
                             idx = self.parent.get_tab_index(panel)
                             self.parent.newMsg(idx)
                             panelexists = 1
@@ -1762,28 +1646,22 @@
                                 #Yup, post message. Player may be in more then 1 group so continue as well
                                 panel = self.parent.create_group_tab(group)
                                 msg = name + text
-                                if type == chat_msg.WHISPER_MESSAGE:
-                                    wx.CallAfter(panel.Post, msg)
-                                else:
-                                    wx.CallAfter(panel.EmotePost, "**" + msg + "**")
+                                if type == chat_msg.WHISPER_MESSAGE: wx.CallAfter(panel.Post, msg)
+                                else: wx.CallAfter(panel.EmotePost, "**" + msg + "**")
                                 created = 1
                     #Check to see if we should create a whisper tab
                     if not created and tabbed_whispers_p == "1":
                         panel = self.parent.create_whisper_tab(player[2])
                         msg = name + whisperingstring + text
-                        if type == chat_msg.WHISPER_MESSAGE:
-                            wx.CallAfter(panel.Post, msg)
-                        else:
-                            wx.CallAfter(panel.EmotePost, "**" + msg + "**")
+                        if type == chat_msg.WHISPER_MESSAGE: wx.CallAfter(panel.Post, msg)
+                        else: wx.CallAfter(panel.EmotePost, "**" + msg + "**")
                         created = 1
                     #Final check
                     if not created:
                         #No tabs to create, just send the message to the main chat tab
                         msg = name + whisperingstring + text
-                        if type == chat_msg.WHISPER_MESSAGE:
-                            self.parent.MainChatPanel.Post(msg)
-                        else:
-                            self.parent.MainChatPanel.EmotePost("**" + msg + "**")
+                        if type == chat_msg.WHISPER_MESSAGE: self.parent.MainChatPanel.Post(msg)
+                        else: self.parent.MainChatPanel.EmotePost("**" + msg + "**")
                         self.parent.newMsg(0)
             except Exception, e:
                 self.log.log(traceback.format_exc(), ORPG_GENERAL)
@@ -1808,34 +1686,32 @@
     #### Posting helpers #####
 
     def InfoPost(self, s):
-        self.log.log("Enter chat_panel->InfoPost(self, s)", ORPG_DEBUG)
-        self.Post(self.colorize(self.infocolor, s))
+        self.log.log("Enter chat_panel->InfoPost(self, s)", ORPG_DEBUG)
+        self.Post(self.colorize(self.infocolor, s), c='info')
         self.log.log("Exit chat_panel->InfoPost(self, s)", ORPG_DEBUG)
 
     def SystemPost(self, s):
-        self.log.log("Enter chat_panel->SystemPost(self, s)", ORPG_DEBUG)
-        self.Post(self.colorize(self.syscolor, s))
+        self.log.log("Enter chat_panel->SystemPost(self, s)", ORPG_DEBUG)
+        self.Post(self.colorize(self.syscolor, s), c='system')
         self.log.log("Exit chat_panel->SystemPost(self, s)", ORPG_DEBUG)
 
     def EmotePost(self, s):
-        self.log.log("Enter chat_panel->EmotePost(self, s)", ORPG_DEBUG)
-        self.Post(self.colorize(self.emotecolor, s))
+        self.log.log("Enter chat_panel->EmotePost(self, s)", ORPG_DEBUG)
+        self.Post(self.colorize(self.emotecolor, s), c='emote')
         self.log.log("Exit chat_panel->EmotePost(self, s)", ORPG_DEBUG)
 
     #### Standard Post method #####
-    def Post(self, s="", send=False, myself=False):
+    def Post(self, s="", send=False, myself=False, c='post'):
         self.log.log("Enter chat_panel->Post(self, s, send, myself)", ORPG_DEBUG)
         strip_p = self.settings.get_setting("striphtml")
         strip_img = self.settings.get_setting("Show_Images_In_Chat")#moved back 7-11-05. --mDuo13
-        if (strip_p == "1"):
-            s = strip_html(s)
-        if (strip_img == "0"):
-            s = chat_util.strip_img_tags(s)
+        if (strip_p == "1"): s = strip_html(s)
+        if (strip_img == "0"): s = chat_util.strip_img_tags(s)
         s = chat_util.simple_html_repair(s)
         s = chat_util.strip_script_tags(s)
         s = chat_util.strip_li_tags(s)
-        s = chat_util.strip_body_tags(s)#7-27-05 mDuo13
-        s = chat_util.strip_misalignment_tags(s)#7-27-05 mDuo13
+        s = chat_util.strip_body_tags(s) #7-27-05 mDuo13
+        s = chat_util.strip_misalignment_tags(s) #7-27-05 mDuo13
         aliasInfo = self.GetName()
         display_name = aliasInfo[0]
         if aliasInfo[1] != 'Default':
@@ -1848,8 +1724,7 @@
         if not myself and not send:
             for plugin_fname in self.activeplugins.keys():
                 plugin = self.activeplugins[plugin_fname]
-                try:
-                    s = plugin.post_msg(s, myself)
+                try: s = plugin.post_msg(s, myself)
                 except Exception, e:
                     if str(e) != "'module' object has no attribute 'post_msg'":
                         self.log.log(traceback.format_exc(), ORPG_GENERAL)
@@ -1858,8 +1733,7 @@
         if myself:
             name = "<b>" + display_name + "</b>: "
             s = self.colorize(self.mytextcolor, s)
-        else:
-            name = ""
+        else: name = ""
         if aliasInfo[1] != 'Default':
             self.settings.set_setting("mytextcolor", defaultcolor)
             self.set_colors()
@@ -1867,8 +1741,7 @@
         # EDIT: Had to rework blank line check to handle malformed HTML throwing error.
         #       this limits the effectiveness of this check -SD
         lineHasText = 1
-        try:
-            lineHasText = strip_html(s).replace("&nbsp;","").replace(" ","").strip()!=""
+        try: lineHasText = strip_html(s).replace("&nbsp;","").replace(" ","").strip()!=""
         except:
             # HTML parser has errored out (most likely). Being as all we are doing is
             # scanning for empty/blank lines anyway there is no harm in letting a
@@ -1892,42 +1765,32 @@
                     if self.type == WHISPER_TAB or self.type == GROUP_TAB or self.sendtarget == 'gm':
                         s2 = s2 + '</i>'
                         name = '<i>' + name
-                        if self.type == WHISPER_TAB:
-                            name += " (whispering): "
-                        elif self.type == GROUP_TAB:
-                            name += self.settings.get_setting("gwtext") + ' '
-                        elif self.sendtarget == 'gm':
-                            name += " (whispering to GM) "
-                    newline = self.TimeIndexString() + name +  s2 + "<br />"
-                    log( self.settings, name + s2 )
+                        if self.type == WHISPER_TAB: name += " (whispering): "
+                        elif self.type == GROUP_TAB: name += self.settings.get_setting("gwtext") + ' '
+                        elif self.sendtarget == 'gm': name += " (whispering to GM) "
+                    newline = self.TimeIndexString() + "<div class='"+c+"'> " +name + s2 + "</div>"
+                    log( self.settings, c+' '+name + s2 )
             else:
-                newline = self.TimeIndexString() + name +  s + "<br />"
-                log( self.settings, name + s )
-        else:
-            send = False
+                newline = self.TimeIndexString() + "<div class='"+c+"'> " +name + s + "</div>"
+                log( self.settings, c+' '+name + s )
+        else: send = False
         newline = chat_util.strip_unicode(newline)
         if self.lockscroll == 0:
             self.chatwnd.AppendToPage(newline)
             self.scroll_down()
-        else:
-            self.storedata.append(newline)
-        if send:
-            if self.type == MAIN_TAB and self.sendtarget == 'all':
-                self.send_chat_message(s)
+        else: self.storedata.append(newline)
+        if send:
+            if self.type == MAIN_TAB and self.sendtarget == 'all': self.send_chat_message(s)
             elif self.type == MAIN_TAB and self.sendtarget == "gm":
                 the_gms = self.get_gms()
                 self.whisper_to_players(s, the_gms)
             elif self.type == GROUP_TAB and WG_LIST.has_key(self.sendtarget):
                 members = []
-                for pid in WG_LIST[self.sendtarget]:
-                    members.append(str(WG_LIST[self.sendtarget][pid]))
+                for pid in WG_LIST[self.sendtarget]: members.append(str(WG_LIST[self.sendtarget][pid]))
                 self.whisper_to_players(self.settings.get_setting("gwtext") + s, members)
-            elif self.type == WHISPER_TAB:
-                self.whisper_to_players(s, [self.sendtarget])
-            elif self.type == NULL_TAB:
-                pass
-            else:
-                self.InfoPost("Failed to send message, unknown send type for this tab")
+            elif self.type == WHISPER_TAB: self.whisper_to_players(s, [self.sendtarget])
+            elif self.type == NULL_TAB: pass
+            else: self.InfoPost("Failed to send message, unknown send type for this tab")
         self.parsed=0
         self.log.log("Exit chat_panel->Post(self, s, send, myself)", ORPG_DEBUG)
 
@@ -1940,8 +1803,7 @@
         self.log.log("Enter chat_panel->TimeIndexString(self)", ORPG_DEBUG)
         try:
             mtime = ""
-            if self.settings.get_setting('Chat_Time_Indexing') == "0":
-                pass
+            if self.settings.get_setting('Chat_Time_Indexing') == "0": pass
             elif self.settings.get_setting('Chat_Time_Indexing') == "1":
                 mtime = time.strftime("[%I:%M:%S] ", time.localtime())
             self.log.log("Exit chat_panel->TimeIndexString(self)", ORPG_DEBUG)
@@ -1963,8 +1825,7 @@
         self.log.log("Enter chat_panel->NormalizeParse(self, s)", ORPG_DEBUG)
         for plugin_fname in self.activeplugins.keys():
             plugin = self.activeplugins[plugin_fname]
-            try:
-                s = plugin.pre_parse(s)
+            try: s = plugin.pre_parse(s)
             except Exception, e:
                 if str(e) != "'module' object has no attribute 'post_msg'":
                     self.log.log(traceback.format_exc(), ORPG_GENERAL)
@@ -2008,14 +1869,11 @@
             if newstr[0].lower() == 'q':
                 newstr = newstr[1:]
                 qmode = 1
-            try:
-                newstr = self.DiceManager.proccessRoll(newstr)
-            except:
-                pass
+            try: newstr = self.DiceManager.proccessRoll(newstr)
+            except: pass
             if qmode == 1:
                 s = s.replace("[" + matches[i] + "]", "<!-- Official Roll [" + newstr1 + "] => " + newstr + "-->" + newstr, 1)
-            else:
-                s = s.replace("[" + matches[i] + "]", "[" + newstr1 + "<!-- Official Roll -->] => " + newstr, 1)
+            else: s = s.replace("[" + matches[i] + "]", "[" + newstr1 + "<!-- Official Roll -->] => " + newstr, 1)
         self.log.log("Exit chat_panel->ParseDice(self, s)", ORPG_DEBUG)
         return s
 
@@ -2033,10 +1891,8 @@
             dlg.SetValue('')
             if matches[i][0] != '':
                 dlg.SetTitle("Enter Value for " + matches[i][1])
-            if dlg.ShowModal() == wx.ID_OK:
-                newstr = dlg.GetValue()
-            if newstr == '':
-                newstr = '0'
+            if dlg.ShowModal() == wx.ID_OK: newstr = dlg.GetValue()
+            if newstr == '': newstr = '0'
             s = s.replace(matches[i][0], newstr, 1).replace(matches[i][1], '', 1).replace(matches[i][2], '', 1)
             dlg.Destroy()
         self.log.log("Exit chat_panel->PraseUnknowns(self, s)", ORPG_DEBUG)
--- a/orpg/gametree/nodehandlers/StarWarsd20.py	Sat Aug 08 00:35:09 2009 -0500
+++ b/orpg/gametree/nodehandlers/StarWarsd20.py	Thu Aug 13 13:14:10 2009 -0500
@@ -1,1833 +1,1840 @@
-# Copyright (C) 2000-2001 The OpenRPG Project
-#
-#        openrpg-dev@lists.sourceforge.net
-#
-# This program is free software; you can redistribute it and/or modify
-# it under the terms of the GNU General Public License as published by
-# the Free Software Foundation; either version 2 of the License, or
-# (at your option) any later version.
-#
-# 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., 675 Mass Ave, Cambridge, MA 02139, USA.
-# --
-#
-# File: StarWarsd20.py
-# Author: Chris Davis; Mark Twombley
-# Maintainer: Mark Twombley
-# Version:
-#   $Id: StarWarsd20.py,v 1.18 2006/11/15 12:11:23 digitalxero Exp $
-#
-# Description: The file contains code for the StarWarsd20 nodehanlers
-#
-
-__version__ = "$Id: StarWarsd20.py,v 1.18 2006/11/15 12:11:23 digitalxero Exp $"
-
-from core import *
-
-SWD20_EXPORT = wx.NewId()
-############################
-## StarWarsd20 character node handler
-############################
-##The whole look and easy of use redone by Digitalxero
-class container_handler(node_handler):
-    """ should not be used! only a base class!
-    <nodehandler name='?'  module='core' class='container_handler'  />
-    """
-    def __init__(self,xml_dom,tree_node):
-        node_handler.__init__(self,xml_dom,tree_node)
-        self.load_children()
-
-    def load_children(self):
-        children = self.master_dom._get_childNodes()
-        for c in children:
-            self.tree.load_xml(c,self.mytree_node)
-
-
-    def on_drop(self,evt):
-        drag_obj = self.tree.drag_obj
-        #if self.is_my_child(self.mytree_node,drag_obj.mytree_node):
-        #    return
-        if drag_obj == self:
-            return
-        opt = wx.MessageBox("Add node as child?","Container Node",wx.YES_NO|wx.CANCEL)
-        if opt == wx.YES:
-            xml_dom = self.tree.drag_obj.delete()
-            xml_dom = self.master_dom.insertBefore(xml_dom,None)
-            self.tree.load_xml(xml_dom, self.mytree_node)
-            self.tree.Expand(self.mytree_node)
-        elif opt == wx.NO:
-            node_handler.on_drop(self,evt)
-
-    def tohtml(self):
-        cookie = 0
-        html_str = "<table border=\"1\" ><tr><td>"
-        html_str += "<b>"+self.master_dom.getAttribute("name") + "</b>"
-        html_str += "</td></tr>\n"
-        html_str += "<tr><td>"
-        max = tree.GetChildrenCount(handler.mytree_node)
-        try:
-            (child,cookie)=self.tree.GetFirstChild(self.mytree_node,cookie)
-        except: # If this happens we probably have a newer version of wxPython
-            (child,cookie)=self.tree.GetFirstChild(self.mytree_node)
-        obj = self.tree.GetPyData(child)
-        for m in xrange(max):
-            html_str += "<p>" + obj.tohtml()
-            if m < max-1:
-                child = self.tree.GetNextSibling(child)
-                obj = self.tree.GetPyData(child)
-        html_str += "</td></tr></table>"
-        return html_str
-
-    def get_size_constraint(self):
-        return 1
-
-    def get_char_name( self ):
-        return self.child_handlers['general'].get_char_name()
-
-##    def set_char_pp(self,attr,evl):
-##        return self.child_handlers['pp'].set_char_pp(attr,evl)
-##
-##    def get_char_pp( self, attr ):
-##        return self.child_handlers['pp'].get_char_pp(attr)
-##
-    def get_char_lvl( self, attr ):
-        return self.child_handlers['classes'].get_char_lvl(attr)
-
-
-
-class SWd20char_handler(node_handler):
-    """ Node handler for a SWd20 charactor
-        <nodehandler name='?'  module='StarWarsd20' class='SWd20char_handler'  />
-    """
-    def __init__(self,xml_dom,tree_node):
-        node_handler.__init__(self,xml_dom,tree_node)
-        self.frame = open_rpg.get_component('frame')
-        self.child_handlers = {}
-        self.new_child_handler('howtouse','HowTO use this tool',SWd20howto,'note')
-        self.new_child_handler('general','General Information',SWd20general,'gear')
-        self.new_child_handler('inventory','Money and Inventory',SWd20inventory,'money')
-        self.new_child_handler('abilities','Abilities Scores',SWd20ability,'gear')
-        self.new_child_handler('classes','Classes',SWd20classes,'knight')
-        self.new_child_handler('saves','Saves',SWd20saves,'skull')
-        self.new_child_handler('skills','Skills',SWd20skill,'book')
-        self.new_child_handler('feats','Feats',SWd20feats,'book')
-        self.new_child_handler('wp','Wound Points',SWd20hp,'gear')
-        self.new_child_handler('vp','Vitality Points',SWd20vp,'gear')
-        self.new_child_handler('attacks','Attacks',SWd20attacks,'spears')
-        self.new_child_handler('ac','Armor',SWd20armor,'spears')
-        self.myeditor = None
-
-
-    def on_version(self,old_version):
-        node_handler.on_version(self,old_version)
-        if old_version == "":
-            tmp = open(orpg.dirpath.dir_struct["nodes"]+"StarWars_d20character.xml","r")
-            xml_dom = parseXml_with_dlg(self.tree,tmp.read())
-            xml_dom = xml_dom._get_firstChild()
-            tmp.close()
-            ## add new nodes
-            for tag in ("howtouse","inventory","powers","divine","pp"):
-                node_list = xml_dom.getElementsByTagName(tag)
-                self.master_dom.appendChild(node_list[0])
-
-            ## add new atts
-            melee_attack = self.master_dom.getElementsByTagName('melee')[0]
-            melee_attack.setAttribute("second","0")
-            melee_attack.setAttribute("third","0")
-            melee_attack.setAttribute("forth","0")
-            melee_attack.setAttribute("fifth","0")
-            melee_attack.setAttribute("sixth","0")
-            range_attack = self.master_dom.getElementsByTagName('ranged')[0]
-            range_attack.setAttribute("second","0")
-            range_attack.setAttribute("third","0")
-            range_attack.setAttribute("forth","0")
-            range_attack.setAttribute("fifth","0")
-            range_attack.setAttribute("sixth","0")
-
-            gen_list = self.master_dom.getElementsByTagName('general')[0]
-
-            for tag in ("currentxp","xptolevel"):
-                node_list = xml_dom.getElementsByTagName(tag)
-                gen_list.appendChild(node_list[0])
-            ## temp fix
-            #parent = self.master_dom._get_parentNode()
-            #old_dom = parent.replaceChild(xml_dom,self.master_dom)
-            #self.master_dom = xml_dom
-        print old_version
-
-
-    def get_char_name( self ):
-        return self.child_handlers['general'].get_char_name()
-
-##    def set_char_pp(self,attr,evl):
-##        return self.child_handlers['pp'].set_char_pp(attr,evl)
-##
-##    def get_char_pp( self, attr ):
-##        return self.child_handlers['pp'].get_char_pp(attr)
-
-    def get_char_lvl( self, attr ):
-        return self.child_handlers['classes'].get_char_lvl(attr)
-
-
-    def new_child_handler(self,tag,text,handler_class,icon='gear'):
-        node_list = self.master_dom.getElementsByTagName(tag)
-        tree = self.tree
-        i = self.tree.icons[icon]
-        new_tree_node = tree.AppendItem(self.mytree_node,text,i,i)
-        handler = handler_class(node_list[0],new_tree_node,self)
-        tree.SetPyData(new_tree_node,handler)
-        self.child_handlers[tag] = handler
-
-    def get_design_panel(self,parent):
-        return tabbed_panel(parent,self,1)
-
-
-    def get_use_panel(self,parent):
-        return tabbed_panel(parent,self,2)
-
-
-    def tohtml(self):
-        html_str = "<table><tr><td colspan=2 >"+self.child_handlers['general'].tohtml()+"</td></tr>"
-        html_str += "<tr><td width='50%' valign=top >"+self.child_handlers['abilities'].tohtml()
-        html_str += "<P>" + self.child_handlers['saves'].tohtml()
-        html_str += "<P>" + self.child_handlers['attacks'].tohtml()
-        html_str += "<P>" + self.child_handlers['ac'].tohtml()
-        html_str += "<P>" + self.child_handlers['feats'].tohtml()
-        #html_str += "<P>" + self.child_handlers['spells'].tohtml()
-        #html_str += "<P>" + self.child_handlers['divine'].tohtml()
-        #html_str += "<P>" + self.child_handlers['powers'].tohtml()
-        html_str += "<P>" + self.child_handlers['inventory'].tohtml() +"</td>"
-        html_str += "<td width='50%' valign=top >"+self.child_handlers['classes'].tohtml()
-        html_str += "<P>" + self.child_handlers['wp'].tohtml()
-        html_str += "<P>" + self.child_handlers['vp'].tohtml()
-        #html_str += "<P>" + self.child_handlers['pp'].tohtml()
-        html_str += "<P>" + self.child_handlers['skills'].tohtml() +"</td>"
-        html_str += "</tr></table>"
-        return html_str
-
-    def about(self):
-        html_str = "<img src='" + orpg.dirpath.dir_struct["icon"]+'d20_logo.gif' "><br /><b>d20 Character Tool v0.7 beta</b>"
-        html_str += "<br />by Chris Davis<br />chris@rpgarchive.com"
-        return html_str
-
-    def get_char_name( self ):
-        return self.child_handlers['general'].get_char_name()
-    def get_armor_class( self ):
-        return self.child_handlers['ac'].get_armor_class()
-    def get_max_hp( self ):
-        return self.child_handlers['wp'].get_max_hp()
-    def get_current_hp( self ):
-        return self.child_handlers['wp'].get_current_hp()
-    def get_max_vp( self ):
-        return self.child_handlers['vp'].get_max_vp()
-    def get_current_vp( self ):
-        return self.child_handlers['vp'].get_current_vp()
-
-##    def set_char_pp(self,attr,evl):
-##        return self.child_handlers['pp'].set_char_pp(attr,evl)
-##
-##    def get_char_pp( self, attr ):
-##        return self.child_handlers['pp'].get_char_pp(attr)
-
-    def get_char_lvl( self, attr ):
-        return self.child_handlers['classes'].get_char_lvl(attr)
-
-class tabbed_panel(wx.Notebook):
-    def __init__(self, parent, handler, mode):
-        wx.Notebook.__init__(self, parent, -1, size=(1200,800))
-        self.handler = handler
-        self.parent = parent
-        tree = self.handler.tree
-        max = tree.GetChildrenCount(handler.mytree_node)
-
-        cookie = 0
-        max = tree.GetChildrenCount(handler.mytree_node)
-        try:
-            (child,cookie)=tree.GetFirstChild(handler.mytree_node,cookie)
-        except: # If this happens we probably have a newer version of wxPython
-            (child,cookie)=tree.GetFirstChild(handler.mytree_node)
-        obj = tree.GetPyData(child)
-        for m in xrange(max):
-            if mode == 1:
-                panel = obj.get_design_panel(self)
-            else:
-                panel = obj.get_use_panel(self)
-            name = obj.master_dom.getAttribute("name")
-
-            if panel:
-                self.AddPage(panel,name)
-            if m < max-1:
-                child = tree.GetNextSibling(child)
-                obj = tree.GetPyData(child)
-
-
-    def about(self):
-        html_str = "<img src='" + orpg.dirpath.dir_struct["icon"]+'d20_logo.gif' "><br /><b>d20 Character Tool v0.7 beta</b>"
-        html_str += "<br />by Chris Davis<br />chris@rpgarchive.com"
-        return html_str
-
-    def get_char_name( self ):
-        return self.child_handlers['general'].get_char_name()
-
-##    def set_char_pp(self,attr,evl):
-##        return self.child_handlers['pp'].set_char_pp(attr,evl)
-##
-##    def get_char_pp( self, attr ):
-##        return self.child_handlers['pp'].get_char_pp(attr)
-
-    def get_char_lvl( self, attr ):
-        return self.child_handlers['classes'].get_char_lvl(attr)
-
-class SWd20_char_child(node_handler):
-    """ Node Handler for skill.  This handler will be
-        created by SWd20char_handler.
-    """
-    def __init__(self, xml_dom, tree_node, parent):
-        node_handler.__init__(self,xml_dom, tree_node)
-        self.char_hander = parent
-        self.drag = False
-        self.frame = open_rpg.get_component('frame')
-        self.myeditor = None
-
-
-    def on_drop(self,evt):
-        pass
-
-    def on_rclick(self,evt):
-        pass
-
-    def on_ldclick(self,evt):
-        return
-        if self.myeditor == None or self.myeditor.destroyed:
-            title = self.master_dom.getAttribute('name') + " Editor"
-            self.myeditor = orpgPFrame(self.frame,title,orpg.dirpath.dir_struct["icon"]+'grid.ico')
-            wnd = self.get_design_panel(self.myeditor)
-            self.myeditor.panel = wnd
-            self.wnd = wnd
-            self.myeditor.Show(1)
-        else:
-            self.myeditor.Raise()
-
-    def on_html(self,evt):
-        html_str = self.tohtml()
-        wnd = http_html_window(self.frame.note,-1)
-        wnd.title = self.master_dom.getAttribute('name')
-        self.frame.add_panel(wnd)
-        wnd.SetPage(html_str)
-
-    def get_design_panel(self,parent):
-        pass
-
-    def get_use_panel(self,parent):
-        return self.get_design_panel(parent)
-
-    def delete(self):
-        pass
-
-
-class SWd20skill(SWd20_char_child):
-    """ Node Handler for skill.  This handler will be
-        created by SWd20char_handler.
-    """
-    def __init__(self, xml_dom, tree_node, parent):
-        SWd20_char_child.__init__(self, xml_dom, tree_node, parent)
-        tree = self.tree
-        icons = self.tree.icons
-        node_list = self.master_dom.getElementsByTagName('skill')
-        self.skills={}
-        for n in node_list:
-            name = n.getAttribute('name')
-            self.skills[name] = n
-            new_tree_node = tree.AppendItem(self.mytree_node,name,icons['gear'],icons['gear'])
-            tree.SetPyData(new_tree_node,self)
-
-    def get_mod(self,name):
-        skill = self.skills[name]
-        stat = skill.getAttribute('stat')
-        ac = int(skill.getAttribute('armorcheck'))
-        if ac:
-            ac = self.char_hander.child_handlers['ac'].get_check_pen()
-        stat_mod = self.char_hander.child_handlers['abilities'].get_mod(stat)
-        rank = int(skill.getAttribute('rank'))
-        misc = int(skill.getAttribute('misc'))
-        total = stat_mod + rank + misc + ac
-        return total
-
-    def on_rclick(self,evt):
-        #updated with code for untrained use check
-        item = self.tree.GetSelection()
-        name = self.tree.GetItemText(item)
-        skill = self.skills[name]
-        rank = int(skill.getAttribute('rank'))
-        untrained = int(skill.getAttribute('untrained'))
-        chat = self.chat
-        if item == self.mytree_node:
-            SWd20_char_child.on_ldclick(self,evt)
-        else:
-            if rank == 0 and untrained == 0:
-                chat.Post('Can\'t use untrained!',True,True)
-            else:
-                mod = self.get_mod(name)
-                if mod >= 0:
-                    mod1 = "+"
-                else:
-                    mod1 = ""
-                txt = '%s Skill Check: [1d20%s%s]' % (name, mod1, mod)
-                chat.ParsePost(txt,True,True)
-
-    def get_design_panel(self,parent):
-        wnd = outline_panel(parent,self,skill_grid,"Skills")
-        wnd.title = "Skills (edit)"
-        return wnd
-
-    def tohtml(self):
-        html_str = """<table border='1' width=100% ><tr BGCOLOR=#E9E9E9 ><th width='30%'>Skill</th><th>Key</th>
-                    <th>Rank</th><th>Abil</th><th>Misc</th><th>Total</th></tr>"""
-        node_list = self.master_dom.getElementsByTagName('skill')
-        for n in node_list:
-            name = n.getAttribute('name')
-            stat = n.getAttribute('stat')
-            rank = n.getAttribute('rank')
-            html_str = html_str + "<tr ALIGN='center'><td>"+name+"</td><td>"+stat+"</td><td>"+rank+"</td>"
-            stat_mod = str(self.char_hander.child_handlers['abilities'].get_mod(stat))
-            misc = n.getAttribute('misc')
-            mod = str(self.get_mod(name))
-            if mod >= 0:
-                mod1 = "+"
-            else:
-                mod1 = ""
-            html_str = html_str + "<td>"+stat_mod+"</td><td>"+misc+'</td><td>%s%s</td></tr>' % (mod1, mod)
-        html_str = html_str + "</table>"
-        return html_str
-
-
-class SWd20ability(SWd20_char_child):
-    """ Node Handler for ability.   This handler will be
-        created by SWd20char_handler.
-    """
-    def __init__(self, xml_dom, tree_node, parent):
-        SWd20_char_child.__init__(self, xml_dom, tree_node, parent)
-        self.abilities = {}
-        node_list = self.master_dom.getElementsByTagName('stat')
-        tree = self.tree
-        icons = tree.icons
-        for n in node_list:
-            name = n.getAttribute('abbr')
-            self.abilities[name] = n
-            new_tree_node = tree.AppendItem( self.mytree_node, name, icons['gear'], icons['gear'] )
-            tree.SetPyData( new_tree_node, self )
-
-    def on_rclick( self, evt ):
-        item = self.tree.GetSelection()
-        name = self.tree.GetItemText( item )
-        if item == self.mytree_node:
-            SWd20_char_child.on_ldclick( self, evt )
-        else:
-            mod = self.get_mod( name )
-            if mod >= 0:
-                mod1 = "+"
-            else:
-                mod1 = ""
-            chat = self.chat
-            txt = '%s check: [1d20%s%s]' % ( name, mod1, mod )
-            chat.ParsePost( txt, True, True )
-
-    def get_mod(self,abbr):
-        score = int(self.abilities[abbr].getAttribute('base'))
-        mod = (score - 10) / 2
-        return mod
-
-    def set_score(self,abbr,score):
-        if score >= 0:
-            self.abilities[abbr].setAttribute("base",str(score))
-
-    def get_design_panel(self,parent):
-        wnd = outline_panel(parent,self,abil_grid,"Abilities")
-        wnd.title = "Abilities (edit)"
-        return wnd
-
-    def tohtml(self):
-        html_str = """<table border='1' width=100%><tr BGCOLOR=#E9E9E9 ><th width='50%'>Ability</th>
-                    <th>Base</th><th>Modifier</th></tr>"""
-        node_list = self.master_dom.getElementsByTagName('stat')
-        for n in node_list:
-            name = n.getAttribute('name')
-            abbr = n.getAttribute('abbr')
-            base = n.getAttribute('base')
-            mod = str(self.get_mod(abbr))
-            if mod >= 0:
-                mod1 = "+"
-            else:
-                mod1 = ""
-            html_str = html_str + "<tr ALIGN='center'><td>"+name+"</td><td>"+base+'</td><td>%s%s</td></tr>' % (mod1, mod)
-        html_str = html_str + "</table>"
-        return html_str
-
-class SWd20saves(SWd20_char_child):
-    """ Node Handler for saves.   This handler will be
-        created by SWd20char_handler.
-    """
-    def __init__(self, xml_dom, tree_node, parent):
-        SWd20_char_child.__init__(self, xml_dom, tree_node, parent)
-        tree = self.tree
-        icons = self.tree.icons
-        node_list = self.master_dom.getElementsByTagName('save')
-        self.saves={}
-        for n in node_list:
-            name = n.getAttribute('name')
-            self.saves[name] = n
-            new_tree_node = tree.AppendItem(self.mytree_node,name,icons['gear'],icons['gear'])
-            tree.SetPyData(new_tree_node,self)
-
-    def get_mod(self,name):
-        save = self.saves[name]
-        stat = save.getAttribute('stat')
-        stat_mod = self.char_hander.child_handlers['abilities'].get_mod(stat)
-        base = int(save.getAttribute('base'))
-        miscmod = int(save.getAttribute('miscmod'))
-#        magmod = int(save.getAttribute('magmod'))
-#        total = stat_mod + base + miscmod + magmod
-        total = stat_mod + base + miscmod
-        return total
-
-    def on_rclick(self,evt):
-        item = self.tree.GetSelection()
-        name = self.tree.GetItemText(item)
-        if item == self.mytree_node:
-            SWd20_char_child.on_ldclick(self,evt)
-            #wnd = save_grid(self.frame.note,self)
-            #wnd.title = "Saves"
-            #self.frame.add_panel(wnd)
-        else:
-            mod = self.get_mod(name)
-            if mod >= 0:
-                mod1 = "+"
-            else:
-                mod1 = ""
-            chat = self.chat
-            txt = '%s save: [1d20%s%s]' % (name, mod1, mod)
-            chat.ParsePost( txt, True, True )
-
-    def get_design_panel(self,parent):
-        wnd = outline_panel(parent,self,save_grid,"Saves")
-        wnd.title = "Saves"
-        return wnd
-
-    def tohtml(self):
-        html_str = """<table border='1' width=100% ><tr BGCOLOR=#E9E9E9 ><th width='30%'>Save</th>
-                    <th>Key</th><th>Base</th><th>Abil</th><th>Magic</th>
-                    <th>Misc</th><th>Total</th></tr>"""
-        node_list = self.master_dom.getElementsByTagName('save')
-        for n in node_list:
-            name = n.getAttribute('name')
-            stat = n.getAttribute('stat')
-            base = n.getAttribute('base')
-            html_str = html_str + "<tr ALIGN='center'><td>"+name+"</td><td>"+stat+"</td><td>"+base+"</td>"
-            stat_mod = str(self.char_hander.child_handlers['abilities'].get_mod(stat))
-            mag = n.getAttribute('magmod')
-            misc = n.getAttribute('miscmod')
-            mod = str(self.get_mod(name))
-            if mod >= 0:
-                mod1 = "+"
-            else:
-                mod1 = ""
-            html_str = html_str + "<td>"+stat_mod+"</td><td>"+mag+"</td>"
-            html_str = html_str + '<td>'+misc+'</td><td>%s%s</td></tr>' % (mod1, mod)
-        html_str = html_str + "</table>"
-        return html_str
-
-
-class SWd20general(SWd20_char_child):
-    """ Node Handler for general information.   This handler will be
-        created by SWd20char_handler.
-    """
-    def __init__(self, xml_dom, tree_node, parent):
-        SWd20_char_child.__init__(self, xml_dom, tree_node, parent)
-
-    def get_design_panel(self,parent):
-        wnd = outline_panel(parent,self,gen_grid,"General Information")
-        wnd.title = "General Info"
-        return wnd
-
-    def tohtml(self):
-        n_list = self.master_dom._get_childNodes()
-        html_str = "<table width=100% border=1 ><tr BGCOLOR=#E9E9E9 ><th>General Information</th></tr><tr><td>"
-        for n in n_list:
-            t_node = safe_get_text_node(n)
-            html_str += "<B>"+n._get_tagName().capitalize() +":</B> "
-            html_str += t_node._get_nodeValue() + ", "
-        html_str = html_str[:len(html_str)-2] + "</td></tr></table>"
-        return html_str
-
-    def on_name_change(self,name):
-        self.char_hander.rename(name)
-
-    def get_char_name( self ):
-        node = self.master_dom.getElementsByTagName( 'name' )[0]
-        t_node = safe_get_text_node( node )
-        return t_node._get_nodeValue()
-
-
-class SWd20classes(SWd20_char_child):
-    """ Node Handler for classes.  This handler will be
-        created by SWd20char_handler.
-    """
-    def __init__(self, xml_dom, tree_node, parent):
-        SWd20_char_child.__init__(self, xml_dom, tree_node, parent)
-
-    def get_design_panel(self,parent):
-        wnd = outline_panel(parent,self,class_panel,"Classes")
-        wnd.title = "Classes"
-        return wnd
-
-    def tohtml(self):
-        html_str = "<table width=100% border=1 ><tr BGCOLOR=#E9E9E9 ><th>Classes</th></tr><tr><td>"
-        n_list = self.master_dom._get_childNodes()
-        for n in n_list:
-            html_str += n.getAttribute('name') + " ("+n.getAttribute('level')+"), "
-        html_str = html_str[:len(html_str)-2] + "</td></tr></table>"
-        return html_str
-
-    def get_char_lvl( self, attr ):
-        node_list = self.master_dom.getElementsByTagName('class')
-        for n in node_list:
-            lvl = n.getAttribute('level')
-            type = n.getAttribute('name')
-            if attr == "level":
-                return lvl
-            elif attr == "class":
-                return type
-
-
-class SWd20feats(SWd20_char_child):
-    """ Node Handler for classes.  This handler will be
-        created by d20char_handler.
-    """
-    def __init__(self, xml_dom, tree_node, parent):
-        SWd20_char_child.__init__(self, xml_dom, tree_node, parent)
-
-    def get_design_panel(self,parent):
-        wnd = outline_panel(parent,self,feat_panel,"Feats")
-        wnd.title = "Feats"
-        return wnd
-
-    def tohtml(self):
-        html_str = "<table width=100% border=1 ><tr BGCOLOR=#E9E9E9 ><th>Feats</th></tr><tr><td>"
-        n_list = self.master_dom._get_childNodes()
-        for n in n_list:
-            html_str += n.getAttribute('name')+ ", "
-        html_str = html_str[:len(html_str)-2] + "</td></tr></table>"
-        return html_str
-
-class SWd20howto(SWd20_char_child):
-    """ Node Handler for hit points.  This handler will be
-        created by d20char_handler.
-    """
-    def __init__(self, xml_dom, tree_node, parent):
-        SWd20_char_child.__init__(self, xml_dom, tree_node, parent)
-
-    def get_design_panel(self,parent):
-        wnd = outline_panel(parent,self,howto_panel,"How To")
-        wnd.title = "How To"
-        return wnd
-
-class SWd20inventory(SWd20_char_child):
-    """ Node Handler for general information.   This handler will be
-        created by d20char_handler.
-    """
-    def __init__(self, xml_dom, tree_node, parent):
-        SWd20_char_child.__init__(self, xml_dom, tree_node, parent)
-
-    def get_design_panel(self,parent):
-        wnd = outline_panel(parent,self,inventory_grid,"Inventory")
-        wnd.title = "General Info"
-        return wnd
-
-    def tohtml(self):
-        n_list = self.master_dom._get_childNodes()
-        html_str = "<table width=100% border=1 ><tr BGCOLOR=#E9E9E9 ><th>General Information</th></tr><tr><td>"
-        for n in n_list:
-            t_node = safe_get_text_node(n)
-            html_str += "<B>"+n._get_tagName().capitalize() +":</B> "
-            html_str += t_node._get_nodeValue() + "<br />"
-        html_str = html_str[:len(html_str)-2] + "</td></tr></table>"
-        return html_str
-
-    def on_name_change(self,name):
-        self.char_hander.rename(name)
-
-    def get_char_name( self ):
-        node = self.master_dom.getElementsByTagName( 'name' )[0]
-        t_node = safe_get_text_node( node )
-        return t_node._get_nodeValue()
-
-class SWd20hp(SWd20_char_child):
-    """ Node Handler for hit points.  This handler will be
-        created by d20char_handler.
-    """
-    def __init__(self,xml_dom,tree_node,parent):
-        SWd20_char_child.__init__(self,xml_dom,tree_node,parent)
-
-    def get_design_panel(self,parent):
-        wnd = outline_panel(parent,self,hp_panel,"Wound Points")
-        wnd.title = "Wound Points"
-        return wnd
-
-    def tohtml(self):
-        html_str = "<table width=100% border=1 ><tr BGCOLOR=#E9E9E9 ><th colspan=4>Wound Points</th></tr>"
-        html_str += "<tr><th>Max:</th><td>"+self.master_dom.getAttribute('max')+"</td>"
-        html_str += "<th>Current:</th><td>"+self.master_dom.getAttribute('current')+"</td>"
-        html_str += "</tr></table>"
-        return html_str
-
-    def get_max_hp( self ):
-        try:
-            return eval( self.master_dom.getAttribute( 'max' ) )
-        except:
-            return 0
-    def get_current_hp( self ):
-        try:
-            return eval( self.master_dom.getAttribute( 'current' ) )
-        except:
-            return 0
-
-class SWd20vp(SWd20_char_child):
-    """ Node Handler for hit points.  This handler will be
-        created by d20char_handler.
-    """
-    def __init__(self,xml_dom,tree_node,parent):
-        SWd20_char_child.__init__(self,xml_dom,tree_node,parent)
-
-    def get_design_panel(self,parent):
-        wnd = outline_panel(parent,self,vp_panel,"Vitality Points")
-        wnd.title = "Vitality Points"
-        return wnd
-
-    def tohtml(self):
-        html_str = "<table width=100% border=1 ><tr BGCOLOR=#E9E9E9 ><th colspan=4>Vitality Points</th></tr>"
-        html_str += "<tr><th>Max:</th><td>"+self.master_dom.getAttribute('max')+"</td>"
-        html_str += "<th>Current:</th><td>"+self.master_dom.getAttribute('current')+"</td>"
-        html_str += "</tr></table>"
-        return html_str
-
-    def get_max_vp( self ):
-        try:
-            return eval( self.master_dom.getAttribute( 'max' ) )
-        except:
-            return 0
-    def get_current_vp( self ):
-        try:
-            return eval( self.master_dom.getAttribute( 'current' ) )
-        except:
-            return 0
-
-class SWd20attacks(SWd20_char_child):
-    """ Node Handler for attacks.  This handler will be
-        created by d20char_handler.
-    """
-    def __init__(self,xml_dom,tree_node,parent):
-        SWd20_char_child.__init__(self,xml_dom,tree_node,parent)
-        node_list = self.master_dom.getElementsByTagName('melee')
-        self.melee = node_list[0]
-        node_list = self.master_dom.getElementsByTagName('ranged')
-        self.ranged = node_list[0]
-        self.refresh_weapons()
-
-    def refresh_weapons(self):
-        self.weapons = {}
-        tree = self.tree
-        icons = self.tree.icons
-        tree.CollapseAndReset(self.mytree_node)
-        node_list = self.master_dom.getElementsByTagName('weapon')
-        for n in node_list:
-            name = n.getAttribute('name')
-            new_tree_node = tree.AppendItem(self.mytree_node,name,icons['sword'],icons['sword'])
-            tree.SetPyData(new_tree_node,self)
-            self.weapons[name]=n
-
-    def get_mod(self,type='m'):
-        (base, base2, base3, base4, base5, base6, stat_mod, misc) = self.get_attack_data(type)
-        return base + misc + stat_mod
-
-    def get_attack_data(self,type='m'):
-        if type=='m' or type=='0':
-            stat_mod = self.char_hander.child_handlers['abilities'].get_mod('Str')
-            temp = self.melee
-        else:
-            stat_mod = self.char_hander.child_handlers['abilities'].get_mod('Dex')
-            temp = self.ranged
-        base = int(temp.getAttribute('base'))
-        base2 = int(temp.getAttribute('second'))
-        base3 = int(temp.getAttribute('third'))
-        base4 = int(temp.getAttribute('forth'))
-        base5 = int(temp.getAttribute('fifth'))
-        base6 = int(temp.getAttribute('sixth'))
-        misc = int(temp.getAttribute('misc'))
-        return (base, base2, base3, base4, base5, base6, stat_mod ,misc)
-
-    def on_rclick(self,evt):
-        #removed the DnD specific code
-        item = self.tree.GetSelection()
-        name = self.tree.GetItemText(item)
-        if item == self.mytree_node:
-            SWd20_char_child.on_ldclick(self,evt)
-            #self.frame.add_panel(self.get_design_panel(self.frame.note))
-        else:
-            mod = int(self.weapons[name].getAttribute('mod'))
-            if self.weapons[name].getAttribute('range') == '0':
-                mod = mod + self.get_mod('m')
-                if mod >= 0:
-                    mod1 = "+"
-                else:
-                    mod1 = ""
-            else:
-                mod = mod + self.get_mod('r')
-                if mod >= 0:
-                    mod1 = "+"
-                else:
-                    mod1 = ""
-            chat = self.chat
-            dmg = self.weapons[name].getAttribute('damage')
-            lvl = self.get_char_lvl('level')
-            cname = self.char_hander.get_char_name()
-            txt = '%s %s Attack Roll: [1d20%s%s] ===> DMG: [%s%s%s]' % (cname, name, mod1, mod, dmg, mod1, mod)
-            chat.ParsePost( txt, True, False )
-            temp = self.melee
-            stat_mod = self.char_hander.child_handlers['abilities'].get_mod('Str')
-
-    def get_design_panel(self,parent):
-        wnd = outline_panel(parent,self,attack_panel,"Attacks")
-        wnd.title = "Attacks"
-        return wnd
-
-    def get_char_lvl( self, attr ):
-        return self.char_hander.get_char_lvl(attr)
-
-    def tohtml(self):
-        melee = self.get_attack_data('m')
-        ranged = self.get_attack_data('r')
-        html_str = """<table width=100% border=1 ><tr BGCOLOR=#E9E9E9 ><th>Attack</th>
-                    <th>Total</th><th >Base</th><th>Abil</th><th>Misc</th></tr>"""
-        html_str += "<tr ALIGN='center' ><th >Melee:</th>"
-        html_str += "<td>"+str(melee[0]+melee[1]+melee[2])+"</td>"
-        html_str += "<td>"+str(melee[0])+"</td>"
-        html_str += "<td>"+str(melee[1])+"</td>"
-        html_str += "<td>"+str(melee[2])+"</td></tr>"
-
-        html_str += "<tr ALIGN='center' ><th >Ranged:</th>"
-        html_str += "<td>"+str(ranged[0]+ranged[1]+ranged[2])+"</td>"
-        html_str += "<td>"+str(ranged[0])+"</td>"
-        html_str += "<td>"+str(ranged[1])+"</td>"
-        html_str += "<td>"+str(ranged[2])+"</td></tr></table>"
-
-        n_list = self.master_dom.getElementsByTagName('weapon')
-        for n in n_list:
-            mod = n.getAttribute('mod')
-            if mod >= 0:
-                mod1 = "+"
-            else:
-                mod1 = ""
-            ran = n.getAttribute('range')
-            total = str(int(mod) + self.get_mod(ran))
-            html_str += """<P><table width=100% border=1 ><tr BGCOLOR=#E9E9E9 ><th colspan=2>Weapon</th>
-                    <th>Attack</th><th >Damage</th><th>Critical</th></tr>"""
-            html_str += "<tr ALIGN='center' ><td  colspan=2>"+n.getAttribute('name')+"</td><td>"+total+"</td>"
-            html_str += "<td>"+n.getAttribute('damage')+"</td><td>"+n.getAttribute('critical')+"</td></tr>"
-            html_str += """<tr BGCOLOR=#E9E9E9 ><th>Range</th><th>Weight</th>
-                        <th>Type</th><th>Size</th><th>Misc Mod</th></tr>"""
-            html_str += "<tr ALIGN='center'><td>"+ran+"</td><td>"+n.getAttribute('weight')+"</td>"
-            html_str += "<td>"+n.getAttribute('type')+"</td><td>"+n.getAttribute('size')+"</td>"
-            html_str += '<td>%s%s</td></tr></table>' % (mod1, mod)
-        return html_str
-
-class SWd20armor(SWd20_char_child):
-    """ Node Handler for ac.  This handler will be
-        created by d20char_handler.
-    """
-    def __init__(self,xml_dom,tree_node,parent):
-        SWd20_char_child.__init__(self,xml_dom,tree_node,parent)
-
-    def get_total_weight(self):
-        return self.get_total('weight')
-
-    def get_check_pen(self):
-        return self.get_total('checkpenalty')
-
-    def get_armor_class(self):
-        ac_total = 10
-        ac_total += self.get_total('bonus')
-        dex_mod = self.char_hander.child_handlers['abilities'].get_mod('Dex')
-        max_dex = self.get_max_dex()
-        if dex_mod < max_dex:
-            ac_total += dex_mod
-        else:
-            ac_total += max_dex
-        return ac_total
-
-    def get_max_dex(self):
-        armor_list = self.master_dom.getElementsByTagName('armor')
-        dex = 10
-        for a in armor_list:
-            temp = int(a.getAttribute("maxdex"))
-            if temp < dex:
-                dex = temp
-        return dex
-
-    def get_total(self,attr):
-        armor_list = self.master_dom.getElementsByTagName('armor')
-        total = 0
-        for a in armor_list:
-            total += int(a.getAttribute(attr))
-        return total
-
-    def get_design_panel(self,parent):
-        wnd = outline_panel(parent,self,ac_panel,"Armor")
-        wnd.title = "Armor"
-        return wnd
-
-    def tohtml(self):
-        html_str = """<table width=100% border=1 ><tr BGCOLOR=#E9E9E9 ><th>AC</th>
-                    <th>Check Penalty</th><th >Spell Failure</th><th>Max Dex</th><th>Total Weight</th></tr>"""
-        html_str += "<tr ALIGN='center' ><td>"+str(self.get_armor_class())+"</td>"
-        html_str += "<td>"+str(self.get_check_pen())+"</td>"
-        html_str += "<td>"+str(self.get_spell_failure())+"</td>"
-        html_str += "<td>"+str(self.get_max_dex())+"</td>"
-        html_str += "<td>"+str(self.get_total_weight())+"</td></tr></table>"
-        n_list = self.master_dom._get_childNodes()
-        for n in n_list:
-            html_str += """<P><table width=100% border=1 ><tr BGCOLOR=#E9E9E9 ><th colspan=3>Armor</th>
-                    <th>Type</th><th >Bonus</th></tr>"""
-            html_str += "<tr ALIGN='center' ><td  colspan=3>"+n.getAttribute('name')+"</td>"
-            html_str += "<td>"+n.getAttribute('type')+"</td>"
-            html_str += "<td>"+n.getAttribute('bonus')+"</td></tr>"
-            html_str += """<tr BGCOLOR=#E9E9E9 ><th>Check Penalty</th><th>Spell Failure</th>
-                        <th>Max Dex</th><th>Speed</th><th>Weight</th></tr>"""
-            html_str += "<tr ALIGN='center'><td>"+n.getAttribute('checkpenalty')+"</td>"
-            html_str += "<td>"+n.getAttribute('maxdex')+"</td>"
-            html_str += "<td>"+n.getAttribute('speed')+"</td>"
-            html_str += "<td>"+n.getAttribute('weight')+"</td></tr></table>"
-        return html_str
-
-
-########################
-##  d20 char windows
-########################
-
-class base_panel(wx.Panel):
-    def __init__(self, parent):
-        wx.Panel.__init__(self, parent, -1)
-
-        #self.build_ctrls()
-        self.Bind(wx.EVT_SIZE, self.on_size)
-
-    def on_size(self,event):
-        s = self.GetClientSizeTuple()
-        #self.splitter.SetDimensions(0,0,s[0],s[1])
-
-class outline_panel(wx.Panel):
-    def __init__(self, parent, handler, wnd, txt,):
-        wx.Panel.__init__(self, parent, -1)
-        self.panel = wnd(self,handler)
-        self.outline = wx.StaticBox(self,-1,txt)
-        self.Bind(wx.EVT_SIZE, self.on_size)
-
-    def on_size(self,event):
-        s = self.GetClientSizeTuple()
-        self.panel.SetDimensions(20,20,s[0]-40,s[1]-40)
-        self.outline.SetDimensions(5,5,s[0]-10,s[1]-10)
-
-class char_panel(wx.ScrolledWindow):
-    def __init__(self, parent, handler):
-        pname = handler.master_dom.setAttribute("name", 'TWO')
-        wx.ScrolledWindow.__init__(self, parent, -1,style=wx.VSCROLL | wx.SUNKEN_BORDER  )
-        self.height = 1200
-        self.SetScrollbars(10, 10,80, self.height/10)
-        self.main_sizer = wx.BoxSizer(wx.HORIZONTAL)
-        self.panels = {}
-        keys = handler.child_handlers.keys()
-        for k in keys:
-            self.panels[k] = handler.child_handlers[k].get_design_panel(self, [k])
-        self.sub_sizer = wx.BoxSizer(wx.VERTICAL)
-        self.sub_sizer2 = wx.BoxSizer(wx.VERTICAL)
-        self.sub_sizer.Add(self.panels['general'], 1, wx.EXPAND)
-        self.sub_sizer.Add(self.panels['abilities'], 1, wx.EXPAND)
-
-        self.sub_sizer.Add(self.panels['attacks'], 2, wx.EXPAND)
-        self.sub_sizer.Add(self.panels['ac'], 1, wx.EXPAND)
-        #self.sub_sizer.Add(self.panels['spells'], 1, wx.EXPAND)
-
-        self.sub_sizer2.Add(self.panels['classes'], 2, wx.EXPAND)
-        self.sub_sizer2.Add(self.panels['wp'], 1, wx.EXPAND)
-        self.sub_sizer2.Add(self.panels['vp'], 1, wx.EXPAND)
-        #self.sub_sizer2.Add(self.panels['pp'], 1, wx.EXPAND)
-        self.sub_sizer2.Add(self.panels['saves'], 2, wx.EXPAND)
-
-        self.sub_sizer2.Add(self.panels['feats'], 2, wx.EXPAND)
-        #self.sub_sizer2.Add(self.panels['powers'], 2, wx.EXPAND)
-        self.sub_sizer2.Add(self.panels['skills'], 3, wx.EXPAND)
-
-        self.main_sizer.Add(self.sub_sizer,   1, wx.EXPAND)
-        self.main_sizer.Add(self.sub_sizer2,   1, wx.EXPAND)
-        self.panels['abilities'].panel.char_wnd = self
-        self.SetSizer(self.main_sizer)
-        self.Bind(wx.EVT_SIZE, self.on_size)
-
-
-    def on_size(self,evt):
-        s = self.GetClientSizeTuple()
-        self.SetScrollbars(10, 10,s[0]/10, self.height/10)
-        dc = wx.ClientDC(self)
-        x = dc.DeviceToLogicalX(0)
-        y = dc.DeviceToLogicalY(0)
-        self.main_sizer.SetDimension(x,y,s[0],self.height)
-        evt.Skip()
-
-    def refresh_data(self):
-        self.panels['saves'].panel.refresh_data()
-        self.panels['skills'].panel.refresh_data()
-        self.panels['attacks'].panel.refresh_data()
-#        self.panels['powers'].panel.refresh_data()
-#        self.panels['spells'].panel.refresh_data()
-
-HOWTO_MAX = wx.NewId()
-
-class howto_panel(wx.Panel):
-    def __init__(self, parent, handler):
-        wx.Panel.__init__(self, parent, -1)
-        pname = handler.master_dom.setAttribute("name", 'How To')
-        self.sizer = wx.FlexGridSizer(2, 4, 2, 2)  # rows, cols, hgap, vgap
-        self.master_dom = handler.master_dom
-        n_list = self.master_dom._get_childNodes()
-        for n in n_list:
-            t_node = safe_get_text_node(n)
-        self.sizer.AddMany([ (wx.StaticText(self, -1, t_node._get_nodeValue()),   0, wx.ALIGN_CENTER_VERTICAL),
-                 ])
-        self.sizer.AddGrowableCol(1)
-        self.SetSizer(self.sizer)
-
-
-WP_CUR = wx.NewId()
-WP_MAX = wx.NewId()
-
-class hp_panel(wx.Panel):
-    def __init__(self, parent, handler):
-        wx.Panel.__init__(self, parent, -1)
-        pname = handler.master_dom.setAttribute("name", 'WoundPoints')
-        self.sizer = wx.FlexGridSizer(2, 4, 2, 2)  # rows, cols, hgap, vgap
-        self.master_dom = handler.master_dom
-        self.sizer.AddMany([ (wx.StaticText(self, -1, "WP Current:"),   0, wx.ALIGN_CENTER_VERTICAL),
-                 (wx.TextCtrl(self, WP_CUR, self.master_dom.getAttribute('current')),   0, wx.EXPAND),
-                 (wx.StaticText(self, -1, "WP Max:"), 0, wx.ALIGN_CENTER_VERTICAL),
-                 (wx.TextCtrl(self, WP_MAX, self.master_dom.getAttribute('max')),  0, wx.EXPAND),
-                 ])
-        self.sizer.AddGrowableCol(1)
-        self.Bind(wx.EVT_SIZE, self.on_size)
-        self.Bind(wx.EVT_TEXT, self.on_text, id=WP_MAX)
-        self.Bind(wx.EVT_TEXT, self.on_text, id=WP_CUR)
-        self.SetSizer(self.sizer)
-
-    def on_text(self,evt):
-        id = evt.GetId()
-        if id == WP_CUR:
-            self.master_dom.setAttribute('current',evt.GetString())
-        elif id == WP_MAX:
-            self.master_dom.setAttribute('max',evt.GetString())
-
-    def on_size(self,evt):
-        s = self.GetClientSizeTuple()
-        self.sizer.SetDimension(0,0,s[0],s[1])
-
-VP_CUR = wx.NewId()
-VP_MAX = wx.NewId()
-
-class vp_panel(wx.Panel):
-    def __init__(self, parent, handler):
-        wx.Panel.__init__(self, parent, -1)
-        pname = handler.master_dom.setAttribute("name", 'VitalityPoints')
-        self.sizer = wx.FlexGridSizer(2, 4, 2, 2)  # rows, cols, hgap, vgap
-        self.master_dom = handler.master_dom
-        self.sizer.AddMany([ (wx.StaticText(self, -1, "VP Current:"),   0, wx.ALIGN_CENTER_VERTICAL),
-                 (wx.TextCtrl(self, VP_CUR, self.master_dom.getAttribute('current')),   0, wx.EXPAND),
-                 (wx.StaticText(self, -1, "VP Max:"), 0, wx.ALIGN_CENTER_VERTICAL),
-                 (wx.TextCtrl(self, VP_MAX, self.master_dom.getAttribute('max')),  0, wx.EXPAND),
-                 ])
-        self.sizer.AddGrowableCol(1)
-        self.Bind(wx.EVT_SIZE, self.on_size)
-        self.Bind(wx.EVT_TEXT, self.on_text, id=VP_MAX)
-        self.Bind(wx.EVT_TEXT, self.on_text, id=VP_CUR)
-        self.SetSizer(self.sizer)
-
-    def on_text(self,evt):
-        id = evt.GetId()
-        if id == VP_CUR:
-            self.master_dom.setAttribute('current',evt.GetString())
-        elif id == VP_MAX:
-            self.master_dom.setAttribute('max',evt.GetString())
-
-    def on_size(self,evt):
-        s = self.GetClientSizeTuple()
-        self.sizer.SetDimension(0,0,s[0],s[1])
-
-#PP_CUR = wx.NewId()
-#PP_MAX = wx.NewId()
-#PP_FRE = wx.NewId()
-#PP_MFRE = wx.NewId()
-
-#class pp_panel(wx.Panel):
-#    def __init__(self, parent, handler):
-#        wx.Panel.__init__(self, parent, -1)
-#        pname = handler.master_dom.setAttribute("name", 'PowerPoints')
-#        self.sizer = wx.FlexGridSizer(2, 4, 2, 2)  # rows, cols, hgap, vgap
-#        self.master_dom = handler.master_dom
-#
-#        self.sizer.AddMany([ (wx.StaticText(self, -1, "PP Current:"),   0, wx.ALIGN_CENTER_VERTICAL),
-#                 (wx.TextCtrl(self, PP_CUR, self.master_dom.getAttribute('current1')),   0, wx.EXPAND),
-#                 (wx.StaticText(self, -1, "PP Max:"), 0, wx.ALIGN_CENTER_VERTICAL),
-#                 (wx.TextCtrl(self, PP_MAX, self.master_dom.getAttribute('max1')),  0, wx.EXPAND),
-#                 (wx.StaticText(self, -1, "Current Free Talants per day:"), 0, wx.ALIGN_CENTER_VERTICAL),
-#                 (wx.TextCtrl(self, PP_FRE, self.master_dom.getAttribute('free')),  0, wx.EXPAND),
-#                 (wx.StaticText(self, -1, "Max Free Talants per day:"), 0, wx.ALIGN_CENTER_VERTICAL),
-#                 (wx.TextCtrl(self, PP_MFRE, self.master_dom.getAttribute('maxfree')),  0, wx.EXPAND),
-#                 ])
-#        self.sizer.AddGrowableCol(1)
-#        self.Bind(wx.EVT_SIZE, self.on_size)
-#        self.Bind(wx.EVT_TEXT, self.on_text, id=PP_MAX)
-#        self.Bind(wx.EVT_TEXT, self.on_text, id=PP_CUR)
-#        self.Bind(wx.EVT_TEXT, self.on_text, id=PP_FRE)
-#        self.Bind(wx.EVT_TEXT, self.on_text, id=PP_MFRE)
-#
-#    def on_text(self,evt):
-#        id = evt.GetId()
-#        if id == PP_CUR:
-#            self.master_dom.setAttribute('current1',evt.GetString())
-#        elif id == PP_MAX:
-#            self.master_dom.setAttribute('max1',evt.GetString())
-#        elif id == PP_FRE:
-#            self.master_dom.setAttribute('free',evt.GetString())
-#        elif id == PP_MFRE:
-#            self.master_dom.setAttribute('maxfree',evt.GetString())
-#
-#    def on_size(self,evt):
-#        s = self.GetClientSizeTuple()
-#        self.sizer.SetDimension(0,0,s[0],s[1])
-
-
-class gen_grid(wx.grid.Grid):
-    """grid for gen info"""
-    def __init__(self, parent, handler):
-        pname = handler.master_dom.setAttribute("name", 'General')
-        wx.grid.Grid.__init__(self, parent, -1, style=wx.SUNKEN_BORDER | wx.WANTS_CHARS)
-        self.Bind(wx.EVT_SIZE, self.on_size)
-        self.Bind(wx.grid.EVT_GRID_CELL_CHANGE, self.on_cell_change)
-        self.handler = handler
-        n_list = handler.master_dom._get_childNodes()
-        self.CreateGrid(len(n_list),2)
-        self.SetRowLabelSize(0)
-        self.SetColLabelSize(0)
-        self.n_list = n_list
-        i = 0
-        for i in range(len(n_list)):
-            self.refresh_row(i)
-
-    def on_cell_change(self,evt):
-        row = evt.GetRow()
-        col = evt.GetCol()
-        value = self.GetCellValue(row,col)
-        t_node = self.n_list[row]._get_firstChild()
-        t_node._set_nodeValue(value)
-        if row==0: self.handler.on_name_change(value)
-
-    def refresh_row(self,rowi):
-        t_node = safe_get_text_node(self.n_list[rowi])
-        self.SetCellValue(rowi,0,self.n_list[rowi]._get_tagName())
-        self.SetReadOnly(rowi,0)
-        self.SetCellValue(rowi,1,t_node._get_nodeValue())
-
-    def on_size(self,evt):
-        (w,h) = self.GetClientSizeTuple()
-        cols = self.GetNumberCols()
-        col_w = w/(cols)
-        for i in range(0,cols):
-            self.SetColSize(i,col_w)
-        evt.Skip()
-        self.Refresh()
-
-class inventory_grid(wx.grid.Grid):
-    """grid for gen info"""
-    def __init__(self, parent, handler):
-        pname = handler.master_dom.setAttribute("name", 'Money and Inventory')
-        wx.grid.Grid.__init__(self, parent, -1, style=wx.SUNKEN_BORDER | wx.WANTS_CHARS)
-        self.Bind(wx.EVT_SIZE, self.on_size)
-        self.Bind(wx.grid.EVT_GRID_CELL_CHANGE, self.on_cell_change)
-        self.handler = handler
-        n_list = handler.master_dom._get_childNodes()
-        self.CreateGrid(len(n_list),2)
-        self.SetRowLabelSize(0)
-        self.SetColLabelSize(0)
-        self.n_list = n_list
-        i = 0
-        for i in range(len(n_list)):
-            self.refresh_row(i)
-
-    def on_cell_change(self,evt):
-        row = evt.GetRow()
-        col = evt.GetCol()
-        value = self.GetCellValue(row,col)
-        t_node = self.n_list[row]._get_firstChild()
-        t_node._set_nodeValue(value)
-        if row==0: self.handler.on_name_change(value)
-
-    def refresh_row(self,rowi):
-        t_node = safe_get_text_node(self.n_list[rowi])
-        self.SetCellValue(rowi,0,self.n_list[rowi]._get_tagName())
-        self.SetReadOnly(rowi,0)
-        self.SetCellValue(rowi,1,t_node._get_nodeValue())
-
-    def on_size(self,evt):
-        (w,h) = self.GetClientSizeTuple()
-        cols = self.GetNumberCols()
-        col_w = w/(cols)
-        for i in range(0,cols):
-            self.SetColSize(i,col_w)
-        evt.Skip()
-        self.Refresh()
-
-class abil_grid(wx.grid.Grid):
-    """grid for abilities"""
-    def __init__(self, parent, handler):
-        pname = handler.master_dom.setAttribute("name", 'Stats')
-        wx.grid.Grid.__init__(self, parent, -1, style=wx.SUNKEN_BORDER | wx.WANTS_CHARS)
-        self.Bind(wx.EVT_SIZE, self.on_size)
-        self.Bind(wx.grid.EVT_GRID_CELL_CHANGE, self.on_cell_change)
-        self.handler = handler
-        stats = handler.master_dom.getElementsByTagName('stat')
-        self.CreateGrid(len(stats),3)
-        self.SetRowLabelSize(0)
-        col_names = ['Ability','Score','Modifier']
-        for i in range(len(col_names)):
-            self.SetColLabelValue(i,col_names[i])
-        self.stats = stats
-        i = 0
-        for i in range(len(stats)):
-            self.refresh_row(i)
-        self.char_wnd = None
-
-    def on_cell_change(self,evt):
-        row = evt.GetRow()
-        col = evt.GetCol()
-        value = self.GetCellValue(row,col)
-        try:
-            int(value)
-            self.stats[row].setAttribute('base',value)
-            self.refresh_row(row)
-        except:
-            self.SetCellValue(row,col,"0")
-        if self.char_wnd:
-            self.char_wnd.refresh_data()
-
-    def refresh_row(self,rowi):
-        s = self.stats[rowi]
-        name = s.getAttribute('name')
-        abbr = s.getAttribute('abbr')
-        self.SetCellValue(rowi,0,name)
-        self.SetReadOnly(rowi,0)
-        self.SetCellValue(rowi,1,s.getAttribute('base'))
-        self.SetCellValue(rowi,2,str(self.handler.get_mod(abbr)))
-        self.SetReadOnly(rowi,2)
-
-    def on_size(self,evt):
-        (w,h) = self.GetClientSizeTuple()
-        cols = self.GetNumberCols()
-        col_w = w/(cols+2)
-        self.SetColSize(0,col_w*3)
-        for i in range(1,cols):
-            self.SetColSize(i,col_w)
-        evt.Skip()
-        self.Refresh()
-
-    def refresh_data(self):
-        for r in range(self.GetNumberRows()-1):
-            self.refresh_row(r)
-
-
-class save_grid(wx.grid.Grid):
-    """grid for saves"""
-    def __init__(self, parent, handler):
-        pname = handler.master_dom.setAttribute("name", 'Saves')
-        wx.grid.Grid.__init__(self, parent, -1, style=wx.SUNKEN_BORDER | wx.WANTS_CHARS)
-        self.Bind(wx.EVT_SIZE, self.on_size)
-        self.Bind(wx.grid.EVT_GRID_CELL_CHANGE, self.on_cell_change)
-        self.handler = handler
-        saves = handler.master_dom.getElementsByTagName('save')
-        self.stats = handler.char_hander.child_handlers['abilities']
-        self.CreateGrid(len(saves),7)
-        self.SetRowLabelSize(0)
-        col_names = ['Save','Key','base','Abil','Magic','Misc','Total']
-        for i in range(len(col_names)):
-            self.SetColLabelValue(i,col_names[i])
-        self.saves = saves
-        i = 0
-        for i in range(len(saves)):
-            self.refresh_row(i)
-
-    def on_cell_change(self,evt):
-        row = evt.GetRow()
-        col = evt.GetCol()
-        value = self.GetCellValue(row,col)
-        try:
-            int(value)
-            if col == 2:
-                self.saves[row].setAttribute('base',value)
-            elif col ==4:
-                self.saves[row].setAttribute('magmod',value)
-            elif col ==4:
-                self.saves[row].setAttribute('miscmod',value)
-            self.refresh_row(row)
-        except:
-            self.SetCellValue(row,col,"0")
-
-    def refresh_row(self,rowi):
-        s = self.saves[rowi]
-        name = s.getAttribute('name')
-        self.SetCellValue(rowi,0,name)
-        self.SetReadOnly(rowi,0)
-        stat = s.getAttribute('stat')
-        self.SetCellValue(rowi,1,stat)
-        self.SetReadOnly(rowi,1)
-        self.SetCellValue(rowi,2,s.getAttribute('base'))
-        self.SetCellValue(rowi,3,str(self.stats.get_mod(stat)))
-        self.SetReadOnly(rowi,3)
-        self.SetCellValue(rowi,4,s.getAttribute('magmod'))
-        self.SetCellValue(rowi,5,s.getAttribute('miscmod'))
-        mod = str(self.handler.get_mod(name))
-        self.SetCellValue(rowi,6,mod)
-        self.SetReadOnly(rowi,6)
-
-    def on_size(self,evt):
-        (w,h) = self.GetClientSizeTuple()
-        cols = self.GetNumberCols()
-        col_w = w/(cols+2)
-        self.SetColSize(0,col_w*3)
-        for i in range(1,cols):
-            self.SetColSize(i,col_w)
-        evt.Skip()
-        self.Refresh()
-
-    def refresh_data(self):
-        for r in range(self.GetNumberRows()):
-            self.refresh_row(r)
-
-
-class skill_grid(wx.grid.Grid):
-    """ panel for skills """
-    def __init__(self, parent, handler):
-        pname = handler.master_dom.setAttribute("name", 'Skills')
-        wx.grid.Grid.__init__(self, parent, -1, style=wx.SUNKEN_BORDER | wx.WANTS_CHARS)
-        self.Bind(wx.EVT_SIZE, self.on_size)
-        self.Bind(wx.grid.EVT_GRID_CELL_CHANGE, self.on_cell_change)
-        self.handler = handler
-        skills = handler.master_dom.getElementsByTagName('skill')
-        self.stats = handler.char_hander.child_handlers['abilities']
-        self.CreateGrid(len(skills),7)
-        self.SetRowLabelSize(0)
-        col_names = ['Skill','Key','Rank','Abil','Misc','Total']
-        for i in range(len(col_names)):
-            self.SetColLabelValue(i,col_names[i])
-        rowi = 0
-        self.skills = skills
-        for i in range(len(skills)):
-            self.refresh_row(i)
-
-    def on_cell_change(self,evt):
-        row = evt.GetRow()
-        col = evt.GetCol()
-        value = self.GetCellValue(row,col)
-        #print value
-        try:
-            int(value)
-            if col == 3:
-                self.skills[row].setAttribute('rank',value)
-            elif col ==5:
-                self.skills[row].setAttribute('misc',value)
-            elif col == 1:
-                self.skills[row].setAttribute('untrained',value)
-            self.refresh_row(row)
-        except:
-            self.SetCellValue(row,col,"0")
-
-    def refresh_row(self,rowi):
-        s = self.skills[rowi]
-        name = s.getAttribute('name')
-        self.SetCellValue(rowi,0,name)
-        self.SetReadOnly(rowi,0)
-        self.SetCellValue(rowi,1,s.getAttribute('untrained'))
-        stat = s.getAttribute('stat')
-        self.SetCellValue(rowi,2,stat)
-        self.SetReadOnly(rowi,2)
-        self.SetCellValue(rowi,3,s.getAttribute('rank'))
-        self.SetCellValue(rowi,4,str(self.stats.get_mod(stat)))
-        self.SetReadOnly(rowi,4)
-        self.SetCellValue(rowi,5,s.getAttribute('misc'))
-        mod = str(self.handler.get_mod(name))
-        self.SetCellValue(rowi,6,mod)
-        self.SetReadOnly(rowi,6)
-
-    def on_size(self,evt):
-        (w,h) = self.GetClientSizeTuple()
-        cols = self.GetNumberCols()
-        col_w = w/(cols+2)
-        self.SetColSize(0,col_w*3)
-        for i in range(1,cols):
-            self.SetColSize(i,col_w)
-        evt.Skip()
-        self.Refresh()
-
-    def refresh_data(self):
-        for r in range(self.GetNumberRows()):
-            self.refresh_row(r)
-
-
-
-class feat_panel(wx.Panel):
-    def __init__(self, parent, handler):
-        pname = handler.master_dom.setAttribute("name", 'Feats')
-        wx.Panel.__init__(self, parent, -1)
-        self.grid =wx.grid.Grid(self, -1, style=wx.SUNKEN_BORDER | wx.WANTS_CHARS)
-        sizer = wx.BoxSizer(wx.HORIZONTAL)
-        sizer.Add(wx.Button(self, 10, "Remove Feat"), 1, wx.EXPAND)
-        sizer.Add(wx.Size(10,10))
-        sizer.Add(wx.Button(self, 20, "Add Feat"), 1, wx.EXPAND)
-        self.sizer = sizer
-        self.SetSizer(self.sizer)
-        self.Bind(wx.EVT_SIZE, self.on_size)
-        EVT_BUTTON(self, 10, self.on_remove)
-        EVT_BUTTON(self, 20, self.on_add)
-
-        n_list = handler.master_dom._get_childNodes()
-        self.n_list = n_list
-        self.master_dom = handler.master_dom
-        self.grid.CreateGrid(len(n_list),2,1)
-        self.grid.SetRowLabelSize(0)
-        self.grid.SetColLabelValue(0,"Feat")
-        self.grid.SetColLabelValue(1,"Type")
-        for i in range(len(n_list)):
-            self.refresh_row(i)
-        self.temp_dom = None
-
-    def refresh_row(self,i):
-        feat = self.n_list[i]
-        name = feat.getAttribute('name')
-        type = feat.getAttribute('type')
-        self.grid.SetCellValue(i,0,name)
-        self.grid.SetReadOnly(i,0)
-        self.grid.SetCellValue(i,1,type)
-        self.grid.SetReadOnly(i,1)
-
-    def on_remove(self,evt):
-        rows = self.grid.GetNumberRows()
-        for i in range(rows):
-            if self.grid.IsInSelection(i,0):
-                self.grid.DeleteRows(i)
-                self.master_dom.removeChild(self.n_list[i])
-
-    def on_add(self,evt):
-        if not self.temp_dom:
-            tmp = open(orpg.dirpath.dir_struct["SWd20"]+"d20feats.xml","r")
-            xml_dom = parseXml_with_dlg(self,tmp.read())
-            xml_dom = xml_dom._get_firstChild()
-            tmp.close()
-            self.temp_dom = xml_dom
-        f_list = self.temp_dom.getElementsByTagName('feat')
-        opts = []
-        for f in f_list:
-            opts.append(f.getAttribute('name'))
-        dlg = wx.SingleChoiceDialog(self,'Choose Feat','Feats',opts)
-        if dlg.ShowModal() == wx.ID_OK:
-            i = dlg.GetSelection()
-            new_node = self.master_dom.appendChild(f_list[i].cloneNode(False))
-            self.grid.AppendRows(1)
-            self.refresh_row(self.grid.GetNumberRows()-1)
-        dlg.Destroy()
-
-
-    def on_size(self,event):
-        s = self.GetClientSizeTuple()
-        self.grid.SetDimensions(0,0,s[0],s[1]-25)
-        self.sizer.SetDimension(0,s[1]-25,s[0],25)
-        (w,h) = self.grid.GetClientSizeTuple()
-        cols = self.grid.GetNumberCols()
-        col_w = w/(cols)
-        for i in range(0,cols):
-            self.grid.SetColSize(i,col_w)
-
-class attack_grid(wx.grid.Grid):
-    """grid for attacks"""
-    def __init__(self, parent, handler):
-        pname = handler.master_dom.setAttribute("name", 'Melee')
-        wx.grid.Grid.__init__(self, parent, -1, style=wx.SUNKEN_BORDER | wx.WANTS_CHARS)
-        self.parent = parent
-        self.handler = handler
-        self.rows = (self.handler.melee,self.handler.ranged)
-        self.CreateGrid(2,10)
-        self.SetRowLabelSize(0)
-        col_names = ['Type','base','base 2','base 3','base 4','base 5','base 6','abil','misc','Total']
-        for i in range(len(col_names)):
-            self.SetColLabelValue(i,col_names[i])
-        self.SetCellValue(0,0,"Melee")
-        self.SetCellValue(1,0,"Ranged")
-        self.refresh_data()
-        self.Bind(wx.EVT_SIZE, self.on_size)
-        self.Bind(wx.grid.EVT_GRID_CELL_CHANGE, self.on_cell_change)
-
-    def on_cell_change(self,evt):
-        row = evt.GetRow()
-        col = evt.GetCol()
-        value = self.GetCellValue(row,col)
-        try:
-            int(value)
-            if col==1:
-                self.rows[row].setAttribute('base',value)
-            elif col==2:
-                self.rows[row].setAttribute('second',value)
-            elif col==3:
-                self.rows[row].setAttribute('third',value)
-            elif col==4:
-                self.rows[row].setAttribute('forth',value)
-            elif col==5:
-                self.rows[row].setAttribute('fifth',value)
-            elif col==6:
-                self.rows[row].setAttribute('sixth',value)
-            elif col==8:
-                self.rows[row].setAttribute('misc',value)
-            self.parent.refresh_data()
-        except:
-            self.SetCellValue(row,col,"0")
-
-    def refresh_data(self):
-        melee = self.handler.get_attack_data('m')
-        ranged = self.handler.get_attack_data('r')
-        for i in range(0,7):
-            self.SetCellValue(0,i+1,str(melee[i]))
-            self.SetCellValue(1,i+1,str(ranged[i]))
-        self.SetCellValue(0,9,str(melee[0]+melee[6]+melee[7]))
-        self.SetCellValue(1,9,str(ranged[0]+ranged[6]+ranged[7]))
-        self.SetReadOnly(0,0)
-        self.SetReadOnly(1,0)
-        self.SetReadOnly(0,7)
-        self.SetReadOnly(1,7)
-        self.SetReadOnly(0,9)
-        self.SetReadOnly(1,9)
-
-
-    def on_size(self,evt):
-        (w,h) = self.GetClientSizeTuple()
-        cols = self.GetNumberCols()
-        col_w = w/(cols+1)
-        self.SetColSize(0,col_w*2)
-        for i in range(1,cols):
-            self.SetColSize(i,col_w)
-        evt.Skip()
-        self.Refresh()
-
-class weapon_panel(wx.Panel):
-    def __init__(self, parent, handler):
-        pname = handler.master_dom.setAttribute("name", 'Weapons')
-        wx.Panel.__init__(self, parent, -1)
-        self.grid =wx.grid.Grid(self, -1, style=wx.SUNKEN_BORDER | wx.WANTS_CHARS)
-        sizer = wx.BoxSizer(wx.HORIZONTAL)
-        sizer.Add(wx.Button(self, 10, "Remove Weapon"), 1, wx.EXPAND)
-        sizer.Add(wx.Size(10,10))
-        sizer.Add(wx.Button(self, 20, "Add Weapon"), 1, wx.EXPAND)
-        self.sizer = sizer
-        self.SetSizer(self.sizer)
-        self.Bind(wx.EVT_SIZE, self.on_size)
-        EVT_BUTTON(self, 10, self.on_remove)
-        EVT_BUTTON(self, 20, self.on_add)
-        self.grid.Bind(wx.grid.EVT_GRID_CELL_CHANGE, self.on_cell_change)
-        n_list = handler.master_dom.getElementsByTagName('weapon')
-        self.n_list = n_list
-        self.master_dom = handler.master_dom
-        self.handler = handler
-        self.grid.CreateGrid(len(n_list),9,1)
-        self.grid.SetRowLabelSize(0)
-        col_names = ['Name','damage','mod','critical','type','weight','range','size','Total']
-        for i in range(len(col_names)):
-            self.grid.SetColLabelValue(i,col_names[i])
-        self.refresh_data()
-        self.temp_dom = None
-
-    def on_cell_change(self,evt):
-        row = evt.GetRow()
-        col = evt.GetCol()
-        value = self.grid.GetCellValue(row,col)
-        if col == 0:
-            self.n_list[row].setAttribute('name',value)
-        elif col == 2:
-            try:
-                int(value)
-                self.n_list[row].setAttribute('mod',value)
-                self.refresh_row(row)
-            except:
-                self.grid.SetCellValue(row,col,"1")
-        else:
-            self.n_list[row].setAttribute(self.grid.GetColLabelValue(col),value)
-
-    def refresh_row(self,i):
-        n = self.n_list[i]
-        name = n.getAttribute('name')
-        mod = n.getAttribute('mod')
-        ran = n.getAttribute('range')
-        total = str(int(mod) + self.handler.get_mod(ran))
-        self.grid.SetCellValue(i,0,name)
-        self.grid.SetCellValue(i,1,n.getAttribute('damage'))
-        self.grid.SetCellValue(i,2,mod)
-        self.grid.SetCellValue(i,3,n.getAttribute('critical'))
-        self.grid.SetCellValue(i,4,n.getAttribute('type'))
-        self.grid.SetCellValue(i,5,n.getAttribute('weight'))
-        self.grid.SetCellValue(i,6,ran)
-        self.grid.SetCellValue(i,7,n.getAttribute('size') )
-        self.grid.SetCellValue(i,8,total)
-        self.grid.SetReadOnly(i,8)
-
-    def on_remove(self,evt):
-        rows = self.grid.GetNumberRows()
-        for i in range(rows):
-            if self.grid.IsInSelection(i,0):
-                self.grid.DeleteRows(i)
-                self.master_dom.removeChild(self.n_list[i])
-                self.n_list = self.master_dom.getElementsByTagName('weapon')
-                self.handler.refresh_weapons()
-
-    def on_add(self,evt):
-        if not self.temp_dom:
-            tmp = open(orpg.dirpath.dir_struct["SWd20"]+"d20weapons.xml","r")
-            xml_dom = parseXml_with_dlg(self,tmp.read())
-            xml_dom = xml_dom._get_firstChild()
-            tmp.close()
-            self.temp_dom = xml_dom
-        f_list = self.temp_dom.getElementsByTagName('weapon')
-        opts = []
-        for f in f_list:
-            opts.append(f.getAttribute('name'))
-        dlg = wx.SingleChoiceDialog(self,'Choose Weapon','Weapon List',opts)
-        if dlg.ShowModal() == wx.ID_OK:
-            i = dlg.GetSelection()
-            new_node = self.master_dom.appendChild(f_list[i].cloneNode(False))
-            self.grid.AppendRows(1)
-            self.n_list = self.master_dom.getElementsByTagName('weapon')
-            self.refresh_row(self.grid.GetNumberRows()-1)
-            self.handler.refresh_weapons()
-        dlg.Destroy()
-
-    def on_size(self,event):
-        s = self.GetClientSizeTuple()
-        self.grid.SetDimensions(0,0,s[0],s[1]-25)
-        self.sizer.SetDimension(0,s[1]-25,s[0],25)
-        (w,h) = self.grid.GetClientSizeTuple()
-        cols = self.grid.GetNumberCols()
-        col_w = w/(cols+1)
-        self.grid.SetColSize(0,col_w*2)
-        for i in range(1,cols):
-            self.grid.SetColSize(i,col_w)
-
-    def refresh_data(self):
-        for i in range(len(self.n_list)):
-            self.refresh_row(i)
-
-
-class attack_panel(wx.Panel):
-    def __init__(self, parent, handler):
-        pname = handler.master_dom.setAttribute("name", 'Melee')
-        wx.Panel.__init__(self, parent, -1)
-
-        self.a_grid = attack_grid(self, handler)
-        self.w_panel = weapon_panel(self, handler)
-        self.sizer = wx.BoxSizer(wx.VERTICAL)
-        self.sizer.Add(self.a_grid, 1, wx.EXPAND)
-        self.sizer.Add(self.w_panel, 2, wx.EXPAND)
-        self.SetSizer(self.sizer)
-        self.Bind(wx.EVT_SIZE, self.on_size)
-
-    def on_size(self,event):
-        s = self.GetClientSizeTuple()
-        self.sizer.SetDimension(0,0,s[0],s[1])
-
-    def refresh_data(self):
-        self.w_panel.refresh_data()
-        self.a_grid.refresh_data()
-
-
-class ac_panel(wx.Panel):
-    def __init__(self, parent, handler):
-        pname = handler.master_dom.setAttribute("name", 'Armor')
-        wx.Panel.__init__(self, parent, -1)
-        self.grid =wx.grid.Grid(self, -1, style=wx.SUNKEN_BORDER | wx.WANTS_CHARS)
-        sizer = wx.BoxSizer(wx.HORIZONTAL)
-        sizer.Add(wx.Button(self, 10, "Remove Armor"), 1, wx.EXPAND)
-        sizer.Add(wx.Size(10,10))
-        sizer.Add(wx.Button(self, 20, "Add Armor"), 1, wx.EXPAND)
-        self.sizer = sizer
-        self.SetSizer(self.sizer)
-        self.Bind(wx.EVT_SIZE, self.on_size)
-        EVT_BUTTON(self, 10, self.on_remove)
-        EVT_BUTTON(self, 20, self.on_add)
-        self.grid.Bind(wx.grid.EVT_GRID_CELL_CHANGE, self.on_cell_change)
-        self.master_dom = handler.master_dom
-        n_list = handler.master_dom._get_childNodes()
-        self.n_list = n_list
-        col_names = ['Armor','DR','Max Dex','Check Penalty','Weight','Speed (10)','Speed (6)','type']
-        self.grid.CreateGrid(len(n_list),len(col_names),1)
-        self.grid.SetRowLabelSize(0)
-        for i in range(len(col_names)):
-            self.grid.SetColLabelValue(i,col_names[i])
-        self.atts =['name','bonus','maxdex','checkpenalty','weight','speed','speed6','type']
-        for i in range(len(n_list)):
-            self.refresh_row(i)
-        self.temp_dom = None
-
-
-    def on_cell_change(self,evt):
-        row = evt.GetRow()
-        col = evt.GetCol()
-        value = self.grid.GetCellValue(row,col)
-        if col >= 1 and col <= 5:
-            try:
-                int(value)
-                self.n_list[row].setAttribute(self.atts[col],value)
-            except:
-                self.grid.SetCellValue(row,col,"0")
-        else:
-            self.n_list[row].setAttribute(self.atts[col],value)
-
-    def refresh_row(self,i):
-        n = self.n_list[i]
-        for y in range(len(self.atts)):
-            self.grid.SetCellValue(i,y,n.getAttribute(self.atts[y]))
-
-    def on_remove(self,evt):
-        rows = self.grid.GetNumberRows()
-        for i in range(rows):
-            if self.grid.IsInSelection(i,0):
-                self.grid.DeleteRows(i)
-                self.master_dom.removeChild(self.n_list[i])
-
-    def on_add(self,evt):
-        if not self.temp_dom:
-            tmp = open(orpg.dirpath.dir_struct["SWd20"]+"d20armor.xml","r")
-            xml_dom = parseXml_with_dlg(self,tmp.read())
-            xml_dom = xml_dom._get_firstChild()
-            tmp.close()
-            self.temp_dom = xml_dom
-        f_list = self.temp_dom.getElementsByTagName('armor')
-        opts = []
-        for f in f_list:
-            opts.append(f.getAttribute('name'))
-        dlg = wx.SingleChoiceDialog(self,'Choose Armor:','Armor List',opts)
-        if dlg.ShowModal() == wx.ID_OK:
-            i = dlg.GetSelection()
-            new_node = self.master_dom.appendChild(f_list[i].cloneNode(False))
-            self.grid.AppendRows(1)
-            self.refresh_row(self.grid.GetNumberRows()-1)
-        dlg.Destroy()
-
-    def on_size(self,event):
-        s = self.GetClientSizeTuple()
-        self.grid.SetDimensions(0,0,s[0],s[1]-25)
-        self.sizer.SetDimension(0,s[1]-25,s[0],25)
-        (w,h) = self.grid.GetClientSizeTuple()
-        cols = self.grid.GetNumberCols()
-        col_w = w/(cols+2)
-        self.grid.SetColSize(0,col_w*3)
-        for i in range(1,cols):
-            self.grid.SetColSize(i,col_w)
-
-
-class class_panel(wx.Panel):
-    def __init__(self, parent, handler):
-        pname = handler.master_dom.setAttribute("name", 'Class')
-        wx.Panel.__init__(self, parent, -1)
-        self.grid =wx.grid.Grid(self, -1, style=wx.SUNKEN_BORDER | wx.WANTS_CHARS)
-        sizer = wx.BoxSizer(wx.HORIZONTAL)
-        sizer.Add(wx.Button(self, 10, "Remove Class"), 1, wx.EXPAND)
-        sizer.Add(wx.Size(10,10))
-        sizer.Add(wx.Button(self, 20, "Add Class"), 1, wx.EXPAND)
-        self.sizer = sizer
-        self.SetSizer(self.sizer)
-        self.Bind(wx.EVT_SIZE, self.on_size)
-        EVT_BUTTON(self, 10, self.on_remove)
-        EVT_BUTTON(self, 20, self.on_add)
-        self.grid.Bind(wx.grid.EVT_GRID_CELL_CHANGE, self.on_cell_change)
-
-        n_list = handler.master_dom._get_childNodes()
-        self.n_list = n_list
-        self.master_dom = handler.master_dom
-        self.grid.CreateGrid(len(n_list),2,1)
-        self.grid.SetRowLabelSize(0)
-        self.grid.SetColLabelValue(0,"Class")
-        self.grid.SetColLabelValue(1,"Level")
-        for i in range(len(n_list)):
-            self.refresh_row(i)
-        self.temp_dom = None
-
-    def on_cell_change(self,evt):
-        row = evt.GetRow()
-        col = evt.GetCol()
-        value = self.grid.GetCellValue(row,col)
-        try:
-            int(value)
-            self.n_list[row].setAttribute('level',value)
-        except:
-            self.grid.SetCellValue(row,col,"1")
-
-
-    def refresh_row(self,i):
-        n = self.n_list[i]
-        name = n.getAttribute('name')
-        level = n.getAttribute('level')
-        self.grid.SetCellValue(i,0,name)
-        self.grid.SetReadOnly(i,0)
-        self.grid.SetCellValue(i,1,level)
-        #self.grid.SetReadOnly(i,1)
-
-    def on_remove(self,evt):
-        rows = self.grid.GetNumberRows()
-        for i in range(rows):
-            if self.grid.IsInSelection(i,0):
-                self.grid.DeleteRows(i)
-                self.master_dom.removeChild(self.n_list[i])
-
-    def on_add(self,evt):
-        if not self.temp_dom:
-            tmp = open(orpg.dirpath.dir_struct["SWd20"]+"SWd20classes.xml","r")
-            xml_dom = parseXml_with_dlg(self,tmp.read())
-            xml_dom = xml_dom._get_firstChild()
-            tmp.close()
-            self.temp_dom = xml_dom
-        f_list = self.temp_dom.getElementsByTagName('class')
-        opts = []
-        for f in f_list:
-            opts.append(f.getAttribute('name'))
-        dlg = wx.SingleChoiceDialog(self,'Choose Class','Classes',opts)
-        if dlg.ShowModal() == wx.ID_OK:
-            i = dlg.GetSelection()
-            new_node = self.master_dom.appendChild(f_list[i].cloneNode(False))
-            self.grid.AppendRows(1)
-            self.refresh_row(self.grid.GetNumberRows()-1)
-        dlg.Destroy()
-
-
-    def on_size(self,event):
-        s = self.GetClientSizeTuple()
-        self.grid.SetDimensions(0,0,s[0],s[1]-25)
-        self.sizer.SetDimension(0,s[1]-25,s[0],25)
-        (w,h) = self.grid.GetClientSizeTuple()
-        cols = self.grid.GetNumberCols()
-        col_w = w/(cols)
-        for i in range(0,cols):
-            self.grid.SetColSize(i,col_w)
+# Copyright (C) 2000-2001 The OpenRPG Project
+#
+#        openrpg-dev@lists.sourceforge.net
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# 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., 675 Mass Ave, Cambridge, MA 02139, USA.
+# --
+#
+# File: StarWarsd20.py
+# Author: Chris Davis; Mark Twombley
+# Maintainer: Mark Twombley
+# Version:
+#   $Id: StarWarsd20.py,v 1.18 2006/11/15 12:11:23 digitalxero Exp $
+#
+# Description: The file contains code for the StarWarsd20 nodehanlers
+#
+
+__version__ = "$Id: StarWarsd20.py,v 1.18 2006/11/15 12:11:23 digitalxero Exp $"
+
+from core import *
+
+SWD20_EXPORT = wx.NewId()
+############################
+## StarWarsd20 character node handler
+############################
+##The whole look and easy of use redone by Digitalxero
+class container_handler(node_handler):
+    """ should not be used! only a base class!
+    <nodehandler name='?'  module='core' class='container_handler'  />
+    """
+    def __init__(self,xml_dom,tree_node):
+        node_handler.__init__(self,xml_dom,tree_node)
+        self.load_children()
+
+    def load_children(self):
+        children = self.master_dom._get_childNodes()
+        for c in children:
+            self.tree.load_xml(c,self.mytree_node)
+
+
+    def on_drop(self,evt):
+        drag_obj = self.tree.drag_obj
+        #if self.is_my_child(self.mytree_node,drag_obj.mytree_node):
+        #    return
+        if drag_obj == self:
+            return
+        opt = wx.MessageBox("Add node as child?","Container Node",wx.YES_NO|wx.CANCEL)
+        if opt == wx.YES:
+            xml_dom = self.tree.drag_obj.delete()
+            xml_dom = self.master_dom.insertBefore(xml_dom,None)
+            self.tree.load_xml(xml_dom, self.mytree_node)
+            self.tree.Expand(self.mytree_node)
+        elif opt == wx.NO:
+            node_handler.on_drop(self,evt)
+
+    def tohtml(self):
+        cookie = 0
+        html_str = "<table border=\"1\" ><tr><td>"
+        html_str += "<b>"+self.master_dom.getAttribute("name") + "</b>"
+        html_str += "</td></tr>\n"
+        html_str += "<tr><td>"
+        max = tree.GetChildrenCount(handler.mytree_node)
+        try:
+            (child,cookie)=self.tree.GetFirstChild(self.mytree_node,cookie)
+        except: # If this happens we probably have a newer version of wxPython
+            (child,cookie)=self.tree.GetFirstChild(self.mytree_node)
+        obj = self.tree.GetPyData(child)
+        for m in xrange(max):
+            html_str += "<p>" + obj.tohtml()
+            if m < max-1:
+                child = self.tree.GetNextSibling(child)
+                obj = self.tree.GetPyData(child)
+        html_str += "</td></tr></table>"
+        return html_str
+
+    def get_size_constraint(self):
+        return 1
+
+    def get_char_name( self ):
+        return self.child_handlers['general'].get_char_name()
+
+##    def set_char_pp(self,attr,evl):
+##        return self.child_handlers['pp'].set_char_pp(attr,evl)
+##
+##    def get_char_pp( self, attr ):
+##        return self.child_handlers['pp'].get_char_pp(attr)
+##
+    def get_char_lvl( self, attr ):
+        return self.child_handlers['classes'].get_char_lvl(attr)
+
+
+
+class SWd20char_handler(node_handler):
+    """ Node handler for a SWd20 charactor
+        <nodehandler name='?'  module='StarWarsd20' class='SWd20char_handler'  />
+    """
+    def __init__(self,xml_dom,tree_node):
+        node_handler.__init__(self,xml_dom,tree_node)
+        self.frame = open_rpg.get_component('frame')
+        self.child_handlers = {}
+        self.new_child_handler('howtouse','HowTO use this tool',SWd20howto,'note')
+        self.new_child_handler('general','General Information',SWd20general,'gear')
+        self.new_child_handler('inventory','Money and Inventory',SWd20inventory,'money')
+        self.new_child_handler('abilities','Abilities Scores',SWd20ability,'gear')
+        self.new_child_handler('classes','Classes',SWd20classes,'knight')
+        self.new_child_handler('saves','Saves',SWd20saves,'skull')
+        self.new_child_handler('skills','Skills',SWd20skill,'book')
+        self.new_child_handler('feats','Feats',SWd20feats,'book')
+        self.new_child_handler('wp','Wound Points',SWd20hp,'gear')
+        self.new_child_handler('vp','Vitality Points',SWd20vp,'gear')
+        self.new_child_handler('attacks','Attacks',SWd20attacks,'spears')
+        self.new_child_handler('ac','Armor',SWd20armor,'spears')
+        self.myeditor = None
+
+
+    def on_version(self,old_version):
+        node_handler.on_version(self,old_version)
+        if old_version == "":
+            tmp = open(orpg.dirpath.dir_struct["nodes"]+"StarWars_d20character.xml","r")
+            xml_dom = parseXml_with_dlg(self.tree,tmp.read())
+            xml_dom = xml_dom._get_firstChild()
+            tmp.close()
+            ## add new nodes
+            for tag in ("howtouse","inventory","powers","divine","pp"):
+                node_list = xml_dom.getElementsByTagName(tag)
+                self.master_dom.appendChild(node_list[0])
+
+            ## add new atts
+            melee_attack = self.master_dom.getElementsByTagName('melee')[0]
+            melee_attack.setAttribute("second","0")
+            melee_attack.setAttribute("third","0")
+            melee_attack.setAttribute("forth","0")
+            melee_attack.setAttribute("fifth","0")
+            melee_attack.setAttribute("sixth","0")
+            range_attack = self.master_dom.getElementsByTagName('ranged')[0]
+            range_attack.setAttribute("second","0")
+            range_attack.setAttribute("third","0")
+            range_attack.setAttribute("forth","0")
+            range_attack.setAttribute("fifth","0")
+            range_attack.setAttribute("sixth","0")
+
+            gen_list = self.master_dom.getElementsByTagName('general')[0]
+
+            for tag in ("currentxp","xptolevel"):
+                node_list = xml_dom.getElementsByTagName(tag)
+                gen_list.appendChild(node_list[0])
+            ## temp fix
+            #parent = self.master_dom._get_parentNode()
+            #old_dom = parent.replaceChild(xml_dom,self.master_dom)
+            #self.master_dom = xml_dom
+        print old_version
+
+
+    def get_char_name( self ):
+        return self.child_handlers['general'].get_char_name()
+
+##    def set_char_pp(self,attr,evl):
+##        return self.child_handlers['pp'].set_char_pp(attr,evl)
+##
+##    def get_char_pp( self, attr ):
+##        return self.child_handlers['pp'].get_char_pp(attr)
+
+    def get_char_lvl( self, attr ):
+        return self.child_handlers['classes'].get_char_lvl(attr)
+
+
+    def new_child_handler(self,tag,text,handler_class,icon='gear'):
+        node_list = self.master_dom.getElementsByTagName(tag)
+        tree = self.tree
+        i = self.tree.icons[icon]
+        new_tree_node = tree.AppendItem(self.mytree_node,text,i,i)
+        handler = handler_class(node_list[0],new_tree_node,self)
+        tree.SetPyData(new_tree_node,handler)
+        self.child_handlers[tag] = handler
+
+    def get_design_panel(self,parent):
+        return tabbed_panel(parent,self,1)
+
+
+    def get_use_panel(self,parent):
+        return tabbed_panel(parent,self,2)
+
+
+    def tohtml(self):
+        html_str = "<table><tr><td colspan=2 >"+self.child_handlers['general'].tohtml()+"</td></tr>"
+        html_str += "<tr><td width='50%' valign=top >"+self.child_handlers['abilities'].tohtml()
+        html_str += "<P>" + self.child_handlers['saves'].tohtml()
+        html_str += "<P>" + self.child_handlers['attacks'].tohtml()
+        html_str += "<P>" + self.child_handlers['ac'].tohtml()
+        html_str += "<P>" + self.child_handlers['feats'].tohtml()
+        #html_str += "<P>" + self.child_handlers['spells'].tohtml()
+        #html_str += "<P>" + self.child_handlers['divine'].tohtml()
+        #html_str += "<P>" + self.child_handlers['powers'].tohtml()
+        html_str += "<P>" + self.child_handlers['inventory'].tohtml() +"</td>"
+        html_str += "<td width='50%' valign=top >"+self.child_handlers['classes'].tohtml()
+        html_str += "<P>" + self.child_handlers['wp'].tohtml()
+        html_str += "<P>" + self.child_handlers['vp'].tohtml()
+        #html_str += "<P>" + self.child_handlers['pp'].tohtml()
+        html_str += "<P>" + self.child_handlers['skills'].tohtml() +"</td>"
+        html_str += "</tr></table>"
+        return html_str
+
+    def about(self):
+        html_str = "<img src='" + orpg.dirpath.dir_struct["icon"]+'d20_logo.gif' "><br /><b>d20 Character Tool v0.7 beta</b>"
+        html_str += "<br />by Chris Davis<br />chris@rpgarchive.com"
+        return html_str
+
+    def get_char_name( self ):
+        return self.child_handlers['general'].get_char_name()
+    def get_armor_class( self ):
+        return self.child_handlers['ac'].get_armor_class()
+    def get_max_hp( self ):
+        return self.child_handlers['wp'].get_max_hp()
+    def get_current_hp( self ):
+        return self.child_handlers['wp'].get_current_hp()
+    def get_max_vp( self ):
+        return self.child_handlers['vp'].get_max_vp()
+    def get_current_vp( self ):
+        return self.child_handlers['vp'].get_current_vp()
+
+##    def set_char_pp(self,attr,evl):
+##        return self.child_handlers['pp'].set_char_pp(attr,evl)
+##
+##    def get_char_pp( self, attr ):
+##        return self.child_handlers['pp'].get_char_pp(attr)
+
+    def get_char_lvl( self, attr ):
+        return self.child_handlers['classes'].get_char_lvl(attr)
+
+class tabbed_panel(wx.Notebook):
+    def __init__(self, parent, handler, mode):
+        wx.Notebook.__init__(self, parent, -1, size=(1200,800))
+        self.handler = handler
+        self.parent = parent
+        tree = self.handler.tree
+        max = tree.GetChildrenCount(handler.mytree_node, False)
+        cookie = 0
+        try:
+            (child,cookie)=tree.GetFirstChild(handler.mytree_node,cookie)
+        except: # If this happens we probably have a newer version of wxPython
+            (child,cookie)=tree.GetFirstChild(handler.mytree_node)
+        obj = tree.GetPyData(child)
+        for m in xrange(max):
+    
+            if mode == 1:
+                panel = obj.get_design_panel(self)
+            else:
+                panel = obj.get_use_panel(self)
+            name = obj.master_dom.getAttribute("name")
+
+            if panel:
+                self.AddPage(panel,name)
+            if m < max-1: 
+                child = tree.GetNextSibling(child)
+                obj = tree.GetPyData(child)
+
+
+    def about(self):
+        html_str = "<img src='" + orpg.dirpath.dir_struct["icon"]+'d20_logo.gif' "><br /><b>d20 Character Tool v0.7 beta</b>"
+        html_str += "<br />by Chris Davis<br />chris@rpgarchive.com"
+        return html_str
+
+    def get_char_name( self ):
+        return self.child_handlers['general'].get_char_name()
+
+##    def set_char_pp(self,attr,evl):
+##        return self.child_handlers['pp'].set_char_pp(attr,evl)
+##
+##    def get_char_pp( self, attr ):
+##        return self.child_handlers['pp'].get_char_pp(attr)
+
+    def get_char_lvl( self, attr ):
+        return self.child_handlers['classes'].get_char_lvl(attr)
+
+class SWd20_char_child(node_handler):
+    """ Node Handler for skill.  This handler will be
+        created by SWd20char_handler.
+    """
+    def __init__(self, xml_dom, tree_node, parent):
+        node_handler.__init__(self,xml_dom, tree_node)
+        self.char_hander = parent
+        self.drag = False
+        self.frame = open_rpg.get_component('frame')
+        self.myeditor = None
+
+
+    def on_drop(self,evt):
+        pass
+
+    def on_rclick(self,evt):
+        pass
+
+    def on_ldclick(self,evt): #Function needs help. Needs an OnClose I think.
+        if self.myeditor == None or self.myeditor.destroyed:
+            title = self.master_dom.getAttribute('name') + " Editor"
+            # Frame created in correctly.
+            self.myeditor = wx.Frame(self.frame,title,orpg.dirpath.dir_struct["icon"]+'grid.ico')
+            wnd = self.get_design_panel(self.myeditor)
+            self.myeditor.panel = wnd
+            self.wnd = wnd
+            self.myeditor.Show(1)
+        else:
+            self.myeditor.Raise()
+
+    def on_html(self,evt):
+        html_str = self.tohtml()
+        wnd = http_html_window(self.frame.note,-1)
+        wnd.title = self.master_dom.getAttribute('name')
+        self.frame.add_panel(wnd)
+        wnd.SetPage(html_str)
+
+    def get_design_panel(self,parent):
+        pass
+
+    def get_use_panel(self,parent):
+        return self.get_design_panel(parent)
+
+    def delete(self):
+        pass
+
+
+class SWd20skill(SWd20_char_child):
+    """ Node Handler for skill.  This handler will be
+        created by SWd20char_handler.
+    """
+    def __init__(self, xml_dom, tree_node, parent):
+        SWd20_char_child.__init__(self, xml_dom, tree_node, parent)
+        tree = self.tree
+        icons = self.tree.icons
+        node_list = self.master_dom.getElementsByTagName('skill')
+        self.skills={}
+        for n in node_list:
+            name = n.getAttribute('name')
+            self.skills[name] = n
+            new_tree_node = tree.AppendItem(self.mytree_node,name,icons['gear'],icons['gear'])
+            tree.SetPyData(new_tree_node,self)
+
+    def get_mod(self,name):
+        skill = self.skills[name]
+        stat = skill.getAttribute('stat')
+        ac = int(skill.getAttribute('armorcheck'))
+        if ac:
+            ac = self.char_hander.child_handlers['ac'].get_check_pen()
+        stat_mod = self.char_hander.child_handlers['abilities'].get_mod(stat)
+        rank = int(skill.getAttribute('rank'))
+        misc = int(skill.getAttribute('misc'))
+        total = stat_mod + rank + misc + ac
+        return total
+
+    def on_rclick(self,evt):
+        #updated with code for untrained use check
+        item = self.tree.GetSelection()
+        name = self.tree.GetItemText(item)
+        skill = self.skills[name]
+        rank = int(skill.getAttribute('rank'))
+        untrained = int(skill.getAttribute('untrained'))
+        chat = self.chat
+        if item == self.mytree_node:
+            SWd20_char_child.on_ldclick(self,evt)
+        else:
+            if rank == 0 and untrained == 0:
+                chat.Post('Can\'t use untrained!',True,True)
+            else:
+                mod = self.get_mod(name)
+                if mod >= 0:
+                    mod1 = "+"
+                else:
+                    mod1 = ""
+                txt = '%s Skill Check: [1d20%s%s]' % (name, mod1, mod)
+                chat.ParsePost(txt,True,True)
+
+    def get_design_panel(self,parent):
+        wnd = outline_panel(parent,self,skill_grid,"Skills")
+        wnd.title = "Skills (edit)"
+        return wnd
+
+    def tohtml(self):
+        html_str = """<table border='1' width=100% ><tr BGCOLOR=#E9E9E9 ><th width='30%'>Skill</th><th>Key</th>
+                    <th>Rank</th><th>Abil</th><th>Misc</th><th>Total</th></tr>"""
+        node_list = self.master_dom.getElementsByTagName('skill')
+        for n in node_list:
+            name = n.getAttribute('name')
+            stat = n.getAttribute('stat')
+            rank = n.getAttribute('rank')
+            html_str = html_str + "<tr ALIGN='center'><td>"+name+"</td><td>"+stat+"</td><td>"+rank+"</td>"
+            stat_mod = str(self.char_hander.child_handlers['abilities'].get_mod(stat))
+            misc = n.getAttribute('misc')
+            mod = str(self.get_mod(name))
+            if mod >= 0:
+                mod1 = "+"
+            else:
+                mod1 = ""
+            html_str = html_str + "<td>"+stat_mod+"</td><td>"+misc+'</td><td>%s%s</td></tr>' % (mod1, mod)
+        html_str = html_str + "</table>"
+        return html_str
+
+
+class SWd20ability(SWd20_char_child):
+    """ Node Handler for ability.   This handler will be
+        created by SWd20char_handler.
+    """
+    def __init__(self, xml_dom, tree_node, parent):
+        SWd20_char_child.__init__(self, xml_dom, tree_node, parent)
+        self.abilities = {}
+        node_list = self.master_dom.getElementsByTagName('stat')
+        tree = self.tree
+        icons = tree.icons
+        for n in node_list:
+            name = n.getAttribute('abbr')
+            self.abilities[name] = n
+            new_tree_node = tree.AppendItem( self.mytree_node, name, icons['gear'], icons['gear'] )
+            tree.SetPyData( new_tree_node, self )
+
+    def on_rclick( self, evt ):
+        item = self.tree.GetSelection()
+        name = self.tree.GetItemText( item )
+        if item == self.mytree_node:
+            SWd20_char_child.on_ldclick( self, evt )
+        else:
+            mod = self.get_mod( name )
+            if mod >= 0:
+                mod1 = "+"
+            else:
+                mod1 = ""
+            chat = self.chat
+            txt = '%s check: [1d20%s%s]' % ( name, mod1, mod )
+            chat.ParsePost( txt, True, True )
+
+    def get_mod(self,abbr):
+        score = int(self.abilities[abbr].getAttribute('base'))
+        mod = (score - 10) / 2
+        return mod
+
+    def set_score(self,abbr,score):
+        if score >= 0:
+            self.abilities[abbr].setAttribute("base",str(score))
+
+    def get_design_panel(self,parent):
+        wnd = outline_panel(parent,self,abil_grid,"Abilities")
+        wnd.title = "Abilities (edit)"
+        return wnd
+
+    def tohtml(self):
+        html_str = """<table border='1' width=100%><tr BGCOLOR=#E9E9E9 ><th width='50%'>Ability</th>
+                    <th>Base</th><th>Modifier</th></tr>"""
+        node_list = self.master_dom.getElementsByTagName('stat')
+        for n in node_list:
+            name = n.getAttribute('name')
+            abbr = n.getAttribute('abbr')
+            base = n.getAttribute('base')
+            mod = str(self.get_mod(abbr))
+            if mod >= 0:
+                mod1 = "+"
+            else:
+                mod1 = ""
+            html_str = html_str + "<tr ALIGN='center'><td>"+name+"</td><td>"+base+'</td><td>%s%s</td></tr>' % (mod1, mod)
+        html_str = html_str + "</table>"
+        return html_str
+
+class SWd20saves(SWd20_char_child):
+    """ Node Handler for saves.   This handler will be
+        created by SWd20char_handler.
+    """
+    def __init__(self, xml_dom, tree_node, parent):
+        SWd20_char_child.__init__(self, xml_dom, tree_node, parent)
+        tree = self.tree
+        icons = self.tree.icons
+        node_list = self.master_dom.getElementsByTagName('save')
+        self.saves={}
+        for n in node_list:
+            name = n.getAttribute('name')
+            self.saves[name] = n
+            new_tree_node = tree.AppendItem(self.mytree_node,name,icons['gear'],icons['gear'])
+            tree.SetPyData(new_tree_node,self)
+
+    def get_mod(self,name):
+        save = self.saves[name]
+        stat = save.getAttribute('stat')
+        stat_mod = self.char_hander.child_handlers['abilities'].get_mod(stat)
+        base = int(save.getAttribute('base'))
+        miscmod = int(save.getAttribute('miscmod'))
+#        magmod = int(save.getAttribute('magmod'))
+#        total = stat_mod + base + miscmod + magmod
+        total = stat_mod + base + miscmod
+        return total
+
+    def on_rclick(self,evt):
+        item = self.tree.GetSelection()
+        name = self.tree.GetItemText(item)
+        if item == self.mytree_node:
+            SWd20_char_child.on_ldclick(self,evt)
+            #wnd = save_grid(self.frame.note,self)
+            #wnd.title = "Saves"
+            #self.frame.add_panel(wnd)
+        else:
+            mod = self.get_mod(name)
+            if mod >= 0:
+                mod1 = "+"
+            else:
+                mod1 = ""
+            chat = self.chat
+            txt = '%s save: [1d20%s%s]' % (name, mod1, mod)
+            chat.ParsePost( txt, True, True )
+
+    def get_design_panel(self,parent):
+        wnd = outline_panel(parent,self,save_grid,"Saves")
+        wnd.title = "Saves"
+        return wnd
+
+    def tohtml(self):
+        html_str = """<table border='1' width=100% ><tr BGCOLOR=#E9E9E9 ><th width='30%'>Save</th>
+                    <th>Key</th><th>Base</th><th>Abil</th><th>Magic</th>
+                    <th>Misc</th><th>Total</th></tr>"""
+        node_list = self.master_dom.getElementsByTagName('save')
+        for n in node_list:
+            name = n.getAttribute('name')
+            stat = n.getAttribute('stat')
+            base = n.getAttribute('base')
+            html_str = html_str + "<tr ALIGN='center'><td>"+name+"</td><td>"+stat+"</td><td>"+base+"</td>"
+            stat_mod = str(self.char_hander.child_handlers['abilities'].get_mod(stat))
+            mag = n.getAttribute('magmod')
+            misc = n.getAttribute('miscmod')
+            mod = str(self.get_mod(name))
+            if mod >= 0:
+                mod1 = "+"
+            else:
+                mod1 = ""
+            html_str = html_str + "<td>"+stat_mod+"</td><td>"+mag+"</td>"
+            html_str = html_str + '<td>'+misc+'</td><td>%s%s</td></tr>' % (mod1, mod)
+        html_str = html_str + "</table>"
+        return html_str
+
+
+class SWd20general(SWd20_char_child):
+    """ Node Handler for general information.   This handler will be
+        created by SWd20char_handler.
+    """
+    def __init__(self, xml_dom, tree_node, parent):
+        SWd20_char_child.__init__(self, xml_dom, tree_node, parent)
+
+    def get_design_panel(self,parent):
+        wnd = outline_panel(parent,self,gen_grid,"General Information")
+        wnd.title = "General Info"
+        return wnd
+
+    def tohtml(self):
+        n_list = self.master_dom._get_childNodes()
+        html_str = "<table width=100% border=1 ><tr BGCOLOR=#E9E9E9 ><th>General Information</th></tr><tr><td>"
+        for n in n_list:
+            t_node = safe_get_text_node(n)
+            html_str += "<B>"+n._get_tagName().capitalize() +":</B> "
+            html_str += t_node._get_nodeValue() + ", "
+        html_str = html_str[:len(html_str)-2] + "</td></tr></table>"
+        return html_str
+
+    def on_name_change(self,name):
+        self.char_hander.rename(name)
+
+    def get_char_name( self ):
+        node = self.master_dom.getElementsByTagName( 'name' )[0]
+        t_node = safe_get_text_node( node )
+        return t_node._get_nodeValue()
+
+
+class SWd20classes(SWd20_char_child):
+    """ Node Handler for classes.  This handler will be
+        created by SWd20char_handler.
+    """
+    def __init__(self, xml_dom, tree_node, parent):
+        SWd20_char_child.__init__(self, xml_dom, tree_node, parent)
+
+    def get_design_panel(self,parent):
+        wnd = outline_panel(parent,self,class_panel,"Classes")
+        wnd.title = "Classes"
+        return wnd
+
+    def tohtml(self):
+        html_str = "<table width=100% border=1 ><tr BGCOLOR=#E9E9E9 ><th>Classes</th></tr><tr><td>"
+        n_list = self.master_dom._get_childNodes()
+        for n in n_list:
+            html_str += n.getAttribute('name') + " ("+n.getAttribute('level')+"), "
+        html_str = html_str[:len(html_str)-2] + "</td></tr></table>"
+        return html_str
+
+    def get_char_lvl( self, attr ):
+        node_list = self.master_dom.getElementsByTagName('class')
+        for n in node_list:
+            lvl = n.getAttribute('level')
+            type = n.getAttribute('name')
+            if attr == "level":
+                return lvl
+            elif attr == "class":
+                return type
+
+
+class SWd20feats(SWd20_char_child):
+    """ Node Handler for classes.  This handler will be
+        created by d20char_handler.
+    """
+    def __init__(self, xml_dom, tree_node, parent):
+        SWd20_char_child.__init__(self, xml_dom, tree_node, parent)
+
+    def get_design_panel(self,parent):
+        wnd = outline_panel(parent,self,feat_panel,"Feats")
+        wnd.title = "Feats"
+        return wnd
+
+    def tohtml(self):
+        html_str = "<table width=100% border=1 ><tr BGCOLOR=#E9E9E9 ><th>Feats</th></tr><tr><td>"
+        n_list = self.master_dom._get_childNodes()
+        for n in n_list:
+            html_str += n.getAttribute('name')+ ", "
+        html_str = html_str[:len(html_str)-2] + "</td></tr></table>"
+        return html_str
+
+class SWd20howto(SWd20_char_child):
+    """ Node Handler for hit points.  This handler will be
+        created by d20char_handler.
+    """
+    def __init__(self, xml_dom, tree_node, parent):
+        SWd20_char_child.__init__(self, xml_dom, tree_node, parent)
+
+    def get_design_panel(self,parent):
+        wnd = outline_panel(parent,self,howto_panel,"How To")
+        wnd.title = "How To"
+        return wnd
+
+class SWd20inventory(SWd20_char_child):
+    """ Node Handler for general information.   This handler will be
+        created by d20char_handler.
+    """
+    def __init__(self, xml_dom, tree_node, parent):
+        SWd20_char_child.__init__(self, xml_dom, tree_node, parent)
+
+    def get_design_panel(self,parent):
+        wnd = outline_panel(parent,self,inventory_grid,"Inventory")
+        wnd.title = "General Info"
+        return wnd
+
+    def tohtml(self):
+        n_list = self.master_dom._get_childNodes()
+        html_str = "<table width=100% border=1 ><tr BGCOLOR=#E9E9E9 ><th>General Information</th></tr><tr><td>"
+        for n in n_list:
+            t_node = safe_get_text_node(n)
+            html_str += "<B>"+n._get_tagName().capitalize() +":</B> "
+            html_str += t_node._get_nodeValue() + "<br />"
+        html_str = html_str[:len(html_str)-2] + "</td></tr></table>"
+        return html_str
+
+    def on_name_change(self,name):
+        self.char_hander.rename(name)
+
+    def get_char_name( self ):
+        node = self.master_dom.getElementsByTagName( 'name' )[0]
+        t_node = safe_get_text_node( node )
+        return t_node._get_nodeValue()
+
+class SWd20hp(SWd20_char_child):
+    """ Node Handler for hit points.  This handler will be
+        created by d20char_handler.
+    """
+    def __init__(self,xml_dom,tree_node,parent):
+        SWd20_char_child.__init__(self,xml_dom,tree_node,parent)
+
+    def get_design_panel(self,parent):
+        wnd = outline_panel(parent,self,hp_panel,"Wound Points")
+        wnd.title = "Wound Points"
+        return wnd
+
+    def tohtml(self):
+        html_str = "<table width=100% border=1 ><tr BGCOLOR=#E9E9E9 ><th colspan=4>Wound Points</th></tr>"
+        html_str += "<tr><th>Max:</th><td>"+self.master_dom.getAttribute('max')+"</td>"
+        html_str += "<th>Current:</th><td>"+self.master_dom.getAttribute('current')+"</td>"
+        html_str += "</tr></table>"
+        return html_str
+
+    def get_max_hp( self ):
+        try:
+            return eval( self.master_dom.getAttribute( 'max' ) )
+        except:
+            return 0
+    def get_current_hp( self ):
+        try:
+            return eval( self.master_dom.getAttribute( 'current' ) )
+        except:
+            return 0
+
+class SWd20vp(SWd20_char_child):
+    """ Node Handler for hit points.  This handler will be
+        created by d20char_handler.
+    """
+    def __init__(self,xml_dom,tree_node,parent):
+        SWd20_char_child.__init__(self,xml_dom,tree_node,parent)
+
+    def get_design_panel(self,parent):
+        wnd = outline_panel(parent,self,vp_panel,"Vitality Points")
+        wnd.title = "Vitality Points"
+        return wnd
+
+    def tohtml(self):
+        html_str = "<table width=100% border=1 ><tr BGCOLOR=#E9E9E9 ><th colspan=4>Vitality Points</th></tr>"
+        html_str += "<tr><th>Max:</th><td>"+self.master_dom.getAttribute('max')+"</td>"
+        html_str += "<th>Current:</th><td>"+self.master_dom.getAttribute('current')+"</td>"
+        html_str += "</tr></table>"
+        return html_str
+
+    def get_max_vp( self ):
+        try:
+            return eval( self.master_dom.getAttribute( 'max' ) )
+        except:
+            return 0
+    def get_current_vp( self ):
+        try:
+            return eval( self.master_dom.getAttribute( 'current' ) )
+        except:
+            return 0
+
+class SWd20attacks(SWd20_char_child):
+    """ Node Handler for attacks.  This handler will be
+        created by d20char_handler.
+    """
+    def __init__(self,xml_dom,tree_node,parent):
+        SWd20_char_child.__init__(self,xml_dom,tree_node,parent)
+        node_list = self.master_dom.getElementsByTagName('melee')
+        self.melee = node_list[0]
+        node_list = self.master_dom.getElementsByTagName('ranged')
+        self.ranged = node_list[0]
+        self.refresh_weapons()
+
+    def refresh_weapons(self):
+        self.weapons = {}
+        tree = self.tree
+        icons = self.tree.icons
+        tree.CollapseAndReset(self.mytree_node)
+        node_list = self.master_dom.getElementsByTagName('weapon')
+        for n in node_list:
+            name = n.getAttribute('name')
+            new_tree_node = tree.AppendItem(self.mytree_node,name,icons['sword'],icons['sword'])
+            tree.SetPyData(new_tree_node,self)
+            self.weapons[name]=n
+
+    def get_mod(self,type='m'):
+        (base, base2, base3, base4, base5, base6, stat_mod, misc) = self.get_attack_data(type)
+        return base + misc + stat_mod
+
+    def get_attack_data(self,type='m'):
+        if type=='m' or type=='0':
+            stat_mod = self.char_hander.child_handlers['abilities'].get_mod('Str')
+            temp = self.melee
+        else:
+            stat_mod = self.char_hander.child_handlers['abilities'].get_mod('Dex')
+            temp = self.ranged
+        base = int(temp.getAttribute('base'))
+        base2 = int(temp.getAttribute('second'))
+        base3 = int(temp.getAttribute('third'))
+        base4 = int(temp.getAttribute('forth'))
+        base5 = int(temp.getAttribute('fifth'))
+        base6 = int(temp.getAttribute('sixth'))
+        misc = int(temp.getAttribute('misc'))
+        return (base, base2, base3, base4, base5, base6, stat_mod ,misc)
+
+    def on_rclick(self,evt):
+        #removed the DnD specific code
+        item = self.tree.GetSelection()
+        name = self.tree.GetItemText(item)
+        if item == self.mytree_node:
+            SWd20_char_child.on_ldclick(self,evt)
+            #self.frame.add_panel(self.get_design_panel(self.frame.note))
+        else:
+            mod = int(self.weapons[name].getAttribute('mod'))
+            if self.weapons[name].getAttribute('range') == '0':
+                mod = mod + self.get_mod('m')
+                if mod >= 0:
+                    mod1 = "+"
+                else:
+                    mod1 = ""
+            else:
+                mod = mod + self.get_mod('r')
+                if mod >= 0:
+                    mod1 = "+"
+                else:
+                    mod1 = ""
+            chat = self.chat
+            dmg = self.weapons[name].getAttribute('damage')
+            lvl = self.get_char_lvl('level')
+            cname = self.char_hander.get_char_name()
+            txt = '%s %s Attack Roll: [1d20%s%s] ===> DMG: [%s%s%s]' % (cname, name, mod1, mod, dmg, mod1, mod)
+            chat.ParsePost( txt, True, False )
+            temp = self.melee
+            stat_mod = self.char_hander.child_handlers['abilities'].get_mod('Str')
+
+    def get_design_panel(self,parent):
+        wnd = outline_panel(parent,self,attack_panel,"Attacks")
+        wnd.title = "Attacks"
+        return wnd
+
+    def get_char_lvl( self, attr ):
+        return self.char_hander.get_char_lvl(attr)
+
+    def tohtml(self):
+        melee = self.get_attack_data('m')
+        ranged = self.get_attack_data('r')
+        html_str = """<table width=100% border=1 ><tr BGCOLOR=#E9E9E9 ><th>Attack</th>
+                    <th>Total</th><th >Base</th><th>Abil</th><th>Misc</th></tr>"""
+        html_str += "<tr ALIGN='center' ><th >Melee:</th>"
+        html_str += "<td>"+str(melee[0]+melee[1]+melee[2])+"</td>"
+        html_str += "<td>"+str(melee[0])+"</td>"
+        html_str += "<td>"+str(melee[1])+"</td>"
+        html_str += "<td>"+str(melee[2])+"</td></tr>"
+
+        html_str += "<tr ALIGN='center' ><th >Ranged:</th>"
+        html_str += "<td>"+str(ranged[0]+ranged[1]+ranged[2])+"</td>"
+        html_str += "<td>"+str(ranged[0])+"</td>"
+        html_str += "<td>"+str(ranged[1])+"</td>"
+        html_str += "<td>"+str(ranged[2])+"</td></tr></table>"
+
+        n_list = self.master_dom.getElementsByTagName('weapon')
+        for n in n_list:
+            mod = n.getAttribute('mod')
+            if mod >= 0:
+                mod1 = "+"
+            else:
+                mod1 = ""
+            ran = n.getAttribute('range')
+            total = str(int(mod) + self.get_mod(ran))
+            html_str += """<P><table width=100% border=1 ><tr BGCOLOR=#E9E9E9 ><th colspan=2>Weapon</th>
+                    <th>Attack</th><th >Damage</th><th>Critical</th></tr>"""
+            html_str += "<tr ALIGN='center' ><td  colspan=2>"+n.getAttribute('name')+"</td><td>"+total+"</td>"
+            html_str += "<td>"+n.getAttribute('damage')+"</td><td>"+n.getAttribute('critical')+"</td></tr>"
+            html_str += """<tr BGCOLOR=#E9E9E9 ><th>Range</th><th>Weight</th>
+                        <th>Type</th><th>Size</th><th>Misc Mod</th></tr>"""
+            html_str += "<tr ALIGN='center'><td>"+ran+"</td><td>"+n.getAttribute('weight')+"</td>"
+            html_str += "<td>"+n.getAttribute('type')+"</td><td>"+n.getAttribute('size')+"</td>"
+            html_str += '<td>%s%s</td></tr></table>' % (mod1, mod)
+        return html_str
+
+class SWd20armor(SWd20_char_child):
+    """ Node Handler for ac.  This handler will be
+        created by d20char_handler.
+    """
+    def __init__(self,xml_dom,tree_node,parent):
+        SWd20_char_child.__init__(self,xml_dom,tree_node,parent)
+
+    def get_total_weight(self):
+        return self.get_total('weight')
+
+    def get_check_pen(self):
+        return self.get_total('checkpenalty')
+
+    def get_armor_class(self):
+        ac_total = 10
+        ac_total += self.get_total('bonus')
+        dex_mod = self.char_hander.child_handlers['abilities'].get_mod('Dex')
+        max_dex = self.get_max_dex()
+        if dex_mod < max_dex:
+            ac_total += dex_mod
+        else:
+            ac_total += max_dex
+        return ac_total
+
+    def get_max_dex(self):
+        armor_list = self.master_dom.getElementsByTagName('armor')
+        dex = 10
+        for a in armor_list:
+            temp = int(a.getAttribute("maxdex"))
+            if temp < dex:
+                dex = temp
+        return dex
+
+    def get_total(self,attr):
+        armor_list = self.master_dom.getElementsByTagName('armor')
+        total = 0
+        for a in armor_list:
+            total += int(a.getAttribute(attr))
+        return total
+
+    def get_design_panel(self,parent):
+        wnd = outline_panel(parent,self,ac_panel,"Armor")
+        wnd.title = "Armor"
+        return wnd
+
+    def tohtml(self):
+        html_str = """<table width=100% border=1 ><tr BGCOLOR=#E9E9E9 ><th>AC</th>
+                    <th>Check Penalty</th><th >Spell Failure</th><th>Max Dex</th><th>Total Weight</th></tr>"""
+        html_str += "<tr ALIGN='center' ><td>"+str(self.get_armor_class())+"</td>"
+        html_str += "<td>"+str(self.get_check_pen())+"</td>"
+        html_str += "<td>"+str(self.get_spell_failure())+"</td>"
+        html_str += "<td>"+str(self.get_max_dex())+"</td>"
+        html_str += "<td>"+str(self.get_total_weight())+"</td></tr></table>"
+        n_list = self.master_dom._get_childNodes()
+        for n in n_list:
+            html_str += """<P><table width=100% border=1 ><tr BGCOLOR=#E9E9E9 ><th colspan=3>Armor</th>
+                    <th>Type</th><th >Bonus</th></tr>"""
+            html_str += "<tr ALIGN='center' ><td  colspan=3>"+n.getAttribute('name')+"</td>"
+            html_str += "<td>"+n.getAttribute('type')+"</td>"
+            html_str += "<td>"+n.getAttribute('bonus')+"</td></tr>"
+            html_str += """<tr BGCOLOR=#E9E9E9 ><th>Check Penalty</th><th>Spell Failure</th>
+                        <th>Max Dex</th><th>Speed</th><th>Weight</th></tr>"""
+            html_str += "<tr ALIGN='center'><td>"+n.getAttribute('checkpenalty')+"</td>"
+            html_str += "<td>"+n.getAttribute('maxdex')+"</td>"
+            html_str += "<td>"+n.getAttribute('speed')+"</td>"
+            html_str += "<td>"+n.getAttribute('weight')+"</td></tr></table>"
+        return html_str
+
+
+########################
+##  d20 char windows
+########################
+
+class base_panel(wx.Panel):
+    def __init__(self, parent):
+        wx.Panel.__init__(self, parent, -1)
+
+        #self.build_ctrls()
+        self.Bind(wx.EVT_SIZE, self.on_size)
+
+    def on_size(self,event):
+        s = self.GetClientSizeTuple()
+        #self.splitter.SetDimensions(0,0,s[0],s[1])
+
+class outline_panel(wx.Panel):
+    def __init__(self, parent, handler, wnd, txt,):
+        wx.Panel.__init__(self, parent, -1)
+        self.panel = wnd(self,handler)
+        self.outline = wx.StaticBox(self,-1,txt)
+        self.Bind(wx.EVT_SIZE, self.on_size)
+
+    def on_size(self,event):
+        s = self.GetClientSizeTuple()
+        self.panel.SetDimensions(20,20,s[0]-40,s[1]-40)
+        self.outline.SetDimensions(5,5,s[0]-10,s[1]-10)
+
+class char_panel(wx.ScrolledWindow):
+    def __init__(self, parent, handler):
+        pname = handler.master_dom.setAttribute("name", 'TWO')
+        wx.ScrolledWindow.__init__(self, parent, -1,style=wx.VSCROLL | wx.SUNKEN_BORDER  )
+        self.height = 1200
+        self.SetScrollbars(10, 10,80, self.height/10)
+        self.main_sizer = wx.BoxSizer(wx.HORIZONTAL)
+        self.panels = {}
+        keys = handler.child_handlers.keys()
+        for k in keys:
+            self.panels[k] = handler.child_handlers[k].get_design_panel(self, [k])
+        self.sub_sizer = wx.BoxSizer(wx.VERTICAL)
+        self.sub_sizer2 = wx.BoxSizer(wx.VERTICAL)
+        self.sub_sizer.Add(self.panels['general'], 1, wx.EXPAND)
+        self.sub_sizer.Add(self.panels['abilities'], 1, wx.EXPAND)
+
+        self.sub_sizer.Add(self.panels['attacks'], 2, wx.EXPAND)
+        self.sub_sizer.Add(self.panels['ac'], 1, wx.EXPAND)
+        #self.sub_sizer.Add(self.panels['spells'], 1, wx.EXPAND)
+
+        self.sub_sizer2.Add(self.panels['classes'], 2, wx.EXPAND)
+        self.sub_sizer2.Add(self.panels['wp'], 1, wx.EXPAND)
+        self.sub_sizer2.Add(self.panels['vp'], 1, wx.EXPAND)
+        #self.sub_sizer2.Add(self.panels['pp'], 1, wx.EXPAND)
+        self.sub_sizer2.Add(self.panels['saves'], 2, wx.EXPAND)
+
+        self.sub_sizer2.Add(self.panels['feats'], 2, wx.EXPAND)
+        #self.sub_sizer2.Add(self.panels['powers'], 2, wx.EXPAND)
+        self.sub_sizer2.Add(self.panels['skills'], 3, wx.EXPAND)
+
+        self.main_sizer.Add(self.sub_sizer,   1, wx.EXPAND)
+        self.main_sizer.Add(self.sub_sizer2,   1, wx.EXPAND)
+        self.panels['abilities'].panel.char_wnd = self
+        self.SetSizer(self.main_sizer)
+        self.Bind(wx.EVT_SIZE, self.on_size)
+
+
+    def on_size(self,evt):
+        s = self.GetClientSizeTuple()
+        self.SetScrollbars(10, 10,s[0]/10, self.height/10)
+        dc = wx.ClientDC(self)
+        x = dc.DeviceToLogicalX(0)
+        y = dc.DeviceToLogicalY(0)
+        self.main_sizer.SetDimension(x,y,s[0],self.height)
+        evt.Skip()
+
+    def refresh_data(self):
+        self.panels['saves'].panel.refresh_data()
+        self.panels['skills'].panel.refresh_data()
+        self.panels['attacks'].panel.refresh_data()
+#        self.panels['powers'].panel.refresh_data()
+#        self.panels['spells'].panel.refresh_data()
+
+HOWTO_MAX = wx.NewId()
+
+class howto_panel(wx.Panel):
+    def __init__(self, parent, handler):
+        wx.Panel.__init__(self, parent, -1)
+        pname = handler.master_dom.setAttribute("name", 'How To')
+        self.sizer = wx.FlexGridSizer(2, 4, 2, 2)  # rows, cols, hgap, vgap
+        self.master_dom = handler.master_dom
+        n_list = self.master_dom._get_childNodes()
+        for n in n_list:
+            t_node = safe_get_text_node(n)
+        self.sizer.AddMany([ (wx.StaticText(self, -1, t_node._get_nodeValue()),   0, wx.ALIGN_CENTER_VERTICAL),
+                 ])
+        self.sizer.AddGrowableCol(1)
+        self.SetSizer(self.sizer)
+
+
+WP_CUR = wx.NewId()
+WP_MAX = wx.NewId()
+
+class hp_panel(wx.Panel):
+    def __init__(self, parent, handler):
+        wx.Panel.__init__(self, parent, -1)
+        pname = handler.master_dom.setAttribute("name", 'WoundPoints')
+        self.sizer = wx.FlexGridSizer(2, 4, 2, 2)  # rows, cols, hgap, vgap
+        self.master_dom = handler.master_dom
+        self.sizer.AddMany([ (wx.StaticText(self, -1, "WP Current:"),   0, wx.ALIGN_CENTER_VERTICAL),
+                 (wx.TextCtrl(self, WP_CUR, self.master_dom.getAttribute('current')),   0, wx.EXPAND),
+                 (wx.StaticText(self, -1, "WP Max:"), 0, wx.ALIGN_CENTER_VERTICAL),
+                 (wx.TextCtrl(self, WP_MAX, self.master_dom.getAttribute('max')),  0, wx.EXPAND),
+                 ])
+        self.sizer.AddGrowableCol(1)
+        self.Bind(wx.EVT_SIZE, self.on_size)
+        self.Bind(wx.EVT_TEXT, self.on_text, id=WP_MAX)
+        self.Bind(wx.EVT_TEXT, self.on_text, id=WP_CUR)
+        self.SetSizer(self.sizer)
+
+    def on_text(self,evt):
+        id = evt.GetId()
+        if id == WP_CUR:
+            self.master_dom.setAttribute('current',evt.GetString())
+        elif id == WP_MAX:
+            self.master_dom.setAttribute('max',evt.GetString())
+
+    def on_size(self,evt):
+        s = self.GetClientSizeTuple()
+        self.sizer.SetDimension(0,0,s[0],s[1])
+
+VP_CUR = wx.NewId()
+VP_MAX = wx.NewId()
+
+class vp_panel(wx.Panel):
+    def __init__(self, parent, handler):
+        wx.Panel.__init__(self, parent, -1)
+        pname = handler.master_dom.setAttribute("name", 'VitalityPoints')
+        self.sizer = wx.FlexGridSizer(2, 4, 2, 2)  # rows, cols, hgap, vgap
+        self.master_dom = handler.master_dom
+        self.sizer.AddMany([ (wx.StaticText(self, -1, "VP Current:"),   0, wx.ALIGN_CENTER_VERTICAL),
+                 (wx.TextCtrl(self, VP_CUR, self.master_dom.getAttribute('current')),   0, wx.EXPAND),
+                 (wx.StaticText(self, -1, "VP Max:"), 0, wx.ALIGN_CENTER_VERTICAL),
+                 (wx.TextCtrl(self, VP_MAX, self.master_dom.getAttribute('max')),  0, wx.EXPAND),
+                 ])
+        self.sizer.AddGrowableCol(1)
+        self.Bind(wx.EVT_SIZE, self.on_size)
+        self.Bind(wx.EVT_TEXT, self.on_text, id=VP_MAX)
+        self.Bind(wx.EVT_TEXT, self.on_text, id=VP_CUR)
+        self.SetSizer(self.sizer)
+
+    def on_text(self,evt):
+        id = evt.GetId()
+        if id == VP_CUR:
+            self.master_dom.setAttribute('current',evt.GetString())
+        elif id == VP_MAX:
+            self.master_dom.setAttribute('max',evt.GetString())
+
+    def on_size(self,evt):
+        s = self.GetClientSizeTuple()
+        self.sizer.SetDimension(0,0,s[0],s[1])
+
+#PP_CUR = wx.NewId()
+#PP_MAX = wx.NewId()
+#PP_FRE = wx.NewId()
+#PP_MFRE = wx.NewId()
+
+#class pp_panel(wx.Panel):
+#    def __init__(self, parent, handler):
+#        wx.Panel.__init__(self, parent, -1)
+#        pname = handler.master_dom.setAttribute("name", 'PowerPoints')
+#        self.sizer = wx.FlexGridSizer(2, 4, 2, 2)  # rows, cols, hgap, vgap
+#        self.master_dom = handler.master_dom
+#
+#        self.sizer.AddMany([ (wx.StaticText(self, -1, "PP Current:"),   0, wx.ALIGN_CENTER_VERTICAL),
+#                 (wx.TextCtrl(self, PP_CUR, self.master_dom.getAttribute('current1')),   0, wx.EXPAND),
+#                 (wx.StaticText(self, -1, "PP Max:"), 0, wx.ALIGN_CENTER_VERTICAL),
+#                 (wx.TextCtrl(self, PP_MAX, self.master_dom.getAttribute('max1')),  0, wx.EXPAND),
+#                 (wx.StaticText(self, -1, "Current Free Talants per day:"), 0, wx.ALIGN_CENTER_VERTICAL),
+#                 (wx.TextCtrl(self, PP_FRE, self.master_dom.getAttribute('free')),  0, wx.EXPAND),
+#                 (wx.StaticText(self, -1, "Max Free Talants per day:"), 0, wx.ALIGN_CENTER_VERTICAL),
+#                 (wx.TextCtrl(self, PP_MFRE, self.master_dom.getAttribute('maxfree')),  0, wx.EXPAND),
+#                 ])
+#        self.sizer.AddGrowableCol(1)
+#        self.Bind(wx.EVT_SIZE, self.on_size)
+#        self.Bind(wx.EVT_TEXT, self.on_text, id=PP_MAX)
+#        self.Bind(wx.EVT_TEXT, self.on_text, id=PP_CUR)
+#        self.Bind(wx.EVT_TEXT, self.on_text, id=PP_FRE)
+#        self.Bind(wx.EVT_TEXT, self.on_text, id=PP_MFRE)
+#
+#    def on_text(self,evt):
+#        id = evt.GetId()
+#        if id == PP_CUR:
+#            self.master_dom.setAttribute('current1',evt.GetString())
+#        elif id == PP_MAX:
+#            self.master_dom.setAttribute('max1',evt.GetString())
+#        elif id == PP_FRE:
+#            self.master_dom.setAttribute('free',evt.GetString())
+#        elif id == PP_MFRE:
+#            self.master_dom.setAttribute('maxfree',evt.GetString())
+#
+#    def on_size(self,evt):
+#        s = self.GetClientSizeTuple()
+#        self.sizer.SetDimension(0,0,s[0],s[1])
+
+
+class gen_grid(wx.grid.Grid):
+    """grid for gen info"""
+    def __init__(self, parent, handler):
+        pname = handler.master_dom.setAttribute("name", 'General')
+        wx.grid.Grid.__init__(self, parent, -1, style=wx.SUNKEN_BORDER | wx.WANTS_CHARS)
+        self.Bind(wx.EVT_SIZE, self.on_size)
+        self.Bind(wx.grid.EVT_GRID_CELL_CHANGE, self.on_cell_change)
+        self.handler = handler
+        n_list = handler.master_dom._get_childNodes()
+        self.CreateGrid(len(n_list),2)
+        self.SetRowLabelSize(0)
+        self.SetColLabelSize(0)
+        self.n_list = n_list
+        i = 0
+        for i in range(len(n_list)):
+            self.refresh_row(i)
+
+    def on_cell_change(self,evt):
+        row = evt.GetRow()
+        col = evt.GetCol()
+        value = self.GetCellValue(row,col)
+        t_node = self.n_list[row]._get_firstChild()
+        t_node._set_nodeValue(value)
+        if row==0: self.handler.on_name_change(value)
+
+    def refresh_row(self,rowi):
+        t_node = safe_get_text_node(self.n_list[rowi])
+        self.SetCellValue(rowi,0,self.n_list[rowi]._get_tagName())
+        self.SetReadOnly(rowi,0)
+        self.SetCellValue(rowi,1,t_node._get_nodeValue())
+
+    def on_size(self,evt):
+        (w,h) = self.GetClientSizeTuple()
+        cols = self.GetNumberCols()
+        col_w = w/(cols)
+        for i in range(0,cols):
+            self.SetColSize(i,col_w)
+        evt.Skip()
+        self.Refresh()
+
+class inventory_grid(wx.grid.Grid):
+    """grid for gen info"""
+    def __init__(self, parent, handler):
+        pname = handler.master_dom.setAttribute("name", 'Money and Inventory')
+        wx.grid.Grid.__init__(self, parent, -1, style=wx.SUNKEN_BORDER | wx.WANTS_CHARS)
+        self.Bind(wx.EVT_SIZE, self.on_size)
+        self.Bind(wx.grid.EVT_GRID_CELL_CHANGE, self.on_cell_change)
+        self.handler = handler
+        n_list = handler.master_dom._get_childNodes()
+        self.CreateGrid(len(n_list),2)
+        self.SetRowLabelSize(0)
+        self.SetColLabelSize(0)
+        self.n_list = n_list
+        i = 0
+        for i in range(len(n_list)):
+            self.refresh_row(i)
+
+    def on_cell_change(self,evt):
+        row = evt.GetRow()
+        col = evt.GetCol()
+        value = self.GetCellValue(row,col)
+        t_node = self.n_list[row]._get_firstChild()
+        t_node._set_nodeValue(value)
+        if row==0: self.handler.on_name_change(value)
+
+    def refresh_row(self,rowi):
+        t_node = safe_get_text_node(self.n_list[rowi])
+        self.SetCellValue(rowi,0,self.n_list[rowi]._get_tagName())
+        self.SetReadOnly(rowi,0)
+        self.SetCellValue(rowi,1,t_node._get_nodeValue())
+
+    def on_size(self,evt):
+        (w,h) = self.GetClientSizeTuple()
+        cols = self.GetNumberCols()
+        col_w = w/(cols)
+        for i in range(0,cols):
+            self.SetColSize(i,col_w)
+        evt.Skip()
+        self.Refresh()
+
+class abil_grid(wx.grid.Grid):
+    """grid for abilities"""
+    def __init__(self, parent, handler):
+        pname = handler.master_dom.setAttribute("name", 'Stats')
+        wx.grid.Grid.__init__(self, parent, -1, style=wx.SUNKEN_BORDER | wx.WANTS_CHARS)
+        self.Bind(wx.EVT_SIZE, self.on_size)
+        self.Bind(wx.grid.EVT_GRID_CELL_CHANGE, self.on_cell_change)
+        self.handler = handler
+        stats = handler.master_dom.getElementsByTagName('stat')
+        self.CreateGrid(len(stats),3)
+        self.SetRowLabelSize(0)
+        col_names = ['Ability','Score','Modifier']
+        for i in range(len(col_names)):
+            self.SetColLabelValue(i,col_names[i])
+        self.stats = stats
+        i = 0
+        for i in range(len(stats)):
+            self.refresh_row(i)
+        self.char_wnd = None
+
+    def on_cell_change(self,evt):
+        row = evt.GetRow()
+        col = evt.GetCol()
+        value = self.GetCellValue(row,col)
+        try:
+            int(value)
+            self.stats[row].setAttribute('base',value)
+            self.refresh_row(row)
+        except:
+            self.SetCellValue(row,col,"0")
+        if self.char_wnd:
+            self.char_wnd.refresh_data()
+
+    def refresh_row(self,rowi):
+        s = self.stats[rowi]
+        name = s.getAttribute('name')
+        abbr = s.getAttribute('abbr')
+        self.SetCellValue(rowi,0,name)
+        self.SetReadOnly(rowi,0)
+        self.SetCellValue(rowi,1,s.getAttribute('base'))
+        self.SetCellValue(rowi,2,str(self.handler.get_mod(abbr)))
+        self.SetReadOnly(rowi,2)
+
+    def on_size(self,evt):
+        (w,h) = self.GetClientSizeTuple()
+        cols = self.GetNumberCols()
+        col_w = w/(cols+2)
+        self.SetColSize(0,col_w*3)
+        for i in range(1,cols):
+            self.SetColSize(i,col_w)
+        evt.Skip()
+        self.Refresh()
+
+    def refresh_data(self):
+        for r in range(self.GetNumberRows()-1):
+            self.refresh_row(r)
+
+
+class save_grid(wx.grid.Grid):
+    """grid for saves"""
+    def __init__(self, parent, handler):
+        pname = handler.master_dom.setAttribute("name", 'Saves')
+        wx.grid.Grid.__init__(self, parent, -1, style=wx.SUNKEN_BORDER | wx.WANTS_CHARS)
+        self.Bind(wx.EVT_SIZE, self.on_size)
+        self.Bind(wx.grid.EVT_GRID_CELL_CHANGE, self.on_cell_change)
+        self.handler = handler
+        saves = handler.master_dom.getElementsByTagName('save')
+        self.stats = handler.char_hander.child_handlers['abilities']
+        self.CreateGrid(len(saves),7)
+        self.SetRowLabelSize(0)
+        col_names = ['Save','Key','base','Abil','Magic','Misc','Total']
+        for i in range(len(col_names)):
+            self.SetColLabelValue(i,col_names[i])
+        self.saves = saves
+        i = 0
+        for i in range(len(saves)):
+            self.refresh_row(i)
+
+    def on_cell_change(self,evt):
+        row = evt.GetRow()
+        col = evt.GetCol()
+        value = self.GetCellValue(row,col)
+        try:
+            int(value)
+            if col == 2:
+                self.saves[row].setAttribute('base',value)
+            elif col ==4:
+                self.saves[row].setAttribute('magmod',value)
+            elif col ==4:
+                self.saves[row].setAttribute('miscmod',value)
+            self.refresh_row(row)
+        except:
+            self.SetCellValue(row,col,"0")
+
+    def refresh_row(self,rowi):
+        s = self.saves[rowi]
+        name = s.getAttribute('name')
+        self.SetCellValue(rowi,0,name)
+        self.SetReadOnly(rowi,0)
+        stat = s.getAttribute('stat')
+        self.SetCellValue(rowi,1,stat)
+        self.SetReadOnly(rowi,1)
+        self.SetCellValue(rowi,2,s.getAttribute('base'))
+        self.SetCellValue(rowi,3,str(self.stats.get_mod(stat)))
+        self.SetReadOnly(rowi,3)
+        self.SetCellValue(rowi,4,s.getAttribute('magmod'))
+        self.SetCellValue(rowi,5,s.getAttribute('miscmod'))
+        mod = str(self.handler.get_mod(name))
+        self.SetCellValue(rowi,6,mod)
+        self.SetReadOnly(rowi,6)
+
+    def on_size(self,evt):
+        (w,h) = self.GetClientSizeTuple()
+        cols = self.GetNumberCols()
+        col_w = w/(cols+2)
+        self.SetColSize(0,col_w*3)
+        for i in range(1,cols):
+            self.SetColSize(i,col_w)
+        evt.Skip()
+        self.Refresh()
+
+    def refresh_data(self):
+        for r in range(self.GetNumberRows()):
+            self.refresh_row(r)
+
+
+class skill_grid(wx.grid.Grid):
+    """ panel for skills """
+    def __init__(self, parent, handler):
+        pname = handler.master_dom.setAttribute("name", 'Skills')
+        wx.grid.Grid.__init__(self, parent, -1, style=wx.SUNKEN_BORDER | wx.WANTS_CHARS)
+        self.Bind(wx.EVT_SIZE, self.on_size)
+        self.Bind(wx.grid.EVT_GRID_CELL_CHANGE, self.on_cell_change)
+        self.handler = handler
+        skills = handler.master_dom.getElementsByTagName('skill')
+        self.stats = handler.char_hander.child_handlers['abilities']
+        self.CreateGrid(len(skills),7)
+        self.SetRowLabelSize(0)
+        col_names = ['Skill','Key','Rank','Abil','Misc','Total']
+        for i in range(len(col_names)):
+            self.SetColLabelValue(i,col_names[i])
+        rowi = 0
+        self.skills = skills
+        for i in range(len(skills)):
+            self.refresh_row(i)
+
+    def on_cell_change(self,evt):
+        row = evt.GetRow()
+        col = evt.GetCol()
+        value = self.GetCellValue(row,col)
+        #print value
+        try:
+            int(value)
+            if col == 3:
+                self.skills[row].setAttribute('rank',value)
+            elif col ==5:
+                self.skills[row].setAttribute('misc',value)
+            elif col == 1:
+                self.skills[row].setAttribute('untrained',value)
+            self.refresh_row(row)
+        except:
+            self.SetCellValue(row,col,"0")
+
+    def refresh_row(self,rowi):
+        s = self.skills[rowi]
+        name = s.getAttribute('name')
+        self.SetCellValue(rowi,0,name)
+        self.SetReadOnly(rowi,0)
+        self.SetCellValue(rowi,1,s.getAttribute('untrained'))
+        stat = s.getAttribute('stat')
+        self.SetCellValue(rowi,2,stat)
+        self.SetReadOnly(rowi,2)
+        self.SetCellValue(rowi,3,s.getAttribute('rank'))
+        self.SetCellValue(rowi,4,str(self.stats.get_mod(stat)))
+        self.SetReadOnly(rowi,4)
+        self.SetCellValue(rowi,5,s.getAttribute('misc'))
+        mod = str(self.handler.get_mod(name))
+        self.SetCellValue(rowi,6,mod)
+        self.SetReadOnly(rowi,6)
+
+    def on_size(self,evt):
+        (w,h) = self.GetClientSizeTuple()
+        cols = self.GetNumberCols()
+        col_w = w/(cols+2)
+        self.SetColSize(0,col_w*3)
+        for i in range(1,cols):
+            self.SetColSize(i,col_w)
+        evt.Skip()
+        self.Refresh()
+
+    def refresh_data(self):
+        for r in range(self.GetNumberRows()):
+            self.refresh_row(r)
+
+
+
+class feat_panel(wx.Panel):
+    def __init__(self, parent, handler):
+        pname = handler.master_dom.setAttribute("name", 'Feats')
+        wx.Panel.__init__(self, parent, -1)
+        self.grid =wx.grid.Grid(self, -1, style=wx.SUNKEN_BORDER | wx.WANTS_CHARS)
+        sizer = wx.BoxSizer(wx.HORIZONTAL)
+        remove_btn = wx.Button(self, wx.ID_ANY, "Remove Feat")
+        add_btn = wx.Button(self, wx.ID_ANY, "Add Feat")
+        sizer.Add(remove_btn, 1, wx.EXPAND)
+        sizer.Add(wx.Size(10,10))
+        sizer.Add(add_btn, 1, wx.EXPAND)
+        self.sizer = sizer
+        self.SetSizer(self.sizer)
+        self.Bind(wx.EVT_SIZE, self.on_size)
+        self.Bind(wx.EVT_BUTTON, self.on_remove, remove_btn)
+        self.Bind(wx.EVT_BUTTON, self.on_add, add_btn)
+
+        n_list = handler.master_dom._get_childNodes()
+        self.n_list = n_list
+        self.master_dom = handler.master_dom
+        self.grid.CreateGrid(len(n_list),2,1)
+        self.grid.SetRowLabelSize(0)
+        self.grid.SetColLabelValue(0,"Feat")
+        self.grid.SetColLabelValue(1,"Type")
+        for i in range(len(n_list)):
+            self.refresh_row(i)
+        self.temp_dom = None
+
+    def refresh_row(self,i):
+        feat = self.n_list[i]
+        name = feat.getAttribute('name')
+        type = feat.getAttribute('type')
+        self.grid.SetCellValue(i,0,name)
+        self.grid.SetReadOnly(i,0)
+        self.grid.SetCellValue(i,1,type)
+        self.grid.SetReadOnly(i,1)
+
+    def on_remove(self,evt):
+        rows = self.grid.GetNumberRows()
+        for i in range(rows):
+            if self.grid.IsInSelection(i,0):
+                self.grid.DeleteRows(i)
+                self.master_dom.removeChild(self.n_list[i])
+
+    def on_add(self,evt):
+        if not self.temp_dom:
+            tmp = open(orpg.dirpath.dir_struct["SWd20"]+"d20feats.xml","r")
+            xml_dom = parseXml_with_dlg(self,tmp.read())
+            xml_dom = xml_dom._get_firstChild()
+            tmp.close()
+            self.temp_dom = xml_dom
+        f_list = self.temp_dom.getElementsByTagName('feat')
+        opts = []
+        for f in f_list:
+            opts.append(f.getAttribute('name'))
+        dlg = wx.SingleChoiceDialog(self,'Choose Feat','Feats',opts)
+        if dlg.ShowModal() == wx.ID_OK:
+            i = dlg.GetSelection()
+            new_node = self.master_dom.appendChild(f_list[i].cloneNode(False))
+            self.grid.AppendRows(1)
+            self.refresh_row(self.grid.GetNumberRows()-1)
+        dlg.Destroy()
+
+
+    def on_size(self,event):
+        s = self.GetClientSizeTuple()
+        self.grid.SetDimensions(0,0,s[0],s[1]-25)
+        self.sizer.SetDimension(0,s[1]-25,s[0],25)
+        (w,h) = self.grid.GetClientSizeTuple()
+        cols = self.grid.GetNumberCols()
+        col_w = w/(cols)
+        for i in range(0,cols):
+            self.grid.SetColSize(i,col_w)
+
+class attack_grid(wx.grid.Grid):
+    """grid for attacks"""
+    def __init__(self, parent, handler):
+        pname = handler.master_dom.setAttribute("name", 'Melee')
+        wx.grid.Grid.__init__(self, parent, -1, style=wx.SUNKEN_BORDER | wx.WANTS_CHARS)
+        self.parent = parent
+        self.handler = handler
+        self.rows = (self.handler.melee,self.handler.ranged)
+        self.CreateGrid(2,10)
+        self.SetRowLabelSize(0)
+        col_names = ['Type','base','base 2','base 3','base 4','base 5','base 6','abil','misc','Total']
+        for i in range(len(col_names)):
+            self.SetColLabelValue(i,col_names[i])
+        self.SetCellValue(0,0,"Melee")
+        self.SetCellValue(1,0,"Ranged")
+        self.refresh_data()
+        self.Bind(wx.EVT_SIZE, self.on_size)
+        self.Bind(wx.grid.EVT_GRID_CELL_CHANGE, self.on_cell_change)
+
+    def on_cell_change(self,evt):
+        row = evt.GetRow()
+        col = evt.GetCol()
+        value = self.GetCellValue(row,col)
+        try:
+            int(value)
+            if col==1:
+                self.rows[row].setAttribute('base',value)
+            elif col==2:
+                self.rows[row].setAttribute('second',value)
+            elif col==3:
+                self.rows[row].setAttribute('third',value)
+            elif col==4:
+                self.rows[row].setAttribute('forth',value)
+            elif col==5:
+                self.rows[row].setAttribute('fifth',value)
+            elif col==6:
+                self.rows[row].setAttribute('sixth',value)
+            elif col==8:
+                self.rows[row].setAttribute('misc',value)
+            self.parent.refresh_data()
+        except:
+            self.SetCellValue(row,col,"0")
+
+    def refresh_data(self):
+        melee = self.handler.get_attack_data('m')
+        ranged = self.handler.get_attack_data('r')
+        for i in range(0,7):
+            self.SetCellValue(0,i+1,str(melee[i]))
+            self.SetCellValue(1,i+1,str(ranged[i]))
+        self.SetCellValue(0,9,str(melee[0]+melee[6]+melee[7]))
+        self.SetCellValue(1,9,str(ranged[0]+ranged[6]+ranged[7]))
+        self.SetReadOnly(0,0)
+        self.SetReadOnly(1,0)
+        self.SetReadOnly(0,7)
+        self.SetReadOnly(1,7)
+        self.SetReadOnly(0,9)
+        self.SetReadOnly(1,9)
+
+
+    def on_size(self,evt):
+        (w,h) = self.GetClientSizeTuple()
+        cols = self.GetNumberCols()
+        col_w = w/(cols+1)
+        self.SetColSize(0,col_w*2)
+        for i in range(1,cols):
+            self.SetColSize(i,col_w)
+        evt.Skip()
+        self.Refresh()
+
+class weapon_panel(wx.Panel):
+    def __init__(self, parent, handler):
+        pname = handler.master_dom.setAttribute("name", 'Weapons')
+        wx.Panel.__init__(self, parent, -1)
+        self.grid =wx.grid.Grid(self, -1, style=wx.SUNKEN_BORDER | wx.WANTS_CHARS)
+        sizer = wx.BoxSizer(wx.HORIZONTAL)
+        remove_btn = wx.Button(self, 10, "Remove Weapon")
+        add_btn = wx.Button(self, 20, "Add Weapon")
+        sizer.Add(remove_btn, 1, wx.EXPAND)
+        sizer.Add(wx.Size(10,10))
+        sizer.Add(add_btn, 1, wx.EXPAND)
+        self.sizer = sizer
+        self.SetSizer(self.sizer)
+        self.Bind(wx.EVT_SIZE, self.on_size)
+        self.Bind(wx.EVT_BUTTON, self.on_remove, remove_btn)
+        self.Bind(wx.EVT_BUTTON, self.on_add, add_btn)
+        self.grid.Bind(wx.grid.EVT_GRID_CELL_CHANGE, self.on_cell_change)
+        n_list = handler.master_dom.getElementsByTagName('weapon')
+        self.n_list = n_list
+        self.master_dom = handler.master_dom
+        self.handler = handler
+        self.grid.CreateGrid(len(n_list),9,1)
+        self.grid.SetRowLabelSize(0)
+        col_names = ['Name','damage','mod','critical','type','weight','range','size','Total']
+        for i in range(len(col_names)):
+            self.grid.SetColLabelValue(i,col_names[i])
+        self.refresh_data()
+        self.temp_dom = None
+
+    def on_cell_change(self,evt):
+        row = evt.GetRow()
+        col = evt.GetCol()
+        value = self.grid.GetCellValue(row,col)
+        if col == 0:
+            self.n_list[row].setAttribute('name',value)
+        elif col == 2:
+            try:
+                int(value)
+                self.n_list[row].setAttribute('mod',value)
+                self.refresh_row(row)
+            except:
+                self.grid.SetCellValue(row,col,"1")
+        else:
+            self.n_list[row].setAttribute(self.grid.GetColLabelValue(col),value)
+
+    def refresh_row(self,i):
+        n = self.n_list[i]
+        name = n.getAttribute('name')
+        mod = n.getAttribute('mod')
+        ran = n.getAttribute('range')
+        total = str(int(mod) + self.handler.get_mod(ran))
+        self.grid.SetCellValue(i,0,name)
+        self.grid.SetCellValue(i,1,n.getAttribute('damage'))
+        self.grid.SetCellValue(i,2,mod)
+        self.grid.SetCellValue(i,3,n.getAttribute('critical'))
+        self.grid.SetCellValue(i,4,n.getAttribute('type'))
+        self.grid.SetCellValue(i,5,n.getAttribute('weight'))
+        self.grid.SetCellValue(i,6,ran)
+        self.grid.SetCellValue(i,7,n.getAttribute('size') )
+        self.grid.SetCellValue(i,8,total)
+        self.grid.SetReadOnly(i,8)
+
+    def on_remove(self,evt):
+        rows = self.grid.GetNumberRows()
+        for i in range(rows):
+            if self.grid.IsInSelection(i,0):
+                self.grid.DeleteRows(i)
+                self.master_dom.removeChild(self.n_list[i])
+                self.n_list = self.master_dom.getElementsByTagName('weapon')
+                self.handler.refresh_weapons()
+
+    def on_add(self,evt):
+        if not self.temp_dom:
+            tmp = open(orpg.dirpath.dir_struct["SWd20"]+"d20weapons.xml","r")
+            xml_dom = parseXml_with_dlg(self,tmp.read())
+            xml_dom = xml_dom._get_firstChild()
+            tmp.close()
+            self.temp_dom = xml_dom
+        f_list = self.temp_dom.getElementsByTagName('weapon')
+        opts = []
+        for f in f_list:
+            opts.append(f.getAttribute('name'))
+        dlg = wx.SingleChoiceDialog(self,'Choose Weapon','Weapon List',opts)
+        if dlg.ShowModal() == wx.ID_OK:
+            i = dlg.GetSelection()
+            new_node = self.master_dom.appendChild(f_list[i].cloneNode(False))
+            self.grid.AppendRows(1)
+            self.n_list = self.master_dom.getElementsByTagName('weapon')
+            self.refresh_row(self.grid.GetNumberRows()-1)
+            self.handler.refresh_weapons()
+        dlg.Destroy()
+
+    def on_size(self,event):
+        s = self.GetClientSizeTuple()
+        self.grid.SetDimensions(0,0,s[0],s[1]-25)
+        self.sizer.SetDimension(0,s[1]-25,s[0],25)
+        (w,h) = self.grid.GetClientSizeTuple()
+        cols = self.grid.GetNumberCols()
+        col_w = w/(cols+1)
+        self.grid.SetColSize(0,col_w*2)
+        for i in range(1,cols):
+            self.grid.SetColSize(i,col_w)
+
+    def refresh_data(self):
+        for i in range(len(self.n_list)):
+            self.refresh_row(i)
+
+
+class attack_panel(wx.Panel):
+    def __init__(self, parent, handler):
+        pname = handler.master_dom.setAttribute("name", 'Melee')
+        wx.Panel.__init__(self, parent, -1)
+
+        self.a_grid = attack_grid(self, handler)
+        self.w_panel = weapon_panel(self, handler)
+        self.sizer = wx.BoxSizer(wx.VERTICAL)
+        self.sizer.Add(self.a_grid, 1, wx.EXPAND)
+        self.sizer.Add(self.w_panel, 2, wx.EXPAND)
+        self.SetSizer(self.sizer)
+        self.Bind(wx.EVT_SIZE, self.on_size)
+
+    def on_size(self,event):
+        s = self.GetClientSizeTuple()
+        self.sizer.SetDimension(0,0,s[0],s[1])
+
+    def refresh_data(self):
+        self.w_panel.refresh_data()
+        self.a_grid.refresh_data()
+
+
+class ac_panel(wx.Panel):
+    def __init__(self, parent, handler):
+        pname = handler.master_dom.setAttribute("name", 'Armor')
+        wx.Panel.__init__(self, parent, -1)
+        self.grid =wx.grid.Grid(self, -1, style=wx.SUNKEN_BORDER | wx.WANTS_CHARS)
+        sizer = wx.BoxSizer(wx.HORIZONTAL)
+        remove_btn = wx.Button(self, 10, "Remove Armor")
+        add_btn = wx.Button(self, 20, "Add Armor")
+        sizer.Add(remove_btn, 1, wx.EXPAND)
+        sizer.Add(wx.Size(10,10))
+        sizer.Add(add_btn, 1, wx.EXPAND)
+        self.sizer = sizer
+        self.SetSizer(self.sizer)
+        self.Bind(wx.EVT_SIZE, self.on_size)
+        self.Bind(wx.EVT_BUTTON, self.on_remove, remove_btn)
+        self.Bind(wx.EVT_BUTTON, self.on_add, add_btn)
+        self.grid.Bind(wx.grid.EVT_GRID_CELL_CHANGE, self.on_cell_change)
+        self.master_dom = handler.master_dom
+        n_list = handler.master_dom._get_childNodes()
+        self.n_list = n_list
+        col_names = ['Armor','DR','Max Dex','Check Penalty','Weight','Speed (10)','Speed (6)','type']
+        self.grid.CreateGrid(len(n_list),len(col_names),1)
+        self.grid.SetRowLabelSize(0)
+        for i in range(len(col_names)):
+            self.grid.SetColLabelValue(i,col_names[i])
+        self.atts =['name','bonus','maxdex','checkpenalty','weight','speed','speed6','type']
+        for i in range(len(n_list)):
+            self.refresh_row(i)
+        self.temp_dom = None
+
+
+    def on_cell_change(self,evt):
+        row = evt.GetRow()
+        col = evt.GetCol()
+        value = self.grid.GetCellValue(row,col)
+        if col >= 1 and col <= 5:
+            try:
+                int(value)
+                self.n_list[row].setAttribute(self.atts[col],value)
+            except:
+                self.grid.SetCellValue(row,col,"0")
+        else:
+            self.n_list[row].setAttribute(self.atts[col],value)
+
+    def refresh_row(self,i):
+        n = self.n_list[i]
+        for y in range(len(self.atts)):
+            self.grid.SetCellValue(i,y,n.getAttribute(self.atts[y]))
+
+    def on_remove(self,evt):
+        rows = self.grid.GetNumberRows()
+        for i in range(rows):
+            if self.grid.IsInSelection(i,0):
+                self.grid.DeleteRows(i)
+                self.master_dom.removeChild(self.n_list[i])
+
+    def on_add(self,evt):
+        if not self.temp_dom:
+            tmp = open(orpg.dirpath.dir_struct["SWd20"]+"d20armor.xml","r")
+            xml_dom = parseXml_with_dlg(self,tmp.read())
+            xml_dom = xml_dom._get_firstChild()
+            tmp.close()
+            self.temp_dom = xml_dom
+        f_list = self.temp_dom.getElementsByTagName('armor')
+        opts = []
+        for f in f_list:
+            opts.append(f.getAttribute('name'))
+        dlg = wx.SingleChoiceDialog(self,'Choose Armor:','Armor List',opts)
+        if dlg.ShowModal() == wx.ID_OK:
+            i = dlg.GetSelection()
+            new_node = self.master_dom.appendChild(f_list[i].cloneNode(False))
+            self.grid.AppendRows(1)
+            self.refresh_row(self.grid.GetNumberRows()-1)
+        dlg.Destroy()
+
+    def on_size(self,event):
+        s = self.GetClientSizeTuple()
+        self.grid.SetDimensions(0,0,s[0],s[1]-25)
+        self.sizer.SetDimension(0,s[1]-25,s[0],25)
+        (w,h) = self.grid.GetClientSizeTuple()
+        cols = self.grid.GetNumberCols()
+        col_w = w/(cols+2)
+        self.grid.SetColSize(0,col_w*3)
+        for i in range(1,cols):
+            self.grid.SetColSize(i,col_w)
+
+
+class class_panel(wx.Panel):
+    def __init__(self, parent, handler):
+        pname = handler.master_dom.setAttribute("name", 'Class')
+        wx.Panel.__init__(self, parent, -1)
+        self.grid =wx.grid.Grid(self, -1, style=wx.SUNKEN_BORDER | wx.WANTS_CHARS)
+        sizer = wx.BoxSizer(wx.HORIZONTAL)
+        remove_btn = wx.Button(self, wx.ID_ANY, "Remove Class")
+        add_btn = wx.Button(self, wx.ID_ANY, "Add Class")
+        sizer.Add(remove_btn, 1, wx.EXPAND)
+        sizer.Add(wx.Size(10,10))
+        sizer.Add(add_btn, 1, wx.EXPAND)
+        self.sizer = sizer
+        self.SetSizer(self.sizer)
+        self.Bind(wx.EVT_SIZE, self.on_size)
+        self.Bind(wx.EVT_BUTTON, self.on_remove, remove_btn)
+        self.Bind(wx.EVT_BUTTON, self.on_add, add_btn)
+        self.grid.Bind(wx.grid.EVT_GRID_CELL_CHANGE, self.on_cell_change)
+
+        n_list = handler.master_dom._get_childNodes()
+        self.n_list = n_list
+        self.master_dom = handler.master_dom
+        self.grid.CreateGrid(len(n_list),2,1)
+        self.grid.SetRowLabelSize(0)
+        self.grid.SetColLabelValue(0,"Class")
+        self.grid.SetColLabelValue(1,"Level")
+        for i in range(len(n_list)):
+            self.refresh_row(i)
+        self.temp_dom = None
+
+    def on_cell_change(self,evt):
+        row = evt.GetRow()
+        col = evt.GetCol()
+        value = self.grid.GetCellValue(row,col)
+        try:
+            int(value)
+            self.n_list[row].setAttribute('level',value)
+        except:
+            self.grid.SetCellValue(row,col,"1")
+
+
+    def refresh_row(self,i):
+        n = self.n_list[i]
+        name = n.getAttribute('name')
+        level = n.getAttribute('level')
+        self.grid.SetCellValue(i,0,name)
+        self.grid.SetReadOnly(i,0)
+        self.grid.SetCellValue(i,1,level)
+        #self.grid.SetReadOnly(i,1)
+
+    def on_remove(self,evt):
+        rows = self.grid.GetNumberRows()
+        for i in range(rows):
+            if self.grid.IsInSelection(i,0):
+                self.grid.DeleteRows(i)
+                self.master_dom.removeChild(self.n_list[i])
+
+    def on_add(self,evt):
+        if not self.temp_dom:
+            tmp = open(orpg.dirpath.dir_struct["SWd20"]+"SWd20classes.xml","r")
+            xml_dom = parseXml_with_dlg(self,tmp.read())
+            xml_dom = xml_dom._get_firstChild()
+            tmp.close()
+            self.temp_dom = xml_dom
+        f_list = self.temp_dom.getElementsByTagName('class')
+        opts = []
+        for f in f_list:
+            opts.append(f.getAttribute('name'))
+        dlg = wx.SingleChoiceDialog(self,'Choose Class','Classes',opts)
+        if dlg.ShowModal() == wx.ID_OK:
+            i = dlg.GetSelection()
+            new_node = self.master_dom.appendChild(f_list[i].cloneNode(False))
+            self.grid.AppendRows(1)
+            self.refresh_row(self.grid.GetNumberRows()-1)
+        dlg.Destroy()
+
+
+    def on_size(self,event):
+        s = self.GetClientSizeTuple()
+        self.grid.SetDimensions(0,0,s[0],s[1]-25)
+        self.sizer.SetDimension(0,s[1]-25,s[0],25)
+        (w,h) = self.grid.GetClientSizeTuple()
+        cols = self.grid.GetNumberCols()
+        col_w = w/(cols)
+        for i in range(0,cols):
+            self.grid.SetColSize(i,col_w)
--- a/orpg/gametree/nodehandlers/core.py	Sat Aug 08 00:35:09 2009 -0500
+++ b/orpg/gametree/nodehandlers/core.py	Thu Aug 13 13:14:10 2009 -0500
@@ -272,8 +272,9 @@
     def on_save(self,evt):
         f = wx.FileDialog(self.tree,"Select a file", orpg.dirpath.dir_struct["user"],"","XML files (*.xml)|*.xml",wx.SAVE)
         if f.ShowModal() == wx.ID_OK:
-            type = f.GetFilterIndex()
-            file = open(f.GetPath(),"w")
+            type = f.GetFilterIndex()
+            if f.GetPath()[:len(f.GetPath())-4] != '.xml': file = open(f.GetPath()+'.xml',"w")
+            else: file = open(f.GetPath(),"w")
             file.write(self.toxml(1))
             file.close()
         f.Destroy()
--- a/orpg/gametree/nodehandlers/dnd35.py	Sat Aug 08 00:35:09 2009 -0500
+++ b/orpg/gametree/nodehandlers/dnd35.py	Thu Aug 13 13:14:10 2009 -0500
@@ -215,7 +215,7 @@
         t_node._set_nodeValue(value)
         if row==0:
             self.handler.on_name_change(value)
-        self.AutoSizeColumn(1)
+        #self.AutoSizeColumn(1)
 
     def refresh_row(self,rowi):
         t_node = safe_get_text_node(self.n_list[rowi])
--- a/orpg/gametree/nodehandlers/dnd3e.py	Sat Aug 08 00:35:09 2009 -0500
+++ b/orpg/gametree/nodehandlers/dnd3e.py	Thu Aug 13 13:14:10 2009 -0500
@@ -459,7 +459,7 @@
         t_node._set_nodeValue(value)
         if row==0:
             self.handler.on_name_change(value)
-        self.AutoSizeColumn(1)
+        #self.AutoSizeColumn(1)
 
     def refresh_row(self,rowi):
         t_node = safe_get_text_node(self.n_list[rowi])
--- a/orpg/main.py	Sat Aug 08 00:35:09 2009 -0500
+++ b/orpg/main.py	Thu Aug 13 13:14:10 2009 -0500
@@ -408,10 +408,10 @@
         menuid = event.GetId()
         name = self.mainwindows[menuid]
         if name == 'Alias Lib':
-            if self.aliaslib.IsShown() == True: self.aliaslib.Hide()
+            if self.aliaslib.IsShown(): self.aliaslib.Hide()
             else: self.aliaslib.Show()
         else:
-            if self._mgr.GetPane(name).IsShown() == True: self._mgr.GetPane(name).Hide()
+            if self._mgr.GetPane(name).IsShown(): self._mgr.GetPane(name).Hide()
             else: self._mgr.GetPane(name).Show()
             self._mgr.Update()
         self.log.log("Exit orpgFrame->OnMB_WindowsMenu(self, event)", ORPG_DEBUG)
@@ -620,13 +620,13 @@
         txt = temp_file.read()
         xml_dom = self.xml.parseXml(txt)._get_documentElement()
         temp_file.close()
+        self.windowsmenu = wx.Menu()
+        self.mainwindows = {}
 
         #Plugins Window
         self.pluginsFrame = pluginUI.PluginFrame(self)
         open_rpg.add_component("plugins", self.get_activeplugins())
         open_rpg.add_component("startplugs", self.get_startplugins())
-        self.windowsmenu = wx.Menu()
-        self.mainwindows = {}
         self.log.log("Menu Created", ORPG_DEBUG)
         h = int(xml_dom.getAttribute("height"))
         w = int(xml_dom.getAttribute("width"))
@@ -638,7 +638,8 @@
 
         #Update Manager
         self.manifest = manifest.ManifestChanges()
-        self.updateMana = upmana.updatemana.updaterFrame(self, "OpenRPG Update Manager Beta 0.6.7", open_rpg, self.manifest, True)
+        self.updateMana = upmana.updatemana.updaterFrame(self, 
+            "OpenRPG Update Manager Beta 0.7.2", open_rpg, self.manifest, True)
         self.log.log("Menu Created", ORPG_DEBUG)
         h = int(xml_dom.getAttribute("height"))
         w = int(xml_dom.getAttribute("width"))
@@ -652,6 +653,8 @@
         self.sound_player = orpg.tools.orpg_sound.orpgSound(self)
         open_rpg.add_component("sound", self.sound_player)
         wndinfo = AUI.AuiPaneInfo()
+        menuid = wx.NewId()
+        self.mainwindows[menuid] = "Sound Control Toolbar"
         wndinfo.DestroyOnClose(False)
         wndinfo.Name("Sound Control Toolbar")
         wndinfo.Caption("Sound Control Toolbar")
@@ -660,12 +663,13 @@
         wndinfo.Hide()
         self._mgr.AddPane(self.sound_player, wndinfo)
         children = xml_dom._get_childNodes()
-        for c in children:
-            self.build_window(c, self)
+        for c in children: self.build_window(c, self)
 
         # status window
         self.status = status_bar(self)
         wndinfo = AUI.AuiPaneInfo()
+        menuid = wx.NewId()
+        self.mainwindows[menuid] = "Status Window"
         wndinfo.DestroyOnClose(False)
         wndinfo.Name("Status Window")
         wndinfo.Caption("Status Window")
@@ -678,6 +682,8 @@
         # Create and show the floating dice toolbar
         self.dieToolBar = orpg.tools.toolBars.DiceToolBar(self, callBack = self.chat.ParsePost)
         wndinfo = AUI.AuiPaneInfo()
+        menuid = wx.NewId()
+        self.mainwindows[menuid] = "Dice Tool Bar"
         wndinfo.DestroyOnClose(False)
         wndinfo.Name("Dice Tool Bar")
         wndinfo.Caption("Dice Tool Bar")
@@ -690,6 +696,8 @@
         #Create the Map tool bar
         self.mapToolBar = orpg.tools.toolBars.MapToolBar(self, callBack = self.map.MapBar)
         wndinfo = AUI.AuiPaneInfo()
+        menuid = wx.NewId()
+        self.mainwindows[menuid] = "Map Tool Bar"
         wndinfo.DestroyOnClose(False)
         wndinfo.Name("Map Tool Bar")
         wndinfo.Caption("Map Tool Bar")
@@ -724,10 +732,8 @@
         self.mainmenu.Insert(3, self.windowsmenu, 'Windows')
         self.log.log("Windows Menu Done", ORPG_DEBUG)
         self._mgr.Update()
-        if wx.VERSION_STRING > "2.8":
-            self.Bind(AUI.EVT_AUI_PANE_CLOSE, self.onPaneClose)
-        else:
-            self.Bind(AUI.EVT_AUI_PANECLOSE, self.onPaneClose)
+        if wx.VERSION_STRING > "2.8": self.Bind(AUI.EVT_AUI_PANE_CLOSE, self.onPaneClose)
+        else: self.Bind(AUI.EVT_AUI_PANECLOSE, self.onPaneClose)
         self.log.log("AUI Bindings Done", ORPG_DEBUG)
 
         #Load the layout if one exists
@@ -836,8 +842,16 @@
     def onPaneClose(self, evt):
         self.log.log("Enter orpgFrame->onPaneClose()", ORPG_DEBUG)
         pane = evt.GetPane()
-        for wndid, wname in self.mainwindows.iteritems():
-            if pane.name == wname: self.windowsmenu.Check(wndid, False); break
+        #Arbitrary If ELIF fix. Items had incorrect ID's set. Finding correct ID will fix it for the iteration.
+        #Adding ID also fixed docking. Go figure.
+        if pane.name == 'Sound Control Toolbar': self.mainmenu.SetMenuState('ToolsSoundToolbar', False) 
+        elif pane.name == 'Status Window': self.mainmenu.SetMenuState('ToolsStatusBar', False) 
+        elif pane.name == 'Dice Tool Bar': self.mainmenu.SetMenuState('ToolsDiceBar', False) 
+        elif pane.name == 'Map Tool Bar': self.mainmenu.SetMenuState('ToolsMapBar', False) 
+        else: 
+            for wndid, wname in self.mainwindows.iteritems():
+                #print pane.name, wname, wndid
+                if pane.name == wname: self.windowsmenu.Check(wndid, False); break
         evt.Skip()
         self._mgr.Update()
         self.log.log("Exit orpgFrame->onPaneClose()", ORPG_DEBUG)
--- a/orpg/mapper/miniatures_handler.py	Sat Aug 08 00:35:09 2009 -0500
+++ b/orpg/mapper/miniatures_handler.py	Thu Aug 13 13:14:10 2009 -0500
@@ -358,7 +358,7 @@
 	    gametree = open_rpg.get_component('tree')
             node_xml = node_begin + min_xml + '</nodehandler>'
             #print "Sending this XML to insert_xml:" + node_xml
-            gametree.insert_xml(node_xml)
+            gametree.insert_xml(str(node_xml))
         elif id == MIN_SHOW_HIDE:
             if self.sel_rmin.hide:  self.sel_rmin.hide = 0
             else: self.sel_rmin.hide = 1
--- a/orpg/networking/gsclient.py	Sat Aug 08 00:35:09 2009 -0500
+++ b/orpg/networking/gsclient.py	Thu Aug 13 13:14:10 2009 -0500
@@ -159,9 +159,9 @@
 
         #Build Rooms Sizer
         self.room_list = wx.ListCtrl(self, LIST_ROOM, style=wx.LC_REPORT | wx.SUNKEN_BORDER)
-        self.room_list.InsertColumn(0,"Game", wx.LIST_FORMAT_LEFT,0)
-        self.room_list.InsertColumn(1,"Players", wx.LIST_FORMAT_LEFT,0)
-        self.room_list.InsertColumn(2,"PW", wx.LIST_FORMAT_LEFT,0)
+        self.room_list.InsertColumn(0,"Game", wx.LIST_FORMAT_LEFT,-1)
+        self.room_list.InsertColumn(1,"Players", wx.LIST_FORMAT_LEFT,-1)
+        self.room_list.InsertColumn(2,"PW", wx.LIST_FORMAT_LEFT,-1)
         self.buttons[GS_JOIN] = wx.Button(self, GS_JOIN, "Join Room")
         self.buttons[GS_JOINLOBBY] = wx.Button(self, GS_JOINLOBBY, "Lobby")
         self.sizers["roombtns"] = wx.BoxSizer(wx.HORIZONTAL)
@@ -243,7 +243,6 @@
 # [END] Snowdog: Updated Game Server Window 12/02
 #---------------------------------------------------------
 
-
     #-----------------------------------------------------
     # on_server_dbclick()
     # support for double click selection of server.
@@ -464,8 +463,11 @@
     def autosizeRooms(self):
         self.log.log("Enter game_server_panel->autosizeRooms(self)", ORPG_DEBUG)
         self.room_list.SetColumnWidth(0, wx.LIST_AUTOSIZE)
-        self.room_list.SetColumnWidth(1, wx.LIST_AUTOSIZE)
-        self.room_list.SetColumnWidth(2, wx.LIST_AUTOSIZE)
+        #self.room_list.SetColumnWidth(1, wx.LIST_AUTOSIZE)
+        #self.room_list.SetColumnWidth(2, wx.LIST_AUTOSIZE)
+        if self.room_list.GetColumnWidth(0) < 70: self.room_list.SetColumnWidth(0, 70)
+        if self.room_list.GetColumnWidth(1) < 70: self.room_list.SetColumnWidth(1, 70)
+        if self.room_list.GetColumnWidth(2) < 50: self.room_list.SetColumnWidth(2, 50)
         self.log.log("Exit game_server_panel->autosizeRooms(self)", ORPG_DEBUG)
 
     def refresh_server_list(self):
@@ -527,6 +529,7 @@
             # No server is currently selected!!!  Versus the broken and random 0!
             self.cur_server_index = -1
             self.server_list.SetColumnWidth(0, wx.LIST_AUTOSIZE)
+            if self.server_list.GetColumnWidth(0) < 70: self.server_list.SetColumnWidth(0, 70)
             self.server_list.SetColumnWidth(1, wx.LIST_AUTOSIZE)
 
             if self.serverNameSet == 0:
--- a/orpg/orpg_version.py	Sat Aug 08 00:35:09 2009 -0500
+++ b/orpg/orpg_version.py	Thu Aug 13 13:14:10 2009 -0500
@@ -2,9 +2,9 @@
 SERVER_MIN_CLIENT_VERSION = "1.7.1"
 
 #BUILD NUMBER FORMAT: "YYMMDD-##" where ## is the incremental daily build index (if needed)
-DISTRO = "Traipse"
-DIS_VER = "Grumpy Goblin"
-BUILD = "090808-00"
+DISTRO = "Traipse Dev"
+DIS_VER = "Ornery Orc"
+BUILD = "090812-00"
 
 # This version is for network capability.
 PROTOCOL_VERSION = "1.2"
--- a/orpg/player_list.py	Sat Aug 08 00:35:09 2009 -0500
+++ b/orpg/player_list.py	Thu Aug 13 13:14:10 2009 -0500
@@ -95,7 +95,7 @@
         self.SetImageList( self._imageList, wx.IMAGE_LIST_SMALL )
         # Create our column headers
         self.InsertColumn( 0, "ID" )
-        self.InsertColumn( 1, "Player" )
+        self.InsertColumn( 1, "Player")
         self.InsertColumn( 2, "Status" )
 #---------------------------------------------------------
 # [START] Digitalxero Multi Whisper Group 1/1/05
@@ -192,6 +192,13 @@
 #
 #       Revised 8/03 to add support for password manager
 #---------------------------------------------------------
+
+    def AutoAdjust(self):
+        self.SetColumnWidth(0, -1)
+        if self.GetColumnWidth(1) < 75: self.SetColumnWidth(1, 75)
+        if self.GetColumnWidth(2) < 75: self.SetColumnWidth(2, 75)
+        self.Refresh()
+
     def on_menu_password( self, evt ):
         id = evt.GetId()
         self.session = open_rpg.get_component("session")
@@ -328,6 +335,7 @@
         roleString = None
         roleBase = "/role %d=%s"
         infoBase = "Attempting to assign the role of %s to (%d) %s..."
+
         # Do type specific processing
 	recycle_bin = {PLAYER_ROLE_LURKER: ROLE_LURKER, PLAYER_ROLE_PLAYER: ROLE_PLAYER, PLAYER_ROLE_GM: ROLE_GM}
 	if recycle_bin.has_key(id):
@@ -449,6 +457,7 @@
         if sound_file != '':
             sound_player = open_rpg.get_component('sound')
             sound_player.play(sound_file)
+        self.AutoAdjust()
 
     def del_player(self,player):
         i = self.FindItemData(-1,int(player[2]))
@@ -492,7 +501,7 @@
         self.SetStringItem(i,2,player[3])
         item = self.GetItem(i)
         self.colorize_player_list()
-        self.Refresh()
+        self.AutoAdjust()
 
     def colorize_player_list(self):
         session = open_rpg.get_component("session")
--- a/orpg/tools/predTextCtrl.py	Sat Aug 08 00:35:09 2009 -0500
+++ b/orpg/tools/predTextCtrl.py	Thu Aug 13 13:14:10 2009 -0500
@@ -33,6 +33,7 @@
 
 import string
 from orpg.orpg_windows import *
+from wx.lib.expando import ExpandoTextCtrl
 
 #  This line added to test CVS commit
 
@@ -304,7 +305,7 @@
 #
 # Defines:
 #    findWord(self,insert,st)
-class predTextCtrl(wx.TextCtrl):
+class predTextCtrl(ExpandoTextCtrl):
 
     # Initialization subroutine.
     #
@@ -332,9 +333,9 @@
 
         #  Call super() for default behavior
         if validator:
-            wx.TextCtrl.__init__(self, parent, id=id, value=value, size=size, style=style, name=name, validator=validator )
+            ExpandoTextCtrl.__init__(self, parent, id=id, value=value, size=size, style=style, name=name, validator=validator )
         else:
-            wx.TextCtrl.__init__(self, parent, id=id, value=value, size=size, style=style, name=name)
+            ExpandoTextCtrl.__init__(self, parent, id=id, value=value, size=size, style=style, name=name)
 
         self.tree = LetterTree      #  Instantiate a new LetterTree.
         #  TODO:  make name of word file an argument.
--- a/upmana/manifest.py	Sat Aug 08 00:35:09 2009 -0500
+++ b/upmana/manifest.py	Thu Aug 13 13:14:10 2009 -0500
@@ -1,13 +1,13 @@
 import xmltramp
 import orpg.dirpath
-import orpg.tools.validate
+import upmana.validate
 from os import sep
 from types import *
 
 class ManifestChanges:
     def __init__(self, filename="updatemana.xml"):
         self.filename = orpg.dirpath.dir_struct["home"] + 'upmana' + sep + filename
-        orpg.tools.validate.Validate(orpg.dirpath.dir_struct["home"] + 'upmana' + sep).config_file(filename,"default_manifest.xml")
+        upmana.validate.Validate(orpg.dirpath.dir_struct["home"] + 'upmana' + sep).config_file(filename,"default_manifest.xml")
         self.xml_dom = self.LoadDoc()
 
     def GetString(self, plugname, strname, defaultval, verbose=0):
--- a/upmana/updatemana.py	Sat Aug 08 00:35:09 2009 -0500
+++ b/upmana/updatemana.py	Thu Aug 13 13:14:10 2009 -0500
@@ -6,10 +6,10 @@
 import orpg.tools.orpg_log
 import orpg.orpg_xml
 import orpg.dirpath
-import orpg.tools.validate
+import upmana.validate
 import tempfile
 import shutil
-from mercurial import ui, hg, commands, repo, revlog, cmdutil
+from mercurial import ui, hg, commands, repo, revlog, cmdutil, util
 
 
 class Updater(wx.Panel):
@@ -28,8 +28,8 @@
         self.log.log("Enter updaterFrame", ORPG_DEBUG)
         self.SetBackgroundColour(wx.WHITE)
         self.sizer = wx.GridBagSizer(hgap=1, vgap=1)
-        self.changelog = wx.TextCtrl(self, wx.ID_ANY, size=(400, -1), style=wx.TE_MULTILINE | wx.TE_READONLY)
-        self.filelist = wx.TextCtrl(self, wx.ID_ANY, size=(250, 300), style=wx.TE_MULTILINE | wx.TE_READONLY)
+        self.changelog = wx.TextCtrl(self, wx.ID_ANY, size=(325, -1), style=wx.TE_MULTILINE | wx.TE_READONLY)
+        self.filelist = wx.TextCtrl(self, wx.ID_ANY, size=(275, 300), style=wx.TE_MULTILINE | wx.TE_READONLY)
         self.buttons = {}
         self.buttons['progress_bar'] = wx.Gauge(self, wx.ID_ANY, 100)
         self.buttons['auto_text'] = wx.StaticText(self, wx.ID_ANY, "Auto Update")
@@ -96,7 +96,7 @@
 
         filename = 'ignorelist.txt'
         self.filename = orpg.dirpath.dir_struct["home"] + 'upmana' + os.sep + filename
-        orpg.tools.validate.Validate(orpg.dirpath.dir_struct["home"] + 'upmana' + os.sep).config_file(filename, "default_ignorelist.txt")
+        upmana.validate.Validate(orpg.dirpath.dir_struct["home"] + 'upmana' + os.sep).config_file(filename, "default_ignorelist.txt")
         self.mana = self.LoadDoc()
         for ignore in self.ignorelist:
             shutil.copy(ignore, orpg.dirpath.dir_struct["home"] + 'upmana' + os.sep + 'tmp' + os.sep +ignore.split('/')[len(ignore.split('/')) - 1])
@@ -169,53 +169,32 @@
         heads = dict.fromkeys(self.repo.heads(), 1)
         l = [((n in heads), self.repo.changelog.rev(n), n, t) for t, n in branches.items()]
 
-        #l.sort()
-        #l.reverse()
-        #for ishead, r, n, t in l: self.package_list.append(t)
-
         if self.current != type:
-            #r = hg.islocal()
-            files = self.c.files()
-            #print commands.log(u, r, c)
-            #print r.changelog
-
-            ### Cleaning up for dev build 0.1
-            ### The below material is for the Rev Log.  You can run hg log to see what data it will pull.
-            #cs = r.changectx(c.rev()).changeset()
-            #get = util.cachefunc(lambda r: repo.changectx(r).changeset())
-            #changeiter, matchfn = cmdutil.walkchangerevs(u, r, 1, cs, 1)
-            #for st, rev, fns in changeiter:
-            #    revbranch = get(rev)[5]['branch']; print revbranch
-
             heads = dict.fromkeys(self.repo.heads(), self.repo.branchtags())
             branches = dict.copy(self.repo.branchtags())
             self.BranchInfo(self.current)
 
     def BranchInfo(self, branch):
-        self.filelist.SetValue('')
-        self.filelist.AppendText("Files that will change\n\n")
+        cs = self.repo.changectx( self.current ).changeset()
+        rev = self.repo.changelog.rev(self.repo.branchtags()[self.current]) #Current revision number. Use in Controls
         self.changelog.SetValue('')
-        changelog = "Traipse 'OpenRPG' Update Manager.\n\nThis is Dev Build 0.7 (open beta) of the Update Manager. This version is nearly 100% functional. Users can now add repositories of OpenRPG, choose from different branches available from those repositories, and add files to an ignore list.\n\nThe Update Manager is divided into tabs, Updater, Repos, Manifest, and Control. \n\nUpdater: Set your update type on startup; Auto, None. Select a package of changes from a branch and update.\n\nRepos: Collect repositories of different projects. Set a name then assign it a URL. Refresh repositories in your list or delete them from your list.\n\nManifest: A complete list of all the files in your current change set. Check files off that you want to be safe from future updates.\n\nControl: Incomplete. Future revisions will allow users to update to specific revision branchs and delete branches from their computer.\n\nThis is a good start. Enjoy the freedom!!"
+        changelog = cs[4]
         self.changelog.AppendText(changelog + '\n')
-        self.filelist.AppendText("Traipse 'OpenRPG'\n\n Currently selected branch: " + branch + "\n\nFile List: When Control is completed this field will display a list of files that will be affected by your selection of branch.  The window to the left will display the description of the branch.\n\nDescription: Stable releases will have a formated Description that displays the Build Number, a summary of the branch, and a summary of the changes in the selected changeset.")
-
-        #### Files works but not fully without the change log information, pulled for Dev 0.1
-        #for f in files:
-        #    fc = c[f]
-        #    self.filelist.AppendText(str(f + '\n'))
+        self.filelist.SetValue('')
+        self.filelist.AppendText("Currently selected branch: " + branch + "\n\nAuthor: "+cs[1]+"\n\nFiles Modified (in update): \n")
+        for f in cs[3]: self.filelist.AppendText(f+"\n")
 
     def get_packages(self, type=None):
         #Fixed and ready for Test. Can be cleaner
         self.package_list = []
         b = self.repo.branchtags()
-        heads = dict.fromkeys(self.repo.heads(), 1)
+        heads = dict.fromkeys(self.repo.heads(), 1) #The code below looks superfluous but there is good info inside
         l = [((n in heads), self.repo.changelog.rev(n), n, t) for t, n in b.items()]
         l.sort()
         l.reverse()
         for ishead, r, n, t in l: self.package_list.append(t)
 
     def get_package(self):
-        #Fixed and ready for test.
         self.get_packages()
         if self.package_list == None: return None
         return None
@@ -259,6 +238,7 @@
         self.sizers["newrepo_layout"].Add(self.texts["reponame"], -1, wx.EXPAND)
         self.sizers["newrepo_layout"].AddGrowableCol(1)
         self.sizers["newbutton"].Add(self.sizers["newrepo_layout"], -1, wx.EXPAND)
+
         #Repo List Panel
         self.repopanel = wx.ScrolledWindow(self)
         self.repopanel.SetScrollbars(20,20,55,40)
@@ -394,7 +374,7 @@
             wx.LC_REPORT|wx.SUNKEN_BORDER|wx.EXPAND|wx.LC_HRULES)
         filename = 'ignorelist.txt'
         self.filename = orpg.dirpath.dir_struct["home"] + 'upmana' + os.sep + filename
-        orpg.tools.validate.Validate(orpg.dirpath.dir_struct["home"] + 'upmana' + os.sep).config_file(filename, "default_ignorelist.txt")
+        upmana.validate.Validate(orpg.dirpath.dir_struct["home"] + 'upmana' + os.sep).config_file(filename, "default_ignorelist.txt")
         self.mana = self.LoadDoc()
         self.manifestlog.Bind(wx.EVT_CHECKLISTBOX, self.GetChecked)
         self.sizer.Add(self.manifestlog, (0,0), flag=wx.EXPAND)
@@ -420,6 +400,8 @@
         for i in ignorelist: #Adds previously ignored files to manifestlistlog if they are not in changesets.
             if self.c.manifest().has_key(i): continue
             else: self.manifestlist.append(i); self.manifestlist.sort()
+        self.manifestlog = wx.CheckListBox( self, -1, wx.DefaultPosition, wx.DefaultSize, self.manifestlist, 
+            wx.LC_REPORT|wx.SUNKEN_BORDER|wx.EXPAND|wx.LC_HRULES)
         self.manifestlog.SetCheckedStrings(ignorelist)
         manifest = ignore.readlines()
         ignore.close()
@@ -431,10 +413,14 @@
 
 class updaterFrame(wx.Frame):
     def __init__(self, parent, title, openrpg, manifest, main):
-        wx.Frame.__init__(self, None, wx.ID_ANY, title, size=(700,480), 
-            style=wx.FRAME_NO_TASKBAR | wx.STAY_ON_TOP | wx.DEFAULT_FRAME_STYLE)
+        self.dir_struct = open_rpg.get_component("dir_struct")
+
+        wx.Frame.__init__(self, None, wx.ID_ANY, title, size=(600,480), style=wx.DEFAULT_FRAME_STYLE)
+        if wx.Platform == '__WXMSW__': icon = wx.Icon(self.dir_struct["icon"]+'d20.ico', wx.BITMAP_TYPE_ICO)
+        else: icon = wx.Icon(self.dir_struct["icon"]+"d20.xpm", wx.BITMAP_TYPE_XPM )
+        self.SetIcon(icon)
+
         self.CenterOnScreen()
-
         self.main = main
         ####### Panel Stuff ######
         p = wx.Panel(self)
@@ -461,8 +447,7 @@
 
     def OnClose(self, event):
         if self.main == False: self.Destroy()
-        if self.main == True: self.Hide() #self.Hide()
-        #continue
+        if self.main == True: self.Hide()
 
 class updateApp(wx.App):
     def OnInit(self):
@@ -475,9 +460,9 @@
         self.open_rpg.add_component("log", self.log)
         self.open_rpg.add_component("xml", orpg.orpg_xml)
         self.open_rpg.add_component("dir_struct", orpg.dirpath.dir_struct)
-        self.validate = orpg.tools.validate.Validate()
-        self.open_rpg.add_component("validate", self.validate)
-        self.updater = updaterFrame(self, "OpenRPG Update Manager 0.7 (open beta)", self.open_rpg, self.manifest, self.main)
+        self.validate = upmana.validate.Validate()
+        self.open_rpg.add_component("validate", self.validate)
+        self.updater = updaterFrame(self, "OpenRPG Update Manager 0.7.2 (open beta)", self.open_rpg, self.manifest, self.main)
         if self.manifest.GetString("updatemana", "auto_update", "") == 'on' and self.main == False:
             self.AutoUpdate(); self.OnExit()
         else: pass
@@ -486,7 +471,6 @@
         else: pass
         try:
             self.updater.Show()
-            #self.SetTopWindow(self.updater)
             self.updater.Fit()
         except: pass
         return True
@@ -502,7 +486,7 @@
             commands.pull(self.ui, self.repo, capture, rev='', update=False, force=True)
             filename = 'ignorelist.txt'
             self.filename = orpg.dirpath.dir_struct["home"] + 'upmana' + os.sep + filename
-            orpg.tools.validate.Validate(orpg.dirpath.dir_struct["home"] + 'upmana' + os.sep).config_file(filename, "default_ignorelist.txt")
+            upmana.validate.Validate(orpg.dirpath.dir_struct["home"] + 'upmana' + os.sep).config_file(filename, "default_ignorelist.txt")
             self.mana = self.LoadDoc()
             for ignore in self.ignorelist:
                 shutil.copy(ignore, orpg.dirpath.dir_struct["home"] + 'upmana' + os.sep + 'tmp' + os.sep +ignore.split('/')[len(ignore.split('/')) - 1])
@@ -521,7 +505,7 @@
         ignore.close()
 
     def OnExit(self):
-        imported = ['manifest', 'orpg.dirpath', 'orpg.orpgCore', 'orpg.orpg_version', 'orpg.tools.orpg_log', 'orpg.tools.orpg_log', 'orpg.orpg_xml', 'orpg.dirpath', 'orpg.dirpath', 'orpg.tools.validate', 'mercurial.ui', 'mercurial.hg', 'mercurial.commands', 'mercurial.repo', 'mercurial.revlog', 'mercurial.cmdutil', 'shutil']
+        imported = ['manifest', 'orpg.dirpath', 'orpg.orpgCore', 'orpg.orpg_version', 'orpg.tools.orpg_log', 'orpg.tools.orpg_log', 'orpg.orpg_xml', 'orpg.dirpath', 'orpg.dirpath', 'upmana.validate', 'mercurial.ui', 'mercurial.hg', 'mercurial.commands', 'mercurial.repo', 'mercurial.revlog', 'mercurial.cmdutil', 'shutil']
         for name in imported:
             if name in sys.modules: del sys.modules[name]