summaryrefslogtreecommitdiff
path: root/rclua5
diff options
context:
space:
mode:
authorPixel <pixel@nobis-crew.org>2010-06-15 00:59:57 -0700
committerPixel <pixel@nobis-crew.org>2010-06-15 00:59:57 -0700
commiteed0eb6a476d54ce19aeff137984aa981d9e3976 (patch)
tree807891636efd2f87dcbd261e971216269973ae07 /rclua5
parentccc8261e4d48de89da4ddfe7b55e378ae0cd6f47 (diff)
Upgrading to iup 3.1
Diffstat (limited to 'rclua5')
-rw-r--r--rclua519591
1 files changed, 19591 insertions, 0 deletions
diff --git a/rclua5 b/rclua5
new file mode 100644
index 0000000..00d4139
--- /dev/null
+++ b/rclua5
@@ -0,0 +1,19591 @@
+diff --git a/iup/COPYRIGHT b/iup/COPYRIGHT
+index dd31d6c..0061f2d 100755
+--- a/iup/COPYRIGHT
++++ b/iup/COPYRIGHT
+@@ -7,7 +7,7 @@ and commercial purposes at absolutely no cost.
+ 
+ ===============================================================================
+ 
+-Copyright (C) 1994-2009 Tecgraf, PUC-Rio.
++Copyright (C) 1994-2010 Tecgraf, PUC-Rio.
+ 
+ Permission is hereby granted, free of charge, to any person obtaining a copy
+ of this software and associated documentation files (the "Software"), to deal
+diff --git a/iup/etc/iup.rc b/iup/etc/iup.rc
+index eab8cf5..49c324d 100755
+--- a/iup/etc/iup.rc
++++ b/iup/etc/iup.rc
+@@ -12,7 +12,7 @@ BEGIN
+ VALUE "CompanyName", "Tecgraf/PUC-Rio\0"
+ VALUE "FileDescription", "IUP - Portable User Interface\0"
+ VALUE "FileVersion", "3.0.0\0"
+- VALUE "LegalCopyright", "Copyright © 1994-2009 Tecgraf, PUC-Rio.\0"
++ VALUE "LegalCopyright", "Copyright © 1994-2010 Tecgraf, PUC-Rio.\0"
+ VALUE "OriginalFilename", "iup.dll\0"
+ VALUE "ProductName", "IUP for Windows\0"
+ VALUE "ProductVersion", "3.0.0\0"
+diff --git a/iup/include/iup.h b/iup/include/iup.h
+index 9913329..2d33b98 100755
+--- a/iup/include/iup.h
++++ b/iup/include/iup.h
+@@ -19,11 +19,11 @@ extern "C" {
+ 
+ 
+ #define IUP_NAME "IUP - Portable User Interface"
+-#define IUP_COPYRIGHT "Copyright (C) 1994-2009 Tecgraf, PUC-Rio."
++#define IUP_COPYRIGHT "Copyright (C) 1994-2010 Tecgraf, PUC-Rio."
+ #define IUP_DESCRIPTION "Portable toolkit for building graphical user interfaces."
+-#define IUP_VERSION "3.0" /* bug fixes are reported only by IupVersion functions */
+-#define IUP_VERSION_NUMBER 300000
+-#define IUP_VERSION_DATE "2009/10/02"
++#define IUP_VERSION "3.1" /* bug fixes are reported only by IupVersion functions */
++#define IUP_VERSION_NUMBER 301000
++#define IUP_VERSION_DATE "2010/04/22"
+ 
+ typedef struct Ihandle_ Ihandle;
+ typedef int (*Icallback)(Ihandle*);
+@@ -38,6 +38,7 @@ void IupImageLibOpen (void);
+ 
+ int IupMainLoop (void);
+ int IupLoopStep (void);
++int IupLoopStepWait (void);
+ int IupMainLoopLevel (void);
+ void IupFlush (void);
+ void IupExitLoop (void);
+@@ -148,6 +149,7 @@ Ihandle* IupNormalizerv(Ihandle* *ih_list);
+ Ihandle* IupCbox (Ihandle* child, ...);
+ Ihandle* IupCboxv (Ihandle* *children);
+ Ihandle* IupSbox (Ihandle *child);
++Ihandle* IupSplit (Ihandle* child1, Ihandle* child2);
+ 
+ Ihandle* IupFrame (Ihandle* child);
+ 
+@@ -197,12 +199,13 @@ int IupTreeSetUserId(Ihandle* ih, int id, void* userid);
+ void* IupTreeGetUserId(Ihandle* ih, int id);
+ int IupTreeGetId(Ihandle* ih, void *userid);
+ 
+-void IupTreeSetAttribute (Ihandle* ih, const char* name, int id, char* value);
+-void IupTreeStoreAttribute(Ihandle* ih, const char* name, int id, char* value);
++void IupTreeSetAttribute (Ihandle* ih, const char* name, int id, const char* value);
++void IupTreeStoreAttribute(Ihandle* ih, const char* name, int id, const char* value);
+ char* IupTreeGetAttribute (Ihandle* ih, const char* name, int id);
+ int IupTreeGetInt (Ihandle* ih, const char* name, int id);
+ float IupTreeGetFloat (Ihandle* ih, const char* name, int id);
+-void IupTreeSetfAttribute (Ihandle* ih, const char* name, int id, char* format, ...);
++void IupTreeSetfAttribute (Ihandle* ih, const char* name, int id, const char* format, ...);
++void IupTreeSetAttributeHandle(Ihandle* ih, const char* a, int id, Ihandle* ih_named);
+ 
+ 
+ /************************************************************************/
+@@ -338,7 +341,7 @@ int IupMain (int argc, char** argv); /* In C++ we have to declare the prototype
+ #endif
+ 
+ /******************************************************************************
+-* Copyright (C) 1994-2009 Tecgraf, PUC-Rio.
++* Copyright (C) 1994-2010 Tecgraf, PUC-Rio.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining
+ * a copy of this software and associated documentation files (the
+diff --git a/iup/include/iupcbs.h b/iup/include/iupcbs.h
+index f33166b..70d117f 100755
+--- a/iup/include/iupcbs.h
++++ b/iup/include/iupcbs.h
+@@ -24,7 +24,7 @@ typedef int (*IFnnii)(Ihandle*, Ihandle*, int, int); /* drop_cb */
+ typedef int (*IFnnn)(Ihandle*, Ihandle*, Ihandle*); /* tabchange_cb */
+ typedef int (*IFnss)(Ihandle*, char *, char *); /* file_cb */
+ typedef int (*IFns)(Ihandle*, char *); /* multiselect_cb */
+-typedef int (*IFnis)(Ihandle*, int, char *); /* text_action, multiline_action, edit_cb, renamenode_cb, rename_cb */
++typedef int (*IFnis)(Ihandle*, int, char *); /* text_action, multiline_action, edit_cb, rename_cb */
+ typedef int (*IFnsii)(Ihandle*, char*, int, int); /* list_action */
+ typedef int (*IFnsiii)(Ihandle*, char*, int, int, int); /* dropfiles_cb */
+ typedef int (*IFniis)(Ihandle*, int, int, char*); /* motion_cb, click_cb, value_edit_cb */
+diff --git a/iup/include/iupcontrols.h b/iup/include/iupcontrols.h
+index c7bc566..a30d407 100755
+--- a/iup/include/iupcontrols.h
++++ b/iup/include/iupcontrols.h
+@@ -15,9 +15,6 @@ extern "C" {
+ int IupControlsOpen(void);
+ void IupControlsClose(void); /* for backward compatibility only, does nothing since IUP 3 */
+ 
+-void IupOldValOpen(void);
+-void IupOldTabsOpen(void);
+-
+ Ihandle* IupColorbar(void);
+ Ihandle* IupCells(void);
+ Ihandle *IupColorBrowser(void);
+diff --git a/iup/include/iuplua.h b/iup/include/iuplua.h
+index dc660b5..854a858 100755
+--- a/iup/include/iuplua.h
++++ b/iup/include/iuplua.h
+@@ -23,7 +23,7 @@ int iuplua_dofile (char *filename);
+ 
+ #ifdef LUA_TNONE /* Lua 5 */
+ int iuplua_open(lua_State *L);
+-int iupkey_open(lua_State *L);
++int iupkey_open(lua_State *L); /* does nothing, kept for backward compatibility */
+ int iuplua_close(lua_State * L);
+ 
+ /* utilities */
+diff --git a/iup/mak.vc8/iupgtk.vcproj b/iup/mak.vc8/iupgtk.vcproj
+index 5d0a8e2..9fccbb2 100755
+--- a/iup/mak.vc8/iupgtk.vcproj
++++ b/iup/mak.vc8/iupgtk.vcproj
+@@ -143,6 +143,10 @@
+ >
+ </File>
+ <File
++ RelativePath="..\src\gtk\iupgtk_clipboard.c"
++ >
++ </File>
++ <File
+ RelativePath="..\src\gtk\iupgtk_colordlg.c"
+ >
+ </File>
+diff --git a/iup/mak.vc8/iuplua5.vcproj b/iup/mak.vc8/iuplua5.vcproj
+index 0c62f76..1245e86 100755
+--- a/iup/mak.vc8/iuplua5.vcproj
++++ b/iup/mak.vc8/iuplua5.vcproj
+@@ -123,6 +123,10 @@
+ >
+ </File>
+ <File
++ RelativePath="..\srclua5\il_clipboard.c"
++ >
++ </File>
++ <File
+ RelativePath="..\srclua5\il_colordlg.c"
+ >
+ </File>
+@@ -307,6 +311,10 @@
+ >
+ </File>
+ <File
++ RelativePath="..\srclua5\clipboard.lua"
++ >
++ </File>
++ <File
+ RelativePath="..\srclua5\colordlg.lua"
+ >
+ </File>
+diff --git a/iup/mak.vc8/iupmot.vcproj b/iup/mak.vc8/iupmot.vcproj
+index aedd67e..d2d1780 100755
+--- a/iup/mak.vc8/iupmot.vcproj
++++ b/iup/mak.vc8/iupmot.vcproj
+@@ -161,6 +161,10 @@
+ >
+ </File>
+ <File
++ RelativePath="..\src\mot\iupmot_clipboard.c"
++ >
++ </File>
++ <File
+ RelativePath="..\src\mot\iupmot_colordlg.c"
+ >
+ </File>
+diff --git a/iup/mak.vc8/iupsample.vcproj b/iup/mak.vc8/iupsample.vcproj
+index bddc4f6..dde33fd 100755
+--- a/iup/mak.vc8/iupsample.vcproj
++++ b/iup/mak.vc8/iupsample.vcproj
+@@ -616,6 +616,13 @@
+ <File
+ RelativePath="..\html\examples\C\sample.c"
+ >
++ <FileConfiguration
++ Name="Debug|Win32"
++ >
++ <Tool
++ Name="VCCLCompilerTool"
++ />
++ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="..\html\examples\C\sbox1.c"
+diff --git a/iup/mak.vc8/iupsamplegtk.vcproj b/iup/mak.vc8/iupsamplegtk.vcproj
+index b4792dd..290a86e 100755
+--- a/iup/mak.vc8/iupsamplegtk.vcproj
++++ b/iup/mak.vc8/iupsamplegtk.vcproj
+@@ -435,6 +435,14 @@
+ <File
+ RelativePath="..\html\examples\C\list1.c"
+ >
++ <FileConfiguration
++ Name="Debug|Win32"
++ ExcludedFromBuild="true"
++ >
++ <Tool
++ Name="VCCLCompilerTool"
++ />
++ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="..\html\examples\C\list2.c"
+@@ -777,7 +785,6 @@
+ >
+ <FileConfiguration
+ Name="Debug|Win32"
+- ExcludedFromBuild="true"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+diff --git a/iup/mak.vc8/iuptest.vcproj b/iup/mak.vc8/iuptest.vcproj
+index 375d83f..b539677 100755
+--- a/iup/mak.vc8/iuptest.vcproj
++++ b/iup/mak.vc8/iuptest.vcproj
+@@ -159,6 +159,10 @@
+ >
+ </File>
+ <File
++ RelativePath="..\test\clipboard.c"
++ >
++ </File>
++ <File
+ RelativePath="..\test\colorbar.c"
+ >
+ </File>
+@@ -255,6 +259,14 @@
+ >
+ </File>
+ <File
++ RelativePath="..\test\sbox.c"
++ >
++ </File>
++ <File
++ RelativePath="..\test\scanf.c"
++ >
++ </File>
++ <File
+ RelativePath="..\test\spin.c"
+ >
+ </File>
+@@ -298,6 +310,10 @@
+ RelativePath="..\test\vbox.c"
+ >
+ </File>
++ <File
++ RelativePath="..\test\zbox.c"
++ >
++ </File>
+ </Files>
+ <Globals>
+ </Globals>
+diff --git a/iup/mak.vc8/iuptestgtk.vcproj b/iup/mak.vc8/iuptestgtk.vcproj
+index 46d9e49..017bb69 100755
+--- a/iup/mak.vc8/iuptestgtk.vcproj
++++ b/iup/mak.vc8/iuptestgtk.vcproj
+@@ -154,6 +154,10 @@
+ >
+ </File>
+ <File
++ RelativePath="..\test\clipboard.c"
++ >
++ </File>
++ <File
+ RelativePath="..\test\colorbar.c"
+ >
+ </File>
+@@ -246,6 +250,14 @@
+ >
+ </File>
+ <File
++ RelativePath="..\test\sbox.c"
++ >
++ </File>
++ <File
++ RelativePath="..\test\scanf.c"
++ >
++ </File>
++ <File
+ RelativePath="..\test\spin.c"
+ >
+ </File>
+@@ -289,6 +301,10 @@
+ RelativePath="..\test\vbox.c"
+ >
+ </File>
++ <File
++ RelativePath="..\test\zbox.c"
++ >
++ </File>
+ </Files>
+ <Globals>
+ </Globals>
+diff --git a/iup/mak.vc8/iupwin.vcproj b/iup/mak.vc8/iupwin.vcproj
+index c1e2434..cf53df8 100755
+--- a/iup/mak.vc8/iupwin.vcproj
++++ b/iup/mak.vc8/iupwin.vcproj
+@@ -176,6 +176,10 @@
+ >
+ </File>
+ <File
++ RelativePath="..\src\win\iupwin_clipboard.c"
++ >
++ </File>
++ <File
+ RelativePath="..\src\win\iupwin_colordlg.c"
+ >
+ </File>
+diff --git a/iup/mak.vc9/iup.sln b/iup/mak.vc9/iup.sln
+index 898c75f..47e2076 100755
+--- a/iup/mak.vc9/iup.sln
++++ b/iup/mak.vc9/iup.sln
+@@ -95,6 +95,7 @@ Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "iuplua5_exe", "iupluaexe5.v
+ {1EBC7A53-4677-AAAA-1234-49D301F17D85} = {1EBC7A53-4677-AAAA-1234-49D301F17D85}
+ {1EBC7A53-4677-75D7-8D4A-49D301F17D85} = {1EBC7A53-4677-75D7-8D4A-49D301F17D85}
+ {1EBC7A53-4677-ADF1-8D4A-49D301F17D85} = {1EBC7A53-4677-ADF1-8D4A-49D301F17D85}
++ {1EBC7A53-4677-FFFF-1234-49D301F17D85} = {1EBC7A53-4677-FFFF-1234-49D301F17D85}
+ {B4823266-DF8C-4EFB-91C0-C7688C234EAC} = {B4823266-DF8C-4EFB-91C0-C7688C234EAC}
+ {5EEFE977-C56D-462F-BDEE-12A5452EB8CC} = {5EEFE977-C56D-462F-BDEE-12A5452EB8CC}
+ {5EEFE977-C56D-462F-BDEE-12A5452EB8CC} = {5EEFE977-C56D-462F-BDEE-12A5452EB8CC}
+@@ -196,6 +197,8 @@ Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "iuplua5gtk_exe", "iupluaexe
+ {E251B4F4-0B0A-482B-BA18-2509ADC4B6AA} = {E251B4F4-0B0A-482B-BA18-2509ADC4B6AA}
+ EndProjectSection
+ EndProject
++Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Tools", "Tools", "{B24D8E0A-2EB5-4C49-A146-C0AABEF81788}"
++EndProject
+ Global
+ GlobalSection(SolutionConfigurationPlatforms) = preSolution
+ Debug|Win32 = Debug|Win32
+@@ -285,7 +288,6 @@ Global
+ {2F92EC58-D94C-40BF-8C82-77607C72E1E3} = {FC52B7B5-744E-45D6-815C-3502F9D965E7}
+ {9462FDEA-3E53-4250-8710-DD50AF48607C} = {FC52B7B5-744E-45D6-815C-3502F9D965E7}
+ {C684B76D-52EC-49CE-84F2-B031509419A5} = {FC52B7B5-744E-45D6-815C-3502F9D965E7}
+- {A60D658D-766C-40DB-BAFF-59AB884D86FB} = {11041D08-354A-4300-9624-41277E67DE34}
+ {1EBC7A53-4677-4C3A-8DFF-269001F17D85} = {11041D08-354A-4300-9624-41277E67DE34}
+ {1EBC7A53-4677-4C3A-8DFF-49DFF4417D85} = {11041D08-354A-4300-9624-41277E67DE34}
+ {1EBC7A53-33FF-4C3A-8DFF-49D301F17D85} = {11041D08-354A-4300-9624-41277E67DE34}
+@@ -293,7 +295,6 @@ Global
+ {1EBC7A53-4677-1234-DDDD-49DFF4417D85} = {11041D08-354A-4300-9624-41277E67DE34}
+ {B4823266-DF8C-4EFB-91C0-C7E78C234EAC} = {11041D08-354A-4300-9624-41277E67DE34}
+ {1EBC7A53-4677-4C3A-8DFF-49D301F17D85} = {11041D08-354A-4300-9624-41277E67DE34}
+- {A60D658D-766C-40DB-BAE4-59AB884D86FB} = {1CBEAA34-BA34-497D-A775-B9AF6F905696}
+ {1EBC7A53-4677-ADF1-8D4A-49D301F17D85} = {1CBEAA34-BA34-497D-A775-B9AF6F905696}
+ {1EBC7A53-4677-75D7-8D4A-49D301F17D85} = {1CBEAA34-BA34-497D-A775-B9AF6F905696}
+ {1EBC7A53-4677-4C3A-8D4A-49D301157985} = {1CBEAA34-BA34-497D-A775-B9AF6F905696}
+@@ -302,7 +303,12 @@ Global
+ {B4823266-DF8C-4EFB-91C0-C7688C234EAC} = {1CBEAA34-BA34-497D-A775-B9AF6F905696}
+ {1EBC7A53-4677-4C3A-8D4A-49D301F17D85} = {1CBEAA34-BA34-497D-A775-B9AF6F905696}
+ {1EBC7A53-4677-FFFF-1234-49D301F17D85} = {1CBEAA34-BA34-497D-A775-B9AF6F905696}
+- {389DF3C9-A628-4F6D-8C52-8924FA01DE66} = {1CBEAA34-BA34-497D-A775-B9AF6F905696}
++ {A60D658D-766C-40DB-BAFF-59AB884D86FB} = {B24D8E0A-2EB5-4C49-A146-C0AABEF81788}
++ {A60D658D-766C-40DB-BAE4-59AB884D86FB} = {B24D8E0A-2EB5-4C49-A146-C0AABEF81788}
++ {389DF3C9-A628-4F6D-8C52-8924FA01DE66} = {B24D8E0A-2EB5-4C49-A146-C0AABEF81788}
++ {2F92EC58-D94C-40BF-4444-77607C72E1E3} = {B24D8E0A-2EB5-4C49-A146-C0AABEF81788}
++ {E7D19356-B0AB-44AD-ACCB-5FFFCC4837BE} = {B24D8E0A-2EB5-4C49-A146-C0AABEF81788}
++ {0F789DF8-22CC-4392-98DB-AC3960FAD4EA} = {B24D8E0A-2EB5-4C49-A146-C0AABEF81788}
+ EndGlobalSection
+ GlobalSection(DevPartner) = postSolution
+ EndGlobalSection
+diff --git a/iup/mak.vc9/iupcontrols.vcproj b/iup/mak.vc9/iupcontrols.vcproj
+index 6a452af..2a7875c 100755
+--- a/iup/mak.vc9/iupcontrols.vcproj
++++ b/iup/mak.vc9/iupcontrols.vcproj
+@@ -311,14 +311,6 @@
+ >
+ </File>
+ <File
+- RelativePath="..\srccontrols\iup_oldtabs.c"
+- >
+- </File>
+- <File
+- RelativePath="..\srccontrols\iup_oldval.c"
+- >
+- </File>
+- <File
+ RelativePath="..\srccontrols\iupcontrols.def"
+ >
+ <FileConfiguration
+diff --git a/iup/mak.vc9/iupcore.vcproj b/iup/mak.vc9/iupcore.vcproj
+index fbe0017..851395e 100755
+--- a/iup/mak.vc9/iupcore.vcproj
++++ b/iup/mak.vc9/iupcore.vcproj
+@@ -475,6 +475,10 @@
+ >
+ </File>
+ <File
++ RelativePath="..\src\iup_split.c"
++ >
++ </File>
++ <File
+ RelativePath="..\src\iup_tabs.c"
+ >
+ </File>
+@@ -583,17 +587,6 @@
+ >
+ </File>
+ </Filter>
+- <File
+- RelativePath="..\src\iup.def"
+- >
+- <FileConfiguration
+- Name="Debug|Win32"
+- >
+- <Tool
+- Name="VCCustomBuildTool"
+- />
+- </FileConfiguration>
+- </File>
+ </Files>
+ <Globals>
+ </Globals>
+diff --git a/iup/mak.vc9/iupgtk.vcproj b/iup/mak.vc9/iupgtk.vcproj
+index 17281f1..a84dd4a 100755
+--- a/iup/mak.vc9/iupgtk.vcproj
++++ b/iup/mak.vc9/iupgtk.vcproj
+@@ -95,6 +95,10 @@
+ >
+ </File>
+ <File
++ RelativePath="..\src\gtk\iupgtk_draw.c"
++ >
++ </File>
++ <File
+ RelativePath="..\src\gtk\iupgtk_focus.c"
+ >
+ </File>
+diff --git a/iup/mak.vc9/iuplua3.vcproj b/iup/mak.vc9/iuplua3.vcproj
+index 9993c1c..e46f316 100755
+--- a/iup/mak.vc9/iuplua3.vcproj
++++ b/iup/mak.vc9/iuplua3.vcproj
+@@ -116,6 +116,10 @@
+ >
+ </File>
+ <File
++ RelativePath="..\srclua3\il_split.c"
++ >
++ </File>
++ <File
+ RelativePath="..\srclua3\il_tabs.c"
+ >
+ </File>
+@@ -164,6 +168,10 @@
+ >
+ </File>
+ <File
++ RelativePath="..\srclua3\split.lua"
++ >
++ </File>
++ <File
+ RelativePath="..\srclua3\tabs.lua"
+ >
+ </File>
+diff --git a/iup/mak.vc9/iuplua5.vcproj b/iup/mak.vc9/iuplua5.vcproj
+index 17d9a55..ad13650 100755
+--- a/iup/mak.vc9/iuplua5.vcproj
++++ b/iup/mak.vc9/iuplua5.vcproj
+@@ -231,6 +231,10 @@
+ >
+ </File>
+ <File
++ RelativePath="..\srclua5\il_split.c"
++ >
++ </File>
++ <File
+ RelativePath="..\srclua5\il_submenu.c"
+ >
+ </File>
+@@ -407,6 +411,10 @@
+ >
+ </File>
+ <File
++ RelativePath="..\srclua5\split.lua"
++ >
++ </File>
++ <File
+ RelativePath="..\srclua5\submenu.lua"
+ >
+ </File>
+diff --git a/iup/mak.vc9/iupluaexe5.vcproj b/iup/mak.vc9/iupluaexe5.vcproj
+index db6804a..39d15f2 100755
+--- a/iup/mak.vc9/iupluaexe5.vcproj
++++ b/iup/mak.vc9/iupluaexe5.vcproj
+@@ -72,7 +72,7 @@
+ OutputFile="$(OutDir)/iuplua51.exe"
+ LinkIncremental="1"
+ SuppressStartupBanner="true"
+- AdditionalLibraryDirectories="..\..\im\lib;..\..\cd\lib;..\lib;..\..\lua5.1\lib\vc9;..\..\luagl\lib\static"
++ AdditionalLibraryDirectories="..\..\im\lib;..\..\cd\lib;..\lib;..\..\lua5.1\lib\vc9;..\..\luagl\lib\static;..\..\lfs\lib\vc9"
+ GenerateManifest="false"
+ GenerateDebugInformation="true"
+ SubSystem="1"
+diff --git a/iup/mak.vc9/iupmot.vcproj b/iup/mak.vc9/iupmot.vcproj
+index 9bbfa5c..5c40695 100755
+--- a/iup/mak.vc9/iupmot.vcproj
++++ b/iup/mak.vc9/iupmot.vcproj
+@@ -109,6 +109,10 @@
+ >
+ </File>
+ <File
++ RelativePath="..\src\mot\iupmot_draw.c"
++ >
++ </File>
++ <File
+ RelativePath="..\src\mot\iupmot_focus.c"
+ >
+ </File>
+diff --git a/iup/mak.vc9/iupsample.vcproj b/iup/mak.vc9/iupsample.vcproj
+index 144f3ba..0e10bb6 100755
+--- a/iup/mak.vc9/iupsample.vcproj
++++ b/iup/mak.vc9/iupsample.vcproj
+@@ -45,7 +45,7 @@
+ Optimization="0"
+ AdditionalIncludeDirectories="..\include;..\..\cd\include"
+ PreprocessorDefinitions="WIN32;_DEBUG;_WIN32_WINNT=0x0500;_WIN32_IE=0x0500;_CRT_SECURE_NO_DEPRECATE;__IUPDEF_H"
+- ExceptionHandling="0"
++ ExceptionHandling="1"
+ BasicRuntimeChecks="3"
+ RuntimeLibrary="1"
+ UsePrecompiledHeader="0"
+diff --git a/iup/mak.vc9/iupsamplegtk.vcproj b/iup/mak.vc9/iupsamplegtk.vcproj
+index 24da672..485b773 100755
+--- a/iup/mak.vc9/iupsamplegtk.vcproj
++++ b/iup/mak.vc9/iupsamplegtk.vcproj
+@@ -617,7 +617,6 @@
+ >
+ <FileConfiguration
+ Name="Debug|Win32"
+- ExcludedFromBuild="true"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+@@ -785,6 +784,7 @@
+ >
+ <FileConfiguration
+ Name="Debug|Win32"
++ ExcludedFromBuild="true"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+diff --git a/iup/mak.vc9/iuptest.vcproj b/iup/mak.vc9/iuptest.vcproj
+index 213431c..ac8f359 100755
+--- a/iup/mak.vc9/iuptest.vcproj
++++ b/iup/mak.vc9/iuptest.vcproj
+@@ -271,6 +271,10 @@
+ >
+ </File>
+ <File
++ RelativePath="..\test\split.c"
++ >
++ </File>
++ <File
+ RelativePath="..\test\sysinfo.c"
+ >
+ </File>
+diff --git a/iup/mak.vc9/iuptestgtk.vcproj b/iup/mak.vc9/iuptestgtk.vcproj
+index 4cbc9da..d8c092c 100755
+--- a/iup/mak.vc9/iuptestgtk.vcproj
++++ b/iup/mak.vc9/iuptestgtk.vcproj
+@@ -73,6 +73,7 @@
+ LinkIncremental="1"
+ SuppressStartupBanner="true"
+ AdditionalLibraryDirectories="..\lib;d:\lng\gtk\lib;..\..\cd\lib;D:\LNG\vld\lib"
++ GenerateManifest="false"
+ GenerateDebugInformation="true"
+ ProgramDatabaseFile="$(TargetDir)$(TargetName).pdb"
+ SubSystem="1"
+@@ -262,6 +263,10 @@
+ >
+ </File>
+ <File
++ RelativePath="..\test\split.c"
++ >
++ </File>
++ <File
+ RelativePath="..\test\sysinfo.c"
+ >
+ </File>
+diff --git a/iup/mak.vc9/iupwin.vcproj b/iup/mak.vc9/iupwin.vcproj
+index 15578a9..94ef390 100755
+--- a/iup/mak.vc9/iupwin.vcproj
++++ b/iup/mak.vc9/iupwin.vcproj
+@@ -248,6 +248,10 @@
+ >
+ </File>
+ </Filter>
++ <File
++ RelativePath="..\src\iup.def"
++ >
++ </File>
+ </Files>
+ <Globals>
+ </Globals>
+diff --git a/iup/src/Makefile b/iup/src/Makefile
+index 028047f..e666555 100755
+--- a/iup/src/Makefile
++++ b/iup/src/Makefile
+@@ -1,9 +1,12 @@
+ 
+-.PHONY: do_all iup iupgtk
+-do_all: iup iupgtk
++.PHONY: do_all iup iupgtk iupmot
++do_all: iup
+ 
+ iup:
+- @$(MAKE) --no-print-directory -f ../tecmake_compact.mak 
++ @$(MAKE) --no-print-directory -f ../tecmake.mak 
+ 
+ iupgtk:
+- @$(MAKE) --no-print-directory -f ../tecmake_compact.mak USE_GTK=Yes
++ @$(MAKE) --no-print-directory -f ../tecmake.mak USE_GTK=Yes
++
++iupmot:
++ @$(MAKE) --no-print-directory -f ../tecmake.mak USE_MOTIF=Yes
+diff --git a/iup/src/config.mak b/iup/src/config.mak
+index e857643..82b8452 100755
+--- a/iup/src/config.mak
++++ b/iup/src/config.mak
+@@ -2,9 +2,31 @@ PROJNAME = iup
+ LIBNAME = iup
+ OPT = YES
+ 
+-#ifdef DBG
++ifdef GTK_DEFAULT
++ ifdef USE_MOTIF
++ # Build Motif version in Linux,Darwin,FreeBSD
++ LIBNAME = iupmot
++ else
++ ifeq ($(findstring Win, $(TEC_SYSNAME)), )
++ # Force definition if not in Windows
++ USE_GTK = Yes
++ endif
++ endif
++else 
++ ifdef USE_GTK
++ # Build GTK version in IRIX,SunOS,AIX,Win32
++ LIBNAME = iupgtk
++ else
++ ifeq ($(findstring Win, $(TEC_SYSNAME)), )
++ # Force definition if not in Windows
++ USE_MOTIF = Yes
++ endif
++ endif
++endif
++
++ifdef DBG
+ DEFINES += IUP_ASSERT
+-#endif 
++endif 
+ 
+ INCLUDES = ../include .
+ 
+@@ -17,19 +39,14 @@ SRC = iup_array.c iup_callback.c iup_dlglist.c iup_attrib.c iup_focus.c iup_font
+ iup_user.c iup_button.c iup_radio.c iup_toggle.c iup_progressbar.c iup_text.c iup_val.c \
+ iup_box.c iup_hbox.c iup_vbox.c iup_cbox.c iup_class.c iup_classbase.c iup_maskmatch.c \
+ iup_mask.c iup_maskparse.c iup_tabs.c iup_spin.c iup_list.c iup_getparam.c \
+- iup_sbox.c iup_normalizer.c iup_tree.c
++ iup_sbox.c iup_normalizer.c iup_tree.c iup_split.c
+ 
+ ifdef USE_GTK
+- ifndef GTK_DEFAULT
+- # Build GTK version in IRIX,SunOS,AIX,Win32
+- LIBNAME := iupgtk
+- endif
+-
+ DEFINES += GTK_DISABLE_DEPRECATED
+ INCLUDES += gtk
+ SRC += gtk/iupgtk_common.c gtk/iupgtk_focus.c gtk/iupgtk_font.c gtk/iupgtk_clipboard.c \
+ gtk/iupgtk_globalattrib.c gtk/iupgtk_key.c gtk/iupgtk_tips.c \
+- gtk/iupgtk_loop.c gtk/iupgtk_open.c gtk/iupgtk_messagedlg.c \
++ gtk/iupgtk_loop.c gtk/iupgtk_open.c gtk/iupgtk_messagedlg.c gtk/iupgtk_draw.c \
+ gtk/iupgtk_dialog.c gtk/iupgtk_timer.c gtk/iupgtk_image.c gtk/iupgtk_label.c \
+ gtk/iupgtk_colordlg.c gtk/iupgtk_fontdlg.c gtk/iupgtk_filedlg.c \
+ gtk/iupgtk_button.c gtk/iupgtk_toggle.c gtk/iupgtk_progressbar.c \
+@@ -40,7 +57,11 @@ ifdef USE_GTK
+ DEFINES += _WIN32_WINNT=0x0500 _WIN32_IE=0x0500 WINVER=0x0500 NOTREEVIEW
+ SRC += win/iupwindows_main.c win/iupwindows_help.c win/iupwindows_info.c
+ else
+- SRC += gtk/iupgtk_help.c mot/iupunix_info.c
++ ifdef GTK_MAC
++ SRC += gtk/iupmac_help.c gtk/iupmac_info.c
++ else
++ SRC += gtk/iupgtk_help.c mot/iupunix_info.c
++ endif
+ endif
+ 
+ ifdef USE_HILDON
+@@ -49,42 +70,35 @@ ifdef USE_GTK
+ LIBS += hildon-1
+ endif
+ else
+- ifneq ($(findstring Win, $(TEC_SYSNAME)), )
+- 
+- SRC += win/iupwin_common.c win/iupwin_brush.c win/iupwin_focus.c win/iupwin_font.c \
+- win/iupwin_globalattrib.c win/iupwin_handle.c win/iupwin_key.c \
+- win/iupwin_loop.c win/iupwin_open.c win/iupwin_tips.c win/iupwin_info.c \
+- win/iupwin_dialog.c win/iupwin_messagedlg.c win/iupwin_timer.c \
+- win/iupwin_image.c win/iupwin_label.c win/iupwin_canvas.c win/iupwin_frame.c \
+- win/iupwin_colordlg.c win/iupwin_fontdlg.c win/iupwin_filedlg.c \
+- win/iupwin_button.c win/iupwin_draw.c win/iupwin_toggle.c win/iupwin_clipboard.c \
+- win/iupwin_progressbar.c win/iupwin_text.c win/iupwin_val.c \
+- win/iupwin_tabs.c win/iupwin_menu.c win/iupwin_list.c win/iupwin_tree.c
+- 
+- SRC += win/iupwindows_main.c win/iupwindows_help.c win/iupwindows_info.c
+- 
+- INCLUDES += win
+- DEFINES += _WIN32_WINNT=0x0500 _WIN32_IE=0x0500 WINVER=0x0500 NOTREEVIEW
+- else
+- ifdef GTK_DEFAULT
+- # Build Motif version in Linux,Darwin,FreeBSD
+- LIBNAME := iupmot
+- endif 
+- 
+- SRC += mot/iupmot_common.c mot/iupmot_color.c mot/iupmot_focus.c mot/iupmot_font.c \
+- mot/iupmot_key.c mot/iupmot_loop.c mot/iupmot_open.c mot/iupmot_tips.c \
+- mot/iupmot_globalattrib.c mot/iupmot_dialog.c mot/iupmot_messagedlg.c \
+- mot/iupmot_timer.c mot/iupmot_image.c mot/iupmot_label.c mot/iupmot_canvas.c \
+- mot/iupmot_colordlg.c mot/iupmot_fontdlg.c mot/iupmot_filedlg.c mot/iupmot_frame.c \
+- mot/iupmot_button.c mot/iupmot_toggle.c mot/iupmot_progressbar.c mot/iupmot_clipboard.c \
+- mot/iupmot_text.c mot/iupmot_val.c mot/iupmot_tabs.c mot/iupmot_menu.c \
+- mot/iupmot_list.c mot/iupmot_tree.c
+- 
+- SRC += mot/iupunix_help.c mot/iupunix_info.c
+- 
+- INCLUDES += mot
+- USE_MOTIF=Yes 
+- endif
++ifdef USE_MOTIF
++ SRC += mot/iupmot_common.c mot/iupmot_color.c mot/iupmot_focus.c mot/iupmot_font.c \
++ mot/iupmot_key.c mot/iupmot_loop.c mot/iupmot_open.c mot/iupmot_tips.c \
++ mot/iupmot_globalattrib.c mot/iupmot_dialog.c mot/iupmot_messagedlg.c mot/iupmot_draw.c \
++ mot/iupmot_timer.c mot/iupmot_image.c mot/iupmot_label.c mot/iupmot_canvas.c \
++ mot/iupmot_colordlg.c mot/iupmot_fontdlg.c mot/iupmot_filedlg.c mot/iupmot_frame.c \
++ mot/iupmot_button.c mot/iupmot_toggle.c mot/iupmot_progressbar.c mot/iupmot_clipboard.c \
++ mot/iupmot_text.c mot/iupmot_val.c mot/iupmot_tabs.c mot/iupmot_menu.c \
++ mot/iupmot_list.c mot/iupmot_tree.c
++ 
++ SRC += mot/iupunix_help.c mot/iupunix_info.c
++
++ INCLUDES += mot
++else
++ SRC += win/iupwin_common.c win/iupwin_brush.c win/iupwin_focus.c win/iupwin_font.c \
++ win/iupwin_globalattrib.c win/iupwin_handle.c win/iupwin_key.c \
++ win/iupwin_loop.c win/iupwin_open.c win/iupwin_tips.c win/iupwin_info.c \
++ win/iupwin_dialog.c win/iupwin_messagedlg.c win/iupwin_timer.c \
++ win/iupwin_image.c win/iupwin_label.c win/iupwin_canvas.c win/iupwin_frame.c \
++ win/iupwin_colordlg.c win/iupwin_fontdlg.c win/iupwin_filedlg.c \
++ win/iupwin_button.c win/iupwin_draw.c win/iupwin_toggle.c win/iupwin_clipboard.c \
++ win/iupwin_progressbar.c win/iupwin_text.c win/iupwin_val.c \
++ win/iupwin_tabs.c win/iupwin_menu.c win/iupwin_list.c win/iupwin_tree.c
++ 
++ SRC += win/iupwindows_main.c win/iupwindows_help.c win/iupwindows_info.c
++
++ INCLUDES += win
++ DEFINES += _WIN32_WINNT=0x0500 _WIN32_IE=0x0500 WINVER=0x0500 NOTREEVIEW
++endif
+ endif
+ 
+ ifeq "$(TEC_SYSNAME)" "SunOS"
+@@ -113,6 +127,6 @@ ifeq "$(TEC_UNAME)" "dll"
+ endif
+ 
+ ifeq "$(TEC_UNAME)" "owc1"
+- # Necessary or IUP will not work in Open Watcom
++ # Necessary or IUP 3 will not work in Open Watcom
+ DBG=Yes
+ endif
+diff --git a/iup/src/gtk/iupgtk_button.c b/iup/src/gtk/iupgtk_button.c
+index 18be87c..f8474ae 100755
+--- a/iup/src/gtk/iupgtk_button.c
++++ b/iup/src/gtk/iupgtk_button.c
+@@ -150,8 +150,10 @@ static int gtkButtonSetPaddingAttrib(Ihandle* ih, const char* value)
+ gtk_alignment_set_padding(alignment, ih->data->vert_padding, ih->data->vert_padding, 
+ ih->data->horiz_padding, ih->data->horiz_padding);
+ }
++ return 0;
+ }
+- return 0;
++ else
++ return 1; /* store until not mapped, when mapped will be set again */
+ }
+ 
+ #ifdef WIN32
+@@ -366,12 +368,12 @@ static int gtkButtonMapMethod(Ihandle* ih)
+ ih->data->type = IUP_BUTTON_IMAGE;
+ 
+ value = iupAttribGet(ih, "TITLE");
+- if (value)
++ if (value && *value!=0)
+ {
+ GtkSettings* settings = gtk_widget_get_settings(ih->handle);
+ g_object_set(settings, "gtk-button-images", (int)TRUE, NULL);
+ 
+- gtk_button_set_label((GtkButton*)ih->handle, value);
++ gtk_button_set_label((GtkButton*)ih->handle, iupgtkStrConvertToUTF8(value));
+ ih->data->type |= IUP_BUTTON_TEXT;
+ 
+ #if GTK_CHECK_VERSION(2, 10, 0)
+@@ -397,7 +399,7 @@ static int gtkButtonMapMethod(Ihandle* ih)
+ #endif
+ }
+ else
+- gtk_button_set_label((GtkButton*)ih->handle, title);
++ gtk_button_set_label((GtkButton*)ih->handle, iupgtkStrConvertToUTF8(title));
+ ih->data->type = IUP_BUTTON_TEXT;
+ }
+ 
+diff --git a/iup/src/gtk/iupgtk_canvas.c b/iup/src/gtk/iupgtk_canvas.c
+index daae4ad..3af48a4 100755
+--- a/iup/src/gtk/iupgtk_canvas.c
++++ b/iup/src/gtk/iupgtk_canvas.c
+@@ -537,8 +537,8 @@ static int gtkCanvasMapMethod(Ihandle* ih)
+ 
+ /* To receive mouse events on a drawing area, you will need to enable them. */
+ gtk_widget_add_events(ih->handle, GDK_EXPOSURE_MASK|
+- GDK_POINTER_MOTION_MASK|GDK_BUTTON_MOTION_MASK|
+- GDK_BUTTON_PRESS_MASK|GDK_BUTTON_RELEASE_MASK|
++ GDK_POINTER_MOTION_MASK|GDK_POINTER_MOTION_HINT_MASK|
++ GDK_BUTTON_PRESS_MASK|GDK_BUTTON_RELEASE_MASK|GDK_BUTTON_MOTION_MASK|
+ GDK_KEY_PRESS_MASK|GDK_KEY_RELEASE_MASK|
+ GDK_ENTER_NOTIFY_MASK|GDK_LEAVE_NOTIFY_MASK|
+ GDK_FOCUS_CHANGE_MASK|GDK_STRUCTURE_MASK);
+@@ -611,14 +611,15 @@ void iupdrvCanvasInitClass(Iclass* ic)
+ iupClassRegisterAttribute(ic, "YAUTOHIDE", NULL, gtkCanvasSetYAutoHideAttrib, "YES", NULL, IUPAF_DEFAULT); /* force new default value */
+ 
+ iupClassRegisterAttribute(ic, "DRAWABLE", gtkCanvasGetDrawableAttrib, NULL, NULL, NULL, IUPAF_NO_STRING);
+- //iupClassRegisterAttribute(ic, "CD_GDK", NULL, NULL, IUPAF_SAMEASSYSTEM, "YES", IUPAF_NO_INHERIT);
+ 
+ /* IupCanvas Windows or X only */
+-#ifdef WIN32 
+- iupClassRegisterAttribute(ic, "HWND", iupgtkGetNativeWindowHandle, NULL, NULL, NULL, IUPAF_NO_STRING|IUPAF_NO_INHERIT);
+-#else
+- iupClassRegisterAttribute(ic, "XWINDOW", iupgtkGetNativeWindowHandle, NULL, NULL, NULL, IUPAF_NO_INHERIT|IUPAF_NO_STRING);
+- iupClassRegisterAttribute(ic, "XDISPLAY", (IattribGetFunc)iupdrvGetDisplay, NULL, NULL, NULL, IUPAF_READONLY|IUPAF_NOT_MAPPED|IUPAF_NO_INHERIT|IUPAF_NO_STRING);
++#ifndef GTK_MAC
++ #ifdef WIN32 
++ iupClassRegisterAttribute(ic, "HWND", iupgtkGetNativeWindowHandle, NULL, NULL, NULL, IUPAF_NO_STRING|IUPAF_NO_INHERIT);
++ #else
++ iupClassRegisterAttribute(ic, "XWINDOW", iupgtkGetNativeWindowHandle, NULL, NULL, NULL, IUPAF_NO_INHERIT|IUPAF_NO_STRING);
++ iupClassRegisterAttribute(ic, "XDISPLAY", (IattribGetFunc)iupdrvGetDisplay, NULL, NULL, NULL, IUPAF_READONLY|IUPAF_NOT_MAPPED|IUPAF_NO_INHERIT|IUPAF_NO_STRING);
++ #endif
+ #endif
+ }
+ 
+diff --git a/iup/src/gtk/iupgtk_common.c b/iup/src/gtk/iupgtk_common.c
+index 40368f2..d84c1c8 100755
+--- a/iup/src/gtk/iupgtk_common.c
++++ b/iup/src/gtk/iupgtk_common.c
+@@ -91,13 +91,13 @@ void iupdrvBaseUnMapMethod(Ihandle* ih)
+ gtk_widget_destroy(widget); /* To match the call to gtk_*****_new */
+ }
+ 
+-void iupdrvDisplayUpdate(Ihandle *ih)
++void iupdrvPostRedraw(Ihandle *ih)
+ {
+ /* Post a REDRAW */
+ gtk_widget_queue_draw(ih->handle);
+ }
+ 
+-void iupdrvDisplayRedraw(Ihandle *ih)
++void iupdrvRedrawNow(Ihandle *ih)
+ {
+ GdkWindow* window = ih->handle->window;
+ /* Post a REDRAW */
+@@ -202,7 +202,11 @@ void iupdrvSetVisible(Ihandle* ih, int visible)
+ 
+ int iupdrvIsVisible(Ihandle* ih)
+ {
++#if GTK_CHECK_VERSION(2, 18, 0)
++ if (gtk_widget_get_visible(ih->handle))
++#else
+ if (GTK_WIDGET_VISIBLE(ih->handle))
++#endif
+ {
+ /* if marked as visible, since we use gtk_widget_hide and NOT gtk_widget_hide_all
+ must check its parents. */
+@@ -211,7 +215,11 @@ int iupdrvIsVisible(Ihandle* ih)
+ {
+ if (parent->iclass->nativetype != IUP_TYPEVOID)
+ {
++#if GTK_CHECK_VERSION(2, 18, 0)
++ if (!gtk_widget_get_visible(parent->handle))
++#else
+ if (!GTK_WIDGET_VISIBLE(parent->handle))
++#endif
+ return 0;
+ }
+ 
+@@ -225,7 +233,11 @@ int iupdrvIsVisible(Ihandle* ih)
+ 
+ int iupdrvIsActive(Ihandle *ih)
+ {
+- return (GTK_WIDGET_IS_SENSITIVE(ih->handle));
++#if GTK_CHECK_VERSION(2, 18, 0)
++ return gtk_widget_is_sensitive(ih->handle);
++#else
++ return GTK_WIDGET_IS_SENSITIVE(ih->handle);
++#endif
+ }
+ 
+ void iupdrvSetActive(Ihandle* ih, int enable)
+@@ -424,9 +436,11 @@ static GdkCursor* gtkGetCursor(Ihandle* ih, const char* name)
+ { "RESIZE_N", GDK_TOP_SIDE},
+ { "RESIZE_S", GDK_BOTTOM_SIDE},
+ { "RESIZE_NS", GDK_SB_V_DOUBLE_ARROW},
++ { "SPLITTER_HORIZ", GDK_SB_V_DOUBLE_ARROW},
+ { "RESIZE_W", GDK_LEFT_SIDE},
+ { "RESIZE_E", GDK_RIGHT_SIDE},
+ { "RESIZE_WE", GDK_SB_H_DOUBLE_ARROW},
++ { "SPLITTER_VERT", GDK_SB_H_DOUBLE_ARROW},
+ { "RESIZE_NE", GDK_TOP_RIGHT_CORNER},
+ { "RESIZE_SE", GDK_BOTTOM_RIGHT_CORNER},
+ { "RESIZE_NW", GDK_TOP_LEFT_CORNER},
+@@ -571,18 +585,24 @@ void iupdrvDrawFocusRect(Ihandle* ih, void* _gc, int x, int y, int w, int h)
+ {
+ GdkWindow* window = ih->handle->window;
+ GtkStyle *style = gtk_widget_get_style(ih->handle);
++#if GTK_CHECK_VERSION(2, 18, 0)
++ GtkStateType state = gtk_widget_get_state(ih->handle);
++#else
++ GtkStateType state = GTK_WIDGET_STATE(ih->handle);
++#endif
++ gtk_paint_focus(style, window, state, NULL, ih->handle, NULL, x, y, w, h);
+ (void)_gc;
+-
+- gtk_paint_focus(style, window, GTK_WIDGET_STATE(ih->handle), NULL, ih->handle, NULL, x, y, w, h);
+ }
+ 
+ void iupdrvBaseRegisterCommonAttrib(Iclass* ic)
+ {
++#ifndef GTK_MAC
+ #ifdef WIN32 
+ iupClassRegisterAttribute(ic, "HFONT", iupgtkGetFontIdAttrib, NULL, NULL, NULL, IUPAF_NOT_MAPPED|IUPAF_NO_INHERIT|IUPAF_NO_STRING);
+ #else
+ iupClassRegisterAttribute(ic, "XFONTID", iupgtkGetFontIdAttrib, NULL, NULL, NULL, IUPAF_NOT_MAPPED|IUPAF_NO_INHERIT|IUPAF_NO_STRING);
+ #endif
++#endif
+ iupClassRegisterAttribute(ic, "PANGOFONTDESC", iupgtkGetPangoFontDescAttrib, NULL, NULL, NULL, IUPAF_NOT_MAPPED|IUPAF_NO_INHERIT|IUPAF_NO_STRING);
+ }
+ 
+@@ -789,7 +809,17 @@ char* iupgtkStrConvertFromFilename(const char* str) /* From Filename to IUP */
+ 
+ gboolean iupgtkMotionNotifyEvent(GtkWidget *widget, GdkEventMotion *evt, Ihandle *ih)
+ {
+- IFniis cb = (IFniis)IupGetCallback(ih,"MOTION_CB");
++ IFniis cb;
++
++ if (evt->is_hint)
++ {
++ int x, y;
++ gdk_window_get_pointer(widget->window, &x, &y, NULL);
++ evt->x = x;
++ evt->y = y;
++ }
++
++ cb = (IFniis)IupGetCallback(ih,"MOTION_CB");
+ if (cb)
+ {
+ char status[IUPKEY_STATUS_SIZE] = IUPKEY_STATUS_INIT;
+@@ -818,6 +848,23 @@ gboolean iupgtkButtonEvent(GtkWidget *widget, GdkEventButton *evt, Ihandle *ih)
+ 
+ iupgtkButtonKeySetStatus(evt->state, evt->button, status, doubleclick);
+ 
++ if (doubleclick)
++ {
++ /* Must compensate the fact that in GTK there is an extra button press event 
++ when occours a double click, we compensate that completing the event 
++ with a button release before the double click. */
++
++ status[5] = ' '; /* clear double click */
++
++ ret = cb(ih, b, 0, (int)evt->x, (int)evt->y, status); /* release */
++ if (ret==IUP_CLOSE)
++ IupExitLoop();
++ else if (ret==IUP_IGNORE)
++ return TRUE;
++
++ status[5] = 'D'; /* restore double click */
++ }
++
+ ret = cb(ih, b, press, (int)evt->x, (int)evt->y, status);
+ if (ret==IUP_CLOSE)
+ IupExitLoop();
+diff --git a/iup/src/gtk/iupgtk_dialog.c b/iup/src/gtk/iupgtk_dialog.c
+index 46c0ce1..ff0d8f2 100755
+--- a/iup/src/gtk/iupgtk_dialog.c
++++ b/iup/src/gtk/iupgtk_dialog.c
+@@ -120,12 +120,13 @@ void iupdrvDialogGetDecoration(Ihandle* ih, int *border, int *caption, int *menu
+ static int native_border = 0;
+ static int native_caption = 0;
+ 
+- int has_caption = iupAttribGetBoolean(ih, "MAXBOX") ||
+- iupAttribGetBoolean(ih, "MINBOX") ||
+- iupAttribGetBoolean(ih, "MENUBOX") || 
+- IupGetAttribute(ih, "TITLE"); /* must use IupGetAttribute to check from the native implementation */
++ int has_titlebar = iupAttribGetBoolean(ih, "RESIZE") || /* GTK and Motif only */
++ iupAttribGetBoolean(ih, "MAXBOX") ||
++ iupAttribGetBoolean(ih, "MINBOX") ||
++ iupAttribGetBoolean(ih, "MENUBOX") || 
++ IupGetAttribute(ih, "TITLE"); /* must use IupGetAttribute to check from the native implementation */
+ 
+- int has_border = has_caption ||
++ int has_border = has_titlebar ||
+ iupAttribGetBoolean(ih, "RESIZE") ||
+ iupAttribGetBoolean(ih, "BORDER");
+ 
+@@ -147,7 +148,7 @@ void iupdrvDialogGetDecoration(Ihandle* ih, int *border, int *caption, int *menu
+ *border = win_border;
+ 
+ *caption = 0;
+- if (has_caption)
++ if (has_titlebar)
+ *caption = win_caption;
+ 
+ if (!native_border && *border)
+@@ -171,7 +172,7 @@ void iupdrvDialogGetDecoration(Ihandle* ih, int *border, int *caption, int *menu
+ }
+ 
+ *caption = 0;
+- if (has_caption)
++ if (has_titlebar)
+ {
+ if (native_caption)
+ *caption = native_caption;
+@@ -429,6 +430,7 @@ static int gtkDialogMapMethod(Ihandle* ih)
+ int functions = 0;
+ InativeHandle* parent;
+ GtkWidget* fixed;
++ int has_titlebar = 0;
+ 
+ #ifdef HILDON
+ if (iupAttribGetBoolean(ih, "HILDONWINDOW")) 
+@@ -494,33 +496,41 @@ static int gtkDialogMapMethod(Ihandle* ih)
+ iupAttribSetStr(ih, "MINBOX", "NO");
+ }
+ 
+- if (IupGetAttribute(ih, "TITLE")) { /* must use IupGetAttribute to check from the native implementation */
+- functions |= GDK_FUNC_MOVE;
+- decorations |= GDK_DECOR_TITLE;
+- }
+-
+- if (iupAttribGetBoolean(ih, "MENUBOX")) {
++ if (iupAttribGet(ih, "TITLE"))
++ has_titlebar = 1;
++ if (iupAttribGetBoolean(ih, "MENUBOX")) 
++ {
+ functions |= GDK_FUNC_CLOSE;
+ decorations |= GDK_DECOR_MENU;
++ has_titlebar = 1;
+ }
+-
+- if (iupAttribGetBoolean(ih, "MINBOX")) {
++ if (iupAttribGetBoolean(ih, "MINBOX")) 
++ {
+ functions |= GDK_FUNC_MINIMIZE;
+ decorations |= GDK_DECOR_MINIMIZE;
++ has_titlebar = 1;
+ }
+-
+- if (iupAttribGetBoolean(ih, "MAXBOX")) {
++ if (iupAttribGetBoolean(ih, "MAXBOX")) 
++ {
+ functions |= GDK_FUNC_MAXIMIZE;
+ decorations |= GDK_DECOR_MAXIMIZE;
++ has_titlebar = 1;
+ }
+-
+- if (iupAttribGetBoolean(ih, "RESIZE")) {
++ if (iupAttribGetBoolean(ih, "RESIZE")) 
++ {
+ functions |= GDK_FUNC_RESIZE;
+ decorations |= GDK_DECOR_RESIZEH;
+- }
+ 
+- if (iupAttribGetBoolean(ih, "BORDER"))
+- decorations |= GDK_DECOR_BORDER;
++ decorations |= GDK_DECOR_BORDER; /* has_border */
++ }
++ if (has_titlebar)
++ {
++ functions |= GDK_FUNC_MOVE;
++ decorations |= GDK_DECOR_TITLE;
++ gtk_window_set_title((GtkWindow*)ih->handle, "");
++ }
++ if (iupAttribGetBoolean(ih, "BORDER") || has_titlebar)
++ decorations |= GDK_DECOR_BORDER; /* has_border */
+ 
+ if (decorations == 0)
+ gtk_window_set_decorated((GtkWindow*)ih->handle, FALSE);
+@@ -980,11 +990,12 @@ void iupdrvDialogInitClass(Iclass* ic)
+ iupClassRegisterCallback(ic, "TRAYCLICK_CB", "iii");
+ 
+ /* Driver Dependent Attribute functions */
+-
+-#ifdef WIN32 
+- iupClassRegisterAttribute(ic, "HWND", iupgtkGetNativeWindowHandle, NULL, NULL, NULL, IUPAF_NO_STRING|IUPAF_NO_INHERIT);
+-#else
+- iupClassRegisterAttribute(ic, "XWINDOW", iupgtkGetNativeWindowHandle, NULL, NULL, NULL, IUPAF_NO_INHERIT|IUPAF_NO_STRING);
++#ifndef GTK_MAC
++ #ifdef WIN32 
++ iupClassRegisterAttribute(ic, "HWND", iupgtkGetNativeWindowHandle, NULL, NULL, NULL, IUPAF_NO_STRING|IUPAF_NO_INHERIT);
++ #else
++ iupClassRegisterAttribute(ic, "XWINDOW", iupgtkGetNativeWindowHandle, NULL, NULL, NULL, IUPAF_NO_INHERIT|IUPAF_NO_STRING);
++ #endif
+ #endif
+ 
+ /* Visual */
+diff --git a/iup/src/gtk/iupgtk_drv.h b/iup/src/gtk/iupgtk_drv.h
+index ade2a4a..bf567d6 100755
+--- a/iup/src/gtk/iupgtk_drv.h
++++ b/iup/src/gtk/iupgtk_drv.h
+@@ -59,8 +59,8 @@ void iupgtkFontUpdateObjectPangoLayout(Ihandle* ih, gpointer object);
+ /* There are PANGO_SCALE Pango units in one device unit. 
+ For an output backend where a device unit is a pixel, 
+ a size value of 10 * PANGO_SCALE gives 10 pixels. */
+-#define IUPGTK_PANGOUNITS2PIXELS(_x) (((_x) + PANGO_SCALE/2) / PANGO_SCALE)
+-#define IUPGTK_PIXELS2PANGOUNITS(_x) ((_x) * PANGO_SCALE)
++#define iupGTK_PANGOUNITS2PIXELS(_x) (((_x) + PANGO_SCALE/2) / PANGO_SCALE)
++#define iupGTK_PIXELS2PANGOUNITS(_x) ((_x) * PANGO_SCALE)
+ 
+ 
+ /* open */
+diff --git a/iup/src/gtk/iupgtk_filedlg.c b/iup/src/gtk/iupgtk_filedlg.c
+index 5426910..a326c72 100755
+--- a/iup/src/gtk/iupgtk_filedlg.c
++++ b/iup/src/gtk/iupgtk_filedlg.c
+@@ -77,6 +77,8 @@ static void gtkFileDlgGetMultipleFiles(Ihandle* ih, GSList* list)
+ cur_len = iupArrayCount(names_array);
+ all_names = iupArrayAdd(names_array, dir_len+1);
+ memcpy(all_names+cur_len, filename, dir_len);
++ all_names[cur_len+dir_len] = '0';
++ iupAttribStoreStr(ih, "DIRECTORY", all_names);
+ all_names[cur_len+dir_len] = '|';
+ 
+ dir_len++; /* skip separator */
+@@ -101,10 +103,14 @@ static void gtkFileDlgGetMultipleFiles(Ihandle* ih, GSList* list)
+ iupArrayDestroy(names_array);
+ }
+ 
+-#ifdef WIN32
+-#include <gdk/gdkwin32.h>
++#ifdef GTK_MAC
++ #include <gdk/gdk.h>
+ #else
+-#include <gdk/gdkx.h>
++ #ifdef WIN32
++ #include <gdk/gdkwin32.h>
++ #else
++ #include <gdk/gdkx.h>
++ #endif
+ #endif
+ 
+ static void gtkFileDlgUpdatePreviewGLCanvas(Ihandle* ih)
+@@ -112,10 +118,12 @@ static void gtkFileDlgUpdatePreviewGLCanvas(Ihandle* ih)
+ Ihandle* glcanvas = IupGetAttributeHandle(ih, "PREVIEWGLCANVAS");
+ if (glcanvas)
+ {
+-#ifdef WIN32 
+- iupAttribSetStr(glcanvas, "HWND", iupAttribGet(ih, "HWND"));
+-#else
+- iupAttribSetStr(glcanvas, "XWINDOW", iupAttribGet(ih, "XWINDOW"));
++#ifndef GTK_MAC
++ #ifdef WIN32 
++ iupAttribSetStr(glcanvas, "HWND", iupAttribGet(ih, "HWND"));
++ #else
++ iupAttribSetStr(glcanvas, "XWINDOW", iupAttribGet(ih, "XWINDOW"));
++ #endif
+ #endif
+ glcanvas->iclass->Map(glcanvas);
+ }
+@@ -126,12 +134,15 @@ static void gtkFileDlgPreviewRealize(GtkWidget *widget, Ihandle *ih)
+ iupAttribSetStr(ih, "PREVIEWDC", iupgtkGetNativeGraphicsContext(widget));
+ iupAttribSetStr(ih, "WID", (char*)widget);
+ 
+-#ifdef WIN32 
+- iupAttribSetStr(ih, "HWND", (char*)GDK_WINDOW_HWND(widget->window));
+-#else
+- iupAttribSetStr(ih, "XWINDOW", (char*)GDK_WINDOW_XID(widget->window));
+- iupAttribSetStr(ih, "XDISPLAY", (char*)iupdrvGetDisplay());
++#ifndef GTK_MAC
++ #ifdef WIN32 
++ iupAttribSetStr(ih, "HWND", (char*)GDK_WINDOW_HWND(widget->window));
++ #else
++ iupAttribSetStr(ih, "XWINDOW", (char*)GDK_WINDOW_XID(widget->window));
++ iupAttribSetStr(ih, "XDISPLAY", (char*)iupdrvGetDisplay());
++ #endif
+ #endif
++
+ gtkFileDlgUpdatePreviewGLCanvas(ih);
+ }
+ 
+@@ -174,11 +185,11 @@ static void gtkFileDlgUpdatePreview(GtkFileChooser *file_chooser, Ihandle* ih)
+ {
+ char *filename = gtk_file_chooser_get_preview_filename(file_chooser);
+ 
++ IFnss cb = (IFnss)IupGetCallback(ih, "FILE_CB");
+ if (iupdrvIsFile(filename))
+- {
+- IFnss cb = (IFnss)IupGetCallback(ih, "FILE_CB");
+ cb(ih, iupgtkStrConvertFromFilename(filename), "SELECT");
+- }
++ else
++ cb(ih, iupgtkStrConvertFromFilename(filename), "OTHER");
+ 
+ g_free (filename);
+ 
+@@ -469,6 +480,13 @@ static int gtkFileDlgPopup(Ihandle* ih, int x, int y)
+ char* filename = (char*)file_list->data;
+ iupAttribStoreStr(ih, "VALUE", iupgtkStrConvertFromFilename(filename));
+ g_free(filename);
++
++ /* store the DIRECTORY */
++ {
++ char* dir = iupStrFileGetPath(iupAttribGet(ih, "VALUE"));
++ iupAttribStoreStr(ih, "DIRECTORY", dir);
++ free(dir);
++ }
+ }
+ 
+ g_slist_free(file_list);
+@@ -481,6 +499,14 @@ static int gtkFileDlgPopup(Ihandle* ih, int x, int y)
+ iupAttribStoreStr(ih, "VALUE", iupgtkStrConvertFromFilename(filename));
+ file_exist = iupdrvIsFile(filename);
+ dir_exist = iupdrvIsDirectory(filename);
++
++ if (file_exist)
++ {
++ char* dir = iupStrFileGetPath(filename);
++ iupAttribStoreStr(ih, "DIRECTORY", dir);
++ free(dir);
++ }
++
+ g_free(filename);
+ }
+ 
+@@ -507,8 +533,11 @@ static int gtkFileDlgPopup(Ihandle* ih, int x, int y)
+ {
+ /* GtkFileChooser does not change the current directory */
+ char* dir = gtk_file_chooser_get_current_folder(GTK_FILE_CHOOSER(dialog));
+- if (dir) iupdrvSetCurrentDirectory(dir);
+- g_free(dir);
++ if (dir) 
++ {
++ iupdrvSetCurrentDirectory(dir);
++ g_free(dir);
++ }
+ }
+ }
+ else
+diff --git a/iup/src/gtk/iupgtk_font.c b/iup/src/gtk/iupgtk_font.c
+index f7ff348..1139f62 100755
+--- a/iup/src/gtk/iupgtk_font.c
++++ b/iup/src/gtk/iupgtk_font.c
+@@ -132,9 +132,9 @@ static IgtkFont* gtkFindFont(const char *standardfont)
+ 
+ metrics = pango_context_get_metrics(gtk_fonts_context, fontdesc, pango_context_get_language(gtk_fonts_context));
+ fonts[i].charheight = pango_font_metrics_get_ascent(metrics) + pango_font_metrics_get_descent(metrics);
+- fonts[i].charheight = IUPGTK_PANGOUNITS2PIXELS(fonts[i].charheight);
++ fonts[i].charheight = iupGTK_PANGOUNITS2PIXELS(fonts[i].charheight);
+ fonts[i].charwidth = pango_font_metrics_get_approximate_char_width(metrics);
+- fonts[i].charwidth = IUPGTK_PANGOUNITS2PIXELS(fonts[i].charwidth);
++ fonts[i].charwidth = iupGTK_PANGOUNITS2PIXELS(fonts[i].charwidth);
+ pango_font_metrics_unref(metrics); 
+ 
+ gtkFontUpdate(&(fonts[i]));
+diff --git a/iup/src/gtk/iupgtk_fontdlg.c b/iup/src/gtk/iupgtk_fontdlg.c
+index 5769cbc..dca0232 100755
+--- a/iup/src/gtk/iupgtk_fontdlg.c
++++ b/iup/src/gtk/iupgtk_fontdlg.c
+@@ -24,7 +24,7 @@ static int gtkFontDlgPopup(Ihandle* ih, int x, int y)
+ InativeHandle* parent = iupDialogGetNativeParent(ih);
+ GtkFontSelectionDialog* dialog;
+ int response;
+- char* preview_text;
++ char* preview_text, *standardfont;
+ 
+ iupAttribSetInt(ih, "_IUPDLG_X", x); /* used in iupDialogUpdatePosition */
+ iupAttribSetInt(ih, "_IUPDLG_Y", y);
+@@ -36,7 +36,10 @@ static int gtkFontDlgPopup(Ihandle* ih, int x, int y)
+ if (parent)
+ gtk_window_set_transient_for((GtkWindow*)dialog, (GtkWindow*)parent);
+ 
+- gtk_font_selection_dialog_set_font_name(dialog, iupAttribGet(ih, "VALUE"));
++ standardfont = iupAttribGet(ih, "VALUE");
++ if (!standardfont)
++ standardfont = IupGetGlobal("DEFAULTFONT");
++ gtk_font_selection_dialog_set_font_name(dialog, standardfont);
+ 
+ preview_text = iupAttribGet(ih, "PREVIEWTEXT");
+ if (preview_text)
+diff --git a/iup/src/gtk/iupgtk_frame.c b/iup/src/gtk/iupgtk_frame.c
+index 022c6c7..25595be 100755
+--- a/iup/src/gtk/iupgtk_frame.c
++++ b/iup/src/gtk/iupgtk_frame.c
+@@ -41,8 +41,11 @@ static char* gtkFrameGetTitleAttrib(Ihandle* ih)
+ 
+ static int gtkFrameSetTitleAttrib(Ihandle* ih, const char* value)
+ {
+- GtkFrame* frame = (GtkFrame*)ih->handle;
+- gtk_frame_set_label(frame, iupgtkStrConvertToUTF8(value));
++ if (iupAttribGetStr(ih, "_IUPFRAME_HAS_TITLE"))
++ {
++ GtkFrame* frame = (GtkFrame*)ih->handle;
++ gtk_frame_set_label(frame, iupgtkStrConvertToUTF8(value));
++ }
+ return 0;
+ }
+ 
+@@ -57,7 +60,11 @@ static int gtkFrameSetBgColorAttrib(Ihandle* ih, const char* value)
+ if (label)
+ iupgtkBaseSetBgColor(label, r, g, b);
+ 
+- iupgtkBaseSetBgColor(ih->handle, r, g, b);
++ if (iupAttribGet(ih, "_IUPFRAME_HAS_BGCOLOR"))
++ {
++ GtkWidget* fixed = gtk_bin_get_child((GtkBin*)ih->handle);
++ iupgtkBaseSetBgColor(fixed, r, g, b);
++ }
+ 
+ return 1;
+ }
+@@ -120,10 +127,19 @@ static int gtkFrameMapMethod(Ihandle* ih)
+ gtk_frame_set_shadow_type((GtkFrame*)ih->handle, GTK_SHADOW_IN);
+ else
+ gtk_frame_set_shadow_type((GtkFrame*)ih->handle, GTK_SHADOW_ETCHED_IN);
++
++ if (iupAttribGet(ih, "BGCOLOR"))
++ iupAttribSetStr(ih, "_IUPFRAME_HAS_BGCOLOR", "1");
+ }
+ 
+ /* the container that will receive the child element. */
+ fixed = gtk_fixed_new();
++ if (iupAttribGet(ih, "_IUPFRAME_HAS_BGCOLOR"))
++#if GTK_CHECK_VERSION(2, 18, 0)
++ gtk_widget_set_has_window(fixed, TRUE);
++#else
++ gtk_fixed_set_has_window((GtkFixed*)fixed, TRUE);
++#endif
+ gtk_container_add((GtkContainer*)ih->handle, fixed);
+ gtk_widget_show(fixed);
+ 
+diff --git a/iup/src/gtk/iupgtk_key.c b/iup/src/gtk/iupgtk_key.c
+index 5aec919..ed485a7 100755
+--- a/iup/src/gtk/iupgtk_key.c
++++ b/iup/src/gtk/iupgtk_key.c
+@@ -316,9 +316,9 @@ gboolean iupgtkKeyPressEvent(GtkWidget *widget, GdkEventKey *evt, Ihandle *ih)
+ if (code == 0) 
+ return FALSE;
+ 
+- /* Avoid duplicate calls if a child of the dialog contains the focus.
+- GTK will call the callback for the child and for the dialog */
+- if (ih->iclass->nativetype == IUP_TYPEDIALOG && ih != IupGetFocus())
++ /* Avoid duplicate calls if a child of a native container contains the focus.
++ GTK will call the callback for the child and for the container. */
++ if (ih->iclass->childtype != IUP_CHILDNONE && ih != IupGetFocus())
+ return FALSE;
+ 
+ result = iupKeyCallKeyCb(ih, code);
+@@ -390,33 +390,33 @@ gboolean iupgtkKeyReleaseEvent(GtkWidget *widget, GdkEventKey *evt, Ihandle *ih)
+ void iupgtkButtonKeySetStatus(guint state, unsigned int but, char* status, int doubleclick)
+ {
+ if (state & GDK_SHIFT_MASK)
+- iupKEYSETSHIFT(status);
++ iupKEY_SETSHIFT(status);
+ 
+ if (state & GDK_CONTROL_MASK)
+- iupKEYSETCONTROL(status); 
++ iupKEY_SETCONTROL(status); 
+ 
+ if ((state & GDK_BUTTON1_MASK) || but==1)
+- iupKEYSETBUTTON1(status);
++ iupKEY_SETBUTTON1(status);
+ 
+ if ((state & GDK_BUTTON2_MASK) || but==2)
+- iupKEYSETBUTTON2(status);
++ iupKEY_SETBUTTON2(status);
+ 
+ if ((state & GDK_BUTTON3_MASK) || but==3)
+- iupKEYSETBUTTON3(status);
++ iupKEY_SETBUTTON3(status);
+ 
+ if ((state & GDK_BUTTON4_MASK) || but==4)
+- iupKEYSETBUTTON4(status);
++ iupKEY_SETBUTTON4(status);
+ 
+ if ((state & GDK_BUTTON5_MASK) || but==5)
+- iupKEYSETBUTTON5(status);
++ iupKEY_SETBUTTON5(status);
+ 
+ if (state & GDK_MOD1_MASK || state & GDK_MOD5_MASK) /* Alt */
+- iupKEYSETALT(status);
++ iupKEY_SETALT(status);
+ 
+ if (state & GDK_MOD4_MASK) /* Apple/Win */
+- iupKEYSETSYS(status);
++ iupKEY_SETSYS(status);
+ 
+ if (doubleclick)
+- iupKEYSETDOUBLE(status);
++ iupKEY_SETDOUBLE(status);
+ }
+ 
+diff --git a/iup/src/gtk/iupgtk_label.c b/iup/src/gtk/iupgtk_label.c
+index 49d5c6d..f95f576 100755
+--- a/iup/src/gtk/iupgtk_label.c
++++ b/iup/src/gtk/iupgtk_label.c
+@@ -133,8 +133,10 @@ static int gtkLabelSetPaddingAttrib(Ihandle* ih, const char* value)
+ {
+ GtkMisc* misc = (GtkMisc*)ih->handle;
+ gtk_misc_set_padding(misc, ih->data->horiz_padding, ih->data->vert_padding);
++ return 0;
+ }
+- return 0;
++ else
++ return 1; /* store until not mapped, when mapped will be set again */
+ }
+ 
+ static char* gtkLabelGetPangoLayoutAttrib(Ihandle* ih)
+diff --git a/iup/src/gtk/iupgtk_list.c b/iup/src/gtk/iupgtk_list.c
+index 80f6cce..48fa88e 100755
+--- a/iup/src/gtk/iupgtk_list.c
++++ b/iup/src/gtk/iupgtk_list.c
+@@ -113,6 +113,8 @@ void iupdrvListInsertItem(Ihandle* ih, int pos, const char* value)
+ GtkTreeIter iter;
+ gtk_list_store_insert(GTK_LIST_STORE(model), &iter, pos);
+ gtk_list_store_set(GTK_LIST_STORE(model), &iter, 0, iupgtkStrConvertToUTF8(value), -1);
++
++ iupListUpdateOldValue(ih, pos, 0);
+ }
+ 
+ void iupdrvListRemoveItem(Ihandle* ih, int pos)
+@@ -127,14 +129,24 @@ void iupdrvListRemoveItem(Ihandle* ih, int pos)
+ int curpos = gtk_combo_box_get_active((GtkComboBox*)ih->handle);
+ if (pos == curpos)
+ {
+- if (curpos > 0) curpos--;
+- else curpos++;
++ if (curpos > 0) 
++ curpos--;
++ else 
++ {
++ curpos=1;
++ if (iupdrvListGetCount(ih)==1)
++ curpos = -1; /* remove the selection */
++ }
+ 
++ g_signal_handlers_block_by_func(G_OBJECT(ih->handle), G_CALLBACK(gtkListComboBoxChanged), ih);
+ gtk_combo_box_set_active((GtkComboBox*)ih->handle, curpos);
++ g_signal_handlers_unblock_by_func(G_OBJECT(ih->handle), G_CALLBACK(gtkListComboBoxChanged), ih);
+ }
+ }
+ 
+ gtk_list_store_remove(GTK_LIST_STORE(model), &iter);
++
++ iupListUpdateOldValue(ih, pos, 1);
+ }
+ }
+ 
+@@ -177,7 +189,7 @@ static int gtkListSetStandardFontAttrib(Ihandle* ih, const char* value)
+ static char* gtkListGetIdValueAttrib(Ihandle* ih, const char* name_id)
+ {
+ int pos = iupListGetPos(ih, name_id);
+- if (pos != -1)
++ if (pos >= 0)
+ {
+ GtkTreeIter iter;
+ GtkTreeModel* model = gtkListGetModel(ih);
+@@ -349,7 +361,7 @@ static int gtkListSetValueAttrib(Ihandle* ih, const char* value)
+ GtkTreeModel *model = gtkListGetModel(ih);
+ g_signal_handlers_block_by_func(G_OBJECT(ih->handle), G_CALLBACK(gtkListComboBoxChanged), ih);
+ if (iupStrToInt(value, &pos)==1 && 
+- (pos>0 && pos<gtk_tree_model_iter_n_children(model, NULL)))
++ (pos>0 && pos<=gtk_tree_model_iter_n_children(model, NULL)))
+ {
+ gtk_combo_box_set_active((GtkComboBox*)ih->handle, pos-1); /* IUP starts at 1 */
+ iupAttribSetInt(ih, "_IUPLIST_OLDVALUE", pos);
+@@ -788,9 +800,10 @@ static int gtkListSetNCAttrib(Ihandle* ih, const char* value)
+ {
+ GtkEntry* entry = (GtkEntry*)iupAttribGet(ih, "_IUPGTK_ENTRY");
+ gtk_entry_set_max_length(entry, ih->data->nc);
++ return 0;
+ }
+-
+- return 0;
++ else
++ return 1; /* store until not mapped, when mapped will be set again */
+ }
+ 
+ static int gtkListSetClipboardAttrib(Ihandle *ih, const char *value)
+@@ -1364,9 +1377,9 @@ static int gtkListMapMethod(Ihandle* ih)
+ if (!ih->data->has_editbox && ih->data->is_multiple)
+ {
+ gtk_tree_selection_set_mode(selection, GTK_SELECTION_MULTIPLE);
+-#if GTK_CHECK_VERSION(2, 10, 0)
++ #if GTK_CHECK_VERSION(2, 10, 0)
+ gtk_tree_view_set_rubber_banding(GTK_TREE_VIEW(ih->handle), TRUE);
+-#endif
++ #endif
+ }
+ else
+ gtk_tree_selection_set_mode(selection, GTK_SELECTION_BROWSE);
+diff --git a/iup/src/gtk/iupgtk_loop.c b/iup/src/gtk/iupgtk_loop.c
+index e349a45..704923e 100755
+--- a/iup/src/gtk/iupgtk_loop.c
++++ b/iup/src/gtk/iupgtk_loop.c
+@@ -69,6 +69,13 @@ int IupMainLoop(void)
+ return IUP_NOERROR;
+ }
+ 
++int IupLoopStepWait(void)
++{
++ if (gtk_main_iteration_do(TRUE))
++ return IUP_CLOSE;
++ return IUP_DEFAULT;
++}
++
+ int IupLoopStep(void)
+ {
+ if (gtk_main_iteration_do(FALSE))
+diff --git a/iup/src/gtk/iupgtk_menu.c b/iup/src/gtk/iupgtk_menu.c
+index c12fbea..772f4cf 100755
+--- a/iup/src/gtk/iupgtk_menu.c
++++ b/iup/src/gtk/iupgtk_menu.c
+@@ -245,11 +245,19 @@ static int gtkMenuMapMethod(Ihandle* ih)
+ return IUP_NOERROR;
+ }
+ 
++static void gtkMenuUnMapMethod(Ihandle* ih)
++{
++ if (iupMenuIsMenuBar(ih))
++ ih->parent = NULL;
++
++ iupdrvBaseUnMapMethod(ih);
++}
++
+ void iupdrvMenuInitClass(Iclass* ic)
+ {
+ /* Driver Dependent Class functions */
+ ic->Map = gtkMenuMapMethod;
+- ic->UnMap = iupdrvBaseUnMapMethod;
++ ic->UnMap = gtkMenuUnMapMethod;
+ 
+ /* Used by iupdrvMenuGetMenuBarSize */
+ iupClassRegisterAttribute(ic, "STANDARDFONT", NULL, NULL, IUPAF_SAMEASSYSTEM, "DEFAULTFONT", IUPAF_DEFAULT); /* use inheritance to retrieve standard fonts */
+@@ -337,15 +345,10 @@ static int gtkItemSetValueAttrib(Ihandle* ih, const char* value)
+ 
+ static char* gtkItemGetValueAttrib(Ihandle* ih)
+ {
+- if (GTK_IS_CHECK_MENU_ITEM(ih->handle))
+- {
+- if (gtk_check_menu_item_get_active((GtkCheckMenuItem*)ih->handle))
+- return "ON";
+- else
+- return "OFF";
+- }
++ if (GTK_IS_CHECK_MENU_ITEM(ih->handle) && gtk_check_menu_item_get_active((GtkCheckMenuItem*)ih->handle))
++ return "ON";
+ else
+- return NULL;
++ return "OFF";
+ }
+ 
+ static int gtkItemMapMethod(Ihandle* ih)
+diff --git a/iup/src/gtk/iupgtk_open.c b/iup/src/gtk/iupgtk_open.c
+index 66e46e8..962f760 100755
+--- a/iup/src/gtk/iupgtk_open.c
++++ b/iup/src/gtk/iupgtk_open.c
+@@ -20,7 +20,52 @@
+ 
+ #include "iupgtk_drv.h"
+ 
++#ifdef GTK_MAC
++#include <gdk/gdk.h>
+ 
++char* iupgtkGetNativeWindowHandle(Ihandle* ih)
++{
++ GdkWindow* window = ih->handle->window;
++ if (window)
++ return (char*)window;
++ else
++ return NULL;
++}
++
++void* iupgtkGetNativeGraphicsContext(GtkWidget* widget)
++{
++ return (void*)gdk_gc_new((GdkDrawable*)widget->window);
++}
++
++void iupgtkReleaseNativeGraphicsContext(GtkWidget* widget, void* gc)
++{
++ g_object_unref(gc);
++ (void)widget;
++}
++
++void* iupdrvGetDisplay(void)
++{
++ GdkDisplay* display = gdk_display_get_default();
++ return display;
++}
++
++void iupgtkPushVisualAndColormap(void* visual, void* colormap)
++{
++ GdkColormap* gdk_colormap;
++ GdkVisual *gdk_visual = gdk_visual_get_best();
++
++ gdk_colormap = gdk_colormap_new(gdk_visual, FALSE);
++
++ gtk_widget_push_colormap(gdk_colormap);
++
++ /* gtk_widget_push_visual is now deprecated */
++}
++
++static void gtkSetDrvGlobalAttrib(void)
++{
++}
++
++#else
+ #ifdef WIN32 /******************************** WIN32 ************************************/
+ #include <gdk/gdkwin32.h>
+ 
+@@ -115,6 +160,8 @@ static void gtkSetDrvGlobalAttrib(void)
+ 
+ #endif
+ 
++#endif
++
+ static void gtkSetGlobalColorAttrib(const char* name, GdkColor *color)
+ {
+ iupGlobalSetDefaultColorAttrib(name, (int)iupCOLOR16TO8(color->red), 
+diff --git a/iup/src/gtk/iupgtk_tabs.c b/iup/src/gtk/iupgtk_tabs.c
+index 8029826..6b5aa66 100755
+--- a/iup/src/gtk/iupgtk_tabs.c
++++ b/iup/src/gtk/iupgtk_tabs.c
+@@ -76,13 +76,13 @@ static void gtkTabsUpdatePageBgColor(Ihandle* ih, unsigned char r, unsigned char
+ 
+ for (child = ih->firstchild; child; child = child->brother)
+ {
+- GtkWidget* tab_page = (GtkWidget*)iupAttribGet(child, "_IUPTAB_CONTAINER");
+- if (tab_page)
++ GtkWidget* tab_container = (GtkWidget*)iupAttribGet(child, "_IUPTAB_CONTAINER");
++ if (tab_container)
+ {
+ GtkWidget* tab_label = (GtkWidget*)iupAttribGet(child, "_IUPGTK_TABLABEL");
+ if (tab_label)
+ iupgtkBaseSetBgColor(tab_label, r, g, b);
+- iupgtkBaseSetBgColor(tab_page, r, g, b);
++ iupgtkBaseSetBgColor(tab_container, r, g, b);
+ }
+ }
+ }
+@@ -121,15 +121,18 @@ static int gtkTabsSetPaddingAttrib(Ihandle* ih, const char* value)
+ iupStrToIntInt(value, &ih->data->horiz_padding, &ih->data->vert_padding, 'x');
+ 
+ if (ih->handle)
++ {
+ gtkTabsUpdatePagePadding(ih);
+- return 0;
++ return 0;
++ }
++ else
++ return 1; /* store until not mapped, when mapped will be set again */
+ }
+ 
+ static void gtkTabsUpdateTabType(Ihandle* ih)
+ {
+- GtkNotebook* tab_page = (GtkNotebook*)ih->handle;
+ int iup2gtk[4] = {GTK_POS_TOP, GTK_POS_BOTTOM, GTK_POS_LEFT, GTK_POS_RIGHT};
+- gtk_notebook_set_tab_pos(tab_page, iup2gtk[ih->data->type]);
++ gtk_notebook_set_tab_pos((GtkNotebook*)ih->handle, iup2gtk[ih->data->type]);
+ }
+ 
+ static int gtkTabsSetTabTypeAttrib(Ihandle* ih, const char* value)
+@@ -144,7 +147,7 @@ static int gtkTabsSetTabTypeAttrib(Ihandle* ih, const char* value)
+ ih->data->type = ITABS_TOP;
+ 
+ if (ih->handle)
+- gtkTabsUpdateTabType(ih);
++ gtkTabsUpdateTabType(ih); /* for this to work must be updated in map */
+ 
+ return 0;
+ }
+@@ -171,7 +174,7 @@ static int gtkTabsSetTabTitleAttrib(Ihandle* ih, const char* name_id, const char
+ GtkWidget* tab_label = (GtkWidget*)iupAttribGet(child, "_IUPGTK_TABLABEL");
+ if (tab_label)
+ {
+- GtkWidget* tab_page = (GtkWidget*)iupAttribGet(child, "_IUPTAB_CONTAINER");
++ GtkWidget* tab_page = (GtkWidget*)iupAttribGet(child, "_IUPTAB_PAGE");
+ gtk_label_set_text((GtkLabel*)tab_label, iupgtkStrConvertToUTF8(value));
+ gtk_notebook_set_menu_label_text((GtkNotebook*)ih->handle, tab_page, gtk_label_get_text((GtkLabel*)tab_label));
+ }
+@@ -238,8 +241,10 @@ void gtkTabSwitchPage(GtkNotebook* notebook, GtkNotebookPage *page, int pos, Iha
+ IFnnn cb;
+ Ihandle* child = IupGetChild(ih, pos);
+ Ihandle* prev_child = IupGetChild(ih, iupdrvTabsGetCurrentTab(ih));
+- IupSetAttribute(child, "VISIBLE", "YES");
+- IupSetAttribute(prev_child, "VISIBLE", "NO");
++ GtkWidget* tab_container = (GtkWidget*)iupAttribGet(child, "_IUPTAB_CONTAINER");
++ GtkWidget* prev_tab_container = (GtkWidget*)iupAttribGet(prev_child, "_IUPTAB_CONTAINER");
++ if (tab_container) gtk_widget_show(tab_container);
++ if (prev_tab_container) gtk_widget_hide(prev_tab_container);
+ 
+ if (iupAttribGet(ih, "_IUPGTK_IGNORE_CHANGE"))
+ return;
+@@ -263,7 +268,7 @@ static void gtkTabsChildAddedMethod(Ihandle* ih, Ihandle* child)
+ 
+ if (ih->handle)
+ {
+- GtkWidget* tab_page;
++ GtkWidget *tab_page, *tab_container;
+ GtkWidget *tab_label = NULL, *tab_image = NULL;
+ char *tabtitle, *tabimage;
+ int pos;
+@@ -271,9 +276,13 @@ static void gtkTabsChildAddedMethod(Ihandle* ih, Ihandle* child)
+ 
+ pos = IupGetChildPos(ih, child);
+ 
+- tab_page = gtk_fixed_new();
++ tab_page = gtk_vbox_new(FALSE, 0);
+ gtk_widget_show(tab_page);
+ 
++ tab_container = gtk_fixed_new();
++ gtk_widget_show(tab_container);
++ gtk_container_add((GtkContainer*)tab_page, tab_container);
++
+ tabtitle = iupAttribGet(child, "TABTITLE");
+ if (!tabtitle) tabtitle = iupTabsAttribGetStrId(ih, "TABTITLE", pos);
+ tabimage = iupAttribGet(child, "TABIMAGE");
+@@ -327,9 +336,10 @@ static void gtkTabsChildAddedMethod(Ihandle* ih, Ihandle* child)
+ 
+ iupAttribSetStr(child, "_IUPGTK_TABIMAGE", (char*)tab_image); /* store it even if its NULL */
+ iupAttribSetStr(child, "_IUPGTK_TABLABEL", (char*)tab_label);
+- iupAttribSetStr(child, "_IUPTAB_CONTAINER", (char*)tab_page);
++ iupAttribSetStr(child, "_IUPTAB_CONTAINER", (char*)tab_container);
++ iupAttribSetStr(child, "_IUPTAB_PAGE", (char*)tab_page);
+ iupStrToRGB(IupGetAttribute(ih, "BGCOLOR"), &r, &g, &b);
+- iupgtkBaseSetBgColor(tab_page, r, g, b);
++ iupgtkBaseSetBgColor(tab_container, r, g, b);
+ 
+ if (tabtitle)
+ {
+@@ -354,10 +364,8 @@ static void gtkTabsChildAddedMethod(Ihandle* ih, Ihandle* child)
+ 
+ iupAttribSetStr(ih, "_IUPGTK_IGNORE_CHANGE", NULL);
+ 
+- if (pos == iupdrvTabsGetCurrentTab(ih))
+- IupSetAttribute(child, "VISIBLE", "YES");
+- else
+- IupSetAttribute(child, "VISIBLE", "NO");
++ if (pos != iupdrvTabsGetCurrentTab(ih))
++ gtk_widget_hide(tab_container);
+ }
+ }
+ 
+@@ -365,10 +373,11 @@ static void gtkTabsChildRemovedMethod(Ihandle* ih, Ihandle* child)
+ {
+ if (ih->handle)
+ {
+- GtkWidget* tab_page = (GtkWidget*)iupAttribGet(child, "_IUPTAB_CONTAINER");
++ GtkWidget* tab_page = (GtkWidget*)iupAttribGet(child, "_IUPTAB_PAGE");
+ if (tab_page)
+ {
+ int pos = gtk_notebook_page_num((GtkNotebook*)ih->handle, tab_page);
++ iupTabsTestRemoveTab(ih, pos);
+ 
+ iupAttribSetStr(ih, "_IUPGTK_IGNORE_CHANGE", "1");
+ gtk_notebook_remove_page((GtkNotebook*)ih->handle, pos);
+@@ -377,6 +386,7 @@ static void gtkTabsChildRemovedMethod(Ihandle* ih, Ihandle* child)
+ iupAttribSetStr(child, "_IUPGTK_TABIMAGE", NULL);
+ iupAttribSetStr(child, "_IUPGTK_TABLABEL", NULL);
+ iupAttribSetStr(child, "_IUPTAB_CONTAINER", NULL);
++ iupAttribSetStr(child, "_IUPTAB_PAGE", NULL);
+ }
+ }
+ }
+@@ -440,5 +450,5 @@ void iupdrvTabsInitClass(Iclass* ic)
+ iupClassRegisterAttribute(ic, "TABORIENTATION", iupTabsGetTabOrientationAttrib, gtkTabsSetTabOrientationAttrib, IUPAF_SAMEASSYSTEM, "HORIZONTAL", IUPAF_NOT_MAPPED|IUPAF_NO_INHERIT);
+ iupClassRegisterAttributeId(ic, "TABTITLE", NULL, gtkTabsSetTabTitleAttrib, IUPAF_NO_INHERIT);
+ iupClassRegisterAttributeId(ic, "TABIMAGE", NULL, gtkTabsSetTabImageAttrib, IUPAF_NO_INHERIT);
+- iupClassRegisterAttribute(ic, "PADDING", iupTabsGetPaddingAttrib, gtkTabsSetPaddingAttrib, IUPAF_SAMEASSYSTEM, "0x0", IUPAF_NOT_MAPPED);
++ iupClassRegisterAttribute(ic, "PADDING", iupTabsGetPaddingAttrib, gtkTabsSetPaddingAttrib, IUPAF_SAMEASSYSTEM, "0x0", IUPAF_NOT_MAPPED|IUPAF_NO_INHERIT);
+ }
+diff --git a/iup/src/gtk/iupgtk_text.c b/iup/src/gtk/iupgtk_text.c
+index 4c2906a..d0909d7 100755
+--- a/iup/src/gtk/iupgtk_text.c
++++ b/iup/src/gtk/iupgtk_text.c
+@@ -101,7 +101,7 @@ static void gtkTextParseParagraphFormat(Ihandle* formattag, GtkTextTag* tag)
+ align = PANGO_TAB_LEFT;
+ free(str);
+ 
+- pango_tab_array_set_tab(tabs, i, align, IUPGTK_PIXELS2PANGOUNITS(pos));
++ pango_tab_array_set_tab(tabs, i, align, iupGTK_PIXELS2PANGOUNITS(pos));
+ i++;
+ if (i == 32) break;
+ }
+@@ -171,7 +171,7 @@ static void gtkTextParseCharacterFormat(Ihandle* formattag, GtkTextTag* tag)
+ else 
+ iupStrToInt(format, &val);
+ 
+- val = IUPGTK_PIXELS2PANGOUNITS(val);
++ val = iupGTK_PIXELS2PANGOUNITS(val);
+ g_object_set(G_OBJECT(tag), "rise", val, NULL);
+ }
+ 
+@@ -214,7 +214,7 @@ static void gtkTextParseCharacterFormat(Ihandle* formattag, GtkTextTag* tag)
+ {
+ if (val < 0) /* in pixels */
+ {
+- val = IUPGTK_PIXELS2PANGOUNITS(-val);
++ val = iupGTK_PIXELS2PANGOUNITS(-val);
+ g_object_set(G_OBJECT(tag), "size", val, NULL);
+ }
+ else /* in points */
+@@ -387,8 +387,8 @@ static int gtkTextConvertXYToPos(Ihandle* ih, int x, int y)
+ 
+ /* transform to Layout coordinates */
+ gtk_entry_get_layout_offsets(GTK_ENTRY(ih->handle), &off_x, &off_y);
+- x = IUPGTK_PIXELS2PANGOUNITS(x - off_x); 
+- y = IUPGTK_PIXELS2PANGOUNITS(y - off_y);
++ x = iupGTK_PIXELS2PANGOUNITS(x - off_x); 
++ y = iupGTK_PIXELS2PANGOUNITS(y - off_y);
+ 
+ pango_layout_xy_to_index(gtk_entry_get_layout(GTK_ENTRY(ih->handle)), x, y, &pos, &trailing);
+ return pos;
+@@ -851,7 +851,7 @@ static char* gtkTextGetValueAttrib(Ihandle* ih)
+ 
+ static int gtkTextSetInsertAttrib(Ihandle* ih, const char* value)
+ {
+- if (!ih->handle) /* do not store the action before map */
++ if (!ih->handle) /* do not do the action before map */
+ return 0;
+ if (!value)
+ return 0;
+@@ -875,7 +875,8 @@ static int gtkTextSetInsertAttrib(Ihandle* ih, const char* value)
+ 
+ static int gtkTextSetAppendAttrib(Ihandle* ih, const char* value)
+ {
+- if (!ih->handle) /* do not store the action before map */
++ gint pos;
++ if (!ih->handle) /* do not do the action before map */
+ return 0;
+ /* disable callbacks */
+ iupAttribSetStr(ih, "_IUPGTK_DISABLE_TEXT_CB", "1");
+@@ -884,13 +885,18 @@ static int gtkTextSetAppendAttrib(Ihandle* ih, const char* value)
+ GtkTextIter iter;
+ GtkTextBuffer *buffer = gtk_text_view_get_buffer(GTK_TEXT_VIEW(ih->handle));
+ gtk_text_buffer_get_end_iter(buffer, &iter);
+- if (ih->data->append_newline)
++ pos = gtk_text_buffer_get_char_count(buffer);
++ if (ih->data->append_newline && pos!=0)
+ gtk_text_buffer_insert(buffer, &iter, "\n", 1);
+ gtk_text_buffer_insert(buffer, &iter, iupgtkStrConvertToUTF8(value), -1);
+ }
+ else
+ {
+- gint pos = strlen(gtk_entry_get_text(GTK_ENTRY(ih->handle)))+1;
++#if GTK_CHECK_VERSION(2, 14, 0)
++ pos = gtk_entry_get_text_length(GTK_ENTRY(ih->handle))+1;
++#else
++ pos = strlen(gtk_entry_get_text(GTK_ENTRY(ih->handle)))+1;
++#endif
+ gtk_editable_insert_text(GTK_EDITABLE(ih->handle), iupgtkStrConvertToUTF8(value), -1, &pos);
+ }
+ iupAttribSetStr(ih, "_IUPGTK_DISABLE_TEXT_CB", NULL);
+@@ -946,8 +952,10 @@ static int gtkTextSetPaddingAttrib(Ihandle* ih, const char* value)
+ gtk_entry_set_inner_border(GTK_ENTRY(ih->handle), &border);
+ #endif
+ }
++ return 0;
+ }
+- return 0;
++ else
++ return 1; /* store until not mapped, when mapped will be set again */
+ }
+ 
+ static int gtkTextSetNCAttrib(Ihandle* ih, const char* value)
+@@ -955,10 +963,14 @@ static int gtkTextSetNCAttrib(Ihandle* ih, const char* value)
+ if (!iupStrToInt(value, &ih->data->nc))
+ ih->data->nc = INT_MAX;
+ 
+- if (!ih->data->is_multiline && ih->handle)
+- gtk_entry_set_max_length(GTK_ENTRY(ih->handle), ih->data->nc);
+-
+- return 0;
++ if (ih->handle)
++ {
++ if (!ih->data->is_multiline)
++ gtk_entry_set_max_length(GTK_ENTRY(ih->handle), ih->data->nc);
++ return 0;
++ }
++ else
++ return 1; /* store until not mapped, when mapped will be set again */
+ }
+ 
+ static int gtkTextSetClipboardAttrib(Ihandle *ih, const char *value)
+diff --git a/iup/src/gtk/iupgtk_toggle.c b/iup/src/gtk/iupgtk_toggle.c
+index 8ff7df5..040beda 100755
+--- a/iup/src/gtk/iupgtk_toggle.c
++++ b/iup/src/gtk/iupgtk_toggle.c
+@@ -213,8 +213,10 @@ static int gtkToggleSetPaddingAttrib(Ihandle* ih, const char* value)
+ GtkButton* button = (GtkButton*)ih->handle;
+ GtkMisc* misc = (GtkMisc*)gtk_button_get_image(button);
+ gtk_misc_set_padding(misc, ih->data->horiz_padding, ih->data->vert_padding);
++ return 0;
+ }
+- return 0;
++ else
++ return 1; /* store until not mapped, when mapped will be set again */
+ }
+ 
+ static int gtkToggleSetFgColorAttrib(Ihandle* ih, const char* value)
+diff --git a/iup/src/gtk/iupgtk_tree.c b/iup/src/gtk/iupgtk_tree.c
+index d408f27..9595ada 100755
+--- a/iup/src/gtk/iupgtk_tree.c
++++ b/iup/src/gtk/iupgtk_tree.c
+@@ -31,33 +31,50 @@
+ #include "iup_drvinfo.h"
+ #include "iupgtk_drv.h"
+ 
++
++/* IMPORTANT: 
++
++ GtkTreeStore uses the "user_data" field of the GtkTreeIter 
++ to store the node pointer that is position independent.
++ So we use it as a reference to the node in the cache, just like in Motif and Windows.
++
++ BUT if GTK change its implementation this must be changed also. See "gtk_tree_store.c".
++
++ ABOUT SELECTIONS:
++
++ From the GTK documentation on GtkTreeSelection
++
++ "Additionally, you cannot change the selection of a row on the model 
++ that is not currently displayed by the view without expanding its parents first."
++*/
++
+ enum
+ {
+- IUPGTK_TREE_IMAGE,
++ IUPGTK_TREE_IMAGE, /* "pixbuf", "pixbuf-expander-closed" */
+ IUPGTK_TREE_HAS_IMAGE,
+- IUPGTK_TREE_IMAGE_EXPANDED,
++ IUPGTK_TREE_IMAGE_EXPANDED, /* "pixbuf-expander-open" */
+ IUPGTK_TREE_HAS_IMAGE_EXPANDED,
+- IUPGTK_TREE_TITLE,
+- IUPGTK_TREE_KIND,
+- IUPGTK_TREE_COLOR,
+- IUPGTK_TREE_FONT,
+- IUPGTK_TREE_USERDATA
++ IUPGTK_TREE_TITLE, /* "text" */
++ IUPGTK_TREE_KIND, /* "is-expander" */
++ IUPGTK_TREE_COLOR, /* "foreground-gdk" */
++ IUPGTK_TREE_FONT, /* "font-desc" */
++ IUPGTK_TREE_SELECT,
++ IUPGTK_TREE_LAST_DATA /* used as a count */
+ };
+ 
+-static GtkTreeIter gtkTreeInvalidIter = {0,0,0,0};
++static void gtkTreeRebuildNodeCache(Ihandle* ih, int id, GtkTreeIter iterItem);
+ 
+ /*****************************************************************************/
+ /* COPYING ITEMS (Branches and its children) */
+ /*****************************************************************************/
+ /* Insert the copied item in a new location. Returns the new item. */
+-static void gtkTreeCopyItem(GtkTreeModel* model, GtkTreeIter* iterItem, GtkTreeIter* iterParent, int position, GtkTreeIter *iterNewItem, int full_copy)
++static void gtkTreeCopyItem(Ihandle* ih, GtkTreeModel* model, GtkTreeIter* iterItem, GtkTreeIter* iterParent, int position, GtkTreeIter *iterNewItem)
+ {
+ GtkTreeStore* store = GTK_TREE_STORE(model);
+ int kind;
+ char* title;
+ gboolean has_image, has_image_expanded;
+ PangoFontDescription* font;
+- void* userdata;
+ GdkColor *color;
+ GdkPixbuf* image, *image_expanded;
+ 
+@@ -69,9 +86,10 @@ static void gtkTreeCopyItem(GtkTreeModel* model, GtkTreeIter* iterItem, GtkTreeI
+ IUPGTK_TREE_KIND, &kind,
+ IUPGTK_TREE_COLOR, &color, 
+ IUPGTK_TREE_FONT, &font, 
+- IUPGTK_TREE_USERDATA, &userdata,
+ -1);
+ 
++ /* Add the new node */
++ ih->data->node_count++;
+ if (position == 2)
+ gtk_tree_store_append(store, iterNewItem, iterParent);
+ else if (position == 1) /* copy as first child of expanded branch */
+@@ -79,9 +97,6 @@ static void gtkTreeCopyItem(GtkTreeModel* model, GtkTreeIter* iterItem, GtkTreeI
+ else /* copy as next brother of item or collapsed branch */
+ gtk_tree_store_insert_after(store, iterNewItem, NULL, iterParent); /* iterParent is sibling of the new item */
+ 
+- if (full_copy) /* during a full copy the userdata reference is not copied */
+- userdata = NULL;
+-
+ gtk_tree_store_set(store, iterNewItem, IUPGTK_TREE_IMAGE, image,
+ IUPGTK_TREE_HAS_IMAGE, has_image,
+ IUPGTK_TREE_IMAGE_EXPANDED, image_expanded,
+@@ -90,21 +105,21 @@ static void gtkTreeCopyItem(GtkTreeModel* model, GtkTreeIter* iterItem, GtkTreeI
+ IUPGTK_TREE_KIND, kind,
+ IUPGTK_TREE_COLOR, color, 
+ IUPGTK_TREE_FONT, font,
+- IUPGTK_TREE_USERDATA, userdata,
++ IUPGTK_TREE_SELECT, 0,
+ -1);
+ }
+ 
+-static void gtkTreeCopyChildren(Ihandle* ih, GtkTreeModel* model, GtkTreeIter *iterItemSrc, GtkTreeIter *iterItemDst, int full_copy)
++static void gtkTreeCopyChildren(Ihandle* ih, GtkTreeModel* model, GtkTreeIter *iterItemSrc, GtkTreeIter *iterItemDst)
+ {
+ GtkTreeIter iterChildSrc;
+ int hasItem = gtk_tree_model_iter_children(model, &iterChildSrc, iterItemSrc); /* get the firstchild */
+ while(hasItem)
+ {
+ GtkTreeIter iterNewItem;
+- gtkTreeCopyItem(model, &iterChildSrc, iterItemDst, 2, &iterNewItem, full_copy); /* append always */
++ gtkTreeCopyItem(ih, model, &iterChildSrc, iterItemDst, 2, &iterNewItem); /* append always */
+ 
+ /* Recursively transfer all the items */
+- gtkTreeCopyChildren(ih, model, &iterChildSrc, &iterNewItem, full_copy); 
++ gtkTreeCopyChildren(ih, model, &iterChildSrc, &iterNewItem); 
+ 
+ /* Go to next sibling item */
+ hasItem = gtk_tree_model_iter_next(model, &iterChildSrc);
+@@ -112,9 +127,17 @@ static void gtkTreeCopyChildren(Ihandle* ih, GtkTreeModel* model, GtkTreeIter *i
+ }
+ 
+ /* Copies all items in a branch to a new location. Returns the new branch node. */
+-static void gtkTreeCopyNode(Ihandle* ih, GtkTreeModel* model, GtkTreeIter *iterItemSrc, GtkTreeIter *iterItemDst, GtkTreeIter* iterNewItem, int full_copy)
++static void gtkTreeCopyMoveNode(Ihandle* ih, GtkTreeModel* model, GtkTreeIter *iterItemSrc, GtkTreeIter *iterItemDst, GtkTreeIter* iterNewItem, int is_copy)
+ {
+ int kind, position = 0; /* insert after iterItemDst */
++ int id_new, count, id_src, id_dst;
++
++ int old_count = ih->data->node_count;
++
++ id_src = iupTreeFindNodeId(ih, iterItemSrc);
++ id_dst = iupTreeFindNodeId(ih, iterItemDst);
++ id_new = id_dst+1; /* contains the position for a copy operation */
++
+ gtk_tree_model_get(model, iterItemDst, IUPGTK_TREE_KIND, &kind, -1);
+ 
+ if (kind == ITREE_BRANCH)
+@@ -122,346 +145,311 @@ static void gtkTreeCopyNode(Ihandle* ih, GtkTreeModel* model, GtkTreeIter *iterI
+ GtkTreePath* path = gtk_tree_model_get_path(model, iterItemDst);
+ if (gtk_tree_view_row_expanded(GTK_TREE_VIEW(ih->handle), path))
+ position = 1; /* insert as first child of iterItemDst */
++ else
++ {
++ int child_count = iupdrvTreeTotalChildCount(ih, iterItemDst);
++ id_new += child_count;
++ }
+ gtk_tree_path_free(path);
+ }
+ 
+- gtkTreeCopyItem(model, iterItemSrc, iterItemDst, position, iterNewItem, full_copy); 
++ /* move to the same place does nothing */
++ if (!is_copy && id_new == id_src)
++ {
++ iterNewItem->stamp = 0;
++ return;
++ }
+ 
+- gtkTreeCopyChildren(ih, model, iterItemSrc, iterNewItem, full_copy);
+-}
++ gtkTreeCopyItem(ih, model, iterItemSrc, iterItemDst, position, iterNewItem); 
+ 
+-/*****************************************************************************/
+-/* FINDING ITEMS */
+-/*****************************************************************************/
++ gtkTreeCopyChildren(ih, model, iterItemSrc, iterNewItem);
+ 
+-static void gtkTreeInvertAllNodeMarking(Ihandle* ih, GtkTreeModel* model, GtkTreeSelection* selection, GtkTreeIter* iterItem)
+-{
+- GtkTreeIter iterChild;
+- int hasItem = TRUE;
++ count = ih->data->node_count - old_count;
++ iupTreeCopyMoveCache(ih, id_src, id_new, count, is_copy);
+ 
+- while(hasItem)
++ if (!is_copy)
+ {
+- if(gtk_tree_selection_iter_is_selected(selection, iterItem))
+- gtk_tree_selection_unselect_iter(selection, iterItem);
+- else
+- gtk_tree_selection_select_iter(selection, iterItem);
++ /* Deleting the node of its old position */
++ iupAttribSetStr(ih, "_IUPTREE_IGNORE_SELECTION_CB", "1");
++ gtk_tree_store_remove(GTK_TREE_STORE(model), iterItemSrc);
++ iupAttribSetStr(ih, "_IUPTREE_IGNORE_SELECTION_CB", NULL);
+ 
+- /* Check whether we have child items */
+- if(gtk_tree_model_iter_has_child(model, iterItem))
+- {
+- gtk_tree_model_iter_children(model, &iterChild, iterItem); /* get the firstchild */
+- gtkTreeInvertAllNodeMarking(ih, model, selection, &iterChild);
+- }
++ /* restore count, because we remove src */
++ ih->data->node_count = old_count;
+ 
+- /* Go to next sibling item */
+- hasItem = gtk_tree_model_iter_next(model, iterItem);
++ /* compensate position for a move */
++ if (id_new > id_src)
++ id_new -= count;
+ }
++
++ gtkTreeRebuildNodeCache(ih, id_new, *iterNewItem);
+ }
+ 
+-static GtkTreeIter gtkTreeFindVisibleNodeId(Ihandle* ih, GtkTreeModel* model, GtkTreeIter iterItem, GtkTreeIter iterNode)
++/*****************************************************************************/
++/* FINDING ITEMS */
++/*****************************************************************************/
++
++static void gtkTreeIterInit(Ihandle* ih, GtkTreeIter* iterItem, InodeHandle* node_handle)
+ {
+- GtkTreeIter iterChild;
+- GtkTreePath* path;
+- int hasItem = TRUE;
++ iterItem->stamp = ih->data->stamp;
++ iterItem->user_data = node_handle;
++ iterItem->user_data2 = NULL;
++ iterItem->user_data3 = NULL;
++}
+ 
+- while(hasItem)
+- {
+- /* ID control to traverse items */
+- ih->data->id_control++; /* not the real id since it counts only the visible ones */
++static int gtkTreeIsNodeSelected(GtkTreeModel* model, GtkTreeIter *iterItem)
++{
++ gboolean selected = 0;
++ gtk_tree_model_get(model, iterItem, IUPGTK_TREE_SELECT, &selected, -1);
++ return selected;
++}
+ 
+- /* StateID founded! */
+- if(iterItem.user_data == iterNode.user_data)
+- return iterItem;
++static void gtkTreeSelectNodeRaw(GtkTreeModel* model, GtkTreeIter *iterItem, int select)
++{
++ /* Cannot change the selection of a row on the model that is not currently displayed. 
++ So we store the selection state here. And update the actual state when the node becames visible. */
++ gtk_tree_store_set(GTK_TREE_STORE(model), iterItem, IUPGTK_TREE_SELECT, select, -1);
++}
+ 
+- path = gtk_tree_model_get_path(model, &iterItem);
++static void gtkTreeSelectNode(GtkTreeModel* model, GtkTreeSelection* selection, GtkTreeIter *iterItem, int select)
++{
++ if (select == -1)
++ select = !gtkTreeIsNodeSelected(model, iterItem); /* toggle */
+ 
+- /* Check whether we have child items and it is expanded (visible) */
+- if (gtk_tree_model_iter_has_child(model, &iterItem) && gtk_tree_view_row_expanded(GTK_TREE_VIEW(ih->handle), path))
+- {
+- gtk_tree_model_iter_children(model, &iterChild, &iterItem); /* get the firstchild */
+- iterChild = gtkTreeFindVisibleNodeId(ih, model, iterChild, iterNode);
++ gtkTreeSelectNodeRaw(model, iterItem, select);
+ 
+- /* StateID founded! */
+- if(iterChild.user_data)
+- {
+- gtk_tree_path_free(path);
+- return iterChild;
+- }
+- }
++ if (select)
++ gtk_tree_selection_select_iter(selection, iterItem);
++ else
++ gtk_tree_selection_unselect_iter(selection, iterItem);
++}
+ 
+- gtk_tree_path_free(path);
+- /* Go to next sibling item */
+- hasItem = gtk_tree_model_iter_next(model, &iterItem);
++static void gtkTreeSelectAll(Ihandle* ih, GtkTreeModel* model, GtkTreeSelection* selection, int selected)
++{
++ int i;
++ GtkTreeIter iterItem;
++
++ for (i = 0; i < ih->data->node_count; i++)
++ {
++ gtkTreeIterInit(ih, &iterItem, ih->data->node_cache[i].node_handle);
++ gtkTreeSelectNodeRaw(model, &iterItem, selected);
+ }
+ 
+- return gtkTreeInvalidIter; /* invalid since gtk_tree_model_iter_next returned false */
++ if (selected)
++ gtk_tree_selection_select_all(selection);
++ else
++ gtk_tree_selection_unselect_all(selection);
+ }
+ 
+-static GtkTreeIter gtkTreeFindVisibleNodeFromId(Ihandle* ih, GtkTreeModel* model, GtkTreeIter iterItem)
++static void gtkTreeInvertAllNodeMarking(Ihandle* ih, GtkTreeModel* model, GtkTreeSelection* selection)
+ {
+- GtkTreeIter iterChild;
+- GtkTreePath* path;
+- int hasItem = TRUE;
++ int i;
++ GtkTreeIter iterItem;
+ 
+- while(hasItem)
++ for (i = 0; i < ih->data->node_count; i++)
+ {
+- /* ID control to traverse items */
+- ih->data->id_control--; /* not the real id since it counts only the visible ones */
++ gtkTreeIterInit(ih, &iterItem, ih->data->node_cache[i].node_handle);
++ gtkTreeSelectNode(model, selection, &iterItem, -1);
++ }
++}
+ 
+- /* StateID founded! */
+- if(ih->data->id_control < 0)
+- return iterItem;
++static void gtkTreeSelectRange(Ihandle* ih, GtkTreeModel* model, GtkTreeSelection* selection, GtkTreeIter *iterItem1, GtkTreeIter *iterItem2, int clear)
++{
++ int i;
++ int id1 = iupTreeFindNodeId(ih, iterItem1->user_data);
++ int id2 = iupTreeFindNodeId(ih, iterItem2->user_data);
++ GtkTreeIter iterItem;
+ 
+- path = gtk_tree_model_get_path(model, &iterItem);
++ if (id1 > id2)
++ {
++ int tmp = id1;
++ id1 = id2;
++ id2 = tmp;
++ }
+ 
+- /* Check whether we have child items and it is expanded (visible) */
+- if(gtk_tree_model_iter_has_child(model, &iterItem) && gtk_tree_view_row_expanded(GTK_TREE_VIEW(ih->handle), path))
++ for (i = 0; i < ih->data->node_count; i++)
++ {
++ gtkTreeIterInit(ih, &iterItem, ih->data->node_cache[i].node_handle);
++ if (i < id1 || i > id2)
+ {
+- gtk_tree_model_iter_children(model, &iterChild, &iterItem); /* get the firstchild */
+- iterChild = gtkTreeFindVisibleNodeFromId(ih, model, iterChild);
+-
+- /* StateID founded! */
+- if(ih->data->id_control < 0)
+- {
+- gtk_tree_path_free(path);
+- return iterChild;
+- }
++ if (clear)
++ gtkTreeSelectNode(model, selection, &iterItem, 0);
+ }
+-
+- gtk_tree_path_free(path);
+- /* Go to next sibling item */
+- hasItem = gtk_tree_model_iter_next(model, &iterItem);
++ else
++ gtkTreeSelectNode(model, selection, &iterItem, 1);
+ }
+-
+- return gtkTreeInvalidIter; /* invalid since gtk_tree_model_iter_next returned false */
+ }
+ 
+-static GtkTreeIter gtkTreeGetLastVisibleNode(Ihandle* ih, GtkTreeModel* model, GtkTreeIter iterItem)
++static int gtkTreeIsNodeVisible(Ihandle* ih, GtkTreeModel* model, InodeHandle* node_handle, InodeHandle* *nodeLastParent)
+ {
+- GtkTreeIter iterChild, iterPrev = gtkTreeInvalidIter;
+- GtkTreePath* path = gtk_tree_model_get_path(model, &iterItem);
+-
+- /* Check whether we have child items and it is expanded (visible) */
+- if(gtk_tree_model_iter_has_child(model, &iterItem) && gtk_tree_view_row_expanded(GTK_TREE_VIEW(ih->handle), path))
+- {
+- int hasItem = TRUE;
+- gtk_tree_model_iter_children(model, &iterChild, &iterItem); /* get the firstchild */
++ GtkTreeIter iterItem, iterParent;
++ GtkTreePath* path;
++ int is_visible;
+ 
+- while(hasItem)
+- {
+- iterPrev = iterChild;
++ gtkTreeIterInit(ih, &iterItem, node_handle);
+ 
+- /* Go to next sibling item */
+- hasItem = gtk_tree_model_iter_next(model, &iterChild);
+- }
++ if (!gtk_tree_model_iter_parent(model, &iterParent, &iterItem) ||
++ iterParent.user_data == *nodeLastParent)
++ return 1;
+ 
+- iterItem = gtkTreeGetLastVisibleNode(ih, model, iterPrev);
+- }
++ path = gtk_tree_model_get_path(model, &iterParent);
++ is_visible = gtk_tree_view_row_expanded(GTK_TREE_VIEW(ih->handle), path);
+ gtk_tree_path_free(path);
+ 
+- return iterItem;
++ if (!is_visible)
++ return 0;
++
++ /* save last parent */
++ *nodeLastParent = iterParent.user_data;
++ return 1;
+ }
+ 
+-static GtkTreeIter gtkTreeFindNodeID(Ihandle* ih, GtkTreeModel* model, GtkTreeIter iterItem, GtkTreeIter iterNode)
++static void gtkTreeGetLastVisibleNode(Ihandle* ih, GtkTreeModel* model, GtkTreeIter *iterItem)
+ {
+- GtkTreeIter iterChild;
+- int hasItem = TRUE;
++ int i;
++ InodeHandle* nodeLastParent = NULL;
+ 
+- while(hasItem)
++ for (i = ih->data->node_count-1; i >= 0; i--)
+ {
+- /* ID control to traverse items */
+- ih->data->id_control++;
+-
+- /* StateID founded! */
+- if (iterItem.user_data == iterNode.user_data)
+- return iterItem;
+-
+- /* Check whether we have child items */
+- if (gtk_tree_model_iter_has_child(model, &iterItem))
++ if (gtkTreeIsNodeVisible(ih, model, ih->data->node_cache[i].node_handle, &nodeLastParent))
+ {
+- gtk_tree_model_iter_children(model, &iterChild, &iterItem); /* get the firstchild */
+- iterChild = gtkTreeFindNodeID(ih, model, iterChild, iterNode);
+-
+- /* StateID founded! */
+- if(iterChild.user_data)
+- return iterChild;
++ gtkTreeIterInit(ih, iterItem, ih->data->node_cache[i].node_handle);
++ return;
+ }
+-
+- /* Go to next sibling item */
+- hasItem = gtk_tree_model_iter_next(model, &iterItem);
+ }
+ 
+- return gtkTreeInvalidIter; /* invalid since gtk_tree_model_iter_next returned false */
++ gtkTreeIterInit(ih, iterItem, ih->data->node_cache[0].node_handle); /* root is always visible */
+ }
+ 
+-static int gtkTreeGetNodeId(Ihandle* ih, GtkTreeIter iterItem)
++static void gtkTreeGetNextVisibleNode(Ihandle* ih, GtkTreeModel* model, GtkTreeIter *iterItem, int count)
+ {
+- GtkTreeModel* model = gtk_tree_view_get_model(GTK_TREE_VIEW(ih->handle));
+- GtkTreeIter iterRoot;
+- gtk_tree_model_get_iter_first(model, &iterRoot);
+-
+- ih->data->id_control = -1;
+- iterItem = gtkTreeFindNodeID(ih, model, iterRoot, iterItem);
+- if (iterItem.user_data)
+- return ih->data->id_control;
+- else
+- return -1;
+-}
++ int i, id;
++ InodeHandle* nodeLastParent = NULL;
+ 
+-static GtkTreeIter gtkTreeFindUserData(Ihandle* ih, GtkTreeModel* model, GtkTreeIter iterItem, void* userdata)
+-{
+- GtkTreeIter iterChild;
+- int hasItem = TRUE;
+- void* node_userdata;
++ id = iupTreeFindNodeId(ih, iterItem->user_data);
++ id += count;
+ 
+- while(hasItem)
++ for (i = id; i < ih->data->node_count; i++)
+ {
+- /* ID control to traverse items */
+- ih->data->id_control++;
++ if (gtkTreeIsNodeVisible(ih, model, ih->data->node_cache[i].node_handle, &nodeLastParent))
++ {
++ gtkTreeIterInit(ih, iterItem, ih->data->node_cache[i].node_handle);
++ return;
++ }
++ }
+ 
+- gtk_tree_model_get(model, &iterItem, IUPGTK_TREE_USERDATA, &node_userdata, -1);
++ gtkTreeIterInit(ih, iterItem, ih->data->node_cache[0].node_handle); /* root is always visible */
++}
+ 
+- /* userdata founded! */
+- if (node_userdata == userdata)
+- return iterItem;
++static void gtkTreeGetPreviousVisibleNode(Ihandle* ih, GtkTreeModel* model, GtkTreeIter *iterItem, int count)
++{
++ int i, id;
++ InodeHandle* nodeLastParent = NULL;
+ 
+- /* Check whether we have child items */
+- if (gtk_tree_model_iter_has_child(model, &iterItem))
+- {
+- gtk_tree_model_iter_children(model, &iterChild, &iterItem); /* get the firstchild */
+- iterChild = gtkTreeFindUserData(ih, model, iterChild, userdata);
++ id = iupTreeFindNodeId(ih, iterItem->user_data);
++ id -= count;
+ 
+- /* userdata founded! */
+- if (iterChild.user_data)
+- return iterChild;
++ for (i = id; i >= 0; i--)
++ {
++ if (gtkTreeIsNodeVisible(ih, model, ih->data->node_cache[i].node_handle, &nodeLastParent))
++ {
++ gtkTreeIterInit(ih, iterItem, ih->data->node_cache[i].node_handle);
++ return;
+ }
+-
+- /* Go to next sibling item */
+- hasItem = gtk_tree_model_iter_next(model, &iterItem);
+ }
+ 
+- return gtkTreeInvalidIter; /* invalid since gtk_tree_model_iter_next returned false */
++ gtkTreeGetLastVisibleNode(ih, model, iterItem);
+ }
+ 
+-static int gtkTreeGetUserDataId(Ihandle* ih, GtkTreeModel* model, void* userdata)
++static int gtkTreeFindNodeId(Ihandle* ih, GtkTreeIter* iterItem)
+ {
+- GtkTreeIter iterRoot, iterItem;
+- gtk_tree_model_get_iter_first(model, &iterRoot);
+-
+- ih->data->id_control = -1;
+- iterItem = gtkTreeFindUserData(ih, model, iterRoot, userdata);
+- if (iterItem.user_data)
+- return ih->data->id_control;
+- else
+- return -1;
++ return iupTreeFindNodeId(ih, iterItem->user_data);
+ }
+ 
+-static void gtkTreeCallNodeRemovedRec(Ihandle* ih, GtkTreeModel* model, GtkTreeIter iterItem, IFnis cb)
++static void gtkTreeCallNodeRemovedRec(Ihandle* ih, GtkTreeModel* model, GtkTreeIter *iterItem, IFns cb, int *id)
+ {
+ GtkTreeIter iterChild;
+- int hasItem = TRUE;
+- void* node_userdata;
++ int hasItem;
++ int old_id = *id;
+ 
++ /* Check whether we have child items */
++ /* remove from children first */
++ hasItem = gtk_tree_model_iter_children(model, &iterChild, iterItem); /* get the firstchild */
+ while(hasItem)
+ {
+- /* ID control to traverse items */
+- ih->data->id_control++;
+-
+- gtk_tree_model_get(model, &iterItem, IUPGTK_TREE_USERDATA, &node_userdata, -1);
+-
+- cb(ih, ih->data->id_control, (char*)node_userdata);
+-
+- /* Check whether we have child items */
+- if (gtk_tree_model_iter_has_child(model, &iterItem))
+- {
+- gtk_tree_model_iter_children(model, &iterChild, &iterItem); /* get the firstchild */
+- gtkTreeCallNodeRemovedRec(ih, model, iterChild, cb);
+- }
++ /* go recursive to children */
++ gtkTreeCallNodeRemovedRec(ih, model, &iterChild, cb, id);
+ 
+ /* Go to next sibling item */
+- hasItem = gtk_tree_model_iter_next(model, &iterItem);
++ hasItem = gtk_tree_model_iter_next(model, &iterChild);
+ }
++
++ /* actually do it for the node */
++ ih->data->node_count--;
++ (*id)++;
++
++ cb(ih, (char*)ih->data->node_cache[old_id].userdata);
+ }
+ 
+ static void gtkTreeCallNodeRemoved(Ihandle* ih, GtkTreeModel* model, GtkTreeIter *iterItem)
+ {
+- IFnis cb = (IFnis)IupGetCallback(ih, "NODEREMOVED_CB");
++ int old_count = ih->data->node_count;
++ int id = iupTreeFindNodeId(ih, iterItem->user_data);
++ int old_id = id;
++
++ IFns cb = (IFns)IupGetCallback(ih, "NODEREMOVED_CB");
+ if (cb) 
++ gtkTreeCallNodeRemovedRec(ih, model, iterItem, cb, &id);
++ else
+ {
+- ih->data->id_control = gtkTreeGetNodeId(ih, *iterItem)-1;
+- gtkTreeCallNodeRemovedRec(ih, model, *iterItem, cb);
++ int removed_count = iupdrvTreeTotalChildCount(ih, iterItem->user_data)+1;
++ ih->data->node_count -= removed_count;
+ }
++
++ iupTreeDelFromCache(ih, old_id, old_count-ih->data->node_count);
+ }
+ 
+-static gboolean gtkTreeFindNodeFromID(Ihandle* ih, GtkTreeModel* model, GtkTreeIter *iterItem, int *id)
++static void gtkTreeCallNodeRemovedAll(Ihandle* ih)
+ {
+- GtkTreeIter iterChild;
+- int hasItem = TRUE;
++ IFns cb = (IFns)IupGetCallback(ih, "NODEREMOVED_CB");
++ int i, old_count = ih->data->node_count;
+ 
+- while(hasItem)
++ if (cb)
+ {
+- /* ID control to traverse items */
+- (*id)--;
+-
+- /* StateID founded! */
+- if (*id < 0)
+- return TRUE;
+-
+- /* Check whether we have child items */
+- if (gtk_tree_model_iter_has_child(model, iterItem))
++ for (i = 0; i < ih->data->node_count; i++)
+ {
+- gtk_tree_model_iter_children(model, &iterChild, iterItem); /* get the firstchild */
+- 
+- if (gtkTreeFindNodeFromID(ih, model, &iterChild, id))
+- {
+- *iterItem = iterChild;
+- return TRUE;
+- }
++ cb(ih, (char*)ih->data->node_cache[i].userdata);
+ }
+-
+- /* Go to next sibling item */
+- hasItem = gtk_tree_model_iter_next(model, iterItem);
+ }
+ 
+- return FALSE;
++ ih->data->node_count = 0;
++
++ iupTreeDelFromCache(ih, 0, old_count);
+ }
+ 
+-static gboolean gtkTreeFindNodeFromString(Ihandle* ih, GtkTreeModel* model, const char* name_id, GtkTreeIter *iterItem)
++static gboolean gtkTreeFindNodeFromString(Ihandle* ih, const char* name_id, GtkTreeIter *iterItem)
+ {
+- if (name_id[0])
+- {
+- int id;
+- if (iupStrToInt(name_id, &id))
+- {
+- gtk_tree_model_get_iter_first(model, iterItem);
+- return gtkTreeFindNodeFromID(ih, model, iterItem, &id);
+- }
+- }
+- else
+- {
+- GtkTreePath* path = NULL;
+- gtk_tree_view_get_cursor(GTK_TREE_VIEW(ih->handle), &path, NULL);
+- if (path)
+- {
+- gtk_tree_model_get_iter(model, iterItem, path);
+- gtk_tree_path_free(path);
+- return TRUE;
+- }
+- }
+- return FALSE;
++ InodeHandle* node_handle = iupTreeGetNodeFromString(ih, name_id);
++ if (!node_handle)
++ return FALSE;
++
++ gtkTreeIterInit(ih, iterItem, node_handle);
++ return TRUE;
+ }
+ 
+ /*****************************************************************************/
+ /* MANIPULATING IMAGES */
+ /*****************************************************************************/
+-static void gtkTreeUpdateImages(Ihandle* ih, GtkTreeModel* model, GtkTreeIter iterItem, int mode)
++static void gtkTreeUpdateImages(Ihandle* ih, int mode)
+ {
+- GtkTreeIter iterChild;
+- int hasItem = TRUE;
+- int kind;
++ GtkTreeModel* model = gtk_tree_view_get_model(GTK_TREE_VIEW(ih->handle));
++ GtkTreeIter iterItem;
++ int i, kind;
+ 
+- while(hasItem)
++ for (i=0; i<ih->data->node_count; i++)
+ {
++ gtkTreeIterInit(ih, &iterItem, ih->data->node_cache[i].node_handle);
++
+ gtk_tree_model_get(model, &iterItem, IUPGTK_TREE_KIND, &kind, -1);
+ 
+ if (kind == ITREE_BRANCH)
+@@ -480,14 +468,6 @@ static void gtkTreeUpdateImages(Ihandle* ih, GtkTreeModel* model, GtkTreeIter it
+ if (!has_image)
+ gtk_tree_store_set(GTK_TREE_STORE(model), &iterItem, IUPGTK_TREE_IMAGE, ih->data->def_image_collapsed, -1);
+ }
+-
+- if (gtk_tree_model_iter_has_child(model, &iterItem))
+- {
+-
+- /* Recursively traverse child items */
+- gtk_tree_model_iter_children(model, &iterChild, &iterItem);
+- gtkTreeUpdateImages(ih, model, iterChild, mode);
+- }
+ }
+ else 
+ {
+@@ -499,9 +479,6 @@ static void gtkTreeUpdateImages(Ihandle* ih, GtkTreeModel* model, GtkTreeIter it
+ gtk_tree_store_set(GTK_TREE_STORE(model), &iterItem, IUPGTK_TREE_IMAGE, ih->data->def_image_leaf, -1);
+ }
+ }
+-
+- /* Go to next sibling item */
+- hasItem = gtk_tree_model_iter_next(model, &iterItem);
+ }
+ }
+ 
+@@ -536,26 +513,49 @@ void iupdrvTreeAddNode(Ihandle* ih, const char* name_id, int kind, const char* t
+ GtkTreeIter iterPrev, iterNewItem, iterParent;
+ GtkTreePath* path;
+ GdkColor color = {0L,0,0,0};
+- int kindPrev;
+-
+- if (!gtkTreeFindNodeFromString(ih, GTK_TREE_MODEL(store), name_id, &iterPrev))
+- return;
++ int kindPrev = -1;
+ 
+- gtk_tree_model_get(GTK_TREE_MODEL(store), &iterPrev, IUPGTK_TREE_KIND, &kindPrev, -1);
++ if (!gtkTreeFindNodeFromString(ih, name_id, &iterPrev))
++ {
++ /* check if the root was really specified */
++ int id = 0;
++ if (!iupStrToInt(name_id, &id) || id != -1)
++ return;
++ }
++ else
++ gtk_tree_model_get(GTK_TREE_MODEL(store), &iterPrev, IUPGTK_TREE_KIND, &kindPrev, -1);
+ 
+- if (kindPrev == ITREE_BRANCH && add)
+- gtk_tree_store_insert(store, &iterNewItem, &iterPrev, 0); /* iterPrev is parent of the new item (firstchild of it) */
++ if (kindPrev != -1)
++ {
++ /* Add the new node */
++ if (kindPrev == ITREE_BRANCH && add)
++ gtk_tree_store_insert(store, &iterNewItem, &iterPrev, 0); /* iterPrev is parent of the new item (firstchild of it) */
++ else
++ gtk_tree_store_insert_after(store, &iterNewItem, NULL, &iterPrev); /* iterPrev is sibling of the new item */
++ iupTreeAddToCache(ih, add, kindPrev, iterPrev.user_data, iterNewItem.user_data);
++ }
+ else
+- gtk_tree_store_insert_after(store, &iterNewItem, NULL, &iterPrev); /* iterPrev is sibling of the new item */
++ {
++ gtk_tree_store_append(store, &iterNewItem, NULL); /* root node */
++ iupTreeAddToCache(ih, 0, 0, NULL, iterNewItem.user_data);
++
++ /* store the stamp for the tree */
++ ih->data->stamp = iterNewItem.stamp;
++ }
+ 
+ iupgtkGetColor(iupAttribGetStr(ih, "FGCOLOR"), &color);
+ 
++ if (!title)
++ title = "";
++
+ /* set the attributes of the new node */
+ gtk_tree_store_set(store, &iterNewItem, IUPGTK_TREE_HAS_IMAGE, FALSE,
+ IUPGTK_TREE_HAS_IMAGE_EXPANDED, FALSE,
+ IUPGTK_TREE_TITLE, iupgtkStrConvertToUTF8(title),
+ IUPGTK_TREE_KIND, kind,
+- IUPGTK_TREE_COLOR, &color, -1);
++ IUPGTK_TREE_COLOR, &color, 
++ IUPGTK_TREE_SELECT, 0,
++ -1);
+ 
+ if (kind == ITREE_LEAF)
+ gtk_tree_store_set(store, &iterNewItem, IUPGTK_TREE_IMAGE, ih->data->def_image_leaf, -1);
+@@ -563,56 +563,113 @@ void iupdrvTreeAddNode(Ihandle* ih, const char* name_id, int kind, const char* t
+ gtk_tree_store_set(store, &iterNewItem, IUPGTK_TREE_IMAGE, ih->data->def_image_collapsed,
+ IUPGTK_TREE_IMAGE_EXPANDED, ih->data->def_image_expanded, -1);
+ 
+- if (kindPrev == ITREE_BRANCH && add)
+- iterParent = iterPrev;
+- else
+- gtk_tree_model_iter_parent(GTK_TREE_MODEL(store), &iterParent, &iterNewItem);
++ if (kindPrev != -1)
++ {
++ if (kindPrev == ITREE_BRANCH && add)
++ iterParent = iterPrev;
++ else if (!gtk_tree_model_iter_parent(GTK_TREE_MODEL(store), &iterParent, &iterNewItem))
++ return;
+ 
+- /* If this is the first child of the parent, then handle the ADDEXPANDED attribute */
+- if (gtk_tree_model_iter_n_children(GTK_TREE_MODEL(store), &iterParent) == 1)
++ /* If this is the first child of the parent, then handle the ADDEXPANDED attribute */
++ if (gtk_tree_model_iter_n_children(GTK_TREE_MODEL(store), &iterParent) == 1)
++ {
++ path = gtk_tree_model_get_path(GTK_TREE_MODEL(store), &iterParent);
++ iupAttribSetStr(ih, "_IUPTREE_IGNORE_BRANCH_CB", "1");
++ if (ih->data->add_expanded)
++ gtk_tree_view_expand_row(GTK_TREE_VIEW(ih->handle), path, FALSE);
++ else
++ gtk_tree_view_collapse_row(GTK_TREE_VIEW(ih->handle), path);
++ iupAttribSetStr(ih, "_IUPTREE_IGNORE_BRANCH_CB", NULL);
++ gtk_tree_path_free(path);
++ }
++ }
++ else
+ {
+- int depth;
+- path = gtk_tree_model_get_path(GTK_TREE_MODEL(store), &iterParent);
+- depth = gtk_tree_path_get_depth(path)-1;
+- if (ih->data->add_expanded || depth==0) /* if this is the first child of the root, expand always */
++ if (ih->data->node_count == 1)
+ {
+- iupAttribSetStr(ih, "_IUPTREE_IGNORE_BRANCHOPEN_CB", "1");
+- gtk_tree_view_expand_row(GTK_TREE_VIEW(ih->handle), path, FALSE);
++ /* MarkStart node */
++ iupAttribSetStr(ih, "_IUPTREE_MARKSTART_NODE", (char*)iterNewItem.user_data);
++
++ /* Set the default VALUE */
++ path = gtk_tree_model_get_path(GTK_TREE_MODEL(store), &iterNewItem);
++ gtk_tree_view_set_cursor(GTK_TREE_VIEW(ih->handle), path, NULL, FALSE);
++ gtk_tree_path_free(path);
+ }
+- else
+- gtk_tree_view_collapse_row(GTK_TREE_VIEW(ih->handle), path);
+- gtk_tree_path_free(path);
+ }
+ }
+ 
+-static void gtkTreeAddRootNode(Ihandle* ih)
++
++/*****************************************************************************/
++/* AUXILIAR FUNCTIONS */
++/*****************************************************************************/
++
++
++static void gtkTreeChildRebuildCacheRec(Ihandle* ih, GtkTreeModel *model, GtkTreeIter *iterItem, int *id)
+ {
+- GtkTreeStore* store = GTK_TREE_STORE(gtk_tree_view_get_model(GTK_TREE_VIEW(ih->handle)));
+- GtkTreePath* path;
+- GtkTreeIter iterRoot;
+- GdkColor color = {0L,0,0,0};
++ GtkTreeIter iterChild;
++ int hasItem = gtk_tree_model_iter_children(model, &iterChild, iterItem); /* get the firstchild */
++ while(hasItem)
++ {
++ (*id)++;
++ ih->data->node_cache[*id].node_handle = iterChild.user_data;
+ 
+- iupgtkGetColor(iupAttribGetStr(ih, "FGCOLOR"), &color);
++ /* go recursive to children */
++ gtkTreeChildRebuildCacheRec(ih, model, &iterChild, id);
++
++ /* Go to next sibling item */
++ hasItem = gtk_tree_model_iter_next(model, &iterChild);
++ }
++}
+ 
+- gtk_tree_store_append(store, &iterRoot, NULL); /* root node */
+- gtk_tree_store_set(store, &iterRoot, IUPGTK_TREE_IMAGE, ih->data->def_image_collapsed,
+- IUPGTK_TREE_HAS_IMAGE, FALSE,
+- IUPGTK_TREE_IMAGE_EXPANDED, ih->data->def_image_expanded,
+- IUPGTK_TREE_HAS_IMAGE_EXPANDED, FALSE,
+- IUPGTK_TREE_KIND, ITREE_BRANCH,
+- IUPGTK_TREE_COLOR, &color, -1);
++static void gtkTreeRebuildNodeCache(Ihandle* ih, int id, GtkTreeIter iterItem)
++{
++ GtkTreeModel* model = gtk_tree_view_get_model(GTK_TREE_VIEW(ih->handle));
++ ih->data->node_cache[id].node_handle = iterItem.user_data;
++ gtkTreeChildRebuildCacheRec(ih, model, &iterItem, &id);
++}
++
++static void gtkTreeChildCountRec(GtkTreeModel *model, GtkTreeIter *iterItem, int *count)
++{
++ GtkTreeIter iterChild;
++ int hasItem = gtk_tree_model_iter_children(model, &iterChild, iterItem); /* get the firstchild */
++ while(hasItem)
++ {
++ (*count)++;
+ 
+- path = gtk_tree_model_get_path(GTK_TREE_MODEL(store), &iterRoot);
+- /* MarkStart node */
+- iupAttribSetStr(ih, "_IUPTREE_MARKSTART_NODE", (char*)path);
++ /* go recursive to children */
++ gtkTreeChildCountRec(model, &iterChild, count);
+ 
+- /* Set the default VALUE */
+- gtk_tree_view_set_cursor(GTK_TREE_VIEW(ih->handle), path, NULL, FALSE);
++ /* Go to next sibling item */
++ hasItem = gtk_tree_model_iter_next(model, &iterChild);
++ }
++}
++
++int iupdrvTreeTotalChildCount(Ihandle* ih, InodeHandle* node_handle)
++{
++ int count = 0;
++ GtkTreeIter iterItem;
++ GtkTreeModel* model = gtk_tree_view_get_model(GTK_TREE_VIEW(ih->handle));
++ gtkTreeIterInit(ih, &iterItem, node_handle);
++ gtkTreeChildCountRec(model, &iterItem, &count);
++ return count;
++}
++
++InodeHandle* iupdrvTreeGetFocusNode(Ihandle* ih)
++{
++ GtkTreePath* path = NULL;
++ gtk_tree_view_get_cursor(GTK_TREE_VIEW(ih->handle), &path, NULL);
++ if (path)
++ {
++ GtkTreeIter iterItem;
++ GtkTreeModel* model = gtk_tree_view_get_model(GTK_TREE_VIEW(ih->handle));
++ gtk_tree_model_get_iter(model, &iterItem, path);
++ gtk_tree_path_free(path);
++ return iterItem.user_data;
++ }
++
++ return NULL;
+ }
+ 
+-/*****************************************************************************/
+-/* AUXILIAR FUNCTIONS */
+-/*****************************************************************************/
+ static void gtkTreeOpenCloseEvent(Ihandle* ih)
+ {
+ GtkTreeModel* model = gtk_tree_view_get_model(GTK_TREE_VIEW(ih->handle));
+@@ -620,7 +677,7 @@ static void gtkTreeOpenCloseEvent(Ihandle* ih)
+ GtkTreePath* path;
+ int kind;
+ 
+- if (!gtkTreeFindNodeFromString(ih, model, "", &iterItem))
++ if (!gtkTreeFindNodeFromString(ih, "", &iterItem))
+ return;
+ 
+ path = gtk_tree_model_get_path(model, &iterItem);
+@@ -637,27 +694,22 @@ static void gtkTreeOpenCloseEvent(Ihandle* ih)
+ }
+ }
+ 
+-static gboolean gtkTreeSelected_Foreach_Func(GtkTreeModel *model, GtkTreePath *path, GtkTreeIter *iter, GList **rowref_list)
++typedef struct _gtkTreeSelectMinMax
+ {
+- GtkTreeRowReference *rowref;
+-
+- rowref = gtk_tree_row_reference_new(model, path);
+- *rowref_list = g_list_append(*rowref_list, rowref);
++ Ihandle* ih;
++ int id1, id2;
++} gtkTreeSelectMinMax;
+ 
+- (void)iter;
+- return FALSE; /* do not stop walking the store, call us with next row */
+-}
+-
+-static gboolean gtkTreeSelected_Iter_Func(GtkTreeModel *model, GtkTreePath *path, GtkTreeIter *iter, GList **rowref_list)
++static gboolean gtkTreeSelected_Foreach_Func(GtkTreeModel *model, GtkTreePath *path, GtkTreeIter *iterItem, gtkTreeSelectMinMax *minmax)
+ {
+- GtkTreeRowReference *rowref;
+- GtkTreeIter iterParent;
+- if (!gtk_tree_model_iter_parent(model, &iterParent, iter)) /* the root node can't be deleted */
+- return FALSE; /* do not stop walking the store, call us with next row */
+-
+- rowref = gtk_tree_row_reference_new(model, path);
+- *rowref_list = g_list_append(*rowref_list, rowref);
++ int id = iupTreeFindNodeId(minmax->ih, iterItem->user_data);
++ if (id < minmax->id1)
++ minmax->id1 = id;
++ if (id > minmax->id2)
++ minmax->id2 = id;
+ 
++ (void)model;
++ (void)path;
+ return FALSE; /* do not stop walking the store, call us with next row */
+ }
+ 
+@@ -672,45 +724,48 @@ static void gtkTreeCallMultiSelectionCb(Ihandle* ih)
+ {
+ GtkTreeModel* model = gtk_tree_view_get_model(GTK_TREE_VIEW(ih->handle));
+ GtkTreeSelection* selection = gtk_tree_view_get_selection(GTK_TREE_VIEW(ih->handle));
+- GtkTreeIter iterRoot;
+- GList *rr_list = NULL;
+- GList *node;
+- int* id_rowItem;
+- int count_selected_rows, i = 0;
++ GtkTreeIter iterItem;
++ int i = 0, countItems;
++ gtkTreeSelectMinMax minmax;
+ 
+- gtk_tree_model_get_iter_first(model, &iterRoot);
++ minmax.ih = ih;
++ minmax.id1 = ih->data->node_count;
++ minmax.id2 = -1;
+ 
+- gtk_tree_selection_selected_foreach(selection, (GtkTreeSelectionForeachFunc)gtkTreeSelected_Foreach_Func, &rr_list);
+- count_selected_rows = g_list_length(rr_list);
+- id_rowItem = malloc(sizeof(int) * count_selected_rows);
++ gtk_tree_selection_selected_foreach(selection, (GtkTreeSelectionForeachFunc)gtkTreeSelected_Foreach_Func, &minmax);
++ if (minmax.id2 == -1)
++ return;
+ 
+- for(node = rr_list; node != NULL; node = node->next)
++ /* interactive selection of several nodes will NOT select hidden nodes,
++ so make sure that they are selected. */
++ for(i = minmax.id1; i <= minmax.id2; i++)
+ {
+- GtkTreePath* path = gtk_tree_row_reference_get_path(node->data);
+- if (path)
+- {
+- GtkTreeIter iterItem;
+- gtk_tree_model_get_iter(model, &iterItem, path);
+-
+- id_rowItem[i] = gtkTreeGetNodeId(ih, iterItem);
+- i++;
+-
+- gtk_tree_path_free(path);
+- }
++ gtkTreeIterInit(ih, &iterItem, ih->data->node_cache[i].node_handle);
++ if (!gtkTreeIsNodeSelected(model, &iterItem))
++ gtkTreeSelectNodeRaw(model, &iterItem, 1);
+ }
+ 
+- g_list_foreach(rr_list, (GFunc) gtk_tree_row_reference_free, NULL);
+- g_list_free(rr_list);
++ /* if last selected item is a branch, then select its children */
++ iupTreeSelectLastCollapsedBranch(ih, &(minmax.id2));
++
++ countItems = minmax.id2-minmax.id1+1;
+ 
+ if (cbMulti)
+- cbMulti(ih, id_rowItem, count_selected_rows);
+- else
+ {
+- for (i=0; i<count_selected_rows; i++)
+- cbSelec(ih, id_rowItem[i], 1);
+- }
++ int* id_rowItem = malloc(sizeof(int) * countItems);
++
++ for(i = 0; i < countItems; i++)
++ id_rowItem[i] = minmax.id1+i;
+ 
+- free(id_rowItem);
++ cbMulti(ih, id_rowItem, countItems);
++
++ free(id_rowItem);
++ }
++ else if (cbSelec)
++ {
++ for (i=0; i<countItems; i++)
++ cbSelec(ih, minmax.id1+i, 1);
++ }
+ }
+ }
+ 
+@@ -747,14 +802,22 @@ static int gtkTreeSetTopItemAttrib(Ihandle* ih, const char* value)
+ GtkTreeStore* store = GTK_TREE_STORE(gtk_tree_view_get_model(GTK_TREE_VIEW(ih->handle)));
+ GtkTreeIter iterItem;
+ GtkTreePath* path;
++ int kind;
+ 
+- if (!gtkTreeFindNodeFromString(ih, GTK_TREE_MODEL(store), value, &iterItem))
++ if (!gtkTreeFindNodeFromString(ih, value, &iterItem))
+ return 0;
+ 
+ path = gtk_tree_model_get_path(GTK_TREE_MODEL(store), &iterItem);
+ 
+- if (!gtk_tree_view_row_expanded(GTK_TREE_VIEW(ih->handle), path))
++ gtk_tree_model_get(GTK_TREE_MODEL(store), &iterItem, IUPGTK_TREE_KIND, &kind, -1);
++ if (kind == ITREE_LEAF)
++ gtk_tree_view_expand_to_path(GTK_TREE_VIEW(ih->handle), path);
++ else
++ {
++ int expanded = gtk_tree_view_row_expanded(GTK_TREE_VIEW(ih->handle), path);
+ gtk_tree_view_expand_to_path(GTK_TREE_VIEW(ih->handle), path);
++ if (!expanded) gtk_tree_view_collapse_row(GTK_TREE_VIEW(ih->handle), path);
++ }
+ 
+ gtk_tree_view_scroll_to_cell(GTK_TREE_VIEW(ih->handle), path, NULL, FALSE, 0, 0); /* scroll to visible */
+ 
+@@ -788,34 +851,23 @@ static int gtkTreeSetExpandAllAttrib(Ihandle* ih, const char* value)
+ if (iupStrBoolean(value))
+ gtk_tree_view_expand_all(GTK_TREE_VIEW(ih->handle));
+ else
+- {
+- GtkTreeModel* model = gtk_tree_view_get_model(GTK_TREE_VIEW(ih->handle));
+- GtkTreeIter iterRoot;
+- GtkTreePath* pathRoot;
+-
+ gtk_tree_view_collapse_all(GTK_TREE_VIEW(ih->handle));
+ 
+- /* The root node is always expanded */
+- gtk_tree_model_get_iter_first(model, &iterRoot);
+- pathRoot = gtk_tree_model_get_path(model, &iterRoot);
+- gtk_tree_view_expand_row(GTK_TREE_VIEW(ih->handle), pathRoot, FALSE);
+- gtk_tree_path_free(pathRoot);
+- }
+-
+ return 0;
+ }
+ 
+ static char* gtkTreeGetDepthAttrib(Ihandle* ih, const char* name_id)
+ {
+- char* depth;
++ char* str;
+ GtkTreeStore* store = GTK_TREE_STORE(gtk_tree_view_get_model(GTK_TREE_VIEW(ih->handle)));
+ GtkTreeIter iterItem;
+- if (!gtkTreeFindNodeFromString(ih, GTK_TREE_MODEL(store), name_id, &iterItem))
++
++ if (!gtkTreeFindNodeFromString(ih, name_id, &iterItem))
+ return NULL;
+ 
+- depth = iupStrGetMemory(10);
+- sprintf(depth, "%d", gtk_tree_store_iter_depth(store, &iterItem));
+- return depth;
++ str = iupStrGetMemory(10);
++ sprintf(str, "%d", gtk_tree_store_iter_depth(store, &iterItem));
++ return str;
+ }
+ 
+ static int gtkTreeSetMoveNodeAttrib(Ihandle* ih, const char* name_id, const char* value)
+@@ -824,14 +876,14 @@ static int gtkTreeSetMoveNodeAttrib(Ihandle* ih, const char* name_id, const char
+ GtkTreeIter iterItemSrc, iterItemDst, iterNewItem;
+ GtkTreeIter iterParent, iterNextParent;
+ 
+- if (!ih->handle) /* do not store the action before map */
++ if (!ih->handle) /* do not do the action before map */
+ return 0;
+ 
+ model = gtk_tree_view_get_model(GTK_TREE_VIEW(ih->handle));
+- if (!gtkTreeFindNodeFromString(ih, model, name_id, &iterItemSrc))
++ if (!gtkTreeFindNodeFromString(ih, name_id, &iterItemSrc))
+ return 0;
+ 
+- if (!gtkTreeFindNodeFromString(ih, model, value, &iterItemDst))
++ if (!gtkTreeFindNodeFromString(ih, value, &iterItemDst))
+ return 0;
+ 
+ /* If Drag item is an ancestor of Drop item then return */
+@@ -843,12 +895,8 @@ static int gtkTreeSetMoveNodeAttrib(Ihandle* ih, const char* name_id, const char
+ iterParent = iterNextParent;
+ }
+ 
+- /* Copying the node and its children to the new position */
+- gtkTreeCopyNode(ih, model, &iterItemSrc, &iterItemDst, &iterNewItem, 0); /* not a full copy, preserve user data */
+-
+- /* Deleting the node of its old position */
+- /* do not delete the user data, we copy the references in CopyNode */
+- gtk_tree_store_remove(GTK_TREE_STORE(model), &iterItemSrc);
++ /* Move the node and its children to the new position */
++ gtkTreeCopyMoveNode(ih, model, &iterItemSrc, &iterItemDst, &iterNewItem, 0);
+ 
+ return 0;
+ }
+@@ -859,14 +907,14 @@ static int gtkTreeSetCopyNodeAttrib(Ihandle* ih, const char* name_id, const char
+ GtkTreeIter iterItemSrc, iterItemDst, iterNewItem;
+ GtkTreeIter iterParent, iterNextParent;
+ 
+- if (!ih->handle) /* do not store the action before map */
++ if (!ih->handle) /* do not do the action before map */
+ return 0;
+ 
+ model = gtk_tree_view_get_model(GTK_TREE_VIEW(ih->handle));
+- if (!gtkTreeFindNodeFromString(ih, model, name_id, &iterItemSrc))
++ if (!gtkTreeFindNodeFromString(ih, name_id, &iterItemSrc))
+ return 0;
+ 
+- if (!gtkTreeFindNodeFromString(ih, model, value, &iterItemDst))
++ if (!gtkTreeFindNodeFromString(ih, value, &iterItemDst))
+ return 0;
+ 
+ /* If Drag item is an ancestor of Drop item then return */
+@@ -878,8 +926,8 @@ static int gtkTreeSetCopyNodeAttrib(Ihandle* ih, const char* name_id, const char
+ iterParent = iterNextParent;
+ }
+ 
+- /* Copying the node and its children to the new position */
+- gtkTreeCopyNode(ih, model, &iterItemSrc, &iterItemDst, &iterNewItem, 1);
++ /* Copy the node and its children to the new position */
++ gtkTreeCopyMoveNode(ih, model, &iterItemSrc, &iterItemDst, &iterNewItem, 1);
+ 
+ return 0;
+ }
+@@ -891,7 +939,7 @@ static char* gtkTreeGetColorAttrib(Ihandle* ih, const char* name_id)
+ GtkTreeIter iterItem;
+ GdkColor *color;
+ 
+- if (!gtkTreeFindNodeFromString(ih, model, name_id, &iterItem))
++ if (!gtkTreeFindNodeFromString(ih, name_id, &iterItem))
+ return NULL;
+ 
+ gtk_tree_model_get(model, &iterItem, IUPGTK_TREE_COLOR, &color, -1);
+@@ -912,7 +960,7 @@ static int gtkTreeSetColorAttrib(Ihandle* ih, const char* name_id, const char* v
+ GdkColor color;
+ unsigned char r, g, b;
+ 
+- if (!gtkTreeFindNodeFromString(ih, GTK_TREE_MODEL(store), name_id, &iterItem))
++ if (!gtkTreeFindNodeFromString(ih, name_id, &iterItem))
+ return 0;
+ 
+ if (!iupStrToRGB(value, &r, &g, &b))
+@@ -931,14 +979,14 @@ static char* gtkTreeGetParentAttrib(Ihandle* ih, const char* name_id)
+ GtkTreeIter iterParent;
+ char* str;
+ 
+- if (!gtkTreeFindNodeFromString(ih, model, name_id, &iterItem))
++ if (!gtkTreeFindNodeFromString(ih, name_id, &iterItem))
+ return NULL;
+ 
+ if (!gtk_tree_model_iter_parent(model, &iterParent, &iterItem))
+ return NULL;
+ 
+ str = iupStrGetMemory(10);
+- sprintf(str, "%d", gtkTreeGetNodeId(ih, iterParent));
++ sprintf(str, "%d", gtkTreeFindNodeId(ih, &iterParent));
+ return str;
+ }
+ 
+@@ -948,7 +996,7 @@ static char* gtkTreeGetChildCountAttrib(Ihandle* ih, const char* name_id)
+ GtkTreeIter iterItem;
+ char* str;
+ 
+- if (!gtkTreeFindNodeFromString(ih, model, name_id, &iterItem))
++ if (!gtkTreeFindNodeFromString(ih, name_id, &iterItem))
+ return NULL;
+ 
+ str = iupStrGetMemory(10);
+@@ -956,40 +1004,13 @@ static char* gtkTreeGetChildCountAttrib(Ihandle* ih, const char* name_id)
+ return str;
+ }
+ 
+-static int gtkTreeCount(GtkTreeModel* model, GtkTreeIter iterBranch)
+-{
+- GtkTreeIter iterChild;
+- int count = 0;
+- int hasItem = gtk_tree_model_iter_children(model, &iterChild, &iterBranch); /* get the firstchild */
+- count++;
+- while(hasItem)
+- {
+- count += gtkTreeCount(model, iterChild);
+-
+- /* Go to next sibling item */
+- hasItem = gtk_tree_model_iter_next(model, &iterChild);
+- }
+-
+- return count;
+-}
+-
+-static char* gtkTreeGetCountAttrib(Ihandle* ih)
+-{
+- GtkTreeIter iterRoot;
+- GtkTreeModel* model = gtk_tree_view_get_model(GTK_TREE_VIEW(ih->handle));
+- char* str = iupStrGetMemory(10);
+- gtk_tree_model_get_iter_first(model, &iterRoot);
+- sprintf(str, "%d", gtkTreeCount(model, iterRoot));
+- return str;
+-}
+-
+ static char* gtkTreeGetKindAttrib(Ihandle* ih, const char* name_id)
+ {
+ GtkTreeModel* model = gtk_tree_view_get_model(GTK_TREE_VIEW(ih->handle));
+ GtkTreeIter iterItem;
+ int kind;
+ 
+- if (!gtkTreeFindNodeFromString(ih, model, name_id, &iterItem))
++ if (!gtkTreeFindNodeFromString(ih, name_id, &iterItem))
+ return NULL;
+ 
+ gtk_tree_model_get(model, &iterItem, IUPGTK_TREE_KIND, &kind, -1);
+@@ -1005,7 +1026,7 @@ static char* gtkTreeGetStateAttrib(Ihandle* ih, const char* name_id)
+ GtkTreeModel* model = gtk_tree_view_get_model(GTK_TREE_VIEW(ih->handle));
+ GtkTreeIter iterItem;
+ 
+- if (!gtkTreeFindNodeFromString(ih, model, name_id, &iterItem))
++ if (!gtkTreeFindNodeFromString(ih, name_id, &iterItem))
+ return NULL;
+ 
+ if (gtk_tree_model_iter_has_child(model, &iterItem))
+@@ -1028,13 +1049,20 @@ static int gtkTreeSetStateAttrib(Ihandle* ih, const char* name_id, const char* v
+ GtkTreeModel* model = gtk_tree_view_get_model(GTK_TREE_VIEW(ih->handle));
+ GtkTreeIter iterItem;
+ GtkTreePath* path;
++ int kind;
+ 
+- if (!gtkTreeFindNodeFromString(ih, model, name_id, &iterItem))
++ if (!gtkTreeFindNodeFromString(ih, name_id, &iterItem))
+ return 0;
+ 
+- path = gtk_tree_model_get_path(model, &iterItem);
+- gtkTreeExpandItem(ih, path, iupStrEqualNoCase(value, "EXPANDED"));
+- gtk_tree_path_free(path);
++ gtk_tree_model_get(model, &iterItem, IUPGTK_TREE_KIND, &kind, -1);
++ if (kind == ITREE_BRANCH)
++ {
++ path = gtk_tree_model_get_path(model, &iterItem);
++ iupAttribSetStr(ih, "_IUPTREE_IGNORE_BRANCH_CB", "1");
++ gtkTreeExpandItem(ih, path, iupStrEqualNoCase(value, "EXPANDED"));
++ iupAttribSetStr(ih, "_IUPTREE_IGNORE_BRANCH_CB", NULL);
++ gtk_tree_path_free(path);
++ }
+ 
+ return 0;
+ }
+@@ -1050,7 +1078,7 @@ static char* gtkTreeGetTitleAttrib(Ihandle* ih, const char* name_id)
+ {
+ GtkTreeModel* model = gtk_tree_view_get_model(GTK_TREE_VIEW(ih->handle));
+ GtkTreeIter iterItem;
+- if (!gtkTreeFindNodeFromString(ih, model, name_id, &iterItem))
++ if (!gtkTreeFindNodeFromString(ih, name_id, &iterItem))
+ return NULL;
+ return gtkTreeGetTitle(model, iterItem);
+ }
+@@ -1059,8 +1087,10 @@ static int gtkTreeSetTitleAttrib(Ihandle* ih, const char* name_id, const char* v
+ {
+ GtkTreeStore* store = GTK_TREE_STORE(gtk_tree_view_get_model(GTK_TREE_VIEW(ih->handle)));
+ GtkTreeIter iterItem;
+- if (!gtkTreeFindNodeFromString(ih, GTK_TREE_MODEL(store), name_id, &iterItem))
++ if (!gtkTreeFindNodeFromString(ih, name_id, &iterItem))
+ return 0;
++ if (!value)
++ value = "";
+ gtk_tree_store_set(store, &iterItem, IUPGTK_TREE_TITLE, iupgtkStrConvertToUTF8(value), -1);
+ return 0;
+ }
+@@ -1070,7 +1100,7 @@ static int gtkTreeSetTitleFontAttrib(Ihandle* ih, const char* name_id, const cha
+ PangoFontDescription* fontdesc = NULL;
+ GtkTreeStore* store = GTK_TREE_STORE(gtk_tree_view_get_model(GTK_TREE_VIEW(ih->handle)));
+ GtkTreeIter iterItem;
+- if (!gtkTreeFindNodeFromString(ih, GTK_TREE_MODEL(store), name_id, &iterItem))
++ if (!gtkTreeFindNodeFromString(ih, name_id, &iterItem))
+ return 0;
+ if (value)
+ fontdesc = iupgtkGetPangoFontDesc(value);
+@@ -1083,49 +1113,12 @@ static char* gtkTreeGetTitleFontAttrib(Ihandle* ih, const char* name_id)
+ PangoFontDescription* fontdesc;
+ GtkTreeModel* model = gtk_tree_view_get_model(GTK_TREE_VIEW(ih->handle));
+ GtkTreeIter iterItem;
+- if (!gtkTreeFindNodeFromString(ih, model, name_id, &iterItem))
++ if (!gtkTreeFindNodeFromString(ih, name_id, &iterItem))
+ return NULL;
+ gtk_tree_model_get(model, &iterItem, IUPGTK_TREE_FONT, &fontdesc, -1);
+ return pango_font_description_to_string(fontdesc);
+ }
+ 
+-static char* gtkTreeGetFindUserDataAttrib(Ihandle* ih, const char* name_id)
+-{
+- GtkTreeModel* model = gtk_tree_view_get_model(GTK_TREE_VIEW(ih->handle));
+- int id;
+- char* str = (char*)(name_id+1); /* skip ':' */
+- void* userdata = NULL;
+- if (sscanf(str, "%p", &userdata)!=1)
+- return NULL;
+- id = gtkTreeGetUserDataId(ih, model, userdata);
+- if (id == -1)
+- return NULL;
+- str = iupStrGetMemory(16);
+- sprintf(str, "%d", id);
+- return str;
+-}
+-
+-static char* gtkTreeGetUserDataAttrib(Ihandle* ih, const char* name_id)
+-{
+- GtkTreeModel* model = gtk_tree_view_get_model(GTK_TREE_VIEW(ih->handle));
+- GtkTreeIter iterItem;
+- char* userdata;
+- if (!gtkTreeFindNodeFromString(ih, model, name_id, &iterItem))
+- return NULL;
+- gtk_tree_model_get(model, &iterItem, IUPGTK_TREE_USERDATA, &userdata, -1);
+- return userdata;
+-}
+-
+-static int gtkTreeSetUserDataAttrib(Ihandle* ih, const char* name_id, const char* value)
+-{
+- GtkTreeStore* store = GTK_TREE_STORE(gtk_tree_view_get_model(GTK_TREE_VIEW(ih->handle)));
+- GtkTreeIter iterItem;
+- if (!gtkTreeFindNodeFromString(ih, GTK_TREE_MODEL(store), name_id, &iterItem))
+- return 0;
+- gtk_tree_store_set(store, &iterItem, IUPGTK_TREE_USERDATA, value, -1);
+- return 0;
+-}
+-
+ static char* gtkTreeGetValueAttrib(Ihandle* ih)
+ {
+ GtkTreeModel* model = gtk_tree_view_get_model(GTK_TREE_VIEW(ih->handle));
+@@ -1140,67 +1133,117 @@ static char* gtkTreeGetValueAttrib(Ihandle* ih)
+ gtk_tree_path_free(path);
+ 
+ str = iupStrGetMemory(16);
+- sprintf(str, "%d", gtkTreeGetNodeId(ih, iterItem));
++ sprintf(str, "%d", gtkTreeFindNodeId(ih, &iterItem));
+ return str;
+ }
+ 
+- return "0"; /* default VALUE is root */
++ if (ih->data->node_count)
++ return "0"; /* default VALUE is root */
++ else
++ return "-1";
++}
++
++static char* gtkTreeGetMarkedNodesAttrib(Ihandle* ih)
++{
++ char* str = iupStrGetMemory(ih->data->node_count+1);
++ GtkTreeModel* model = gtk_tree_view_get_model(GTK_TREE_VIEW(ih->handle));
++ GtkTreeIter iterItem;
++ int i;
++
++ for (i=0; i<ih->data->node_count; i++)
++ {
++ gtkTreeIterInit(ih, &iterItem, ih->data->node_cache[i].node_handle);
++ if (gtkTreeIsNodeSelected(model, &iterItem))
++ str[i] = '+';
++ else
++ str[i] = '-';
++ }
++
++ str[ih->data->node_count] = 0;
++ return str;
++}
++
++static int gtkTreeSetMarkedNodesAttrib(Ihandle* ih, const char* value)
++{
++ int count, i;
++ GtkTreeModel* model;
++ GtkTreeIter iterItem;
++ GtkTreeSelection* selection;
++
++ if (ih->data->mark_mode==ITREE_MARK_SINGLE || !value)
++ return 0;
++
++ count = strlen(value);
++ if (count > ih->data->node_count)
++ count = ih->data->node_count;
++
++ selection = gtk_tree_view_get_selection(GTK_TREE_VIEW(ih->handle));
++ model = gtk_tree_view_get_model(GTK_TREE_VIEW(ih->handle));
++
++ iupAttribSetStr(ih, "_IUPTREE_IGNORE_SELECTION_CB", "1");
++
++ for (i=0; i<count; i++)
++ {
++ gtkTreeIterInit(ih, &iterItem, ih->data->node_cache[i].node_handle);
++ if (value[i] == '+')
++ gtkTreeSelectNode(model, selection, &iterItem, 1);
++ else
++ gtkTreeSelectNode(model, selection, &iterItem, 0);
++ }
++
++ iupAttribSetStr(ih, "_IUPTREE_IGNORE_SELECTION_CB", NULL);
++
++ return 0;
+ }
+ 
+ static int gtkTreeSetMarkAttrib(Ihandle* ih, const char* value)
+ {
+ GtkTreeModel* model = gtk_tree_view_get_model(GTK_TREE_VIEW(ih->handle));
+ GtkTreeSelection* selection = gtk_tree_view_get_selection(GTK_TREE_VIEW(ih->handle));
+- GtkTreeIter iterRoot;
+ 
+ if (ih->data->mark_mode==ITREE_MARK_SINGLE)
+ return 0;
+ 
+- gtk_tree_model_get_iter_first(model, &iterRoot);
+-
+ if(iupStrEqualNoCase(value, "BLOCK"))
+ {
++ GtkTreeIter iterItem1, iterItem2;
+ GtkTreePath* pathFocus;
+ gtk_tree_view_get_cursor(GTK_TREE_VIEW(ih->handle), &pathFocus, NULL);
+- gtk_tree_selection_select_range(selection, (GtkTreePath*)iupAttribGet(ih, "_IUPTREE_MARKSTART_NODE"), pathFocus);
++ gtk_tree_model_get_iter(model, &iterItem1, pathFocus);
+ gtk_tree_path_free(pathFocus);
++
++ gtkTreeIterInit(ih, &iterItem2, iupAttribGet(ih, "_IUPTREE_MARKSTART_NODE"));
++
++ gtkTreeSelectRange(ih, model, selection, &iterItem1, &iterItem2, 0);
+ }
+ else if(iupStrEqualNoCase(value, "CLEARALL"))
+- gtk_tree_selection_unselect_all(selection);
++ gtkTreeSelectAll(ih, model, selection, 0);
+ else if(iupStrEqualNoCase(value, "MARKALL"))
+- gtk_tree_selection_select_all(selection);
++ gtkTreeSelectAll(ih, model, selection, 1);
+ else if(iupStrEqualNoCase(value, "INVERTALL")) /* INVERTALL *MUST* appear before INVERT, or else INVERTALL will never be called. */
+- gtkTreeInvertAllNodeMarking(ih, model, selection, &iterRoot);
++ gtkTreeInvertAllNodeMarking(ih, model, selection);
+ else if(iupStrEqualPartial(value, "INVERT"))
+ {
+ /* iupStrEqualPartial allows the use of "INVERTid" form */
+ GtkTreeIter iterItem;
+- if (!gtkTreeFindNodeFromString(ih, model, &value[strlen("INVERT")], &iterItem))
++ if (!gtkTreeFindNodeFromString(ih, &value[strlen("INVERT")], &iterItem))
+ return 0;
+ 
+- if(gtk_tree_selection_iter_is_selected(selection, &iterItem))
+- gtk_tree_selection_unselect_iter(selection, &iterItem);
+- else
+- gtk_tree_selection_select_iter(selection, &iterItem);
++ gtkTreeSelectNode(model, selection, &iterItem, -1); /* toggle */
+ }
+ else
+ {
+- GtkTreePath *path1, *path2;
+ GtkTreeIter iterItem1, iterItem2;
+ char str1[50], str2[50];
+ if (iupStrToStrStr(value, str1, str2, '-')!=2)
+ return 0;
+ 
+- if (!gtkTreeFindNodeFromString(ih, model, str1, &iterItem1))
++ if (!gtkTreeFindNodeFromString(ih, str1, &iterItem1))
+ return 0;
+- if (!gtkTreeFindNodeFromString(ih, model, str2, &iterItem2))
++ if (!gtkTreeFindNodeFromString(ih, str2, &iterItem2))
+ return 0;
+ 
+- path1 = gtk_tree_model_get_path(model, &iterItem1);
+- path2 = gtk_tree_model_get_path(model, &iterItem2);
+- gtk_tree_selection_select_range(selection, path1, path2);
+- gtk_tree_path_free(path1);
+- gtk_tree_path_free(path2);
++ gtkTreeSelectRange(ih, model, selection, &iterItem1, &iterItem2, 0);
+ }
+ 
+ return 1;
+@@ -1210,148 +1253,112 @@ static int gtkTreeSetValueAttrib(Ihandle* ih, const char* value)
+ {
+ GtkTreeModel* model = gtk_tree_view_get_model(GTK_TREE_VIEW(ih->handle));
+ GtkTreeSelection* selection = gtk_tree_view_get_selection(GTK_TREE_VIEW(ih->handle));
+- GtkTreeIter iterRoot, iterItem;
++ GtkTreeIter iterItem;
+ GtkTreePath* path;
++ int kind;
+ 
+ if (gtkTreeSetMarkAttrib(ih, value))
+ return 0;
+ 
+- gtk_tree_model_get_iter_first(model, &iterRoot);
+-
+- if (iupStrEqualNoCase(value, "ROOT"))
+- iterItem = iterRoot;
++ if (iupStrEqualNoCase(value, "ROOT") || iupStrEqualNoCase(value, "FIRST"))
++ gtk_tree_model_get_iter_first(model, &iterItem);
+ else if(iupStrEqualNoCase(value, "LAST"))
+- iterItem = gtkTreeGetLastVisibleNode(ih, model, iterRoot);
++ gtkTreeGetLastVisibleNode(ih, model, &iterItem);
+ else if(iupStrEqualNoCase(value, "PGUP"))
+ {
+- GtkTreeIter iterPrev;
+-
+ GtkTreePath* pathFocus;
+ gtk_tree_view_get_cursor(GTK_TREE_VIEW(ih->handle), &pathFocus, NULL);
+- gtk_tree_model_get_iter(model, &iterPrev, pathFocus);
++ gtk_tree_model_get_iter(model, &iterItem, pathFocus);
+ gtk_tree_path_free(pathFocus);
+ 
+- ih->data->id_control = -1;
+- gtkTreeFindVisibleNodeId(ih, model, iterRoot, iterPrev);
+- ih->data->id_control -= 10; /* less 10 visible nodes */
+-
+- if(ih->data->id_control < 0)
+- ih->data->id_control = 0; /* Begin of tree = Root id */
+-
+- iterItem = gtkTreeFindVisibleNodeFromId(ih, model, iterRoot);
++ gtkTreeGetPreviousVisibleNode(ih, model, &iterItem, 10);
+ }
+ else if(iupStrEqualNoCase(value, "PGDN"))
+ {
+- GtkTreeIter iterNext;
+-
+ GtkTreePath* pathFocus;
+ gtk_tree_view_get_cursor(GTK_TREE_VIEW(ih->handle), &pathFocus, NULL);
+- gtk_tree_model_get_iter(model, &iterNext, pathFocus);
++ gtk_tree_model_get_iter(model, &iterItem, pathFocus);
+ gtk_tree_path_free(pathFocus);
+ 
+- ih->data->id_control = -1;
+- gtkTreeFindVisibleNodeId(ih, model, iterRoot, iterNext);
+- ih->data->id_control += 10; /* more 10 visible nodes */
+-
+- iterNext = gtkTreeFindVisibleNodeFromId(ih, model, iterRoot);
+-
+- if (ih->data->id_control >= 0)
+- iterNext = gtkTreeGetLastVisibleNode(ih, model, iterRoot);
+-
+- iterItem = iterNext;
++ gtkTreeGetNextVisibleNode(ih, model, &iterItem, 10);
+ }
+ else if(iupStrEqualNoCase(value, "NEXT"))
+ {
+- GtkTreeIter iterNext;
+-
+ GtkTreePath* pathFocus;
+ gtk_tree_view_get_cursor(GTK_TREE_VIEW(ih->handle), &pathFocus, NULL);
+- gtk_tree_model_get_iter(model, &iterNext, pathFocus);
++ gtk_tree_model_get_iter(model, &iterItem, pathFocus);
+ gtk_tree_path_free(pathFocus);
+ 
+- ih->data->id_control = -1;
+- gtkTreeFindVisibleNodeId(ih, model, iterRoot, iterNext);
+- ih->data->id_control++; /* more 1 visible node */
+-
+- iterNext = gtkTreeFindVisibleNodeFromId(ih, model, iterRoot);
+-
+- if (ih->data->id_control >= 0)
+- iterNext = gtkTreeGetLastVisibleNode(ih, model, iterRoot);
+-
+- iterItem = iterNext;
++ gtkTreeGetNextVisibleNode(ih, model, &iterItem, 1);
+ }
+ else if(iupStrEqualNoCase(value, "PREVIOUS"))
+ {
+- GtkTreeIter iterPrev;
+-
+ GtkTreePath* pathFocus;
+ gtk_tree_view_get_cursor(GTK_TREE_VIEW(ih->handle), &pathFocus, NULL);
+- gtk_tree_model_get_iter(model, &iterPrev, pathFocus);
++ gtk_tree_model_get_iter(model, &iterItem, pathFocus);
+ gtk_tree_path_free(pathFocus);
+ 
+- ih->data->id_control = -1;
+- gtkTreeFindVisibleNodeId(ih, model, iterRoot, iterPrev);
+- ih->data->id_control--; /* less 1 visible node */
+-
+- if (ih->data->id_control < 0)
+- ih->data->id_control = 0;
+-
+- iterItem = gtkTreeFindVisibleNodeFromId(ih, model, iterRoot);
+- if (!iterItem.user_data)
+- return 0;
++ gtkTreeGetPreviousVisibleNode(ih, model, &iterItem, 1);
+ }
+ else
+ {
+- if (!gtkTreeFindNodeFromString(ih, model, value, &iterItem))
++ if (!gtkTreeFindNodeFromString(ih, value, &iterItem))
+ return 0;
+ }
+ 
+ /* select */
+ if (ih->data->mark_mode==ITREE_MARK_SINGLE)
+ {
+- iupAttribSetStr(ih, "_IUP_IGNORE_SELECTION", "1");
+- gtk_tree_selection_select_iter(selection, &iterItem);
++ iupAttribSetStr(ih, "_IUPTREE_IGNORE_SELECTION_CB", "1");
++ gtkTreeSelectNode(model, selection, &iterItem, 1);
++ iupAttribSetStr(ih, "_IUPTREE_IGNORE_SELECTION_CB", NULL);
+ }
+ 
+ path = gtk_tree_model_get_path(model, &iterItem);
++
++ /* make it visible */
++ gtk_tree_model_get(model, &iterItem, IUPGTK_TREE_KIND, &kind, -1);
++ if (kind == ITREE_LEAF)
++ gtk_tree_view_expand_to_path(GTK_TREE_VIEW(ih->handle), path);
++ else
++ {
++ int expanded = gtk_tree_view_row_expanded(GTK_TREE_VIEW(ih->handle), path);
++ gtk_tree_view_expand_to_path(GTK_TREE_VIEW(ih->handle), path);
++ if (!expanded) gtk_tree_view_collapse_row(GTK_TREE_VIEW(ih->handle), path);
++ }
++
+ gtk_tree_view_scroll_to_cell(GTK_TREE_VIEW(ih->handle), path, NULL, FALSE, 0, 0); /* scroll to visible */
++ iupAttribSetStr(ih, "_IUPTREE_IGNORE_SELECTION_CB", "1");
+ gtk_tree_view_set_cursor(GTK_TREE_VIEW(ih->handle), path, NULL, FALSE); /* set focus */
++ iupAttribSetStr(ih, "_IUPTREE_IGNORE_SELECTION_CB", NULL);
++
+ gtk_tree_path_free(path);
+ 
+- iupAttribSetInt(ih, "_IUPTREE_OLDVALUE", gtkTreeGetNodeId(ih, iterItem));
++ iupAttribSetInt(ih, "_IUPTREE_OLDVALUE", gtkTreeFindNodeId(ih, &iterItem));
+ 
+ return 0;
+ } 
+ 
+ static int gtkTreeSetMarkStartAttrib(Ihandle* ih, const char* name_id)
+ {
+- GtkTreePath *pathMarkStart, *pathMarkStartPrev;
+- GtkTreeModel* model = gtk_tree_view_get_model(GTK_TREE_VIEW(ih->handle));
+ GtkTreeIter iterItem;
+- if (!gtkTreeFindNodeFromString(ih, model, name_id, &iterItem))
++ if (!gtkTreeFindNodeFromString(ih, name_id, &iterItem))
+ return 0;
+ 
+- pathMarkStart = gtk_tree_model_get_path(model, &iterItem);
+-
+- pathMarkStartPrev = (GtkTreePath*)iupAttribGet(ih, "_IUPTREE_MARKSTART_NODE");
+- if (pathMarkStartPrev)
+- gtk_tree_path_free(pathMarkStartPrev);
+-
+- iupAttribSetStr(ih, "_IUPTREE_MARKSTART_NODE", (char*)pathMarkStart);
++ iupAttribSetStr(ih, "_IUPTREE_MARKSTART_NODE", (char*)iterItem.user_data);
+ 
+ return 1;
+ }
+ 
+ static char* gtkTreeGetMarkedAttrib(Ihandle* ih, const char* name_id)
+ {
+- GtkTreeSelection* selection;
+- GtkTreeModel* model = gtk_tree_view_get_model(GTK_TREE_VIEW(ih->handle));
++ GtkTreeModel* model;
+ GtkTreeIter iterItem;
+- if (!gtkTreeFindNodeFromString(ih, model, name_id, &iterItem))
++ if (!gtkTreeFindNodeFromString(ih, name_id, &iterItem))
+ return 0;
+ 
+- selection = gtk_tree_view_get_selection(GTK_TREE_VIEW(ih->handle));
+- if (gtk_tree_selection_iter_is_selected(selection, &iterItem))
++ model = gtk_tree_view_get_model(GTK_TREE_VIEW(ih->handle));
++ if (gtkTreeIsNodeSelected(model, &iterItem))
+ return "YES";
+ else
+ return "NO";
+@@ -1359,87 +1366,99 @@ static char* gtkTreeGetMarkedAttrib(Ihandle* ih, const char* name_id)
+ 
+ static int gtkTreeSetMarkedAttrib(Ihandle* ih, const char* name_id, const char* value)
+ {
++ GtkTreeModel* model;
+ GtkTreeSelection* selection;
+- GtkTreeModel* model = gtk_tree_view_get_model(GTK_TREE_VIEW(ih->handle));
+ GtkTreeIter iterItem;
+- if (!gtkTreeFindNodeFromString(ih, model, name_id, &iterItem))
++ if (!gtkTreeFindNodeFromString(ih, name_id, &iterItem))
+ return 0;
+ 
+- iupAttribSetStr(ih, "_IUP_IGNORE_SELECTION", "1");
++ iupAttribSetStr(ih, "_IUPTREE_IGNORE_SELECTION_CB", "1");
+ 
+ selection = gtk_tree_view_get_selection(GTK_TREE_VIEW(ih->handle));
++ model = gtk_tree_view_get_model(GTK_TREE_VIEW(ih->handle));
+ if (iupStrBoolean(value))
+- gtk_tree_selection_select_iter(selection, &iterItem);
++ gtkTreeSelectNode(model, selection, &iterItem, 1);
+ else
+- gtk_tree_selection_unselect_iter(selection, &iterItem);
++ gtkTreeSelectNode(model, selection, &iterItem, 0);
++
++ iupAttribSetStr(ih, "_IUPTREE_IGNORE_SELECTION_CB", NULL);
+ 
+ return 0;
+ }
+ 
+ static int gtkTreeSetDelNodeAttrib(Ihandle* ih, const char* name_id, const char* value)
+ {
+- if (!ih->handle) /* do not store the action before map */
++ if (!ih->handle) /* do not do the action before map */
+ return 0;
+- if (iupStrEqualNoCase(value, "SELECTED")) /* selected here means the specified one */
++ if (iupStrEqualNoCase(value, "ALL"))
+ {
+ GtkTreeModel* model = gtk_tree_view_get_model(GTK_TREE_VIEW(ih->handle));
+- GtkTreeIter iterItem;
+- GtkTreeIter iterParent;
++ gtkTreeCallNodeRemovedAll(ih);
+ 
+- if (!gtkTreeFindNodeFromString(ih, model, name_id, &iterItem))
+- return 0;
++ /* deleting the reference node (and it's children) */
++ iupAttribSetStr(ih, "_IUPTREE_IGNORE_SELECTION_CB", "1");
++ gtk_tree_store_clear(GTK_TREE_STORE(model));
++ iupAttribSetStr(ih, "_IUPTREE_IGNORE_SELECTION_CB", NULL);
++ return 0;
++ }
++ if (iupStrEqualNoCase(value, "SELECTED")) /* selected here means the reference node */
++ {
++ GtkTreeModel* model = gtk_tree_view_get_model(GTK_TREE_VIEW(ih->handle));
++ GtkTreeIter iterItem;
+ 
+- if (!gtk_tree_model_iter_parent(model, &iterParent, &iterItem)) /* the root node can't be deleted */
++ if (!gtkTreeFindNodeFromString(ih, name_id, &iterItem))
+ return 0;
+ 
+ gtkTreeCallNodeRemoved(ih, model, &iterItem);
+ 
+- /* deleting the specified node (and it's children) */
++ /* deleting the reference node (and it's children) */
++ iupAttribSetStr(ih, "_IUPTREE_IGNORE_SELECTION_CB", "1");
+ gtk_tree_store_remove(GTK_TREE_STORE(model), &iterItem);
++ iupAttribSetStr(ih, "_IUPTREE_IGNORE_SELECTION_CB", NULL);
+ }
+- else if(iupStrEqualNoCase(value, "CHILDREN")) /* children of the specified one */
++ else if(iupStrEqualNoCase(value, "CHILDREN")) /* children of the reference node */
+ {
+ GtkTreeModel* model = gtk_tree_view_get_model(GTK_TREE_VIEW(ih->handle));
+ GtkTreeIter iterItem, iterChild;
+ int hasChildren;
+ 
+- if (!gtkTreeFindNodeFromString(ih, model, name_id, &iterItem))
++ if (!gtkTreeFindNodeFromString(ih, name_id, &iterItem))
+ return 0;
+ 
+ hasChildren = gtk_tree_model_iter_children(model, &iterChild, &iterItem);
+ 
+- /* deleting the selected node's children */
++ iupAttribSetStr(ih, "_IUPTREE_IGNORE_SELECTION_CB", "1");
++
++ /* deleting the reference node children */
+ while(hasChildren)
+ {
+ gtkTreeCallNodeRemoved(ih, model, &iterChild);
+ hasChildren = gtk_tree_store_remove(GTK_TREE_STORE(model), &iterChild);
+ }
++
++ iupAttribSetStr(ih, "_IUPTREE_IGNORE_SELECTION_CB", NULL);
+ }
+ else if(iupStrEqualNoCase(value, "MARKED")) /* Delete the array of marked nodes */
+ {
++ int i;
+ GtkTreeModel* model = gtk_tree_view_get_model(GTK_TREE_VIEW(ih->handle));
+- GtkTreeSelection* selection = gtk_tree_view_get_selection(GTK_TREE_VIEW(ih->handle));
+- GList *rr_list = NULL;
+- GList *node;
++ GtkTreeIter iterItem;
+ 
+- gtk_tree_selection_selected_foreach(selection, (GtkTreeSelectionForeachFunc)gtkTreeSelected_Iter_Func, &rr_list);
++ iupAttribSetStr(ih, "_IUPTREE_IGNORE_SELECTION_CB", "1");
+ 
+- for(node = rr_list; node != NULL; node = node->next)
++ for(i = 1; i < ih->data->node_count; /* increment only if not removed */)
+ {
+- GtkTreePath* path = gtk_tree_row_reference_get_path(node->data);
+- if (path)
++ gtkTreeIterInit(ih, &iterItem, ih->data->node_cache[i].node_handle);
++ if (gtkTreeIsNodeSelected(model, &iterItem))
+ {
+- GtkTreeIter iterItem;
+- if (gtk_tree_model_get_iter(model, &iterItem, path))
+- {
+- gtkTreeCallNodeRemoved(ih, model, &iterItem);
+- gtk_tree_store_remove(GTK_TREE_STORE(model), &iterItem);
+- }
+- gtk_tree_path_free(path);
++ gtkTreeCallNodeRemoved(ih, model, &iterItem);
++ gtk_tree_store_remove(GTK_TREE_STORE(model), &iterItem);
+ }
+- gtk_tree_row_reference_free(node->data);
++ else
++ i++;
+ }
+- g_list_free(rr_list);
++
++ iupAttribSetStr(ih, "_IUPTREE_IGNORE_SELECTION_CB", NULL);
+ }
+ 
+ return 0;
+@@ -1450,36 +1469,11 @@ static int gtkTreeSetRenameAttrib(Ihandle* ih, const char* value)
+ if (ih->data->show_rename)
+ {
+ GtkTreePath* path;
+- IFni cbShowRename = (IFni)IupGetCallback(ih, "SHOWRENAME_CB");
+ GtkTreeViewColumn *focus_column;
+-
+ gtk_tree_view_get_cursor(GTK_TREE_VIEW(ih->handle), &path, &focus_column);
+-
+- if (cbShowRename)
+- {
+- GtkTreeIter iterItem;
+- GtkTreeModel* model = gtk_tree_view_get_model(GTK_TREE_VIEW(ih->handle));
+- gtk_tree_model_get_iter(model, &iterItem, path);
+- cbShowRename(ih, gtkTreeGetNodeId(ih, iterItem));
+- }
+-
+ gtk_tree_view_set_cursor(GTK_TREE_VIEW(ih->handle), path, focus_column, TRUE);
+ gtk_tree_path_free(path);
+ }
+- else
+- {
+- IFnis cbRenameNode = (IFnis)IupGetCallback(ih, "RENAMENODE_CB");
+- if (cbRenameNode)
+- {
+- GtkTreePath* path;
+- GtkTreeIter iterItem;
+- GtkTreeModel* model = gtk_tree_view_get_model(GTK_TREE_VIEW(ih->handle));
+- gtk_tree_view_get_cursor(GTK_TREE_VIEW(ih->handle), &path, NULL);
+- gtk_tree_model_get_iter(model, &iterItem, path);
+- gtk_tree_path_free(path);
+- cbRenameNode(ih, gtkTreeGetNodeId(ih, iterItem), gtkTreeGetTitle(model, iterItem)); 
+- }
+- }
+ 
+ (void)value;
+ return 0;
+@@ -1491,7 +1485,7 @@ static int gtkTreeSetImageExpandedAttrib(Ihandle* ih, const char* name_id, const
+ GtkTreeStore* store = GTK_TREE_STORE(gtk_tree_view_get_model(GTK_TREE_VIEW(ih->handle)));
+ GdkPixbuf* pixExpand = iupImageGetImage(value, ih, 0);
+ GtkTreeIter iterItem;
+- if (!gtkTreeFindNodeFromString(ih, GTK_TREE_MODEL(store), name_id, &iterItem))
++ if (!gtkTreeFindNodeFromString(ih, name_id, &iterItem))
+ return 0;
+ 
+ gtk_tree_model_get(GTK_TREE_MODEL(store), &iterItem, IUPGTK_TREE_KIND, &kind, -1);
+@@ -1514,7 +1508,7 @@ static int gtkTreeSetImageAttrib(Ihandle* ih, const char* name_id, const char* v
+ GtkTreeStore* store = GTK_TREE_STORE(gtk_tree_view_get_model(GTK_TREE_VIEW(ih->handle)));
+ GdkPixbuf* pixImage = iupImageGetImage(value, ih, 0);
+ GtkTreeIter iterItem;
+- if (!gtkTreeFindNodeFromString(ih, GTK_TREE_MODEL(store), name_id, &iterItem))
++ if (!gtkTreeFindNodeFromString(ih, name_id, &iterItem))
+ return 0;
+ 
+ if (pixImage)
+@@ -1539,42 +1533,30 @@ static int gtkTreeSetImageAttrib(Ihandle* ih, const char* name_id, const char* v
+ 
+ static int gtkTreeSetImageBranchExpandedAttrib(Ihandle* ih, const char* value)
+ {
+- GtkTreeIter iterRoot;
+- GtkTreeModel* model = gtk_tree_view_get_model(GTK_TREE_VIEW(ih->handle));
+ ih->data->def_image_expanded = iupImageGetImage(value, ih, 0);
+ 
+- gtk_tree_model_get_iter_first(model, &iterRoot);
+-
+- /* Update all images, starting at root node */
+- gtkTreeUpdateImages(ih, model, iterRoot, ITREE_UPDATEIMAGE_EXPANDED);
++ /* Update all images */
++ gtkTreeUpdateImages(ih, ITREE_UPDATEIMAGE_EXPANDED);
+ 
+ return 1;
+ }
+ 
+ static int gtkTreeSetImageBranchCollapsedAttrib(Ihandle* ih, const char* value)
+ {
+- GtkTreeIter iterRoot;
+- GtkTreeModel* model = gtk_tree_view_get_model(GTK_TREE_VIEW(ih->handle));
+ ih->data->def_image_collapsed = iupImageGetImage(value, ih, 0);
+ 
+- gtk_tree_model_get_iter_first(model, &iterRoot);
+-
+- /* Update all images, starting at root node */
+- gtkTreeUpdateImages(ih, model, iterRoot, ITREE_UPDATEIMAGE_COLLAPSED);
++ /* Update all images */
++ gtkTreeUpdateImages(ih, ITREE_UPDATEIMAGE_COLLAPSED);
+ 
+ return 1;
+ }
+ 
+ static int gtkTreeSetImageLeafAttrib(Ihandle* ih, const char* value)
+ {
+- GtkTreeIter iterRoot;
+- GtkTreeModel* model = gtk_tree_view_get_model(GTK_TREE_VIEW(ih->handle));
+ ih->data->def_image_leaf = iupImageGetImage(value, ih, 0);
+ 
+- gtk_tree_model_get_iter_first(model, &iterRoot);
+-
+- /* Update all images, starting at root node */
+- gtkTreeUpdateImages(ih, model, iterRoot, ITREE_UPDATEIMAGE_LEAF);
++ /* Update all images */
++ gtkTreeUpdateImages(ih, ITREE_UPDATEIMAGE_LEAF);
+ 
+ return 1;
+ }
+@@ -1655,6 +1637,7 @@ void iupdrvTreeUpdateMarkMode(Ihandle *ih)
+ if (ih->data->mark_mode==ITREE_MARK_MULTIPLE && !ih->data->show_dragdrop)
+ {
+ #if GTK_CHECK_VERSION(2, 10, 0)
++ if (iupAttribGetInt(ih, "RUBBERBAND"))
+ gtk_tree_view_set_rubber_banding(GTK_TREE_VIEW(ih->handle), TRUE);
+ #endif
+ }
+@@ -1704,6 +1687,19 @@ static void gtkTreeCellTextEditingStarted(GtkCellRenderer *cell, GtkCellEditable
+ PangoFontDescription* fontdesc = NULL;
+ GdkColor *color = NULL;
+ GtkTreeModel* model = gtk_tree_view_get_model(GTK_TREE_VIEW(ih->handle));
++ IFni cbShowRename;
++
++ gtk_tree_model_get_iter_from_string(model, &iterItem, path_string);
++
++ cbShowRename = (IFni)IupGetCallback(ih, "SHOWRENAME_CB");
++ if (cbShowRename && cbShowRename(ih, gtkTreeFindNodeId(ih, &iterItem))==IUP_IGNORE)
++ {
++ /* TODO: non of these worked:
++ gtk_cell_renderer_stop_editing(cell, TRUE);
++ gtk_cell_editable_editing_done(editable); */
++ gtk_editable_set_editable(GTK_EDITABLE(editable), FALSE);
++ return;
++ }
+ 
+ value = iupAttribGetStr(ih, "RENAMECARET");
+ if (value)
+@@ -1713,7 +1709,6 @@ static void gtkTreeCellTextEditingStarted(GtkCellRenderer *cell, GtkCellEditable
+ if (value)
+ gtkTreeSetRenameSelectionPos(editable, value);
+ 
+- gtk_tree_model_get_iter_from_string(model, &iterItem, path_string);
+ gtk_tree_model_get(model, &iterItem, IUPGTK_TREE_FONT, &fontdesc, -1);
+ if (fontdesc)
+ gtk_widget_modify_font(GTK_WIDGET(editable), fontdesc);
+@@ -1732,7 +1727,7 @@ static void gtkTreeCellTextEdited(GtkCellRendererText *cell, gchar *path_string,
+ IFnis cbRename;
+ 
+ if (!new_text)
+- return;
++ new_text = "";
+ 
+ model = gtk_tree_view_get_model(GTK_TREE_VIEW(ih->handle));
+ if (!gtk_tree_model_get_iter_from_string(model, &iterItem, path_string))
+@@ -1741,7 +1736,7 @@ static void gtkTreeCellTextEdited(GtkCellRendererText *cell, gchar *path_string,
+ cbRename = (IFnis)IupGetCallback(ih, "RENAME_CB");
+ if (cbRename)
+ {
+- if (cbRename(ih, gtkTreeGetNodeId(ih, iterItem), iupgtkStrConvertFromUTF8(new_text)) == IUP_IGNORE)
++ if (cbRename(ih, gtkTreeFindNodeId(ih, &iterItem), iupgtkStrConvertFromUTF8(new_text)) == IUP_IGNORE)
+ return;
+ }
+ 
+@@ -1766,8 +1761,8 @@ static int gtkTreeCallDragDropCb(Ihandle* ih, GtkTreeIter *iterDrag, GtkTreeIter
+ 
+ if (cbDragDrop)
+ {
+- int drag_id = gtkTreeGetNodeId(ih, *iterDrag);
+- int drop_id = gtkTreeGetNodeId(ih, *iterDrop);
++ int drag_id = gtkTreeFindNodeId(ih, iterDrag);
++ int drop_id = gtkTreeFindNodeId(ih, iterDrop);
+ return cbDragDrop(ih, drag_id, drop_id, is_shift, *is_ctrl);
+ }
+ 
+@@ -1804,22 +1799,17 @@ static void gtkTreeDragDataReceived(GtkWidget *widget, GdkDragContext *context,
+ {
+ GtkTreeIter iterNewItem;
+ 
+- /* Copy the dragged item to the new position. */
+- gtkTreeCopyNode(ih, model, &iterDrag, &iterDrop, &iterNewItem, is_ctrl);
+-
+- if (!is_ctrl)
+- {
+- /* do not delete the user data, we copy the references in CopyNode */
+- gtk_tree_store_remove(GTK_TREE_STORE(model), &iterDrag);
+- }
++ /* Copy or move the dragged item to the new position. */
++ gtkTreeCopyMoveNode(ih, model, &iterDrag, &iterDrop, &iterNewItem, is_ctrl);
+ 
+ /* set focus and selection */
++ if (iterNewItem.stamp)
+ {
+ GtkTreePath *pathNew;
+ GtkTreeSelection* selection = gtk_tree_view_get_selection(GTK_TREE_VIEW(ih->handle));
+ 
+ pathNew = gtk_tree_model_get_path(model, &iterNewItem);
+- gtk_tree_selection_select_path(selection, pathNew);
++ gtkTreeSelectNode(model, selection, &iterNewItem, 1);
+ 
+ gtk_tree_view_scroll_to_cell(GTK_TREE_VIEW(ih->handle), pathNew, NULL, FALSE, 0, 0);
+ gtk_tree_view_set_cursor(GTK_TREE_VIEW(ih->handle), pathNew, NULL, FALSE);
+@@ -1927,10 +1917,24 @@ static void gtkTreeDragBegin(GtkWidget *widget, GdkDragContext *context, Ihandle
+ (void)widget;
+ }
+ 
++static gboolean gtkTreeSelectionFunc(GtkTreeSelection *selection, GtkTreeModel *model, GtkTreePath *path, gboolean selected, Ihandle* ih)
++{
++ GtkTreeIter iterItem;
++ gtk_tree_model_get_iter(model, &iterItem, path);
++ gtkTreeSelectNodeRaw(model, &iterItem, !selected);
++ (void)ih;
++ (void)selection;
++ return TRUE;
++}
++
+ static void gtkTreeSelectionChanged(GtkTreeSelection* selection, Ihandle* ih)
+ {
+ IFnii cbSelec;
+ int is_ctrl = 0;
++ (void)selection;
++
++ if (iupAttribGet(ih, "_IUPTREE_IGNORE_SELECTION_CB"))
++ return;
+ 
+ if (ih->data->mark_mode == ITREE_MARK_MULTIPLE)
+ {
+@@ -1953,25 +1957,17 @@ static void gtkTreeSelectionChanged(GtkTreeSelection* selection, Ihandle* ih)
+ if (cbSelec)
+ {
+ int curpos = -1, is_selected = 0;
++ GtkTreeIter iterFocus;
++ GtkTreePath* pathFocus;
++ GtkTreeModel* model = gtk_tree_view_get_model(GTK_TREE_VIEW(ih->handle));
+ 
+- if (iupAttribGet(ih, "_IUP_IGNORE_SELECTION"))
+- {
+- iupAttribSetStr(ih, "_IUP_IGNORE_SELECTION", NULL);
+- return;
+- }
+-
++ gtk_tree_view_get_cursor(GTK_TREE_VIEW(ih->handle), &pathFocus, NULL);
++ if (pathFocus)
+ {
+- GtkTreeIter iterFocus;
+- GtkTreePath* pathFocus;
+- GtkTreeModel* model = gtk_tree_view_get_model(GTK_TREE_VIEW(ih->handle));
+- gtk_tree_view_get_cursor(GTK_TREE_VIEW(ih->handle), &pathFocus, NULL);
+- if (pathFocus)
+- {
+- gtk_tree_model_get_iter(model, &iterFocus, pathFocus);
+- gtk_tree_path_free(pathFocus);
+- curpos = gtkTreeGetNodeId(ih, iterFocus);
+- is_selected = gtk_tree_selection_iter_is_selected(selection, &iterFocus);
+- }
++ gtk_tree_model_get_iter(model, &iterFocus, pathFocus);
++ gtk_tree_path_free(pathFocus);
++ curpos = gtkTreeFindNodeId(ih, &iterFocus);
++ is_selected = gtkTreeIsNodeSelected(model, &iterFocus);
+ }
+ 
+ if (curpos == -1)
+@@ -1993,18 +1989,52 @@ static void gtkTreeSelectionChanged(GtkTreeSelection* selection, Ihandle* ih)
+ }
+ }
+ 
++static void gtkTreeUpdateSelectionChildren(Ihandle* ih, GtkTreeModel* model, GtkTreeSelection* selection, GtkTreeIter *iterItem)
++{
++ int expanded;
++ GtkTreeIter iterChild;
++ int hasItem = gtk_tree_model_iter_children(model, &iterChild, iterItem); /* get the firstchild */
++ while(hasItem)
++ {
++ if (gtkTreeIsNodeSelected(model, &iterChild))
++ gtk_tree_selection_select_iter(selection, &iterChild);
++
++ expanded = 0;
++ if (gtk_tree_model_iter_has_child(model, &iterChild))
++ {
++ GtkTreePath* path = gtk_tree_model_get_path(model, &iterChild);
++ expanded = gtk_tree_view_row_expanded(GTK_TREE_VIEW(ih->handle), path);
++ gtk_tree_path_free(path);
++ }
++
++ /* Recursive only if expanded */
++ if (expanded)
++ gtkTreeUpdateSelectionChildren(ih, model, selection, &iterChild); 
++
++ /* Go to next sibling item */
++ hasItem = gtk_tree_model_iter_next(model, &iterChild);
++ }
++}
++
++static void gtkTreeRowExpanded(GtkTreeView* tree_view, GtkTreeIter *iterItem, GtkTreePath *path, Ihandle* ih)
++{
++ GtkTreeSelection* selection = gtk_tree_view_get_selection(tree_view);
++ GtkTreeModel* model = gtk_tree_view_get_model(tree_view);
++ iupAttribSetStr(ih, "_IUPTREE_IGNORE_SELECTION_CB", "1");
++ gtkTreeUpdateSelectionChildren(ih, model, selection, iterItem);
++ iupAttribSetStr(ih, "_IUPTREE_IGNORE_SELECTION_CB", NULL);
++ (void)path;
++}
++
+ static gboolean gtkTreeTestExpandRow(GtkTreeView* tree_view, GtkTreeIter *iterItem, GtkTreePath *path, Ihandle* ih)
+ {
+ IFni cbBranchOpen = (IFni)IupGetCallback(ih, "BRANCHOPEN_CB");
+ if (cbBranchOpen)
+ {
+- if (iupAttribGet(ih, "_IUPTREE_IGNORE_BRANCHOPEN_CB"))
+- {
+- iupAttribSetStr(ih, "_IUPTREE_IGNORE_BRANCHOPEN_CB", NULL);
++ if (iupAttribGet(ih, "_IUPTREE_IGNORE_BRANCH_CB"))
+ return FALSE;
+- }
+ 
+- if (cbBranchOpen(ih, gtkTreeGetNodeId(ih, *iterItem)) == IUP_IGNORE)
++ if (cbBranchOpen(ih, gtkTreeFindNodeId(ih, iterItem)) == IUP_IGNORE)
+ return TRUE; /* prevent the change */
+ }
+ 
+@@ -2018,7 +2048,10 @@ static gboolean gtkTreeTestCollapseRow(GtkTreeView* tree_view, GtkTreeIter *iter
+ IFni cbBranchClose = (IFni)IupGetCallback(ih, "BRANCHCLOSE_CB");
+ if (cbBranchClose)
+ {
+- if (cbBranchClose(ih, gtkTreeGetNodeId(ih, *iterItem)) == IUP_IGNORE)
++ if (iupAttribGet(ih, "_IUPTREE_IGNORE_BRANCH_CB"))
++ return FALSE;
++
++ if (cbBranchClose(ih, gtkTreeFindNodeId(ih, iterItem)) == IUP_IGNORE)
+ return TRUE;
+ }
+ 
+@@ -2042,7 +2075,7 @@ static void gtkTreeRowActived(GtkTreeView* tree_view, GtkTreePath *path, GtkTree
+ 
+ /* just to leaf nodes */
+ if(gtk_tree_model_iter_has_child(model, &iterItem) == 0 && kind == ITREE_LEAF)
+- cbExecuteLeaf(ih, gtkTreeGetNodeId(ih, iterItem));
++ cbExecuteLeaf(ih, gtkTreeFindNodeId(ih, &iterItem));
+ 
+ (void)column;
+ (void)tree_view;
+@@ -2057,11 +2090,57 @@ static int gtkTreeConvertXYToPos(Ihandle* ih, int x, int y)
+ GtkTreeModel* model = gtk_tree_view_get_model(GTK_TREE_VIEW(ih->handle));
+ gtk_tree_model_get_iter(model, &iterItem, path);
+ gtk_tree_path_free (path);
+- return gtkTreeGetNodeId(ih, iterItem);
++ return gtkTreeFindNodeId(ih, &iterItem);
+ }
+ return -1;
+ }
+ 
++static Iarray* gtkTreeGetSelectedArrayId(Ihandle* ih)
++{
++ Iarray* selarray = iupArrayCreate(1, sizeof(int));
++ int i;
++ GtkTreeIter iterItem;
++ GtkTreeModel* model = gtk_tree_view_get_model(GTK_TREE_VIEW(ih->handle));
++
++ for (i = 0; i < ih->data->node_count; i++)
++ {
++ gtkTreeIterInit(ih, &iterItem, ih->data->node_cache[i].node_handle);
++ if (gtkTreeIsNodeSelected(model, &iterItem))
++ {
++ int* id_hitem = (int*)iupArrayInc(selarray);
++ int j = iupArrayCount(selarray);
++ id_hitem[j-1] = i;
++ }
++ }
++
++ return selarray;
++}
++
++static void gtkTreeCallMultiUnSelectionCb(Ihandle* ih)
++{
++ IFnIi cbMulti = (IFnIi)IupGetCallback(ih, "MULTIUNSELECTION_CB");
++ IFnii cbSelec = (IFnii)IupGetCallback(ih, "SELECTION_CB");
++ if (cbSelec || cbMulti)
++ {
++ Iarray* markedArray = gtkTreeGetSelectedArrayId(ih);
++ int* id_hitem = (int*)iupArrayGetData(markedArray);
++ int i, count = iupArrayCount(markedArray);
++
++ if (count > 1)
++ {
++ if (cbMulti)
++ cbMulti(ih, id_hitem, iupArrayCount(markedArray));
++ else
++ {
++ for (i=0; i<count; i++)
++ cbSelec(ih, id_hitem[i], 0);
++ }
++ }
++
++ iupArrayDestroy(markedArray);
++ }
++}
++
+ static gboolean gtkTreeButtonEvent(GtkWidget *treeview, GdkEventButton *evt, Ihandle* ih)
+ {
+ if (iupgtkButtonEvent(treeview, evt, ih) == TRUE)
+@@ -2097,6 +2176,18 @@ static gboolean gtkTreeButtonEvent(GtkWidget *treeview, GdkEventButton *evt, Iha
+ gtk_tree_path_free(path);
+ }
+ }
++ else if (evt->type == GDK_BUTTON_PRESS && evt->button == 1) /* left single press */
++ {
++ iupAttribSetInt(ih, "_IUPTREE_DRAG_X", (int)evt->x);
++ iupAttribSetInt(ih, "_IUPTREE_DRAG_Y", (int)evt->y);
++
++ if (ih->data->mark_mode==ITREE_MARK_MULTIPLE && 
++ !(evt->state & GDK_SHIFT_MASK) && !(evt->state & GDK_CONTROL_MASK))
++ {
++ gtkTreeCallMultiUnSelectionCb(ih);
++ iupAttribSetStr(ih, "_IUPTREE_EXTENDSELECT", "1");
++ }
++ }
+ else if (evt->type == GDK_BUTTON_RELEASE && evt->button == 1) /* left single release */
+ {
+ if (ih->data->mark_mode==ITREE_MARK_MULTIPLE && (evt->state & GDK_SHIFT_MASK))
+@@ -2109,16 +2200,7 @@ static gboolean gtkTreeButtonEvent(GtkWidget *treeview, GdkEventButton *evt, Iha
+ iupAttribSetStr(ih, "_IUPTREE_EXTENDSELECT", "2");
+ }
+ }
+- else if (evt->type == GDK_BUTTON_PRESS && evt->button == 1) /* left single press */
+- {
+- iupAttribSetInt(ih, "_IUPTREE_DRAG_X", (int)evt->x);
+- iupAttribSetInt(ih, "_IUPTREE_DRAG_Y", (int)evt->y);
+ 
+- if (ih->data->mark_mode==ITREE_MARK_MULTIPLE && 
+- !(evt->state & GDK_SHIFT_MASK) && !(evt->state & GDK_CONTROL_MASK))
+- iupAttribSetStr(ih, "_IUPTREE_EXTENDSELECT", "1");
+- }
+- 
+ return FALSE;
+ }
+ 
+@@ -2159,29 +2241,14 @@ static void gtkTreeEnableDragDrop(Ihandle* ih)
+ { "GTK_TREE_MODEL_ROW", GTK_TARGET_SAME_WIDGET, 0 }
+ };
+ 
+- if (iupAttribGetBoolean(ih, "AUTODRAGDROP"))
+- {
+- gtk_tree_view_enable_model_drag_source (GTK_TREE_VIEW(ih->handle),
+- GDK_BUTTON1_MASK,
+- row_targets,
+- G_N_ELEMENTS(row_targets),
+- GDK_ACTION_MOVE|GDK_ACTION_COPY);
+- gtk_tree_view_enable_model_drag_dest (GTK_TREE_VIEW(ih->handle),
+- row_targets,
+- G_N_ELEMENTS(row_targets),
+- GDK_ACTION_MOVE|GDK_ACTION_COPY);
+- }
+- else
+- {
+- gtk_drag_source_set(ih->handle, GDK_BUTTON1_MASK, row_targets, G_N_ELEMENTS(row_targets), GDK_ACTION_MOVE|GDK_ACTION_COPY);
+- gtk_drag_dest_set(ih->handle, GDK_BUTTON1_MASK, row_targets, G_N_ELEMENTS(row_targets), GDK_ACTION_MOVE|GDK_ACTION_COPY);
++ gtk_drag_source_set(ih->handle, GDK_BUTTON1_MASK, row_targets, G_N_ELEMENTS(row_targets), GDK_ACTION_MOVE|GDK_ACTION_COPY);
++ gtk_drag_dest_set(ih->handle, GDK_BUTTON1_MASK, row_targets, G_N_ELEMENTS(row_targets), GDK_ACTION_MOVE|GDK_ACTION_COPY);
+ 
+- g_signal_connect(G_OBJECT(ih->handle), "drag-begin", G_CALLBACK(gtkTreeDragBegin), ih);
+- g_signal_connect(G_OBJECT(ih->handle), "drag-motion", G_CALLBACK(gtkTreeDragMotion), ih);
+- g_signal_connect(G_OBJECT(ih->handle), "drag-leave", G_CALLBACK(gtkTreeDragLeave), NULL);
+- g_signal_connect(G_OBJECT(ih->handle), "drag-drop", G_CALLBACK(gtkTreeDragDrop), ih);
+- g_signal_connect(G_OBJECT(ih->handle), "drag-data-received", G_CALLBACK(gtkTreeDragDataReceived), ih);
+- }
++ g_signal_connect(G_OBJECT(ih->handle), "drag-begin", G_CALLBACK(gtkTreeDragBegin), ih);
++ g_signal_connect(G_OBJECT(ih->handle), "drag-motion", G_CALLBACK(gtkTreeDragMotion), ih);
++ g_signal_connect(G_OBJECT(ih->handle), "drag-leave", G_CALLBACK(gtkTreeDragLeave), NULL);
++ g_signal_connect(G_OBJECT(ih->handle), "drag-drop", G_CALLBACK(gtkTreeDragDrop), ih);
++ g_signal_connect(G_OBJECT(ih->handle), "drag-data-received", G_CALLBACK(gtkTreeDragDataReceived), ih);
+ }
+ 
+ /*****************************************************************************/
+@@ -2194,8 +2261,16 @@ static int gtkTreeMapMethod(Ihandle* ih)
+ GtkTreeSelection* selection;
+ GtkTreeViewColumn *column;
+ 
+- store = gtk_tree_store_new(9, GDK_TYPE_PIXBUF, G_TYPE_BOOLEAN, GDK_TYPE_PIXBUF, G_TYPE_BOOLEAN,
+- G_TYPE_STRING, G_TYPE_INT, GDK_TYPE_COLOR, PANGO_TYPE_FONT_DESCRIPTION, G_TYPE_POINTER);
++ store = gtk_tree_store_new(IUPGTK_TREE_LAST_DATA, 
++ GDK_TYPE_PIXBUF, /* IUPGTK_TREE_IMAGE */
++ G_TYPE_BOOLEAN, /* IUPGTK_TREE_HAS_IMAGE */
++ GDK_TYPE_PIXBUF, /* IUPGTK_TREE_IMAGE_EXPANDED */
++ G_TYPE_BOOLEAN, /* IUPGTK_TREE_HAS_IMAGE_EXPANDED */
++ G_TYPE_STRING, /* IUPGTK_TREE_TITLE */
++ G_TYPE_INT, /* IUPGTK_TREE_KIND */
++ GDK_TYPE_COLOR, /* IUPGTK_TREE_COLOR */
++ PANGO_TYPE_FONT_DESCRIPTION, /* IUPGTK_TREE_FONT */
++ G_TYPE_BOOLEAN); /* IUPGTK_TREE_SELECT */
+ 
+ ih->handle = gtk_tree_view_new_with_model(GTK_TREE_MODEL(store));
+ 
+@@ -2262,8 +2337,9 @@ static int gtkTreeMapMethod(Ihandle* ih)
+ gtk_scrolled_window_set_policy(scrolled_window, GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC);
+ 
+ selection = gtk_tree_view_get_selection(GTK_TREE_VIEW(ih->handle));
+- 
+ gtk_tree_selection_set_mode(selection, GTK_SELECTION_SINGLE);
++ gtk_tree_selection_set_select_function(selection, (GtkTreeSelectionFunc)gtkTreeSelectionFunc, ih, NULL);
++
+ gtk_tree_view_set_reorderable(GTK_TREE_VIEW(ih->handle), FALSE);
+ 
+ /* callbacks */
+@@ -2279,6 +2355,7 @@ static int gtkTreeMapMethod(Ihandle* ih)
+ g_signal_connect(G_OBJECT(ih->handle), "show-help", G_CALLBACK(iupgtkShowHelp), ih);
+ g_signal_connect(G_OBJECT(ih->handle), "motion-notify-event",G_CALLBACK(iupgtkMotionNotifyEvent), ih);
+ 
++ g_signal_connect(G_OBJECT(ih->handle), "row-expanded", G_CALLBACK(gtkTreeRowExpanded), ih);
+ g_signal_connect(G_OBJECT(ih->handle), "test-expand-row", G_CALLBACK(gtkTreeTestExpandRow), ih);
+ g_signal_connect(G_OBJECT(ih->handle), "test-collapse-row", G_CALLBACK(gtkTreeTestCollapseRow), ih);
+ g_signal_connect(G_OBJECT(ih->handle), "row-activated", G_CALLBACK(gtkTreeRowActived), ih);
+@@ -2301,7 +2378,8 @@ static int gtkTreeMapMethod(Ihandle* ih)
+ ih->data->def_image_collapsed = iupImageGetImage("IMGCOLLAPSED", ih, 0);
+ ih->data->def_image_expanded = iupImageGetImage("IMGEXPANDED", ih, 0);
+ 
+- gtkTreeAddRootNode(ih);
++ if (iupAttribGetInt(ih, "ADDROOT"))
++ iupdrvTreeAddNode(ih, "-1", ITREE_BRANCH, "", 0);
+ 
+ /* configure for DRAG&DROP of files */
+ if (IupGetCallback(ih, "DROPFILES_CB"))
+@@ -2309,13 +2387,23 @@ static int gtkTreeMapMethod(Ihandle* ih)
+ 
+ IupSetCallback(ih, "_IUP_XY2POS_CB", (Icallback)gtkTreeConvertXYToPos);
+ 
++ iupdrvTreeUpdateMarkMode(ih);
++
+ return IUP_NOERROR;
+ }
+ 
++static void gtkTreeUnMapMethod(Ihandle* ih)
++{
++ ih->data->node_count = 0;
++
++ iupdrvBaseUnMapMethod(ih);
++}
++
+ void iupdrvTreeInitClass(Iclass* ic)
+ {
+ /* Driver Dependent Class functions */
+ ic->Map = gtkTreeMapMethod;
++ ic->UnMap = gtkTreeUnMapMethod;
+ 
+ /* Visual */
+ iupClassRegisterAttribute(ic, "BGCOLOR", NULL, gtkTreeSetBgColorAttrib, IUPAF_SAMEASSYSTEM, "TXTBGCOLOR", IUPAF_DEFAULT);
+@@ -2324,7 +2412,6 @@ void iupdrvTreeInitClass(Iclass* ic)
+ /* IupTree Attributes - GENERAL */
+ iupClassRegisterAttribute(ic, "EXPANDALL", NULL, gtkTreeSetExpandAllAttrib, NULL, NULL, IUPAF_WRITEONLY|IUPAF_NO_INHERIT);
+ iupClassRegisterAttribute(ic, "INDENTATION", gtkTreeGetIndentationAttrib, gtkTreeSetIndentationAttrib, NULL, NULL, IUPAF_DEFAULT);
+- iupClassRegisterAttribute(ic, "COUNT", gtkTreeGetCountAttrib, NULL, NULL, NULL, IUPAF_NO_DEFAULTVALUE|IUPAF_READONLY|IUPAF_NO_INHERIT);
+ iupClassRegisterAttribute(ic, "DRAGDROP", NULL, iupgtkSetDragDropAttrib, NULL, NULL, IUPAF_NO_INHERIT);
+ iupClassRegisterAttribute(ic, "SPACING", iupTreeGetSpacingAttrib, gtkTreeSetSpacingAttrib, NULL, NULL, IUPAF_NOT_MAPPED);
+ iupClassRegisterAttribute(ic, "TOPITEM", NULL, gtkTreeSetTopItemAttrib, NULL, NULL, IUPAF_WRITEONLY|IUPAF_NO_INHERIT);
+@@ -2345,7 +2432,6 @@ void iupdrvTreeInitClass(Iclass* ic)
+ iupClassRegisterAttributeId(ic, "COLOR", gtkTreeGetColorAttrib, gtkTreeSetColorAttrib, IUPAF_NO_INHERIT);
+ iupClassRegisterAttributeId(ic, "NAME", gtkTreeGetTitleAttrib, gtkTreeSetTitleAttrib, IUPAF_NO_INHERIT);
+ iupClassRegisterAttributeId(ic, "TITLE", gtkTreeGetTitleAttrib, gtkTreeSetTitleAttrib, IUPAF_NO_INHERIT);
+- iupClassRegisterAttributeId(ic, "USERDATA", gtkTreeGetUserDataAttrib, gtkTreeSetUserDataAttrib, IUPAF_NO_STRING|IUPAF_NO_INHERIT);
+ 
+ iupClassRegisterAttributeId(ic, "CHILDCOUNT", gtkTreeGetChildCountAttrib, NULL, IUPAF_READONLY|IUPAF_NO_INHERIT);
+ iupClassRegisterAttributeId(ic, "TITLEFONT", gtkTreeGetTitleFontAttrib, gtkTreeSetTitleFontAttrib, IUPAF_NO_INHERIT);
+@@ -2355,6 +2441,7 @@ void iupdrvTreeInitClass(Iclass* ic)
+ iupClassRegisterAttribute (ic, "MARK", NULL, gtkTreeSetMarkAttrib, NULL, NULL, IUPAF_WRITEONLY|IUPAF_NO_INHERIT);
+ iupClassRegisterAttribute (ic, "STARTING", NULL, gtkTreeSetMarkStartAttrib, NULL, NULL, IUPAF_NO_DEFAULTVALUE|IUPAF_NO_INHERIT);
+ iupClassRegisterAttribute (ic, "MARKSTART", NULL, gtkTreeSetMarkStartAttrib, NULL, NULL, IUPAF_NO_DEFAULTVALUE|IUPAF_NO_INHERIT);
++ iupClassRegisterAttribute (ic, "MARKEDNODES", gtkTreeGetMarkedNodesAttrib, gtkTreeSetMarkedNodesAttrib, NULL, NULL, IUPAF_NO_DEFAULTVALUE|IUPAF_NO_INHERIT);
+ 
+ iupClassRegisterAttribute (ic, "VALUE", gtkTreeGetValueAttrib, gtkTreeSetValueAttrib, NULL, NULL, IUPAF_NO_DEFAULTVALUE|IUPAF_NO_INHERIT);
+ 
+@@ -2363,7 +2450,7 @@ void iupdrvTreeInitClass(Iclass* ic)
+ iupClassRegisterAttribute(ic, "RENAME", NULL, gtkTreeSetRenameAttrib, NULL, NULL, IUPAF_WRITEONLY|IUPAF_NO_INHERIT);
+ iupClassRegisterAttributeId(ic, "MOVENODE", NULL, gtkTreeSetMoveNodeAttrib, IUPAF_NOT_MAPPED|IUPAF_WRITEONLY|IUPAF_NO_INHERIT);
+ iupClassRegisterAttributeId(ic, "COPYNODE", NULL, gtkTreeSetCopyNodeAttrib, IUPAF_NOT_MAPPED|IUPAF_WRITEONLY|IUPAF_NO_INHERIT);
+- iupClassRegisterAttributeId(ic, "FINDUSERDATA", gtkTreeGetFindUserDataAttrib, NULL, IUPAF_READONLY|IUPAF_NO_INHERIT);
+ 
+- iupClassRegisterAttribute (ic, "AUTODRAGDROP", NULL, NULL, NULL, NULL, IUPAF_DEFAULT);
++ /* IupTree Attributes - GTK Only */
++ iupClassRegisterAttribute (ic, "RUBBERBAND", NULL, NULL, IUPAF_SAMEASSYSTEM, "YES", IUPAF_NO_INHERIT);
+ }
+diff --git a/iup/src/iup.c b/iup/src/iup.c
+index df4bf34..d103af5 100755
+--- a/iup/src/iup.c
++++ b/iup/src/iup.c
+@@ -36,8 +36,10 @@
+ * \subsection com File Comments (at start)
+ * - Check an existant file for example.
+ * 
+- * \subsection inc Include Defines
+- * - __IUPXXX_H (same file name, upper case, "__" preffix and replace "." by "_")
++ * \subsection def Defines
++ * - __IUPXXX_H (for include file, same file name, upper case, "__" preffix and replace "." by "_")
++ * - IUP_XXX (for enumerations)
++ * - iupXXX (for macros, complement with Function Names rules)
+ * 
+ * \subsection doc Documentation
+ * - In the header, using Doxygen commands.
+@@ -58,7 +60,7 @@
+ #include "iup.h"
+ 
+ /* This appears only here to avoid changing the iup.h header fo bug fixes */
+-#define IUP_VERSION_FIX " RC3"
++#define IUP_VERSION_FIX ""
+ #define IUP_VERSION_FIX_NUMBER 0
+ 
+ const char iup_ident[] = 
+diff --git a/iup/src/iup.def b/iup/src/iup.def
+index d0dcfbd..56e7225 100755
+--- a/iup/src/iup.def
++++ b/iup/src/iup.def
+@@ -27,6 +27,8 @@ IupGetFunction
+ IupGetGlobal
+ IupGetHandle
+ IupGetInt
++IupGetInt2
++IupGetIntInt
+ IupGetLanguage
+ IupGetName
+ IupHbox
+@@ -40,6 +42,7 @@ IupListDialog
+ IupLoad
+ IupLoadBuffer
+ IupLoopStep
++IupLoopStepWait
+ IupMainLoop
+ IupMap
+ IupMapFont
+@@ -68,6 +71,7 @@ IupShowXY
+ IupStoreAttribute
+ IupStoreGlobal
+ IupSubmenu
++IupSplit
+ IupText
+ IupToggle
+ IupUnMapFont
+@@ -135,6 +139,7 @@ IupTextConvertLinColToPos
+ IupTextConvertPosToLinCol
+ IupUpdateChildren
+ IupTreeSetAttribute 
++IupTreeSetAttributeHandle
+ IupTreeStoreAttribute
+ IupTreeGetAttribute 
+ IupTreeGetInt 
+@@ -175,8 +180,8 @@ iupdrvFontGetStringWidth
+ iupdrvFontGetMultiLineStringSize
+ iupdrvFontGetCharSize
+ iupdrvDrawFocusRect
+-iupdrvDisplayUpdate
+-iupdrvDisplayRedraw
++iupdrvPostRedraw
++iupdrvRedrawNow
+ iupdrvBaseUnMapMethod
+ iupdrvBaseSetZorderAttrib
+ iupdrvBaseSetTipVisibleAttrib
+@@ -351,3 +356,17 @@ iupArrayCreate
+ iupArrayCount
+ iupArrayAdd
+ iupSaveImageAsText
++iupDrawCreateCanvas
++iupDrawKillCanvas
++iupDrawFlush
++iupDrawGetSize
++iupDrawParentBackground
++iupDrawRectangle
++iupDrawLine
++iupDrawArc
++iupDrawPolygon
++iupDrawResetClip
++iupDrawSetClipRect
++iupDrawText
++iupDrawUpdateSize
++iupDrawImage
+diff --git a/iup/src/iup_attrib.c b/iup/src/iup_attrib.c
+index 2bbb80a..bf9576e 100755
+--- a/iup/src/iup_attrib.c
++++ b/iup/src/iup_attrib.c
+@@ -63,7 +63,7 @@ char* IupGetAttributes(Ihandle *ih)
+ name = iupTableFirst(ih->attrib);
+ while (name)
+ {
+- if (!iupAttribIsInternal(name))
++ if (!iupATTRIB_ISINTERNAL(name))
+ {
+ if (buffer[0] != 0)
+ strcat(buffer,",");
+@@ -115,6 +115,14 @@ void iupAttribUpdateFromParent(Ihandle* ih)
+ }
+ }
+ 
++static int iAttribIsInherit(Ihandle* ih, const char* name)
++{
++ int inherit;
++ char *def_value;
++ iupClassObjectGetAttributeInfo(ih, name, &def_value, &inherit);
++ return inherit;
++}
++
+ static void iAttribNotifyChildren(Ihandle *ih, const char* name, const char *value)
+ {
+ int inherit;
+@@ -123,17 +131,36 @@ static void iAttribNotifyChildren(Ihandle *ih, const char* name, const char *val
+ {
+ if (!iupTableGet(child->attrib, name))
+ {
+- /* set on the class */
+- iupClassObjectSetAttribute(child, name, value, &inherit);
++ /* set only if an inheritable attribute at the child */
++ if (iAttribIsInherit(child, name))
++ {
++ /* set on the class */
++ iupClassObjectSetAttribute(child, name, value, &inherit);
+ 
+- if (inherit) /* inherit can be different for the child */
+ iAttribNotifyChildren(child, name, value);
++ }
+ }
+ 
+ child = child->brother;
+ }
+ }
+ 
++void iupAttribUpdateChildren(Ihandle* ih)
++{
++ char *name = iupTableFirst(ih->attrib);
++ while (name)
++ {
++ if (!iupATTRIB_ISINTERNAL(name) && iAttribIsInherit(ih, name))
++ {
++ /* retrieve from the table */
++ char* value = iupTableGet(ih->attrib, name);
++ iAttribNotifyChildren(ih, name, value);
++ }
++
++ name = iupTableNext(ih->attrib);
++ }
++}
++
+ void iupAttribUpdate(Ihandle* ih)
+ {
+ char** name_array;
+@@ -159,7 +186,7 @@ void iupAttribUpdate(Ihandle* ih)
+ for (i = 0; i < count; i++)
+ {
+ name = name_array[i];
+- if (!iupAttribIsInternal(name))
++ if (!iupATTRIB_ISINTERNAL(name))
+ {
+ /* retrieve from the table */
+ value = iupTableGet(ih->attrib, name);
+@@ -196,7 +223,7 @@ void IupSetAttribute(Ihandle *ih, const char* name, const char *value)
+ if (!iupObjectCheck(ih))
+ return;
+ 
+- if (iupAttribIsInternal(name))
++ if (iupATTRIB_ISINTERNAL(name))
+ iupAttribSetStr(ih, name, value);
+ else
+ {
+@@ -225,7 +252,7 @@ void IupStoreAttribute(Ihandle *ih, const char* name, const char *value)
+ if (!iupObjectCheck(ih))
+ return;
+ 
+- if (iupAttribIsInternal(name))
++ if (iupATTRIB_ISINTERNAL(name))
+ iupAttribStoreStr(ih, name, value);
+ else
+ {
+@@ -257,7 +284,7 @@ char* IupGetAttribute(Ihandle *ih, const char* name)
+ if (!value)
+ value = iupAttribGet(ih, name);
+ 
+- if (!value && !iupAttribIsInternal(name))
++ if (!value && !iupATTRIB_ISINTERNAL(name))
+ {
+ if (inherit)
+ {
+@@ -346,6 +373,16 @@ void iupAttribSetHandleName(Ihandle *ih)
+ IupSetHandle(str_name, ih);
+ }
+ 
++char* iupAttribGetHandleName(Ihandle *ih)
++{
++ char str_name[100];
++ sprintf(str_name, "_IUP_NAME(%p)", ih);
++ if (IupGetHandle(str_name)==ih)
++ return iupStrGetMemoryCopy(str_name);
++ else
++ return NULL;
++}
++
+ void IupSetAttributeHandle(Ihandle *ih, const char* name, Ihandle *ih_named)
+ {
+ int inherit;
+@@ -426,7 +463,7 @@ void iupAttribSetInt(Ihandle *ih, const char* name, int num)
+ 
+ void iupAttribSetFloat(Ihandle *ih, const char* name, float num)
+ {
+- iupAttribSetStrf(ih, name, "%f", (double)num);
++ iupAttribSetStrf(ih, name, "%g", (double)num);
+ }
+ 
+ int iupAttribGetBoolean(Ihandle* ih, const char* name)
+@@ -479,7 +516,7 @@ char* iupAttribGetStr(Ihandle* ih, const char* name)
+ 
+ value = iupTableGet(ih->attrib, name);
+ 
+- if (!value && !iupAttribIsInternal(name))
++ if (!value && !iupATTRIB_ISINTERNAL(name))
+ {
+ int inherit;
+ char *def_value;
+@@ -555,6 +592,15 @@ static void iAttribCapture(char* env_buffer, char* dlm)
+ env_buffer[i-1]='\0'; /* discard delimiter */
+ }
+ 
++static void iAttribSkipComment(void)
++{
++ int c;
++ do
++ {
++ c = *env_str; ++env_str;
++ } while ((c > 0) && (c != '\n'));
++}
++
+ static int iAttribToken(char* env_buffer)
+ {
+ for (;;)
+@@ -565,6 +611,11 @@ static int iAttribToken(char* env_buffer)
+ case 0:
+ return IUPLEX_TK_END;
+ 
++ case '#': /* Skip comment */
++ case '%': /* Skip comment */
++ iAttribSkipComment();
++ continue;
++
+ case ' ': /* ignore whitespace */
+ case '\t':
+ case '\n':
+@@ -609,7 +660,7 @@ static void iAttribParse(Ihandle *ih, const char* str)
+ {
+ switch (iAttribToken(env_buffer))
+ {
+- case IUPLEX_TK_END: /* procedimento igual ao IUPLEX_TK_COMMA */
++ case IUPLEX_TK_END: /* same as IUPLEX_TK_COMMA */
+ end = 1;
+ case IUPLEX_TK_COMMA:
+ if (name)
+diff --git a/iup/src/iup_attrib.h b/iup/src/iup_attrib.h
+index 993dd3c..8593d6e 100755
+--- a/iup/src/iup_attrib.h
++++ b/iup/src/iup_attrib.h
+@@ -28,7 +28,7 @@ extern "C" {
+ 
+ /** Returns true if the attribute name if in the internal format "_IUP...".
+ * \ingroup attrib */
+-#define iupAttribIsInternal(_name) ((_name[0] == '_' && _name[1] == 'I' && _name[2] == 'U' && _name[3] == 'P')? 1: 0)
++#define iupATTRIB_ISINTERNAL(_name) ((_name[0] == '_' && _name[1] == 'I' && _name[2] == 'U' && _name[3] == 'P')? 1: 0)
+ 
+ /** Returns true if the attribute name is a known pointer.
+ * \ingroup attrib */
+@@ -102,16 +102,23 @@ float iupAttribGetFloat(Ihandle* ih, const char* name);
+ * \ingroup attrib */
+ void iupAttribSetHandleName(Ihandle *ih);
+ 
++/** Returns the internal name if set.
++ * \ingroup attrib */
++char* iupAttribGetHandleName(Ihandle *ih);
++
+ 
+ /* For all attributes in the evironment, call the class SetAttribute only.
+- * Called only after the element is mapped. */
++ * Called only after the element is mapped, but before the children are mapped. */
+ void iupAttribUpdate(Ihandle* ih); 
+ 
+ /* For all registered inherited attributes, checks the parent tree and 
+ * call the class SetAttribute if the attribute is defined.
+- * Called only after the element is mapped. */
++ * Called only after the element is mapped, but before the children are mapped. */
+ void iupAttribUpdateFromParent(Ihandle* ih);
+ 
++/* For all attributes in the evironment, call the class SetAttribute only for the children.
++ * Called only after the element is mapped, and after the children are mapped. */
++void iupAttribUpdateChildren(Ihandle* ih);
+ 
+ 
+ /* Other functions declared in <iup.h> and implemented here. 
+diff --git a/iup/src/iup_box.c b/iup/src/iup_box.c
+index 54e56d9..111cab4 100755
+--- a/iup/src/iup_box.c
++++ b/iup/src/iup_box.c
+@@ -172,9 +172,9 @@ static int iBoxSetCMarginAttrib(Ihandle* ih, const char* value)
+ iupdrvFontGetCharSize(ih, &charwidth, &charheight);
+ iupStrToIntInt(value, &cmargin_x, &cmargin_y, 'x');
+ if (cmargin_x!=-1)
+- ih->data->margin_x = iupHEIGHT2RASTER(cmargin_x, charheight);
++ ih->data->margin_x = iupWIDTH2RASTER(cmargin_x, charwidth);
+ if (cmargin_y!=-1)
+- ih->data->margin_x = iupWIDTH2RASTER(cmargin_y, charwidth);
++ ih->data->margin_y = iupHEIGHT2RASTER(cmargin_y, charheight);
+ return 0;
+ }
+ 
+@@ -227,8 +227,12 @@ Iclass* iupBoxClassBase(void)
+ /* boxes only */
+ iupClassRegisterAttribute(ic, "GAP", iBoxGetGapAttrib, iBoxSetGapAttrib, IUPAF_SAMEASSYSTEM, "0", IUPAF_NOT_MAPPED);
+ iupClassRegisterAttribute(ic, "CGAP", iBoxGetCGapAttrib, iBoxSetCGapAttrib, IUPAF_SAMEASSYSTEM, "0", IUPAF_NOT_MAPPED);
++ iupClassRegisterAttribute(ic, "NGAP", iBoxGetGapAttrib, iBoxSetGapAttrib, IUPAF_SAMEASSYSTEM, "0", IUPAF_NOT_MAPPED|IUPAF_NO_INHERIT);
++ iupClassRegisterAttribute(ic, "NCGAP", iBoxGetCGapAttrib, iBoxSetCGapAttrib, IUPAF_SAMEASSYSTEM, "0", IUPAF_NOT_MAPPED|IUPAF_NO_INHERIT);
+ iupClassRegisterAttribute(ic, "MARGIN", iBoxGetMarginAttrib, iBoxSetMarginAttrib, IUPAF_SAMEASSYSTEM, "0x0", IUPAF_NOT_MAPPED);
+ iupClassRegisterAttribute(ic, "CMARGIN", iBoxGetCMarginAttrib, iBoxSetCMarginAttrib, IUPAF_SAMEASSYSTEM, "0x0", IUPAF_NOT_MAPPED);
++ iupClassRegisterAttribute(ic, "NMARGIN", iBoxGetMarginAttrib, iBoxSetMarginAttrib, IUPAF_SAMEASSYSTEM, "0x0", IUPAF_NOT_MAPPED|IUPAF_NO_INHERIT);
++ iupClassRegisterAttribute(ic, "NCMARGIN", iBoxGetCMarginAttrib, iBoxSetCMarginAttrib, IUPAF_SAMEASSYSTEM, "0x0", IUPAF_NOT_MAPPED|IUPAF_NO_INHERIT);
+ 
+ iupClassRegisterAttribute(ic, "EXPANDCHILDREN", iBoxGetExpandChildrenAttrib, iBoxSetExpandChildrenAttrib, NULL, NULL, IUPAF_NOT_MAPPED|IUPAF_NO_INHERIT);
+ iupClassRegisterAttribute(ic, "HOMOGENEOUS", iBoxGetHomogeneousAttrib, iBoxSetHomogeneousAttrib, NULL, NULL, IUPAF_NOT_MAPPED|IUPAF_NO_INHERIT);
+diff --git a/iup/src/iup_button.c b/iup/src/iup_button.c
+index 7719663..56befe2 100755
+--- a/iup/src/iup_button.c
++++ b/iup/src/iup_button.c
+@@ -100,8 +100,9 @@ static void iButtonComputeNaturalSizeMethod(Ihandle* ih, int *w, int *h, int *ex
+ char* value = iupAttribGet(ih, "IMAGE");
+ if (value)
+ {
++ char* title = iupAttribGet(ih, "TITLE");
+ type = IUP_BUTTON_IMAGE;
+- if (iupAttribGet(ih, "TITLE"))
++ if (title && *title!=0)
+ type |= IUP_BUTTON_TEXT;
+ }
+ else
+diff --git a/iup/src/iup_canvas.c b/iup/src/iup_canvas.c
+index 5eda988..46fefd9 100755
+--- a/iup/src/iup_canvas.c
++++ b/iup/src/iup_canvas.c
+@@ -55,14 +55,14 @@ void iupCanvasCalcScrollRealPos(double min, double max, double *pos,
+ char* iupCanvasGetPosXAttrib(Ihandle* ih)
+ {
+ char* str = iupStrGetMemory(20);
+- sprintf(str, "%f", ih->data->posx);
++ sprintf(str, "%g", ih->data->posx);
+ return str;
+ }
+ 
+ char* iupCanvasGetPosYAttrib(Ihandle* ih)
+ {
+ char* str = iupStrGetMemory(20);
+- sprintf(str, "%f", ih->data->posy);
++ sprintf(str, "%g", ih->data->posy);
+ return str;
+ }
+ 
+diff --git a/iup/src/iup_classattrib.c b/iup/src/iup_classattrib.c
+index df8f873..3ac780c 100755
+--- a/iup/src/iup_classattrib.c
++++ b/iup/src/iup_classattrib.c
+@@ -55,7 +55,7 @@ static const char* iClassFindId(const char* name)
+ {
+ if (*name >= '0' && *name <= '9')
+ return name;
+- if (*name == '*' || *name == ':')
++ if (*name == '*' || *name == ':' || *name == '-')
+ return name;
+ 
+ name++;
+@@ -94,7 +94,6 @@ int iupClassObjectSetAttribute(Ihandle* ih, const char* name, const char * value
+ const char* name_id = iClassFindId(name);
+ if (name_id)
+ {
+- IattribFunc* afunc;
+ const char* partial_name = iClassCutNameId(name, name_id);
+ if (!partial_name)
+ partial_name = "IDVALUE"; /* pure numbers are used as attributes in IupList and IupMatrix, 
+@@ -474,8 +473,12 @@ void iupClassObjectEnsureDefaultAttributes(Ihandle* ih)
+ (afunc->call_global_default && iupGlobalDefaultColorChanged(afunc->default_value)))
+ {
+ if ((!ih->handle && (afunc->flags & IUPAF_NOT_MAPPED)) ||
+- (ih->handle && !(afunc->flags & IUPAF_NOT_MAPPED) && !iupAttribGet(ih, name)))
+- afunc->set(ih, iClassGetDefaultValue(afunc));
++ (ih->handle && !(afunc->flags & IUPAF_NOT_MAPPED)))
++ {
++ char* value = iupAttribGet(ih, name);
++ if (!value) /* if set will be updated later */
++ afunc->set(ih, iClassGetDefaultValue(afunc));
++ }
+ }
+ }
+ 
+diff --git a/iup/src/iup_classbase.c b/iup/src/iup_classbase.c
+index 9cb9e63..03a98d1 100755
+--- a/iup/src/iup_classbase.c
++++ b/iup/src/iup_classbase.c
+@@ -164,8 +164,7 @@ static char* iBaseGetPositionAttrib(Ihandle* ih)
+ 
+ static int iBaseSetPositionAttrib(Ihandle* ih, const char* value)
+ {
+- if (ih->is_floating)
+- iupStrToIntInt(value, &ih->x, &ih->y, ',');
++ iupStrToIntInt(value, &ih->x, &ih->y, ',');
+ return 0;
+ }
+ 
+@@ -211,7 +210,7 @@ char* iupBaseGetVisibleAttrib(Ihandle* ih)
+ int iupBaseSetVisibleAttrib(Ihandle* ih, const char* value)
+ {
+ iupdrvSetVisible(ih, iupStrBoolean(value));
+- return 0;
++ return 1; /* must be 1 to mark when set at the element */
+ }
+ 
+ char* iupBaseNativeParentGetBgColorAttrib(Ihandle* ih)
+@@ -410,15 +409,19 @@ void iupBaseRegisterCommonAttrib(Iclass* ic)
+ iupClassRegisterAttribute(ic, "FLOATING", iBaseGetFloatingAttrib, iBaseSetFloatingAttrib, NULL, NULL, IUPAF_NOT_MAPPED|IUPAF_NO_INHERIT);
+ iupClassRegisterAttribute(ic, "EXPAND", iBaseGetExpandAttrib, iBaseSetExpandAttrib, NULL, NULL, IUPAF_NOT_MAPPED|IUPAF_NO_INHERIT);
+ iupClassRegisterAttribute(ic, "NORMALIZERGROUP", NULL, iBaseSetNormalizerGroupAttrib, NULL, NULL, IUPAF_NOT_MAPPED|IUPAF_NO_INHERIT);
++ iupClassRegisterAttribute(ic, "EXPANDWEIGTH", NULL, NULL, NULL, NULL, IUPAF_NOT_MAPPED|IUPAF_NO_INHERIT);
+ 
+ /* make sure everyone has the correct default value */
+- iupClassRegisterAttribute(ic, "VISIBLE", NULL, NULL, IUPAF_SAMEASSYSTEM, "YES", IUPAF_DEFAULT);
+ iupClassRegisterAttribute(ic, "ACTIVE", NULL, NULL, IUPAF_SAMEASSYSTEM, "YES", IUPAF_DEFAULT);
+ if (ic->is_interactive)
+ iupClassRegisterAttribute(ic, "CANFOCUS", NULL, NULL, IUPAF_SAMEASSYSTEM, "YES", IUPAF_NO_INHERIT);
+ else
+ iupClassRegisterAttribute(ic, "CANFOCUS", NULL, NULL, IUPAF_SAMEASSYSTEM, "NO", IUPAF_NO_INHERIT);
+ 
++ /* if not native container, must set at children,
++ native container will automatically hide its children. */
++ iupClassRegisterAttribute(ic, "VISIBLE", NULL, NULL, IUPAF_SAMEASSYSTEM, "YES", IUPAF_DEFAULT); /* let the attribute to be propagated to children */
++
+ iupClassRegisterAttribute(ic, "SIZE", iupBaseGetSizeAttrib, iupBaseSetSizeAttrib, NULL, NULL, IUPAF_NO_DEFAULTVALUE|IUPAF_NOT_MAPPED|IUPAF_NO_INHERIT);
+ iupClassRegisterAttribute(ic, "RASTERSIZE", iupBaseGetRasterSizeAttrib, iupBaseSetRasterSizeAttrib, NULL, NULL, IUPAF_NO_DEFAULTVALUE|IUPAF_NOT_MAPPED|IUPAF_NO_INHERIT);
+ iupClassRegisterAttribute(ic, "CHARSIZE", iupBaseGetCharSizeAttrib, NULL, NULL, NULL, IUPAF_NO_DEFAULTVALUE|IUPAF_READONLY|IUPAF_NOT_MAPPED|IUPAF_NO_INHERIT);
+@@ -439,7 +442,7 @@ void iupBaseRegisterCommonAttrib(Iclass* ic)
+ 
+ void iupBaseRegisterVisualAttrib(Iclass* ic)
+ {
+- iupClassRegisterAttribute(ic, "VISIBLE", iupBaseGetVisibleAttrib, iupBaseSetVisibleAttrib, IUPAF_SAMEASSYSTEM, "YES", IUPAF_NO_INHERIT); /* VISIBLE inheritance comes from the native system */
++ iupClassRegisterAttribute(ic, "VISIBLE", iupBaseGetVisibleAttrib, iupBaseSetVisibleAttrib, "YES", "NO", IUPAF_DEFAULT);
+ iupClassRegisterAttribute(ic, "ACTIVE", iupBaseGetActiveAttrib, iupBaseSetActiveAttrib, IUPAF_SAMEASSYSTEM, "YES", IUPAF_DEFAULT);
+ 
+ iupClassRegisterAttribute(ic, "ZORDER", NULL, iupdrvBaseSetZorderAttrib, NULL, NULL, IUPAF_WRITEONLY|IUPAF_NO_INHERIT);
+diff --git a/iup/src/iup_dialog.c b/iup/src/iup_dialog.c
+index d70e12c..1aaf095 100755
+--- a/iup/src/iup_dialog.c
++++ b/iup/src/iup_dialog.c
+@@ -220,11 +220,19 @@ static void iDialogDestroyMethod(Ihandle* ih)
+ iupDlgListRemove(ih);
+ }
+ 
++static int iDialogSetMenuAttrib(Ihandle* ih, const char* value);
++
+ static void iDialogComputeNaturalSizeMethod(Ihandle* ih, int *w, int *h, int *expand)
+ {
+ int decorwidth, decorheight;
+ Ihandle* child = ih->firstchild;
+ 
++ /* if does not have a menu, but the attribute is defined,
++ try to update the menu before retrieving the decoration. */
++ char* value = iupAttribGet(ih, "MENU");
++ if (!ih->data->menu && value)
++ iDialogSetMenuAttrib(ih, value);
++
+ iupDialogGetDecorSize(ih, &decorwidth, &decorheight);
+ *w = decorwidth;
+ *h = decorheight;
+@@ -278,20 +286,22 @@ static void iDialogAfterShow(Ihandle* ih)
+ {
+ Ihandle* old_focus;
+ IFni show_cb;
++ int show_state;
+ 
+ /* process all pending messages */
+ IupFlush();
+ 
+ old_focus = IupGetFocus();
++ show_state = ih->data->show_state;
+ 
+ show_cb = (IFni)IupGetCallback(ih, "SHOW_CB");
+- if (show_cb && show_cb(ih, ih->data->show_state) == IUP_CLOSE)
++ if (show_cb && show_cb(ih, show_state) == IUP_CLOSE)
+ {
+ IupExitLoop();
+ return;
+ }
+ 
+- if (ih->data->show_state == IUP_SHOW)
++ if (show_state == IUP_SHOW)
+ {
+ if (show_cb)
+ IupFlush(); /* again to update focus */
+@@ -718,7 +728,8 @@ Iclass* iupDialogGetClass(void)
+ iupBaseRegisterVisualAttrib(ic);
+ 
+ /* Overwrite Visual */
+- iupClassRegisterAttribute(ic, "VISIBLE", iupBaseGetVisibleAttrib, iDialogSetVisibleAttrib, IUPAF_SAMEASSYSTEM, "NO", IUPAF_NO_INHERIT); /* the only case where VISIBLE default is NO */
++ /* the only case where VISIBLE default is NO, and must not be propagated to the dialog children */
++ iupClassRegisterAttribute(ic, "VISIBLE", iupBaseGetVisibleAttrib, iDialogSetVisibleAttrib, IUPAF_SAMEASSYSTEM, "NO", IUPAF_NO_INHERIT); 
+ 
+ /* IupDialog only */
+ iupClassRegisterAttribute(ic, "MENU", NULL, iDialogSetMenuAttrib, NULL, NULL, IUPAF_NOT_MAPPED|IUPAF_NO_INHERIT);
+diff --git a/iup/src/iup_drv.h b/iup/src/iup_drv.h
+index 5cdb8e7..1071347 100755
+--- a/iup/src/iup_drv.h
++++ b/iup/src/iup_drv.h
+@@ -60,11 +60,11 @@ void iupdrvSetActive(Ihandle* ih, int enable);
+ 
+ /** Post a redraw of a control.
+ * \ingroup drv */
+-void iupdrvDisplayUpdate(Ihandle *ih);
++void iupdrvPostRedraw(Ihandle *ih);
+ 
+ /** Force a redraw of a control.
+ * \ingroup drv */
+-void iupdrvDisplayRedraw(Ihandle *ih);
++void iupdrvRedrawNow(Ihandle *ih);
+ 
+ /** Reparent the native control.
+ * \ingroup drv */
+diff --git a/iup/src/iup_focus.c b/iup/src/iup_focus.c
+index be54b75..fc0579c 100755
+--- a/iup/src/iup_focus.c
++++ b/iup/src/iup_focus.c
+@@ -220,15 +220,25 @@ void iupFocusPrevious(Ihandle *ih)
+ /* local variables */
+ static Ihandle* iup_current_focus = NULL;
+ 
++Ihandle* IupGetFocus(void)
++{
++ return iup_current_focus;
++}
++
++void iupSetCurrentFocus(Ihandle *ih)
++{
++ iup_current_focus = ih;
++}
++
+ Ihandle *IupSetFocus(Ihandle *ih)
+ {
+- Ihandle* old_focus = iup_current_focus;
++ Ihandle* old_focus = IupGetFocus();
+ 
+ iupASSERT(iupObjectCheck(ih));
+ if (!iupObjectCheck(ih))
+ return old_focus;
+ 
+- /* iup_current_focus is NOT set here, 
++ /* Current focus is NOT set here, 
+ only in the iupCallGetFocusCb */
+ 
+ if (iupFocusCanAccept(ih)) 
+@@ -237,16 +247,11 @@ Ihandle *IupSetFocus(Ihandle *ih)
+ return old_focus;
+ }
+ 
+-Ihandle *IupGetFocus(void)
+-{
+- return iup_current_focus;
+-}
+-
+ void iupCallGetFocusCb(Ihandle *ih)
+ {
+ Icallback cb;
+ 
+- if (ih == iup_current_focus) /* avoid duplicate messages */
++ if (ih == IupGetFocus()) /* avoid duplicate messages */
+ return;
+ 
+ cb = (Icallback)IupGetCallback(ih, "GETFOCUS_CB");
+@@ -258,14 +263,14 @@ void iupCallGetFocusCb(Ihandle *ih)
+ if (cb2) cb2(ih, 1);
+ }
+ 
+- iup_current_focus = ih;
++ iupSetCurrentFocus(ih);
+ }
+ 
+ void iupCallKillFocusCb(Ihandle *ih)
+ {
+ Icallback cb;
+ 
+- if (ih != iup_current_focus) /* avoid duplicate messages */
++ if (ih != IupGetFocus()) /* avoid duplicate messages */
+ return;
+ 
+ cb = IupGetCallback(ih, "KILLFOCUS_CB");
+@@ -277,5 +282,5 @@ void iupCallKillFocusCb(Ihandle *ih)
+ if (cb2) cb2(ih, 0);
+ }
+ 
+- iup_current_focus = NULL;
++ iupSetCurrentFocus(NULL);
+ }
+diff --git a/iup/src/iup_focus.h b/iup/src/iup_focus.h
+index 239e233..9fb4e58 100755
+--- a/iup/src/iup_focus.h
++++ b/iup/src/iup_focus.h
+@@ -39,6 +39,7 @@ Ihandle* iupFocusNextInteractive(Ihandle *ih);
+ void iupFocusNext(Ihandle *ih);
+ void iupFocusPrevious(Ihandle *ih);
+ 
++void iupSetCurrentFocus(Ihandle *ih);
+ 
+ /* Other functions declared in <iup.h> and implemented here. 
+ IupPreviousField
+diff --git a/iup/src/iup_getparam.c b/iup/src/iup_getparam.c
+index 1418aa5..7fd6a94 100755
+--- a/iup/src/iup_getparam.c
++++ b/iup/src/iup_getparam.c
+@@ -45,6 +45,14 @@ static int iParamButtonCancel_CB(Ihandle* self)
+ return IUP_CLOSE;
+ }
+ 
++static int iParamButtonHelp_CB(Ihandle* self)
++{
++ Ihandle* dlg = IupGetDialog(self);
++ Iparamcb cb = (Iparamcb)IupGetCallback(dlg, "PARAM_CB");
++ if (cb) cb(dlg, -4, (void*)iupAttribGet(dlg, "USER_DATA"));
++ return IUP_DEFAULT;
++}
++
+ static int iParamToggleAction_CB(Ihandle *self, int v)
+ {
+ Ihandle* param = (Ihandle*)iupAttribGetInherit(self, "_IUPGP_PARAM");
+@@ -288,7 +296,7 @@ static int iParamColorButton_CB(Ihandle *self, int button, int pressed)
+ 
+ IupPopup(dlg, IUP_CENTER, IUP_CENTER);
+ 
+- if (IupGetInt(dlg, "STATUS") != -1)
++ if (IupGetInt(dlg, "STATUS")==1)
+ {
+ char* value = IupGetAttribute(dlg, "VALUE");
+ IupSetAttribute(textbox, "VALUE", value);
+@@ -381,11 +389,13 @@ static int iParamSpinInt_CB(Ihandle *self, int pos)
+ static Ihandle* iParamCreateBox(Ihandle* param)
+ {
+ Ihandle *box, *ctrl = NULL, *label;
+- char *type;
++ char *type = iupAttribGet(param, "TYPE");
++
++ if (iupStrEqual(type, "BUTTONNAMES"))
++ return NULL;
+ 
+ label = IupLabel(iupAttribGet(param, "TITLE"));
+ 
+- type = iupAttribGet(param, "TYPE");
+ if (iupStrEqual(type, "SEPARATOR"))
+ {
+ box = IupHbox(label, NULL);
+@@ -563,7 +573,7 @@ static Ihandle* iParamCreateBox(Ihandle* param)
+ float step = iupAttribGetFloat(param, "STEP");
+ float val = iupAttribGetFloat(param, "VALUE");
+ if (step == 0) step = (max-min)/20.0f;
+- IupSetfAttribute(ctrl, "MASKFLOAT", "%f:%f", (double)min, (double)max);
++ IupSetfAttribute(ctrl, "MASKFLOAT", "%g:%g", (double)min, (double)max);
+ 
+ /* here spin is always [0-spinmax] converted to [min-max] */
+ 
+@@ -584,7 +594,7 @@ static Ihandle* iParamCreateBox(Ihandle* param)
+ if (min == 0)
+ IupSetAttribute(ctrl, "MASK", IUP_MASK_UFLOAT);
+ else
+- IupSetfAttribute(ctrl, "MASKFLOAT", "%f:%f", (double)min, (double)1.0e10);
++ IupSetfAttribute(ctrl, "MASKFLOAT", "%g:%g", (double)min, (double)1.0e10);
+ IupAppend(box, ctrl);
+ }
+ else
+@@ -620,6 +630,7 @@ static Ihandle* iParamCreateBox(Ihandle* param)
+ }
+ IupSetfAttribute(ctrl, "SPINMAX", "%d", max);
+ IupSetfAttribute(ctrl, "SPINMIN", "%d", min);
++ IupSetfAttribute(ctrl, "MASKINT", "%d:%d", min, max);
+ }
+ else if (iupAttribGetInt(param, "PARTIAL"))
+ {
+@@ -696,7 +707,7 @@ static Ihandle* iParamCreateBox(Ihandle* param)
+ 
+ static Ihandle* IupParamDlgP(Ihandle** params)
+ {
+- Ihandle *dlg, *button_ok, *button_cancel, 
++ Ihandle *dlg, *button_ok, *button_cancel, *button_help=NULL, 
+ *dlg_box, *button_box, *param_box;
+ int i, lbl_width, p, expand;
+ 
+@@ -713,7 +724,23 @@ static Ihandle* IupParamDlgP(Ihandle** params)
+ i = 0; expand = 0;
+ while (params[i] != NULL)
+ {
+- IupAppend(param_box, iParamCreateBox(params[i]));
++ Ihandle* box = iParamCreateBox(params[i]);
++ if (box)
++ IupAppend(param_box, box);
++ else /* buttonnames */
++ {
++ char* value = iupAttribGet(params[i], "_IUPGP_OK");
++ if (value && *value) IupSetAttribute(button_ok, "TITLE", value);
++ value = iupAttribGet(params[i], "_IUPGP_CANCEL");
++ if (value && *value) IupSetAttribute(button_cancel, "TITLE", value);
++ value = iupAttribGet(params[i], "_IUPGP_HELP");
++ if (value && *value) 
++ {
++ button_help = IupButton(value, NULL);
++ IupSetAttribute(button_help, "PADDING", "20x0");
++ IupSetCallback(button_help, "ACTION", (Icallback)iParamButtonHelp_CB);
++ }
++ }
+ 
+ if (IupGetInt(params[i], "EXPAND"))
+ expand = 1;
+@@ -725,6 +752,7 @@ static Ihandle* IupParamDlgP(Ihandle** params)
+ IupFill(),
+ button_ok,
+ button_cancel,
++ button_help,
+ NULL);
+ IupSetAttribute(button_box,"MARGIN","0x0");
+ IupSetAttribute(button_box, "NORMALIZESIZE", "HORIZONTAL");
+@@ -926,6 +954,23 @@ static void iParamSetFileOptions(char* extra, Ihandle* param)
+ iupAttribStoreStr(param, "_IUPGP_NOOVERWRITEPROMPT", nooverwriteprompt);
+ }
+ 
++static void iParamSetButtonNames(char* extra, Ihandle* param)
++{
++ char *ok, *cancel, *help;
++ int count;
++
++ if (!extra)
++ return;
++
++ ok = iParamGetNextStrItem(extra, ',', &count); extra += count;
++ cancel = iParamGetNextStrItem(extra, ',', &count); extra += count;
++ help = iParamGetNextStrItem(extra, ',', &count); extra += count;
++
++ iupAttribStoreStr(param, "_IUPGP_OK", ok);
++ iupAttribStoreStr(param, "_IUPGP_CANCEL", cancel);
++ iupAttribStoreStr(param, "_IUPGP_HELP", help);
++}
++
+ static void iParamSetListItems(char* extra, Ihandle* param)
+ {
+ int d = 1, count;
+@@ -1082,6 +1127,12 @@ static Ihandle *IupParamf(const char* format, int *line_size)
+ iupAttribSetStr(param, "TYPE", "SEPARATOR");
+ iupAttribSetStr(param, "DATA_TYPE", "-1"); /* NONE */
+ break;
++ case 'u':
++ iupAttribSetStr(param, "TYPE", "BUTTONNAMES");
++ iupAttribSetStr(param, "DATA_TYPE", "-1"); /* NONE */
++ extra = iParamGetStrExtra(line_ptr, '[', ']', &count); line_ptr += count;
++ iParamSetButtonNames(extra, param);
++ break;
+ default:
+ return NULL;
+ }
+@@ -1099,7 +1150,7 @@ static Ihandle *IupParamf(const char* format, int *line_size)
+ 
+ int iupGetParamCount(const char *format, int *param_extra)
+ {
+- int param_count = 0, sep = 0;
++ int param_count = 0, extra = 0;
+ const char* s = format;
+ 
+ *param_extra = 0;
+@@ -1107,14 +1158,20 @@ int iupGetParamCount(const char *format, int *param_extra)
+ {
+ if (*s == '%' && *(s+1) == 't') /* do not count separator lines */
+ {
+- sep = 1;
++ extra = 1;
++ (*param_extra)++;
++ }
++
++ if (*s == '%' && *(s+1) == 'u') /* do not count button names lines */
++ {
++ extra = 1;
+ (*param_extra)++;
+ }
+ 
+ if (*s == '\n')
+ {
+- if (sep)
+- sep = 0;
++ if (extra)
++ extra = 0;
+ else
+ param_count++;
+ }
+@@ -1154,21 +1211,21 @@ int IupGetParamv(const char* title, Iparamcb action, void* user_data, const char
+ return 0;
+ 
+ data_type = IupGetInt(params[i], "DATA_TYPE");
+- if (data_type == 1)
+- {
+- int *data_int = (int*)(param_data[p]);
+- if (!data_int) return 0;
+- iupAttribSetStrf(params[i], "VALUE", "%d", *data_int);
+- p++;
+- }
+- else if (data_type == 2)
++ if (data_type == 2) /* float */
+ {
+ float *data_float = (float*)(param_data[p]);
+ if (!data_float) return 0;
+ iupAttribSetStrf(params[i], "VALUE", "%g", *data_float);
+ p++;
+ }
+- else if (data_type == 0)
++ else if (data_type == 1) /* integer */
++ {
++ int *data_int = (int*)(param_data[p]);
++ if (!data_int) return 0;
++ iupAttribSetStrf(params[i], "VALUE", "%d", *data_int);
++ p++;
++ }
++ else if (data_type == 0) /* string */
+ {
+ char *data_str = (char*)(param_data[p]);
+ if (!data_str) return 0;
+diff --git a/iup/src/iup_globalattrib.c b/iup/src/iup_globalattrib.c
+index 00586fb..d1a2584 100755
+--- a/iup/src/iup_globalattrib.c
++++ b/iup/src/iup_globalattrib.c
+@@ -129,12 +129,14 @@ int iupGlobalIsPointer(const char* name)
+ static struct {
+ const char *name;
+ } ptr_table[] = {
+-#ifdef WIN32
++#ifndef GTK_MAC
++ #ifdef WIN32
+ {"HINSTANCE"},
+-#else
++ #else
+ {"XDISPLAY"},
+ {"XSCREEN"},
+ {"APPSHELL"},
++ #endif
+ #endif
+ };
+ #define PTR_TABLE_SIZE ((sizeof ptr_table)/(sizeof ptr_table[0]))
+diff --git a/iup/src/iup_hbox.c b/iup/src/iup_hbox.c
+index e790636..a8a93a3 100755
+--- a/iup/src/iup_hbox.c
++++ b/iup/src/iup_hbox.c
+@@ -213,6 +213,13 @@ static void iHboxSetChildrenCurrentSizeMethod(Ihandle* ih, int shrink)
+ else
+ {
+ int empty = (child->expand & IUP_EXPAND_W1)? empty_w1: ((child->expand & IUP_EXPAND_W0)? empty_w0: 0);
++ char* weigth_str = iupAttribGet(child, "EXPANDWEIGTH");
++ if (weigth_str)
++ {
++ float weigth; 
++ if (iupStrToFloat(weigth_str, &weigth))
++ empty = iupROUND(empty * weigth);
++ }
+ iupBaseSetCurrentSize(child, child->naturalwidth+empty, client_height, shrink);
+ }
+ 
+diff --git a/iup/src/iup_key.h b/iup/src/iup_key.h
+index 37d6c9d..9b30bc4 100755
+--- a/iup/src/iup_key.h
++++ b/iup/src/iup_key.h
+@@ -51,16 +51,16 @@ void iupKeyInit(void);
+ 
+ #define IUPKEY_STATUS_SIZE 11 /* 10 chars + null */
+ #define IUPKEY_STATUS_INIT " " /* 10 spaces */
+-#define iupKEYSETSHIFT(_s) (_s[0]='S')
+-#define iupKEYSETCONTROL(_s) (_s[1]='C')
+-#define iupKEYSETBUTTON1(_s) (_s[2]='1')
+-#define iupKEYSETBUTTON2(_s) (_s[3]='2')
+-#define iupKEYSETBUTTON3(_s) (_s[4]='3')
+-#define iupKEYSETDOUBLE(_s) (_s[5]='D')
+-#define iupKEYSETALT(_s) (_s[6]='A')
+-#define iupKEYSETSYS(_s) (_s[7]='Y')
+-#define iupKEYSETBUTTON4(_s) (_s[8]='4')
+-#define iupKEYSETBUTTON5(_s) (_s[9]='5')
++#define iupKEY_SETSHIFT(_s) (_s[0]='S')
++#define iupKEY_SETCONTROL(_s) (_s[1]='C')
++#define iupKEY_SETBUTTON1(_s) (_s[2]='1')
++#define iupKEY_SETBUTTON2(_s) (_s[3]='2')
++#define iupKEY_SETBUTTON3(_s) (_s[4]='3')
++#define iupKEY_SETDOUBLE(_s) (_s[5]='D')
++#define iupKEY_SETALT(_s) (_s[6]='A')
++#define iupKEY_SETSYS(_s) (_s[7]='Y')
++#define iupKEY_SETBUTTON4(_s) (_s[8]='4')
++#define iupKEY_SETBUTTON5(_s) (_s[9]='5')
+ 
+ 
+ #ifdef __cplusplus
+diff --git a/iup/src/iup_layout.c b/iup/src/iup_layout.c
+index b96293c..0ccd496 100755
+--- a/iup/src/iup_layout.c
++++ b/iup/src/iup_layout.c
+@@ -43,7 +43,7 @@ static void iLayoutDisplayUpdateChildren(Ihandle *ih)
+ iLayoutDisplayUpdateChildren(child);
+ 
+ if (child->handle && child->iclass->nativetype != IUP_TYPEVOID)
+- iupdrvDisplayUpdate(child);
++ iupdrvPostRedraw(child);
+ }
+ }
+ 
+@@ -54,7 +54,7 @@ void IupUpdate(Ihandle* ih)
+ return;
+ 
+ if (ih->handle && ih->iclass->nativetype != IUP_TYPEVOID)
+- iupdrvDisplayUpdate(ih);
++ iupdrvPostRedraw(ih);
+ }
+ 
+ void IupUpdateChildren(Ihandle* ih)
+@@ -74,7 +74,7 @@ static void iLayoutDisplayRedrawChildren(Ihandle *ih)
+ iLayoutDisplayRedrawChildren(child);
+ 
+ if (child->handle && child->iclass->nativetype != IUP_TYPEVOID)
+- iupdrvDisplayRedraw(child);
++ iupdrvRedrawNow(child);
+ }
+ }
+ 
+@@ -85,7 +85,7 @@ void IupRedraw(Ihandle* ih, int children)
+ return;
+ 
+ if (ih->handle && ih->iclass->nativetype != IUP_TYPEVOID)
+- iupdrvDisplayRedraw(ih);
++ iupdrvRedrawNow(ih);
+ 
+ if (children)
+ iLayoutDisplayRedrawChildren(ih);
+@@ -136,7 +136,7 @@ void iupLayoutCompute(Ihandle* ih)
+ iupBaseSetPosition(ih, 0, 0);
+ }
+ 
+-static void iLayoutSetMinMaxSize(Ihandle* ih, int *w, int *h)
++void iupLayoutSetMinMaxSize(Ihandle* ih, int *w, int *h)
+ {
+ if (ih->has_minsize)
+ {
+@@ -163,7 +163,8 @@ void iupBaseComputeNaturalSize(Ihandle* ih)
+ ih->naturalwidth = ih->userwidth;
+ ih->naturalheight = ih->userheight;
+ 
+- if (ih->iclass->childtype!=IUP_CHILDNONE || ih->iclass->nativetype == IUP_TYPEDIALOG)
++ if (ih->iclass->childtype!=IUP_CHILDNONE || 
++ ih->iclass->nativetype == IUP_TYPEDIALOG) /* pre-defined dialogs can restrict the number of children */
+ {
+ int w=0, h=0, children_expand;
+ 
+@@ -190,7 +191,7 @@ void iupBaseComputeNaturalSize(Ihandle* ih)
+ ih->naturalheight = iupMAX(ih->naturalheight, h);
+ 
+ /* crop the natural size */
+- iLayoutSetMinMaxSize(ih, &(ih->naturalwidth), &(ih->naturalheight));
++ iupLayoutSetMinMaxSize(ih, &(ih->naturalwidth), &(ih->naturalheight));
+ }
+ }
+ else 
+@@ -198,15 +199,15 @@ void iupBaseComputeNaturalSize(Ihandle* ih)
+ /* for non-container only compute if user size is not defined */
+ if (ih->naturalwidth <= 0 || ih->naturalheight <= 0)
+ {
+- int w=0, h=0;
+- iupClassObjectComputeNaturalSize(ih, &w, &h, NULL);
++ int w=0, h=0, children_expand;
++ iupClassObjectComputeNaturalSize(ih, &w, &h, &children_expand);
+ 
+ if (ih->naturalwidth <= 0) ih->naturalwidth = w;
+ if (ih->naturalheight <= 0) ih->naturalheight = h;
+ }
+ 
+ /* crop the natural size */
+- iLayoutSetMinMaxSize(ih, &(ih->naturalwidth), &(ih->naturalheight));
++ iupLayoutSetMinMaxSize(ih, &(ih->naturalwidth), &(ih->naturalheight));
+ }
+ }
+ 
+@@ -259,7 +260,7 @@ void iupBaseSetCurrentSize(Ihandle* ih, int w, int h, int shrink)
+ 
+ /* crop the current size if expanded */
+ if (ih->expand & IUP_EXPAND_WIDTH || ih->expand & IUP_EXPAND_HEIGHT)
+- iLayoutSetMinMaxSize(ih, &(ih->currentwidth), &(ih->currentheight));
++ iupLayoutSetMinMaxSize(ih, &(ih->currentwidth), &(ih->currentheight));
+ }
+ }
+ 
+diff --git a/iup/src/iup_layout.h b/iup/src/iup_layout.h
+index a2a0c29..775e5a2 100755
+--- a/iup/src/iup_layout.h
++++ b/iup/src/iup_layout.h
+@@ -16,6 +16,8 @@ extern "C" {
+ void iupLayoutCompute(Ihandle* ih); /* can be called before map */
+ void iupLayoutUpdate(Ihandle* ih); /* called only after map */
+ 
++void iupLayoutSetMinMaxSize(Ihandle* ih, int *w, int *h);
++
+ /* Other functions declared in <iup.h> and implemented here. 
+ IupRefresh
+ */
+diff --git a/iup/src/iup_ledlex.c b/iup/src/iup_ledlex.c
+index 3283a43..5cf8640 100755
+--- a/iup/src/iup_ledlex.c
++++ b/iup/src/iup_ledlex.c
+@@ -35,7 +35,7 @@ static struct /* lexical variables */
+ static int iLexGetChar (void);
+ static int iLexToken(int *erro);
+ static int iLexCapture (char* dlm);
+-static int iLexSkip (char* dlm);
++static void iLexSkipComment (void);
+ static int iLexCaptureAttr (void);
+ 
+ int iupLexStart(const char* filename, int is_file) /* initialize lexical analysis */
+@@ -186,9 +186,9 @@ static int iLexToken(int *erro)
+ case ']':
+ return IUPLEX_TK_ENDATTR;
+ 
+- case '#': /* iLexSkip comment */
+- case '%': /* iLexSkip comment */
+- iLexSkip ("\n\r");
++ case '#': /* Skip comment */
++ case '%': /* Skip comment */
++ iLexSkipComment();
+ continue;
+ 
+ case ' ': /* ignore whitespace */
+@@ -276,14 +276,13 @@ static int iLexCaptureAttr (void)
+ return c; /* return delimiter */
+ }
+ 
+-static int iLexSkip (char* dlm)
++static void iLexSkipComment (void)
+ {
+ int c;
+ do
+ {
+- c = iLexGetChar ();
+- } while ((c > 0) && !strchr (dlm,c));
+- return c; /* return delimiter */
++ c = iLexGetChar();
++ } while ((c > 0) && (c != '\n'));
+ }
+ 
+ static int iLexGetChar (void)
+diff --git a/iup/src/iup_list.c b/iup/src/iup_list.c
+index 5965665..1077d98 100755
+--- a/iup/src/iup_list.c
++++ b/iup/src/iup_list.c
+@@ -53,6 +53,37 @@ static void iListCallActionCallback(Ihandle* ih, IFnsii cb, int pos, int state)
+ IupExitLoop();
+ }
+ 
++void iupListUpdateOldValue(Ihandle* ih, int pos, int removed)
++{
++ if (!ih->data->has_editbox)
++ {
++ char* old_value = iupAttribGet(ih, "_IUPLIST_OLDVALUE");
++ if (old_value)
++ {
++ int old_pos = atoi(old_value)-1; /* was in IUP reference, starting at 1 */
++ if (ih->data->is_dropdown || !ih->data->is_multiple)
++ {
++ if (old_pos >= pos)
++ {
++ if (removed && old_pos == pos)
++ {
++ /* when the current item is removed nothing remains selected */
++ iupAttribSetStr(ih, "_IUPLIST_OLDVALUE", NULL);
++ }
++ else
++ iupAttribSetInt(ih, "_IUPLIST_OLDVALUE", removed? old_pos-1: old_pos+1);
++ }
++ }
++ else
++ {
++ /* multiple selection on a non drop-down list. */
++ char* value = IupGetAttribute(ih, "VALUE");
++ iupAttribStoreStr(ih, "_IUPLIST_OLDVALUE", value);
++ }
++ }
++ }
++}
++
+ void iupListSingleCallActionCallback(Ihandle* ih, IFnsii cb, int pos)
+ {
+ char* old_str = iupAttribGet(ih, "_IUPLIST_OLDVALUE");
+@@ -77,7 +108,7 @@ void iupListMultipleCallActionCallback(Ihandle* ih, IFnsii cb, IFns multi_cb, in
+ char* old_str = iupAttribGet(ih, "_IUPLIST_OLDVALUE");
+ int old_count = old_str? strlen(old_str): 0;
+ 
+- char* str = iupStrGetMemory(count+1);
++ char* str = malloc(count+1);
+ memset(str, '-', count);
+ str[count]=0;
+ for (i=0; i<sel_count; i++)
+@@ -92,6 +123,7 @@ void iupListMultipleCallActionCallback(Ihandle* ih, IFnsii cb, IFns multi_cb, in
+ if (multi_cb)
+ {
+ int unchanged = 1;
++
+ for (i=0; i<count && old_str; i++)
+ {
+ if (str[i] == old_str[i])
+@@ -101,7 +133,10 @@ void iupListMultipleCallActionCallback(Ihandle* ih, IFnsii cb, IFns multi_cb, in
+ }
+ 
+ if (old_str && unchanged)
++ {
++ free(str);
+ return;
++ }
+ 
+ if (multi_cb(ih, str) == IUP_CLOSE)
+ IupExitLoop();
+@@ -133,6 +168,7 @@ void iupListMultipleCallActionCallback(Ihandle* ih, IFnsii cb, IFns multi_cb, in
+ }
+ 
+ iupAttribStoreStr(ih, "_IUPLIST_OLDVALUE", str);
++ free(str);
+ }
+ 
+ int iupListGetPos(Ihandle* ih, const char* name_id)
+@@ -145,7 +181,8 @@ int iupListGetPos(Ihandle* ih, const char* name_id)
+ pos--; /* IUP items start at 1 */
+ 
+ if (pos < 0) return -1;
+- if (pos > count-1) return -1;
++ if (pos == count) return -2;
++ if (pos > count) return -1;
+ 
+ return pos;
+ }
+@@ -217,7 +254,10 @@ int iupListSetIdValueAttrib(Ihandle* ih, const char* name_id, const char* value)
+ if (pos >= 0 && pos <= count-1)
+ {
+ if (pos == 0)
++ {
+ iupdrvListRemoveAllItems(ih);
++ iupAttribSetStr(ih, "_IUPLIST_OLDVALUE", NULL);
++ }
+ else
+ {
+ int i = pos;
+@@ -245,7 +285,7 @@ int iupListSetIdValueAttrib(Ihandle* ih, const char* name_id, const char* value)
+ 
+ static int iListSetAppendItemAttrib(Ihandle* ih, const char* value)
+ {
+- if (!ih->handle) /* do not store the action before map */
++ if (!ih->handle) /* do not do the action before map */
+ return 0;
+ if (value)
+ iupdrvListAppendItem(ih, value);
+@@ -254,27 +294,32 @@ static int iListSetAppendItemAttrib(Ihandle* ih, const char* value)
+ 
+ static int iListSetInsertItemAttrib(Ihandle* ih, const char* name_id, const char* value)
+ {
+- if (!ih->handle) /* do not store the action before map */
++ if (!ih->handle) /* do not do the action before map */
+ return 0;
+ if (value)
+ {
+ int pos = iupListGetPos(ih, name_id);
+- if (pos!=-1)
++ if (pos >= 0)
+ iupdrvListInsertItem(ih, pos, value);
++ else if (pos == -2)
++ iupdrvListAppendItem(ih, value);
+ }
+ return 0;
+ }
+ 
+ static int iListSetRemoveItemAttrib(Ihandle* ih, const char* value)
+ {
+- if (!ih->handle) /* do not store the action before map */
++ if (!ih->handle) /* do not do the action before map */
+ return 0;
+ if (!value)
++ {
+ iupdrvListRemoveAllItems(ih);
++ iupAttribSetStr(ih, "_IUPLIST_OLDVALUE", NULL);
++ }
+ else
+ {
+ int pos = iupListGetPos(ih, value);
+- if (pos!=-1)
++ if (pos >= 0)
+ iupdrvListRemoveItem(ih, pos);
+ }
+ return 0;
+diff --git a/iup/src/iup_list.h b/iup/src/iup_list.h
+index 045116b..05fe9f8 100755
+--- a/iup/src/iup_list.h
++++ b/iup/src/iup_list.h
+@@ -30,6 +30,7 @@ char* iupListGetNCAttrib(Ihandle* ih);
+ char* iupListGetPaddingAttrib(Ihandle* ih);
+ char* iupListGetSpacingAttrib(Ihandle* ih);
+ void iupListSingleCallDblClickCallback(Ihandle* ih, IFnis cb, int pos);
++void iupListUpdateOldValue(Ihandle* ih, int pos, int removed);
+ 
+ struct _IcontrolData 
+ {
+diff --git a/iup/src/iup_names.c b/iup/src/iup_names.c
+index 9ec01a6..18ca3ef 100755
+--- a/iup/src/iup_names.c
++++ b/iup/src/iup_names.c
+@@ -14,11 +14,41 @@
+ #include "iup_object.h"
+ #include "iup_class.h"
+ #include "iup_assert.h"
++#include "iup_attrib.h"
+ #include "iup_str.h"
+ 
+ 
+ static Itable *inames_strtable = NULL; /* table indexed by name containing Ihandle* address */
+-static Itable *inames_ihtable = NULL; /* table indexed by Ihandle* address containing names */
++
++void iupNamesInit(void)
++{
++ inames_strtable = iupTableCreate(IUPTABLE_STRINGINDEXED);
++}
++
++void iupNamesFinish(void)
++{
++ iupTableDestroy(inames_strtable);
++ inames_strtable = NULL;
++}
++
++static Ihandle* iNameGetTopParent(Ihandle* ih)
++{
++ Ihandle* parent = ih;
++ while (parent->parent)
++ parent = parent->parent;
++ return parent;
++}
++
++static int iNameCheckArray(Ihandle** ih_array, int count, Ihandle* ih)
++{
++ int i;
++ for (i = 0; i < count; i++)
++ {
++ if (ih_array[i] == ih)
++ return 0;
++ }
++ return 1;
++}
+ 
+ void iupNamesDestroyHandles(void)
+ {
+@@ -37,10 +67,14 @@ void iupNamesDestroyHandles(void)
+ while (name)
+ {
+ ih = (Ihandle*)iupTableGetCurr(inames_strtable);
+- if (iupObjectCheck(ih))
++ if (iupObjectCheck(ih)) /* here must be a handle */
+ {
+- ih_array[i] = ih;
+- i++;
++ ih = iNameGetTopParent(ih);
++ if (iNameCheckArray(ih_array, i, ih))
++ {
++ ih_array[i] = ih;
++ i++;
++ }
+ }
+ name = iupTableNext(inames_strtable);
+ }
+@@ -48,44 +82,28 @@ void iupNamesDestroyHandles(void)
+ count = i;
+ for (i = 0; i < count; i++)
+ {
+- if (iupObjectCheck(ih_array[i]))
++ if (iupObjectCheck(ih_array[i])) /* here must be a handle */
+ IupDestroy(ih_array[i]);
+ }
+ 
+ free(ih_array);
+ }
+ 
+-void iupNamesInit(void)
+-{
+- inames_strtable = iupTableCreate(IUPTABLE_STRINGINDEXED);
+- inames_ihtable = iupTableCreate(IUPTABLE_POINTERINDEXED);
+-}
+-
+-void iupNamesFinish(void)
+-{
+- iupTableDestroy(inames_strtable);
+- inames_strtable = NULL;
+-
+- iupTableDestroy(inames_ihtable);
+- inames_ihtable = NULL;
+-}
+-
+-void iupRemoveAllNames(Ihandle* ih)
++void iupRemoveNames(Ihandle* ih)
+ {
+ char *name;
+- Ihandle *cur_ih;
+ 
+- name = iupTableFirst(inames_strtable);
+- while (name)
+- {
+- cur_ih = (Ihandle*)iupTableGetCurr(inames_strtable);
+- if (iupObjectCheck(cur_ih) && cur_ih == ih)
+- iupTableRemoveCurr(inames_strtable);
++ /* clear the cache */
++ name = iupAttribGet(ih, "_IUP_LASTHANDLENAME");
++ if (name)
++ iupTableRemove(inames_strtable, name);
+ 
+- name = iupTableNext(inames_strtable);
+- }
++ /* check for an internal name */
++ name = iupAttribGetHandleName(ih);
++ if (name)
++ iupTableRemove(inames_strtable, name);
+ 
+- iupTableRemove(inames_ihtable, (char*)ih);
++ /* Do NOT search for other names */
+ }
+ 
+ Ihandle *IupGetHandle(const char *name)
+@@ -104,22 +122,24 @@ Ihandle* IupSetHandle(const char *name, Ihandle *ih)
+ return NULL;
+ 
+ old_ih = iupTableGet(inames_strtable, name);
++
+ if (ih != NULL)
+ {
+ iupTableSet(inames_strtable, name, ih, IUPTABLE_POINTER);
+- iupTableSet(inames_ihtable, (char*)ih, (char*)name, IUPTABLE_STRING); /* keep only the last name set */
++
++ /* save the name in the cache if it is a valid handle */
++ if (iupObjectCheck(ih))
++ iupAttribStoreStr(ih, "_IUP_LASTHANDLENAME", name);
+ }
+ else
+ {
+- ih = iupTableGet(inames_strtable, name);
+ iupTableRemove(inames_strtable, name);
+- if (ih) 
+- {
+- char* cur_name = iupTableGet(inames_ihtable, (char*)ih);
+- if (iupStrEqualNoCase(cur_name, name))
+- iupTableRemove(inames_ihtable, (char*)ih);
+- }
++
++ /* clear the name from the cache if it is a valid handle */
++ if (iupObjectCheck(old_ih))
++ iupAttribSetStr(old_ih, "_IUP_LASTHANDLENAME", NULL);
+ }
++
+ return old_ih;
+ }
+ 
+@@ -151,7 +171,8 @@ static int iNamesCountDialogs(void)
+ while (name)
+ {
+ Ihandle* dlg = (Ihandle*)iupTableGetCurr(inames_strtable);
+- if (iupObjectCheck(dlg) && dlg->iclass->nativetype == IUP_TYPEDIALOG)
++ if (iupObjectCheck(dlg) && /* here must be a handle */
++ dlg->iclass->nativetype == IUP_TYPEDIALOG)
+ i++;
+ 
+ name = iupTableNext(inames_strtable);
+@@ -171,7 +192,8 @@ int IupGetAllDialogs(char** names, int n)
+ while (name)
+ {
+ Ihandle* dlg = (Ihandle*)iupTableGetCurr(inames_strtable);
+- if (iupObjectCheck(dlg) && dlg->iclass->nativetype == IUP_TYPEDIALOG)
++ if (iupObjectCheck(dlg) && /* here must be a handle */
++ dlg->iclass->nativetype == IUP_TYPEDIALOG)
+ {
+ names[i] = name;
+ i++;
+@@ -186,8 +208,32 @@ int IupGetAllDialogs(char** names, int n)
+ 
+ char* IupGetName(Ihandle* ih)
+ {
+- iupASSERT(iupObjectCheck(ih));
+- if (!iupObjectCheck(ih))
++ char *name;
++ if (!ih) /* no iupASSERT needed here */
+ return NULL;
+- return iupTableGet(inames_ihtable, (char*)ih);
++
++ if (iupObjectCheck(ih))
++ {
++ /* check the cache first, but must be a handle */
++ name = iupAttribGet(ih, "_IUP_LASTHANDLENAME");
++ if (name)
++ return name;
++ }
++
++ /* check for an internal name */
++ name = iupAttribGetHandleName(ih);
++ if (name)
++ return name;
++ 
++ /* search for the name */
++ name = iupTableFirst(inames_strtable);
++ while (name)
++ {
++ if ((Ihandle*)iupTableGetCurr(inames_strtable) == ih)
++ return name;
++
++ name = iupTableNext(inames_strtable);
++ }
++
++ return NULL;
+ }
+diff --git a/iup/src/iup_names.h b/iup/src/iup_names.h
+index 9d3adc7..d652594 100755
+--- a/iup/src/iup_names.h
++++ b/iup/src/iup_names.h
+@@ -17,7 +17,7 @@ void iupNamesFinish(void);
+ void iupNamesDestroyHandles(void);
+ 
+ /* called from IupDestroy */
+-void iupRemoveAllNames(Ihandle* ih);
++void iupRemoveNames(Ihandle* ih);
+ 
+ /* Other functions declared in <iup.h> and implemented here.
+ IupGetName
+diff --git a/iup/src/iup_object.c b/iup/src/iup_object.c
+index 7f4ce23..f0d5dc9 100755
+--- a/iup/src/iup_object.c
++++ b/iup/src/iup_object.c
+@@ -148,6 +148,8 @@ Ihandle* IupCreate(const char *name)
+ 
+ void IupDestroy(Ihandle *ih)
+ {
++ Icallback cb;
++
+ iupASSERT(iupObjectCheck(ih));
+ if (!iupObjectCheck(ih))
+ return;
+@@ -156,6 +158,9 @@ void IupDestroy(Ihandle *ih)
+ if (ih->iclass->nativetype == IUP_TYPEDIALOG)
+ IupHide(ih);
+ 
++ cb = IupGetCallback(ih, "DESTROY_CB");
++ if (cb) cb(ih);
++
+ /* Destroy all its children.
+ Just need to remove the first child,
+ IupDetach will update firstchild. */
+@@ -165,6 +170,9 @@ void IupDestroy(Ihandle *ih)
+ /* unmap if mapped and remove from its parent child list */
+ IupDetach(ih);
+ 
++ /* removes names associated with the element */
++ iupRemoveNames(ih);
++
+ /* destroy the element */
+ iupClassObjectDestroy(ih);
+ 
+@@ -172,9 +180,6 @@ void IupDestroy(Ihandle *ih)
+ if (ih->data)
+ free(ih->data);
+ 
+- /* removes all the names associated with the element */
+- iupRemoveAllNames(ih);
+-
+ /* destroy the base handle structure */
+ iHandleDestroy(ih);
+ }
+diff --git a/iup/src/iup_object.h b/iup/src/iup_object.h
+index 6f6b668..a69edc0 100755
+--- a/iup/src/iup_object.h
++++ b/iup/src/iup_object.h
+@@ -113,6 +113,7 @@ Ihandle* iupObjectCreate(Iclass* ic, void** params);
+ void** iupObjectGetParamList(void* first, va_list arglist);
+ 
+ /** Checks if the handle is still valid based on the signature.
++ * But if the handle was destroyed still can access invalid memory.
+ * \ingroup object */
+ int iupObjectCheck(Ihandle* ih);
+ 
+diff --git a/iup/src/iup_open.c b/iup/src/iup_open.c
+index e02561e..bce5c5c 100755
+--- a/iup/src/iup_open.c
++++ b/iup/src/iup_open.c
+@@ -101,8 +101,8 @@ void IupClose(void)
+ 
+ iupdrvSetIdleFunction(NULL); /* stop any idle */
+ 
+- iupDlgListDestroyAll(); /* destroy all dialogs */
+- iupNamesDestroyHandles(); /* destroy everything else that have names */
++ iupDlgListDestroyAll(); /* destroy all dialogs and their children */
++ iupNamesDestroyHandles(); /* destroy everything that do not belong to a dialog */
+ iupImageStockFinish(); /* release stock images hash table and the images */
+ 
+ iupRegisterFinish(); /* release native classes */
+diff --git a/iup/src/iup_register.c b/iup/src/iup_register.c
+index 4c58038..2e9954a 100755
+--- a/iup/src/iup_register.c
++++ b/iup/src/iup_register.c
+@@ -99,6 +99,7 @@ void iupRegisterInternalClasses(void)
+ iupRegisterClass(iupCboxGetClass());
+ iupRegisterClass(iupSboxGetClass());
+ iupRegisterClass(iupNormalizerGetClass());
++ iupRegisterClass(iupSplitGetClass());
+ 
+ iupRegisterClass(iupMenuGetClass());
+ iupRegisterClass(iupItemGetClass());
+diff --git a/iup/src/iup_sbox.c b/iup/src/iup_sbox.c
+index 5a71d33..9998481 100755
+--- a/iup/src/iup_sbox.c
++++ b/iup/src/iup_sbox.c
+@@ -57,6 +57,7 @@ static void iSboxSaveDimension(Ihandle* ih, int w, int h)
+ {
+ ih->data->w = w;
+ ih->data->h = h;
++ iupLayoutSetMinMaxSize(ih, &(ih->data->w), &(ih->data->h));
+ }
+ 
+ static void iSboxAddDecorOffset(Ihandle* ih, int *x, int *y)
+diff --git a/iup/src/iup_show.c b/iup/src/iup_show.c
+index 9ea1408..b42975e 100755
+--- a/iup/src/iup_show.c
++++ b/iup/src/iup_show.c
+@@ -53,35 +53,6 @@ void IupUnmap(Ihandle *ih)
+ ih->handle = NULL;
+ }
+ 
+-static char* iShowGetVisible(Ihandle* ih)
+-{
+- char* value = iupAttribGet(ih, "VISIBLE"); /* Check on the element first */
+- while (!value)
+- {
+- ih = ih->parent; /* iheritance here independs on the attribute */
+- if (!ih)
+- return NULL;
+-
+- value = iupAttribGet(ih, "VISIBLE");
+-
+- /* only recursive up to the native parent */ 
+- if (ih->iclass->nativetype != IUP_TYPEVOID)
+- return value; /* can be NULL */
+- }
+-
+- return value;
+-}
+-
+-static void iShowUpdateVisible(Ihandle* ih)
+-{
+- int inherit;
+- /* although default is VISIBLE=YES, 
+- when mapped the element is still hidden. 
+- So we must manually update the visible state. */
+- char* value = iShowGetVisible(ih);
+- iupClassObjectSetAttribute(ih, "VISIBLE", value, &inherit);
+-}
+-
+ int IupMap(Ihandle* ih)
+ {
+ iupASSERT(iupObjectCheck(ih));
+@@ -108,7 +79,7 @@ int IupMap(Ihandle* ih)
+ return IUP_ERROR;
+ }
+ 
+- /* update FONT, must be the before several others */
++ /* update FONT, must be the before several others, so we do it here */
+ if (ih->iclass->nativetype != IUP_TYPEVOID &&
+ ih->iclass->nativetype != IUP_TYPEIMAGE &&
+ ih->iclass->nativetype != IUP_TYPEMENU)
+@@ -117,18 +88,13 @@ int IupMap(Ihandle* ih)
+ /* ensure attributes default values, at this time only the ones that need to be set after map */
+ iupClassObjectEnsureDefaultAttributes(ih);
+ 
+- /* check visible state if not a dialog */
+- if (ih->iclass->nativetype == IUP_TYPECANVAS || 
+- ih->iclass->nativetype == IUP_TYPECONTROL)
+- iShowUpdateVisible(ih);
+-
+- /* updates the defined attributes in the native system. */
++ /* updates the defined attributes from the hash table to the native system. */
+ iupAttribUpdate(ih); 
+ 
+- /* updates attributes defined in the parent tree */
++ /* updates inheritable attributes defined in the parent tree */
+ iupAttribUpdateFromParent(ih);
+ 
+- /* map children */
++ /* map children independent from childtype */
+ {
+ Ihandle* child = ih->firstchild;
+ while (child)
+@@ -140,6 +106,10 @@ int IupMap(Ihandle* ih)
+ }
+ }
+ 
++ /* updates the defined attributes from the hash table to the native system. */
++ if (ih->iclass->childtype!=IUP_CHILDNONE)
++ iupAttribUpdateChildren(ih);
++
+ /* moves and resizes the elements to reflect the layout computation */
+ /* if the dialog is visible will be reflected in the user interface */
+ if (ih->iclass->nativetype == IUP_TYPEDIALOG)
+diff --git a/iup/src/iup_spin.c b/iup/src/iup_spin.c
+index 6fadab4..514703f 100755
+--- a/iup/src/iup_spin.c
++++ b/iup/src/iup_spin.c
+@@ -175,7 +175,7 @@ static int iSpinCreateMethod(Ihandle* ih, void** params)
+ 
+ static int iSpinboxCreateMethod(Ihandle* ih, void** params)
+ {
+- Ihandle *spin, *ctrl;
++ Ihandle *spin;
+ 
+ if (!params || !(params[0]))
+ return IUP_ERROR;
+@@ -184,8 +184,7 @@ static int iSpinboxCreateMethod(Ihandle* ih, void** params)
+ IupSetAttribute(ih, "MARGIN", "0x0");
+ IupSetAttribute(ih, "ALIGNMENT", "ACENTER");
+ 
+- ctrl = (Ihandle*)(params[0]);
+- iupChildTreeAppend(ih, ctrl);
++ /* IupText is already a child of Spinbox because of the IupHbox Create method */
+ 
+ spin = IupSpin();
+ iupChildTreeAppend(ih, spin);
+@@ -249,7 +248,7 @@ Iclass* iupSpinboxGetClass(void)
+ ic->name = "spinbox";
+ ic->format = "h"; /* one Ihandle */
+ ic->nativetype = IUP_TYPEVOID;
+- ic->childtype = IUP_CHILDNONE;
++ ic->childtype = IUP_CHILD_ONE; /* fake value to define it as a container */
+ ic->is_interactive = 0;
+ 
+ iupClassRegisterCallback(ic, "SPIN_CB", "i");
+@@ -267,7 +266,7 @@ Iclass* iupSpinGetClass(void)
+ ic->name = "spin";
+ ic->format = NULL; /* no parameters */
+ ic->nativetype = IUP_TYPEVOID;
+- ic->childtype = IUP_CHILDNONE;
++ ic->childtype = IUP_CHILD_ONE; /* fake value to define it as a container */
+ ic->is_interactive = 0;
+ 
+ /* Class functions */
+diff --git a/iup/src/iup_stdcontrols.h b/iup/src/iup_stdcontrols.h
+index 11499ae..0f3deb9 100755
+--- a/iup/src/iup_stdcontrols.h
++++ b/iup/src/iup_stdcontrols.h
+@@ -46,6 +46,7 @@ Iclass* iupZboxGetClass(void);
+ Iclass* iupCboxGetClass(void);
+ Iclass* iupSboxGetClass(void);
+ Iclass* iupNormalizerGetClass(void);
++Iclass* iupSplitGetClass(void);
+ 
+ Iclass* iupTimerGetClass(void);
+ Iclass* iupImageGetClass(void);
+diff --git a/iup/src/iup_str.c b/iup/src/iup_str.c
+index 68976f1..5f5b85d 100755
+--- a/iup/src/iup_str.c
++++ b/iup/src/iup_str.c
+@@ -147,8 +147,9 @@ char *iupStrCopyUntil(char **str, int c)
+ return NULL;
+ 
+ p_str=strchr(*str,c);
+- if (!p_str) return NULL;
+-
++ if (!p_str) 
++ return NULL;
++ else
+ {
+ int i;
+ int sl=(int)(p_str - (*str));
+@@ -160,10 +161,10 @@ char *iupStrCopyUntil(char **str, int c)
+ new_str[i] = (*str)[i];
+ 
+ new_str[sl] = 0;
+- }
+ 
+- *str = p_str+1;
+- return new_str;
++ *str = p_str+1;
++ return new_str;
++ }
+ }
+ 
+ char *iupStrCopyUntilNoCase(char **str, int c)
+@@ -174,11 +175,12 @@ char *iupStrCopyUntilNoCase(char **str, int c)
+ 
+ p_str=strchr(*str,c); /* usually the lower case is enough */
+ if (!p_str && isalpha(c)) 
+- {
+ p_str=strchr(*str, toupper(c)); /* but check also for upper case */
+- if (!p_str) return NULL;
+- }
+ 
++ /* if both fail, then abort */
++ if (!p_str) 
++ return NULL;
++ else
+ {
+ int i;
+ int sl=(int)(p_str - (*str));
+@@ -190,10 +192,10 @@ char *iupStrCopyUntilNoCase(char **str, int c)
+ new_str[i] = (*str)[i];
+ 
+ new_str[sl] = 0;
+- }
+ 
+- *str = p_str+1;
+- return new_str;
++ *str = p_str+1;
++ return new_str;
++ }
+ }
+ 
+ char *iupStrGetMemory(int size)
+diff --git a/iup/src/iup_table.c b/iup/src/iup_table.c
+index 9e97ff5..a873191 100755
+--- a/iup/src/iup_table.c
++++ b/iup/src/iup_table.c
+@@ -19,12 +19,12 @@
+ /* Adjust these parameters for optimal performance and memory usage */
+ static const unsigned int itable_maxTableSizeIndex = 8;
+ static const unsigned int itable_hashTableSize[] = { 31, 101, 401, 1601, 4001, 8009, 16001, 32003, 64007 };
+-static const float itable_resizeLimit = 2;
++static const unsigned int itable_resizeLimit = 2;
+ static const unsigned int itable_itemGrow = 5;
+ 
+ /* Iteration context.
+ */
+-typedef struct ItableContext
++typedef struct _ItableContext
+ {
+ unsigned int entryIndex; /* index at the Itable::entries array */
+ unsigned int itemIndex; /* index at the ItableEntry::items array */
+@@ -41,7 +41,7 @@ typedef struct ItableContext
+ * this is simply the pointer (in this case keyIndex
+ * and keyStr are equal).
+ */
+-typedef struct ItableKey
++typedef struct _ItableKey
+ {
+ unsigned long keyIndex; /* the secondary hash number */
+ const char *keyStr;
+@@ -52,11 +52,11 @@ ItableKey;
+ * Such an item is stored in the item list of
+ * an entry.
+ */
+-typedef struct ItableItem
++typedef struct _ItableItem
+ {
+ Itable_Types itemType;
+- ItableKey key;
+- void *value;
++ ItableKey key;
++ void* value;
+ }
+ ItableItem;
+ 
+@@ -67,29 +67,28 @@ ItableItem;
+ * in nextItemIndex.
+ * size is the current size of the items array.
+ */
+-typedef struct ItableEntry
++typedef struct _ItableEntry
+ {
+ unsigned int nextItemIndex;
+- unsigned int size;
+- ItableItem *items;
++ unsigned int itemsSize;
++ ItableItem* items;
+ }
+ ItableEntry;
+ 
+ 
+ /* A hash table.
+- * indexType is the type of the index.
+ * entries is an array of entries. Select an
+ * entry by its index.
+ * size is the number of entries in the hash table...
+ */
+-struct Itable
++struct _Itable
+ {
+- unsigned int size;
+- unsigned int numberOfEntries;
+- unsigned int tableSizeIndex; /* index into itable_hashTableSize array */
+- Itable_IndexTypes indexType;
+- ItableEntry *entries;
+- ItableContext context;
++ unsigned int entriesSize;
++ unsigned int numberOfEntries;
++ unsigned int tableSizeIndex; /* index into itable_hashTableSize array */
++ Itable_IndexTypes indexType; /* type of the index: string or pointer. */
++ ItableEntry *entries;
++ ItableContext context;
+ };
+ 
+ 
+@@ -121,8 +120,7 @@ Itable *iupTableCreate(Itable_IndexTypes indexType)
+ 
+ Itable *iupTableCreateSized(Itable_IndexTypes indexType, unsigned int initialSizeIndex)
+ {
+- Itable *it = (Itable *)malloc(sizeof(struct Itable));
+-
++ Itable *it = (Itable *)malloc(sizeof(Itable));
+ iupASSERT(it!=NULL);
+ if (!it)
+ return 0;
+@@ -130,12 +128,12 @@ Itable *iupTableCreateSized(Itable_IndexTypes indexType, unsigned int initialSiz
+ if (initialSizeIndex > itable_maxTableSizeIndex)
+ initialSizeIndex = itable_maxTableSizeIndex;
+ 
+- it->size = itable_hashTableSize[initialSizeIndex];
++ it->entriesSize = itable_hashTableSize[initialSizeIndex];
+ it->tableSizeIndex = initialSizeIndex;
+ it->numberOfEntries = 0;
+ it->indexType = indexType;
+ 
+- it->entries = (ItableEntry *)malloc(it->size * sizeof(ItableEntry));
++ it->entries = (ItableEntry *)malloc(it->entriesSize * sizeof(ItableEntry));
+ iupASSERT(it->entries!=NULL);
+ if (!it->entries)
+ {
+@@ -143,7 +141,7 @@ Itable *iupTableCreateSized(Itable_IndexTypes indexType, unsigned int initialSiz
+ return 0;
+ }
+ 
+- memset(it->entries, 0, it->size * sizeof(ItableEntry));
++ memset(it->entries, 0, it->entriesSize * sizeof(ItableEntry));
+ 
+ it->context.entryIndex = (unsigned int)-1;
+ it->context.itemIndex = (unsigned int)-1;
+@@ -158,16 +156,19 @@ void iupTableClear(Itable *it)
+ if (!it)
+ return;
+ 
+- for (i = 0; i < it->size; i++)
++ for (i = 0; i < it->entriesSize; i++)
+ {
+ ItableEntry *entry = &(it->entries[i]);
+ if (entry->items)
++ {
+ iTableFreeItemArray(it->indexType, entry->nextItemIndex, entry->items);
++ entry->items = NULL;
++ }
+ }
+ 
+ it->numberOfEntries = 0;
+ 
+- memset(it->entries, 0, it->size * sizeof(ItableEntry));
++ memset(it->entries, 0, it->entriesSize * sizeof(ItableEntry));
+ 
+ it->context.entryIndex = (unsigned int)-1;
+ it->context.itemIndex = (unsigned int)-1;
+@@ -185,7 +186,10 @@ void iupTableDestroy(Itable *it)
+ iupTableClear(it);
+ 
+ if (it->entries)
++ {
+ free(it->entries);
++ it->entries = NULL;
++ }
+ 
+ free(it);
+ }
+@@ -288,17 +292,23 @@ static void iTableRemoveItem(Itable *it, ItableEntry *entry, unsigned int itemIn
+ item = &(entry->items[itemIndex]);
+ 
+ if (it->indexType == IUPTABLE_STRINGINDEXED)
++ {
+ free((void *)item->key.keyStr);
++ item->key.keyStr = NULL;
++ }
+ 
+ if (item->itemType == IUPTABLE_STRING)
++ {
+ free(item->value);
++ item->value = NULL;
++ }
+ 
+- /* order the remaining items */
++ /* re-order the remaining items */
+ for (i = itemIndex; i < entry->nextItemIndex-1; i++)
+ entry->items[i] = entry->items[i+1];
+ 
+- /* clear the non used item */
+- memset(entry->items + entry->nextItemIndex, 0, sizeof (ItableItem));
++ /* clear the released item */
++ memset(entry->items + entry->nextItemIndex-1, 0, sizeof (ItableItem));
+ 
+ entry->nextItemIndex--;
+ it->numberOfEntries--;
+@@ -398,7 +408,7 @@ char *iupTableFirst(Itable *it)
+ it->context.itemIndex = (unsigned int)-1;
+ 
+ /* find the first used entry */
+- for (entryIndex = 0; entryIndex < it->size; entryIndex++)
++ for (entryIndex = 0; entryIndex < it->entriesSize; entryIndex++)
+ {
+ if (it->entries[entryIndex].nextItemIndex > 0)
+ {
+@@ -430,7 +440,7 @@ char *iupTableNext(Itable *it)
+ else
+ {
+ /* find the next used entry */
+- for (entryIndex = it->context.entryIndex+1; entryIndex < it->size; entryIndex++)
++ for (entryIndex = it->context.entryIndex+1; entryIndex < it->entriesSize; entryIndex++)
+ {
+ if (it->entries[entryIndex].nextItemIndex > 0)
+ {
+@@ -471,7 +481,7 @@ char *iupTableRemoveCurr(Itable *it)
+ else
+ {
+ /* find the next used entry */
+- for (entryIndex = it->context.entryIndex+1; entryIndex < it->size; entryIndex++)
++ for (entryIndex = it->context.entryIndex+1; entryIndex < it->entriesSize; entryIndex++)
+ {
+ if (it->entries[entryIndex].nextItemIndex > 0)
+ {
+@@ -498,6 +508,8 @@ static void iTableFreeItemArray(Itable_IndexTypes indexType, unsigned int nextFr
+ {
+ unsigned int i;
+ 
++ /* Used only in iupTableClear */
++
+ iupASSERT(items!=NULL);
+ if (!items)
+ return;
+@@ -505,13 +517,19 @@ static void iTableFreeItemArray(Itable_IndexTypes indexType, unsigned int nextFr
+ if (indexType == IUPTABLE_STRINGINDEXED)
+ {
+ for (i = 0; i < nextFreeIndex; i++)
++ {
+ free((void *)(items[i].key.keyStr));
++ items[i].key.keyStr = NULL;
++ }
+ }
+ 
+ for (i = 0; i < nextFreeIndex; i++)
+ {
+ if (items[i].itemType == IUPTABLE_STRING)
++ {
+ free(items[i].value);
++ items[i].value = NULL;
++ }
+ }
+ 
+ free(items);
+@@ -545,7 +563,7 @@ static unsigned int iTableGetEntryIndex(Itable *it, const char *key, unsigned lo
+ *keyIndex = (unsigned long)key; /* this could NOT be dependent from table size */
+ }
+ 
+- return (unsigned int)((*keyIndex) % it->size);
++ return (unsigned int)((*keyIndex) % it->entriesSize);
+ }
+ 
+ #ifdef DEBUGTABLE
+@@ -603,25 +621,24 @@ static unsigned int iTableFindItem(Itable *it, const char *key, ItableEntry **en
+ 
+ static void iTableUpdateArraySize(ItableEntry *entry)
+ {
+- if (entry->nextItemIndex >= entry->size)
++ if (entry->nextItemIndex >= entry->itemsSize)
+ {
+ /* we have to expand the item array */
+ unsigned int newSize;
+ 
+- newSize = entry->size + itable_itemGrow;
++ newSize = entry->itemsSize + itable_itemGrow;
+ 
+ entry->items = (ItableItem *)realloc(entry->items, newSize * sizeof(ItableItem));
+ iupASSERT(entry->items!=NULL);
+ if (!entry->items)
+ return;
+ 
+- memset(entry->items + entry->size, 0, itable_itemGrow * sizeof(ItableItem));
++ memset(entry->items + entry->itemsSize, 0, itable_itemGrow * sizeof(ItableItem));
+ 
+- entry->size = newSize;
++ entry->itemsSize = newSize;
+ }
+ }
+ 
+-
+ static void iTableAdd(Itable *it, ItableKey *key, void *value, Itable_Types itemType)
+ {
+ unsigned int entryIndex;
+@@ -657,7 +674,7 @@ static unsigned int iTableResize(Itable *it)
+ /* check if we do not need to resize the hash table */
+ if (it->numberOfEntries == 0 ||
+ it->tableSizeIndex >= itable_maxTableSizeIndex ||
+- it->size / it->numberOfEntries >= itable_resizeLimit)
++ it->entriesSize / it->numberOfEntries >= itable_resizeLimit)
+ return 0;
+ 
+ /* create a new hash table and copy the contents of
+@@ -666,7 +683,7 @@ static unsigned int iTableResize(Itable *it)
+ newSizeIndex = it->tableSizeIndex + 1;
+ newTable = iupTableCreateSized(it->indexType, newSizeIndex);
+ 
+- for (entryIndex = 0; entryIndex < it->size; entryIndex++)
++ for (entryIndex = 0; entryIndex < it->entriesSize; entryIndex++)
+ {
+ entry = &(it->entries[entryIndex]);
+ 
+@@ -680,12 +697,13 @@ static unsigned int iTableResize(Itable *it)
+ } 
+ 
+ free(entry->items);
++ entry->items = NULL;
+ }
+ }
+ 
+ free(it->entries);
+ 
+- it->size = newTable->size;
++ it->entriesSize = newTable->entriesSize;
+ it->tableSizeIndex = newTable->tableSizeIndex;
+ it->numberOfEntries = newTable->numberOfEntries;
+ it->entries = newTable->entries;
+@@ -712,11 +730,11 @@ static void iTableShowStatistics(Itable *it)
+ return;
+ }
+ 
+- nofSlots = it->size;
++ nofSlots = it->entriesSize;
+ nofKeys = it->numberOfEntries;
+ optimalNofKeysPerSlot = (double)nofKeys / (double)nofSlots;
+ 
+- for (entryIndex = 0; entryIndex < it->size; entryIndex++)
++ for (entryIndex = 0; entryIndex < it->entriesSize; entryIndex++)
+ {
+ ItableEntry *entry = &(it->entries[entryIndex]);
+ 
+diff --git a/iup/src/iup_table.h b/iup/src/iup_table.h
+index 5222160..f2ff2c7 100755
+--- a/iup/src/iup_table.h
++++ b/iup/src/iup_table.h
+@@ -42,8 +42,8 @@ typedef enum _Itable_Types
+ 
+ typedef void (*Ifunc)(void);
+ 
+-struct Itable;
+-typedef struct Itable Itable;
++struct _Itable;
++typedef struct _Itable Itable;
+ 
+ 
+ /** Creates a hash table with an initial default size.
+@@ -63,7 +63,7 @@ Itable *iupTableCreateSized(Itable_IndexTypes indexType, unsigned int initialSiz
+ /** Destroys the Itable.
+ * Calls \ref iupTableClear.
+ * \ingroup table */
+-void iupTableDestroy(Itable *n);
++void iupTableDestroy(Itable *it);
+ 
+ /** Removes all items in the table.
+ * This function does also free the memory of strings contained in the table!!!!
+@@ -76,33 +76,33 @@ int iupTableCount(Itable *it);
+ 
+ /** Store an element in the table.
+ * \ingroup table */
+-void iupTableSet(Itable *n, const char *key, void *value, Itable_Types itemType);
++void iupTableSet(Itable *it, const char *key, void *value, Itable_Types itemType);
+ 
+ /** Store a function pointer in the table.
+ * Type is set to IUPTABLE_FUNCPOINTER.
+ * \ingroup table */
+-void iupTableSetFunc(Itable *n, const char *key, Ifunc func);
++void iupTableSetFunc(Itable *it, const char *key, Ifunc func);
+ 
+ /** Retrieves an element from the table.
+ * Returns NULL if not found.
+ * \ingroup table */
+-void *iupTableGet(Itable *n, const char *key);
++void *iupTableGet(Itable *it, const char *key);
+ 
+ /** Retrieves a function pointer from the table. 
+ * If not a function or not found returns NULL.
+ * value always contains the element pointer.
+ * \ingroup table */
+-Ifunc iupTableGetFunc(Itable *n, const char *key, void **value);
++Ifunc iupTableGetFunc(Itable *it, const char *key, void **value);
+ 
+ /** Retrieves an element from the table and its type.
+ * \ingroup table */
+-void *iupTableGetTyped(Itable *n, const char *key, Itable_Types *itemType);
++void *iupTableGetTyped(Itable *it, const char *key, Itable_Types *itemType);
+ 
+ /** Removes the entry at the specified key from the
+ * hash table and frees the memory used by it if
+ * it is a string...
+ * \ingroup table */
+-void iupTableRemove(Itable *n, const char *key);
++void iupTableRemove(Itable *it, const char *key);
+ 
+ /** Key iteration function. Returns a key.
+ * To iterate over all keys call iupTableFirst at the first
+diff --git a/iup/src/iup_tabs.c b/iup/src/iup_tabs.c
+index 77b2cf5..2907371 100755
+--- a/iup/src/iup_tabs.c
++++ b/iup/src/iup_tabs.c
+@@ -307,6 +307,25 @@ static char* iTabsGetClientSizeAttrib(Ihandle* ih)
+ return str;
+ }
+ 
++void iupTabsTestRemoveTab(Ihandle* ih, int pos)
++{
++ int cur_pos = iupdrvTabsGetCurrentTab(ih);
++ if (cur_pos == pos)
++ {
++ if (cur_pos == 0)
++ {
++ Ihandle* child = IupGetChild(ih, 1);
++ if (!child) /* not found child, means only one child, do nothing */
++ return;
++
++ cur_pos = 1;
++ }
++ else
++ cur_pos--;
++
++ iupdrvTabsSetCurrentTab(ih, cur_pos);
++ }
++}
+ 
+ /* ------------------------------------------------------------------------- */
+ /* TABS - Methods */
+diff --git a/iup/src/iup_tabs.h b/iup/src/iup_tabs.h
+index 7f5df2e..fd0edf4 100755
+--- a/iup/src/iup_tabs.h
++++ b/iup/src/iup_tabs.h
+@@ -16,6 +16,7 @@ char* iupTabsGetTabOrientationAttrib(Ihandle* ih);
+ char* iupTabsGetTabTypeAttrib(Ihandle* ih);
+ char* iupTabsAttribGetStrId(Ihandle* ih, const char* name, int pos);
+ char* iupTabsGetPaddingAttrib(Ihandle* ih);
++void iupTabsTestRemoveTab(Ihandle* ih, int pos);
+ 
+ int iupdrvTabsExtraDecor(Ihandle* ih);
+ int iupdrvTabsGetLineCountAttrib(Ihandle* ih);
+diff --git a/iup/src/iup_tree.c b/iup/src/iup_tree.c
+index c06e573..b5344f5 100755
+--- a/iup/src/iup_tree.c
++++ b/iup/src/iup_tree.c
+@@ -200,6 +200,240 @@ void iupTreeUpdateImages(Ihandle *ih)
+ iupClassObjectSetAttribute(ih, "IMAGEBRANCHEXPANDED", value, &inherit);
+ }
+ 
++void iupTreeSelectLastCollapsedBranch(Ihandle* ih, int *last_id)
++{
++ /* if last selected item is a branch, then select its children */
++ if (iupStrEqual(IupTreeGetAttribute(ih, "KIND", *last_id), "BRANCH") && 
++ iupStrEqual(IupTreeGetAttribute(ih, "STATE", *last_id), "COLLAPSED"))
++ {
++ int childcount = IupTreeGetInt(ih, "CHILDCOUNT", *last_id);
++ if (childcount > 0)
++ {
++ int start = *last_id + 1;
++ int end = *last_id + childcount;
++ IupSetfAttribute(ih, "MARK", "%d-%d", start, end);
++ *last_id = *last_id + childcount;
++ }
++ }
++}
++
++int iupTreeForEach(Ihandle* ih, iupTreeNodeFunc func, void* userdata)
++{
++ int i;
++ for (i = 0; i < ih->data->node_count; i++)
++ {
++ if (!func(ih, ih->data->node_cache[i].node_handle, i, userdata))
++ return 0;
++ }
++
++ return 1;
++}
++
++int iupTreeFindNodeId(Ihandle* ih, InodeHandle* node_handle)
++{
++ /* Unoptimized version:
++ int i;
++ for (i = 0; i < ih->data->node_count; i++)
++ {
++ if (ih->data->node_cache[i].node_handle == node_handle)
++ return i;
++ }
++ */
++ InodeData *node_cache = ih->data->node_cache;
++ while(node_cache->node_handle != node_handle && 
++ node_cache->node_handle != NULL) /* the cache always have zeros at the end */
++ node_cache++;
++
++ if (node_cache->node_handle != NULL)
++ return node_cache - ih->data->node_cache;
++ else
++ return -1;
++}
++
++static int iTreeFindUserDataId(Ihandle* ih, void* userdata)
++{
++ /* Unoptimized version:
++ int i;
++ for (i = 0; i < ih->data->node_count; i++)
++ {
++ if (ih->data->node_cache[i].node_handle == node_handle)
++ return i;
++ }
++ */
++ InodeData *node_cache = ih->data->node_cache;
++ while(node_cache->userdata != userdata && 
++ node_cache->node_handle != NULL) /* the cache always have zeros at the end */
++ node_cache++;
++
++ if (node_cache->node_handle != NULL)
++ return node_cache - ih->data->node_cache;
++ else
++ return -1;
++}
++
++static int iTreeGetIdFromString(const char* name_id)
++{
++ if (name_id && name_id[0])
++ {
++ int id = -1;
++ iupStrToInt(name_id, &id);
++ return id;
++ }
++ else
++ return -2;
++}
++
++InodeHandle* iupTreeGetNode(Ihandle* ih, int id)
++{
++ if (id >= 0 && id < ih->data->node_count)
++ return ih->data->node_cache[id].node_handle;
++ else if (id == -2)
++ return iupdrvTreeGetFocusNode(ih);
++ else
++ return NULL;
++}
++
++InodeHandle* iupTreeGetNodeFromString(Ihandle* ih, const char* name_id)
++{
++ return iupTreeGetNode(ih, iTreeGetIdFromString(name_id));
++}
++
++static void iTreeAddToCache(Ihandle* ih, int id, InodeHandle* node_handle)
++{
++ iupASSERT(id >= 0 && id < ih->data->node_count);
++ if (id < 0 || id >= ih->data->node_count)
++ return;
++
++ /* node_count here already contains the final count */
++
++ if (id == ih->data->node_count-1)
++ ih->data->node_cache[id].node_handle = node_handle;
++ else
++ {
++ /* open space for the new id */
++ int remain_count = ih->data->node_count-id;
++ memmove(ih->data->node_cache+id+1, ih->data->node_cache+id, remain_count*sizeof(InodeData));
++ ih->data->node_cache[id].node_handle = node_handle;
++ }
++
++ ih->data->node_cache[id].userdata = NULL;
++}
++
++static void iTreeIncCacheMem(Ihandle* ih)
++{
++ /* node_count here already contains the final count */
++
++ if (ih->data->node_count+10 > ih->data->node_cache_max)
++ {
++ int old_node_cache_max = ih->data->node_cache_max;
++ ih->data->node_cache_max += 20;
++ ih->data->node_cache = realloc(ih->data->node_cache, ih->data->node_cache_max*sizeof(InodeData));
++ memset(ih->data->node_cache+old_node_cache_max, 0, 20*sizeof(InodeData));
++ }
++}
++
++void iupTreeAddToCache(Ihandle* ih, int add, int kindPrev, InodeHandle* prevNode, InodeHandle* node_handle)
++{
++ int new_id = 0;
++
++ ih->data->node_count++;
++
++ /* node_count here already contains the final count */
++ iTreeIncCacheMem(ih);
++
++ if (prevNode)
++ {
++ if (add || kindPrev == ITREE_LEAF)
++ {
++ /* ADD implies always that id=prev_id+1 */
++ /* INSERT after a leaf implies always that new_id=prev_id+1 */
++ int prev_id = iupTreeFindNodeId(ih, prevNode);
++ new_id = prev_id+1;
++ }
++ else
++ {
++ /* INSERT after a branch implies always that new_id=prev_id+1+child_count */
++ int prev_id = iupTreeFindNodeId(ih, prevNode);
++ int child_count = iupdrvTreeTotalChildCount(ih, prevNode);
++ new_id = prev_id+1+child_count;
++ }
++ }
++
++ iTreeAddToCache(ih, new_id, node_handle);
++ iupAttribSetInt(ih, "LASTADDNODE", new_id);
++}
++
++void iupTreeDelFromCache(Ihandle* ih, int id, int count)
++{
++ int remain_count;
++
++ /* id can be the last node, actually==node_count becase node_count is already updated */
++ iupASSERT(id >= 0 && id <= ih->data->node_count); 
++ if (id < 0 || id > ih->data->node_count)
++ return;
++
++ /* node_count here already contains the final count */
++
++ /* remove id+count */
++ remain_count = ih->data->node_count-id;
++ memmove(ih->data->node_cache+id, ih->data->node_cache+id+count, remain_count*sizeof(InodeData));
++
++ /* clear the remaining space */
++ memset(ih->data->node_cache+ih->data->node_count, 0, count*sizeof(InodeData));
++}
++
++void iupTreeCopyMoveCache(Ihandle* ih, int id_src, int id_dst, int count, int is_copy)
++{
++ int remain_count;
++
++ iupASSERT(id_src >= 0 && id_src < ih->data->node_count);
++ if (id_src < 0 || id_src >= ih->data->node_count)
++ return;
++
++ iupASSERT(id_dst >= 0 && id_dst < ih->data->node_count);
++ if (id_dst < 0 || id_dst >= ih->data->node_count)
++ return;
++
++ iupASSERT(id_dst < id_src || id_dst > id_src+count);
++ if (id_dst >= id_src && id_dst <= id_src+count)
++ return;
++
++ /* id_dst here points to the final position for a copy operation */
++
++ /* node_count here contains the final count for a copy operation */
++ iTreeIncCacheMem(ih);
++
++ /* add space for new nodes */
++ remain_count = ih->data->node_count - (id_dst + count);
++ memmove(ih->data->node_cache+id_dst+count, ih->data->node_cache+id_dst, remain_count*sizeof(InodeData));
++
++ /* compensate because we add space for new nodes */
++ if (id_src > id_dst)
++ id_src += count;
++
++ if (is_copy) 
++ {
++ /* during a copy, the userdata is not reused, so clear it */
++ memset(ih->data->node_cache+id_dst, 0, count*sizeof(InodeData));
++ }
++ else /* move = copy + delete */
++ {
++ /* copy userdata from src to dst */
++ memcpy(ih->data->node_cache+id_dst, ih->data->node_cache+id_src, count*sizeof(InodeData));
++
++ /* remove the src */
++ remain_count = ih->data->node_count - (id_src + count);
++ memmove(ih->data->node_cache+id_src, ih->data->node_cache+id_src+count, remain_count*sizeof(InodeData));
++
++ /* clear the remaining space */
++ memset(ih->data->node_cache+ih->data->node_count-count, 0, count*sizeof(InodeData));
++ }
++}
++
++
++/*************************************************************************/
++
++
+ char* iupTreeGetSpacingAttrib(Ihandle* ih)
+ {
+ char *str = iupStrGetMemory(50);
+@@ -221,8 +455,10 @@ static int iTreeSetMarkModeAttrib(Ihandle* ih, const char* value)
+ ih->data->mark_mode = ITREE_MARK_MULTIPLE; 
+ else 
+ ih->data->mark_mode = ITREE_MARK_SINGLE;
++
+ if (ih->handle)
+- iupdrvTreeUpdateMarkMode(ih);
++ iupdrvTreeUpdateMarkMode(ih); /* for this to work, must update during map */
++
+ return 0;
+ }
+ 
+@@ -290,7 +526,7 @@ static int iTreeSetShowDragDropAttrib(Ihandle* ih, const char* value)
+ 
+ static int iTreeSetAddLeafAttrib(Ihandle* ih, const char* name_id, const char* value)
+ {
+- if (!ih->handle) /* do not store the action before map */
++ if (!ih->handle) /* do not do the action before map */
+ return 0;
+ iupdrvTreeAddNode(ih, name_id, ITREE_LEAF, value, 1);
+ return 0;
+@@ -298,7 +534,7 @@ static int iTreeSetAddLeafAttrib(Ihandle* ih, const char* name_id, const char* v
+ 
+ static int iTreeSetAddBranchAttrib(Ihandle* ih, const char* name_id, const char* value)
+ {
+- if (!ih->handle) /* do not store the action before map */
++ if (!ih->handle) /* do not do the action before map */
+ return 0;
+ iupdrvTreeAddNode(ih, name_id, ITREE_BRANCH, value, 1);
+ return 0;
+@@ -306,7 +542,7 @@ static int iTreeSetAddBranchAttrib(Ihandle* ih, const char* name_id, const char*
+ 
+ static int iTreeSetInsertLeafAttrib(Ihandle* ih, const char* name_id, const char* value)
+ {
+- if (!ih->handle) /* do not store the action before map */
++ if (!ih->handle) /* do not do the action before map */
+ return 0;
+ iupdrvTreeAddNode(ih, name_id, ITREE_LEAF, value, 0);
+ return 0;
+@@ -314,7 +550,7 @@ static int iTreeSetInsertLeafAttrib(Ihandle* ih, const char* name_id, const char
+ 
+ static int iTreeSetInsertBranchAttrib(Ihandle* ih, const char* name_id, const char* value)
+ {
+- if (!ih->handle) /* do not store the action before map */
++ if (!ih->handle) /* do not do the action before map */
+ return 0;
+ iupdrvTreeAddNode(ih, name_id, ITREE_BRANCH, value, 0);
+ return 0;
+@@ -338,6 +574,74 @@ static int iTreeSetAddExpandedAttrib(Ihandle* ih, const char* value)
+ return 0;
+ }
+ 
++static char* iTreeGetCountAttrib(Ihandle* ih)
++{
++ char* str = iupStrGetMemory(10);
++ sprintf(str, "%d", ih->data->node_count);
++ return str;
++}
++
++static char* iTreeGetTotalChildCountAttrib(Ihandle* ih, const char* name_id)
++{
++ char* str;
++ InodeHandle* node_handle = iupTreeGetNodeFromString(ih, name_id);
++ if (!node_handle)
++ return NULL;
++
++ str = iupStrGetMemory(10);
++ sprintf(str, "%d", iupdrvTreeTotalChildCount(ih, node_handle));
++ return str;
++}
++
++
++static char* iTreeGetFindUserDataAttrib(Ihandle* ih, const char* name_id)
++{
++ int id;
++ char* str = (char*)(name_id+1); /* skip ':' */
++ void* userdata = NULL;
++ if (sscanf(str, "%p", &userdata)!=1)
++ return NULL;
++ id = iTreeFindUserDataId(ih, userdata);
++ if (id == -1)
++ return NULL;
++ str = iupStrGetMemory(16);
++ sprintf(str, "%d", id);
++ return str;
++}
++
++static char* iTreeGetUserDataAttrib(Ihandle* ih, const char* name_id)
++{
++ int id = iTreeGetIdFromString(name_id);
++ if (id >= 0 && id < ih->data->node_count)
++ return ih->data->node_cache[id].userdata;
++ else if (id == -2)
++ {
++ InodeHandle* node_handle = iupdrvTreeGetFocusNode(ih);
++ id = iupTreeFindNodeId(ih, node_handle);
++ if (id >= 0 && id < ih->data->node_count)
++ return ih->data->node_cache[id].userdata;
++ }
++ return NULL;
++}
++
++static int iTreeSetUserDataAttrib(Ihandle* ih, const char* name_id, const char* value)
++{
++ int id = iTreeGetIdFromString(name_id);
++ if (id >= 0 && id < ih->data->node_count)
++ ih->data->node_cache[id].userdata = (void*)value;
++ else if (id == -2)
++ {
++ InodeHandle* node_handle = iupdrvTreeGetFocusNode(ih);
++ id = iupTreeFindNodeId(ih, node_handle);
++ if (id >= 0 && id < ih->data->node_count)
++ ih->data->node_cache[id].userdata = (void*)value;
++ }
++ return 0;
++}
++
++
++/*************************************************************************/
++
+ static int iTreeCreateMethod(Ihandle* ih, void **params)
+ {
+ (void)params;
+@@ -348,10 +652,20 @@ static int iTreeCreateMethod(Ihandle* ih, void **params)
+ IupSetAttribute(ih, "EXPAND", "YES");
+ 
+ ih->data->add_expanded = 1;
++ ih->data->node_cache_max = 20;
++ ih->data->node_cache = calloc(ih->data->node_cache_max, sizeof(InodeData));
+ 
+ return IUP_NOERROR;
+ }
+ 
++static void iTreeDestroyMethod(Ihandle* ih)
++{
++ if (ih->data->node_cache)
++ free(ih->data->node_cache);
++}
++
++/*************************************************************************/
++
+ Ihandle* IupTree(void)
+ {
+ return IupCreate("tree");
+@@ -371,15 +685,15 @@ Iclass* iupTreeGetClass(void)
+ /* Class functions */
+ ic->Create = iTreeCreateMethod;
+ ic->LayoutUpdate = iupdrvBaseLayoutUpdateMethod;
+- ic->UnMap = iupdrvBaseUnMapMethod;
++ ic->Destroy = iTreeDestroyMethod;
+ 
+ /* Callbacks */
+ iupClassRegisterCallback(ic, "SELECTION_CB", "ii");
+ iupClassRegisterCallback(ic, "MULTISELECTION_CB", "Ii");
++ iupClassRegisterCallback(ic, "MULTIUNSELECTION_CB", "Ii");
+ iupClassRegisterCallback(ic, "BRANCHOPEN_CB", "i");
+ iupClassRegisterCallback(ic, "BRANCHCLOSE_CB", "i");
+ iupClassRegisterCallback(ic, "EXECUTELEAF_CB", "i");
+- iupClassRegisterCallback(ic, "RENAMENODE_CB", "is");
+ iupClassRegisterCallback(ic, "SHOWRENAME_CB", "i");
+ iupClassRegisterCallback(ic, "RENAME_CB", "is");
+ iupClassRegisterCallback(ic, "DRAGDROP_CB", "iiii");
+@@ -392,9 +706,12 @@ Iclass* iupTreeGetClass(void)
+ iupBaseRegisterVisualAttrib(ic);
+ 
+ /* IupTree Attributes - GENERAL */
+- iupClassRegisterAttribute(ic, "SHOWDRAGDROP", iTreeGetShowDragDropAttrib, iTreeSetShowDragDropAttrib, NULL, NULL, IUPAF_NOT_MAPPED|IUPAF_NO_INHERIT);
+- iupClassRegisterAttribute(ic, "SHOWRENAME", iTreeGetShowRenameAttrib, iTreeSetShowRenameAttrib, NULL, NULL, IUPAF_NOT_MAPPED|IUPAF_NO_INHERIT);
+- iupClassRegisterAttribute(ic, "ADDEXPANDED", iTreeGetAddExpandedAttrib, iTreeSetAddExpandedAttrib, IUPAF_SAMEASSYSTEM, "YES", IUPAF_NOT_MAPPED|IUPAF_NO_INHERIT);
++ iupClassRegisterAttribute(ic, "SHOWDRAGDROP", iTreeGetShowDragDropAttrib, iTreeSetShowDragDropAttrib, NULL, NULL, IUPAF_NOT_MAPPED|IUPAF_NO_INHERIT);
++ iupClassRegisterAttribute(ic, "SHOWRENAME", iTreeGetShowRenameAttrib, iTreeSetShowRenameAttrib, NULL, NULL, IUPAF_NOT_MAPPED|IUPAF_NO_INHERIT);
++ iupClassRegisterAttribute(ic, "ADDEXPANDED", iTreeGetAddExpandedAttrib, iTreeSetAddExpandedAttrib, IUPAF_SAMEASSYSTEM, "YES", IUPAF_NOT_MAPPED|IUPAF_NO_INHERIT);
++ iupClassRegisterAttribute(ic, "COUNT", iTreeGetCountAttrib, NULL, NULL, NULL, IUPAF_NO_DEFAULTVALUE|IUPAF_READONLY|IUPAF_NO_INHERIT);
++ iupClassRegisterAttribute(ic, "LASTADDNODE", NULL, NULL, IUPAF_SAMEASSYSTEM, NULL, IUPAF_READONLY|IUPAF_NO_INHERIT);
++ iupClassRegisterAttribute(ic, "ADDROOT", NULL, NULL, IUPAF_SAMEASSYSTEM, "YES", IUPAF_NO_INHERIT);
+ 
+ /* IupTree Attributes - MARKS */
+ iupClassRegisterAttribute(ic, "CTRL", NULL, iTreeSetCtrlAttrib, NULL, NULL, IUPAF_NOT_MAPPED);
+@@ -406,6 +723,11 @@ Iclass* iupTreeGetClass(void)
+ iupClassRegisterAttributeId(ic, "ADDBRANCH", NULL, iTreeSetAddBranchAttrib, IUPAF_NOT_MAPPED|IUPAF_WRITEONLY|IUPAF_NO_INHERIT);
+ iupClassRegisterAttributeId(ic, "INSERTLEAF", NULL, iTreeSetInsertLeafAttrib, IUPAF_NOT_MAPPED|IUPAF_WRITEONLY|IUPAF_NO_INHERIT);
+ iupClassRegisterAttributeId(ic, "INSERTBRANCH", NULL, iTreeSetInsertBranchAttrib, IUPAF_NOT_MAPPED|IUPAF_WRITEONLY|IUPAF_NO_INHERIT);
++
++ /* IupTree Attributes - NODES */
++ iupClassRegisterAttributeId(ic, "TOTALCHILDCOUNT", iTreeGetTotalChildCountAttrib, NULL, IUPAF_READONLY|IUPAF_NO_INHERIT);
++ iupClassRegisterAttributeId(ic, "FINDUSERDATA", iTreeGetFindUserDataAttrib, NULL, IUPAF_READONLY|IUPAF_NO_INHERIT);
++ iupClassRegisterAttributeId(ic, "USERDATA", iTreeGetUserDataAttrib, iTreeSetUserDataAttrib, IUPAF_NO_STRING|IUPAF_NO_INHERIT);
+ 
+ /* Default node images */
+ iTreeInitializeImages();
+@@ -415,18 +737,23 @@ Iclass* iupTreeGetClass(void)
+ return ic;
+ }
+ 
+-
+ /********************************************************************************************/
+ 
+-
+-void IupTreeSetAttribute(Ihandle* ih, const char* a, int id, char* v)
++void IupTreeSetAttribute(Ihandle* ih, const char* a, int id, const char* v)
+ {
+ char* attr = iupStrGetMemory(50);
+ sprintf(attr, "%s%d", a, id);
+ IupSetAttribute(ih, attr, v);
+ }
+ 
+-void IupTreeStoreAttribute(Ihandle* ih, const char* a, int id, char* v)
++void IupTreeSetAttributeHandle(Ihandle* ih, const char* a, int id, Ihandle* ih_named)
++{
++ char* attr = iupStrGetMemory(50);
++ sprintf(attr, "%s%d", a, id);
++ IupSetAttributeHandle(ih, attr, ih_named);
++}
++
++void IupTreeStoreAttribute(Ihandle* ih, const char* a, int id, const char* v)
+ {
+ char* attr = iupStrGetMemory(50);
+ sprintf(attr, "%s%d", a, id);
+@@ -454,7 +781,7 @@ float IupTreeGetFloat(Ihandle* ih, const char* a, int id)
+ return IupGetFloat(ih, attr);
+ }
+ 
+-void IupTreeSetfAttribute(Ihandle* ih, const char* a, int id, char* f, ...)
++void IupTreeSetfAttribute(Ihandle* ih, const char* a, int id, const char* f, ...)
+ {
+ static char v[SHRT_MAX];
+ char* attr = iupStrGetMemory(50);
+@@ -466,34 +793,40 @@ void IupTreeSetfAttribute(Ihandle* ih, const char* a, int id, char* f, ...)
+ IupStoreAttribute(ih, attr, v);
+ }
+ 
+-
+ /************************************************************************************/
+ 
+-
+ int IupTreeSetUserId(Ihandle* ih, int id, void* userdata)
+ {
+- char attr[30];
+- sprintf(attr,"USERDATA%d",id);
+- IupSetAttribute(ih, attr, userdata);
+- return IupGetAttribute(ih, attr)? 1: 0;
++ iupASSERT(iupObjectCheck(ih));
++ if (!iupObjectCheck(ih))
++ return 0;
++
++ if (id >= 0 && id < ih->data->node_count)
++ {
++ ih->data->node_cache[id].userdata = userdata;
++ return 1;
++ }
++
++ return 0;
+ }
+ 
+ int IupTreeGetId(Ihandle* ih, void *userdata)
+ {
+- int id = -1;
+- char* value;
+- char attr[30];
+- sprintf(attr,"FINDUSERDATA:%p",userdata);
+- value = IupGetAttribute(ih, attr);
+- if (!value) return -1;
++ iupASSERT(iupObjectCheck(ih));
++ if (!iupObjectCheck(ih))
++ return -1;
+ 
+- iupStrToInt(value, &id);
+- return id;
++ return iTreeFindUserDataId(ih, userdata);
+ }
+ 
+ void* IupTreeGetUserId(Ihandle* ih, int id)
+ {
+- char attr[30];
+- sprintf(attr,"USERDATA%d",id);
+- return IupGetAttribute(ih, attr);
++ iupASSERT(iupObjectCheck(ih));
++ if (!iupObjectCheck(ih))
++ return NULL;
++
++ if (id >= 0 && id < ih->data->node_count)
++ return ih->data->node_cache[id].userdata;
++
++ return NULL;
+ }
+diff --git a/iup/src/iup_tree.h b/iup/src/iup_tree.h
+index f96a698..44acc83 100755
+--- a/iup/src/iup_tree.h
++++ b/iup/src/iup_tree.h
+@@ -29,6 +29,36 @@ void iupdrvTreeUpdateMarkMode(Ihandle *ih);
+ 
+ char* iupTreeGetSpacingAttrib(Ihandle* ih);
+ 
++#if defined(GTK_MAJOR_VERSION)
++typedef void InodeHandle;
++#elif defined(XmVERSION)
++typedef struct _WidgetRec InodeHandle;
++#elif defined(WINVER)
++typedef struct _TREEITEM InodeHandle;
++#else
++typedef struct _InodeData InodeHandle;
++#endif
++
++typedef struct _InodeData
++{
++ InodeHandle* node_handle;
++ void* userdata;
++} InodeData;
++
++typedef int (*iupTreeNodeFunc)(Ihandle* ih, InodeHandle* node_handle, int id, void* userdata);
++int iupTreeForEach(Ihandle* ih, iupTreeNodeFunc func, void* userdata);
++InodeHandle* iupTreeGetNode(Ihandle* ih, int id);
++InodeHandle* iupTreeGetNodeFromString(Ihandle* ih, const char* name_id);
++int iupTreeFindNodeId(Ihandle* ih, InodeHandle* node_handle);
++
++InodeHandle* iupdrvTreeGetFocusNode(Ihandle* ih);
++int iupdrvTreeTotalChildCount(Ihandle* ih, InodeHandle* node_handle);
++void iupTreeSelectLastCollapsedBranch(Ihandle* ih, int *last_id);
++
++void iupTreeDelFromCache(Ihandle* ih, int id, int count);
++void iupTreeAddToCache(Ihandle* ih, int add, int kindPrev, InodeHandle* prevNode, InodeHandle* node_handle);
++void iupTreeCopyMoveCache(Ihandle* ih, int id_src, int id_dst, int count, int is_copy);
++
+ /* Structure of the tree */
+ struct _IcontrolData
+ {
+@@ -36,6 +66,7 @@ struct _IcontrolData
+ add_expanded,
+ show_dragdrop,
+ show_rename,
++ stamp, /* GTK only */
+ spacing;
+ 
+ void* def_image_leaf; /* Default image leaf */
+@@ -44,9 +75,10 @@ struct _IcontrolData
+ 
+ void* def_image_leaf_mask; /* Motif Only */
+ void* def_image_collapsed_mask; 
+- void* def_image_expanded_mask; 
++ void* def_image_expanded_mask; 
+ 
+- int id_control; /* auxiliary variable for computing or finding the id of a node */
++ InodeData *node_cache;
++ int node_cache_max, node_count;
+ };
+ 
+ 
+diff --git a/iup/src/iup_vbox.c b/iup/src/iup_vbox.c
+index f71aa51..23e8e3a 100755
+--- a/iup/src/iup_vbox.c
++++ b/iup/src/iup_vbox.c
+@@ -215,6 +215,13 @@ static void iVboxSetChildrenCurrentSizeMethod(Ihandle* ih, int shrink)
+ else
+ {
+ int empty = (child->expand & IUP_EXPAND_H1)? empty_h1: ((child->expand & IUP_EXPAND_H0)? empty_h0: 0);
++ char* weigth_str = iupAttribGet(child, "EXPANDWEIGTH");
++ if (weigth_str)
++ {
++ float weigth; 
++ if (iupStrToFloat(weigth_str, &weigth))
++ empty = iupROUND(empty * weigth);
++ }
+ iupBaseSetCurrentSize(child, client_width, child->naturalheight+empty, shrink);
+ }
+ 
+diff --git a/iup/src/iup_zbox.c b/iup/src/iup_zbox.c
+index 3f79892..dd4a0e4 100755
+--- a/iup/src/iup_zbox.c
++++ b/iup/src/iup_zbox.c
+@@ -210,7 +210,7 @@ static int iZboxSetVisibleAttrib(Ihandle* ih, const char* value)
+ {
+ if (iupObjectCheck(ih->data->value_handle))
+ IupSetAttribute(ih->data->value_handle, "VISIBLE", (char*)value);
+- return 0;
++ return 1; /* must be 1 to mark when set at the element */
+ }
+ 
+ static void iZboxComputeNaturalSizeMethod(Ihandle* ih, int *w, int *h, int *expand)
+@@ -368,8 +368,8 @@ Iclass* iupZboxGetClass(void)
+ iupClassRegisterAttribute(ic, "VALUEPOS", iZboxGetValuePosAttrib, iZboxSetValuePosAttrib, NULL, NULL, IUPAF_NOT_MAPPED|IUPAF_NO_INHERIT);
+ iupClassRegisterAttribute(ic, "VALUE_HANDLE", NULL, iZboxSetValueHandleAttrib, NULL, NULL, IUPAF_NOT_MAPPED|IUPAF_NO_INHERIT|IUPAF_NO_STRING);
+ 
+- /* Intercept VISIBLE since ZBOX works showing and hidding its children */
+- iupClassRegisterAttribute(ic, "VISIBLE", NULL, iZboxSetVisibleAttrib, IUPAF_SAMEASSYSTEM, "YES", IUPAF_NOT_MAPPED|IUPAF_NO_INHERIT);
++ /* Intercept VISIBLE since ZBOX works by showing and hidding its children */
++ iupClassRegisterAttribute(ic, "VISIBLE", NULL, iZboxSetVisibleAttrib, IUPAF_SAMEASSYSTEM, "YES", IUPAF_NOT_MAPPED);
+ 
+ return ic;
+ }
+diff --git a/iup/src/make_uname b/iup/src/make_uname
+index 7fec9f8..6542234 100755
+--- a/iup/src/make_uname
++++ b/iup/src/make_uname
+@@ -1,4 +1,4 @@
+ #This builds all the libraries of the folder for 1 uname
+ 
+-tecmake $1 $2 $3 $4 $5 $6 $7
++tecmake USE_MOTIF=Yes $1 $2 $3 $4 $5 $6 $7
+ tecmake USE_GTK=Yes $1 $2 $3 $4 $5 $6 $7
+diff --git a/iup/src/mot/iupmot_button.c b/iup/src/mot/iupmot_button.c
+index 2d93588..f6e383f 100755
+--- a/iup/src/mot/iupmot_button.c
++++ b/iup/src/mot/iupmot_button.c
+@@ -112,8 +112,10 @@ static int motButtonSetPaddingAttrib(Ihandle* ih, const char* value)
+ {
+ XtVaSetValues(ih->handle, XmNmarginHeight, ih->data->vert_padding,
+ XmNmarginWidth, ih->data->horiz_padding, NULL);
++ return 0;
+ }
+- return 0;
++ else
++ return 1; /* store until not mapped, when mapped will be set again */
+ }
+ 
+ static int motButtonSetBgColorAttrib(Ihandle* ih, const char* value)
+@@ -189,43 +191,43 @@ static int motButtonMapMethod(Ihandle* ih)
+ if (value)
+ {
+ ih->data->type = IUP_BUTTON_IMAGE;
+- iupmotSetArg(args, num_args, XmNlabelType, XmPIXMAP);
++ iupMOT_SETARG(args, num_args, XmNlabelType, XmPIXMAP);
+ }
+ else
+ {
+ ih->data->type = IUP_BUTTON_TEXT;
+- iupmotSetArg(args, num_args, XmNlabelType, XmSTRING);
++ iupMOT_SETARG(args, num_args, XmNlabelType, XmSTRING);
+ }
+ 
+ /* Core */
+- iupmotSetArg(args, num_args, XmNmappedWhenManaged, False); /* not visible when managed */
+- iupmotSetArg(args, num_args, XmNx, 0); /* x-position */
+- iupmotSetArg(args, num_args, XmNy, 0); /* y-position */
+- iupmotSetArg(args, num_args, XmNwidth, 10); /* default width to avoid 0 */
+- iupmotSetArg(args, num_args, XmNheight, 10); /* default height to avoid 0 */
++ iupMOT_SETARG(args, num_args, XmNmappedWhenManaged, False); /* not visible when managed */
++ iupMOT_SETARG(args, num_args, XmNx, 0); /* x-position */
++ iupMOT_SETARG(args, num_args, XmNy, 0); /* y-position */
++ iupMOT_SETARG(args, num_args, XmNwidth, 10); /* default width to avoid 0 */
++ iupMOT_SETARG(args, num_args, XmNheight, 10); /* default height to avoid 0 */
+ /* Label */
+- iupmotSetArg(args, num_args, XmNrecomputeSize, False); /* no automatic resize from text */
+- iupmotSetArg(args, num_args, XmNmarginHeight, 0); /* default padding */
+- iupmotSetArg(args, num_args, XmNmarginWidth, 0);
+- iupmotSetArg(args, num_args, XmNmarginTop, 0); /* no extra margins */
+- iupmotSetArg(args, num_args, XmNmarginLeft, 0);
+- iupmotSetArg(args, num_args, XmNmarginBottom, 0);
+- iupmotSetArg(args, num_args, XmNmarginRight, 0);
++ iupMOT_SETARG(args, num_args, XmNrecomputeSize, False); /* no automatic resize from text */
++ iupMOT_SETARG(args, num_args, XmNmarginHeight, 0); /* default padding */
++ iupMOT_SETARG(args, num_args, XmNmarginWidth, 0);
++ iupMOT_SETARG(args, num_args, XmNmarginTop, 0); /* no extra margins */
++ iupMOT_SETARG(args, num_args, XmNmarginLeft, 0);
++ iupMOT_SETARG(args, num_args, XmNmarginBottom, 0);
++ iupMOT_SETARG(args, num_args, XmNmarginRight, 0);
+ /* PushButton */
+- iupmotSetArg(args, num_args, XmNfillOnArm, False);
++ iupMOT_SETARG(args, num_args, XmNfillOnArm, False);
+ 
+ /* Primitive */
+ if (iupAttribGetBoolean(ih, "FOCUSONCLICK"))
+ {
+ if (iupAttribGetBoolean(ih, "CANFOCUS"))
+- iupmotSetArg(args, num_args, XmNtraversalOn, True);
++ iupMOT_SETARG(args, num_args, XmNtraversalOn, True);
+ else
+- iupmotSetArg(args, num_args, XmNtraversalOn, False);
++ iupMOT_SETARG(args, num_args, XmNtraversalOn, False);
+ }
+ else
+- iupmotSetArg(args, num_args, XmNtraversalOn, False);
+- iupmotSetArg(args, num_args, XmNhighlightThickness, 2);
+- iupmotSetArg(args, num_args, XmNnavigationType, XmTAB_GROUP);
++ iupMOT_SETARG(args, num_args, XmNtraversalOn, False);
++ iupMOT_SETARG(args, num_args, XmNhighlightThickness, 2);
++ iupMOT_SETARG(args, num_args, XmNnavigationType, XmTAB_GROUP);
+ 
+ ih->handle = XtCreateManagedWidget(
+ iupDialogGetChildIdStr(ih), /* child identifier */
+diff --git a/iup/src/mot/iupmot_canvas.c b/iup/src/mot/iupmot_canvas.c
+index 7777cf3..299bbcd 100755
+--- a/iup/src/mot/iupmot_canvas.c
++++ b/iup/src/mot/iupmot_canvas.c
+@@ -434,6 +434,10 @@ static void motCanvasLayoutUpdateMethod(Ihandle *ih)
+ 
+ XtVaGetValues(sb_win, XmNborderWidth, &border, NULL);
+ 
++ /* avoid abort in X */
++ if (ih->currentwidth <= 2*border) ih->currentwidth = 2*border+1;
++ if (ih->currentheight <= 2*border) ih->currentheight = 2*border+1;
++
+ XtVaSetValues(sb_win,
+ XmNx, (XtArgVal)ih->x,
+ XmNy, (XtArgVal)ih->y,
+@@ -458,19 +462,19 @@ static int motCanvasMapMethod(Ihandle* ih)
+ /* Create the scrolled window */
+ /******************************/
+ 
+- iupmotSetArg(args, num_args, XmNmappedWhenManaged, False); /* not visible when managed */
+- iupmotSetArg(args, num_args, XmNscrollingPolicy, XmAPPLICATION_DEFINED);
+- iupmotSetArg(args, num_args, XmNvisualPolicy, XmVARIABLE);
+- iupmotSetArg(args, num_args, XmNspacing, 0); /* no space between scrollbars and draw area */
+- iupmotSetArg(args, num_args, XmNshadowThickness, 0);
++ iupMOT_SETARG(args, num_args, XmNmappedWhenManaged, False); /* not visible when managed */
++ iupMOT_SETARG(args, num_args, XmNscrollingPolicy, XmAPPLICATION_DEFINED);
++ iupMOT_SETARG(args, num_args, XmNvisualPolicy, XmVARIABLE);
++ iupMOT_SETARG(args, num_args, XmNspacing, 0); /* no space between scrollbars and draw area */
++ iupMOT_SETARG(args, num_args, XmNshadowThickness, 0);
+ 
+ if (iupAttribGetBoolean(ih, "BORDER"))
+ {
+- iupmotSetArg(args, num_args, XmNborderWidth, 1);
+- iupmotSetArg(args, num_args, XmNborderColor, iupmotColorGetPixelStr("0 0 0"));
++ iupMOT_SETARG(args, num_args, XmNborderWidth, 1);
++ iupMOT_SETARG(args, num_args, XmNborderColor, iupmotColorGetPixelStr("0 0 0"));
+ }
+ else
+- iupmotSetArg(args, num_args, XmNborderWidth, 0);
++ iupMOT_SETARG(args, num_args, XmNborderWidth, 0);
+ 
+ sb_win = XtCreateManagedWidget(
+ iupDialogGetChildIdStr(ih), /* child identifier */
+@@ -488,36 +492,36 @@ static int motCanvasMapMethod(Ihandle* ih)
+ /****************************/
+ 
+ num_args = 0;
+- iupmotSetArg(args, num_args, XmNmarginHeight, 0); /* no shadow margins */
+- iupmotSetArg(args, num_args, XmNmarginWidth, 0); /* no shadow margins */
+- iupmotSetArg(args, num_args, XmNshadowThickness, 0);
+- iupmotSetArg(args, num_args, XmNresizePolicy, XmRESIZE_NONE); /* no automatic resize of children */
++ iupMOT_SETARG(args, num_args, XmNmarginHeight, 0); /* no shadow margins */
++ iupMOT_SETARG(args, num_args, XmNmarginWidth, 0); /* no shadow margins */
++ iupMOT_SETARG(args, num_args, XmNshadowThickness, 0);
++ iupMOT_SETARG(args, num_args, XmNresizePolicy, XmRESIZE_NONE); /* no automatic resize of children */
+ if (ih->iclass->is_interactive)
+ {
+- iupmotSetArg(args, num_args, XmNnavigationType, XmTAB_GROUP); /* include in navigation */
++ iupMOT_SETARG(args, num_args, XmNnavigationType, XmTAB_GROUP); /* include in navigation */
+ 
+ if (iupAttribGetBoolean(ih, "CANFOCUS"))
+- iupmotSetArg(args, num_args, XmNtraversalOn, True);
++ iupMOT_SETARG(args, num_args, XmNtraversalOn, True);
+ else
+- iupmotSetArg(args, num_args, XmNtraversalOn, False);
++ iupMOT_SETARG(args, num_args, XmNtraversalOn, False);
+ }
+ else
+ {
+- iupmotSetArg(args, num_args, XmNnavigationType, XmNONE);
+- iupmotSetArg(args, num_args, XmNtraversalOn, False);
++ iupMOT_SETARG(args, num_args, XmNnavigationType, XmNONE);
++ iupMOT_SETARG(args, num_args, XmNtraversalOn, False);
+ }
+ 
+- iupmotSetArg(args, num_args, XmNx, 0); /* x-position */
+- iupmotSetArg(args, num_args, XmNy, 0); /* y-position */
+- iupmotSetArg(args, num_args, XmNwidth, 10); /* default width to avoid 0 */
+- iupmotSetArg(args, num_args, XmNheight, 10); /* default height to avoid 0 */
++ iupMOT_SETARG(args, num_args, XmNx, 0); /* x-position */
++ iupMOT_SETARG(args, num_args, XmNy, 0); /* y-position */
++ iupMOT_SETARG(args, num_args, XmNwidth, 10); /* default width to avoid 0 */
++ iupMOT_SETARG(args, num_args, XmNheight, 10); /* default height to avoid 0 */
+ 
+ visual = IupGetAttribute(ih, "VISUAL"); /* defined by the OpenGL Canvas or NULL */
+ if (visual)
+ {
+ Colormap colormap = (Colormap)iupAttribGet(ih, "COLORMAP");
+ if (colormap)
+- iupmotSetArg(args, num_args, XmNcolormap,colormap);
++ iupMOT_SETARG(args, num_args, XmNcolormap,colormap);
+ 
+ iupmotDialogSetVisual(ih, visual);
+ }
+diff --git a/iup/src/mot/iupmot_common.c b/iup/src/mot/iupmot_common.c
+index 7b3f8b7..286e075 100755
+--- a/iup/src/mot/iupmot_common.c
++++ b/iup/src/mot/iupmot_common.c
+@@ -167,6 +167,10 @@ void iupdrvBaseLayoutUpdateMethod(Ihandle *ih)
+ Widget widget = (Widget)iupAttribGet(ih, "_IUP_EXTRAPARENT");
+ if (!widget) widget = ih->handle;
+ 
++ /* avoid abort in X */
++ if (ih->currentwidth == 0) ih->currentwidth = 1;
++ if (ih->currentheight == 0) ih->currentheight = 1;
++
+ XtVaSetValues(widget,
+ XmNx, (XtArgVal)ih->x,
+ XmNy, (XtArgVal)ih->y,
+@@ -184,7 +188,7 @@ void iupdrvBaseUnMapMethod(Ihandle* ih)
+ XtDestroyWidget(widget); /* To match the call to XtCreateManagedWidget */
+ }
+ 
+-void iupdrvDisplayUpdate(Ihandle *ih)
++void iupdrvPostRedraw(Ihandle *ih)
+ {
+ XExposeEvent evt;
+ Dimension w, h;
+@@ -209,12 +213,12 @@ void iupdrvDisplayUpdate(Ihandle *ih)
+ XSendEvent(iupmot_display, XtWindow(ih->handle), False, ExposureMask, (XEvent*)&evt);
+ }
+ 
+-void iupdrvDisplayRedraw(Ihandle *ih)
++void iupdrvRedrawNow(Ihandle *ih)
+ {
+ Widget w;
+ 
+ /* POST a Redraw */
+- iupdrvDisplayUpdate(ih);
++ iupdrvPostRedraw(ih);
+ 
+ /* if this element has an inner native parent (like IupTabs), 
+ then redraw that native parent if different from the element. */
+@@ -223,7 +227,7 @@ void iupdrvDisplayRedraw(Ihandle *ih)
+ {
+ Widget handle = ih->handle;
+ ih->handle = w;
+- iupdrvDisplayUpdate(ih);
++ iupdrvPostRedraw(ih);
+ ih->handle = handle;
+ }
+ 
+@@ -276,10 +280,11 @@ int iupdrvBaseSetZorderAttrib(Ihandle* ih, const char* value)
+ {
+ if (iupdrvIsVisible(ih))
+ {
++ Widget widget = (Widget)iupAttribGet(ih, "_IUP_EXTRAPARENT");
+ if (iupStrEqualNoCase(value, "TOP"))
+- XRaiseWindow(iupmot_display, XtWindow(ih->handle));
++ XRaiseWindow(iupmot_display, XtWindow(widget));
+ else
+- XLowerWindow(iupmot_display, XtWindow(ih->handle));
++ XLowerWindow(iupmot_display, XtWindow(widget));
+ }
+ 
+ return 0;
+@@ -455,9 +460,11 @@ static Cursor motGetCursor(Ihandle* ih, const char* name)
+ { "RESIZE_N", XC_top_side},
+ { "RESIZE_S", XC_bottom_side},
+ { "RESIZE_NS", XC_sb_v_double_arrow},
++ { "SPLITTER_HORIZ", XC_sb_v_double_arrow},
+ { "RESIZE_W", XC_left_side},
+ { "RESIZE_E", XC_right_side},
+ { "RESIZE_WE", XC_sb_h_double_arrow},
++ { "SPLITTER_VERT", XC_sb_h_double_arrow},
+ { "RESIZE_NE", XC_top_right_corner},
+ { "RESIZE_SE", XC_bottom_right_corner},
+ { "RESIZE_NW", XC_top_left_corner},
+diff --git a/iup/src/mot/iupmot_dialog.c b/iup/src/mot/iupmot_dialog.c
+index 4eeb834..7a27d74 100755
+--- a/iup/src/mot/iupmot_dialog.c
++++ b/iup/src/mot/iupmot_dialog.c
+@@ -134,12 +134,13 @@ void iupdrvDialogGetDecoration(Ihandle* ih, int *border, int *caption, int *menu
+ static int native_border = 0;
+ static int native_caption = 0;
+ 
+- int has_caption = iupAttribGetBoolean(ih, "MAXBOX") ||
+- iupAttribGetBoolean(ih, "MINBOX") ||
+- iupAttribGetBoolean(ih, "MENUBOX") || 
+- IupGetAttribute(ih, "TITLE"); /* must use IupGetAttribute to check from the native implementation */
++ int has_titlebar = iupAttribGetBoolean(ih, "RESIZE") || /* GTK and Motif only */
++ iupAttribGetBoolean(ih, "MAXBOX") ||
++ iupAttribGetBoolean(ih, "MINBOX") ||
++ iupAttribGetBoolean(ih, "MENUBOX") || 
++ IupGetAttribute(ih, "TITLE"); /* must use IupGetAttribute to check from the native implementation */
+ 
+- int has_border = has_caption ||
++ int has_border = has_titlebar ||
+ iupAttribGetBoolean(ih, "RESIZE") ||
+ iupAttribGetBoolean(ih, "BORDER");
+ 
+@@ -155,7 +156,7 @@ void iupdrvDialogGetDecoration(Ihandle* ih, int *border, int *caption, int *menu
+ *border = win_border;
+ 
+ *caption = 0;
+- if (has_caption)
++ if (has_titlebar)
+ *caption = win_caption;
+ 
+ if (!native_border && *border)
+@@ -181,7 +182,7 @@ void iupdrvDialogGetDecoration(Ihandle* ih, int *border, int *caption, int *menu
+ }
+ 
+ *caption = 0;
+- if (has_caption)
++ if (has_titlebar)
+ {
+ if (native_caption)
+ *caption = native_caption;
+@@ -853,6 +854,7 @@ static int motDialogMapMethod(Ihandle* ih)
+ InativeHandle* parent;
+ int mwm_decor = 0;
+ int num_args = 0;
++ int has_titlebar = 0;
+ Arg args[20];
+ 
+ if (iupAttribGetBoolean(ih, "DIALOGFRAME")) 
+@@ -867,32 +869,46 @@ static int motDialogMapMethod(Ihandle* ih)
+ /****************************/
+ 
+ if (iupAttribGet(ih, "TITLE"))
+- mwm_decor |= MWM_DECOR_TITLE;
++ has_titlebar = 1;
+ if (iupAttribGetBoolean(ih, "MENUBOX"))
+- mwm_decor |= MWM_DECOR_MENU;
++ {
++ mwm_decor |= MWM_DECOR_MENU;
++ has_titlebar = 1;
++ }
+ if (iupAttribGetBoolean(ih, "MINBOX"))
+- mwm_decor |= MWM_DECOR_MINIMIZE;
++ {
++ mwm_decor |= MWM_DECOR_MINIMIZE;
++ has_titlebar = 1;
++ }
+ if (iupAttribGetBoolean(ih, "MAXBOX"))
+- mwm_decor |= MWM_DECOR_MAXIMIZE;
++ {
++ mwm_decor |= MWM_DECOR_MAXIMIZE;
++ has_titlebar = 1;
++ }
+ if (iupAttribGetBoolean(ih, "RESIZE"))
+- mwm_decor |= MWM_DECOR_RESIZEH;
+- if (iupAttribGetBoolean(ih, "BORDER"))
+- mwm_decor |= MWM_DECOR_BORDER;
+-
+- iupmotSetArg(args, num_args, XmNmappedWhenManaged, False); /* so XtRealizeWidget will not show the dialog */
+- iupmotSetArg(args, num_args, XmNdeleteResponse, XmDO_NOTHING);
+- iupmotSetArg(args, num_args, XmNallowShellResize, True); /* Used so the BulletinBoard can control the shell size */
+- iupmotSetArg(args, num_args, XmNtitle, "");
+- iupmotSetArg(args, num_args, XmNvisual, iupmot_visual);
++ {
++ mwm_decor |= MWM_DECOR_RESIZEH;
++ mwm_decor |= MWM_DECOR_BORDER; /* has_border */
++ }
++ if (has_titlebar)
++ mwm_decor |= MWM_DECOR_TITLE;
++ if (iupAttribGetBoolean(ih, "BORDER") || has_titlebar) 
++ mwm_decor |= MWM_DECOR_BORDER; /* has_border */
++
++ iupMOT_SETARG(args, num_args, XmNmappedWhenManaged, False); /* so XtRealizeWidget will not show the dialog */
++ iupMOT_SETARG(args, num_args, XmNdeleteResponse, XmDO_NOTHING);
++ iupMOT_SETARG(args, num_args, XmNallowShellResize, True); /* Used so the BulletinBoard can control the shell size */
++ iupMOT_SETARG(args, num_args, XmNtitle, "");
++ iupMOT_SETARG(args, num_args, XmNvisual, iupmot_visual);
+ 
+ if (iupmotColorMap()) 
+- iupmotSetArg(args, num_args, XmNcolormap, iupmotColorMap());
++ iupMOT_SETARG(args, num_args, XmNcolormap, iupmotColorMap());
+ 
+ if (mwm_decor != 0x7E) 
+- iupmotSetArg(args, num_args, XmNmwmDecorations, mwm_decor);
++ iupMOT_SETARG(args, num_args, XmNmwmDecorations, mwm_decor);
+ 
+ if (iupAttribGetBoolean(ih, "SAVEUNDER"))
+- iupmotSetArg(args, num_args, XmNsaveUnder, True);
++ iupMOT_SETARG(args, num_args, XmNsaveUnder, True);
+ 
+ parent = iupDialogGetNativeParent(ih);
+ if (parent)
+diff --git a/iup/src/mot/iupmot_drv.h b/iup/src/mot/iupmot_drv.h
+index 8a536ef..424ae9f 100755
+--- a/iup/src/mot/iupmot_drv.h
++++ b/iup/src/mot/iupmot_drv.h
+@@ -65,7 +65,7 @@ void iupmotGetWindowSize(Ihandle *ih, int *width, int *height);
+ 
+ char* iupmotGetXWindowAttrib(Ihandle *ih);
+ 
+-#define iupmotSetArg(_a, _i, _n, _d) ((_a)[(_i)].name = (_n), (_a)[(_i)].value = (XtArgVal)(_d), (_i)++)
++#define iupMOT_SETARG(_a, _i, _n, _d) ((_a)[(_i)].name = (_n), (_a)[(_i)].value = (XtArgVal)(_d), (_i)++)
+ 
+ 
+ #ifdef __cplusplus
+diff --git a/iup/src/mot/iupmot_filedlg.c b/iup/src/mot/iupmot_filedlg.c
+index 768dd2b..0be6319 100755
+--- a/iup/src/mot/iupmot_filedlg.c
++++ b/iup/src/mot/iupmot_filedlg.c
+@@ -17,6 +17,7 @@
+ #include <Xm/DrawingA.h>
+ #include <Xm/PushB.h>
+ #include <Xm/Frame.h>
++#include <Xm/List.h>
+ 
+ #include "iup.h"
+ #include "iupcbs.h"
+@@ -28,6 +29,7 @@
+ #include "iup_dialog.h"
+ #include "iup_strmessage.h"
+ #include "iup_drvinfo.h"
++#include "iup_array.h"
+ 
+ #include "iupmot_drv.h"
+ 
+@@ -87,14 +89,14 @@ static int motFileDlgCheckValue(Ihandle* ih, Widget w)
+ return 0;
+ }
+ }
+- else
++ else if (!iupAttribGetBoolean(ih, "MULTIPLEFILES"))
+ {
+ if (iupdrvIsDirectory(value)) /* selected a directory */
+ {
+ iupStrMessageShowError(ih, "IUP_INVALIDDIR");
+ return 0;
+ }
+- else if (!iupdrvIsFile(value)) /* new file */
++ else if (!iupdrvIsFile(value)) /* not a file == new file */
+ {
+ value = iupAttribGet(ih, "ALLOWNEW");
+ if (!value)
+@@ -132,6 +134,51 @@ static void motFileDlgCBclose(Widget w, XtPointer client_data, XtPointer call_da
+ iupAttribSetStr(ih, "_IUP_WM_DELETE", "1");
+ }
+ 
++static int motFileDlgGetMultipleFiles(Ihandle* ih, const char* dir, Widget wList)
++{
++ int *pos, sel_count, dir_len;
++ int i, len, cur_len;
++ char *filename, *all_names;
++ Iarray* names_array;
++ XmString* items;
++
++ if (!XmListGetSelectedPos(wList, &pos, &sel_count))
++ return 0;
++
++ names_array = iupArrayCreate(1024, 1); /* just set an initial size, but count is 0 */
++ XtVaGetValues(wList, XmNitems, &items, NULL);
++
++ cur_len = strlen(dir);
++
++ all_names = iupArrayAdd(names_array, cur_len+1);
++ memcpy(all_names, dir, cur_len);
++ all_names[cur_len] = '|';
++ dir_len = cur_len;
++ cur_len++; /* skip separator */
++
++ for (i = 0; i<sel_count; i++)
++ {
++ filename = iupmotConvertString(items[pos[i]-1]); /* XmListGetSelectedPos starts at 1 */
++ len = strlen(filename)-dir_len;
++
++ cur_len = iupArrayCount(names_array);
++ all_names = iupArrayAdd(names_array, len+1);
++ memcpy(all_names+cur_len, filename+dir_len, len);
++ all_names[cur_len+len] = '|';
++ }
++
++ XtFree((char*)pos);
++
++ cur_len = iupArrayCount(names_array);
++ all_names = iupArrayInc(names_array);
++ all_names[cur_len+1] = 0;
++
++ iupAttribStoreStr(ih, "VALUE", all_names);
++
++ iupArrayDestroy(names_array);
++ return 1;
++}
++
+ static void motFileDlgCallback(Widget w, Ihandle* ih, XmFileSelectionBoxCallbackStruct* call_data)
+ {
+ (void)w;
+@@ -151,14 +198,38 @@ static void motFileDlgCallback(Widget w, Ihandle* ih, XmFileSelectionBoxCallback
+ iupAttribSetStr(ih, "STATUS", "0");
+ iupAttribSetStr(ih, "FILEEXIST", NULL);
+ }
++ else if (iupAttribGetBoolean(ih, "MULTIPLEFILES"))
++ {
++ Widget wList = XmFileSelectionBoxGetChild(w, XmDIALOG_LIST);
++
++ /* VALUE obtained above contains exactly the DIRECTORY */
++ char* dir = iupAttribGet(ih, "VALUE");
++ int len = strlen(dir);
++ if (dir[len-1]=='/') dir[len-1] = 0; /* remove last '/' */
++ iupAttribStoreStr(ih, "DIRECTORY", dir);
++
++ if (!motFileDlgGetMultipleFiles(ih, iupAttribGet(ih, "DIRECTORY"), wList))
++ {
++ iupStrMessageShowError(ih, "IUP_FILENOTEXIST");
++ return;
++ }
++
++ iupAttribSetStr(ih, "STATUS", "0");
++ iupAttribSetStr(ih, "FILEEXIST", "YES");
++ }
+ else
+ {
+ IFnss file_cb = (IFnss)IupGetCallback(ih, "FILE_CB");
+- if (file_cb && file_cb(ih, iupAttribGet(ih, "VALUE"), "OK") == IUP_IGNORE)
++ filename = iupAttribGet(ih, "VALUE");
++ if (file_cb && file_cb(ih, filename, "OK") == IUP_IGNORE)
+ return;
+ 
+- if (iupdrvIsFile(iupAttribGet(ih, "VALUE"))) /* check if file exists */
++ if (iupdrvIsFile(filename)) /* check if file exists */
+ {
++ char* dir = iupStrFileGetPath(filename);
++ iupAttribStoreStr(ih, "DIRECTORY", dir);
++ free(dir);
++
+ iupAttribSetStr(ih, "FILEEXIST", "YES");
+ iupAttribSetStr(ih, "STATUS", "0");
+ }
+@@ -188,9 +259,8 @@ static void motFileDlgCallback(Widget w, Ihandle* ih, XmFileSelectionBoxCallback
+ }
+ }
+ 
+-static void motFileDlgHelpCallback(Widget w, XtPointer client_data, XtPointer call_data)
++static void motFileDlgHelpCallback(Widget w, Ihandle *ih, XtPointer call_data)
+ {
+- Ihandle *ih = (Ihandle*)client_data;
+ Icallback cb = IupGetCallback(ih, "HELP_CB");
+ if (cb && cb(ih) == IUP_CLOSE)
+ {
+@@ -340,14 +410,15 @@ static void motFileDlgPreviewCanvasExposeCallback(Widget w, Ihandle *ih, XtPoint
+ static void motFileDlgBrowseSelectionCallback(Widget w, Ihandle* ih, XmListCallbackStruct* list_data)
+ {
+ char* filename;
++ IFnss cb;
+ 
+ XmStringGetLtoR(list_data->item, XmSTRING_DEFAULT_CHARSET, &filename);
+ 
++ cb = (IFnss)IupGetCallback(ih, "FILE_CB");
+ if (iupdrvIsFile(filename))
+- {
+- IFnss cb = (IFnss)IupGetCallback(ih, "FILE_CB");
+ cb(ih, filename, "SELECT");
+- }
++ else
++ cb(ih, filename, "OTHER");
+ 
+ XtFree(filename);
+ (void)w;
+@@ -417,6 +488,13 @@ static int motFileDlgPopup(Ihandle* ih, int x, int y)
+ if (dialogtype == IUP_DIALOGDIR)
+ XtVaSetValues(filebox, XmNfileTypeMask, XmFILE_DIRECTORY, NULL);
+ 
++ if (iupAttribGetBoolean(ih, "MULTIPLEFILES"))
++ {
++ Widget wList = XmFileSelectionBoxGetChild(filebox, XmDIALOG_LIST);
++ XtVaSetValues(wList, XmNselectionPolicy, XmEXTENDED_SELECT, NULL);
++ XtAddCallback(wList, XmNextendedSelectionCallback, (XtCallbackProc)motFileDlgBrowseSelectionCallback, (XtPointer)ih);
++ }
++
+ /* just check for the path inside FILE */
+ value = iupAttribGet(ih, "FILE");
+ if (value && value[0] == '/')
+@@ -501,8 +579,10 @@ static int motFileDlgPopup(Ihandle* ih, int x, int y)
+ file_cb = (IFnss)IupGetCallback(ih, "FILE_CB");
+ if (file_cb)
+ {
+- Widget file_list = XmFileSelectionBoxGetChild(filebox, XmDIALOG_LIST);
+- XtAddCallback(file_list, XmNbrowseSelectionCallback, (XtCallbackProc)motFileDlgBrowseSelectionCallback, (XtPointer)ih);
++ Widget list = XmFileSelectionBoxGetChild(filebox, XmDIALOG_LIST);
++ XtAddCallback(list, XmNbrowseSelectionCallback, (XtCallbackProc)motFileDlgBrowseSelectionCallback, (XtPointer)ih);
++ list = XmFileSelectionBoxGetChild(filebox, XmDIALOG_DIR_LIST);
++ XtAddCallback(list, XmNbrowseSelectionCallback, (XtCallbackProc)motFileDlgBrowseSelectionCallback, (XtPointer)ih);
+ 
+ if (iupAttribGetBoolean(ih, "SHOWPREVIEW"))
+ {
+@@ -575,4 +655,6 @@ static int motFileDlgPopup(Ihandle* ih, int x, int y)
+ void iupdrvFileDlgInitClass(Iclass* ic)
+ {
+ ic->DlgPopup = motFileDlgPopup;
++
++ iupClassRegisterAttribute(ic, "MULTIPLEFILES", NULL, NULL, NULL, NULL, IUPAF_NO_INHERIT);
+ }
+diff --git a/iup/src/mot/iupmot_font.c b/iup/src/mot/iupmot_font.c
+index 8da06dd..42154b6 100755
+--- a/iup/src/mot/iupmot_font.c
++++ b/iup/src/mot/iupmot_font.c
+@@ -135,19 +135,19 @@ static XmFontList motFontCreateRenderTable(XFontStruct* fontstruct, int is_under
+ Arg args[10];
+ int num_args = 0;
+ 
+- iupmotSetArg(args, num_args, XmNfontType, XmFONT_IS_FONT);
+- iupmotSetArg(args, num_args, XmNfont, (XtPointer)fontstruct);
+- iupmotSetArg(args, num_args, XmNloadModel, XmLOAD_IMMEDIATE);
++ iupMOT_SETARG(args, num_args, XmNfontType, XmFONT_IS_FONT);
++ iupMOT_SETARG(args, num_args, XmNfont, (XtPointer)fontstruct);
++ iupMOT_SETARG(args, num_args, XmNloadModel, XmLOAD_IMMEDIATE);
+ 
+ if (is_underline)
+- iupmotSetArg(args, num_args, XmNunderlineType, XmSINGLE_LINE);
++ iupMOT_SETARG(args, num_args, XmNunderlineType, XmSINGLE_LINE);
+ else
+- iupmotSetArg(args, num_args, XmNunderlineType, XmNO_LINE);
++ iupMOT_SETARG(args, num_args, XmNunderlineType, XmNO_LINE);
+ 
+ if (is_strikeout)
+- iupmotSetArg(args, num_args, XmNstrikethruType, XmSINGLE_LINE);
++ iupMOT_SETARG(args, num_args, XmNstrikethruType, XmSINGLE_LINE);
+ else
+- iupmotSetArg(args, num_args, XmNstrikethruType, XmNO_LINE);
++ iupMOT_SETARG(args, num_args, XmNstrikethruType, XmNO_LINE);
+ 
+ rendition = XmRenditionCreate(NULL, "", args, num_args);
+ 
+diff --git a/iup/src/mot/iupmot_frame.c b/iup/src/mot/iupmot_frame.c
+index 39de5d8..cfda44f 100755
+--- a/iup/src/mot/iupmot_frame.c
++++ b/iup/src/mot/iupmot_frame.c
+@@ -42,22 +42,33 @@ static int motFrameSetBgColorAttrib(Ihandle* ih, const char* value)
+ {
+ Pixel color;
+ 
+- /* ignore given value, must use only from parent */
+- value = iupBaseNativeParentGetBgColor(ih);
++ if (!iupAttribGet(ih, "_IUPFRAME_HAS_BGCOLOR"))
++ {
++ /* ignore given value, must use only from parent */
++ value = iupBaseNativeParentGetBgColor(ih);
++ }
+ 
+ color = iupmotColorGetPixelStr(value);
+ if (color != (Pixel)-1)
+ {
+ Widget title_label, child_manager;
+ 
+- iupmotSetBgColor(ih->handle, color);
++ if (!iupAttribGet(ih, "_IUPFRAME_HAS_BGCOLOR"))
++ {
++ iupmotSetBgColor(ih->handle, color);
+ 
+- child_manager = XtNameToWidget(ih->handle, "*child_manager");
+- iupmotSetBgColor(child_manager, color);
++ child_manager = XtNameToWidget(ih->handle, "*child_manager");
++ iupmotSetBgColor(child_manager, color);
+ 
+- title_label = XtNameToWidget(ih->handle, "*title_label");
+- if (!title_label) return 1;
+- iupmotSetBgColor(title_label, color);
++ title_label = XtNameToWidget(ih->handle, "*title_label");
++ if (!title_label) return 1;
++ iupmotSetBgColor(title_label, color);
++ }
++ else
++ {
++ child_manager = XtNameToWidget(ih->handle, "*child_manager");
++ iupmotSetBgColor(child_manager, color);
++ }
+ 
+ return 1;
+ }
+@@ -171,22 +182,25 @@ static int motFrameMapMethod(Ihandle* ih)
+ {
+ char* value = iupAttribGetStr(ih, "SUNKEN");
+ if (iupStrBoolean(value))
+- iupmotSetArg(args, num_args, XmNshadowType, XmSHADOW_IN); 
++ iupMOT_SETARG(args, num_args, XmNshadowType, XmSHADOW_IN); 
+ else
+- iupmotSetArg(args, num_args, XmNshadowType, XmSHADOW_ETCHED_IN); 
++ iupMOT_SETARG(args, num_args, XmNshadowType, XmSHADOW_ETCHED_IN); 
++
++ if (iupAttribGet(ih, "BGCOLOR"))
++ iupAttribSetStr(ih, "_IUPFRAME_HAS_BGCOLOR", "1");
+ }
+ 
+ /* Core */
+- iupmotSetArg(args, num_args, XmNmappedWhenManaged, False); /* not visible when managed */
+- iupmotSetArg(args, num_args, XmNx, 0); /* x-position */
+- iupmotSetArg(args, num_args, XmNy, 0); /* y-position */
+- iupmotSetArg(args, num_args, XmNwidth, 10); /* default width to avoid 0 */
+- iupmotSetArg(args, num_args, XmNheight, 10); /* default height to avoid 0 */
++ iupMOT_SETARG(args, num_args, XmNmappedWhenManaged, False); /* not visible when managed */
++ iupMOT_SETARG(args, num_args, XmNx, 0); /* x-position */
++ iupMOT_SETARG(args, num_args, XmNy, 0); /* y-position */
++ iupMOT_SETARG(args, num_args, XmNwidth, 10); /* default width to avoid 0 */
++ iupMOT_SETARG(args, num_args, XmNheight, 10); /* default height to avoid 0 */
+ /* Manager */
+- iupmotSetArg(args, num_args, XmNshadowThickness, 2);
++ iupMOT_SETARG(args, num_args, XmNshadowThickness, 2);
+ /* Frame */
+- iupmotSetArg(args, num_args, XmNmarginHeight, 0); /* no shadow margins */
+- iupmotSetArg(args, num_args, XmNmarginWidth, 0); /* no shadow margins */
++ iupMOT_SETARG(args, num_args, XmNmarginHeight, 0); /* no shadow margins */
++ iupMOT_SETARG(args, num_args, XmNmarginWidth, 0); /* no shadow margins */
+ 
+ ih->handle = XtCreateManagedWidget(
+ iupDialogGetChildIdStr(ih), /* child identifier */
+@@ -204,11 +218,11 @@ static int motFrameMapMethod(Ihandle* ih)
+ Widget title_label;
+ num_args = 0;
+ /* Label */
+- iupmotSetArg(args, num_args, XmNlabelType, XmSTRING); 
+- iupmotSetArg(args, num_args, XmNmarginHeight, 0); /* default padding */
+- iupmotSetArg(args, num_args, XmNmarginWidth, 0);
++ iupMOT_SETARG(args, num_args, XmNlabelType, XmSTRING); 
++ iupMOT_SETARG(args, num_args, XmNmarginHeight, 0); /* default padding */
++ iupMOT_SETARG(args, num_args, XmNmarginWidth, 0);
+ /* Frame Constraint */
+- iupmotSetArg(args, num_args, XmNchildType, XmFRAME_TITLE_CHILD);
++ iupMOT_SETARG(args, num_args, XmNchildType, XmFRAME_TITLE_CHILD);
+ title_label = XtCreateManagedWidget("title_label", xmLabelWidgetClass, ih->handle, args, num_args);
+ iupmotSetString(title_label, XmNlabelString, title);
+ }
+diff --git a/iup/src/mot/iupmot_key.c b/iup/src/mot/iupmot_key.c
+index 835b5d7..9897741 100755
+--- a/iup/src/mot/iupmot_key.c
++++ b/iup/src/mot/iupmot_key.c
+@@ -393,33 +393,33 @@ void iupmotKeyPressEvent(Widget w, Ihandle *ih, XEvent *evt, Boolean *cont)
+ void iupmotButtonKeySetStatus(unsigned int state, unsigned int but, char* status, int doubleclick)
+ {
+ if (state & ShiftMask)
+- iupKEYSETSHIFT(status);
++ iupKEY_SETSHIFT(status);
+ 
+ if (state & ControlMask)
+- iupKEYSETCONTROL(status); 
++ iupKEY_SETCONTROL(status); 
+ 
+ if ((state & Button1Mask) || but==Button1)
+- iupKEYSETBUTTON1(status);
++ iupKEY_SETBUTTON1(status);
+ 
+ if ((state & Button2Mask) || but==Button2)
+- iupKEYSETBUTTON2(status);
++ iupKEY_SETBUTTON2(status);
+ 
+ if ((state & Button3Mask) || but==Button3)
+- iupKEYSETBUTTON3(status);
++ iupKEY_SETBUTTON3(status);
+ 
+ if ((state & Button4Mask) || but==Button4)
+- iupKEYSETBUTTON4(status);
++ iupKEY_SETBUTTON4(status);
+ 
+ if ((state & Button5Mask) || but==Button5)
+- iupKEYSETBUTTON5(status);
++ iupKEY_SETBUTTON5(status);
+ 
+ if (state & Mod1Mask || state & Mod5Mask) /* Alt */
+- iupKEYSETALT(status);
++ iupKEY_SETALT(status);
+ 
+ if (state & Mod4Mask) /* Apple/Win */
+- iupKEYSETSYS(status);
++ iupKEY_SETSYS(status);
+ 
+ if (doubleclick)
+- iupKEYSETDOUBLE(status);
++ iupKEY_SETDOUBLE(status);
+ }
+ 
+diff --git a/iup/src/mot/iupmot_label.c b/iup/src/mot/iupmot_label.c
+index 52dfc9a..afff3c3 100755
+--- a/iup/src/mot/iupmot_label.c
++++ b/iup/src/mot/iupmot_label.c
+@@ -147,8 +147,10 @@ static int motLabelSetPaddingAttrib(Ihandle* ih, const char* value)
+ {
+ XtVaSetValues(ih->handle, XmNmarginHeight, ih->data->vert_padding,
+ XmNmarginWidth, ih->data->horiz_padding, NULL);
++ return 0;
+ }
+- return 0;
++ else
++ return 1; /* store until not mapped, when mapped will be set again */
+ }
+ 
+ static int motLabelMapMethod(Ihandle* ih)
+@@ -165,12 +167,12 @@ static int motLabelMapMethod(Ihandle* ih)
+ if (iupStrEqualNoCase(value, "HORIZONTAL"))
+ {
+ ih->data->type = IUP_LABEL_SEP_HORIZ;
+- iupmotSetArg(args, num_args, XmNorientation, XmHORIZONTAL);
++ iupMOT_SETARG(args, num_args, XmNorientation, XmHORIZONTAL);
+ }
+ else /* "VERTICAL" */
+ {
+ ih->data->type = IUP_LABEL_SEP_VERT;
+- iupmotSetArg(args, num_args, XmNorientation, XmVERTICAL);
++ iupMOT_SETARG(args, num_args, XmNorientation, XmVERTICAL);
+ }
+ }
+ else
+@@ -180,32 +182,32 @@ static int motLabelMapMethod(Ihandle* ih)
+ if (value)
+ {
+ ih->data->type = IUP_LABEL_IMAGE;
+- iupmotSetArg(args, num_args, XmNlabelType, XmPIXMAP); 
++ iupMOT_SETARG(args, num_args, XmNlabelType, XmPIXMAP); 
+ }
+ else
+ {
+ ih->data->type = IUP_LABEL_TEXT;
+- iupmotSetArg(args, num_args, XmNlabelType, XmSTRING); 
++ iupMOT_SETARG(args, num_args, XmNlabelType, XmSTRING); 
+ }
+ }
+ 
+ /* Core */
+- iupmotSetArg(args, num_args, XmNmappedWhenManaged, False); /* not visible when managed */
+- iupmotSetArg(args, num_args, XmNx, 0); /* x-position */
+- iupmotSetArg(args, num_args, XmNy, 0); /* y-position */
+- iupmotSetArg(args, num_args, XmNwidth, 10); /* default width to avoid 0 */
+- iupmotSetArg(args, num_args, XmNheight, 10); /* default height to avoid 0 */
++ iupMOT_SETARG(args, num_args, XmNmappedWhenManaged, False); /* not visible when managed */
++ iupMOT_SETARG(args, num_args, XmNx, 0); /* x-position */
++ iupMOT_SETARG(args, num_args, XmNy, 0); /* y-position */
++ iupMOT_SETARG(args, num_args, XmNwidth, 10); /* default width to avoid 0 */
++ iupMOT_SETARG(args, num_args, XmNheight, 10); /* default height to avoid 0 */
+ /* Primitive */
+- iupmotSetArg(args, num_args, XmNtraversalOn, False);
+- iupmotSetArg(args, num_args, XmNhighlightThickness, 0);
++ iupMOT_SETARG(args, num_args, XmNtraversalOn, False);
++ iupMOT_SETARG(args, num_args, XmNhighlightThickness, 0);
+ /* Label */
+- iupmotSetArg(args, num_args, XmNrecomputeSize, False); /* no automatic resize from text */
+- iupmotSetArg(args, num_args, XmNmarginHeight, 0); /* default padding */
+- iupmotSetArg(args, num_args, XmNmarginWidth, 0);
+- iupmotSetArg(args, num_args, XmNmarginTop, 0); /* no extra margins */
+- iupmotSetArg(args, num_args, XmNmarginLeft, 0);
+- iupmotSetArg(args, num_args, XmNmarginBottom, 0);
+- iupmotSetArg(args, num_args, XmNmarginRight, 0);
++ iupMOT_SETARG(args, num_args, XmNrecomputeSize, False); /* no automatic resize from text */
++ iupMOT_SETARG(args, num_args, XmNmarginHeight, 0); /* default padding */
++ iupMOT_SETARG(args, num_args, XmNmarginWidth, 0);
++ iupMOT_SETARG(args, num_args, XmNmarginTop, 0); /* no extra margins */
++ iupMOT_SETARG(args, num_args, XmNmarginLeft, 0);
++ iupMOT_SETARG(args, num_args, XmNmarginBottom, 0);
++ iupMOT_SETARG(args, num_args, XmNmarginRight, 0);
+ 
+ ih->handle = XtCreateManagedWidget(
+ iupDialogGetChildIdStr(ih), /* child identifier */
+diff --git a/iup/src/mot/iupmot_list.c b/iup/src/mot/iupmot_list.c
+index f8e73ed..800e6e9 100755
+--- a/iup/src/mot/iupmot_list.c
++++ b/iup/src/mot/iupmot_list.c
+@@ -143,15 +143,36 @@ void iupdrvListInsertItem(Ihandle* ih, int pos, const char* value)
+ motListAddSortedItem(ih, value);
+ else
+ motListAddItem(ih, pos, value);
++
++ iupListUpdateOldValue(ih, pos, 0);
+ }
+ 
+ void iupdrvListRemoveItem(Ihandle* ih, int pos)
+ {
+ /* The utility functions use 0=last 1=first */
+ if (ih->data->is_dropdown || ih->data->has_editbox)
++ {
++ if (ih->data->is_dropdown && !ih->data->has_editbox)
++ {
++ /* must check if removing the current item */
++ int curpos;
++ XtVaGetValues(ih->handle, XmNselectedPosition, &curpos, NULL);
++ if (pos == curpos && iupdrvListGetCount(ih)>1)
++ {
++ if (curpos > 0) curpos--;
++ else curpos++;
++
++ XtRemoveCallback(ih->handle, XmNselectionCallback, (XtCallbackProc)motListComboBoxSelectionCallback, (XtPointer)ih);
++ XtVaSetValues(ih->handle, XmNselectedPosition, curpos, NULL); 
++ XtAddCallback(ih->handle, XmNselectionCallback, (XtCallbackProc)motListComboBoxSelectionCallback, (XtPointer)ih);
++ }
++ }
+ XmComboBoxDeletePos(ih->handle, pos+1);
++ }
+ else
+ XmListDeletePos(ih->handle, pos+1);
++
++ iupListUpdateOldValue(ih, pos, 1);
+ }
+ 
+ void iupdrvListRemoveAllItems(Ihandle* ih)
+@@ -174,7 +195,7 @@ void iupdrvListRemoveAllItems(Ihandle* ih)
+ static char* motListGetIdValueAttrib(Ihandle* ih, const char* name_id)
+ {
+ int pos = iupListGetPos(ih, name_id);
+- if (pos != -1)
++ if (pos >= 0)
+ {
+ XmString* items;
+ XtVaGetValues(ih->handle, XmNitems, &items, NULL);
+@@ -852,8 +873,10 @@ static int motListSetNCAttrib(Ihandle* ih, const char* value)
+ Widget cbedit;
+ XtVaGetValues(ih->handle, XmNtextField, &cbedit, NULL);
+ XtVaSetValues(cbedit, XmNmaxLength, ih->data->nc, NULL);
++ return 0;
+ }
+- return 0;
++ else
++ return 1; /* store until not mapped, when mapped will be set again */
+ }
+ 
+ static int motListSetClipboardAttrib(Ihandle *ih, const char *value)
+@@ -1181,32 +1204,32 @@ static int motListMapMethod(Ihandle* ih)
+ if (ih->data->is_dropdown || ih->data->has_editbox)
+ {
+ /* could not set XmNmappedWhenManaged to False because the list and the edit box where not displayed */
+- /* iupmotSetArg(args, num_args, XmNmappedWhenManaged, False); */
+- iupmotSetArg(args, num_args, XmNx, 0); /* x-position */
+- iupmotSetArg(args, num_args, XmNy, 0); /* y-position */
+- iupmotSetArg(args, num_args, XmNwidth, 10); /* default width to avoid 0 */
+- iupmotSetArg(args, num_args, XmNheight, 10); /* default height to avoid 0 */
+- iupmotSetArg(args, num_args, XmNmarginHeight, 0);
+- iupmotSetArg(args, num_args, XmNmarginWidth, 0);
++ /* iupMOT_SETARG(args, num_args, XmNmappedWhenManaged, False); */
++ iupMOT_SETARG(args, num_args, XmNx, 0); /* x-position */
++ iupMOT_SETARG(args, num_args, XmNy, 0); /* y-position */
++ iupMOT_SETARG(args, num_args, XmNwidth, 10); /* default width to avoid 0 */
++ iupMOT_SETARG(args, num_args, XmNheight, 10); /* default height to avoid 0 */
++ iupMOT_SETARG(args, num_args, XmNmarginHeight, 0);
++ iupMOT_SETARG(args, num_args, XmNmarginWidth, 0);
+ 
+ if (iupAttribGetBoolean(ih, "CANFOCUS"))
+- iupmotSetArg(args, num_args, XmNtraversalOn, True);
++ iupMOT_SETARG(args, num_args, XmNtraversalOn, True);
+ else
+- iupmotSetArg(args, num_args, XmNtraversalOn, False);
++ iupMOT_SETARG(args, num_args, XmNtraversalOn, False);
+ 
+- iupmotSetArg(args, num_args, XmNnavigationType, XmTAB_GROUP);
+- iupmotSetArg(args, num_args, XmNhighlightThickness, 2);
+- iupmotSetArg(args, num_args, XmNshadowThickness, 2);
++ iupMOT_SETARG(args, num_args, XmNnavigationType, XmTAB_GROUP);
++ iupMOT_SETARG(args, num_args, XmNhighlightThickness, 2);
++ iupMOT_SETARG(args, num_args, XmNshadowThickness, 2);
+ 
+ if (ih->data->has_editbox)
+ {
+ if (ih->data->is_dropdown)
+- iupmotSetArg(args, num_args, XmNcomboBoxType, XmDROP_DOWN_COMBO_BOX); /* hidden-list+edit */
++ iupMOT_SETARG(args, num_args, XmNcomboBoxType, XmDROP_DOWN_COMBO_BOX); /* hidden-list+edit */
+ else
+- iupmotSetArg(args, num_args, XmNcomboBoxType, XmCOMBO_BOX); /* visible-list+edit */
++ iupMOT_SETARG(args, num_args, XmNcomboBoxType, XmCOMBO_BOX); /* visible-list+edit */
+ }
+ else
+- iupmotSetArg(args, num_args, XmNcomboBoxType, XmDROP_DOWN_LIST); /* hidden-list */
++ iupMOT_SETARG(args, num_args, XmNcomboBoxType, XmDROP_DOWN_LIST); /* hidden-list */
+ 
+ ih->handle = XtCreateManagedWidget(
+ child_id, /* child identifier */
+@@ -1220,13 +1243,13 @@ static int motListMapMethod(Ihandle* ih)
+ 
+ /* Create the scrolled window */
+ 
+- iupmotSetArg(args, num_args, XmNmappedWhenManaged, False); /* not visible when managed */
+- iupmotSetArg(args, num_args, XmNscrollingPolicy, XmAPPLICATION_DEFINED);
+- iupmotSetArg(args, num_args, XmNvisualPolicy, XmVARIABLE);
+- iupmotSetArg(args, num_args, XmNscrollBarDisplayPolicy, XmSTATIC); /* can NOT be XmAS_NEEDED because XmAPPLICATION_DEFINED */
+- iupmotSetArg(args, num_args, XmNspacing, 0); /* no space between scrollbars and text */
+- iupmotSetArg(args, num_args, XmNborderWidth, 0);
+- iupmotSetArg(args, num_args, XmNshadowThickness, 0);
++ iupMOT_SETARG(args, num_args, XmNmappedWhenManaged, False); /* not visible when managed */
++ iupMOT_SETARG(args, num_args, XmNscrollingPolicy, XmAPPLICATION_DEFINED);
++ iupMOT_SETARG(args, num_args, XmNvisualPolicy, XmVARIABLE);
++ iupMOT_SETARG(args, num_args, XmNscrollBarDisplayPolicy, XmSTATIC); /* can NOT be XmAS_NEEDED because XmAPPLICATION_DEFINED */
++ iupMOT_SETARG(args, num_args, XmNspacing, 0); /* no space between scrollbars and text */
++ iupMOT_SETARG(args, num_args, XmNborderWidth, 0);
++ iupMOT_SETARG(args, num_args, XmNshadowThickness, 0);
+ 
+ sb_win = XtCreateManagedWidget(
+ child_id, /* child identifier */
+@@ -1243,34 +1266,34 @@ static int motListMapMethod(Ihandle* ih)
+ /* Create the list */
+ 
+ num_args = 0;
+- iupmotSetArg(args, num_args, XmNx, 0); /* x-position */
+- iupmotSetArg(args, num_args, XmNy, 0); /* y-position */
+- iupmotSetArg(args, num_args, XmNwidth, 10); /* default width to avoid 0 */
+- iupmotSetArg(args, num_args, XmNheight, 10); /* default height to avoid 0 */
++ iupMOT_SETARG(args, num_args, XmNx, 0); /* x-position */
++ iupMOT_SETARG(args, num_args, XmNy, 0); /* y-position */
++ iupMOT_SETARG(args, num_args, XmNwidth, 10); /* default width to avoid 0 */
++ iupMOT_SETARG(args, num_args, XmNheight, 10); /* default height to avoid 0 */
+ 
+ if (iupAttribGetBoolean(ih, "CANFOCUS"))
+- iupmotSetArg(args, num_args, XmNtraversalOn, True);
++ iupMOT_SETARG(args, num_args, XmNtraversalOn, True);
+ else
+- iupmotSetArg(args, num_args, XmNtraversalOn, False);
++ iupMOT_SETARG(args, num_args, XmNtraversalOn, False);
+ 
+- iupmotSetArg(args, num_args, XmNnavigationType, XmTAB_GROUP);
+- iupmotSetArg(args, num_args, XmNhighlightThickness, 2);
+- iupmotSetArg(args, num_args, XmNshadowThickness, 2);
++ iupMOT_SETARG(args, num_args, XmNnavigationType, XmTAB_GROUP);
++ iupMOT_SETARG(args, num_args, XmNhighlightThickness, 2);
++ iupMOT_SETARG(args, num_args, XmNshadowThickness, 2);
+ 
+- iupmotSetArg(args, num_args, XmNlistMarginHeight, 0); /* default padding */
+- iupmotSetArg(args, num_args, XmNlistMarginWidth, 0);
+- iupmotSetArg(args, num_args, XmNlistSpacing, 0);
+- iupmotSetArg(args, num_args, XmNlistSizePolicy, XmCONSTANT); /* don't grow to fit, add scrollbar */
++ iupMOT_SETARG(args, num_args, XmNlistMarginHeight, 0); /* default padding */
++ iupMOT_SETARG(args, num_args, XmNlistMarginWidth, 0);
++ iupMOT_SETARG(args, num_args, XmNlistSpacing, 0);
++ iupMOT_SETARG(args, num_args, XmNlistSizePolicy, XmCONSTANT); /* don't grow to fit, add scrollbar */
+ 
+ if (ih->data->is_multiple)
+- iupmotSetArg(args, num_args, XmNselectionPolicy, XmEXTENDED_SELECT);
++ iupMOT_SETARG(args, num_args, XmNselectionPolicy, XmEXTENDED_SELECT);
+ else
+- iupmotSetArg(args, num_args, XmNselectionPolicy, XmBROWSE_SELECT);
++ iupMOT_SETARG(args, num_args, XmNselectionPolicy, XmBROWSE_SELECT);
+ 
+ if (iupAttribGetBoolean(ih, "AUTOHIDE"))
+- iupmotSetArg(args, num_args, XmNscrollBarDisplayPolicy, XmAS_NEEDED);
++ iupMOT_SETARG(args, num_args, XmNscrollBarDisplayPolicy, XmAS_NEEDED);
+ else
+- iupmotSetArg(args, num_args, XmNscrollBarDisplayPolicy, XmSTATIC);
++ iupMOT_SETARG(args, num_args, XmNscrollBarDisplayPolicy, XmSTATIC);
+ 
+ ih->handle = XtCreateManagedWidget(
+ child_id, /* child identifier */
+diff --git a/iup/src/mot/iupmot_loop.c b/iup/src/mot/iupmot_loop.c
+index 828ddcd..c1f92ec 100755
+--- a/iup/src/mot/iupmot_loop.c
++++ b/iup/src/mot/iupmot_loop.c
+@@ -56,7 +56,7 @@ void iupdrvSetIdleFunction(Icallback f)
+ mot_idle_id = XtAppAddWorkProc(iupmot_appcontext, motIdlecbWorkProc, NULL);
+ }
+ 
+-static int motLoopStep(void)
++static int motLoopProcessEvent(void)
+ {
+ XtAppProcessEvent(iupmot_appcontext, XtIMAll);
+ return (mot_exitmainloop)? IUP_CLOSE : IUP_DEFAULT;
+@@ -79,7 +79,7 @@ int IupMainLoop(void)
+ 
+ while (!mot_exitmainloop)
+ {
+- if (motLoopStep() == IUP_CLOSE)
++ if (motLoopProcessEvent() == IUP_CLOSE)
+ break;
+ }
+ 
+@@ -88,19 +88,26 @@ int IupMainLoop(void)
+ return IUP_NOERROR;
+ }
+ 
++int IupLoopStepWait(void)
++{
++ while(!XtAppPending(iupmot_appcontext));
++
++ return motLoopProcessEvent();
++}
++
+ int IupLoopStep(void)
+ {
+ if (!XtAppPending(iupmot_appcontext)) 
+ return IUP_DEFAULT;
+ 
+- return motLoopStep();
++ return motLoopProcessEvent();
+ }
+ 
+ void IupFlush(void)
+ {
+ while (XPending(iupmot_display) != 0)
+ {
+- if (motLoopStep() == IUP_CLOSE)
++ if (motLoopProcessEvent() == IUP_CLOSE)
+ break;
+ }
+ 
+diff --git a/iup/src/mot/iupmot_menu.c b/iup/src/mot/iupmot_menu.c
+index be9b953..8f51334 100755
+--- a/iup/src/mot/iupmot_menu.c
++++ b/iup/src/mot/iupmot_menu.c
+@@ -125,7 +125,10 @@ static void motPopupMenuUnmapCallback(Widget w, Ihandle* ih, XtPointer call_data
+ static void motMenuUnMapMethod(Ihandle* ih)
+ {
+ if (iupMenuIsMenuBar(ih))
++ {
+ XtDestroyWidget(ih->handle);
++ ih->parent = NULL;
++ }
+ else
+ XtDestroyWidget(XtParent(ih->handle)); /* in this case the RowColumn widget is a child of a MenuShell. */
+ }
+@@ -146,7 +149,6 @@ static int motMenuMapMethod(Ihandle* ih)
+ XmNrowColumnType, XmMENU_BAR,
+ XmNmarginHeight, 0,
+ XmNmarginWidth, 0,
+- XmNresizeWidth, False,
+ NULL);
+ if (!ih->handle)
+ return IUP_ERROR;
+@@ -161,8 +163,8 @@ static int motMenuMapMethod(Ihandle* ih)
+ 
+ if (iupAttribGetBoolean(ih, "RADIO"))
+ {
+- iupmotSetArg(args, num_args, XmNpacking, XmPACK_COLUMN);
+- iupmotSetArg(args, num_args, XmNradioBehavior, TRUE);
++ iupMOT_SETARG(args, num_args, XmNpacking, XmPACK_COLUMN);
++ iupMOT_SETARG(args, num_args, XmNradioBehavior, TRUE);
+ }
+ 
+ ih->handle = XmCreatePulldownMenu(
+@@ -183,7 +185,7 @@ static int motMenuMapMethod(Ihandle* ih)
+ {
+ /* top level menu used for IupPopup */
+ 
+- iupmotSetArg(args, num_args, XmNpopupEnabled, XmPOPUP_AUTOMATIC);
++ iupMOT_SETARG(args, num_args, XmNpopupEnabled, XmPOPUP_AUTOMATIC);
+ 
+ ih->handle = XmCreatePopupMenu(
+ iupmot_appshell, 
+@@ -307,19 +309,19 @@ static int motItemMapMethod(Ihandle* ih)
+ 
+ if (iupAttribGetBoolean(ih->parent, "RADIO"))
+ {
+- iupmotSetArg(args, num_args, XmNtoggleMode, XmTOGGLE_BOOLEAN);
+- iupmotSetArg(args, num_args, XmNindicatorType, XmONE_OF_MANY_ROUND);
+- iupmotSetArg(args, num_args, XmNindicatorOn, XmINDICATOR_CHECK_BOX);
+- iupmotSetArg(args, num_args, XmNindicatorSize, 13);
+- iupmotSetArg(args, num_args, XmNselectColor, iupmotColorGetPixel(0, 0, 0));
++ iupMOT_SETARG(args, num_args, XmNtoggleMode, XmTOGGLE_BOOLEAN);
++ iupMOT_SETARG(args, num_args, XmNindicatorType, XmONE_OF_MANY_ROUND);
++ iupMOT_SETARG(args, num_args, XmNindicatorOn, XmINDICATOR_CHECK_BOX);
++ iupMOT_SETARG(args, num_args, XmNindicatorSize, 13);
++ iupMOT_SETARG(args, num_args, XmNselectColor, iupmotColorGetPixel(0, 0, 0));
+ }
+ else
+ {
+ if (iupAttribGetBoolean(ih, "HIDEMARK"))
+- iupmotSetArg(args, num_args, XmNindicatorOn, XmINDICATOR_NONE);
++ iupMOT_SETARG(args, num_args, XmNindicatorOn, XmINDICATOR_NONE);
+ else
+- iupmotSetArg(args, num_args, XmNindicatorOn, XmINDICATOR_CHECK);
+- iupmotSetArg(args, num_args, XmNlabelType, iupAttribGet(ih, "TITLEIMAGE")? XmPIXMAP: XmSTRING);
++ iupMOT_SETARG(args, num_args, XmNindicatorOn, XmINDICATOR_CHECK);
++ iupMOT_SETARG(args, num_args, XmNlabelType, iupAttribGet(ih, "TITLEIMAGE")? XmPIXMAP: XmSTRING);
+ }
+ 
+ ih->handle = XtCreateManagedWidget(
+diff --git a/iup/src/mot/iupmot_progressbar.c b/iup/src/mot/iupmot_progressbar.c
+index 7266d38..82fa178 100755
+--- a/iup/src/mot/iupmot_progressbar.c
++++ b/iup/src/mot/iupmot_progressbar.c
+@@ -98,25 +98,25 @@ static int motProgressBarMapMethod(Ihandle* ih)
+ Arg args[30];
+ 
+ /* Core */
+- iupmotSetArg(args, num_args, XmNmappedWhenManaged, False); /* not visible when managed */
+- iupmotSetArg(args, num_args, XmNx, 0); /* x-position */
+- iupmotSetArg(args, num_args, XmNy, 0); /* y-position */
+- iupmotSetArg(args, num_args, XmNwidth, 10); /* default width to avoid 0 */
+- iupmotSetArg(args, num_args, XmNheight, 10); /* default height to avoid 0 */
++ iupMOT_SETARG(args, num_args, XmNmappedWhenManaged, False); /* not visible when managed */
++ iupMOT_SETARG(args, num_args, XmNx, 0); /* x-position */
++ iupMOT_SETARG(args, num_args, XmNy, 0); /* y-position */
++ iupMOT_SETARG(args, num_args, XmNwidth, 10); /* default width to avoid 0 */
++ iupMOT_SETARG(args, num_args, XmNheight, 10); /* default height to avoid 0 */
+ /* Primitive */
+- iupmotSetArg(args, num_args, XmNtraversalOn, False);
+- iupmotSetArg(args, num_args, XmNhighlightThickness, 0);
++ iupMOT_SETARG(args, num_args, XmNtraversalOn, False);
++ iupMOT_SETARG(args, num_args, XmNhighlightThickness, 0);
+ /* Scale */
+- iupmotSetArg(args, num_args, XmNminimum, 0);
+- iupmotSetArg(args, num_args, XmNmaximum, SHRT_MAX);
+- iupmotSetArg(args, num_args, XmNslidingMode, XmTHERMOMETER); /* thermometer effect */
+- iupmotSetArg(args, num_args, XmNsliderMark, XmNONE);
+- iupmotSetArg(args, num_args, XmNeditable, False);
+- iupmotSetArg(args, num_args, XmNshowValue, XmNONE);
++ iupMOT_SETARG(args, num_args, XmNminimum, 0);
++ iupMOT_SETARG(args, num_args, XmNmaximum, SHRT_MAX);
++ iupMOT_SETARG(args, num_args, XmNslidingMode, XmTHERMOMETER); /* thermometer effect */
++ iupMOT_SETARG(args, num_args, XmNsliderMark, XmNONE);
++ iupMOT_SETARG(args, num_args, XmNeditable, False);
++ iupMOT_SETARG(args, num_args, XmNshowValue, XmNONE);
+ 
+ if (iupStrEqualNoCase(iupAttribGetStr(ih, "ORIENTATION"), "VERTICAL"))
+ {
+- iupmotSetArg(args, num_args, XmNorientation, XmVERTICAL);
++ iupMOT_SETARG(args, num_args, XmNorientation, XmVERTICAL);
+ 
+ if (ih->currentheight < ih->currentwidth)
+ {
+@@ -126,7 +126,7 @@ static int motProgressBarMapMethod(Ihandle* ih)
+ }
+ }
+ else
+- iupmotSetArg(args, num_args, XmNorientation, XmHORIZONTAL);
++ iupMOT_SETARG(args, num_args, XmNorientation, XmHORIZONTAL);
+ 
+ ih->handle = XtCreateManagedWidget(
+ iupDialogGetChildIdStr(ih), /* child identifier */
+diff --git a/iup/src/mot/iupmot_tabs.c b/iup/src/mot/iupmot_tabs.c
+index 7c8a6b5..cafc41d 100755
+--- a/iup/src/mot/iupmot_tabs.c
++++ b/iup/src/mot/iupmot_tabs.c
+@@ -52,8 +52,10 @@ void iupdrvTabsSetCurrentTab(Ihandle* ih, int pos)
+ {
+ Ihandle* child = IupGetChild(ih, pos);
+ Ihandle* prev_child = IupGetChild(ih, iupdrvTabsGetCurrentTab(ih));
+- IupSetAttribute(child, "VISIBLE", "YES");
+- IupSetAttribute(prev_child, "VISIBLE", "NO");
++ Widget child_manager = (Widget)iupAttribGet(child, "_IUPTAB_CONTAINER");
++ Widget prev_child_manager = (Widget)iupAttribGet(prev_child, "_IUPTAB_CONTAINER");
++ XtMapWidget(child_manager);
++ if (prev_child_manager) XtUnmapWidget(prev_child_manager);
+ 
+ XtVaSetValues(ih->handle, XmNcurrentPageNumber, pos, NULL);
+ }
+@@ -200,7 +202,7 @@ static int motTabsSetTabTypeAttrib(Ihandle* ih, const char* value)
+ ih->data->type = ITABS_TOP;
+ 
+ if (ih->handle)
+- motTabsUpdateTabType(ih);
++ motTabsUpdateTabType(ih); /* for this to work must be updated in map */
+ 
+ return 0;
+ }
+@@ -313,8 +315,10 @@ void motTabsPageChangedCallback(Widget w, Ihandle* ih, XmNotebookCallbackStruct
+ IFnnn cb;
+ Ihandle* child = IupGetChild(ih, nptr->page_number);
+ Ihandle* prev_child = IupGetChild(ih, nptr->prev_page_number);
+- IupSetAttribute(child, "VISIBLE", "YES");
+- IupSetAttribute(prev_child, "VISIBLE", "NO");
++ Widget child_manager = (Widget)iupAttribGet(child, "_IUPTAB_CONTAINER");
++ Widget prev_child_manager = (Widget)iupAttribGet(prev_child, "_IUPTAB_CONTAINER");
++ XtMapWidget(child_manager);
++ if (prev_child_manager) XtUnmapWidget(prev_child_manager);
+ 
+ cb = (IFnnn)IupGetCallback(ih, "TABCHANGE_CB");
+ if (cb)
+@@ -397,12 +401,12 @@ static void motTabsChildAddedMethod(Ihandle* ih, Ihandle* child)
+ 
+ /* Create tabs */
+ /* Label */
+- iupmotSetArg(args, num_args, XmNlabelType, tabtitle? XmSTRING: XmPIXMAP);
+- iupmotSetArg(args, num_args, XmNmarginHeight, 0);
+- iupmotSetArg(args, num_args, XmNmarginWidth, 0);
++ iupMOT_SETARG(args, num_args, XmNlabelType, tabtitle? XmSTRING: XmPIXMAP);
++ iupMOT_SETARG(args, num_args, XmNmarginHeight, 0);
++ iupMOT_SETARG(args, num_args, XmNmarginWidth, 0);
+ /* Notebook Constraint */
+- iupmotSetArg(args, num_args, XmNnotebookChildType, XmMAJOR_TAB);
+- iupmotSetArg(args, num_args, XmNpageNumber, pos);
++ iupMOT_SETARG(args, num_args, XmNnotebookChildType, XmMAJOR_TAB);
++ iupMOT_SETARG(args, num_args, XmNpageNumber, pos);
+ tab_button = XtCreateManagedWidget("tab_button", xmPushButtonWidgetClass, ih->handle, args, num_args);
+ 
+ /* Disable Drag Source */
+@@ -450,10 +454,8 @@ static void motTabsChildAddedMethod(Ihandle* ih, Ihandle* child)
+ iupAttribSetStr(child, "_IUPMOT_TABBUTTON", (char*)tab_button);
+ iupAttribSetInt(child, "_IUPMOT_TABNUMBER", pos);
+ 
+- if (pos == iupdrvTabsGetCurrentTab(ih))
+- IupSetAttribute(child, "VISIBLE", "YES");
+- else
+- IupSetAttribute(child, "VISIBLE", "NO");
++ if (pos != iupdrvTabsGetCurrentTab(ih))
++ XtUnmapWidget(child_manager);
+ }
+ }
+ 
+@@ -464,20 +466,11 @@ static void motTabsChildRemovedMethod(Ihandle* ih, Ihandle* child)
+ Widget child_manager = (Widget)iupAttribGet(child, "_IUPTAB_CONTAINER");
+ if (child_manager)
+ {
+- int cur_pos, pos;
++ int pos;
+ Widget tab_button = (Widget)iupAttribGet(child, "_IUPMOT_TABBUTTON");
+ 
+- cur_pos = iupdrvTabsGetCurrentTab(ih);
+ pos = iupAttribGetInt(child, "_IUPMOT_TABNUMBER"); /* did not work when using XtVaGetValues(child_manager, XmNpageNumber) */
+- if (cur_pos == pos)
+- {
+- if (cur_pos == 0)
+- cur_pos = 1;
+- else
+- cur_pos--;
+-
+- iupdrvTabsSetCurrentTab(ih, cur_pos);
+- }
++ iupTabsTestRemoveTab(ih, pos);
+ 
+ XtDestroyWidget(tab_button);
+ XtDestroyWidget(child_manager);
+@@ -501,22 +494,22 @@ static int motTabsMapMethod(Ihandle* ih)
+ return IUP_ERROR;
+ 
+ /* Core */
+- iupmotSetArg(args, num_args, XmNmappedWhenManaged, False); /* not visible when managed */
+- iupmotSetArg(args, num_args, XmNx, 0); /* x-position */
+- iupmotSetArg(args, num_args, XmNy, 0); /* y-position */
+- iupmotSetArg(args, num_args, XmNwidth, 10); /* default width to avoid 0 */
+- iupmotSetArg(args, num_args, XmNheight, 10); /* default height to avoid 0 */
++ iupMOT_SETARG(args, num_args, XmNmappedWhenManaged, False); /* not visible when managed */
++ iupMOT_SETARG(args, num_args, XmNx, 0); /* x-position */
++ iupMOT_SETARG(args, num_args, XmNy, 0); /* y-position */
++ iupMOT_SETARG(args, num_args, XmNwidth, 10); /* default width to avoid 0 */
++ iupMOT_SETARG(args, num_args, XmNheight, 10); /* default height to avoid 0 */
+ /* Manager */
+- iupmotSetArg(args, num_args, XmNshadowThickness, 0);
+- iupmotSetArg(args, num_args, XmNtraversalOn, True);
+- iupmotSetArg(args, num_args, XmNhighlightThickness, 0);
++ iupMOT_SETARG(args, num_args, XmNshadowThickness, 0);
++ iupMOT_SETARG(args, num_args, XmNtraversalOn, True);
++ iupMOT_SETARG(args, num_args, XmNhighlightThickness, 0);
+ /* Notebook */
+- iupmotSetArg(args, num_args, XmNbindingType, XmNONE);
+- iupmotSetArg(args, num_args, XmNbindingWidth, 0);
+- iupmotSetArg(args, num_args, XmNfirstPageNumber, 0); /* IupTabs index always starts with zero */
+- iupmotSetArg(args, num_args, XmNbackPageSize, 0);
+- iupmotSetArg(args, num_args, XmNbackPageNumber, 1);
+- iupmotSetArg(args, num_args, XmNframeShadowThickness, 2);
++ iupMOT_SETARG(args, num_args, XmNbindingType, XmNONE);
++ iupMOT_SETARG(args, num_args, XmNbindingWidth, 0);
++ iupMOT_SETARG(args, num_args, XmNfirstPageNumber, 0); /* IupTabs index always starts with zero */
++ iupMOT_SETARG(args, num_args, XmNbackPageSize, 0);
++ iupMOT_SETARG(args, num_args, XmNbackPageNumber, 1);
++ iupMOT_SETARG(args, num_args, XmNframeShadowThickness, 2);
+ 
+ ih->handle = XtCreateManagedWidget(
+ iupDialogGetChildIdStr(ih), /* child identifier */
+@@ -589,5 +582,5 @@ void iupdrvTabsInitClass(Iclass* ic)
+ iupClassRegisterAttribute(ic, "TABORIENTATION", iupTabsGetTabOrientationAttrib, NULL, IUPAF_SAMEASSYSTEM, "HORIZONTAL", IUPAF_READONLY|IUPAF_NOT_MAPPED|IUPAF_NO_INHERIT); /* can not be set, always HORIZONTAL in Motif */
+ iupClassRegisterAttributeId(ic, "TABTITLE", NULL, motTabsSetTabTitleAttrib, IUPAF_NO_INHERIT);
+ iupClassRegisterAttributeId(ic, "TABIMAGE", NULL, motTabsSetTabImageAttrib, IUPAF_NO_INHERIT);
+- iupClassRegisterAttribute(ic, "PADDING", iupTabsGetPaddingAttrib, motTabsSetPaddingAttrib, IUPAF_SAMEASSYSTEM, "0x0", IUPAF_NOT_MAPPED);
++ iupClassRegisterAttribute(ic, "PADDING", iupTabsGetPaddingAttrib, motTabsSetPaddingAttrib, IUPAF_SAMEASSYSTEM, "0x0", IUPAF_NOT_MAPPED|IUPAF_NO_INHERIT);
+ }
+diff --git a/iup/src/mot/iupmot_text.c b/iup/src/mot/iupmot_text.c
+index 4a8f936..d9d2c74 100755
+--- a/iup/src/mot/iupmot_text.c
++++ b/iup/src/mot/iupmot_text.c
+@@ -142,8 +142,10 @@ static int motTextSetPaddingAttrib(Ihandle* ih, const char* value)
+ {
+ XtVaSetValues(ih->handle, XmNmarginHeight, ih->data->vert_padding,
+ XmNmarginWidth, ih->data->horiz_padding, NULL);
++ return 0;
+ }
+- return 0;
++ else
++ return 1; /* store until not mapped, when mapped will be set again */
+ }
+ 
+ static int motTextSetReadOnlyAttrib(Ihandle* ih, const char* value)
+@@ -164,7 +166,7 @@ static char* motTextGetReadOnlyAttrib(Ihandle* ih)
+ 
+ static int motTextSetInsertAttrib(Ihandle* ih, const char* value)
+ {
+- if (!ih->handle) /* do not store the action before map */
++ if (!ih->handle) /* do not do the action before map */
+ return 0;
+ if (!value)
+ return 0;
+@@ -207,12 +209,12 @@ static char* motTextGetSelectedTextAttrib(Ihandle* ih)
+ static int motTextSetAppendAttrib(Ihandle* ih, const char* value)
+ {
+ XmTextPosition pos;
+- if (!ih->handle) /* do not store the action before map */
++ if (!ih->handle) /* do not do the action before map */
+ return 0;
+ pos = XmTextGetLastPosition(ih->handle);
+ /* disable callbacks */
+ iupAttribSetStr(ih, "_IUPMOT_DISABLE_TEXT_CB", "1");
+- if (ih->data->is_multiline && ih->data->append_newline)
++ if (ih->data->is_multiline && ih->data->append_newline && pos!=0)
+ XmTextInsert(ih->handle, pos, "\n");
+ if (value)
+ XmTextInsert(ih->handle, pos+1, (char*)value);
+@@ -482,8 +484,12 @@ static int motTextSetNCAttrib(Ihandle* ih, const char* value)
+ if (!iupStrToInt(value, &ih->data->nc))
+ ih->data->nc = INT_MAX;
+ if (ih->handle)
++ {
+ XtVaSetValues(ih->handle, XmNmaxLength, ih->data->nc, NULL);
+- return 0;
++ return 0;
++ }
++ else
++ return 1; /* store until not mapped, when mapped will be set again */
+ }
+ 
+ static int motTextSetClipboardAttrib(Ihandle *ih, const char *value)
+@@ -911,6 +917,10 @@ static void motTextLayoutUpdateMethod(Ihandle* ih)
+ Widget spinbox = (Widget)iupAttribGet(ih, "_IUP_EXTRAPARENT");
+ if (spinbox && XmIsSpinBox(spinbox))
+ {
++ /* avoid abort in X */
++ if (ih->currentwidth == 0) ih->currentwidth = 1;
++ if (ih->currentheight == 0) ih->currentheight = 1;
++
+ XtVaSetValues(ih->handle,
+ XmNwidth, (XtArgVal)ih->currentwidth-ih->currentheight/2,
+ XmNheight, (XtArgVal)ih->currentheight,
+@@ -952,13 +962,13 @@ static int motTextMapMethod(Ihandle* ih)
+ /* Create the scrolled window */
+ /******************************/
+ 
+- iupmotSetArg(args, num_args, XmNmappedWhenManaged, False); /* not visible when managed */
+- iupmotSetArg(args, num_args, XmNscrollingPolicy, XmAPPLICATION_DEFINED);
+- iupmotSetArg(args, num_args, XmNvisualPolicy, XmVARIABLE);
+- iupmotSetArg(args, num_args, XmNscrollBarDisplayPolicy, XmSTATIC); /* can NOT be XmAS_NEEDED because XmAPPLICATION_DEFINED */
+- iupmotSetArg(args, num_args, XmNspacing, 0); /* no space between scrollbars and text */
+- iupmotSetArg(args, num_args, XmNborderWidth, 0);
+- iupmotSetArg(args, num_args, XmNshadowThickness, 0);
++ iupMOT_SETARG(args, num_args, XmNmappedWhenManaged, False); /* not visible when managed */
++ iupMOT_SETARG(args, num_args, XmNscrollingPolicy, XmAPPLICATION_DEFINED);
++ iupMOT_SETARG(args, num_args, XmNvisualPolicy, XmVARIABLE);
++ iupMOT_SETARG(args, num_args, XmNscrollBarDisplayPolicy, XmSTATIC); /* can NOT be XmAS_NEEDED because XmAPPLICATION_DEFINED */
++ iupMOT_SETARG(args, num_args, XmNspacing, 0); /* no space between scrollbars and text */
++ iupMOT_SETARG(args, num_args, XmNborderWidth, 0);
++ iupMOT_SETARG(args, num_args, XmNshadowThickness, 0);
+ 
+ sb_win = XtCreateManagedWidget(
+ child_id, /* child identifier */
+@@ -973,9 +983,9 @@ static int motTextMapMethod(Ihandle* ih)
+ child_id = "text";
+ 
+ num_args = 0;
+- iupmotSetArg(args, num_args, XmNeditMode, XmMULTI_LINE_EDIT);
++ iupMOT_SETARG(args, num_args, XmNeditMode, XmMULTI_LINE_EDIT);
+ if (wordwrap)
+- iupmotSetArg(args, num_args, XmNwordWrap, True);
++ iupMOT_SETARG(args, num_args, XmNwordWrap, True);
+ }
+ else
+ {
+@@ -986,18 +996,18 @@ static int motTextMapMethod(Ihandle* ih)
+ Widget spinbox;
+ 
+ num_args = 0;
+- iupmotSetArg(args, num_args, XmNmappedWhenManaged, False); /* not visible when managed */
+- iupmotSetArg(args, num_args, XmNspacing, 0); /* no space between spin and text */
+- iupmotSetArg(args, num_args, XmNborderWidth, 0);
+- iupmotSetArg(args, num_args, XmNshadowThickness, 0);
+- iupmotSetArg(args, num_args, XmNmarginHeight, 0);
+- iupmotSetArg(args, num_args, XmNmarginWidth, 0);
+- iupmotSetArg(args, num_args, XmNarrowSize, 8);
++ iupMOT_SETARG(args, num_args, XmNmappedWhenManaged, False); /* not visible when managed */
++ iupMOT_SETARG(args, num_args, XmNspacing, 0); /* no space between spin and text */
++ iupMOT_SETARG(args, num_args, XmNborderWidth, 0);
++ iupMOT_SETARG(args, num_args, XmNshadowThickness, 0);
++ iupMOT_SETARG(args, num_args, XmNmarginHeight, 0);
++ iupMOT_SETARG(args, num_args, XmNmarginWidth, 0);
++ iupMOT_SETARG(args, num_args, XmNarrowSize, 8);
+ 
+ if (iupStrEqualNoCase(iupAttribGetStr(ih, "SPINALIGN"), "LEFT"))
+- iupmotSetArg(args, num_args, XmNarrowLayout, XmARROWS_BEGINNING);
++ iupMOT_SETARG(args, num_args, XmNarrowLayout, XmARROWS_BEGINNING);
+ else
+- iupmotSetArg(args, num_args, XmNarrowLayout, XmARROWS_END);
++ iupMOT_SETARG(args, num_args, XmNarrowLayout, XmARROWS_END);
+ 
+ spinbox = XtCreateManagedWidget(
+ child_id, /* child identifier */
+@@ -1019,61 +1029,61 @@ static int motTextMapMethod(Ihandle* ih)
+ }
+ 
+ num_args = 0;
+- iupmotSetArg(args, num_args, XmNeditMode, XmSINGLE_LINE_EDIT);
++ iupMOT_SETARG(args, num_args, XmNeditMode, XmSINGLE_LINE_EDIT);
+ 
+ if (spin)
+ {
+ /* Spin Constraints */
+- iupmotSetArg(args, num_args, XmNspinBoxChildType, XmNUMERIC);
+- iupmotSetArg(args, num_args, XmNminimumValue, 0);
+- iupmotSetArg(args, num_args, XmNmaximumValue, 100);
+- iupmotSetArg(args, num_args, XmNposition, 0);
++ iupMOT_SETARG(args, num_args, XmNspinBoxChildType, XmNUMERIC);
++ iupMOT_SETARG(args, num_args, XmNminimumValue, 0);
++ iupMOT_SETARG(args, num_args, XmNmaximumValue, 100);
++ iupMOT_SETARG(args, num_args, XmNposition, 0);
+ 
+ if (iupAttribGetBoolean(ih, "SPINWRAP"))
+- iupmotSetArg(args, num_args, XmNwrap, TRUE);
++ iupMOT_SETARG(args, num_args, XmNwrap, TRUE);
+ else
+- iupmotSetArg(args, num_args, XmNwrap, FALSE);
++ iupMOT_SETARG(args, num_args, XmNwrap, FALSE);
+ }
+ else
+ {
+- iupmotSetArg(args, num_args, XmNmappedWhenManaged, False); /* not visible when managed */
++ iupMOT_SETARG(args, num_args, XmNmappedWhenManaged, False); /* not visible when managed */
+ }
+ }
+ 
+- iupmotSetArg(args, num_args, XmNx, 0); /* x-position */
+- iupmotSetArg(args, num_args, XmNy, 0); /* y-position */
+- iupmotSetArg(args, num_args, XmNwidth, 10); /* default width to avoid 0 */
+- iupmotSetArg(args, num_args, XmNheight, 10); /* default height to avoid 0 */
++ iupMOT_SETARG(args, num_args, XmNx, 0); /* x-position */
++ iupMOT_SETARG(args, num_args, XmNy, 0); /* y-position */
++ iupMOT_SETARG(args, num_args, XmNwidth, 10); /* default width to avoid 0 */
++ iupMOT_SETARG(args, num_args, XmNheight, 10); /* default height to avoid 0 */
+ 
+- iupmotSetArg(args, num_args, XmNmarginHeight, 0); /* default padding */
+- iupmotSetArg(args, num_args, XmNmarginWidth, 0);
++ iupMOT_SETARG(args, num_args, XmNmarginHeight, 0); /* default padding */
++ iupMOT_SETARG(args, num_args, XmNmarginWidth, 0);
+ 
+ if (iupAttribGetBoolean(ih, "CANFOCUS"))
+- iupmotSetArg(args, num_args, XmNtraversalOn, True);
++ iupMOT_SETARG(args, num_args, XmNtraversalOn, True);
+ else
+- iupmotSetArg(args, num_args, XmNtraversalOn, False);
++ iupMOT_SETARG(args, num_args, XmNtraversalOn, False);
+ 
+- iupmotSetArg(args, num_args, XmNnavigationType, XmTAB_GROUP);
+- iupmotSetArg(args, num_args, XmNhighlightThickness, 2);
+- iupmotSetArg(args, num_args, XmNverifyBell, False);
+- iupmotSetArg(args, num_args, XmNspacing, 0);
++ iupMOT_SETARG(args, num_args, XmNnavigationType, XmTAB_GROUP);
++ iupMOT_SETARG(args, num_args, XmNhighlightThickness, 2);
++ iupMOT_SETARG(args, num_args, XmNverifyBell, False);
++ iupMOT_SETARG(args, num_args, XmNspacing, 0);
+ 
+ if (iupAttribGetBoolean(ih, "BORDER"))
+- iupmotSetArg(args, num_args, XmNshadowThickness, 2);
++ iupMOT_SETARG(args, num_args, XmNshadowThickness, 2);
+ else
+- iupmotSetArg(args, num_args, XmNshadowThickness, 0);
++ iupMOT_SETARG(args, num_args, XmNshadowThickness, 0);
+ 
+ if (ih->data->is_multiline)
+ {
+ if (ih->data->sb & IUP_SB_HORIZ)
+- iupmotSetArg(args, num_args, XmNscrollHorizontal, True);
++ iupMOT_SETARG(args, num_args, XmNscrollHorizontal, True);
+ else
+- iupmotSetArg(args, num_args, XmNscrollHorizontal, False);
++ iupMOT_SETARG(args, num_args, XmNscrollHorizontal, False);
+ 
+ if (ih->data->sb & IUP_SB_VERT)
+- iupmotSetArg(args, num_args, XmNscrollVertical, True);
++ iupMOT_SETARG(args, num_args, XmNscrollVertical, True);
+ else
+- iupmotSetArg(args, num_args, XmNscrollVertical, False);
++ iupMOT_SETARG(args, num_args, XmNscrollVertical, False);
+ }
+ 
+ ih->handle = XtCreateManagedWidget(
+diff --git a/iup/src/mot/iupmot_toggle.c b/iup/src/mot/iupmot_toggle.c
+index b18f24d..1fda258 100755
+--- a/iup/src/mot/iupmot_toggle.c
++++ b/iup/src/mot/iupmot_toggle.c
+@@ -236,8 +236,10 @@ static int motToggleSetPaddingAttrib(Ihandle* ih, const char* value)
+ {
+ XtVaSetValues(ih->handle, XmNmarginHeight, ih->data->vert_padding,
+ XmNmarginWidth, ih->data->horiz_padding, NULL);
++ return 0;
+ }
+- return 0;
++ else
++ return 1; /* store until not mapped, when mapped will be set again */
+ }
+ 
+ static char* motToggleGetSelectColorAttrib(Ihandle* ih)
+@@ -336,40 +338,40 @@ static int motToggleMapMethod(Ihandle* ih)
+ if (value)
+ {
+ ih->data->type = IUP_TOGGLE_IMAGE;
+- iupmotSetArg(args, num_args, XmNlabelType, XmPIXMAP); 
++ iupMOT_SETARG(args, num_args, XmNlabelType, XmPIXMAP); 
+ }
+ else
+ {
+ ih->data->type = IUP_TOGGLE_TEXT;
+- iupmotSetArg(args, num_args, XmNlabelType, XmSTRING); 
++ iupMOT_SETARG(args, num_args, XmNlabelType, XmSTRING); 
+ }
+ 
+ /* Core */
+- iupmotSetArg(args, num_args, XmNmappedWhenManaged, False); /* not visible when managed */
+- iupmotSetArg(args, num_args, XmNx, 0); /* x-position */
+- iupmotSetArg(args, num_args, XmNy, 0); /* y-position */
+- iupmotSetArg(args, num_args, XmNwidth, 10); /* default width to avoid 0 */
+- iupmotSetArg(args, num_args, XmNheight, 10); /* default height to avoid 0 */
++ iupMOT_SETARG(args, num_args, XmNmappedWhenManaged, False); /* not visible when managed */
++ iupMOT_SETARG(args, num_args, XmNx, 0); /* x-position */
++ iupMOT_SETARG(args, num_args, XmNy, 0); /* y-position */
++ iupMOT_SETARG(args, num_args, XmNwidth, 10); /* default width to avoid 0 */
++ iupMOT_SETARG(args, num_args, XmNheight, 10); /* default height to avoid 0 */
+ /* Primitive */
+ if (iupAttribGetBoolean(ih, "CANFOCUS"))
+- iupmotSetArg(args, num_args, XmNtraversalOn, True);
++ iupMOT_SETARG(args, num_args, XmNtraversalOn, True);
+ else
+- iupmotSetArg(args, num_args, XmNtraversalOn, False);
+- iupmotSetArg(args, num_args, XmNhighlightThickness, 2);
+- iupmotSetArg(args, num_args, XmNnavigationType, XmTAB_GROUP);
++ iupMOT_SETARG(args, num_args, XmNtraversalOn, False);
++ iupMOT_SETARG(args, num_args, XmNhighlightThickness, 2);
++ iupMOT_SETARG(args, num_args, XmNnavigationType, XmTAB_GROUP);
+ /* Label */
+- iupmotSetArg(args, num_args, XmNrecomputeSize, False); /* no automatic resize from text */
+- iupmotSetArg(args, num_args, XmNmarginHeight, 0); /* default padding */
+- iupmotSetArg(args, num_args, XmNmarginWidth, 0);
+- iupmotSetArg(args, num_args, XmNmarginTop, 0); /* no extra margins */
+- iupmotSetArg(args, num_args, XmNmarginLeft, 0);
+- iupmotSetArg(args, num_args, XmNmarginBottom, 0);
+- iupmotSetArg(args, num_args, XmNmarginRight, 0);
++ iupMOT_SETARG(args, num_args, XmNrecomputeSize, False); /* no automatic resize from text */
++ iupMOT_SETARG(args, num_args, XmNmarginHeight, 0); /* default padding */
++ iupMOT_SETARG(args, num_args, XmNmarginWidth, 0);
++ iupMOT_SETARG(args, num_args, XmNmarginTop, 0); /* no extra margins */
++ iupMOT_SETARG(args, num_args, XmNmarginLeft, 0);
++ iupMOT_SETARG(args, num_args, XmNmarginBottom, 0);
++ iupMOT_SETARG(args, num_args, XmNmarginRight, 0);
+ 
+ if (radio)
+ {
+- iupmotSetArg(args, num_args, XmNtoggleMode, XmTOGGLE_BOOLEAN);
+- iupmotSetArg(args, num_args, XmNindicatorType, XmONE_OF_MANY_ROUND);
++ iupMOT_SETARG(args, num_args, XmNtoggleMode, XmTOGGLE_BOOLEAN);
++ iupMOT_SETARG(args, num_args, XmNindicatorType, XmONE_OF_MANY_ROUND);
+ 
+ if (!iupAttribGet(radio, "_IUPMOT_LASTTOGGLE"))
+ {
+@@ -380,33 +382,33 @@ static int motToggleMapMethod(Ihandle* ih)
+ else
+ {
+ if (ih->data->type == IUP_TOGGLE_TEXT && iupAttribGetBoolean(ih, "3STATE"))
+- iupmotSetArg(args, num_args, XmNtoggleMode, XmTOGGLE_INDETERMINATE);
++ iupMOT_SETARG(args, num_args, XmNtoggleMode, XmTOGGLE_INDETERMINATE);
+ else
+- iupmotSetArg(args, num_args, XmNtoggleMode, XmTOGGLE_BOOLEAN);
+- iupmotSetArg(args, num_args, XmNindicatorType, XmN_OF_MANY);
++ iupMOT_SETARG(args, num_args, XmNtoggleMode, XmTOGGLE_BOOLEAN);
++ iupMOT_SETARG(args, num_args, XmNindicatorType, XmN_OF_MANY);
+ }
+ 
+ if (ih->data->type == IUP_TOGGLE_IMAGE)
+ {
+- iupmotSetArg(args, num_args, XmNindicatorOn, XmINDICATOR_NONE);
+- iupmotSetArg(args, num_args, XmNalignment, XmALIGNMENT_CENTER);
+- iupmotSetArg(args, num_args, XmNshadowThickness, 2);
++ iupMOT_SETARG(args, num_args, XmNindicatorOn, XmINDICATOR_NONE);
++ iupMOT_SETARG(args, num_args, XmNalignment, XmALIGNMENT_CENTER);
++ iupMOT_SETARG(args, num_args, XmNshadowThickness, 2);
+ }
+ else
+ {
+- iupmotSetArg(args, num_args, XmNspacing, 3);
+- iupmotSetArg(args, num_args, XmNindicatorOn, XmINDICATOR_CHECK_BOX);
+- iupmotSetArg(args, num_args, XmNalignment, XmALIGNMENT_BEGINNING);
++ iupMOT_SETARG(args, num_args, XmNspacing, 3);
++ iupMOT_SETARG(args, num_args, XmNindicatorOn, XmINDICATOR_CHECK_BOX);
++ iupMOT_SETARG(args, num_args, XmNalignment, XmALIGNMENT_BEGINNING);
+ if (radio)
+ {
+- iupmotSetArg(args, num_args, XmNindicatorSize, 13);
+- iupmotSetArg(args, num_args, XmNselectColor, iupmotColorGetPixel(0, 0, 0));
++ iupMOT_SETARG(args, num_args, XmNindicatorSize, 13);
++ iupMOT_SETARG(args, num_args, XmNselectColor, iupmotColorGetPixel(0, 0, 0));
+ }
+ else
+- iupmotSetArg(args, num_args, XmNindicatorSize, 15);
++ iupMOT_SETARG(args, num_args, XmNindicatorSize, 15);
+ 
+- iupmotSetArg(args, num_args, XmNshadowThickness, 0);
+- iupmotSetArg(args, num_args, XmNdetailShadowThickness, 2);
++ iupMOT_SETARG(args, num_args, XmNshadowThickness, 0);
++ iupMOT_SETARG(args, num_args, XmNdetailShadowThickness, 2);
+ }
+ 
+ ih->handle = XtCreateManagedWidget(
+diff --git a/iup/src/mot/iupmot_tree.c b/iup/src/mot/iupmot_tree.c
+index eb230af..fa5ef09 100755
+--- a/iup/src/mot/iupmot_tree.c
++++ b/iup/src/mot/iupmot_tree.c
+@@ -46,48 +46,20 @@ typedef struct _motTreeItemData
+ Pixmap image, image_mask;
+ Pixmap image_expanded, image_expanded_mask;
+ unsigned char kind;
+- void* userdata;
+ } motTreeItemData;
+ 
+ 
+ static void motTreeShowEditField(Ihandle* ih, Widget wItem);
+-static int motTreeGetNodeId(Ihandle* ih, Widget wItem);
++static void motTreeRemoveNode(Ihandle* ih, Widget wItem, int del_data, int call_cb);
+ 
+-typedef int (*motTreeNodeFunc)(Ihandle* ih, Widget wItem, void* userdata);
+-
+-static int motTreeForEach(Ihandle* ih, Widget wItem, motTreeNodeFunc func, void* userdata)
+-{
+- WidgetList wItemChildList = NULL;
+- int i, numChild;
+-
+- if (!wItem)
+- wItem = (Widget)iupAttribGet(ih, "_IUPTREE_ROOTITEM");
+-
+- if (!func(ih, wItem, userdata))
+- return 0;
+-
+- numChild = XmContainerGetItemChildren(ih->handle, wItem, &wItemChildList);
+- for (i=0; i<numChild; i++)
+- {
+- /* Recursively traverse child items */
+- if (!motTreeForEach(ih, wItemChildList[i], func, userdata))
+- {
+- XtFree((char*)wItemChildList);
+- return 0;
+- }
+- }
+- if (wItemChildList) XtFree((char*)wItemChildList);
+-
+- return 1;
+-}
+ 
+ /*****************************************************************************/
+ /* COPYING ITEMS (Branches and its children) */
+ /*****************************************************************************/
+ /* Insert the copied item in a new location. Returns the new item. */
+-static Widget motTreeCopyItem(Ihandle* ih, Widget wItem, Widget wParent, int pos, int full_copy)
++static Widget motTreeCopyItem(Ihandle* ih, Widget wItem, Widget wParent, int pos, int is_copy)
+ {
+- Widget wNewItem;
++ Widget wItemNew;
+ XmString title;
+ motTreeItemData *itemData;
+ Pixel fgcolor, bgcolor;
+@@ -96,13 +68,13 @@ static Widget motTreeCopyItem(Ihandle* ih, Widget wItem, Widget wParent, int pos
+ Pixmap image = XmUNSPECIFIED_PIXMAP, mask = XmUNSPECIFIED_PIXMAP;
+ unsigned char state;
+ 
+- iupmotSetArg(args, num_args, XmNentryParent, wParent);
+- iupmotSetArg(args, num_args, XmNmarginHeight, ih->data->spacing);
+- iupmotSetArg(args, num_args, XmNmarginWidth, 0);
+- iupmotSetArg(args, num_args, XmNviewType, XmSMALL_ICON);
+- iupmotSetArg(args, num_args, XmNnavigationType, XmTAB_GROUP);
+- iupmotSetArg(args, num_args, XmNtraversalOn, True);
+- iupmotSetArg(args, num_args, XmNshadowThickness, 0);
++ iupMOT_SETARG(args, num_args, XmNentryParent, wParent);
++ iupMOT_SETARG(args, num_args, XmNmarginHeight, ih->data->spacing);
++ iupMOT_SETARG(args, num_args, XmNmarginWidth, 0);
++ iupMOT_SETARG(args, num_args, XmNviewType, XmSMALL_ICON);
++ iupMOT_SETARG(args, num_args, XmNnavigationType, XmTAB_GROUP);
++ iupMOT_SETARG(args, num_args, XmNtraversalOn, True);
++ iupMOT_SETARG(args, num_args, XmNshadowThickness, 0);
+ 
+ /* Get values to copy */
+ XtVaGetValues(wItem, XmNlabelString, &title,
+@@ -113,49 +85,73 @@ static Widget motTreeCopyItem(Ihandle* ih, Widget wItem, Widget wParent, int pos
+ XmNoutlineState, &state,
+ NULL);
+ 
+- if (full_copy) /* during a full copy the userdata reference is not copied */
++ if (is_copy) /* during a copy the itemdata reference is not reused */
+ {
+ /* create a new one */
+ motTreeItemData* itemDataNew = malloc(sizeof(motTreeItemData));
+ memcpy(itemDataNew, itemData, sizeof(motTreeItemData));
+- itemDataNew->userdata = NULL;
+ itemData = itemDataNew;
+ }
+ 
+- iupmotSetArg(args, num_args, XmNlabelString, title);
+- iupmotSetArg(args, num_args, XmNuserData, itemData);
+- iupmotSetArg(args, num_args, XmNforeground, fgcolor);
+- iupmotSetArg(args, num_args, XmNsmallIconPixmap, image);
+- iupmotSetArg(args, num_args, XmNsmallIconMask, mask);
+- iupmotSetArg(args, num_args, XmNoutlineState, state);
++ iupMOT_SETARG(args, num_args, XmNlabelString, title);
++ iupMOT_SETARG(args, num_args, XmNuserData, itemData);
++ iupMOT_SETARG(args, num_args, XmNforeground, fgcolor);
++ iupMOT_SETARG(args, num_args, XmNsmallIconPixmap, image);
++ iupMOT_SETARG(args, num_args, XmNsmallIconMask, mask);
++ iupMOT_SETARG(args, num_args, XmNoutlineState, state);
+ 
+- iupmotSetArg(args, num_args, XmNentryParent, wParent);
+- iupmotSetArg(args, num_args, XmNpositionIndex, pos);
++ iupMOT_SETARG(args, num_args, XmNentryParent, wParent);
++ iupMOT_SETARG(args, num_args, XmNpositionIndex, pos);
+ 
+ XtVaGetValues(ih->handle, XmNbackground, &bgcolor, NULL);
+- iupmotSetArg(args, num_args, XmNbackground, bgcolor);
++ iupMOT_SETARG(args, num_args, XmNbackground, bgcolor);
++
++ /* Add the new node */
++ wItemNew = XtCreateManagedWidget("icon", xmIconGadgetClass, ih->handle, args, num_args);
++ ih->data->node_count++;
++
++ XtRealizeWidget(wItemNew);
++
++ return wItemNew;
++}
++
++static void motTreeChildRebuildCacheRec(Ihandle* ih, Widget wItem, int *id)
++{
++ WidgetList itemChildList = NULL;
++ int i, numChild;
+ 
+- wNewItem = XtCreateManagedWidget("icon", xmIconGadgetClass, ih->handle, args, num_args);
++ /* Check whether we have child items */
++ numChild = XmContainerGetItemChildren(ih->handle, wItem, &itemChildList);
++
++ for (i = 0; i < numChild; i++)
++ {
++ (*id)++;
++ ih->data->node_cache[*id].node_handle = itemChildList[i];
+ 
+- /* Root always expanded */
+- XtVaSetValues((Widget)iupAttribGet(ih, "_IUPTREE_ROOTITEM"), XmNoutlineState, XmEXPANDED, NULL);
++ /* go recursive to children */
++ motTreeChildRebuildCacheRec(ih, itemChildList[i], id);
++ }
+ 
+- XtRealizeWidget(wNewItem);
++ if (itemChildList) XtFree((char*)itemChildList);
++}
+ 
+- return wNewItem;
++static void motTreeRebuildNodeCache(Ihandle* ih, int id, Widget wItem)
++{
++ ih->data->node_cache[id].node_handle = wItem;
++ motTreeChildRebuildCacheRec(ih, wItem, &id);
+ }
+ 
+-static void motTreeCopyChildren(Ihandle* ih, Widget wItemSrc, Widget wItemDst, int full_copy)
++static void motTreeCopyChildren(Ihandle* ih, Widget wItemSrc, Widget wItemDst, int is_copy)
+ {
+ WidgetList wItemChildList = NULL;
+ int i = 0;
+ int numChild = XmContainerGetItemChildren(ih->handle, wItemSrc, &wItemChildList);
+ while(i != numChild)
+ {
+- Widget wNewItem = motTreeCopyItem(ih, wItemChildList[i], wItemDst, i, full_copy); /* Use the same order they where enumerated */
++ Widget wItemNew = motTreeCopyItem(ih, wItemChildList[i], wItemDst, i, is_copy); /* Use the same order they where enumerated */
+ 
+ /* Recursively transfer all the items */
+- motTreeCopyChildren(ih, wItemChildList[i], wNewItem, full_copy); 
++ motTreeCopyChildren(ih, wItemChildList[i], wItemNew, is_copy); 
+ 
+ /* Go to next sibling item */
+ i++;
+@@ -165,12 +161,18 @@ static void motTreeCopyChildren(Ihandle* ih, Widget wItemSrc, Widget wItemDst, i
+ }
+ 
+ /* Copies all items in a branch to a new location. Returns the new branch node. */
+-static Widget motTreeCopyNode(Ihandle* ih, Widget wItemSrc, Widget wItemDst, int full_copy)
++static Widget motTreeCopyMoveNode(Ihandle* ih, Widget wItemSrc, Widget wItemDst, int is_copy)
+ {
+- Widget wNewItem, wParent;
++ Widget wItemNew, wParent;
+ motTreeItemData *itemDataDst;
+ unsigned char stateDst;
+- int pos;
++ int pos, id_new, count, id_src, id_dst;
++
++ int old_count = ih->data->node_count;
++
++ id_src = iupTreeFindNodeId(ih, wItemSrc);
++ id_dst = iupTreeFindNodeId(ih, wItemDst);
++ id_new = id_dst+1; /* contains the position for a copy operation */
+ 
+ XtVaGetValues(wItemDst, XmNoutlineState, &stateDst, 
+ XmNuserData, &itemDataDst, 
+@@ -184,17 +186,46 @@ static Widget motTreeCopyNode(Ihandle* ih, Widget wItemSrc, Widget wItemDst, int
+ }
+ else
+ {
++ if (itemDataDst->kind == ITREE_BRANCH)
++ {
++ int child_count = iupdrvTreeTotalChildCount(ih, wItemDst);
++ id_new += child_count;
++ }
++
+ /* copy as next brother of item or collapsed branch */
+ XtVaGetValues(wItemDst, XmNentryParent, &wParent, NULL);
+ XtVaGetValues(wItemDst, XmNpositionIndex, &pos, NULL);
+ pos++;
+ }
+ 
+- wNewItem = motTreeCopyItem(ih, wItemSrc, wParent, pos, full_copy);
++ /* move to the same place does nothing */
++ if (!is_copy && id_new == id_src)
++ return NULL;
++
++ wItemNew = motTreeCopyItem(ih, wItemSrc, wParent, pos, is_copy);
++
++ motTreeCopyChildren(ih, wItemSrc, wItemNew, is_copy);
++
++ count = ih->data->node_count - old_count;
++ iupTreeCopyMoveCache(ih, id_src, id_new, count, is_copy);
+ 
+- motTreeCopyChildren(ih, wItemSrc, wNewItem, full_copy);
++ if (!is_copy)
++ {
++ /* Deleting the node (and its children) from the old position */
++ /* do not delete the itemdata, we reuse the references in CopyNode */
++ motTreeRemoveNode(ih, wItemSrc, 0, 0);
++
++ /* restore count, because we remove src */
++ ih->data->node_count = old_count;
++
++ /* compensate position for a move */
++ if (id_new > id_src)
++ id_new -= count;
++ }
+ 
+- return wNewItem;
++ motTreeRebuildNodeCache(ih, id_new, wItemNew);
++
++ return wItemNew;
+ }
+ 
+ static void motTreeContainerDeselectAll(Ihandle *ih)
+@@ -233,229 +264,181 @@ static void motTreeContainerSelectAll(Ihandle *ih)
+ XtCallActionProc(ih->handle, "ContainerSelectAll", (XEvent*)&ev, 0, 0);
+ }
+ 
+-static Widget motTreeGetLastVisibleNode(Ihandle* ih, Widget wItem)
++static int motTreeIsNodeVisible(Widget wItem, Widget *wLastItemParent)
+ {
+- unsigned char itemState;
+-
+- XtVaGetValues(wItem, XmNoutlineState, &itemState, NULL);
+-
+- if (itemState == XmEXPANDED)
++ unsigned char itemParentState;
++ Widget wItemParent = NULL;
++ XtVaGetValues(wItem, XmNentryParent, &wItemParent, NULL);
++ if (!wItemParent || wItemParent == *wLastItemParent)
++ return 1;
++ while(wItemParent)
+ {
+- WidgetList wChildrenTree = NULL;
+- int numChildren = XmContainerGetItemChildren(ih->handle, wItem, &wChildrenTree);
+- if(numChildren)
+- wItem = motTreeGetLastVisibleNode(ih, wChildrenTree[numChildren - 1]);
+- if (wChildrenTree) XtFree((char*)wChildrenTree);
++ XtVaGetValues(wItemParent, XmNoutlineState, &itemParentState, NULL);
++ if (itemParentState != XmEXPANDED)
++ return 0;
++
++ XtVaGetValues(wItemParent, XmNentryParent, &wItemParent, NULL);
+ }
+ 
+- return wItem;
++ /* save last parent */
++ XtVaGetValues(wItem, XmNentryParent, &wItemParent, NULL);
++ *wLastItemParent = wItemParent;
++ return 1;
+ }
+ 
+-static Widget motTreeFindVisibleNodeId(Ihandle* ih, WidgetList itemList, int numItems, Widget itemNode)
++static Widget motTreeGetLastVisibleNode(Ihandle* ih)
+ {
+- Widget itemChild;
+- WidgetList itemChildList;
+- int i = 0;
+- int numChild;
+- unsigned char itemState;
++ int i;
++ Widget wLastItemParent = NULL;
+ 
+- while(i != numItems)
++ for (i = ih->data->node_count-1; i >= 0; i--)
+ {
+- /* ID control to traverse items */
+- ih->data->id_control++; /* not the real id since it counts only the visible ones */
+-
+- /* StateID founded! */
+- if(itemList[i] == itemNode)
+- return itemList[i];
+-
+- /* Check whether we have child items */
+- itemChildList = NULL;
+- numChild = XmContainerGetItemChildren(ih->handle, itemList[i], &itemChildList);
+- XtVaGetValues(itemList[i], XmNoutlineState, &itemState, NULL);
+-
+- /* The itemWidget has child and it is expanded (visible) */
+- if (numChild && itemState == XmEXPANDED)
+- {
+- /* pass the list of children of this item */
+- itemChild = motTreeFindVisibleNodeId(ih, itemChildList, numChild, itemNode);
+-
+- /* StateID founded! */
+- if(itemChild)
+- {
+- XtFree((char*)itemChildList);
+- return itemChild;
+- }
+- }
+-
+- if (itemChildList) XtFree((char*)itemChildList);
+- /* Go to next sibling item */
+- i++;
++ if (motTreeIsNodeVisible(ih->data->node_cache[i].node_handle, &wLastItemParent))
++ return ih->data->node_cache[i].node_handle;
+ }
+ 
+- return NULL;
++ return ih->data->node_cache[0].node_handle; /* root is always visible */
+ }
+ 
+-static Widget motTreeFindVisibleNodeFromId(Ihandle* ih, WidgetList itemList, int numItems)
++static Widget motTreeGetNextVisibleNode(Ihandle* ih, Widget wItem, int count)
+ {
+- Widget itemChild;
+- WidgetList itemChildList;
+- int i = 0;
+- int numChild;
+- unsigned char itemState;
++ int i, id;
++ Widget wLastItemParent = NULL;
+ 
+- while(i != numItems)
+- {
+- /* ID control to traverse items */
+- ih->data->id_control--; /* not the real id since it counts only the visible ones */
++ id = iupTreeFindNodeId(ih, wItem);
++ id += count;
+ 
+- /* StateID founded! */
+- if(ih->data->id_control < 0)
+- return itemList[i];
++ for (i = id; i < ih->data->node_count; i++)
++ {
++ if (motTreeIsNodeVisible(ih->data->node_cache[i].node_handle, &wLastItemParent))
++ return ih->data->node_cache[i].node_handle;
++ }
+ 
+- /* Check whether we have child items */
+- itemChildList = NULL;
+- numChild = XmContainerGetItemChildren(ih->handle, itemList[i], &itemChildList);
+- XtVaGetValues(itemList[i], XmNoutlineState, &itemState, NULL);
++ return ih->data->node_cache[0].node_handle; /* root is always visible */
++}
+ 
+- /* The itemWidget has child and it is expanded (visible) */
+- if (numChild && itemState == XmEXPANDED)
+- {
+- /* pass the list of children of this item */
+- itemChild = motTreeFindVisibleNodeFromId(ih, itemChildList, numChild);
++static Widget motTreeGetPreviousVisibleNode(Ihandle* ih, Widget wItem, int count)
++{
++ int i, id;
++ Widget wLastItemParent = NULL;
+ 
+- /* StateID founded! */
+- if(ih->data->id_control < 0)
+- {
+- if (itemChildList) XtFree((char*)itemChildList);
+- return itemChild;
+- }
+- }
++ id = iupTreeFindNodeId(ih, wItem);
++ id -= count;
+ 
+- if (itemChildList) XtFree((char*)itemChildList);
+- /* Go to next sibling item */
+- i++;
++ for (i = id; i >= 0; i--)
++ {
++ if (motTreeIsNodeVisible(ih->data->node_cache[i].node_handle, &wLastItemParent))
++ return ih->data->node_cache[i].node_handle;
+ }
+ 
+- return NULL;
++ return motTreeGetLastVisibleNode(ih);
+ }
+ 
+-static Widget motTreeGetNextVisibleNode(Ihandle* ih, Widget wRoot, Widget wItem)
++static void motTreeChildCountRec(Ihandle* ih, Widget wItem, int *count)
+ {
+- Widget wNext;
++ WidgetList itemChildList = NULL;
++ int i, numChild;
+ 
+- ih->data->id_control = -1;
+- motTreeFindVisibleNodeId(ih, &wRoot, 1, wItem);
+- ih->data->id_control++; /* more 1 visible node */
++ /* Check whether we have child items */
++ numChild = XmContainerGetItemChildren(ih->handle, wItem, &itemChildList);
+ 
+- wNext = motTreeFindVisibleNodeFromId(ih, &wRoot, 1);
++ for (i = 0; i < numChild; i++)
++ {
++ (*count)++;
+ 
+- if (ih->data->id_control >= 0)
+- wNext = motTreeGetLastVisibleNode(ih, wRoot);
++ /* go recursive to children */
++ motTreeChildCountRec(ih, itemChildList[i], count);
++ }
+ 
+- return wNext;
++ if (itemChildList) XtFree((char*)itemChildList);
+ }
+ 
+-static Widget motTreeGetPreviousVisibleNode(Ihandle* ih, Widget wRoot, Widget wItem)
++int iupdrvTreeTotalChildCount(Ihandle* ih, Widget wItem)
+ {
+- ih->data->id_control = -1;
+- motTreeFindVisibleNodeId(ih, &wRoot, 1, wItem);
+- ih->data->id_control--; /* less 1 visible node */
+-
+- if (ih->data->id_control < 0)
+- ih->data->id_control = 0; /* Begin of tree = Root id */
+-
+- return motTreeFindVisibleNodeFromId(ih, &wRoot, 1);
++ int count = 0;
++ motTreeChildCountRec(ih, wItem, &count);
++ return count;
+ }
+ 
+-static void motTreeUpdateBgColor(Ihandle* ih, WidgetList itemList, int numItems, Pixel bgcolor)
++static void motTreeUpdateBgColor(Ihandle* ih, Pixel bgcolor)
+ {
+- WidgetList itemChildList;
+- int i = 0;
+- int numChild;
+-
+- while(i != numItems)
++ int i;
++ for (i = 0; i < ih->data->node_count; i++)
+ {
+- XtVaSetValues(itemList[i], XmNbackground, bgcolor, NULL);
+-
+- /* Check whether we have child items */
+- itemChildList = NULL;
+- numChild = XmContainerGetItemChildren(ih->handle, itemList[i], &itemChildList);
+- if(numChild)
+- motTreeUpdateBgColor(ih, itemChildList, numChild, bgcolor);
+- if (itemChildList) XtFree((char*)itemChildList);
+-
+- /* Go to next sibling item */
+- i++;
++ XtVaSetValues(ih->data->node_cache[i].node_handle, XmNbackground, bgcolor, NULL);
+ }
+ }
+ 
+-static void motTreeUpdateImages(Ihandle* ih, WidgetList itemList, int numItems, int mode)
++static void motTreeUpdateImages(Ihandle* ih, int mode)
+ {
+- motTreeItemData *itemData;
+- int i = 0;
+-
++ int i;
+ /* called when one of the default images is changed */
+-
+- while(i != numItems)
++ for (i = 0; i < ih->data->node_count; i++)
+ {
+- /* Get node attributes */
+- XtVaGetValues(itemList[i], XmNuserData, &itemData, NULL);
+- 
++ motTreeItemData *itemData;
++ Widget wItem = ih->data->node_cache[i].node_handle;
++
++ XtVaGetValues(wItem, XmNuserData, &itemData, NULL);
++
+ if (itemData->kind == ITREE_BRANCH)
+ {
+ unsigned char itemState;
+- XtVaGetValues(itemList[i], XmNoutlineState, &itemState, NULL);
++ XtVaGetValues(wItem, XmNoutlineState, &itemState, NULL);
+ 
+ if (itemState == XmEXPANDED)
+ {
+ if (mode == ITREE_UPDATEIMAGE_EXPANDED)
+ {
+- XtVaSetValues(itemList[i], XmNsmallIconPixmap, (itemData->image_expanded!=XmUNSPECIFIED_PIXMAP)? itemData->image_expanded: (Pixmap)ih->data->def_image_expanded, NULL);
+- XtVaSetValues(itemList[i], XmNsmallIconMask, (itemData->image_expanded_mask!=XmUNSPECIFIED_PIXMAP)? itemData->image_expanded_mask: (Pixmap)ih->data->def_image_expanded_mask, NULL);
++ XtVaSetValues(wItem, XmNsmallIconPixmap, (itemData->image_expanded!=XmUNSPECIFIED_PIXMAP)? itemData->image_expanded: (Pixmap)ih->data->def_image_expanded, NULL);
++ XtVaSetValues(wItem, XmNsmallIconMask, (itemData->image_expanded_mask!=XmUNSPECIFIED_PIXMAP)? itemData->image_expanded_mask: (Pixmap)ih->data->def_image_expanded_mask, NULL);
+ }
+ }
+ else 
+ {
+ if (mode == ITREE_UPDATEIMAGE_COLLAPSED)
+ {
+- XtVaSetValues(itemList[i], XmNsmallIconPixmap, (itemData->image!=XmUNSPECIFIED_PIXMAP)? itemData->image: (Pixmap)ih->data->def_image_collapsed, NULL);
+- XtVaSetValues(itemList[i], XmNsmallIconMask, (itemData->image_mask!=XmUNSPECIFIED_PIXMAP)? itemData->image_mask: (Pixmap)ih->data->def_image_collapsed_mask, NULL);
++ XtVaSetValues(wItem, XmNsmallIconPixmap, (itemData->image!=XmUNSPECIFIED_PIXMAP)? itemData->image: (Pixmap)ih->data->def_image_collapsed, NULL);
++ XtVaSetValues(wItem, XmNsmallIconMask, (itemData->image_mask!=XmUNSPECIFIED_PIXMAP)? itemData->image_mask: (Pixmap)ih->data->def_image_collapsed_mask, NULL);
+ }
+ }
+-
+- /* Recursively traverse child items */
+- {
+- WidgetList itemChildList;
+- int numChild;
+- itemChildList = NULL;
+- numChild = XmContainerGetItemChildren(ih->handle, itemList[i], &itemChildList);
+- motTreeUpdateImages(ih, itemChildList, numChild, mode);
+- if (itemChildList) XtFree((char*)itemChildList);
+- }
+ }
+ else 
+ {
+ if (mode == ITREE_UPDATEIMAGE_LEAF)
+ {
+- XtVaSetValues(itemList[i], XmNsmallIconPixmap, (itemData->image!=XmUNSPECIFIED_PIXMAP)? itemData->image: (Pixmap)ih->data->def_image_leaf, NULL);
+- XtVaSetValues(itemList[i], XmNsmallIconMask, (itemData->image_mask!=XmUNSPECIFIED_PIXMAP)? itemData->image_mask: (Pixmap)ih->data->def_image_leaf_mask, NULL);
++ XtVaSetValues(wItem, XmNsmallIconPixmap, (itemData->image!=XmUNSPECIFIED_PIXMAP)? itemData->image: (Pixmap)ih->data->def_image_leaf, NULL);
++ XtVaSetValues(wItem, XmNsmallIconMask, (itemData->image_mask!=XmUNSPECIFIED_PIXMAP)? itemData->image_mask: (Pixmap)ih->data->def_image_leaf_mask, NULL);
+ }
+ }
+-
+- /* Go to next sibling node */
+- i++;
+ }
+ }
+ 
+-static int motTreeSelectFunc(Ihandle* ih, Widget wItem, int *select)
++static int motTreeIsNodeSelected(Widget wItem)
++{
++ unsigned char isSelected;
++ XtVaGetValues(wItem, XmNvisualEmphasis, &isSelected, NULL);
++ if(isSelected == XmSELECTED)
++ return 1;
++ else
++ return 0;
++}
++
++static void motTreeSelectNode(Widget wItem, int select)
++{
++ if (select == -1)
++ select = !motTreeIsNodeSelected(wItem); /* toggle */
++
++ if (select)
++ XtVaSetValues(wItem, XmNvisualEmphasis, XmSELECTED, NULL);
++ else
++ XtVaSetValues(wItem, XmNvisualEmphasis, XmNOT_SELECTED, NULL);
++}
++
++static int motTreeSelectFunc(Ihandle* ih, Widget wItem, int id, int *select)
+ {
+ int do_select = *select;
+ if (do_select == -1)
+- {
+- unsigned char isSelected;
+- XtVaGetValues(wItem, XmNvisualEmphasis, &isSelected, NULL);
+- do_select = (isSelected == XmSELECTED)? 0: 1; /* toggle */
+- }
++ do_select = !motTreeIsNodeSelected(wItem); /* toggle */
+ 
+ if (do_select)
+ XtVaSetValues(wItem, XmNvisualEmphasis, XmSELECTED, NULL);
+@@ -463,272 +446,111 @@ static int motTreeSelectFunc(Ihandle* ih, Widget wItem, int *select)
+ XtVaSetValues(wItem, XmNvisualEmphasis, XmNOT_SELECTED, NULL);
+ 
+ (void)ih;
++ (void)id;
+ return 1;
+ }
+ 
+ static void motTreeInvertAllNodeMarking(Ihandle* ih)
+ {
+ int select = -1;
+- motTreeForEach(ih, NULL, (motTreeNodeFunc)motTreeSelectFunc, &select);
++ iupTreeForEach(ih, (iupTreeNodeFunc)motTreeSelectFunc, &select);
+ }
+ 
+-typedef struct _motTreeRange{
+- Widget wItem1, wItem2;
+- char inside, clear;
+-}motTreeRange;
+-
+-static int motTreeSelectRangeFunc(Ihandle* ih, Widget wItem, motTreeRange* range)
++static void motTreeSelectRange(Ihandle* ih, Widget wItem1, Widget wItem2, int clear)
+ {
+- int end_range = 0;
+-
+- if (range->inside == 0) /* detect the range start */
+- {
+- if (range->wItem1 == wItem) range->inside=1;
+- else if (range->wItem2 == wItem) range->inside=1;
+- }
+- else if (range->inside == 1) /* detect the range end */
++ int i;
++ int id1 = iupTreeFindNodeId(ih, wItem1);
++ int id2 = iupTreeFindNodeId(ih, wItem2);
++ if (id1 > id2)
+ {
+- if (range->wItem1 == wItem) end_range=1;
+- else if (range->wItem2 == wItem) end_range=1;
++ int tmp = id1;
++ id1 = id2;
++ id2 = tmp;
+ }
+ 
+- if (range->inside == 1) /* if inside, select */
+- XtVaSetValues(wItem, XmNvisualEmphasis, XmSELECTED, NULL);
+- else if (range->clear) /* if outside and clear, unselect */
+- XtVaSetValues(wItem, XmNvisualEmphasis, XmNOT_SELECTED, NULL);
+-
+- if (end_range || (range->inside && range->wItem1==range->wItem2))
+- range->inside=-1; /* update after selecting the node */
+-
+- (void)ih;
+- return 1;
+-}
+-
+-static void motTreeSelectRange(Ihandle* ih, Widget wItem1, Widget wItem2, int clear)
+-{
+- motTreeRange range;
+- range.wItem1 = wItem1;
+- range.wItem2 = wItem2;
+- range.inside = 0;
+- range.clear = (char)clear;
+- motTreeForEach(ih, NULL, (motTreeNodeFunc)motTreeSelectRangeFunc, &range);
+-}
+-
+-void motTreeExpandCollapseAllNodes(Ihandle* ih, WidgetList itemList, int numItems, unsigned char itemState)
+-{
+- WidgetList itemChildList;
+- int numChild;
+- int i = 0;
+-
+- while(i != numItems)
++ for (i = 0; i < ih->data->node_count; i++)
+ {
+- /* Check whether we have child items */
+- itemChildList = NULL;
+- numChild = XmContainerGetItemChildren(ih->handle, itemList[i], &itemChildList);
+-
+- if(numChild)
++ if (i < id1 || i > id2)
+ {
+- XtVaSetValues(itemList[i], XmNoutlineState, itemState, NULL);
+- motTreeExpandCollapseAllNodes(ih, itemChildList, numChild, itemState);
++ if (clear)
++ XtVaSetValues(ih->data->node_cache[i].node_handle, XmNvisualEmphasis, XmNOT_SELECTED, NULL);
+ }
+-
+- if (itemChildList) XtFree((char*)itemChildList);
+- /* Go to next sibling item */
+- i++;
++ else
++ XtVaSetValues(ih->data->node_cache[i].node_handle, XmNvisualEmphasis, XmSELECTED, NULL);
+ }
+ }
+ 
+-static void motTreeDestroyItemData(Ihandle* ih, Widget wItem)
++void motTreeExpandCollapseAllNodes(Ihandle* ih, unsigned char itemState)
+ {
+- motTreeItemData *itemData = NULL;
+- XtVaGetValues(wItem, XmNuserData, &itemData, NULL);
+- if (itemData)
++ int i;
++ /* called when one of the default images is changed */
++ for (i = 0; i < ih->data->node_count; i++)
+ {
+- IFnis cb = (IFnis)IupGetCallback(ih, "NODEREMOVED_CB");
+- if (cb) cb(ih, motTreeGetNodeId(ih, wItem), (char*)itemData->userdata);
+- free(itemData);
+- XtVaSetValues(wItem, XmNuserData, NULL, NULL);
+- }
+-}
+-
+-static void motTreeRemoveChildren(Ihandle* ih, WidgetList itemList, int numItems, int del_userdata)
+-{
+- WidgetList itemChildList;
+- int numChild;
+- int i = 0;
++ motTreeItemData *itemData;
++ Widget wItem = ih->data->node_cache[i].node_handle;
+ 
+- while(i != numItems)
+- { 
++ XtVaGetValues(wItem, XmNuserData, &itemData, NULL);
++ 
+ /* Check whether we have child items */
+- itemChildList = NULL;
+- numChild = XmContainerGetItemChildren(ih->handle, itemList[i], &itemChildList);
+- if (numChild)
+- motTreeRemoveChildren(ih, itemChildList, numChild, del_userdata);
+-
+- if (del_userdata)
+- motTreeDestroyItemData(ih, itemList[i]);
+-
+- XtDestroyWidget(itemList[i]);
+-
+- if (itemChildList) XtFree((char*)itemChildList);
+- /* Go to next sibling item */
+- i++;
++ if (itemData->kind == ITREE_BRANCH)
++ XtVaSetValues(wItem, XmNoutlineState, itemState, NULL);
+ }
+ }
+ 
+-static void motTreeRemoveNode(Ihandle* ih, Widget wItem, int del_userdata)
++static void motTreeDestroyItemData(Ihandle* ih, Widget wItem, int del_data, IFns cb, int id)
+ {
+- WidgetList wChildList = NULL;
+- int numChild = XmContainerGetItemChildren(ih->handle, wItem, &wChildList);
+- if (numChild)
+- motTreeRemoveChildren(ih, wChildList, numChild, del_userdata);
+- if (del_userdata)
+- motTreeDestroyItemData(ih, wItem);
+- XtDestroyWidget(wItem);
+- if (wChildList) XtFree((char*)wChildList);
+-}
+-
+-static Widget motTreeFindNodeID(Ihandle* ih, WidgetList itemList, int numItems, Widget itemNode)
+-{
+- Widget itemChild;
+- WidgetList itemChildList;
+- int i = 0;
+- int numChild;
+-
+- while(i != numItems)
++ motTreeItemData *itemData = NULL;
++ XtVaGetValues(wItem, XmNuserData, &itemData, NULL);
++ if (itemData)
+ {
+- /* ID control to traverse items */
+- ih->data->id_control++;
++ if (cb) 
++ cb(ih, (char*)ih->data->node_cache[id].userdata);
+ 
+- /* StateID founded! */
+- if(itemList[i] == itemNode)
+- return itemList[i];
+-
+- /* Check whether we have child items */
+- itemChildList = NULL;
+- numChild = XmContainerGetItemChildren(ih->handle, itemList[i], &itemChildList);
+- if(numChild)
++ if (del_data)
+ {
+- /* pass the list of children of this item */
+- itemChild = motTreeFindNodeID(ih, itemChildList, numChild, itemNode);
+-
+- /* StateID founded! */
+- if(itemChild)
+- {
+- if (itemChildList) XtFree((char*)itemChildList);
+- return itemChild;
+- }
++ free(itemData);
++ XtVaSetValues(wItem, XmNuserData, NULL, NULL);
+ }
+-
+- if (itemChildList) XtFree((char*)itemChildList);
+- /* Go to next sibling item */
+- i++;
+ }
+-
+- return NULL;
+ }
+ 
+-static Widget motTreeFindNodeFromID(Ihandle* ih, WidgetList itemList, int numItems)
++static void motTreeRemoveNodeRec(Ihandle* ih, Widget wItem, int del_data, IFns cb, int *id)
+ {
+- Widget itemChild;
+- WidgetList itemChildList;
+- int i = 0;
+- int numChild;
++ WidgetList itemChildList = NULL;
++ int i, numChild;
++ int old_id = *id;
+ 
+- while(i != numItems)
++ /* Check whether we have child items */
++ /* remove from children first */
++ numChild = XmContainerGetItemChildren(ih->handle, wItem, &itemChildList);
++ for (i = 0; i < numChild; i++)
+ {
+- /* ID control to traverse items */
+- ih->data->id_control--;
+-
+- /* StateID founded! */
+- if(ih->data->id_control < 0)
+- return itemList[i];
+-
+- /* Check whether we have child items */
+- itemChildList = NULL;
+- numChild = XmContainerGetItemChildren(ih->handle, itemList[i], &itemChildList);
+- if(numChild)
+- {
+- /* pass the list of children of this item */
+- itemChild = motTreeFindNodeFromID(ih, itemChildList, numChild);
+-
+- /* StateID founded! */
+- if(ih->data->id_control < 0)
+- {
+- if (itemChildList) XtFree((char*)itemChildList);
+- return itemChild;
+- }
+- }
+-
+- if (itemChildList) XtFree((char*)itemChildList);
+- /* Go to next sibling item */
+- i++;
++ /* go recursive to children */
++ motTreeRemoveNodeRec(ih, itemChildList[i], del_data, cb, id);
+ }
++ if (itemChildList) XtFree((char*)itemChildList);
+ 
+- return NULL;
+-}
++ /* actually do it for the node */
++ ih->data->node_count--;
++ (*id)++;
+ 
+-static int motTreeGetNodeId(Ihandle* ih, Widget wItem)
+-{
+- Widget wRoot = (Widget)iupAttribGet(ih, "_IUPTREE_ROOTITEM");
+- ih->data->id_control = -1;
+- if (motTreeFindNodeID(ih, &wRoot, 1, wItem))
+- return ih->data->id_control;
+- else
+- return -1;
++ if (del_data || cb)
++ motTreeDestroyItemData(ih, wItem, del_data, cb, old_id);
++
++ XtDestroyWidget(wItem); /* must manually destroy each node, this is NOT recursive */
+ }
+ 
+-static Widget motTreeFindUserDataID(Ihandle* ih, WidgetList itemList, int numItems, void* userdata)
++static void motTreeRemoveNode(Ihandle* ih, Widget wItem, int del_data, int call_cb)
+ {
+- Widget itemChild;
+- WidgetList itemChildList;
+- motTreeItemData *itemData;
+- int i = 0;
+- int numChild;
+-
+- while(i != numItems)
+- {
+- /* ID control to traverse items */
+- ih->data->id_control++;
+-
+- XtVaGetValues(itemList[i], XmNuserData, &itemData, NULL);
+-
+- /* StateID founded! */
+- if(itemData->userdata == userdata)
+- return itemList[i];
++ IFns cb = call_cb? (IFns)IupGetCallback(ih, "NODEREMOVED_CB"): NULL;
++ int old_count = ih->data->node_count;
++ int id = iupTreeFindNodeId(ih, wItem);
++ int old_id = id;
+ 
+- /* Check whether we have child items */
+- itemChildList = NULL;
+- numChild = XmContainerGetItemChildren(ih->handle, itemList[i], &itemChildList);
+- if(numChild)
+- {
+- /* pass the list of children of this item */
+- itemChild = motTreeFindUserDataID(ih, itemChildList, numChild, userdata);
+-
+- /* StateID founded! */
+- if (itemChild)
+- {
+- if (itemChildList) XtFree((char*)itemChildList);
+- return itemChild;
+- }
+- }
++ motTreeRemoveNodeRec(ih, wItem, del_data, cb, &id);
+ 
+- if (itemChildList) XtFree((char*)itemChildList);
+- /* Go to next sibling item */
+- i++;
+- }
+-
+- return NULL;
+-}
+-
+-static int motTreeGetUserDataId(Ihandle* ih, void* userdata)
+-{
+- Widget wRoot = (Widget)iupAttribGet(ih, "_IUPTREE_ROOTITEM");
+- ih->data->id_control = -1;
+- if (motTreeFindUserDataID(ih, &wRoot, 1, userdata))
+- return ih->data->id_control;
+- else
+- return -1;
++ if (call_cb)
++ iupTreeDelFromCache(ih, old_id, old_count-ih->data->node_count);
+ }
+ 
+ static void motTreeSetFocusNode(Ihandle* ih, Widget wItem)
+@@ -737,7 +559,7 @@ static void motTreeSetFocusNode(Ihandle* ih, Widget wItem)
+ XmProcessTraversal(wItem, XmTRAVERSE_CURRENT);
+ }
+ 
+-static Widget motTreeGetFocusNode(Ihandle* ih)
++Widget iupdrvTreeGetFocusNode(Ihandle* ih)
+ {
+ Widget wItem = XmGetFocusWidget(ih->handle); /* returns the focus in the dialog */
+ if (wItem && XtParent(wItem) == ih->handle) /* is a node */
+@@ -746,18 +568,6 @@ static Widget motTreeGetFocusNode(Ihandle* ih)
+ return (Widget)iupAttribGet(ih, "_IUPTREE_LAST_FOCUS");
+ }
+ 
+-static Widget motTreeFindNodeFromString(Ihandle* ih, const char* name_id)
+-{
+- if (name_id[0])
+- {
+- Widget wRoot = (Widget)iupAttribGet(ih, "_IUPTREE_ROOTITEM");
+- iupStrToInt(name_id, &ih->data->id_control);
+- return motTreeFindNodeFromID(ih, &wRoot, 1);
+- }
+- else
+- return motTreeGetFocusNode(ih);
+-}
+-
+ static void motTreeEnterLeaveWindowEvent(Widget w, Ihandle *ih, XEvent *evt, Boolean *cont)
+ {
+ if (iupAttribGet(ih, "_IUPTREE_EDITFIELD"))
+@@ -812,16 +622,24 @@ static void motTreeFocusChangeEvent(Widget w, Ihandle *ih, XEvent *evt, Boolean
+ 
+ void iupdrvTreeAddNode(Ihandle* ih, const char* name_id, int kind, const char* title, int add)
+ {
+- Widget wItemPrev = motTreeFindNodeFromString(ih, name_id);
+- Widget wNewItem;
++ Widget wItemPrev = iupTreeGetNodeFromString(ih, name_id);
++ Widget wItemNew;
+ XmString itemTitle;
+- motTreeItemData *itemData, *itemDataPrev;
++ motTreeItemData *itemData;
+ Pixel bgcolor, fgcolor;
+- int kindPrev, num_args = 0;
++ int kindPrev = 0, num_args = 0;
+ Arg args[30];
+ 
+ if (!wItemPrev)
+- return;
++ {
++ /* check if the root was really specified */
++ int id = 0;
++ if (!iupStrToInt(name_id, &id) || id != -1)
++ return;
++ }
++
++ if (!title)
++ title = "";
+ 
+ itemData = calloc(1, sizeof(motTreeItemData));
+ itemData->image = XmUNSPECIFIED_PIXMAP;
+@@ -836,138 +654,103 @@ void iupdrvTreeAddNode(Ihandle* ih, const char* name_id, int kind, const char* t
+ XtVaGetValues(ih->handle, XmNforeground, &fgcolor, NULL);
+ XtVaGetValues(ih->handle, XmNbackground, &bgcolor, NULL);
+ 
+- /* Get the kind of previous item */
+- XtVaGetValues(wItemPrev, XmNuserData, &itemDataPrev, NULL);
+- kindPrev = itemDataPrev->kind;
+-
+- if (kindPrev == ITREE_BRANCH && add)
++ if (wItemPrev)
+ {
+- /* wItemPrev is parent of the new item (firstchild of it) */
+- iupmotSetArg(args, num_args, XmNentryParent, wItemPrev);
+- iupmotSetArg(args, num_args, XmNpositionIndex, 0);
+- }
+- else
+- {
+- /* wItemPrev is sibling of the new item (set its parent to the new item) */
+- Widget wItemParent;
+- int pos;
++ motTreeItemData *itemDataPrev;
+ 
+- XtVaGetValues(wItemPrev, XmNentryParent, &wItemParent, NULL);
+- XtVaGetValues(wItemPrev, XmNpositionIndex, &pos, NULL);
++ /* Get the kind of previous item */
++ XtVaGetValues(wItemPrev, XmNuserData, &itemDataPrev, NULL);
++ kindPrev = itemDataPrev->kind;
++
++ if (kindPrev == ITREE_BRANCH && add)
++ {
++ /* wItemPrev is parent of the new item (firstchild of it) */
++ iupMOT_SETARG(args, num_args, XmNentryParent, wItemPrev);
++ iupMOT_SETARG(args, num_args, XmNpositionIndex, 0);
++ }
++ else
++ {
++ /* wItemPrev is sibling of the new item (set its parent to the new item) */
++ Widget wItemParent;
++ int pos;
+ 
+- iupmotSetArg(args, num_args, XmNentryParent, wItemParent);
+- iupmotSetArg(args, num_args, XmNpositionIndex, pos+1);
++ XtVaGetValues(wItemPrev, XmNentryParent, &wItemParent, NULL);
++ XtVaGetValues(wItemPrev, XmNpositionIndex, &pos, NULL);
++
++ iupMOT_SETARG(args, num_args, XmNentryParent, wItemParent);
++ iupMOT_SETARG(args, num_args, XmNpositionIndex, pos+1);
++ }
+ }
+ 
+- iupmotSetArg(args, num_args, XmNuserData, itemData);
+- iupmotSetArg(args, num_args, XmNforeground, fgcolor);
+- iupmotSetArg(args, num_args, XmNbackground, bgcolor);
+- iupmotSetArg(args, num_args, XmNmarginHeight, ih->data->spacing);
+- iupmotSetArg(args, num_args, XmNmarginWidth, 0);
+- iupmotSetArg(args, num_args, XmNviewType, XmSMALL_ICON);
+- iupmotSetArg(args, num_args, XmNnavigationType, XmTAB_GROUP);
+- iupmotSetArg(args, num_args, XmNtraversalOn, True);
+- iupmotSetArg(args, num_args, XmNshadowThickness, 0);
+- iupmotSetArg(args, num_args, XmNlabelString, itemTitle);
++ iupMOT_SETARG(args, num_args, XmNuserData, itemData);
++ iupMOT_SETARG(args, num_args, XmNforeground, fgcolor);
++ iupMOT_SETARG(args, num_args, XmNbackground, bgcolor);
++ iupMOT_SETARG(args, num_args, XmNmarginHeight, ih->data->spacing);
++ iupMOT_SETARG(args, num_args, XmNmarginWidth, 0);
++ iupMOT_SETARG(args, num_args, XmNviewType, XmSMALL_ICON);
++ iupMOT_SETARG(args, num_args, XmNnavigationType, XmTAB_GROUP);
++ iupMOT_SETARG(args, num_args, XmNtraversalOn, True);
++ iupMOT_SETARG(args, num_args, XmNshadowThickness, 0);
++ iupMOT_SETARG(args, num_args, XmNlabelString, itemTitle);
+ 
+ if (kind == ITREE_BRANCH)
+ {
+ if (ih->data->add_expanded)
+ {
+- iupmotSetArg(args, num_args, XmNsmallIconPixmap, ih->data->def_image_expanded);
+- iupmotSetArg(args, num_args, XmNsmallIconMask, ih->data->def_image_expanded_mask);
++ iupMOT_SETARG(args, num_args, XmNsmallIconPixmap, ih->data->def_image_expanded);
++ iupMOT_SETARG(args, num_args, XmNsmallIconMask, ih->data->def_image_expanded_mask);
+ }
+ else
+ {
+- iupmotSetArg(args, num_args, XmNsmallIconPixmap, ih->data->def_image_collapsed);
+- iupmotSetArg(args, num_args, XmNsmallIconMask, ih->data->def_image_collapsed_mask);
++ iupMOT_SETARG(args, num_args, XmNsmallIconPixmap, ih->data->def_image_collapsed);
++ iupMOT_SETARG(args, num_args, XmNsmallIconMask, ih->data->def_image_collapsed_mask);
+ }
+ }
+ else
+ {
+- iupmotSetArg(args, num_args, XmNsmallIconPixmap, ih->data->def_image_leaf);
+- iupmotSetArg(args, num_args, XmNsmallIconMask, ih->data->def_image_leaf_mask);
++ iupMOT_SETARG(args, num_args, XmNsmallIconPixmap, ih->data->def_image_leaf);
++ iupMOT_SETARG(args, num_args, XmNsmallIconMask, ih->data->def_image_leaf_mask);
+ }
+ 
++ /* Add the new node */
++ wItemNew = XtCreateManagedWidget("icon", xmIconGadgetClass, ih->handle, args, num_args);
++ if (wItemPrev)
++ iupTreeAddToCache(ih, add, kindPrev, wItemPrev, wItemNew);
++ else
++ {
++ iupTreeAddToCache(ih, 0, 0, NULL, wItemNew);
++
++ if (ih->data->node_count == 1)
++ {
++ /* MarkStart node */
++ iupAttribSetStr(ih, "_IUPTREE_MARKSTART_NODE", (char*)wItemNew);
+ 
+- wNewItem = XtCreateManagedWidget("icon", xmIconGadgetClass, ih->handle, args, num_args);
++ /* Set the default VALUE */
++ motTreeSetFocusNode(ih, wItemNew);
++ }
++ }
+ 
+ if (kind == ITREE_BRANCH)
+ {
++ iupAttribSetStr(ih, "_IUP_IGNORE_BRANCH_CB", "1");
+ if (ih->data->add_expanded)
+- {
+- iupAttribSetStr(ih, "_IUP_IGNORE_BRANCHOPEN", "1");
+- XtVaSetValues(wNewItem, XmNoutlineState, XmEXPANDED, NULL);
+- }
++ XtVaSetValues(wItemNew, XmNoutlineState, XmEXPANDED, NULL);
+ else
+- XtVaSetValues(wNewItem, XmNoutlineState, XmCOLLAPSED, NULL);
++ XtVaSetValues(wItemNew, XmNoutlineState, XmCOLLAPSED, NULL);
++ iupAttribSetStr(ih, "_IUP_IGNORE_BRANCH_CB", NULL);
+ }
+ 
+- /* Root always expanded */
+- XtVaSetValues((Widget)iupAttribGet(ih, "_IUPTREE_ROOTITEM"), XmNoutlineState, XmEXPANDED, NULL);
+-
+- XtRealizeWidget(wNewItem);
++ XtRealizeWidget(wItemNew);
+ XmStringFree(itemTitle);
+ }
+ 
+-static void motTreeAddRootNode(Ihandle* ih)
+-{
+- Widget wRootItem;
+- motTreeItemData *itemData;
+- Pixel bgcolor, fgcolor;
+- int num_args = 0;
+- Arg args[30];
+-
+- itemData = calloc(1, sizeof(motTreeItemData));
+- itemData->image = XmUNSPECIFIED_PIXMAP;
+- itemData->image_expanded = XmUNSPECIFIED_PIXMAP;
+- itemData->image_mask = XmUNSPECIFIED_PIXMAP;
+- itemData->image_expanded_mask = XmUNSPECIFIED_PIXMAP;
+- itemData->kind = ITREE_BRANCH;
+-
+- /* Get default foreground color */
+- XtVaGetValues(ih->handle, XmNforeground, &fgcolor, NULL);
+- XtVaGetValues(ih->handle, XmNbackground, &bgcolor, NULL);
+-
+- iupmotSetArg(args, num_args, XmNentryParent, NULL);
+- iupmotSetArg(args, num_args, XmNuserData, itemData);
+- iupmotSetArg(args, num_args, XmNforeground, fgcolor);
+- iupmotSetArg(args, num_args, XmNbackground, bgcolor);
+- iupmotSetArg(args, num_args, XmNoutlineState, XmEXPANDED);
+- iupmotSetArg(args, num_args, XmNmarginHeight, ih->data->spacing);
+- iupmotSetArg(args, num_args, XmNmarginWidth, 0);
+- iupmotSetArg(args, num_args, XmNviewType, XmSMALL_ICON);
+- iupmotSetArg(args, num_args, XmNnavigationType, XmTAB_GROUP);
+- iupmotSetArg(args, num_args, XmNtraversalOn, True);
+- iupmotSetArg(args, num_args, XmNshadowThickness, 0);
+- iupmotSetArg(args, num_args, XmNsmallIconPixmap, ih->data->def_image_expanded);
+- iupmotSetArg(args, num_args, XmNsmallIconMask, ih->data->def_image_expanded_mask);
+-
+- wRootItem = XtCreateManagedWidget("icon", xmIconGadgetClass, ih->handle, args, num_args);
+-
+- /* Select the new item */
+- XtVaSetValues(wRootItem, XmNvisualEmphasis, XmSELECTED, NULL);
+-
+- XtRealizeWidget(wRootItem);
+-
+- /* Save the root node for later use */
+- iupAttribSetStr(ih, "_IUPTREE_ROOTITEM", (char*)wRootItem);
+-
+- /* MarkStart node */
+- iupAttribSetStr(ih, "_IUPTREE_MARKSTART_NODE", (char*)wRootItem);
+-
+- /* Set the default VALUE */
+- /* In Motif this will set also the current focus */
+- motTreeSetFocusNode(ih, wRootItem);
+-}
+-
+ /*****************************************************************************/
+ 
+ static int motTreeSetImageExpandedAttrib(Ihandle* ih, const char* name_id, const char* value)
+ {
+ motTreeItemData *itemData;
+ unsigned char itemState;
+- Widget wItem = motTreeFindNodeFromString(ih, name_id);
++ Widget wItem = iupTreeGetNodeFromString(ih, name_id);
+ if (!wItem)
+ return 0;
+ 
+@@ -1003,7 +786,7 @@ static int motTreeSetImageExpandedAttrib(Ihandle* ih, const char* name_id, const
+ static int motTreeSetImageAttrib(Ihandle* ih, const char* name_id, const char* value)
+ {
+ motTreeItemData *itemData;
+- Widget wItem = motTreeFindNodeFromString(ih, name_id);
++ Widget wItem = iupTreeGetNodeFromString(ih, name_id);
+ if (!wItem) 
+ return 0;
+ 
+@@ -1053,7 +836,6 @@ static int motTreeSetImageAttrib(Ihandle* ih, const char* name_id, const char* v
+ 
+ static int motTreeSetImageBranchExpandedAttrib(Ihandle* ih, const char* value)
+ {
+- Widget wRoot = (Widget)iupAttribGet(ih, "_IUPTREE_ROOTITEM");
+ ih->data->def_image_expanded = iupImageGetImage(value, ih, 0);
+ if (!ih->data->def_image_expanded) 
+ {
+@@ -1067,14 +849,13 @@ static int motTreeSetImageBranchExpandedAttrib(Ihandle* ih, const char* value)
+ }
+ 
+ /* Update all images, starting at root node */
+- motTreeUpdateImages(ih, &wRoot, 1, ITREE_UPDATEIMAGE_EXPANDED);
++ motTreeUpdateImages(ih, ITREE_UPDATEIMAGE_EXPANDED);
+ 
+ return 1;
+ }
+ 
+ static int motTreeSetImageBranchCollapsedAttrib(Ihandle* ih, const char* value)
+ {
+- Widget wRoot = (Widget)iupAttribGet(ih, "_IUPTREE_ROOTITEM");
+ ih->data->def_image_collapsed = iupImageGetImage(value, ih, 0);
+ if (!ih->data->def_image_collapsed) 
+ {
+@@ -1088,14 +869,13 @@ static int motTreeSetImageBranchCollapsedAttrib(Ihandle* ih, const char* value)
+ }
+ 
+ /* Update all images, starting at root node */
+- motTreeUpdateImages(ih, &wRoot, 1, ITREE_UPDATEIMAGE_COLLAPSED);
++ motTreeUpdateImages(ih, ITREE_UPDATEIMAGE_COLLAPSED);
+ 
+ return 1;
+ }
+ 
+ static int motTreeSetImageLeafAttrib(Ihandle* ih, const char* value)
+ {
+- Widget wRoot = (Widget)iupAttribGet(ih, "_IUPTREE_ROOTITEM");
+ ih->data->def_image_leaf = iupImageGetImage(value, ih, 0);
+ if (!ih->data->def_image_leaf) 
+ {
+@@ -1109,7 +889,7 @@ static int motTreeSetImageLeafAttrib(Ihandle* ih, const char* value)
+ }
+ 
+ /* Update all images, starting at root node */
+- motTreeUpdateImages(ih, &wRoot, 1, ITREE_UPDATEIMAGE_LEAF);
++ motTreeUpdateImages(ih, ITREE_UPDATEIMAGE_LEAF);
+ 
+ return 1;
+ }
+@@ -1118,7 +898,7 @@ static char* motTreeGetStateAttrib(Ihandle* ih, const char* name_id)
+ {
+ int hasChildren;
+ unsigned char itemState;
+- Widget wItem = motTreeFindNodeFromString(ih, name_id);
++ Widget wItem = iupTreeGetNodeFromString(ih, name_id);
+ if (!wItem) 
+ return 0;
+ 
+@@ -1138,14 +918,21 @@ static char* motTreeGetStateAttrib(Ihandle* ih, const char* name_id)
+ 
+ static int motTreeSetStateAttrib(Ihandle* ih, const char* name_id, const char* value)
+ {
+- Widget wItem = motTreeFindNodeFromString(ih, name_id);
+- if (!wItem) 
++ motTreeItemData *itemData;
++ Widget wItem = iupTreeGetNodeFromString(ih, name_id);
++ if (!wItem)
+ return 0;
+ 
+- if (iupStrEqualNoCase(value, "EXPANDED"))
+- XtVaSetValues(wItem, XmNoutlineState, XmEXPANDED, NULL);
+- else 
+- XtVaSetValues(wItem, XmNoutlineState, XmCOLLAPSED, NULL);
++ XtVaGetValues(wItem, XmNuserData, &itemData, NULL);
++ if (itemData->kind == ITREE_BRANCH)
++ {
++ iupAttribSetStr(ih, "_IUP_IGNORE_BRANCH_CB", "1");
++ if (iupStrEqualNoCase(value, "EXPANDED"))
++ XtVaSetValues(wItem, XmNoutlineState, XmEXPANDED, NULL);
++ else 
++ XtVaSetValues(wItem, XmNoutlineState, XmCOLLAPSED, NULL);
++ iupAttribSetStr(ih, "_IUP_IGNORE_BRANCH_CB", NULL);
++ }
+ 
+ return 0;
+ }
+@@ -1155,7 +942,7 @@ static char* motTreeGetColorAttrib(Ihandle* ih, const char* name_id)
+ unsigned char r, g, b;
+ Pixel color;
+ char* str;
+- Widget wItem = motTreeFindNodeFromString(ih, name_id); 
++ Widget wItem = iupTreeGetNodeFromString(ih, name_id); 
+ if (!wItem) 
+ return NULL;
+ 
+@@ -1170,7 +957,7 @@ static char* motTreeGetColorAttrib(Ihandle* ih, const char* name_id)
+ static int motTreeSetColorAttrib(Ihandle* ih, const char* name_id, const char* value)
+ {
+ Pixel color;
+- Widget wItem = motTreeFindNodeFromString(ih, name_id); 
++ Widget wItem = iupTreeGetNodeFromString(ih, name_id); 
+ if (!wItem) 
+ return 0;
+ 
+@@ -1182,36 +969,33 @@ static int motTreeSetColorAttrib(Ihandle* ih, const char* name_id, const char* v
+ 
+ static char* motTreeGetDepthAttrib(Ihandle* ih, const char* name_id)
+ {
+- Widget wRoot;
+- int dep = 0;
+- char* depth;
+- Widget wItem = motTreeFindNodeFromString(ih, name_id); 
++ int depth = -1;
++ char* str;
++ Widget wItem = iupTreeGetNodeFromString(ih, name_id); 
+ if (!wItem) 
+ return NULL;
+ 
+- wRoot = (Widget)iupAttribGet(ih, "_IUPTREE_ROOTITEM");
+-
+- while((wRoot != wItem) && (wItem != NULL))
++ while(wItem != NULL)
+ {
+ XtVaGetValues(wItem, XmNentryParent, &wItem, NULL);
+- dep++;
++ depth++;
+ }
+ 
+- depth = iupStrGetMemory(10);
+- sprintf(depth, "%d", dep);
+- return depth;
++ str = iupStrGetMemory(10);
++ sprintf(str, "%d", depth);
++ return str;
+ }
+ 
+ static int motTreeSetMoveNodeAttrib(Ihandle* ih, const char* name_id, const char* value)
+ {
+ Widget wItemDst, wParent, wItemSrc;
+ 
+- if (!ih->handle) /* do not store the action before map */
++ if (!ih->handle) /* do not do the action before map */
+ return 0;
+- wItemSrc = motTreeFindNodeFromString(ih, name_id);
++ wItemSrc = iupTreeGetNodeFromString(ih, name_id);
+ if (!wItemSrc)
+ return 0;
+- wItemDst = motTreeFindNodeFromString(ih, value);
++ wItemDst = iupTreeGetNodeFromString(ih, value);
+ if (!wItemDst)
+ return 0;
+ 
+@@ -1224,11 +1008,8 @@ static int motTreeSetMoveNodeAttrib(Ihandle* ih, const char* name_id, const char
+ return 0;
+ }
+ 
+- /* Copying the node and its children to the new position */
+- motTreeCopyNode(ih, wItemSrc, wItemDst, 0); /* not a full copy, preserve user data */
+-
+- /* Deleting the node (and its children) inserted into the old position */
+- motTreeRemoveNode(ih, wItemSrc, 0); /* do not delete the user data, we copy the references in CopyNode */
++ /* Move the node and its children to the new position */
++ motTreeCopyMoveNode(ih, wItemSrc, wItemDst, 0);
+ 
+ return 0;
+ }
+@@ -1237,12 +1018,12 @@ static int motTreeSetCopyNodeAttrib(Ihandle* ih, const char* name_id, const char
+ {
+ Widget wItemDst, wParent, wItemSrc;
+ 
+- if (!ih->handle) /* do not store the action before map */
++ if (!ih->handle) /* do not do the action before map */
+ return 0;
+- wItemSrc = motTreeFindNodeFromString(ih, name_id);
++ wItemSrc = iupTreeGetNodeFromString(ih, name_id);
+ if (!wItemSrc)
+ return 0;
+- wItemDst = motTreeFindNodeFromString(ih, value);
++ wItemDst = iupTreeGetNodeFromString(ih, value);
+ if (!wItemDst)
+ return 0;
+ 
+@@ -1255,8 +1036,8 @@ static int motTreeSetCopyNodeAttrib(Ihandle* ih, const char* name_id, const char
+ return 0;
+ }
+ 
+- /* Copying the node and its children to the new position */
+- motTreeCopyNode(ih, wItemSrc, wItemDst, 1);
++ /* Copy the node and its children to the new position */
++ motTreeCopyMoveNode(ih, wItemSrc, wItemDst, 1);
+ 
+ return 0;
+ }
+@@ -1265,7 +1046,7 @@ static char* motTreeGetParentAttrib(Ihandle* ih, const char* name_id)
+ {
+ Widget wItemParent;
+ char* str;
+- Widget wItem = motTreeFindNodeFromString(ih, name_id);
++ Widget wItem = iupTreeGetNodeFromString(ih, name_id);
+ if (!wItem) 
+ return NULL;
+ 
+@@ -1275,7 +1056,7 @@ static char* motTreeGetParentAttrib(Ihandle* ih, const char* name_id)
+ return NULL;
+ 
+ str = iupStrGetMemory(10);
+- sprintf(str, "%d", motTreeGetNodeId(ih, wItemParent));
++ sprintf(str, "%d", iupTreeFindNodeId(ih, wItemParent));
+ return str;
+ }
+ 
+@@ -1283,7 +1064,7 @@ static char* motTreeGetChildCountAttrib(Ihandle* ih, const char* name_id)
+ {
+ char* str;
+ WidgetList wList = NULL;
+- Widget wItem = motTreeFindNodeFromString(ih, name_id);
++ Widget wItem = iupTreeGetNodeFromString(ih, name_id);
+ if (!wItem) 
+ return NULL;
+ 
+@@ -1293,30 +1074,10 @@ static char* motTreeGetChildCountAttrib(Ihandle* ih, const char* name_id)
+ return str;
+ }
+ 
+-static int motTreeCount(Ihandle* ih, Widget wItem)
+-{
+- WidgetList wList = NULL;
+- int i, count = 0;
+- int childCount = XmContainerGetItemChildren(ih->handle, wItem, &wList);
+- count++;
+- for (i=0; i<childCount; i++)
+- count += motTreeCount(ih, wList[i]);
+- if (wList) XtFree((char*)wList);
+- return count;
+-}
+-
+-static char* motTreeGetCountAttrib(Ihandle* ih)
+-{
+- char* str = iupStrGetMemory(10);
+- Widget wRoot = (Widget)iupAttribGet(ih, "_IUPTREE_ROOTITEM");
+- sprintf(str, "%d", motTreeCount(ih, wRoot));
+- return str;
+-}
+-
+ static char* motTreeGetKindAttrib(Ihandle* ih, const char* name_id)
+ {
+ motTreeItemData *itemData;
+- Widget wItem = motTreeFindNodeFromString(ih, name_id);
++ Widget wItem = iupTreeGetNodeFromString(ih, name_id);
+ if (!wItem) 
+ return NULL;
+ 
+@@ -1331,15 +1092,64 @@ static char* motTreeGetKindAttrib(Ihandle* ih, const char* name_id)
+ static char* motTreeGetValueAttrib(Ihandle* ih)
+ {
+ char* str;
+- Widget wItem = motTreeGetFocusNode(ih);
++ Widget wItem = iupdrvTreeGetFocusNode(ih);
+ if (!wItem)
+- return "0"; /* default VALUE is root */
++ {
++ if (ih->data->node_count)
++ return "0"; /* default VALUE is root */
++ else
++ return "-1";
++ }
+ 
+ str = iupStrGetMemory(10);
+- sprintf(str, "%d", motTreeGetNodeId(ih, wItem));
++ sprintf(str, "%d", iupTreeFindNodeId(ih, wItem));
++ return str;
++}
++
++static char* motTreeGetMarkedNodesAttrib(Ihandle* ih)
++{
++ char* str;
++ int i;
++
++ if (ih->data->mark_mode==ITREE_MARK_SINGLE)
++ return NULL;
++
++ str = iupStrGetMemory(ih->data->node_count+1);
++
++ for (i=0; i<ih->data->node_count; i++)
++ {
++ if (motTreeIsNodeSelected(ih->data->node_cache[i].node_handle))
++ str[i] = '+';
++ else
++ str[i] = '-';
++ }
++
++ str[ih->data->node_count] = 0;
+ return str;
+ }
+ 
++static int motTreeSetMarkedNodesAttrib(Ihandle* ih, const char* value)
++{
++ int count, i;
++
++ if (ih->data->mark_mode==ITREE_MARK_SINGLE || !value)
++ return 0;
++
++ count = strlen(value);
++ if (count > ih->data->node_count)
++ count = ih->data->node_count;
++
++ for (i=0; i<count; i++)
++ {
++ if (value[i] == '+')
++ XtVaSetValues(ih->data->node_cache[i].node_handle, XmNvisualEmphasis, XmSELECTED, NULL);
++ else
++ XtVaSetValues(ih->data->node_cache[i].node_handle, XmNvisualEmphasis, XmNOT_SELECTED, NULL);
++ }
++
++ return 0;
++}
++
+ static int motTreeSetMarkAttrib(Ihandle* ih, const char* value)
+ {
+ if (ih->data->mark_mode==ITREE_MARK_SINGLE)
+@@ -1353,21 +1163,16 @@ static int motTreeSetMarkAttrib(Ihandle* ih, const char* value)
+ motTreeInvertAllNodeMarking(ih);
+ else if(iupStrEqualPartial(value, "INVERT"))
+ {
+- unsigned char isSelected;
+- Widget wItem = motTreeFindNodeFromString(ih, &value[strlen("INVERT")]);
++ Widget wItem = iupTreeGetNodeFromString(ih, &value[strlen("INVERT")]);
+ if (!wItem) 
+ return 0;
+ 
+- XtVaGetValues(wItem, XmNvisualEmphasis, &isSelected, NULL);
+- if (isSelected == XmSELECTED)
+- XtVaSetValues(wItem, XmNvisualEmphasis, XmNOT_SELECTED, NULL);
+- else
+- XtVaSetValues(wItem, XmNvisualEmphasis, XmSELECTED, NULL);
++ motTreeSelectNode(wItem, -1);
+ }
+ else if(iupStrEqualNoCase(value, "BLOCK"))
+ {
+ Widget wItem = (Widget)iupAttribGet(ih, "_IUPTREE_MARKSTART_NODE");
+- Widget wFocusItem = motTreeGetFocusNode(ih);
++ Widget wFocusItem = iupdrvTreeGetFocusNode(ih);
+ if(!wFocusItem || !wItem)
+ return 0;
+ motTreeSelectRange(ih, wFocusItem, wItem, 0);
+@@ -1379,10 +1184,10 @@ static int motTreeSetMarkAttrib(Ihandle* ih, const char* value)
+ if (iupStrToStrStr(value, str1, str2, '-')!=2)
+ return 0;
+ 
+- wItem1 = motTreeFindNodeFromString(ih, str1);
++ wItem1 = iupTreeGetNodeFromString(ih, str1);
+ if (!wItem1) 
+ return 0;
+- wItem2 = motTreeFindNodeFromString(ih, str2);
++ wItem2 = iupTreeGetNodeFromString(ih, str2);
+ if (!wItem2) 
+ return 0;
+ 
+@@ -1394,69 +1199,49 @@ static int motTreeSetMarkAttrib(Ihandle* ih, const char* value)
+ 
+ static int motTreeSetValueAttrib(Ihandle* ih, const char* value)
+ {
+- Widget wRoot, wItem;
++ Widget wItem, wItemParent;
+ 
+ if (motTreeSetMarkAttrib(ih, value))
+ return 0;
+ 
+- wRoot = (Widget)iupAttribGet(ih, "_IUPTREE_ROOTITEM");
+-
+- if (iupStrEqualNoCase(value, "ROOT"))
+- wItem = wRoot;
++ if (iupStrEqualNoCase(value, "ROOT") || iupStrEqualNoCase(value, "FIRST"))
++ wItem = (Widget)iupAttribGet(ih, "_IUPTREE_ROOTITEM");
+ else if(iupStrEqualNoCase(value, "LAST"))
+- wItem = motTreeGetLastVisibleNode(ih, wRoot);
++ wItem = motTreeGetLastVisibleNode(ih);
+ else if(iupStrEqualNoCase(value, "PGUP"))
+ {
+- Widget wItemFocus = motTreeGetFocusNode(ih);
++ Widget wItemFocus = iupdrvTreeGetFocusNode(ih);
+ if(!wItemFocus)
+ return 0;
+ 
+- ih->data->id_control = -1;
+- motTreeFindVisibleNodeId(ih, &wRoot, 1, wItemFocus);
+- ih->data->id_control -= 10; /* less 10 visible nodes */
+-
+- if(ih->data->id_control < 0)
+- ih->data->id_control = 0; /* Begin of tree = Root id */
+-
+- wItem = motTreeFindVisibleNodeFromId(ih, &wRoot, 1);
++ wItem = motTreeGetPreviousVisibleNode(ih, wItemFocus, 10);
+ }
+ else if(iupStrEqualNoCase(value, "PGDN"))
+ {
+- Widget wNext, wItemFocus;
+-
+- wItemFocus = motTreeGetFocusNode(ih);
++ Widget wItemFocus = iupdrvTreeGetFocusNode(ih);
+ if(!wItemFocus)
+ return 0;
+ 
+- ih->data->id_control = -1;
+- motTreeFindVisibleNodeId(ih, &wRoot, 1, wItemFocus);
+- ih->data->id_control += 10; /* more 10 visible nodes */
+-
+- wNext = motTreeFindVisibleNodeFromId(ih, &wRoot, 1);
+-
+- if (ih->data->id_control >= 0)
+- wNext = motTreeGetLastVisibleNode(ih, wRoot);
+- 
+- wItem = wNext;
++ wItem = motTreeGetNextVisibleNode(ih, wItemFocus, 10);
+ }
+ else if(iupStrEqualNoCase(value, "NEXT"))
+ {
+- Widget wItemFocus = motTreeGetFocusNode(ih);
++ Widget wItemFocus = iupdrvTreeGetFocusNode(ih);
+ if (!wItemFocus)
+ return 0;
+ 
+- wItem = motTreeGetNextVisibleNode(ih, wRoot, wItemFocus);
++ wItem = motTreeGetNextVisibleNode(ih, wItemFocus, 1);
+ }
+ else if(iupStrEqualNoCase(value, "PREVIOUS"))
+ {
+- Widget wItemFocus = motTreeGetFocusNode(ih);
++ Widget wItemFocus = iupdrvTreeGetFocusNode(ih);
+ if(!wItemFocus)
+ return 0;
+ 
+- wItem = motTreeGetPreviousVisibleNode(ih, wRoot, wItemFocus);
++ wItem = motTreeGetPreviousVisibleNode(ih, wItemFocus, 1);
+ }
+ else
+- wItem = motTreeFindNodeFromString(ih, value);
++ wItem = iupTreeGetNodeFromString(ih, value);
+ 
+ if (!wItem) 
+ return 0;
+@@ -1471,17 +1256,26 @@ static int motTreeSetValueAttrib(Ihandle* ih, const char* value)
+ XtVaSetValues(wItem, XmNvisualEmphasis, XmSELECTED, NULL);
+ }
+ 
++
++ /* expand all parents */
++ XtVaGetValues(wItem, XmNentryParent, &wItemParent, NULL);
++ while(wItemParent)
++ {
++ XtVaSetValues(wItemParent, XmNoutlineState, XmEXPANDED, NULL);
++ XtVaGetValues(wItemParent, XmNentryParent, &wItemParent, NULL);
++ }
++
+ /* set focus (will scroll to visible) */
+ motTreeSetFocusNode(ih, wItem);
+ 
+- iupAttribSetInt(ih, "_IUPTREE_OLDVALUE", motTreeGetNodeId(ih, wItem));
++ iupAttribSetInt(ih, "_IUPTREE_OLDVALUE", iupTreeFindNodeId(ih, wItem));
+ 
+ return 0;
+ } 
+ 
+ static int motTreeSetMarkStartAttrib(Ihandle* ih, const char* name_id)
+ {
+- Widget wItem = motTreeFindNodeFromString(ih, name_id);
++ Widget wItem = iupTreeGetNodeFromString(ih, name_id);
+ if (!wItem) 
+ return 0;
+ 
+@@ -1492,14 +1286,11 @@ static int motTreeSetMarkStartAttrib(Ihandle* ih, const char* name_id)
+ 
+ static char* motTreeGetMarkedAttrib(Ihandle* ih, const char* name_id)
+ {
+- unsigned char isSelected;
+- Widget wItem = motTreeFindNodeFromString(ih, name_id);
++ Widget wItem = iupTreeGetNodeFromString(ih, name_id);
+ if (!wItem) 
+ return NULL;
+ 
+- XtVaGetValues(wItem, XmNvisualEmphasis, &isSelected, NULL);
+-
+- if(isSelected == XmSELECTED)
++ if (motTreeIsNodeSelected(wItem))
+ return "YES";
+ else
+ return "NO";
+@@ -1507,7 +1298,7 @@ static char* motTreeGetMarkedAttrib(Ihandle* ih, const char* name_id)
+ 
+ static int motTreeSetMarkedAttrib(Ihandle* ih, const char* name_id, const char* value)
+ {
+- Widget wItem = motTreeFindNodeFromString(ih, name_id);
++ Widget wItem = iupTreeGetNodeFromString(ih, name_id);
+ if (!wItem) 
+ return 0;
+ 
+@@ -1531,7 +1322,7 @@ static char* motTreeGetTitle(Widget wItem)
+ 
+ static char* motTreeGetTitleAttrib(Ihandle* ih, const char* name_id)
+ {
+- Widget wItem = motTreeFindNodeFromString(ih, name_id);
++ Widget wItem = iupTreeGetNodeFromString(ih, name_id);
+ if (!wItem) 
+ return NULL;
+ return motTreeGetTitle(wItem);
+@@ -1539,10 +1330,13 @@ static char* motTreeGetTitleAttrib(Ihandle* ih, const char* name_id)
+ 
+ static int motTreeSetTitleAttrib(Ihandle* ih, const char* name_id, const char* value)
+ {
+- Widget wItem = motTreeFindNodeFromString(ih, name_id);
++ Widget wItem = iupTreeGetNodeFromString(ih, name_id);
+ if (!wItem) 
+ return 0;
+ 
++ if (!value)
++ value = "";
++
+ iupmotSetString(wItem, XmNlabelString, value);
+ 
+ return 0;
+@@ -1551,7 +1345,7 @@ static int motTreeSetTitleAttrib(Ihandle* ih, const char* name_id, const char* v
+ static int motTreeSetTitleFontAttrib(Ihandle* ih, const char* name_id, const char* value)
+ {
+ XmFontList fontlist = NULL;
+- Widget wItem = motTreeFindNodeFromString(ih, name_id);
++ Widget wItem = iupTreeGetNodeFromString(ih, name_id);
+ if (!wItem) 
+ return 0;
+ 
+@@ -1569,7 +1363,7 @@ static int motTreeSetTitleFontAttrib(Ihandle* ih, const char* name_id, const cha
+ static char* motTreeGetTitleFontAttrib(Ihandle* ih, const char* name_id)
+ {
+ XmFontList fontlist;
+- Widget wItem = motTreeFindNodeFromString(ih, name_id);
++ Widget wItem = iupTreeGetNodeFromString(ih, name_id);
+ if (!wItem) 
+ return NULL;
+ 
+@@ -1577,118 +1371,81 @@ static char* motTreeGetTitleFontAttrib(Ihandle* ih, const char* name_id)
+ return iupmotFindFontList(fontlist);
+ }
+ 
+-static char* motTreeGetFindUserDataAttrib(Ihandle* ih, const char* name_id)
+-{
+- int id;
+- char* str = (char*)(name_id+1); /* skip ':' */
+- void* userdata = NULL;
+- if (sscanf(str, "%p", &userdata)!=1)
+- return NULL;
+- id = motTreeGetUserDataId(ih, userdata);
+- if (id == -1)
+- return NULL;
+- str = iupStrGetMemory(16);
+- sprintf(str, "%d", id);
+- return str;
+-}
+-
+-static char* motTreeGetUserDataAttrib(Ihandle* ih, const char* name_id)
+-{
+- motTreeItemData *itemData;
+- Widget wItem = motTreeFindNodeFromString(ih, name_id);
+- if (!wItem) 
+- return NULL;
+-
+- XtVaGetValues(wItem, XmNuserData, &itemData, NULL);
+-
+- return itemData->userdata;
+-}
+-
+-static int motTreeSetUserDataAttrib(Ihandle* ih, const char* name_id, const char* value)
+-{
+- motTreeItemData *itemData;
+- Widget wItem = motTreeFindNodeFromString(ih, name_id);
+- if (!wItem) 
+- return 0;
+-
+- XtVaGetValues(wItem, XmNuserData, &itemData, NULL);
+- itemData->userdata = (void*)value;
+-
+- return 0;
+-}
+-
+ static int motTreeSetRenameAttrib(Ihandle* ih, const char* value)
+ { 
+ if (ih->data->show_rename)
+ {
+- IFni cbShowRename = (IFni)IupGetCallback(ih, "SHOWRENAME_CB");
+- Widget wItemFocus = motTreeGetFocusNode(ih);
+- if (cbShowRename)
+- cbShowRename(ih, motTreeGetNodeId(ih, wItemFocus));
++ Widget wItemFocus = iupdrvTreeGetFocusNode(ih);
+ motTreeShowEditField(ih, wItemFocus);
+ }
+- else
+- {
+- IFnis cbRenameNode = (IFnis)IupGetCallback(ih, "RENAMENODE_CB");
+- if (cbRenameNode)
+- {
+- Widget wItemFocus = motTreeGetFocusNode(ih);
+- cbRenameNode(ih, motTreeGetNodeId(ih, wItemFocus), motTreeGetTitle(wItemFocus)); 
+- }
+- }
+ 
+ (void)value;
+ return 0;
+ }
+ 
++static void motTreeRemoveAllNodes(Ihandle* ih, int call_cb)
++{
++ IFns cb = call_cb? (IFns)IupGetCallback(ih, "NODEREMOVED_CB"): NULL;
++ int i, old_count = ih->data->node_count;
++ Widget wItem;
++
++ for (i = 0; i < ih->data->node_count; i++)
++ {
++ wItem = ih->data->node_cache[i].node_handle;
++
++ motTreeDestroyItemData(ih, wItem, 1, cb, i);
++
++ XtDestroyWidget(wItem); /* must manually destroy each node, this is NOT recursive */
++ }
++
++ ih->data->node_count = 0;
++
++ if (call_cb)
++ iupTreeDelFromCache(ih, 0, old_count);
++}
++
+ static int motTreeSetDelNodeAttrib(Ihandle* ih, const char* name_id, const char* value)
+ {
+- if (!ih->handle) /* do not store the action before map */
++ if (!ih->handle) /* do not do the action before map */
+ return 0;
+- if(iupStrEqualNoCase(value, "SELECTED")) /* selected here means the specified one */
++ if (iupStrEqualNoCase(value, "ALL"))
+ {
+- Widget wItem = motTreeFindNodeFromString(ih, name_id);
+- Widget wRoot = (Widget)iupAttribGet(ih, "_IUPTREE_ROOTITEM");
+-
+- /* the root node can't be deleted */
+- if(!wItem || wItem == wRoot) /* root is the unique child */
++ motTreeRemoveAllNodes(ih, 1);
++ return 0;
++ }
++ if(iupStrEqualNoCase(value, "SELECTED")) /* selected here means the reference node */
++ {
++ Widget wItem = iupTreeGetNodeFromString(ih, name_id);
++ if(!wItem)
+ return 0;
+ 
+- /* deleting the specified node (and it's children) */
+- motTreeRemoveNode(ih, wItem, 1);
++ /* deleting the reference node (and it's children) */
++ motTreeRemoveNode(ih, wItem, 1, 1);
+ }
+- else if(iupStrEqualNoCase(value, "CHILDREN")) /* children of the specified one */
++ else if(iupStrEqualNoCase(value, "CHILDREN")) /* children of the reference node */
+ {
+- Widget wItem = motTreeFindNodeFromString(ih, name_id);
++ int numChild, i;
++ WidgetList wItemList = NULL;
++ Widget wItem = iupTreeGetNodeFromString(ih, name_id);
+ 
+ if(!wItem)
+ return 0;
+ 
+- {
+- /* deleting the selected node's children only */
+- WidgetList wItemList = NULL;
+- int numChild = XmContainerGetItemChildren(ih->handle, wItem, &wItemList);
+- if(numChild)
+- motTreeRemoveChildren(ih, wItemList, numChild, 1);
+- if (wItemList) XtFree((char*)wItemList);
+- }
++ /* deleting the reference node children only */
++ numChild = XmContainerGetItemChildren(ih->handle, wItem, &wItemList);
++ for(i = 0; i < numChild; i++)
++ motTreeRemoveNode(ih, wItemList[i], 1, 1);
++ if (wItemList) XtFree((char*)wItemList);
+ }
+ else if(iupStrEqualNoCase(value, "MARKED")) /* Delete the array of marked nodes */
+ {
+- WidgetList wSelectedItemList = NULL;
+- Widget wRoot;
+- int countItems, i;
+-
+- XtVaGetValues(ih->handle, XmNselectedObjects, &wSelectedItemList,
+- XmNselectedObjectCount, &countItems, NULL);
+-
+- wRoot = (Widget)iupAttribGet(ih, "_IUPTREE_ROOTITEM");
+-
+- for(i = 0; i < countItems; i++)
++ int i;
++ for(i = 1; i < ih->data->node_count; /* increment only if not removed */)
+ {
+- int ok = XmIsIconGadget(wSelectedItemList[i]);
+- if ((wSelectedItemList[i] != wRoot) && ok) /* the root node can't be deleted */
+- motTreeRemoveNode(ih, wSelectedItemList[i], 1);
++ if (motTreeIsNodeSelected(ih->data->node_cache[i].node_handle))
++ motTreeRemoveNode(ih, ih->data->node_cache[i].node_handle, 1, 1);
++ else
++ i++;
+ }
+ }
+ 
+@@ -1714,7 +1471,7 @@ static int motTreeSetIndentationAttrib(Ihandle* ih, const char* value)
+ 
+ static int motTreeSetTopItemAttrib(Ihandle* ih, const char* value)
+ {
+- Widget wItem = motTreeFindNodeFromString(ih, value);
++ Widget wItem = iupTreeGetNodeFromString(ih, value);
+ Widget sb_win;
+ Widget wItemParent;
+ 
+@@ -1735,10 +1492,11 @@ static int motTreeSetTopItemAttrib(Ihandle* ih, const char* value)
+ return 0;
+ }
+ 
+-static int motTreeSpacingFunc(Ihandle* ih, Widget wItem, void *data)
++static int motTreeSpacingFunc(Ihandle* ih, Widget wItem, int id, void *data)
+ {
+ XtVaSetValues(wItem, XmNmarginHeight, ih->data->spacing, NULL);
+ (void)data;
++ (void)id;
+ return 1;
+ }
+ 
+@@ -1752,7 +1510,7 @@ static int motTreeSetSpacingAttrib(Ihandle* ih, const char* value)
+ 
+ if (ih->handle)
+ {
+- motTreeForEach(ih, NULL, (motTreeNodeFunc)motTreeSpacingFunc, 0);
++ iupTreeForEach(ih, (iupTreeNodeFunc)motTreeSpacingFunc, 0);
+ return 0;
+ }
+ else
+@@ -1761,17 +1519,10 @@ static int motTreeSetSpacingAttrib(Ihandle* ih, const char* value)
+ 
+ static int motTreeSetExpandAllAttrib(Ihandle* ih, const char* value)
+ {
+- Widget wRoot = (Widget)iupAttribGet(ih, "_IUPTREE_ROOTITEM");
+-
+ if (iupStrBoolean(value))
+- motTreeExpandCollapseAllNodes(ih, &wRoot, 1, XmEXPANDED);
++ motTreeExpandCollapseAllNodes(ih, XmEXPANDED);
+ else
+- {
+- motTreeExpandCollapseAllNodes(ih, &wRoot, 1, XmCOLLAPSED);
+-
+- /* The root node is always expanded */
+- XtVaSetValues((Widget)iupAttribGet(ih, "_IUPTREE_ROOTITEM"), XmNoutlineState, XmEXPANDED, NULL);
+- }
++ motTreeExpandCollapseAllNodes(ih, XmCOLLAPSED);
+ 
+ return 0;
+ }
+@@ -1801,16 +1552,13 @@ static int motTreeSetBgColorAttrib(Ihandle* ih, const char* value)
+ color = iupmotColorGetPixelStr(value);
+ if (color != (Pixel)-1)
+ {
+- Widget wRoot;
+ Widget clipwin = NULL;
+ 
+ XtVaGetValues(sb_win, XmNclipWindow, &clipwin, NULL);
+ if (clipwin) iupmotSetBgColor(clipwin, color);
+ 
+- wRoot = (Widget)iupAttribGet(ih, "_IUPTREE_ROOTITEM");
+- 
+ /* Update all children, starting at root node */
+- motTreeUpdateBgColor(ih, &wRoot, 1, color);
++ motTreeUpdateBgColor(ih, color);
+ }
+ 
+ iupdrvBaseSetBgColorAttrib(ih, value); /* use given value for contents */
+@@ -1871,10 +1619,14 @@ static void motTreeSetRenameSelectionPos(Widget cbEdit, const char* value)
+ 
+ static int motTreeCallBranchCloseCb(Ihandle* ih, Widget wItem)
+ {
+- IFni cbBranchClose = (IFni)IupGetCallback(ih, "BRANCHCLOSE_CB");
++ IFni cbBranchClose;
++
++ if (iupAttribGet(ih, "_IUP_IGNORE_BRANCH_CB"))
++ return IUP_DEFAULT;
+ 
+- if(cbBranchClose)
+- return cbBranchClose(ih, motTreeGetNodeId(ih, wItem));
++ cbBranchClose = (IFni)IupGetCallback(ih, "BRANCHCLOSE_CB");
++ if (cbBranchClose)
++ return cbBranchClose(ih, iupTreeFindNodeId(ih, wItem));
+ 
+ return IUP_DEFAULT;
+ }
+@@ -1883,59 +1635,136 @@ static int motTreeCallBranchOpenCb(Ihandle* ih, Widget wItem)
+ {
+ IFni cbBranchOpen;
+ 
+- if (iupAttribGet(ih, "_IUP_IGNORE_BRANCHOPEN"))
+- {
+- iupAttribSetStr(ih, "_IUP_IGNORE_BRANCHOPEN", NULL);
++ if (iupAttribGet(ih, "_IUP_IGNORE_BRANCH_CB"))
+ return IUP_DEFAULT;
+- }
+ 
+ cbBranchOpen = (IFni)IupGetCallback(ih, "BRANCHOPEN_CB");
+ if (cbBranchOpen)
+- return cbBranchOpen(ih, motTreeGetNodeId(ih, wItem));
++ return cbBranchOpen(ih, iupTreeFindNodeId(ih, wItem));
+ 
+ return IUP_DEFAULT;
+ }
+ 
++static void motTreeFindRange(Ihandle* ih, WidgetList wSelectedItemList, int countItems, int *id1, int *id2)
++{
++ int i = 0, id;
++
++ *id1 = ih->data->node_count;
++ *id2 = -1;
++
++ for(i = 0; i < countItems; i++)
++ {
++ int is_icon = XmIsIconGadget(wSelectedItemList[i]); /* this line generates a warning in some compilers */
++ if (is_icon)
++ {
++ id = iupTreeFindNodeId(ih, wSelectedItemList[i]);
++ if (id < *id1)
++ *id1 = id;
++ if (id > *id2)
++ *id2 = id;
++ }
++ }
++
++ /* interactive selection of several nodes will NOT select hidden nodes,
++ so make sure that they are selected. */
++ for(i = *id1; i <= *id2; i++)
++ {
++ if (!motTreeIsNodeSelected(ih->data->node_cache[i].node_handle))
++ XtVaSetValues(ih->data->node_cache[i].node_handle, XmNvisualEmphasis, XmSELECTED, NULL);
++ }
++
++ /* if last selected item is a branch, then select its children */
++ iupTreeSelectLastCollapsedBranch(ih, id2);
++}
++
++static Iarray* motTreeGetSelectedArrayId(Ihandle* ih, WidgetList wSelectedItemList, int countItems)
++{
++ Iarray* selarray = iupArrayCreate(1, sizeof(int));
++ int i;
++
++ for(i = 0; i < countItems; i++)
++ {
++ int is_icon = XmIsIconGadget(wSelectedItemList[i]); /* this line generates a warning in some compilers */
++ if (is_icon)
++ {
++ int* id_hitem = (int*)iupArrayInc(selarray);
++ int j = iupArrayCount(selarray);
++ id_hitem[j-1] = iupTreeFindNodeId(ih, wSelectedItemList[i]);
++ }
++ }
++
++ return selarray;
++}
++
++static void motTreeCallMultiUnSelectionCb(Ihandle* ih)
++{
++ IFnIi cbMulti = (IFnIi)IupGetCallback(ih, "MULTIUNSELECTION_CB");
++ IFnii cbSelec = (IFnii)IupGetCallback(ih, "SELECTION_CB");
++ if (cbSelec || cbMulti)
++ {
++ WidgetList wSelectedItemList = NULL;
++ int countItems = 0;
++
++ XtVaGetValues(ih->handle, XmNselectedObjects, &wSelectedItemList,
++ XmNselectedObjectCount, &countItems, NULL);
++ if (countItems > 1)
++ {
++ Iarray* markedArray = motTreeGetSelectedArrayId(ih, wSelectedItemList, countItems);
++ int* id_hitem = (int*)iupArrayGetData(markedArray);
++ int i, count = iupArrayCount(markedArray);
++
++ if (cbMulti)
++ cbMulti(ih, id_hitem, iupArrayCount(markedArray));
++ else
++ {
++ for (i=0; i<count; i++)
++ cbSelec(ih, id_hitem[i], 0);
++ }
++
++ iupArrayDestroy(markedArray);
++ }
++ }
++}
++
+ static void motTreeCallMultiSelectionCb(Ihandle* ih)
+ {
+ IFnIi cbMulti = (IFnIi)IupGetCallback(ih, "MULTISELECTION_CB");
+ IFnii cbSelec = (IFnii)IupGetCallback(ih, "SELECTION_CB");
+ WidgetList wSelectedItemList = NULL;
+- Widget wRoot;
+- int countItems;
+-
+- wRoot = (Widget)iupAttribGet(ih, "_IUPTREE_ROOTITEM");
++ int countItems, id1, id2, i;
+ 
+ XtVaGetValues(ih->handle, XmNselectedObjects, &wSelectedItemList,
+ XmNselectedObjectCount, &countItems, NULL);
+ if (countItems == 0)
+ return;
+ 
+- if (cbMulti || cbSelec)
++ /* Must be a continuous range of selection ids */
++ motTreeFindRange(ih, wSelectedItemList, countItems, &id1, &id2);
++ countItems = id2-id1+1;
++
++ if (cbMulti)
+ {
+ int* id_rowItem = malloc(sizeof(int) * countItems);
+- int i = 0;
+ 
+ for(i = 0; i < countItems; i++)
+- id_rowItem[i] = motTreeGetNodeId(ih, wSelectedItemList[i]);
++ id_rowItem[i] = id1+i;
+ 
+- if (cbMulti)
+- cbMulti(ih, id_rowItem, countItems);
+- else
+- {
+- for (i=0; i<countItems; i++)
+- cbSelec(ih, id_rowItem[i], 1);
+- }
++ cbMulti(ih, id_rowItem, countItems);
+ 
+ free(id_rowItem);
+ }
++ else if (cbSelec)
++ {
++ for (i=0; i<countItems; i++)
++ cbSelec(ih, id1+i, 1);
++ }
+ }
+ 
+ static int motTreeConvertXYToPos(Ihandle* ih, int x, int y)
+ {
+ Widget wItem = XmObjectAtPoint(ih->handle, (Position)x, (Position)y);
+ if (wItem)
+- return motTreeGetNodeId(ih, wItem);
++ return iupTreeFindNodeId(ih, wItem);
+ return -1;
+ }
+ 
+@@ -1965,7 +1794,7 @@ static void motTreeCallRenameCb(Ihandle* ih)
+ cbRename = (IFnis)IupGetCallback(ih, "RENAME_CB");
+ if (cbRename)
+ {
+- if (cbRename(ih, motTreeGetNodeId(ih, wItem), title) == IUP_IGNORE)
++ if (cbRename(ih, iupTreeFindNodeId(ih, wItem), title) == IUP_IGNORE)
+ ignore = 1;
+ }
+ 
+@@ -1993,8 +1822,8 @@ static int motTreeCallDragDropCb(Ihandle* ih, Widget wItemDrag, Widget wItemDrop
+ 
+ if (cbDragDrop)
+ {
+- int drag_id = motTreeGetNodeId(ih, wItemDrag);
+- int drop_id = motTreeGetNodeId(ih, wItemDrop);
++ int drag_id = iupTreeFindNodeId(ih, wItemDrag);
++ int drop_id = iupTreeFindNodeId(ih, wItemDrop);
+ return cbDragDrop(ih, drag_id, drop_id, is_shift, *is_ctrl);
+ }
+ 
+@@ -2069,6 +1898,10 @@ static void motTreeShowEditField(Ihandle* ih, Widget wItem)
+ XmFontList fontlist;
+ Widget sb_win = (Widget)iupAttribGet(ih, "_IUP_EXTRAPARENT");
+ 
++ IFni cbShowRename = (IFni)IupGetCallback(ih, "SHOWRENAME_CB");
++ if (cbShowRename && cbShowRename(ih, iupTreeFindNodeId(ih, wItem))==IUP_IGNORE)
++ return;
++
+ XtVaGetValues(wItem, XmNx, &x, 
+ XmNy, &y,
+ XmNwidth, &w, 
+@@ -2083,16 +1916,16 @@ static void motTreeShowEditField(Ihandle* ih, Widget wItem)
+ iupdrvImageGetInfo((void*)image, &w_img, NULL, NULL);
+ w_img += 3; /* add some room for borders */
+ 
+- iupmotSetArg(args, num_args, XmNx, x+w_img); /* x-position */
+- iupmotSetArg(args, num_args, XmNy, y); /* y-position */
+- iupmotSetArg(args, num_args, XmNwidth, w-w_img); /* default width to avoid 0 */
+- iupmotSetArg(args, num_args, XmNheight, h); /* default height to avoid 0 */
+- iupmotSetArg(args, num_args, XmNmarginHeight, ih->data->spacing); /* default padding */
+- iupmotSetArg(args, num_args, XmNmarginWidth, 0);
+- iupmotSetArg(args, num_args, XmNforeground, color);
+- iupmotSetArg(args, num_args, XmNrenderTable, fontlist);
+- iupmotSetArg(args, num_args, XmNvalue, iupmotConvertString(title));
+- iupmotSetArg(args, num_args, XmNtraversalOn, True);
++ iupMOT_SETARG(args, num_args, XmNx, x+w_img); /* x-position */
++ iupMOT_SETARG(args, num_args, XmNy, y); /* y-position */
++ iupMOT_SETARG(args, num_args, XmNwidth, w-w_img); /* default width to avoid 0 */
++ iupMOT_SETARG(args, num_args, XmNheight, h); /* default height to avoid 0 */
++ iupMOT_SETARG(args, num_args, XmNmarginHeight, ih->data->spacing); /* default padding */
++ iupMOT_SETARG(args, num_args, XmNmarginWidth, 0);
++ iupMOT_SETARG(args, num_args, XmNforeground, color);
++ iupMOT_SETARG(args, num_args, XmNrenderTable, fontlist);
++ iupMOT_SETARG(args, num_args, XmNvalue, iupmotConvertString(title));
++ iupMOT_SETARG(args, num_args, XmNtraversalOn, True);
+ 
+ cbEdit = XtCreateManagedWidget(
+ child_id, /* child identifier */
+@@ -2134,8 +1967,6 @@ static void motTreeSelectionCallback(Widget w, Ihandle* ih, XmContainerSelectCal
+ (void)w;
+ (void)nptr;
+ 
+-printf("SelectionCallback(%d)\n", nptr->selected_item_count);
+-
+ if (ih->data->mark_mode == ITREE_MARK_MULTIPLE)
+ {
+ char key[5];
+@@ -2149,11 +1980,13 @@ printf("SelectionCallback(%d)\n", nptr->selected_item_count);
+ {
+ if (IupGetCallback(ih, "MULTISELECTION_CB"))
+ {
++ /* current selection same as the initial selection */
+ if (nptr->auto_selection_type==XmAUTO_NO_CHANGE)
+ motTreeCallMultiSelectionCb(ih);
+ }
+ else
+ {
++ /* current selection is caused by button drag */
+ if (nptr->auto_selection_type==XmAUTO_MOTION)
+ motTreeCallMultiSelectionCb(ih);
+ }
+@@ -2164,14 +1997,10 @@ printf("SelectionCallback(%d)\n", nptr->selected_item_count);
+ cbSelec = (IFnii)IupGetCallback(ih, "SELECTION_CB");
+ if (cbSelec)
+ {
+- Widget wItemFocus = motTreeGetFocusNode(ih);
+- int curpos = motTreeGetNodeId(ih, wItemFocus);
++ Widget wItemFocus = iupdrvTreeGetFocusNode(ih);
++ int curpos = iupTreeFindNodeId(ih, wItemFocus);
+ if (is_ctrl) 
+- {
+- unsigned char isSelected;
+- XtVaGetValues(wItemFocus, XmNvisualEmphasis, &isSelected, NULL);
+- cbSelec(ih, curpos, isSelected == XmSELECTED? 1: 0);
+- }
++ cbSelec(ih, curpos, motTreeIsNodeSelected(wItemFocus));
+ else
+ {
+ int oldpos = iupAttribGetInt(ih, "_IUPTREE_OLDVALUE");
+@@ -2218,7 +2047,7 @@ static void motTreeDefaultActionCallback(Widget w, Ihandle* ih, XmContainerSelec
+ {
+ IFni cbExecuteLeaf = (IFni)IupGetCallback(ih, "EXECUTELEAF_CB");
+ if (cbExecuteLeaf)
+- cbExecuteLeaf(ih, motTreeGetNodeId(ih, wItem));
++ cbExecuteLeaf(ih, iupTreeFindNodeId(ih, wItem));
+ }
+ }
+ 
+@@ -2295,15 +2124,14 @@ static void motTreeKeyPressEvent(Widget w, Ihandle *ih, XKeyEvent *evt, Boolean
+ iupmotHelpCallback(w, ih, NULL);
+ else if ((motcode == XK_Down || motcode == XK_Up) && (evt->state & ControlMask))
+ {
+- Widget wRoot = (Widget)iupAttribGet(ih, "_IUPTREE_ROOTITEM");
+ Widget wItem;
+- Widget wItemFocus = motTreeGetFocusNode(ih);
++ Widget wItemFocus = iupdrvTreeGetFocusNode(ih);
+ 
+ /* Ctrl+Arrows move only focus */
+ if (motcode == XK_Down)
+- wItem = motTreeGetNextVisibleNode(ih, wRoot, wItemFocus);
++ wItem = motTreeGetNextVisibleNode(ih, wItemFocus, 1);
+ else
+- wItem = motTreeGetPreviousVisibleNode(ih, wRoot, wItemFocus);
++ wItem = motTreeGetPreviousVisibleNode(ih, wItemFocus, 1);
+ 
+ motTreeSetFocusNode(ih, wItem);
+ *cont = False;
+@@ -2317,8 +2145,8 @@ static void motTreeKeyPressEvent(Widget w, Ihandle *ih, XKeyEvent *evt, Boolean
+ 
+ if (motcode == XK_Home)
+ wItem = wRoot;
+- else
+- wItem = motTreeGetLastVisibleNode(ih, wRoot);
++ else /* motcode == XK_End */
++ wItem = motTreeGetLastVisibleNode(ih);
+ 
+ /* Ctrl+Arrows move only focus */
+ if (!(evt->state & ControlMask))
+@@ -2326,7 +2154,7 @@ static void motTreeKeyPressEvent(Widget w, Ihandle *ih, XKeyEvent *evt, Boolean
+ /* Shift+Arrows select block */
+ if (evt->state & ShiftMask)
+ {
+- Widget wItemFocus = motTreeGetFocusNode(ih);
++ Widget wItemFocus = iupdrvTreeGetFocusNode(ih);
+ if (!wItemFocus)
+ return;
+ motTreeSelectRange(ih, wItemFocus, wItem, 1);
+@@ -2346,16 +2174,9 @@ static void motTreeKeyPressEvent(Widget w, Ihandle *ih, XKeyEvent *evt, Boolean
+ }
+ else if(motcode == XK_space && (evt->state & ControlMask))
+ {
+- Widget wItemFocus = motTreeGetFocusNode(ih);
++ Widget wItemFocus = iupdrvTreeGetFocusNode(ih);
+ if (wItemFocus)
+- {
+- unsigned char isSelected;
+- XtVaGetValues(wItemFocus, XmNvisualEmphasis, &isSelected, NULL);
+- if (isSelected == XmSELECTED)
+- XtVaSetValues(wItemFocus, XmNvisualEmphasis, XmNOT_SELECTED, NULL);
+- else
+- XtVaSetValues(wItemFocus, XmNvisualEmphasis, XmSELECTED, NULL);
+- }
++ motTreeSelectNode(wItemFocus, -1);
+ }
+ }
+ 
+@@ -2378,7 +2199,7 @@ static void motTreeButtonEvent(Widget w, Ihandle* ih, XButtonEvent* evt, Boolean
+ 
+ if (evt->button==Button1)
+ {
+- Widget wItemFocus = motTreeGetFocusNode(ih);
++ Widget wItemFocus = iupdrvTreeGetFocusNode(ih);
+ static Widget wLastItem = NULL;
+ static Time last = 0;
+ int clicktwice = 0, doubleclicktime = XtGetMultiClickTime(iupmot_display);
+@@ -2395,6 +2216,11 @@ static void motTreeButtonEvent(Widget w, Ihandle* ih, XButtonEvent* evt, Boolean
+ *cont = False;
+ }
+ wLastItem = wItemFocus;
++
++ if (ih->data->mark_mode==ITREE_MARK_MULTIPLE && 
++ !(evt->state & ShiftMask) &&
++ !(evt->state & ControlMask))
++ motTreeCallMultiUnSelectionCb(ih);
+ }
+ else if (evt->button==Button3)
+ motTreeCallRightClickCb(ih, evt->x, evt->y);
+@@ -2436,21 +2262,18 @@ static void motTreeTransferProc(Widget drop_context, XtPointer client_data, Atom
+ 
+ if (motTreeCallDragDropCb(ih, wItemDrag, wItemDrop, &is_ctrl) == IUP_CONTINUE)
+ {
+- /* Copy the dragged item to the new position. */
+- Widget wNewItem = motTreeCopyNode(ih, wItemDrag, wItemDrop, is_ctrl);
++ /* Copy or move the dragged item to the new position. */
++ Widget wItemNew = motTreeCopyMoveNode(ih, wItemDrag, wItemDrop, is_ctrl);
+ 
+- if (!is_ctrl)
++ /* Set focus and selection */
++ if (wItemNew)
+ {
+- /* do not delete the user data, we copy the references in CopyNode */
+- motTreeRemoveNode(ih, wItemDrag, 0);
+- }
+-
+- /* Select the dragged item */
+- XtVaSetValues(ih->handle, XmNselectedObjects, NULL, NULL);
+- XtVaSetValues(ih->handle, XmNselectedObjectCount, 0, NULL);
+- XtVaSetValues(wNewItem, XmNvisualEmphasis, XmSELECTED, NULL);
++ XtVaSetValues(ih->handle, XmNselectedObjects, NULL, NULL);
++ XtVaSetValues(ih->handle, XmNselectedObjectCount, 0, NULL);
++ XtVaSetValues(wItemNew, XmNvisualEmphasis, XmSELECTED, NULL);
+ 
+- motTreeSetFocusNode(ih, wNewItem);
++ motTreeSetFocusNode(ih, wItemNew);
++ }
+ }
+ }
+ 
+@@ -2475,8 +2298,8 @@ static void motTreeDropProc(Widget w, XtPointer client_data, XmDropProcCallbackS
+ drop_context = drop_data->dragContext;
+ 
+ /* retrieve the data targets */
+- iupmotSetArg(args, num_args, XmNexportTargets, &exportTargets);
+- iupmotSetArg(args, num_args, XmNnumExportTargets, &numExportTargets);
++ iupMOT_SETARG(args, num_args, XmNexportTargets, &exportTargets);
++ iupMOT_SETARG(args, num_args, XmNnumExportTargets, &numExportTargets);
+ XtGetValues(drop_context, args, num_args);
+ 
+ for (i = 0; i < (int)numExportTargets; i++) 
+@@ -2495,17 +2318,17 @@ static void motTreeDropProc(Widget w, XtPointer client_data, XmDropProcCallbackS
+ num_args = 0;
+ if ((!found) || (drop_data->dropAction != XmDROP) || (drop_data->operation != XmDROP_COPY && drop_data->operation != XmDROP_MOVE)) 
+ {
+- iupmotSetArg(args, num_args, XmNtransferStatus, XmTRANSFER_FAILURE);
+- iupmotSetArg(args, num_args, XmNnumDropTransfers, 0);
++ iupMOT_SETARG(args, num_args, XmNtransferStatus, XmTRANSFER_FAILURE);
++ iupMOT_SETARG(args, num_args, XmNnumDropTransfers, 0);
+ }
+ else 
+ {
+ /* set up transfer requests for drop site */
+ transferList[0].target = atomTreeItem;
+ transferList[0].client_data = (XtPointer)wItemDrop;
+- iupmotSetArg(args, num_args, XmNdropTransfers, transferList);
+- iupmotSetArg(args, num_args, XmNnumDropTransfers, 1);
+- iupmotSetArg(args, num_args, XmNtransferProc, motTreeTransferProc);
++ iupMOT_SETARG(args, num_args, XmNdropTransfers, transferList);
++ iupMOT_SETARG(args, num_args, XmNnumDropTransfers, 1);
++ iupMOT_SETARG(args, num_args, XmNtransferProc, motTreeTransferProc);
+ }
+ 
+ XmDropTransferStart(drop_context, args, num_args);
+@@ -2584,23 +2407,23 @@ static void motTreeStartDrag(Widget w, XButtonEvent* evt, String* params, Cardin
+ XmNforeground, &fg,
+ NULL);
+ 
+- iupmotSetArg(args, num_args, XmNpixmap, pixmap);
+- iupmotSetArg(args, num_args, XmNmask, mask);
++ iupMOT_SETARG(args, num_args, XmNpixmap, pixmap);
++ iupMOT_SETARG(args, num_args, XmNmask, mask);
+ drag_icon = XmCreateDragIcon(w, "drag_icon", args, num_args);
+ 
+ exportList[0] = atomTreeItem;
+ 
+ /* specify resources for DragContext for the transfer */
+ num_args = 0;
+- iupmotSetArg(args, num_args, XmNcursorBackground, bg);
+- iupmotSetArg(args, num_args, XmNcursorForeground, fg);
+- /* iupmotSetArg(args, num_args, XmNsourcePixmapIcon, drag_icon); works, but only outside the dialog, inside disapears */
+- iupmotSetArg(args, num_args, XmNsourceCursorIcon, drag_icon); /* does not work, shows the default cursor */
+- iupmotSetArg(args, num_args, XmNexportTargets, exportList);
+- iupmotSetArg(args, num_args, XmNnumExportTargets, 1);
+- iupmotSetArg(args, num_args, XmNdragOperations, XmDROP_MOVE|XmDROP_COPY);
+- iupmotSetArg(args, num_args, XmNconvertProc, motTreeConvertProc);
+- iupmotSetArg(args, num_args, XmNclientData, wItemDrag);
++ iupMOT_SETARG(args, num_args, XmNcursorBackground, bg);
++ iupMOT_SETARG(args, num_args, XmNcursorForeground, fg);
++ /* iupMOT_SETARG(args, num_args, XmNsourcePixmapIcon, drag_icon); works, but only outside the dialog, inside disapears */
++ iupMOT_SETARG(args, num_args, XmNsourceCursorIcon, drag_icon); /* does not work, shows the default cursor */
++ iupMOT_SETARG(args, num_args, XmNexportTargets, exportList);
++ iupMOT_SETARG(args, num_args, XmNnumExportTargets, 1);
++ iupMOT_SETARG(args, num_args, XmNdragOperations, XmDROP_MOVE|XmDROP_COPY);
++ iupMOT_SETARG(args, num_args, XmNconvertProc, motTreeConvertProc);
++ iupMOT_SETARG(args, num_args, XmNclientData, wItemDrag);
+ 
+ /* start the drag and register a callback to clean up when done */
+ drop_context = XmDragStart(w, (XEvent*)evt, args, num_args);
+@@ -2628,10 +2451,10 @@ static void motTreeEnableDragDrop(Widget w)
+ XtOverrideTranslations(w, XtParseTranslationTable(dragTranslations));
+ 
+ importList[0] = atomTreeItem;
+- iupmotSetArg(args, num_args, XmNimportTargets, importList);
+- iupmotSetArg(args, num_args, XmNnumImportTargets, 1);
+- iupmotSetArg(args, num_args, XmNdropSiteOperations, XmDROP_MOVE|XmDROP_COPY);
+- iupmotSetArg(args, num_args, XmNdropProc, motTreeDropProc);
++ iupMOT_SETARG(args, num_args, XmNimportTargets, importList);
++ iupMOT_SETARG(args, num_args, XmNnumImportTargets, 1);
++ iupMOT_SETARG(args, num_args, XmNdropSiteOperations, XmDROP_MOVE|XmDROP_COPY);
++ iupMOT_SETARG(args, num_args, XmNdropProc, motTreeDropProc);
+ XmDropSiteUpdate(w, args, num_args);
+ 
+ XtVaSetValues(XmGetXmDisplay(iupmot_display), XmNenableDragIcon, True, NULL);
+@@ -2648,13 +2471,13 @@ static int motTreeMapMethod(Ihandle* ih)
+ /******************************/
+ /* Create the scrolled window */
+ /******************************/
+- iupmotSetArg(args, num_args, XmNmappedWhenManaged, False); /* not visible when managed */
+- iupmotSetArg(args, num_args, XmNscrollingPolicy, XmAUTOMATIC);
+- iupmotSetArg(args, num_args, XmNvisualPolicy, XmVARIABLE); 
+- iupmotSetArg(args, num_args, XmNscrollBarDisplayPolicy, XmAS_NEEDED);
+- iupmotSetArg(args, num_args, XmNspacing, 0); /* no space between scrollbars and text */
+- iupmotSetArg(args, num_args, XmNborderWidth, 0);
+- iupmotSetArg(args, num_args, XmNshadowThickness, 2);
++ iupMOT_SETARG(args, num_args, XmNmappedWhenManaged, False); /* not visible when managed */
++ iupMOT_SETARG(args, num_args, XmNscrollingPolicy, XmAUTOMATIC);
++ iupMOT_SETARG(args, num_args, XmNvisualPolicy, XmVARIABLE); 
++ iupMOT_SETARG(args, num_args, XmNscrollBarDisplayPolicy, XmAS_NEEDED);
++ iupMOT_SETARG(args, num_args, XmNspacing, 0); /* no space between scrollbars and text */
++ iupMOT_SETARG(args, num_args, XmNborderWidth, 0);
++ iupMOT_SETARG(args, num_args, XmNshadowThickness, 2);
+ 
+ sb_win = XtCreateManagedWidget(
+ child_id, /* child identifier */
+@@ -2672,37 +2495,37 @@ static int motTreeMapMethod(Ihandle* ih)
+ 
+ num_args = 0;
+ 
+- iupmotSetArg(args, num_args, XmNx, 0); /* x-position */
+- iupmotSetArg(args, num_args, XmNy, 0); /* y-position */
+- iupmotSetArg(args, num_args, XmNwidth, 10); /* default width to avoid 0 */
+- iupmotSetArg(args, num_args, XmNheight, 10); /* default height to avoid 0 */
++ iupMOT_SETARG(args, num_args, XmNx, 0); /* x-position */
++ iupMOT_SETARG(args, num_args, XmNy, 0); /* y-position */
++ iupMOT_SETARG(args, num_args, XmNwidth, 10); /* default width to avoid 0 */
++ iupMOT_SETARG(args, num_args, XmNheight, 10); /* default height to avoid 0 */
+ 
+- iupmotSetArg(args, num_args, XmNmarginHeight, 0); /* default padding */
+- iupmotSetArg(args, num_args, XmNmarginWidth, 0);
++ iupMOT_SETARG(args, num_args, XmNmarginHeight, 0); /* default padding */
++ iupMOT_SETARG(args, num_args, XmNmarginWidth, 0);
+ 
+ if (iupAttribGetBoolean(ih, "CANFOCUS"))
+- iupmotSetArg(args, num_args, XmNtraversalOn, True);
++ iupMOT_SETARG(args, num_args, XmNtraversalOn, True);
+ else
+- iupmotSetArg(args, num_args, XmNtraversalOn, False);
++ iupMOT_SETARG(args, num_args, XmNtraversalOn, False);
+ 
+- iupmotSetArg(args, num_args, XmNnavigationType, XmTAB_GROUP);
+- iupmotSetArg(args, num_args, XmNhighlightThickness, 2);
+- iupmotSetArg(args, num_args, XmNshadowThickness, 0);
++ iupMOT_SETARG(args, num_args, XmNnavigationType, XmTAB_GROUP);
++ iupMOT_SETARG(args, num_args, XmNhighlightThickness, 2);
++ iupMOT_SETARG(args, num_args, XmNshadowThickness, 0);
+ 
+- iupmotSetArg(args, num_args, XmNlayoutType, XmOUTLINE);
+- iupmotSetArg(args, num_args, XmNentryViewType, XmSMALL_ICON);
+- iupmotSetArg(args, num_args, XmNselectionPolicy, XmSINGLE_SELECT);
+- iupmotSetArg(args, num_args, XmNoutlineIndentation, 20);
++ iupMOT_SETARG(args, num_args, XmNlayoutType, XmOUTLINE);
++ iupMOT_SETARG(args, num_args, XmNentryViewType, XmSMALL_ICON);
++ iupMOT_SETARG(args, num_args, XmNselectionPolicy, XmSINGLE_SELECT);
++ iupMOT_SETARG(args, num_args, XmNoutlineIndentation, 20);
+ 
+ if (iupAttribGetBoolean(ih, "HIDELINES"))
+- iupmotSetArg(args, num_args, XmNoutlineLineStyle, XmNO_LINE);
++ iupMOT_SETARG(args, num_args, XmNoutlineLineStyle, XmNO_LINE);
+ else
+- iupmotSetArg(args, num_args, XmNoutlineLineStyle, XmSINGLE);
++ iupMOT_SETARG(args, num_args, XmNoutlineLineStyle, XmSINGLE);
+ 
+ if (iupAttribGetBoolean(ih, "HIDEBUTTONS"))
+- iupmotSetArg(args, num_args, XmNoutlineButtonPolicy, XmOUTLINE_BUTTON_ABSENT);
++ iupMOT_SETARG(args, num_args, XmNoutlineButtonPolicy, XmOUTLINE_BUTTON_ABSENT);
+ else
+- iupmotSetArg(args, num_args, XmNoutlineButtonPolicy, XmOUTLINE_BUTTON_PRESENT);
++ iupMOT_SETARG(args, num_args, XmNoutlineButtonPolicy, XmOUTLINE_BUTTON_PRESENT);
+ 
+ ih->handle = XtCreateManagedWidget(
+ child_id, /* child identifier */
+@@ -2788,17 +2611,30 @@ static int motTreeMapMethod(Ihandle* ih)
+ if (!ih->data->def_image_expanded_mask) ih->data->def_image_expanded_mask = (void*)XmUNSPECIFIED_PIXMAP;
+ }
+ 
+- motTreeAddRootNode(ih);
++ if (iupAttribGetInt(ih, "ADDROOT"))
++ iupdrvTreeAddNode(ih, "-1", ITREE_BRANCH, "", 0);
+ 
+ IupSetCallback(ih, "_IUP_XY2POS_CB", (Icallback)motTreeConvertXYToPos);
+ 
++ iupdrvTreeUpdateMarkMode(ih);
++
+ return IUP_NOERROR;
+ }
+ 
++static void motTreeUnMapMethod(Ihandle* ih)
++{
++ motTreeRemoveAllNodes(ih, 0);
++
++ ih->data->node_count = 0;
++
++ iupdrvBaseUnMapMethod(ih);
++}
++
+ void iupdrvTreeInitClass(Iclass* ic)
+ {
+ /* Driver Dependent Class functions */
+ ic->Map = motTreeMapMethod;
++ ic->UnMap = motTreeUnMapMethod;
+ 
+ /* Visual */
+ iupClassRegisterAttribute(ic, "BGCOLOR", NULL, motTreeSetBgColorAttrib, "TXTBGCOLOR", NULL, IUPAF_DEFAULT);
+@@ -2807,7 +2643,6 @@ void iupdrvTreeInitClass(Iclass* ic)
+ /* IupTree Attributes - GENERAL */
+ iupClassRegisterAttribute(ic, "EXPANDALL", NULL, motTreeSetExpandAllAttrib, NULL, NULL, IUPAF_WRITEONLY||IUPAF_NO_INHERIT);
+ iupClassRegisterAttribute(ic, "INDENTATION", motTreeGetIndentationAttrib, motTreeSetIndentationAttrib, NULL, NULL, IUPAF_DEFAULT);
+- iupClassRegisterAttribute(ic, "COUNT", motTreeGetCountAttrib, NULL, NULL, NULL, IUPAF_NO_DEFAULTVALUE|IUPAF_READONLY|IUPAF_NO_INHERIT);
+ iupClassRegisterAttribute(ic, "SPACING", iupTreeGetSpacingAttrib, motTreeSetSpacingAttrib, NULL, NULL, IUPAF_NOT_MAPPED);
+ iupClassRegisterAttribute(ic, "TOPITEM", NULL, motTreeSetTopItemAttrib, NULL, NULL, IUPAF_WRITEONLY|IUPAF_NO_INHERIT);
+ 
+@@ -2827,7 +2662,6 @@ void iupdrvTreeInitClass(Iclass* ic)
+ iupClassRegisterAttributeId(ic, "COLOR", motTreeGetColorAttrib, motTreeSetColorAttrib, IUPAF_NO_INHERIT);
+ iupClassRegisterAttributeId(ic, "NAME", motTreeGetTitleAttrib, motTreeSetTitleAttrib, IUPAF_NO_INHERIT);
+ iupClassRegisterAttributeId(ic, "TITLE", motTreeGetTitleAttrib, motTreeSetTitleAttrib, IUPAF_NO_INHERIT);
+- iupClassRegisterAttributeId(ic, "USERDATA", motTreeGetUserDataAttrib, motTreeSetUserDataAttrib, IUPAF_NO_STRING|IUPAF_NO_INHERIT);
+ iupClassRegisterAttributeId(ic, "CHILDCOUNT", motTreeGetChildCountAttrib, NULL, IUPAF_READONLY|IUPAF_NO_INHERIT);
+ iupClassRegisterAttributeId(ic, "TITLEFONT", motTreeGetTitleFontAttrib, motTreeSetTitleFontAttrib, IUPAF_NO_INHERIT);
+ 
+@@ -2836,6 +2670,7 @@ void iupdrvTreeInitClass(Iclass* ic)
+ iupClassRegisterAttribute (ic, "MARK", NULL, motTreeSetMarkAttrib, NULL, NULL, IUPAF_WRITEONLY|IUPAF_NO_INHERIT);
+ iupClassRegisterAttribute (ic, "STARTING", NULL, motTreeSetMarkStartAttrib, NULL, NULL, IUPAF_NO_DEFAULTVALUE|IUPAF_NO_INHERIT);
+ iupClassRegisterAttribute (ic, "MARKSTART", NULL, motTreeSetMarkStartAttrib, NULL, NULL, IUPAF_NO_DEFAULTVALUE|IUPAF_NO_INHERIT);
++ iupClassRegisterAttribute (ic, "MARKEDNODES", motTreeGetMarkedNodesAttrib, motTreeSetMarkedNodesAttrib, NULL, NULL, IUPAF_NO_DEFAULTVALUE|IUPAF_NO_INHERIT);
+ 
+ iupClassRegisterAttribute (ic, "VALUE", motTreeGetValueAttrib, motTreeSetValueAttrib, NULL, NULL, IUPAF_NO_DEFAULTVALUE|IUPAF_NO_INHERIT);
+ 
+@@ -2844,5 +2679,4 @@ void iupdrvTreeInitClass(Iclass* ic)
+ iupClassRegisterAttribute(ic, "RENAME", NULL, motTreeSetRenameAttrib, NULL, NULL, IUPAF_WRITEONLY|IUPAF_NO_INHERIT);
+ iupClassRegisterAttributeId(ic, "MOVENODE", NULL, motTreeSetMoveNodeAttrib, IUPAF_NOT_MAPPED|IUPAF_WRITEONLY|IUPAF_NO_INHERIT);
+ iupClassRegisterAttributeId(ic, "COPYNODE", NULL, motTreeSetCopyNodeAttrib, IUPAF_NOT_MAPPED|IUPAF_WRITEONLY|IUPAF_NO_INHERIT);
+- iupClassRegisterAttributeId(ic, "FINDUSERDATA", motTreeGetFindUserDataAttrib, NULL, IUPAF_READONLY|IUPAF_NO_INHERIT);
+ }
+diff --git a/iup/src/mot/iupmot_val.c b/iup/src/mot/iupmot_val.c
+index 200d2b4..ce9eba7 100755
+--- a/iup/src/mot/iupmot_val.c
++++ b/iup/src/mot/iupmot_val.c
+@@ -383,41 +383,41 @@ static int motValMapMethod(Ihandle* ih)
+ int show_ticks;
+ 
+ /* Core */
+- iupmotSetArg(args, num_args, XmNmappedWhenManaged, False); /* not visible when managed */
+- iupmotSetArg(args, num_args, XmNx, 0); /* x-position */
+- iupmotSetArg(args, num_args, XmNy, 0); /* y-position */
+- iupmotSetArg(args, num_args, XmNwidth, 10); /* default width to avoid 0 */
+- iupmotSetArg(args, num_args, XmNheight, 10); /* default height to avoid 0 */
++ iupMOT_SETARG(args, num_args, XmNmappedWhenManaged, False); /* not visible when managed */
++ iupMOT_SETARG(args, num_args, XmNx, 0); /* x-position */
++ iupMOT_SETARG(args, num_args, XmNy, 0); /* y-position */
++ iupMOT_SETARG(args, num_args, XmNwidth, 10); /* default width to avoid 0 */
++ iupMOT_SETARG(args, num_args, XmNheight, 10); /* default height to avoid 0 */
+ /* Primitive */
+ if (iupAttribGetBoolean(ih, "CANFOCUS"))
+- iupmotSetArg(args, num_args, XmNtraversalOn, True);
++ iupMOT_SETARG(args, num_args, XmNtraversalOn, True);
+ else
+- iupmotSetArg(args, num_args, XmNtraversalOn, False);
+- iupmotSetArg(args, num_args, XmNhighlightThickness, 2);
+- iupmotSetArg(args, num_args, XmNnavigationType, XmTAB_GROUP);
++ iupMOT_SETARG(args, num_args, XmNtraversalOn, False);
++ iupMOT_SETARG(args, num_args, XmNhighlightThickness, 2);
++ iupMOT_SETARG(args, num_args, XmNnavigationType, XmTAB_GROUP);
+ /* Scale */
+- iupmotSetArg(args, num_args, XmNminimum, 0);
+- iupmotSetArg(args, num_args, XmNmaximum, SHRT_MAX);
+- iupmotSetArg(args, num_args, XmNslidingMode, XmSLIDER);
+- iupmotSetArg(args, num_args, XmNsliderMark, XmETCHED_LINE);
+- iupmotSetArg(args, num_args, XmNsliderSize, 16);
+- iupmotSetArg(args, num_args, XmNshowValue, XmNONE);
++ iupMOT_SETARG(args, num_args, XmNminimum, 0);
++ iupMOT_SETARG(args, num_args, XmNmaximum, SHRT_MAX);
++ iupMOT_SETARG(args, num_args, XmNslidingMode, XmSLIDER);
++ iupMOT_SETARG(args, num_args, XmNsliderMark, XmETCHED_LINE);
++ iupMOT_SETARG(args, num_args, XmNsliderSize, 16);
++ iupMOT_SETARG(args, num_args, XmNshowValue, XmNONE);
+ 
+ if (ih->data->type == IVAL_HORIZONTAL)
+ {
+- iupmotSetArg(args, num_args, XmNorientation, XmHORIZONTAL);
++ iupMOT_SETARG(args, num_args, XmNorientation, XmHORIZONTAL);
+ if (ih->data->inverted)
+- iupmotSetArg(args, num_args, XmNprocessingDirection, XmMAX_ON_LEFT);
++ iupMOT_SETARG(args, num_args, XmNprocessingDirection, XmMAX_ON_LEFT);
+ else
+- iupmotSetArg(args, num_args, XmNprocessingDirection, XmMAX_ON_RIGHT);
++ iupMOT_SETARG(args, num_args, XmNprocessingDirection, XmMAX_ON_RIGHT);
+ }
+ else
+ {
+- iupmotSetArg(args, num_args, XmNorientation, XmVERTICAL);
++ iupMOT_SETARG(args, num_args, XmNorientation, XmVERTICAL);
+ if (ih->data->inverted)
+- iupmotSetArg(args, num_args, XmNprocessingDirection, XmMAX_ON_TOP);
++ iupMOT_SETARG(args, num_args, XmNprocessingDirection, XmMAX_ON_TOP);
+ else
+- iupmotSetArg(args, num_args, XmNprocessingDirection, XmMAX_ON_BOTTOM);
++ iupMOT_SETARG(args, num_args, XmNprocessingDirection, XmMAX_ON_BOTTOM);
+ }
+ 
+ ih->handle = XtCreateManagedWidget(
+diff --git a/iup/src/mot/iupunix_info.c b/iup/src/mot/iupunix_info.c
+index b522638..f09573c 100755
+--- a/iup/src/mot/iupunix_info.c
++++ b/iup/src/mot/iupunix_info.c
+@@ -282,7 +282,7 @@ char *iupdrvGetSystemName(void)
+ char *iupdrvGetSystemVersion(void)
+ {
+ struct utsname un;
+- char *str = iupStrGetMemory(60); 
++ char *str = iupStrGetMemory(100); 
+ 
+ uname(&un);
+ strcpy(str, un.release);
+diff --git a/iup/src/win/iupwin_button.c b/iup/src/win/iupwin_button.c
+index 7f780e3..3b05ba7 100755
+--- a/iup/src/win/iupwin_button.c
++++ b/iup/src/win/iupwin_button.c
+@@ -27,6 +27,7 @@
+ #include "iupwin_drv.h"
+ #include "iupwin_handle.h"
+ #include "iupwin_draw.h"
++#include "iupwin_info.h"
+ 
+ 
+ #ifndef CDIS_SHOWKEYBOARDCUES
+@@ -308,18 +309,22 @@ static void winButtonDrawText(Ihandle* ih, HDC hDC, int rect_width, int rect_hei
+ 
+ static void winButtonDrawItem(Ihandle* ih, DRAWITEMSTRUCT *drawitem)
+ { 
++ HDC hDC;
+ iupwinBitmapDC bmpDC;
+ int border, draw_border;
+ int width = drawitem->rcItem.right - drawitem->rcItem.left;
+ int height = drawitem->rcItem.bottom - drawitem->rcItem.top;
+ 
+- HDC hDC = iupwinDrawCreateBitmapDC(&bmpDC, drawitem->hDC, width, height);
++ hDC = iupwinDrawCreateBitmapDC(&bmpDC, drawitem->hDC, width, height);
+ 
+ iupwinDrawParentBackground(ih, hDC, &drawitem->rcItem);
+ 
+ if ((drawitem->itemState & ODS_FOCUS) && !(drawitem->itemState & ODS_HOTLIGHT))
+ drawitem->itemState |= ODS_DEFAULT;
+ 
++ if (iupAttribGet(ih, "_IUPWINBUT_SELECTED"))
++ drawitem->itemState |= ODS_SELECTED;
++
+ border = winButtonGetBorder();
+ 
+ if (ih->data->type & IUP_BUTTON_IMAGE && iupAttribGet(ih, "IMPRESS") && !iupAttribGetStr(ih, "IMPRESSBORDER"))
+@@ -365,7 +370,7 @@ static int winButtonSetImageAttrib(Ihandle* ih, const char* value)
+ (void)value;
+ if (ih->data->type != IUP_BUTTON_TEXT)
+ {
+- iupdrvDisplayUpdate(ih);
++ iupdrvPostRedraw(ih);
+ return 1;
+ }
+ else
+@@ -377,7 +382,7 @@ static int winButtonSetImInactiveAttrib(Ihandle* ih, const char* value)
+ (void)value;
+ if (ih->data->type != IUP_BUTTON_TEXT)
+ {
+- iupdrvDisplayUpdate(ih);
++ iupdrvPostRedraw(ih);
+ return 1;
+ }
+ else
+@@ -389,7 +394,7 @@ static int winButtonSetImPressAttrib(Ihandle* ih, const char* value)
+ (void)value;
+ if (ih->data->type != IUP_BUTTON_TEXT)
+ {
+- iupdrvDisplayUpdate(ih);
++ iupdrvPostRedraw(ih);
+ return 1;
+ }
+ else
+@@ -400,7 +405,7 @@ static int winButtonSetActiveAttrib(Ihandle* ih, const char* value)
+ {
+ /* redraw IMINACTIVE image if any */
+ if (ih->data->type != IUP_BUTTON_TEXT)
+- iupdrvDisplayUpdate(ih);
++ iupdrvPostRedraw(ih);
+ 
+ return iupBaseSetActiveAttrib(ih, value);
+ }
+@@ -425,7 +430,7 @@ static int winButtonSetAlignmentAttrib(Ihandle* ih, const char* value)
+ else /* "ACENTER" */
+ ih->data->vert_alignment = IUP_ALIGN_ACENTER;
+ 
+- iupdrvDisplayRedraw(ih);
++ iupdrvRedrawNow(ih);
+ 
+ return 1;
+ }
+@@ -443,7 +448,7 @@ static int winButtonSetPaddingAttrib(Ihandle* ih, const char* value)
+ {
+ iupStrToIntInt(value, &ih->data->horiz_padding, &ih->data->vert_padding, 'x');
+ if (ih->handle)
+- iupdrvDisplayRedraw(ih);
++ iupdrvRedrawNow(ih);
+ return 0;
+ }
+ 
+@@ -454,7 +459,7 @@ static int winButtonSetBgColorAttrib(Ihandle* ih, const char* value)
+ {
+ iupAttribSetStr(ih, "BGCOLOR", value);
+ iupImageUpdateParent(ih);
+- iupdrvDisplayRedraw(ih);
++ iupdrvRedrawNow(ih);
+ }
+ return 1;
+ }
+@@ -486,7 +491,9 @@ static int winButtonSetFgColorAttrib(Ihandle* ih, const char* value)
+ if (iupStrToRGB(value, &r, &g, &b))
+ {
+ ih->data->fgcolor = RGB(r,g,b);
+- iupdrvDisplayRedraw(ih);
++
++ if (ih->handle)
++ iupdrvRedrawNow(ih);
+ }
+ return 1;
+ }
+@@ -499,7 +506,7 @@ static int winButtonProc(Ihandle* ih, UINT msg, WPARAM wp, LPARAM lp, LRESULT *r
+ {
+ /* redraw IMPRESS image if any */
+ if ((msg == WM_LBUTTONDOWN || msg == WM_LBUTTONUP) && iupAttribGet(ih, "IMPRESS"))
+- iupdrvDisplayRedraw(ih);
++ iupdrvRedrawNow(ih);
+ }
+ 
+ switch (msg)
+@@ -514,6 +521,13 @@ static int winButtonProc(Ihandle* ih, UINT msg, WPARAM wp, LPARAM lp, LRESULT *r
+ case WM_RBUTTONDOWN:
+ {
+ iupwinButtonDown(ih, msg, wp, lp);
++
++ /* Feedback will NOT be done when not receiving the focus */
++ if (msg==WM_LBUTTONDOWN && !iupAttribGetBoolean(ih, "FOCUSONCLICK"))
++ {
++ iupAttribSetStr(ih, "_IUPWINBUT_SELECTED", "1");
++ iupdrvRedrawNow(ih);
++ }
+ break;
+ }
+ case WM_XBUTTONUP:
+@@ -526,11 +540,24 @@ static int winButtonProc(Ihandle* ih, UINT msg, WPARAM wp, LPARAM lp, LRESULT *r
+ /* BN_CLICKED will NOT be notified when not receiving the focus */
+ if (msg==WM_LBUTTONUP && !iupAttribGetBoolean(ih, "FOCUSONCLICK"))
+ {
+- Icallback cb = IupGetCallback(ih, "ACTION");
++ Icallback cb;
++
++ iupAttribSetStr(ih, "_IUPWINBUT_SELECTED", NULL);
++ iupdrvRedrawNow(ih);
++
++ cb = IupGetCallback(ih, "ACTION");
+ if (cb && cb(ih) == IUP_CLOSE)
+ IupExitLoop();
+ }
+ 
++ if (!iupwinIsVistaOrNew())
++ {
++ /* TIPs desapear forever after a button click in XP,
++ so we force an update. */
++ char* tip = iupAttribGet(ih, "TIP");
++ if (tip)
++ iupdrvBaseSetTipAttrib(ih, tip);
++ }
+ break;
+ }
+ case WM_KEYDOWN:
+@@ -549,7 +576,12 @@ static int winButtonProc(Ihandle* ih, UINT msg, WPARAM wp, LPARAM lp, LRESULT *r
+ if (!iupwin_comctl32ver6)
+ {
+ iupAttribSetStr(ih, "_IUPWINBUT_ENTERWIN", NULL);
+- iupdrvDisplayRedraw(ih);
++ iupdrvRedrawNow(ih);
++ }
++ if (!iupAttribGetBoolean(ih, "FOCUSONCLICK"))
++ {
++ iupAttribSetStr(ih, "_IUPWINBUT_SELECTED", NULL);
++ iupdrvRedrawNow(ih);
+ }
+ break;
+ case WM_MOUSEMOVE:
+@@ -558,7 +590,7 @@ static int winButtonProc(Ihandle* ih, UINT msg, WPARAM wp, LPARAM lp, LRESULT *r
+ if (!iupAttribGet(ih, "_IUPWINBUT_ENTERWIN"))
+ {
+ iupAttribSetStr(ih, "_IUPWINBUT_ENTERWIN", "1");
+- iupdrvDisplayRedraw(ih);
++ iupdrvRedrawNow(ih);
+ }
+ }
+ break;
+@@ -635,7 +667,7 @@ static int winButtonWmCommand(Ihandle* ih, WPARAM wp, LPARAM lp)
+ static int winButtonMapMethod(Ihandle* ih)
+ {
+ char* value;
+- DWORD dwStyle = WS_CHILD | 
++ DWORD dwStyle = WS_CHILD | WS_CLIPSIBLINGS |
+ BS_NOTIFY; /* necessary because of the base messages */
+ 
+ if (!ih->parent)
+@@ -661,7 +693,7 @@ static int winButtonMapMethod(Ihandle* ih)
+ ih->data->type = IUP_BUTTON_IMAGE;
+ 
+ value = iupAttribGet(ih, "TITLE");
+- if (value)
++ if (value && *value!=0)
+ ih->data->type |= IUP_BUTTON_TEXT;
+ }
+ else
+diff --git a/iup/src/win/iupwin_canvas.c b/iup/src/win/iupwin_canvas.c
+index bb88b8a..b865160 100755
+--- a/iup/src/win/iupwin_canvas.c
++++ b/iup/src/win/iupwin_canvas.c
+@@ -45,7 +45,7 @@ static void winCanvasSetScrollInfo(HWND hWnd, int imin, int imax, int ipos, int
+ static int winCanvasSetBgColorAttrib(Ihandle *ih, const char *value)
+ {
+ (void)value;
+- iupdrvDisplayUpdate(ih);
++ iupdrvPostRedraw(ih);
+ return 1;
+ }
+ 
+@@ -220,7 +220,7 @@ static void winCanvasUpdateHorScroll(Ihandle* ih, WORD winop)
+ xmax = iupAttribGetFloat(ih,"XMAX");
+ xmin = iupAttribGetFloat(ih,"XMIN");
+ 
+- winCanvasGetScrollInfo(ih->handle, &iposx, &ipagex, SB_HORZ, winop==SB_THUMBTRACK? 1: 0);
++ winCanvasGetScrollInfo(ih->handle, &iposx, &ipagex, SB_HORZ, winop==SB_THUMBTRACK||winop==SB_THUMBPOSITION? 1: 0);
+ 
+ if (!iupAttribGet(ih,"LINEX"))
+ {
+@@ -296,7 +296,7 @@ static void winCanvasUpdateVerScroll(Ihandle* ih, WORD winop)
+ ymax = iupAttribGetFloat(ih,"YMAX");
+ ymin = iupAttribGetFloat(ih,"YMIN");
+ 
+- winCanvasGetScrollInfo(ih->handle, &iposy, &ipagey, SB_VERT, winop==SB_THUMBTRACK? 1: 0);
++ winCanvasGetScrollInfo(ih->handle, &iposy, &ipagey, SB_VERT, winop==SB_THUMBTRACK||winop==SB_THUMBPOSITION? 1: 0);
+ 
+ if (!iupAttribGet(ih, "LINEY"))
+ {
+@@ -372,6 +372,10 @@ static int winCanvasProc(Ihandle* ih, UINT msg, WPARAM wp, LPARAM lp, LRESULT *r
+ GetClientRect(ih->handle, &rect); 
+ FillRect(hdc, &rect, iupwinBrushGet(color)); 
+ }
++ else
++ InvalidateRect(ih->handle,NULL,FALSE); /* This will invalidate all area. 
++ Necessary in XP, or overlapping windows will have the effect of partial redrawing. */
++
+ /* always return non zero value */
+ *result = 1;
+ return 1; 
+@@ -382,7 +386,7 @@ static int winCanvasProc(Ihandle* ih, UINT msg, WPARAM wp, LPARAM lp, LRESULT *r
+ {
+ PAINTSTRUCT ps;
+ HDC hdc = BeginPaint(ih->handle, &ps);
+- iupAttribSetStr(ih, "HDC_WMPAINT", (char*)&hdc);
++ iupAttribSetStr(ih, "HDC_WMPAINT", (char*)hdc);
+ iupAttribSetStrf(ih, "CLIPRECT", "%d %d %d %d", ps.rcPaint.left, ps.rcPaint.top, ps.rcPaint.right-ps.rcPaint.left, ps.rcPaint.bottom-ps.rcPaint.top);
+ 
+ cb(ih, ih->data->posx, ih->data->posy);
+@@ -542,27 +546,13 @@ static int winCanvasProc(Ihandle* ih, UINT msg, WPARAM wp, LPARAM lp, LRESULT *r
+ return iupwinBaseProc(ih, msg, wp, lp, result);
+ }
+ 
+-static void winCanvasRegisterClass(void)
+-{
+- WNDCLASS wndclass;
+- ZeroMemory(&wndclass, sizeof(WNDCLASS));
+- 
+- wndclass.hInstance = iupwin_hinstance;
+- wndclass.lpszClassName = "IupCanvas";
+- wndclass.lpfnWndProc = (WNDPROC)iupwinBaseWinProc;
+- wndclass.hCursor = LoadCursor(NULL, IDC_ARROW);
+- wndclass.style = CS_DBLCLKS | CS_OWNDC | CS_HREDRAW | CS_VREDRAW; /* using CS_OWNDC will minimize the work of cdActivate in the CD library */
+- wndclass.hbrBackground = NULL; /* remove the background to optimize redraw */
+- 
+- RegisterClass(&wndclass);
+-}
+-
+ static int winCanvasMapMethod(Ihandle* ih)
+ {
+ CLIENTCREATESTRUCT clientstruct;
+ void *clientdata = NULL;
+ char *classname;
+- DWORD dwStyle = WS_CHILD, dwExStyle = 0;
++ DWORD dwStyle = WS_CHILD|WS_CLIPSIBLINGS, 
++ dwExStyle = 0;
+ 
+ if (!ih->parent)
+ return IUP_ERROR;
+@@ -574,14 +564,7 @@ static int winCanvasMapMethod(Ihandle* ih)
+ }
+ 
+ if (ih->firstchild) /* can be a container */
+- {
+- dwStyle |= WS_CLIPSIBLINGS;
+-
+- if (iupAttribGetBoolean(IupGetDialog(ih), "COMPOSITED"))
+- dwExStyle |= WS_EX_COMPOSITED;
+- else
+- dwStyle |= WS_CLIPCHILDREN;
+- }
++ iupwinGetNativeParentStyle(ih, &dwExStyle, &dwStyle);
+ 
+ if (iupAttribGetBoolean(ih, "MDICLIENT")) 
+ {
+@@ -693,6 +676,21 @@ static void winCanvasReleaseMethod(Iclass* ic)
+ UnregisterClass("IupCanvas", iupwin_hinstance);
+ }
+ 
++static void winCanvasRegisterClass(void)
++{
++ WNDCLASS wndclass;
++ ZeroMemory(&wndclass, sizeof(WNDCLASS));
++ 
++ wndclass.hInstance = iupwin_hinstance;
++ wndclass.lpszClassName = "IupCanvas";
++ wndclass.lpfnWndProc = (WNDPROC)iupwinBaseWinProc;
++ wndclass.hCursor = LoadCursor(NULL, IDC_ARROW);
++ wndclass.style = CS_DBLCLKS | CS_OWNDC | CS_HREDRAW | CS_VREDRAW; /* using CS_OWNDC will minimize the work of cdActivate in the CD library */
++ wndclass.hbrBackground = NULL; /* remove the background to optimize redraw */
++ 
++ RegisterClass(&wndclass);
++}
++
+ void iupdrvCanvasInitClass(Iclass* ic)
+ {
+ if (!iupwinClassExist("IupCanvas"))
+diff --git a/iup/src/win/iupwin_common.c b/iup/src/win/iupwin_common.c
+index a1a7c0f..ba68b78 100755
+--- a/iup/src/win/iupwin_common.c
++++ b/iup/src/win/iupwin_common.c
+@@ -94,16 +94,17 @@ void iupdrvBaseLayoutUpdateMethod(Ihandle *ih)
+ SWP_NOZORDER|SWP_NOACTIVATE|SWP_NOOWNERZORDER);
+ }
+ 
+-void iupdrvDisplayRedraw(Ihandle *ih)
++void iupdrvRedrawNow(Ihandle *ih)
+ {
+ /* REDRAW Now */
+- RedrawWindow(ih->handle,NULL,NULL,RDW_ERASE|RDW_INVALIDATE|RDW_INTERNALPAINT|RDW_NOCHILDREN|RDW_UPDATENOW);
++ RedrawWindow(ih->handle,NULL,NULL,RDW_ERASE|RDW_INVALIDATE|RDW_INTERNALPAINT|RDW_UPDATENOW);
+ }
+ 
+-void iupdrvDisplayUpdate(Ihandle *ih)
++void iupdrvPostRedraw(Ihandle *ih)
+ {
+ /* Post a REDRAW */
+- RedrawWindow(ih->handle,NULL,NULL,RDW_ERASE|RDW_INVALIDATE|RDW_INTERNALPAINT|RDW_NOCHILDREN);
++ /* can NOT use RDW_NOCHILDREN because IupList has internal children that needs to be redraw */
++ RedrawWindow(ih->handle,NULL,NULL,RDW_ERASE|RDW_INVALIDATE|RDW_INTERNALPAINT); 
+ }
+ 
+ void iupdrvScreenToClient(Ihandle* ih, int *x, int *y)
+@@ -534,6 +535,8 @@ int iupdrvBaseSetZorderAttrib(Ihandle* ih, const char* value)
+ 
+ void iupdrvSetVisible(Ihandle* ih, int visible)
+ {
++ if (iupStrEqual(ih->iclass->name, "colorbar"))
++ ih=ih;
+ ShowWindow(ih->handle, visible? SW_SHOWNORMAL: SW_HIDE);
+ }
+ 
+@@ -618,6 +621,18 @@ char* iupdrvBaseGetClientSizeAttrib(Ihandle* ih)
+ #define IDC_HELP MAKEINTRESOURCE(32651)
+ #endif
+ 
++static HCURSOR winLoadComCtlCursor(LPCTSTR lpCursorName)
++{
++ HCURSOR cur = NULL;
++ HINSTANCE hinstDll = LoadLibrary("comctl32.dll");
++ if (hinstDll)
++ {
++ cur = LoadCursor(hinstDll, lpCursorName);
++ FreeLibrary(hinstDll);
++ }
++ return cur;
++}
++
+ static HCURSOR winGetCursor(Ihandle* ih, const char* name)
+ {
+ static struct {
+@@ -649,7 +664,7 @@ static HCURSOR winGetCursor(Ihandle* ih, const char* name)
+ {"APPSTARTING", IDC_APPSTARTING}
+ };
+ 
+- HCURSOR cur;
++ HCURSOR cur = NULL;
+ char str[50];
+ int i, count = sizeof(table)/sizeof(table[0]);
+ 
+@@ -676,14 +691,22 @@ static HCURSOR winGetCursor(Ihandle* ih, const char* name)
+ if (i == count)
+ {
+ /* check other system cursors */
+- /* cursor PEN is handled here */
++
+ if (iupStrEqualNoCase(name, "PEN"))
+- name = "CURSOR_PEN";
++ name = "CURSOR_PEN"; /* name in "iup.rc" */
+ 
+ /* check for an name defined cursor */
+ cur = iupImageGetCursor(name);
+ }
+ 
++ if (!cur)
++ {
++ if (iupStrEqualNoCase(name, "SPLITTER_VERT"))
++ cur = winLoadComCtlCursor(MAKEINTRESOURCE(107));
++ else if (iupStrEqualNoCase(name, "SPLITTER_HORIZ"))
++ cur = winLoadComCtlCursor(MAKEINTRESOURCE(135));
++ }
++
+ iupAttribSetStr(ih, str, (char*)cur);
+ return cur;
+ }
+@@ -758,29 +781,29 @@ int iupwinButtonUp(Ihandle* ih, UINT msg, WPARAM wp, LPARAM lp)
+ if (msg==WM_LBUTTONUP)
+ {
+ b = IUP_BUTTON1;
+- iupKEYSETBUTTON1(status); 
++ iupKEY_SETBUTTON1(status); 
+ }
+ else if (msg==WM_MBUTTONUP)
+ {
+ b = IUP_BUTTON2;
+- iupKEYSETBUTTON2(status);
++ iupKEY_SETBUTTON2(status);
+ }
+ else if (msg==WM_RBUTTONUP)
+ {
+ b = IUP_BUTTON3;
+- iupKEYSETBUTTON3(status);
++ iupKEY_SETBUTTON3(status);
+ }
+ else if (msg==WM_XBUTTONUP)
+ {
+ if (HIWORD(wp) == XBUTTON1)
+ {
+ b = IUP_BUTTON4;
+- iupKEYSETBUTTON4(status);
++ iupKEY_SETBUTTON4(status);
+ }
+ else
+ {
+ b = IUP_BUTTON5;
+- iupKEYSETBUTTON5(status);
++ iupKEY_SETBUTTON5(status);
+ }
+ }
+ 
+@@ -807,6 +830,14 @@ int iupwinMouseMove(Ihandle* ih, UINT msg, WPARAM wp, LPARAM lp)
+ return 0;
+ }
+ 
++void iupwinGetNativeParentStyle(Ihandle* ih, DWORD *dwExStyle, DWORD *dwStyle)
++{
++ *dwStyle |= WS_CLIPCHILDREN;
++
++ if (iupAttribGetBoolean(IupGetDialog(ih), "COMPOSITED"))
++ *dwExStyle |= WS_EX_COMPOSITED;
++}
++
+ int iupwinCreateWindowEx(Ihandle* ih, LPCSTR lpClassName, DWORD dwExStyle, DWORD dwStyle)
+ {
+ ih->serial = iupDialogGetChildId(ih);
+diff --git a/iup/src/win/iupwin_dialog.c b/iup/src/win/iupwin_dialog.c
+index 39fdc0c..c13b88d 100755
+--- a/iup/src/win/iupwin_dialog.c
++++ b/iup/src/win/iupwin_dialog.c
+@@ -102,9 +102,9 @@ void iupdrvDialogGetDecoration(Ihandle* ih, int *border, int *caption, int *menu
+ else
+ {
+ int has_titlebar = iupAttribGetBoolean(ih, "MAXBOX") ||
+- iupAttribGetBoolean(ih, "MINBOX") ||
+- iupAttribGetBoolean(ih, "MENUBOX") || 
+- IupGetAttribute(ih, "TITLE"); /* must use IupGetAttribute to check from the native implementation */
++ iupAttribGetBoolean(ih, "MINBOX") ||
++ iupAttribGetBoolean(ih, "MENUBOX") || 
++ IupGetAttribute(ih, "TITLE"); /* must use IupGetAttribute to check from the native implementation */
+ 
+ *caption = 0;
+ if (has_titlebar)
+@@ -118,14 +118,17 @@ void iupdrvDialogGetDecoration(Ihandle* ih, int *border, int *caption, int *menu
+ *border = 0;
+ if (iupAttribGetBoolean(ih, "RESIZE"))
+ {
++ /* has_border */
+ *border = GetSystemMetrics(SM_CXFRAME); /* Thickness of the sizing border around the perimeter of a window */
+ } /* that can be resized, in pixels. */
+ else if (has_titlebar)
+ {
++ /* has_border */
+ *border = GetSystemMetrics(SM_CXFIXEDFRAME); /* Thickness of the frame around the perimeter of a window */
+ } /* that has a caption but is not sizable, in pixels. */
+ else if (iupAttribGetBoolean(ih, "BORDER"))
+ {
++ /* has_border */
+ *border = GetSystemMetrics(SM_CXBORDER);
+ }
+ }
+@@ -712,28 +715,27 @@ static int winDialogMapMethod(Ihandle* ih)
+ }
+ 
+ if (iupAttribGetBoolean(ih, "RESIZE"))
++ {
+ dwStyle |= WS_THICKFRAME;
++ has_border = 1;
++ }
+ else
+ iupAttribSetStr(ih, "MAXBOX", "NO"); /* Must also remove this to RESIZE=NO work */
+-
+ if (iupAttribGetBoolean(ih, "MAXBOX"))
+ {
+ dwStyle |= WS_MAXIMIZEBOX;
+ has_titlebar = 1;
+ }
+-
+ if (iupAttribGetBoolean(ih, "MINBOX"))
+ {
+ dwStyle |= WS_MINIMIZEBOX;
+ has_titlebar = 1;
+ }
+-
+ if (iupAttribGetBoolean(ih, "MENUBOX"))
+ {
+ dwStyle |= WS_SYSMENU;
+ has_titlebar = 1;
+ }
+-
+ if (iupAttribGetBoolean(ih, "BORDER") || has_titlebar)
+ has_border = 1;
+ 
+@@ -815,10 +817,7 @@ static int winDialogMapMethod(Ihandle* ih)
+ if (iupAttribGetBoolean(ih, "DIALOGFRAME") && native_parent)
+ dwExStyle |= WS_EX_DLGMODALFRAME; /* this will hide the MENUBOX but not the close button */
+ 
+- if (iupAttribGetBoolean(ih, "COMPOSITED"))
+- dwExStyle |= WS_EX_COMPOSITED;
+- else
+- dwStyle |= WS_CLIPCHILDREN;
++ iupwinGetNativeParentStyle(ih, &dwExStyle, &dwStyle);
+ 
+ if (iupAttribGetBoolean(ih, "HELPBUTTON"))
+ dwExStyle |= WS_EX_CONTEXTHELP;
+@@ -878,7 +877,6 @@ static int winDialogMapMethod(Ihandle* ih)
+ /* Reset attributes handled during creation that */
+ /* also can be changed later, and can be consulted from the native system. */
+ iupAttribSetStr(ih, "TITLE", NULL); 
+- iupAttribSetStr(ih, "BORDER", NULL);
+ 
+ /* Ignore VISIBLE before mapping */
+ iupAttribSetStr(ih, "VISIBLE", NULL);
+@@ -956,7 +954,7 @@ static int winDialogSetBgColorAttrib(Ihandle* ih, const char* value)
+ {
+ iupAttribStoreStr(ih, "_IUPWIN_BACKGROUND_COLOR", value);
+ iupAttribSetStr(ih, "_IUPWIN_BACKGROUND_BITMAP", NULL);
+- RedrawWindow(ih->handle, NULL, NULL, RDW_ERASE|RDW_ERASENOW); /* force a WM_ERASEBKGND now */
++ RedrawWindow(ih->handle, NULL, NULL, RDW_INVALIDATE|RDW_ERASE|RDW_ALLCHILDREN); /* post WM_ERASEBKGND and WM_PAINT */
+ return 1;
+ }
+ return 0;
+@@ -973,7 +971,7 @@ static int winDialogSetBackgroundAttrib(Ihandle* ih, const char* value)
+ {
+ iupAttribSetStr(ih, "_IUPWIN_BACKGROUND_COLOR", NULL);
+ iupAttribSetStr(ih, "_IUPWIN_BACKGROUND_BITMAP", (char*)hBitmap);
+- RedrawWindow(ih->handle, NULL, NULL, RDW_ERASE|RDW_ERASENOW); /* force a WM_ERASEBKGND now */
++ RedrawWindow(ih->handle, NULL, NULL, RDW_INVALIDATE|RDW_ERASE|RDW_ALLCHILDREN); /* post WM_ERASEBKGND and WM_PAINT */
+ return 1;
+ }
+ }
+diff --git a/iup/src/win/iupwin_draw.c b/iup/src/win/iupwin_draw.c
+index 4a810e6..f663d20 100755
+--- a/iup/src/win/iupwin_draw.c
++++ b/iup/src/win/iupwin_draw.c
+@@ -14,12 +14,16 @@
+ #include <stdio.h>
+ #include <string.h>
+ #include <memory.h>
++#include <math.h>
+ 
+ #include "iup.h"
+ 
+ #include "iup_attrib.h"
+ #include "iup_class.h"
+ #include "iup_str.h"
++#include "iup_object.h"
++#include "iup_image.h"
++#include "iup_draw.h"
+ 
+ #include "iupwin_drv.h"
+ #include "iupwin_info.h"
+@@ -38,6 +42,11 @@
+ #endif
+ 
+ 
++/******************************************************************************
++ Themes
++*******************************************************************************/
++
++
+ typedef HTHEME (STDAPICALLTYPE *_winThemeOpenData)(HWND hwnd, LPCWSTR pszClassList);
+ typedef HRESULT (STDAPICALLTYPE *_winThemeCloseData)(HTHEME hTheme);
+ typedef HRESULT (STDAPICALLTYPE *_winThemeDrawBackground)(HTHEME hTheme, HDC hDC, int iPartId, int iStateId, const RECT *pRect, const RECT *pClipRect);
+@@ -61,58 +70,6 @@ static int winDrawThemeEnabled(void)
+ return winThemeOpenData? 1: 0;
+ }
+ 
+-void iupwinDrawText(HDC hDC, const char* text, int x, int y, int width, int height, HFONT hFont, COLORREF fgcolor, int style)
+-{
+- COLORREF oldcolor;
+- RECT rect;
+- HFONT hOldFont = SelectObject(hDC, hFont);
+-
+- rect.left = x;
+- rect.top = y;
+- rect.right = x+width;
+- rect.bottom = y+height;
+-
+- SetTextAlign(hDC, TA_TOP|TA_LEFT);
+- SetBkMode(hDC, TRANSPARENT);
+- oldcolor = SetTextColor(hDC, fgcolor);
+-
+- DrawText(hDC, text, -1, &rect, style|DT_NOCLIP);
+-
+- SelectObject(hDC, hOldFont);
+- SetTextColor(hDC, oldcolor);
+- SetBkMode(hDC, OPAQUE);
+-}
+-
+-void iupwinDrawBitmap(HDC hDC, HBITMAP hBitmap, HBITMAP hMask, int x, int y, int width, int height, int bpp)
+-{
+- HDC hMemDC = CreateCompatibleDC(hDC);
+- SelectObject(hMemDC, hBitmap);
+-
+- if (bpp == 32 && winAlphaBlend)
+- {
+- BLENDFUNCTION blendfunc;
+- blendfunc.BlendOp = AC_SRC_OVER;
+- blendfunc.BlendFlags = 0;
+- blendfunc.SourceConstantAlpha = 0xFF;
+- blendfunc.AlphaFormat = AC_SRC_ALPHA;
+-
+- winAlphaBlend(hDC, x, y, width, height, 
+- hMemDC, 0, 0, width, height, 
+- blendfunc);
+- }
+- else if (bpp == 8 && hMask)
+- MaskBlt(hDC, x, y, width, height, 
+- hMemDC, 0, 0, 
+- hMask, 0, 0, MAKEROP4(SRCCOPY, 0xAA0000));
+- else
+- BitBlt(hDC, x, y, width, height, 
+- hMemDC, 0, 0, 
+- SRCCOPY);
+-
+-
+- DeleteDC(hMemDC);
+-}
+-
+ void iupwinDrawInit(void)
+ {
+ if (!winAlphaBlend)
+@@ -201,7 +158,7 @@ int iupwinDrawGetThemeTabsBgColor(HWND hWnd, COLORREF *color)
+ if (!hTheme) 
+ return 0;
+ 
+- if (iupwinIsVista())
++ if (iupwinIsVistaOrNew())
+ ret = winThemeGetColor(hTheme, TABP_AEROWIZARDBODY, TIS_NORMAL, TMT_FILLCOLORHINT, color);
+ else
+ ret = winThemeGetColor(hTheme, TABP_BODY, TIS_NORMAL, TMT_FILLCOLORHINT, color);
+@@ -246,6 +203,79 @@ int iupwinDrawGetThemeFrameFgColor(HWND hWnd, COLORREF *color)
+ return (ret == S_OK)? 1: 0;
+ }
+ 
++void iupwinDrawRemoveTheme(HWND hwnd)
++{
++ typedef HRESULT (STDAPICALLTYPE *winSetWindowTheme)(HWND hwnd, LPCWSTR pszSubAppName, LPCWSTR pszSubIdList);
++ static winSetWindowTheme mySetWindowTheme = NULL;
++ if (!mySetWindowTheme)
++ {
++ HMODULE hinstDll = LoadLibrary("uxtheme.dll");
++ if (hinstDll)
++ mySetWindowTheme = (winSetWindowTheme)GetProcAddress(hinstDll, "SetWindowTheme");
++ }
++
++ if (mySetWindowTheme)
++ mySetWindowTheme(hwnd, L"", L"");
++}
++
++
++/******************************************************************************
++ Utilities
++*******************************************************************************/
++
++
++void iupwinDrawText(HDC hDC, const char* text, int x, int y, int width, int height, HFONT hFont, COLORREF fgcolor, int style)
++{
++ COLORREF oldcolor;
++ RECT rect;
++ HFONT hOldFont = SelectObject(hDC, hFont);
++
++ rect.left = x;
++ rect.top = y;
++ rect.right = x+width;
++ rect.bottom = y+height;
++
++ SetTextAlign(hDC, TA_TOP|TA_LEFT);
++ SetBkMode(hDC, TRANSPARENT);
++ oldcolor = SetTextColor(hDC, fgcolor);
++
++ DrawText(hDC, text, -1, &rect, style|DT_NOCLIP);
++
++ SelectObject(hDC, hOldFont);
++ SetTextColor(hDC, oldcolor);
++ SetBkMode(hDC, OPAQUE);
++}
++
++void iupwinDrawBitmap(HDC hDC, HBITMAP hBitmap, HBITMAP hMask, int x, int y, int width, int height, int bpp)
++{
++ HDC hMemDC = CreateCompatibleDC(hDC);
++ SelectObject(hMemDC, hBitmap);
++
++ if (bpp == 32 && winAlphaBlend)
++ {
++ BLENDFUNCTION blendfunc;
++ blendfunc.BlendOp = AC_SRC_OVER;
++ blendfunc.BlendFlags = 0;
++ blendfunc.SourceConstantAlpha = 0xFF;
++ blendfunc.AlphaFormat = AC_SRC_ALPHA;
++
++ winAlphaBlend(hDC, x, y, width, height, 
++ hMemDC, 0, 0, width, height, 
++ blendfunc);
++ }
++ else if (bpp == 8 && hMask)
++ MaskBlt(hDC, x, y, width, height, 
++ hMemDC, 0, 0, 
++ hMask, 0, 0, MAKEROP4(SRCCOPY, 0xAA0000));
++ else
++ BitBlt(hDC, x, y, width, height, 
++ hMemDC, 0, 0, 
++ SRCCOPY);
++
++
++ DeleteDC(hMemDC);
++}
++
+ static int winDrawGetStateId(int itemState)
+ {
+ if (itemState & ODS_DISABLED)
+@@ -282,21 +312,6 @@ void iupdrvDrawFocusRect(Ihandle* ih, void* gc, int x, int y, int w, int h)
+ DrawFocusRect(hDC, &rect);
+ }
+ 
+-void iupwinDrawRemoveTheme(HWND hwnd)
+-{
+- typedef HRESULT (STDAPICALLTYPE *winSetWindowTheme)(HWND hwnd, LPCWSTR pszSubAppName, LPCWSTR pszSubIdList);
+- static winSetWindowTheme mySetWindowTheme = NULL;
+- if (!mySetWindowTheme)
+- {
+- HMODULE hinstDll = LoadLibrary("uxtheme.dll");
+- if (hinstDll)
+- mySetWindowTheme = (winSetWindowTheme)GetProcAddress(hinstDll, "SetWindowTheme");
+- }
+-
+- if (mySetWindowTheme)
+- mySetWindowTheme(hwnd, L"", L"");
+-}
+-
+ void iupwinDrawParentBackground(Ihandle* ih, HDC hDC, RECT* rect)
+ {
+ unsigned char r=0, g=0, b=0;
+@@ -326,3 +341,226 @@ void iupwinDrawDestroyBitmapDC(iupwinBitmapDC *bmpDC)
+ DeleteDC(bmpDC->hBitmapDC);
+ }
+ 
++
++/******************************************************************************
++ Simple Draw
++*******************************************************************************/
++
++struct _IdrawCanvas{
++ Ihandle* ih;
++ int w, h;
++
++ int release_dc;
++ HBITMAP hBitmap, hOldBitmap;
++ HDC hBitmapDC, hDC;
++};
++
++IdrawCanvas* iupDrawCreateCanvas(Ihandle* ih)
++{
++ IdrawCanvas* dc = calloc(1, sizeof(IdrawCanvas));
++ RECT rect;
++
++ /* valid only inside the ACTION callback of an IupCanvas */
++ dc->hDC = (HDC)IupGetAttribute(ih, "HDC_WMPAINT");
++ if (!dc->hDC)
++ {
++ dc->hDC = GetDC(ih->handle);
++ dc->release_dc = 1;
++ }
++
++ GetClientRect(ih->handle, &rect);
++ dc->w = rect.right - rect.left;
++ dc->h = rect.bottom - rect.top;
++
++ dc->hBitmap = CreateCompatibleBitmap(dc->hDC, dc->w, dc->h);
++ dc->hBitmapDC = CreateCompatibleDC(dc->hDC);
++ dc->hOldBitmap = SelectObject(dc->hBitmapDC, dc->hBitmap);
++
++ SetBkMode(dc->hBitmapDC, TRANSPARENT);
++ SetTextAlign(dc->hBitmapDC, TA_TOP|TA_LEFT);
++
++ return dc;
++}
++
++void iupDrawKillCanvas(IdrawCanvas* dc)
++{
++ SelectObject(dc->hBitmapDC, dc->hOldBitmap);
++ DeleteObject(dc->hBitmap);
++ DeleteDC(dc->hBitmapDC);
++ if (dc->release_dc)
++ DeleteDC(dc->hDC);
++
++ free(dc);
++}
++
++void iupDrawUpdateSize(IdrawCanvas* dc)
++{
++ int w, h;
++ RECT rect;
++ GetClientRect(dc->ih->handle, &rect);
++ w = rect.right - rect.left;
++ h = rect.bottom - rect.top;
++
++ if (w != dc->w || h != dc->h)
++ {
++ SelectObject(dc->hBitmapDC, dc->hOldBitmap);
++ DeleteObject(dc->hBitmap);
++ DeleteDC(dc->hBitmapDC);
++
++ dc->hBitmap = CreateCompatibleBitmap(dc->hDC, dc->w, dc->h);
++ dc->hBitmapDC = CreateCompatibleDC(dc->hDC);
++ dc->hOldBitmap = SelectObject(dc->hBitmapDC, dc->hBitmap);
++
++ SetBkMode(dc->hBitmapDC, TRANSPARENT);
++ SetTextAlign(dc->hBitmapDC, TA_TOP|TA_LEFT);
++ }
++}
++
++void iupDrawFlush(IdrawCanvas* dc)
++{
++ BitBlt(dc->hDC, 0, 0, dc->w, dc->h, dc->hBitmapDC, 0, 0, SRCCOPY);
++}
++
++void iupDrawGetSize(IdrawCanvas* dc, int *w, int *h)
++{
++ if (w) *w = dc->w;
++ if (h) *h = dc->h;
++}
++
++void iupDrawParentBackground(IdrawCanvas* dc)
++{
++ unsigned char r=0, g=0, b=0;
++ char* color = iupBaseNativeParentGetBgColorAttrib(dc->ih);
++ iupStrToRGB(color, &r, &g, &b);
++ iupDrawRectangle(dc, 0, 0, dc->w-1, dc->h-1, r, g, b, 1);
++}
++
++void iupDrawRectangle(IdrawCanvas* dc, int x1, int y1, int x2, int y2, unsigned char r, unsigned char g, unsigned char b, int filled)
++{
++ RECT rect;
++ rect.left = x1; rect.top = y1; rect.right = x2+1; rect.bottom = y2+1;
++ SetDCBrushColor(dc->hBitmapDC, RGB(r,g,b));
++ if (filled)
++ FillRect(dc->hBitmapDC, &rect, (HBRUSH)GetStockObject(DC_BRUSH));
++ else
++ FrameRect(dc->hBitmapDC, &rect, (HBRUSH)GetStockObject(DC_BRUSH));
++}
++
++void iupDrawLine(IdrawCanvas* dc, int x1, int y1, int x2, int y2, unsigned char r, unsigned char g, unsigned char b)
++{
++ POINT line_poly[2];
++ HPEN hPen = CreatePen(PS_SOLID, 1, RGB(r, g, b));
++ HPEN hPenOld = SelectObject(dc->hBitmapDC, hPen);
++ line_poly[0].x = x1;
++ line_poly[0].y = y1;
++ line_poly[1].x = x2;
++ line_poly[1].y = y2;
++ Polyline(dc->hBitmapDC, line_poly, 2);
++ SelectObject(dc->hBitmapDC, hPenOld);
++ DeleteObject(hPen);
++}
++
++#define IUP_DEG2RAD 0.01745329252 /* degrees to radians (rad = CD_DEG2RAD * deg) */
++
++static int winDrawCalcArc(int c1, int c2, double a, int start)
++{
++ double proj, off;
++ if (start)
++ proj = cos(IUP_DEG2RAD * a);
++ else
++ proj = sin(IUP_DEG2RAD * a);
++ off = (c2+c1)/2.0 + (c2-c1+1)*proj/2.0;
++ return iupROUND(off);
++}
++
++void iupDrawArc(IdrawCanvas* dc, int x1, int y1, int x2, int y2, double a1, double a2, unsigned char r, unsigned char g, unsigned char b, int filled)
++{
++ int XStartArc = winDrawCalcArc(x1, x2, a1, 1);
++ int XEndArc = winDrawCalcArc(x1, x2, a2, 0);
++ int YStartArc = winDrawCalcArc(y1, y2, a1, 1);
++ int YEndArc = winDrawCalcArc(y1, y2, a2, 0);
++
++ if (filled)
++ {
++ HBRUSH hBrush = CreateSolidBrush(RGB(r,g,b));
++ HPEN hBrushOld = SelectObject(dc->hBitmapDC, hBrush); 
++ BeginPath(dc->hBitmapDC); 
++ Pie(dc->hBitmapDC, x1, y1, x2+1, y2+1, XStartArc, YStartArc, XEndArc, YEndArc);
++ EndPath(dc->hBitmapDC);
++ FillPath(dc->hBitmapDC);
++ SelectObject(dc->hBitmapDC, hBrushOld);
++ DeleteObject(hBrush);
++ }
++ else
++ {
++ HPEN hPen = CreatePen(PS_SOLID, 1, RGB(r, g, b));
++ HPEN hPenOld = SelectObject(dc->hBitmapDC, hPen);
++ Arc(dc->hBitmapDC, x1, y1, x2+1, y2+1, XStartArc, YStartArc, XEndArc, YEndArc);
++ SelectObject(dc->hBitmapDC, hPenOld);
++ DeleteObject(hPen);
++ }
++}
++
++void iupDrawPolygon(IdrawCanvas* dc, int* points, int count, unsigned char r, unsigned char g, unsigned char b, int filled)
++{
++ if (filled)
++ {
++ HBRUSH hBrush = CreateSolidBrush(RGB(r,g,b));
++ HPEN hBrushOld = SelectObject(dc->hBitmapDC, hBrush); 
++ BeginPath(dc->hBitmapDC); 
++ Polygon(dc->hBitmapDC, (POINT*)points, count);
++ EndPath(dc->hBitmapDC);
++ FillPath(dc->hBitmapDC);
++ SelectObject(dc->hBitmapDC, hBrushOld);
++ DeleteObject(hBrush);
++ }
++ else
++ {
++ HPEN hPen = CreatePen(PS_SOLID, 1, RGB(r, g, b));
++ HPEN hPenOld = SelectObject(dc->hBitmapDC, hPen);
++ Polyline(dc->hBitmapDC, (POINT*)points, count);
++ SelectObject(dc->hBitmapDC, hPenOld);
++ DeleteObject(hPen);
++ }
++}
++
++void iupDrawSetClipRect(IdrawCanvas* dc, int x1, int y1, int x2, int y2)
++{
++ HRGN clip_hrgn = CreateRectRgn(x1, y1, x2, y2);
++ SelectClipRgn(dc->hBitmapDC, clip_hrgn);
++ DeleteObject(clip_hrgn);
++}
++
++void iupDrawResetClip(IdrawCanvas* dc)
++{
++ SelectClipRgn(dc->hBitmapDC, NULL);
++}
++
++void iupDrawText(IdrawCanvas* dc, const char* text, int len, int x, int y, unsigned char r, unsigned char g, unsigned char b)
++{
++ HFONT hOldFont, hFont = (HFONT)IupGetAttribute(dc->ih, "HFONT");
++ SetTextColor(dc->hBitmapDC, RGB(r, g, b));
++ hOldFont = SelectObject(dc->hBitmapDC, hFont);
++ TextOut(dc->hBitmapDC, x, y, text, len);
++ SelectObject(dc->hBitmapDC, hOldFont);
++}
++
++void iupDrawImage(IdrawCanvas* dc, const char* name, int make_inactive, int x, int y)
++{
++ int img_w, img_h, bpp;
++ HBITMAP hMask = NULL;
++ HBITMAP hBitmap = iupImageGetImage(name, dc->ih, make_inactive);
++ if (!hBitmap)
++ return;
++
++ /* must use this info, since image can be a driver image loaded from resources */
++ iupdrvImageGetInfo(hBitmap, &img_w, &img_h, &bpp);
++
++ if (bpp == 8)
++ hMask = iupdrvImageCreateMask(IupGetHandle(name));
++
++ iupwinDrawBitmap(dc->hBitmapDC, hBitmap, hMask, x, y, img_w, img_h, bpp);
++
++ if (hMask)
++ DeleteObject(hMask);
++}
+diff --git a/iup/src/win/iupwin_drv.h b/iup/src/win/iupwin_drv.h
+index 3372c1a..7407a7a 100755
+--- a/iup/src/win/iupwin_drv.h
++++ b/iup/src/win/iupwin_drv.h
+@@ -77,6 +77,7 @@ int iupwinBaseContainerProc(Ihandle* ih, UINT msg, WPARAM wp, LPARAM lp, LRESULT
+ /* Creates the Window with native parent and child ID, associate HWND with Ihandle*, 
+ and replace the WinProc by iupwinBaseWinProc */
+ int iupwinCreateWindowEx(Ihandle* ih, LPCSTR lpClassName, DWORD dwExStyle, DWORD dwStyle);
++void iupwinGetNativeParentStyle(Ihandle* ih, DWORD *dwExStyle, DWORD *dwStyle);
+ 
+ int iupwinClassExist(const char* name);
+ int iupwinGetColorRef(Ihandle *ih, char *name, COLORREF *color);
+@@ -97,8 +98,8 @@ char* iupwinGetClipboardText(Ihandle* ih);
+ int iupwinGetScreenRes(void);
+ /* 1 point = 1/72 inch */
+ /* pixel = (point/72)*(pixel/inch) */
+-#define IUPWIN_PT2PIXEL(_pt, _res) MulDiv(_pt, _res, 72) /* (((_pt)*(_res))/72) */
+-#define IUPWIN_PIXEL2PT(_pixel, _res) MulDiv(_pixel, 72, _res) /* (((_pixel)*72)/(_res)) */
++#define iupWIN_PT2PIXEL(_pt, _res) MulDiv(_pt, _res, 72) /* (((_pt)*(_res))/72) */
++#define iupWIN_PIXEL2PT(_pixel, _res) MulDiv(_pixel, 72, _res) /* (((_pixel)*72)/(_res)) */
+ 
+ 
+ /* child window identifier of the first MDI child window created,
+diff --git a/iup/src/win/iupwin_filedlg.c b/iup/src/win/iupwin_filedlg.c
+index da66b4b..26994e5 100755
+--- a/iup/src/win/iupwin_filedlg.c
++++ b/iup/src/win/iupwin_filedlg.c
+@@ -63,7 +63,7 @@ static INT CALLBACK winFileDlgBrowseCallback(HWND hWnd, UINT uMsg, LPARAM lParam
+ }
+ else if (uMsg == BFFM_SELCHANGED)
+ {
+- char* buffer = iupStrGetMemory(MAX_FILENAME_SIZE);
++ char buffer[MAX_FILENAME_SIZE];
+ ITEMIDLIST* selecteditem = (ITEMIDLIST*)lParam;
+ buffer[0] = 0;
+ SHGetPathFromIDList(selecteditem, buffer);
+@@ -90,7 +90,7 @@ static void winFileDlgGetFolder(Ihandle *ih)
+ browseinfo.pszDisplayName = buffer; 
+ browseinfo.lpfn = winFileDlgBrowseCallback;
+ browseinfo.lParam = (LPARAM)ih;
+- browseinfo.ulFlags = BIF_NEWDIALOGSTYLE;
++ browseinfo.ulFlags = IupGetGlobal("_IUPWIN_COINIT_MULTITHREADED")? 0: BIF_NEWDIALOGSTYLE;
+ browseinfo.hwndOwner = parent;
+ 
+ selecteditem = SHBrowseForFolder(&browseinfo);
+@@ -112,6 +112,37 @@ static void winFileDlgGetFolder(Ihandle *ih)
+ 
+ /************************************************************************************************/
+ 
++static int winFileDlgGetSelectedFile(Ihandle* ih, HWND hWnd, char* filename)
++{
++ int ret = CommDlg_OpenSave_GetFilePath(GetParent(hWnd), filename, MAX_FILENAME_SIZE);
++ if (ret < 0)
++ return 0;
++
++ if (iupAttribGetBoolean(ih, "MULTIPLEFILES"))
++ {
++ /* check if there are more than 1 files and return only the first one */
++ int found = 0;
++ while(*filename != 0)
++ { 
++ if (*filename == '"')
++ {
++ if (!found)
++ found = 1;
++ else
++ {
++ *(filename-1) = 0;
++ return 1;
++ }
++ }
++ if (found)
++ *filename = *(filename+1);
++ filename++;
++ }
++ }
++
++ return 1;
++}
++
+ static UINT_PTR CALLBACK winFileDlgSimpleHook(HWND hWnd, UINT uiMsg, WPARAM wParam, LPARAM lParam)
+ {
+ (void)wParam;
+@@ -152,16 +183,15 @@ static UINT_PTR CALLBACK winFileDlgSimpleHook(HWND hWnd, UINT uiMsg, WPARAM wPar
+ IFnss cb = (IFnss)IupGetCallback(ih, "FILE_CB");
+ if (cb)
+ {
+- char* filename = iupStrGetMemory(MAX_FILENAME_SIZE);
+- if (CommDlg_OpenSave_GetFilePath(GetParent(hWnd), filename, MAX_FILENAME_SIZE) <= MAX_FILENAME_SIZE)
++ char filename[MAX_FILENAME_SIZE];
++ if (winFileDlgGetSelectedFile(ih, hWnd, filename))
+ {
+ int ret;
+ char* file_msg;
+ 
+ if (!iupdrvIsFile(filename))
+- break;
+-
+- if (pofn->hdr.code == CDN_FILEOK)
++ file_msg = "OTHER";
++ else if (pofn->hdr.code == CDN_FILEOK)
+ file_msg = "OK";
+ else 
+ file_msg = "SELECT";
+@@ -267,9 +297,9 @@ static UINT_PTR CALLBACK winFileDlgPreviewHook(HWND hWnd, UINT uiMsg, WPARAM wPa
+ LPDRAWITEMSTRUCT lpDrawItem = (LPDRAWITEMSTRUCT)lParam;
+ Ihandle* ih = (Ihandle*)GetWindowLongPtr(hWnd, DWLP_USER);
+ IFnss cb = (IFnss)IupGetCallback(ih, "FILE_CB");
+- char* filename = iupStrGetMemory(MAX_FILENAME_SIZE);
++ char filename[MAX_FILENAME_SIZE];
+ iupAttribSetStr(ih, "PREVIEWDC", (char*)lpDrawItem->hDC);
+- if (CommDlg_OpenSave_GetFilePath(GetParent(hWnd), filename, MAX_FILENAME_SIZE) <= MAX_FILENAME_SIZE)
++ if (winFileDlgGetSelectedFile(ih, hWnd, filename))
+ {
+ if (iupdrvIsFile(filename))
+ cb(ih, filename, "PAINT");
+@@ -324,16 +354,15 @@ static UINT_PTR CALLBACK winFileDlgPreviewHook(HWND hWnd, UINT uiMsg, WPARAM wPa
+ case CDN_SELCHANGE:
+ {
+ HWND hWndPreview = GetDlgItem(hWnd, IUP_PREVIEWCANVAS);
+- char* filename = iupStrGetMemory(MAX_FILENAME_SIZE);
+- if (CommDlg_OpenSave_GetFilePath(GetParent(hWnd), filename, MAX_FILENAME_SIZE) <= MAX_FILENAME_SIZE)
++ char filename[MAX_FILENAME_SIZE];
++ if (winFileDlgGetSelectedFile(ih, hWnd, filename))
+ {
+ int ret;
+ char* file_msg;
+ 
+ if (!iupdrvIsFile(filename))
+- break;
+-
+- if (pofn->hdr.code == CDN_FILEOK)
++ file_msg = "OTHER";
++ else if (pofn->hdr.code == CDN_FILEOK)
+ file_msg = "OK";
+ else
+ file_msg = "SELECT";
+@@ -520,9 +549,14 @@ static int winFileDlgPopup(Ihandle *ih, int x, int y)
+ if (iupAttribGetBoolean(ih, "MULTIPLEFILES"))
+ {
+ int i = 0;
+- 
++
++ char* dir = iupStrFileGetPath(openfilename.lpstrFile); /* the first part is the directory already */
++ iupAttribStoreStr(ih, "DIRECTORY", dir);
++ free(dir);
++ 
+ /* If there is more than one file, replace terminator by the separator */
+- if (openfilename.lpstrFile && openfilename.lpstrFile[openfilename.nFileOffset-1] == 0 && openfilename.nFileOffset>0) 
++ if (openfilename.lpstrFile[openfilename.nFileOffset-1] == 0 && 
++ openfilename.nFileOffset>0) 
+ {
+ while (openfilename.lpstrFile[i] != 0 || openfilename.lpstrFile[i+1] != 0)
+ {
+@@ -534,12 +568,16 @@ static int winFileDlgPopup(Ihandle *ih, int x, int y)
+ }
+ 
+ iupAttribSetStr(ih, "STATUS", "0");
+- iupAttribSetStr(ih, "FILEEXIST", NULL);
++ iupAttribSetStr(ih, "FILEEXIST", "YES");
+ }
+ else
+ {
+ if (iupdrvIsFile(openfilename.lpstrFile)) /* check if file exists */
+ {
++ char* dir = iupStrFileGetPath(openfilename.lpstrFile);
++ iupAttribStoreStr(ih, "DIRECTORY", dir);
++ free(dir);
++
+ iupAttribSetStr(ih, "FILEEXIST", "YES");
+ iupAttribSetStr(ih, "STATUS", "0");
+ }
+diff --git a/iup/src/win/iupwin_focus.c b/iup/src/win/iupwin_focus.c
+index 63da02d..2328dea 100755
+--- a/iup/src/win/iupwin_focus.c
++++ b/iup/src/win/iupwin_focus.c
+@@ -32,7 +32,7 @@
+ 
+ /* Since Windows XP, the focus feedback only appears after the user press a key.
+ Except for the IupText where the feedback is the caret.
+- Before that if you click in a control the focus feedback will be hidden.
++ Before a key is pressed if you click in a control the focus feedback will be hidden.
+ 
+ We manually send WM_CHANGEUISTATE because we do not use IsDialogMessage anymore,
+ and the focus feedback was not shown even after the used press a key.
+@@ -43,19 +43,28 @@
+ void iupdrvSetFocus(Ihandle *ih)
+ {
+ SetFocus(ih->handle);
+- SendMessage(ih->handle, WM_CHANGEUISTATE, UIS_CLEAR|UISF_HIDEFOCUS, 0);
++
++ /* See comments above */
++ SendMessage(ih->handle, WM_CHANGEUISTATE, UIS_CLEAR|UISF_HIDEFOCUS, 0); /* clear+hidefocus=showfocus */
+ }
+ 
+ void iupwinWmSetFocus(Ihandle *ih)
+ {
+ Ihandle* dialog = IupGetDialog(ih);
+ if (ih != dialog)
+- iupAttribSetStr(dialog, "_IUPWIN_LASTFOCUS", (char*)ih); /* used by IupMenu */
++ iupAttribSetStr(dialog, "_IUPWIN_LASTFOCUS", (char*)ih); /* used by IupMenu and here. */
+ else
+ {
+ /* if a control inside that dialog had the focus, then reset to it when the dialog gets the focus */
+ Ihandle* lastfocus = (Ihandle*)iupAttribGet(dialog, "_IUPWIN_LASTFOCUS");
+- if (lastfocus) IupSetFocus(lastfocus);
++ if (lastfocus)
++ {
++ /* call the callback and update current focus before changing it again */
++ iupCallGetFocusCb(ih);
++
++ IupSetFocus(lastfocus);
++ return;
++ }
+ }
+ 
+ iupCallGetFocusCb(ih);
+diff --git a/iup/src/win/iupwin_font.c b/iup/src/win/iupwin_font.c
+index 659e2d9..c10befb 100755
+--- a/iup/src/win/iupwin_font.c
++++ b/iup/src/win/iupwin_font.c
+@@ -70,7 +70,7 @@ static IwinFont* winFindFont(const char *standardfont)
+ if (height < 0) 
+ height_pixels = height; /* already in pixels */
+ else
+- height_pixels = -IUPWIN_PT2PIXEL(height, res);
++ height_pixels = -iupWIN_PT2PIXEL(height, res);
+ 
+ if (height_pixels == 0)
+ return NULL;
+@@ -119,7 +119,7 @@ static void winFontFromLogFont(LOGFONT* logfont, char * font)
+ int is_strikeout = logfont->lfStrikeOut;
+ int height_pixels = logfont->lfHeight; /* negative value */
+ int res = iupwinGetScreenRes();
+- int height = IUPWIN_PIXEL2PT(-height_pixels, res); /* return in points */
++ int height = iupWIN_PIXEL2PT(-height_pixels, res); /* return in points */
+ 
+ sprintf(font, "%s, %s%s%s%s %d", logfont->lfFaceName, 
+ is_bold?"Bold ":"", 
+diff --git a/iup/src/win/iupwin_fontdlg.c b/iup/src/win/iupwin_fontdlg.c
+index 0602441..ce27cf2 100755
+--- a/iup/src/win/iupwin_fontdlg.c
++++ b/iup/src/win/iupwin_fontdlg.c
+@@ -68,7 +68,7 @@ static int winFontDlgPopup(Ihandle* ih, int x, int y)
+ 
+ standardfont = iupAttribGet(ih, "VALUE");
+ if (!standardfont)
+- return IUP_ERROR;
++ standardfont = IupGetGlobal("DEFAULTFONT");
+ 
+ /* parse the old format first */
+ if (!iupFontParseWin(standardfont, typeface, &height, &is_bold, &is_italic, &is_underline, &is_strikeout))
+@@ -81,7 +81,7 @@ static int winFontDlgPopup(Ihandle* ih, int x, int y)
+ if (height < 0)
+ height_pixels = height; /* already in pixels */
+ else
+- height_pixels = -IUPWIN_PT2PIXEL(height, res);
++ height_pixels = -iupWIN_PT2PIXEL(height, res);
+ 
+ if (height_pixels == 0)
+ return IUP_ERROR;
+@@ -134,7 +134,7 @@ static int winFontDlgPopup(Ihandle* ih, int x, int y)
+ if (height < 0) /* not an error, use old value as a reference for the units */
+ height = height_pixels; /* return in pixels */
+ else
+- height = IUPWIN_PIXEL2PT(-height_pixels, res); /* return in points */
++ height = iupWIN_PIXEL2PT(-height_pixels, res); /* return in points */
+ 
+ iupAttribSetStrf(ih, "VALUE", "%s, %s%s%s%s %d", logfont.lfFaceName, 
+ is_bold?"Bold ":"", 
+diff --git a/iup/src/win/iupwin_frame.c b/iup/src/win/iupwin_frame.c
+index 0949b5d..3f56aed 100755
+--- a/iup/src/win/iupwin_frame.c
++++ b/iup/src/win/iupwin_frame.c
+@@ -47,6 +47,27 @@ void iupdrvFrameGetDecorOffset(Ihandle* ih, int *x, int *y)
+ }
+ }
+ 
++static char* winFrameGetBgColorAttrib(Ihandle* ih)
++{
++ if (iupAttribGet(ih, "_IUPFRAME_HAS_BGCOLOR"))
++ return NULL;
++ else
++ return iupBaseNativeParentGetBgColorAttrib(ih);
++}
++
++static int winFrameSetBgColorAttrib(Ihandle* ih, const char* value)
++{
++ (void)value;
++
++ if (iupAttribGet(ih, "_IUPFRAME_HAS_BGCOLOR"))
++ {
++ IupUpdate(ih); /* post a redraw */
++ return 1;
++ }
++ else
++ return 0;
++}
++
+ static void winFrameDrawText(HDC hDC, const char* text, int x, int y, COLORREF fgcolor)
+ {
+ COLORREF oldcolor;
+@@ -126,6 +147,16 @@ static void winFrameDrawItem(Ihandle* ih, DRAWITEMSTRUCT *drawitem)
+ DrawEdge(hDC, &drawitem->rcItem, EDGE_SUNKEN, BF_RECT);
+ else
+ DrawEdge(hDC, &drawitem->rcItem, EDGE_ETCHED, BF_RECT);
++
++ if (iupAttribGet(ih, "_IUPFRAME_HAS_BGCOLOR"))
++ {
++ unsigned char r=0, g=0, b=0;
++ char* color = iupAttribGetStr(ih, "BGCOLOR");
++ iupStrToRGB(color, &r, &g, &b);
++ SetDCBrushColor(hDC, RGB(r,g,b));
++ InflateRect(&drawitem->rcItem, -2, -2);
++ FillRect(hDC, &drawitem->rcItem, (HBRUSH)GetStockObject(DC_BRUSH));
++ }
+ }
+ 
+ iupwinDrawDestroyBitmapDC(&bmpDC);
+@@ -169,11 +200,13 @@ static int winFrameMapMethod(Ihandle* ih)
+ title = iupAttribGet(ih, "TITLE");
+ if (title)
+ iupAttribSetStr(ih, "_IUPFRAME_HAS_TITLE", "1");
+-
+- if (iupAttribGetBoolean(IupGetDialog(ih), "COMPOSITED"))
+- dwExStyle |= WS_EX_COMPOSITED;
+ else
+- dwStyle |= WS_CLIPCHILDREN;
++ {
++ if (iupAttribGet(ih, "BGCOLOR"))
++ iupAttribSetStr(ih, "_IUPFRAME_HAS_BGCOLOR", "1");
++ }
++
++ iupwinGetNativeParentStyle(ih, &dwExStyle, &dwStyle);
+ 
+ if (!iupwinCreateWindowEx(ih, "BUTTON", dwExStyle, dwStyle))
+ return IUP_ERROR;
+@@ -195,7 +228,7 @@ void iupdrvFrameInitClass(Iclass* ic)
+ /* Driver Dependent Attribute functions */
+ 
+ /* Visual */
+- iupClassRegisterAttribute(ic, "BGCOLOR", iupBaseNativeParentGetBgColorAttrib, NULL, IUPAF_SAMEASSYSTEM, "DLGBGCOLOR", IUPAF_DEFAULT); 
++ iupClassRegisterAttribute(ic, "BGCOLOR", winFrameGetBgColorAttrib, winFrameSetBgColorAttrib, IUPAF_SAMEASSYSTEM, "DLGBGCOLOR", IUPAF_DEFAULT); 
+ 
+ /* Special */
+ iupClassRegisterAttribute(ic, "FGCOLOR", NULL, NULL, IUPAF_SAMEASSYSTEM, "DLGFGCOLOR", IUPAF_NOT_MAPPED);
+diff --git a/iup/src/win/iupwin_globalattrib.c b/iup/src/win/iupwin_globalattrib.c
+index a176925..bcd6355 100755
+--- a/iup/src/win/iupwin_globalattrib.c
++++ b/iup/src/win/iupwin_globalattrib.c
+@@ -148,6 +148,11 @@ int iupdrvSetGlobal(const char *name, const char *value)
+ winGlobalSendKey(key, 0x03);
+ return 0;
+ }
++ if (iupStrEqual(name, "DLL_HINSTANCE"))
++ {
++ iupwin_dll_hinstance = (HINSTANCE)value;
++ return 0;
++ }
+ return 1;
+ }
+ 
+@@ -239,5 +244,7 @@ char *iupdrvGetGlobal(const char *name)
+ return "YES";
+ return "NO";
+ }
++ if (iupStrEqual(name, "DLL_HINSTANCE"))
++ return (char*)iupwin_dll_hinstance;
+ return NULL;
+ }
+diff --git a/iup/src/win/iupwin_info.c b/iup/src/win/iupwin_info.c
+index 8ea7dd4..4d57289 100755
+--- a/iup/src/win/iupwin_info.c
++++ b/iup/src/win/iupwin_info.c
+@@ -18,7 +18,7 @@
+ #include "iupwin_info.h"
+ 
+ 
+-int iupwinIsVista(void)
++int iupwinIsVistaOrNew(void)
+ {
+ OSVERSIONINFO osvi;
+ osvi.dwOSVersionInfoSize = sizeof(OSVERSIONINFO);
+diff --git a/iup/src/win/iupwin_info.h b/iup/src/win/iupwin_info.h
+index d39bae0..8d461fb 100755
+--- a/iup/src/win/iupwin_info.h
++++ b/iup/src/win/iupwin_info.h
+@@ -16,7 +16,7 @@ int iupwinGetSystemMajorVersion(void);
+ int iupwinGetComCtl32Version(void);
+ char* iupwinGetSystemLanguage(void);
+ int iupwinIsAppThemed(void);
+-int iupwinIsVista(void);
++int iupwinIsVistaOrNew(void);
+ 
+ /* color */
+ void iupwinGetSysColor(char* color, int wincolor);
+diff --git a/iup/src/win/iupwin_key.c b/iup/src/win/iupwin_key.c
+index 921ed94..899e837 100755
+--- a/iup/src/win/iupwin_key.c
++++ b/iup/src/win/iupwin_key.c
+@@ -317,32 +317,32 @@ int iupwinKeyEvent(Ihandle* ih, int wincode, int press)
+ void iupwinButtonKeySetStatus(WORD keys, char* status, int doubleclick)
+ {
+ if (keys & MK_SHIFT)
+- iupKEYSETSHIFT(status);
++ iupKEY_SETSHIFT(status);
+ 
+ if (keys & MK_CONTROL)
+- iupKEYSETCONTROL(status); 
++ iupKEY_SETCONTROL(status); 
+ 
+ if (keys & MK_LBUTTON)
+- iupKEYSETBUTTON1(status);
++ iupKEY_SETBUTTON1(status);
+ 
+ if (keys & MK_MBUTTON)
+- iupKEYSETBUTTON2(status);
++ iupKEY_SETBUTTON2(status);
+ 
+ if (keys & MK_RBUTTON)
+- iupKEYSETBUTTON3(status);
++ iupKEY_SETBUTTON3(status);
+ 
+ if (doubleclick)
+- iupKEYSETDOUBLE(status);
++ iupKEY_SETDOUBLE(status);
+ 
+ if (GetKeyState(VK_MENU) & 0x8000)
+- iupKEYSETALT(status);
++ iupKEY_SETALT(status);
+ 
+ if ((GetKeyState(VK_LWIN) & 0x8000) || (GetKeyState(VK_RWIN) & 0x8000))
+- iupKEYSETSYS(status);
++ iupKEY_SETSYS(status);
+ 
+ if (keys & MK_XBUTTON1)
+- iupKEYSETBUTTON4(status);
++ iupKEY_SETBUTTON4(status);
+ 
+ if (keys & MK_XBUTTON2)
+- iupKEYSETBUTTON5(status);
++ iupKEY_SETBUTTON5(status);
+ }
+diff --git a/iup/src/win/iupwin_label.c b/iup/src/win/iupwin_label.c
+index d5a1f53..95dd10c 100755
+--- a/iup/src/win/iupwin_label.c
++++ b/iup/src/win/iupwin_label.c
+@@ -173,7 +173,7 @@ static int winLabelSetAlignmentAttrib(Ihandle* ih, const char* value)
+ else /* "ATOP" */
+ ih->data->vert_alignment = IUP_ALIGN_ATOP;
+ 
+- iupdrvDisplayRedraw(ih);
++ iupdrvRedrawNow(ih);
+ }
+ return 0;
+ }
+@@ -197,7 +197,7 @@ static int winLabelSetPaddingAttrib(Ihandle* ih, const char* value)
+ iupStrToIntInt(value, &ih->data->horiz_padding, &ih->data->vert_padding, 'x');
+ 
+ if (ih->handle && ih->data->type != IUP_LABEL_SEP_HORIZ && ih->data->type != IUP_LABEL_SEP_VERT)
+- iupdrvDisplayRedraw(ih);
++ iupdrvRedrawNow(ih);
+ 
+ return 0;
+ }
+@@ -211,7 +211,7 @@ static int winLabelSetWordWrapAttrib(Ihandle* ih, const char* value)
+ else
+ ih->data->text_style &= ~DT_WORDBREAK;
+ 
+- iupdrvDisplayRedraw(ih);
++ iupdrvRedrawNow(ih);
+ }
+ 
+ return 1;
+@@ -226,7 +226,7 @@ static int winLabelSetEllipsisAttrib(Ihandle* ih, const char* value)
+ else
+ ih->data->text_style &= ~DT_END_ELLIPSIS;
+ 
+- iupdrvDisplayRedraw(ih);
++ iupdrvRedrawNow(ih);
+ }
+ 
+ return 1;
+@@ -240,12 +240,24 @@ static int winLabelSetFgColorAttrib(Ihandle* ih, const char* value)
+ if (iupStrToRGB(value, &r, &g, &b))
+ {
+ ih->data->fgcolor = RGB(r,g,b);
+- iupdrvDisplayRedraw(ih);
++
++ if (ih->handle)
++ iupdrvRedrawNow(ih);
+ }
+ }
+ return 1;
+ }
+ 
++static int winLabelSetUpdateAttrib(Ihandle* ih, const char* value)
++{
++ (void)value;
++
++ if (ih->handle)
++ iupdrvPostRedraw(ih); /* Post a redraw */
++
++ return 1;
++}
++
+ static int winLabelProc(Ihandle* ih, UINT msg, WPARAM wp, LPARAM lp, LRESULT *result)
+ {
+ switch (msg)
+@@ -257,6 +269,7 @@ static int winLabelProc(Ihandle* ih, UINT msg, WPARAM wp, LPARAM lp, LRESULT *re
+ *result = WVR_HREDRAW|WVR_VREDRAW;
+ return 1;
+ }
++ break;
+ }
+ }
+ 
+@@ -266,7 +279,7 @@ static int winLabelProc(Ihandle* ih, UINT msg, WPARAM wp, LPARAM lp, LRESULT *re
+ static int winLabelMapMethod(Ihandle* ih)
+ {
+ char* value;
+- DWORD dwStyle = WS_CHILD |
++ DWORD dwStyle = WS_CHILD | WS_CLIPSIBLINGS |
+ SS_NOTIFY; /* SS_NOTIFY is necessary because of the base messages */
+ 
+ if (!ih->parent)
+@@ -330,7 +343,7 @@ void iupdrvLabelInitClass(Iclass* ic)
+ 
+ /* IupLabel only */
+ iupClassRegisterAttribute(ic, "ALIGNMENT", winLabelGetAlignmentAttrib, winLabelSetAlignmentAttrib, IUPAF_SAMEASSYSTEM, "ALEFT:ACENTER", IUPAF_NO_INHERIT);
+- iupClassRegisterAttribute(ic, "IMAGE", NULL, NULL, NULL, NULL, IUPAF_NO_DEFAULTVALUE|IUPAF_NO_INHERIT);
++ iupClassRegisterAttribute(ic, "IMAGE", NULL, winLabelSetUpdateAttrib, NULL, NULL, IUPAF_NO_DEFAULTVALUE|IUPAF_NO_INHERIT);
+ iupClassRegisterAttribute(ic, "PADDING", iupLabelGetPaddingAttrib, winLabelSetPaddingAttrib, IUPAF_SAMEASSYSTEM, "0x0", IUPAF_NOT_MAPPED);
+ 
+ /* IupLabel Windows and GTK only */
+diff --git a/iup/src/win/iupwin_list.c b/iup/src/win/iupwin_list.c
+index 8fdadb6..cb510b5 100755
+--- a/iup/src/win/iupwin_list.c
++++ b/iup/src/win/iupwin_list.c
+@@ -154,6 +154,8 @@ void iupdrvListInsertItem(Ihandle* ih, int pos, const char* value)
+ SendMessage(ih->handle, WIN_INSERTSTRING(ih), pos, (LPARAM)value);
+ SendMessage(ih->handle, WIN_SETITEMDATA(ih), pos, (LPARAM)iupdrvFontGetStringWidth(ih, value));
+ winListUpdateScrollWidth(ih);
++
++ iupListUpdateOldValue(ih, pos, 0);
+ }
+ 
+ void iupdrvListRemoveItem(Ihandle* ih, int pos)
+@@ -164,8 +166,14 @@ void iupdrvListRemoveItem(Ihandle* ih, int pos)
+ int curpos = SendMessage(ih->handle, WIN_GETCURSEL(ih), 0, 0);
+ if (pos == curpos)
+ {
+- if (curpos > 0) curpos--;
+- else curpos++;
++ if (curpos > 0) 
++ curpos--;
++ else 
++ {
++ curpos=1;
++ if (iupdrvListGetCount(ih)==1)
++ curpos = -1; /* remove the selection */
++ }
+ 
+ SendMessage(ih->handle, WIN_SETCURSEL(ih), curpos, 0);
+ }
+@@ -173,6 +181,8 @@ void iupdrvListRemoveItem(Ihandle* ih, int pos)
+ 
+ SendMessage(ih->handle, WIN_DELETESTRING(ih), pos, 0L);
+ winListUpdateScrollWidth(ih);
++
++ iupListUpdateOldValue(ih, pos, 1);
+ }
+ 
+ void iupdrvListRemoveAllItems(Ihandle* ih)
+@@ -220,18 +230,29 @@ static void winListUpdateItemWidth(Ihandle* ih)
+ }
+ }
+ 
++static int winListSetBgColorAttrib(Ihandle *ih, const char *value)
++{
++ (void)value;
++ if (ih->handle)
++ iupdrvPostRedraw(ih);
++ return 1;
++}
++
+ static int winListSetStandardFontAttrib(Ihandle* ih, const char* value)
+ {
+ iupdrvSetStandardFontAttrib(ih, value);
+- winListUpdateItemWidth(ih);
+- winListUpdateScrollWidth(ih);
++ if (ih->handle)
++ {
++ winListUpdateItemWidth(ih);
++ winListUpdateScrollWidth(ih);
++ }
+ return 1;
+ }
+ 
+ static char* winListGetIdValueAttrib(Ihandle* ih, const char* name_id)
+ {
+ int pos = iupListGetPos(ih, name_id);
+- if (pos != -1)
++ if (pos >= 0)
+ {
+ int len = SendMessage(ih->handle, WIN_GETTEXTLEN(ih), (WPARAM)pos, 0);
+ char* str = iupStrGetMemory(len+1);
+@@ -514,8 +535,10 @@ static int winListSetNCAttrib(Ihandle* ih, const char* value)
+ {
+ HWND cbedit = (HWND)iupAttribGet(ih, "_IUPWIN_EDITBOX");
+ SendMessage(cbedit, EM_LIMITTEXT, ih->data->nc, 0L);
++ return 0;
+ }
+- return 0;
++ else
++ return 1; /* store until not mapped, when mapped will be set again */
+ }
+ 
+ static int winListSetSelectionAttrib(Ihandle* ih, const char* value)
+@@ -995,13 +1018,27 @@ static int winListEditProc(Ihandle* ih, HWND cbedit, UINT msg, WPARAM wp, LPARAM
+ if (msg==WM_KEYDOWN) /* process K_ANY before text callbacks */
+ {
+ ret = iupwinBaseProc(ih, msg, wp, lp, result);
+- if (ret) return 1;
++ if (ret) 
++ {
++ iupAttribSetStr(ih, "_IUPWIN_IGNORE_CHAR", "1");
++ *result = 0;
++ return 1;
++ }
++ else
++ iupAttribSetStr(ih, "_IUPWIN_IGNORE_CHAR", NULL);
+ }
+ 
+ switch (msg)
+ {
+ case WM_CHAR:
+ {
++ if (iupAttribGet(ih, "_IUPWIN_IGNORE_CHAR"))
++ {
++ iupAttribSetStr(ih, "_IUPWIN_IGNORE_CHAR", NULL);
++ *result = 0;
++ return 1;
++ }
++
+ if ((char)wp == '\b')
+ { 
+ if (!winListCallEditCb(ih, cbedit, NULL, 0, -1))
+@@ -1301,7 +1338,7 @@ static void winListLayoutUpdateMethod(Ihandle *ih)
+ static int winListMapMethod(Ihandle* ih)
+ {
+ char* class_name;
+- DWORD dwStyle = WS_CHILD,
++ DWORD dwStyle = WS_CHILD|WS_CLIPSIBLINGS,
+ dwExStyle = WS_EX_CLIENTEDGE;
+ 
+ if (!ih->parent)
+@@ -1426,7 +1463,7 @@ void iupdrvListInitClass(Iclass* ic)
+ iupClassRegisterAttribute(ic, "STANDARDFONT", NULL, winListSetStandardFontAttrib, IUPAF_SAMEASSYSTEM, "DEFAULTFONT", IUPAF_NOT_MAPPED);
+ 
+ /* Visual */
+- iupClassRegisterAttribute(ic, "BGCOLOR", NULL, NULL, IUPAF_SAMEASSYSTEM, "TXTBGCOLOR", IUPAF_NOT_MAPPED); 
++ iupClassRegisterAttribute(ic, "BGCOLOR", NULL, winListSetBgColorAttrib, IUPAF_SAMEASSYSTEM, "TXTBGCOLOR", IUPAF_NOT_MAPPED);
+ 
+ /* Special */
+ iupClassRegisterAttribute(ic, "FGCOLOR", NULL, NULL, IUPAF_SAMEASSYSTEM, "TXTFGCOLOR", IUPAF_NOT_MAPPED);
+diff --git a/iup/src/win/iupwin_loop.c b/iup/src/win/iupwin_loop.c
+index 7c5dbe7..fd25537 100755
+--- a/iup/src/win/iupwin_loop.c
++++ b/iup/src/win/iupwin_loop.c
+@@ -106,6 +106,18 @@ int IupMainLoop(void)
+ return IUP_NOERROR;
+ }
+ 
++int IupLoopStepWait(void)
++{
++ MSG msg;
++ int ret = GetMessage(&msg, NULL, 0, 0);
++ if (ret == -1) /* error */
++ return IUP_ERROR;
++ if (ret == 0 || /* WM_QUIT */
++ winLoopProcessMessage(&msg) == IUP_CLOSE) /* ret != 0 */
++ return IUP_CLOSE;
++ return IUP_DEFAULT;
++}
++
+ int IupLoopStep(void)
+ {
+ MSG msg;
+diff --git a/iup/src/win/iupwin_menu.c b/iup/src/win/iupwin_menu.c
+index 74a8b52..06ad93e 100755
+--- a/iup/src/win/iupwin_menu.c
++++ b/iup/src/win/iupwin_menu.c
+@@ -385,7 +385,10 @@ static int winMenuMapMethod(Ihandle* ih)
+ static void winMenuUnMapMethod(Ihandle* ih)
+ {
+ if (iupMenuIsMenuBar(ih))
++ {
+ SetMenu(ih->parent->handle, NULL);
++ ih->parent = NULL;
++ }
+ 
+ DestroyMenu((HMENU)ih->handle); /* DestroyMenu is recursive */
+ }
+diff --git a/iup/src/win/iupwin_open.c b/iup/src/win/iupwin_open.c
+index 7357cde..3629ce4 100755
+--- a/iup/src/win/iupwin_open.c
++++ b/iup/src/win/iupwin_open.c
+@@ -76,8 +76,9 @@ int iupdrvOpen(int *argc, char ***argv)
+ iupwin_hinstance = GetModuleHandle(NULL);
+ IupSetGlobal("HINSTANCE", (char*)iupwin_hinstance);
+ }
+-
+- CoInitializeEx(NULL, COINIT_APARTMENTTHREADED);
++ 
++ if (CoInitializeEx(NULL, COINIT_APARTMENTTHREADED)==RPC_E_CHANGED_MODE)
++ IupSetGlobal("_IUPWIN_COINIT_MULTITHREADED", "1");
+ 
+ {
+ INITCOMMONCONTROLSEX InitCtrls;
+diff --git a/iup/src/win/iupwin_progressbar.c b/iup/src/win/iupwin_progressbar.c
+index 9038d79..4a52cc4 100755
+--- a/iup/src/win/iupwin_progressbar.c
++++ b/iup/src/win/iupwin_progressbar.c
+@@ -106,7 +106,7 @@ static int winProgressBarSetFgColorAttrib(Ihandle* ih, const char* value)
+ 
+ static int winProgressBarMapMethod(Ihandle* ih)
+ {
+- DWORD dwStyle = WS_CHILD;
++ DWORD dwStyle = WS_CHILD|WS_CLIPSIBLINGS;
+ 
+ if (!ih->parent)
+ return IUP_ERROR;
+diff --git a/iup/src/win/iupwin_tabs.c b/iup/src/win/iupwin_tabs.c
+index 682f451..b39f7fe 100755
+--- a/iup/src/win/iupwin_tabs.c
++++ b/iup/src/win/iupwin_tabs.c
+@@ -232,10 +232,7 @@ static HWND winTabCreatePageWindow(Ihandle* ih)
+ DWORD dwStyle = WS_CHILD|WS_CLIPSIBLINGS, 
+ dwExStyle = 0;
+ 
+- if (iupAttribGetBoolean(IupGetDialog(ih), "COMPOSITED"))
+- dwExStyle |= WS_EX_COMPOSITED;
+- else
+- dwStyle |= WS_CLIPCHILDREN;
++ iupwinGetNativeParentStyle(ih, &dwExStyle, &dwStyle);
+ 
+ hWnd = CreateWindowEx(dwExStyle, "IupTabsPage", NULL, dwStyle, 
+ 0, 0, CW_USEDEFAULT, CW_USEDEFAULT, 
+@@ -255,9 +252,12 @@ static int winTabsSetPaddingAttrib(Ihandle* ih, const char* value)
+ iupStrToIntInt(value, &ih->data->horiz_padding, &ih->data->vert_padding, 'x');
+ 
+ if (ih->handle)
++ {
+ SendMessage(ih->handle, TCM_SETPADDING, 0, MAKELPARAM(ih->data->horiz_padding, ih->data->vert_padding));
+-
+- return 0;
++ return 0;
++ }
++ else
++ return 1; /* store until not mapped, when mapped will be set again */
+ }
+ 
+ static int winTabsSetMultilineAttrib(Ihandle* ih, const char* value)
+@@ -368,6 +368,13 @@ static char* winTabsGetBgColorAttrib(Ihandle* ih)
+ return IupGetGlobal("DLGBGCOLOR");
+ }
+ 
++static int winTabsSetBgColorAttrib(Ihandle *ih, const char *value)
++{
++ (void)value;
++ iupdrvPostRedraw(ih);
++ return 1;
++}
++
+ 
+ /* ------------------------------------------------------------------------- */
+ /* winTabs - Calls the user callback to change of tab */
+@@ -397,6 +404,7 @@ static int winTabsWmNotify(Ihandle* ih, NMHDR* msg_info, int *result)
+ int prev_pos = SendMessage(ih->handle, TCM_GETCURSEL, 0, 0);
+ iupAttribSetInt(ih, "_IUPTABS_PREV_CHILD_POS", prev_pos);
+ 
++ /* save the previous handle if callback exists */
+ if (cb)
+ {
+ Ihandle* prev_child = IupGetChild(ih, prev_pos);
+@@ -420,7 +428,9 @@ static int winTabsWmNotify(Ihandle* ih, NMHDR* msg_info, int *result)
+ Ihandle* prev_child = (Ihandle*)iupAttribGet(ih, "_IUPTABS_PREV_CHILD");
+ iupAttribSetStr(ih, "_IUPTABS_PREV_CHILD", NULL);
+ 
+- cb(ih, child, prev_child);
++ /* avoid duplicate calls when a Tab is inside another Tab. */
++ if (prev_child)
++ cb(ih, child, prev_child);
+ }
+ }
+ 
+@@ -522,7 +532,7 @@ static void winTabsChildAddedMethod(Ihandle* ih, Ihandle* child)
+ }
+ }
+ 
+- iupdrvDisplayRedraw(ih);
++ iupdrvRedrawNow(ih);
+ }
+ }
+ }
+@@ -535,12 +545,11 @@ static void winTabsChildRemovedMethod(Ihandle* ih, Ihandle* child)
+ if (tab_page)
+ {
+ int pos = winTabsGetPageWindowPos(ih, tab_page);
++ iupTabsTestRemoveTab(ih, pos);
++
+ SendMessage(ih->handle, TCM_DELETEITEM, pos, 0);
+ DestroyWindow(tab_page);
+ 
+- if (pos==0) pos++;
+- iupdrvTabsSetCurrentTab(ih, pos-1);
+-
+ iupAttribSetStr(child, "_IUPTAB_CONTAINER", NULL);
+ }
+ }
+@@ -564,19 +573,14 @@ static int winTabsMapMethod(Ihandle* ih)
+ if (ih->data->is_multiline)
+ dwStyle |= TCS_MULTILINE;
+ 
+- if (iupAttribGetBoolean(IupGetDialog(ih), "COMPOSITED"))
+- {
+- dwExStyle |= WS_EX_COMPOSITED;
++ iupwinGetNativeParentStyle(ih, &dwExStyle, &dwStyle);
+ 
+- if (!ih->data->is_multiline && iupwinIsVista())
+- {
+- /* workaround for composite bug in Vista */
+- ih->data->is_multiline = 1; 
+- dwStyle |= TCS_MULTILINE;
+- }
++ if (dwExStyle & WS_EX_COMPOSITED && !ih->data->is_multiline && iupwinIsVistaOrNew())
++ {
++ /* workaround for composite bug in Vista */
++ ih->data->is_multiline = 1; 
++ dwStyle |= TCS_MULTILINE;
+ }
+- else
+- dwStyle |= WS_CLIPCHILDREN;
+ 
+ if (!iupwinCreateWindowEx(ih, WC_TABCONTROL, dwExStyle, dwStyle))
+ return IUP_ERROR;
+@@ -665,7 +669,7 @@ void iupdrvTabsInitClass(Iclass* ic)
+ /* Driver Dependent Attribute functions */
+ 
+ /* Visual */
+- iupClassRegisterAttribute(ic, "BGCOLOR", winTabsGetBgColorAttrib, NULL, IUPAF_SAMEASSYSTEM, "DLGBGCOLOR", IUPAF_DEFAULT); 
++ iupClassRegisterAttribute(ic, "BGCOLOR", winTabsGetBgColorAttrib, winTabsSetBgColorAttrib, IUPAF_SAMEASSYSTEM, "DLGBGCOLOR", IUPAF_DEFAULT);
+ 
+ /* Special */
+ iupClassRegisterAttribute(ic, "FGCOLOR", NULL, NULL, IUPAF_SAMEASSYSTEM, "DLGFGCOLOR", IUPAF_NOT_MAPPED);
+@@ -676,5 +680,9 @@ void iupdrvTabsInitClass(Iclass* ic)
+ iupClassRegisterAttribute(ic, "MULTILINE", winTabsGetMultilineAttrib, winTabsSetMultilineAttrib, NULL, NULL, IUPAF_NOT_MAPPED|IUPAF_NO_INHERIT);
+ iupClassRegisterAttributeId(ic, "TABTITLE", NULL, winTabsSetTabTitleAttrib, IUPAF_NO_DEFAULTVALUE|IUPAF_NO_INHERIT);
+ iupClassRegisterAttributeId(ic, "TABIMAGE", NULL, winTabsSetTabImageAttrib, IUPAF_NO_DEFAULTVALUE|IUPAF_NO_INHERIT);
+- iupClassRegisterAttribute(ic, "PADDING", iupTabsGetPaddingAttrib, winTabsSetPaddingAttrib, IUPAF_SAMEASSYSTEM, "0x0", IUPAF_NOT_MAPPED);
++ iupClassRegisterAttribute(ic, "PADDING", iupTabsGetPaddingAttrib, winTabsSetPaddingAttrib, IUPAF_SAMEASSYSTEM, "0x0", IUPAF_NOT_MAPPED|IUPAF_NO_INHERIT);
++
++ /* necessary because transparent background does not work when not using visual styles */
++ if (!iupwin_comctl32ver6) /* Used by iupdrvImageCreateImage */
++ iupClassRegisterAttribute(ic, "FLAT_ALPHA", NULL, NULL, IUPAF_SAMEASSYSTEM, "YES", IUPAF_NOT_MAPPED|IUPAF_NO_INHERIT);
+ }
+diff --git a/iup/src/win/iupwin_text.c b/iup/src/win/iupwin_text.c
+index dfe489a..2a61724 100755
+--- a/iup/src/win/iupwin_text.c
++++ b/iup/src/win/iupwin_text.c
+@@ -432,8 +432,8 @@ static int winTextSetLinColToPosition(Ihandle *ih, int lin, int col)
+ col--;
+ 
+ linmax = SendMessage(ih->handle, EM_GETLINECOUNT, 0, 0L);
+- if (lin > linmax)
+- lin = linmax;
++ if (lin > linmax-1)
++ lin = linmax-1;
+ 
+ lineindex = SendMessage(ih->handle, EM_LINEINDEX, (WPARAM)lin, 0L);
+ 
+@@ -639,8 +639,12 @@ static int winTextSetPaddingAttrib(Ihandle* ih, const char* value)
+ iupStrToIntInt(value, &(ih->data->horiz_padding), &(ih->data->vert_padding), 'x');
+ ih->data->vert_padding = 0;
+ if (ih->handle)
++ {
+ SendMessage(ih->handle, EM_SETMARGINS, EC_LEFTMARGIN|EC_RIGHTMARGIN, MAKELPARAM(ih->data->horiz_padding, ih->data->horiz_padding));
+- return 0;
++ return 0;
++ }
++ else
++ return 1; /* store until not mapped, when mapped will be set again */
+ }
+ 
+ static int winTextSetSelectedTextAttrib(Ihandle* ih, const char* value)
+@@ -713,8 +717,11 @@ static int winTextSetNCAttrib(Ihandle* ih, const char* value)
+ SendMessage(ih->handle, EM_EXLIMITTEXT, 0, ih->data->nc); /* so it can be larger than 64k */
+ else
+ SendMessage(ih->handle, EM_LIMITTEXT, ih->data->nc, 0L);
++
++ return 0;
+ }
+- return 0;
++ else
++ return 1; /* store until not mapped, when mapped will be set again */
+ }
+ 
+ static int winTextSetSelectionAttrib(Ihandle* ih, const char* value)
+@@ -845,7 +852,7 @@ static char* winTextGetSelectionPosAttrib(Ihandle* ih)
+ 
+ static int winTextSetInsertAttrib(Ihandle* ih, const char* value)
+ {
+- if (!ih->handle) /* do not store the action before map */
++ if (!ih->handle) /* do not do the action before map */
+ return 0;
+ if (value)
+ {
+@@ -867,9 +874,9 @@ static int winTextSetInsertAttrib(Ihandle* ih, const char* value)
+ 
+ static int winTextSetAppendAttrib(Ihandle* ih, const char* value)
+ {
+- int len;
++ int pos;
+ char* str;
+- if (!ih->handle) /* do not store the action before map */
++ if (!ih->handle) /* do not do the action before map */
+ return 0;
+ if (!value) value = "";
+ str = (char*)value;
+@@ -881,9 +888,9 @@ static int winTextSetAppendAttrib(Ihandle* ih, const char* value)
+ str = iupStrToDos(str);
+ }
+ 
+- len = GetWindowTextLength(ih->handle)+1;
+- SendMessage(ih->handle, EM_SETSEL, (WPARAM)len, (LPARAM)len);
+- if (ih->data->is_multiline && ih->data->append_newline)
++ pos = GetWindowTextLength(ih->handle)+1;
++ SendMessage(ih->handle, EM_SETSEL, (WPARAM)pos, (LPARAM)pos);
++ if (ih->data->is_multiline && ih->data->append_newline && pos!=1)
+ {
+ if (ih->data->has_formatting)
+ SendMessage(ih->handle, EM_REPLACESEL, (WPARAM)FALSE, (LPARAM)"\r");
+@@ -920,7 +927,7 @@ static int winTextSetTabSizeAttrib(Ihandle* ih, const char* value)
+ iupStrToInt(value, &tabsize);
+ tabsize *= 4;
+ SendMessage(ih->handle, EM_SETTABSTOPS, (WPARAM)1L, (LPARAM)&tabsize);
+- iupdrvDisplayRedraw(ih);
++ iupdrvRedrawNow(ih);
+ return 1;
+ }
+ 
+@@ -1120,6 +1127,7 @@ static int winTextSetBgColorAttrib(Ihandle *ih, const char *value)
+ SendMessage(ih->handle, EM_SETBKGNDCOLOR, 0, (LPARAM)color);
+ }
+ }
++ iupdrvPostRedraw(ih);
+ return 1;
+ }
+ 
+@@ -1529,15 +1537,27 @@ static int winTextProc(Ihandle* ih, UINT msg, WPARAM wp, LPARAM lp, LRESULT *res
+ ret = iupwinBaseProc(ih, msg, wp, lp, result);
+ if (ret) 
+ {
++ iupAttribSetStr(ih, "_IUPWIN_IGNORE_CHAR", "1");
+ *result = 0;
+ return 1;
+ }
++ else
++ iupAttribSetStr(ih, "_IUPWIN_IGNORE_CHAR", NULL);
+ }
+ 
+ switch (msg)
+ {
+ case WM_CHAR:
+ {
++ /* even aborting WM_KEYDOWN, a WM_CHAR will be sent, so ignore it also */
++ /* if a dialog was shown, the loop will be processed, so ignore out of focus WM_CHAR messages */
++ if (GetFocus() != ih->handle || iupAttribGet(ih, "_IUPWIN_IGNORE_CHAR"))
++ {
++ iupAttribSetStr(ih, "_IUPWIN_IGNORE_CHAR", NULL);
++ *result = 0;
++ return 1;
++ }
++
+ if ((char)wp == '\b')
+ { 
+ if (!winTextCallActionCb(ih, NULL, 0, -1))
+@@ -1736,7 +1756,7 @@ static int winTextProc(Ihandle* ih, UINT msg, WPARAM wp, LPARAM lp, LRESULT *res
+ static void winTextCreateSpin(Ihandle* ih)
+ {
+ HWND hSpin;
+- DWORD dwStyle = WS_CHILD|UDS_ARROWKEYS|UDS_HOTTRACK|UDS_NOTHOUSANDS;
++ DWORD dwStyle = WS_CHILD|WS_CLIPSIBLINGS|UDS_ARROWKEYS|UDS_HOTTRACK|UDS_NOTHOUSANDS;
+ int serial = iupDialogGetChildId(ih);
+ 
+ if (iupStrEqualNoCase(iupAttribGetStr(ih, "SPINALIGN"), "LEFT"))
+@@ -1826,7 +1846,7 @@ static void winTextLayoutUpdateMethod(Ihandle* ih)
+ 
+ static int winTextMapMethod(Ihandle* ih)
+ {
+- DWORD dwStyle = WS_CHILD, 
++ DWORD dwStyle = WS_CHILD|WS_CLIPSIBLINGS, 
+ dwExStyle = 0;
+ char* winclass = "EDIT", *value;
+ 
+@@ -1873,7 +1893,7 @@ static int winTextMapMethod(Ihandle* ih)
+ }
+ else
+ {
+- dwStyle |= ES_AUTOHSCROLL|ES_NOHIDESEL;
++ dwStyle |= ES_AUTOHSCROLL;
+ 
+ if (iupAttribGetBoolean(ih, "PASSWORD"))
+ dwStyle |= ES_PASSWORD;
+@@ -1950,8 +1970,8 @@ void iupdrvTextInitClass(Iclass* ic)
+ iupClassRegisterAttribute(ic, "STANDARDFONT", NULL, winTextSetStandardFontAttrib, IUPAF_SAMEASSYSTEM, "DEFAULTFONT", IUPAF_NOT_MAPPED);
+ 
+ /* Overwrite Visual */
+- iupClassRegisterAttribute(ic, "BGCOLOR", NULL, winTextSetBgColorAttrib, IUPAF_SAMEASSYSTEM, "TXTBGCOLOR", IUPAF_NOT_MAPPED); 
+- iupClassRegisterAttribute(ic, "VISIBLE", iupBaseGetVisibleAttrib, winTextSetVisibleAttrib, IUPAF_SAMEASSYSTEM, "YES", IUPAF_NO_INHERIT);
++ iupClassRegisterAttribute(ic, "BGCOLOR", NULL, winTextSetBgColorAttrib, IUPAF_SAMEASSYSTEM, "TXTBGCOLOR", IUPAF_DEFAULT); 
++ iupClassRegisterAttribute(ic, "VISIBLE", iupBaseGetVisibleAttrib, winTextSetVisibleAttrib, "YES", "NO", IUPAF_DEFAULT);
+ 
+ /* Special */
+ iupClassRegisterAttribute(ic, "FGCOLOR", NULL, NULL, IUPAF_SAMEASSYSTEM, "TXTFGCOLOR", IUPAF_NOT_MAPPED); /* usually black */ 
+diff --git a/iup/src/win/iupwin_toggle.c b/iup/src/win/iupwin_toggle.c
+index fcaa438..c17f594 100755
+--- a/iup/src/win/iupwin_toggle.c
++++ b/iup/src/win/iupwin_toggle.c
+@@ -35,7 +35,9 @@
+ 
+ void iupdrvToggleAddCheckBox(int *x, int *y)
+ {
+- (*x) += 16+6;
++ (*x) += 16+8;
++ if (!iupwin_comctl32ver6)
++ (*x) += 4;
+ if ((*y) < 16) (*y) = 16; /* minimum height */
+ }
+ 
+@@ -229,7 +231,7 @@ static int winToggleSetImageAttrib(Ihandle* ih, const char* value)
+ iupAttribSetStr(ih, "IMAGE", (char*)value);
+ 
+ if (iupwin_comctl32ver6)
+- iupdrvDisplayRedraw(ih);
++ iupdrvRedrawNow(ih);
+ else
+ {
+ int check = SendMessage(ih->handle, BM_GETCHECK, 0L, 0L);
+@@ -249,7 +251,7 @@ static int winToggleSetImInactiveAttrib(Ihandle* ih, const char* value)
+ iupAttribSetStr(ih, "IMINACTIVE", (char*)value);
+ 
+ if (iupwin_comctl32ver6)
+- iupdrvDisplayRedraw(ih);
++ iupdrvRedrawNow(ih);
+ else
+ {
+ int check = SendMessage(ih->handle, BM_GETCHECK, 0L, 0L);
+@@ -269,7 +271,7 @@ static int winToggleSetImPressAttrib(Ihandle* ih, const char* value)
+ iupAttribSetStr(ih, "IMPRESS", (char*)value);
+ 
+ if (iupwin_comctl32ver6)
+- iupdrvDisplayRedraw(ih);
++ iupdrvRedrawNow(ih);
+ else
+ {
+ int check = SendMessage(ih->handle, BM_GETCHECK, 0L, 0L);
+@@ -339,7 +341,7 @@ static int winToggleSetActiveAttrib(Ihandle* ih, const char* value)
+ if (iupwin_comctl32ver6)
+ {
+ iupBaseSetActiveAttrib(ih, value);
+- iupdrvDisplayRedraw(ih);
++ iupdrvRedrawNow(ih);
+ return 0;
+ }
+ else
+@@ -382,11 +384,21 @@ static int winToggleSetPaddingAttrib(Ihandle* ih, const char* value)
+ iupStrToIntInt(value, &ih->data->horiz_padding, &ih->data->vert_padding, 'x');
+ 
+ if (ih->handle && iupwin_comctl32ver6 && ih->data->type == IUP_TOGGLE_IMAGE)
+- iupdrvDisplayRedraw(ih);
++ iupdrvRedrawNow(ih);
+ 
+ return 0;
+ }
+ 
++static int winToggleSetUpdateAttrib(Ihandle* ih, const char* value)
++{
++ (void)value;
++
++ if (ih->handle)
++ iupdrvPostRedraw(ih); /* Post a redraw */
++
++ return 1;
++}
++
+ static int winToggleSetBgColorAttrib(Ihandle* ih, const char* value)
+ {
+ (void)value;
+@@ -395,7 +407,7 @@ static int winToggleSetBgColorAttrib(Ihandle* ih, const char* value)
+ /* update internal image cache for controls that have the IMAGE attribute */
+ iupAttribSetStr(ih, "BGCOLOR", value);
+ iupImageUpdateParent(ih);
+- iupdrvDisplayRedraw(ih);
++ iupdrvRedrawNow(ih);
+ }
+ return 1;
+ }
+@@ -591,7 +603,7 @@ static int winToggleMapMethod(Ihandle* ih)
+ {
+ Ihandle* radio = iupRadioFindToggleParent(ih);
+ char* value;
+- DWORD dwStyle = WS_CHILD | 
++ DWORD dwStyle = WS_CHILD | WS_CLIPSIBLINGS |
+ BS_NOTIFY; /* necessary because of the base messages */
+ 
+ if (!ih->parent)
+@@ -673,11 +685,11 @@ void iupdrvToggleInitClass(Iclass* ic)
+ iupClassRegisterAttribute(ic, "BGCOLOR", winToggleGetBgColorAttrib, winToggleSetBgColorAttrib, IUPAF_SAMEASSYSTEM, "DLGBGCOLOR", IUPAF_DEFAULT); 
+ 
+ /* Special */
+- iupClassRegisterAttribute(ic, "FGCOLOR", NULL, NULL, "DLGFGCOLOR", NULL, IUPAF_NOT_MAPPED); /* force the new default value */ 
++ iupClassRegisterAttribute(ic, "FGCOLOR", NULL, winToggleSetUpdateAttrib, "DLGFGCOLOR", NULL, IUPAF_NOT_MAPPED); /* force the new default value */ 
+ iupClassRegisterAttribute(ic, "TITLE", iupdrvBaseGetTitleAttrib, winToggleSetTitleAttrib, NULL, NULL, IUPAF_NO_DEFAULTVALUE|IUPAF_NO_INHERIT);
+ 
+ /* IupToggle only */
+- iupClassRegisterAttribute(ic, "ALIGNMENT", NULL, NULL, IUPAF_SAMEASSYSTEM, "ACENTER:ACENTER", IUPAF_NO_INHERIT);
++ iupClassRegisterAttribute(ic, "ALIGNMENT", NULL, winToggleSetUpdateAttrib, IUPAF_SAMEASSYSTEM, "ACENTER:ACENTER", IUPAF_NO_INHERIT);
+ iupClassRegisterAttribute(ic, "IMAGE", NULL, winToggleSetImageAttrib, NULL, NULL, IUPAF_NO_DEFAULTVALUE|IUPAF_NO_INHERIT);
+ iupClassRegisterAttribute(ic, "IMINACTIVE", NULL, winToggleSetImInactiveAttrib, NULL, NULL, IUPAF_NO_DEFAULTVALUE|IUPAF_NO_INHERIT);
+ iupClassRegisterAttribute(ic, "IMPRESS", NULL, winToggleSetImPressAttrib, NULL, NULL, IUPAF_NO_DEFAULTVALUE|IUPAF_NO_INHERIT);
+diff --git a/iup/src/win/iupwin_tree.c b/iup/src/win/iupwin_tree.c
+index e6877dc..4a5f8be 100755
+--- a/iup/src/win/iupwin_tree.c
++++ b/iup/src/win/iupwin_tree.c
+@@ -31,17 +31,19 @@
+ #include "iupwin_draw.h"
+ #include "iupwin_info.h"
+ 
++
+ typedef struct _winTreeItemData
+ {
+ COLORREF color;
+ unsigned char kind;
+- void* userdata;
+ HFONT hFont;
+ short image;
+ short image_expanded;
+ } winTreeItemData;
+ 
+-#ifndef TVN_ITEMCHANGING /* Vista Only */
++/* Vista Only */
++
++#ifndef TVN_ITEMCHANGING 
+ typedef struct tagNMTVITEMCHANGE {
+ NMHDR hdr;
+ UINT uChanged;
+@@ -54,257 +56,125 @@ typedef struct tagNMTVITEMCHANGE {
+ #define TVN_ITEMCHANGINGW (TVN_FIRST-17) 
+ #endif
+ 
+-static void winTreeSetFocusNode(Ihandle* ih, HTREEITEM hItem);
+-typedef int (*winTreeNodeFunc)(Ihandle* ih, HTREEITEM hItem, void* userdata);
+-
+-static int winTreeForEach(Ihandle* ih, HTREEITEM hItem, winTreeNodeFunc func, void* userdata)
+-{
+- HTREEITEM hItemChild;
+-
+- if (!hItem)
+- hItem = (HTREEITEM)SendMessage(ih->handle, TVM_GETNEXTITEM, TVGN_ROOT, 0);
++#ifndef TVS_EX_DOUBLEBUFFER
++#define TVS_EX_DOUBLEBUFFER 0x0004
++#endif
+ 
+- while(hItem != NULL)
+- {
+- if (!func(ih, hItem, userdata))
+- return 0;
++#ifndef TVM_SETEXTENDEDSTYLE
++#define TVM_SETEXTENDEDSTYLE (TV_FIRST + 44)
++#endif
+ 
+- hItemChild = (HTREEITEM)SendMessage(ih->handle, TVM_GETNEXTITEM, TVGN_CHILD, (LPARAM)hItem);
+- if (hItemChild)
+- {
+- /* Recursively traverse child items */
+- if (!winTreeForEach(ih, hItemChild, func, userdata))
+- return 0;
+- }
+ 
+- /* Go to next sibling item */
+- hItem = (HTREEITEM)SendMessage(ih->handle, TVM_GETNEXTITEM, TVGN_NEXT, (LPARAM)hItem);
+- }
++static void winTreeSetFocusNode(Ihandle* ih, HTREEITEM hItem);
+ 
+- return 1;
+-}
+ 
+ /*****************************************************************************/
+ /* FINDING ITEMS */
+ /*****************************************************************************/
+-static HTREEITEM winTreeFindNodeID(Ihandle* ih, HTREEITEM hItem, HTREEITEM hNode)
+-{
+- TVITEM item;
+- winTreeItemData* itemData;
+-
+- while(hItem != NULL)
+- {
+- /* ID control to traverse items */
+- ih->data->id_control++;
+-
+- /* StateID founded! */
+- if(hItem == hNode)
+- return hItem;
+ 
+- /* Get hItem attributes */
+- item.hItem = hItem;
+- item.mask = TVIF_HANDLE|TVIF_PARAM;
+- SendMessage(ih->handle, TVM_GETITEM, 0, (LPARAM)(LPTVITEM)&item);
+- itemData = (winTreeItemData*)item.lParam;
+-
+- /* Check whether we have child items */
+- if (itemData->kind == ITREE_BRANCH)
+- {
+- /* Recursively traverse child items */
+- HTREEITEM hItemChild = (HTREEITEM)SendMessage(ih->handle, TVM_GETNEXTITEM, TVGN_CHILD, (LPARAM)hItem);
+- hItemChild = winTreeFindNodeID(ih, hItemChild, hNode);
+-
+- /* StateID founded! */
+- if(hItemChild)
+- return hItemChild;
+- }
+- /* Go to next sibling item */
+- hItem = (HTREEITEM)SendMessage(ih->handle, TVM_GETNEXTITEM, TVGN_NEXT, (LPARAM)hItem);
+- }
+-
+- return NULL;
++InodeHandle* iupdrvTreeGetFocusNode(Ihandle* ih)
++{
++ return (InodeHandle*)SendMessage(ih->handle, TVM_GETNEXTITEM, TVGN_CARET, 0);
+ }
+ 
+-static int winTreeGetNodeId(Ihandle* ih, HTREEITEM hItem)
++static HTREEITEM winTreeFindNodeXY(Ihandle* ih, int x, int y)
+ {
+- HTREEITEM hItemRoot = (HTREEITEM)SendMessage(ih->handle, TVM_GETNEXTITEM, TVGN_ROOT, 0);
+- ih->data->id_control = -1;
+- if (winTreeFindNodeID(ih, hItemRoot, hItem))
+- return ih->data->id_control;
+- else
+- return -1;
++ TVHITTESTINFO info;
++ info.pt.x = x;
++ info.pt.y = y;
++ return (HTREEITEM)SendMessage(ih->handle, TVM_HITTEST, 0, (LPARAM)(LPTVHITTESTINFO)&info);
+ }
+ 
+-static HTREEITEM winTreeFindUserDataID(Ihandle* ih, HTREEITEM hItem, void* userdata)
++static HTREEITEM winTreeFindNodePointed(Ihandle* ih)
+ {
+- TVITEM item;
+- winTreeItemData* itemData;
+-
+- while(hItem != NULL)
+- {
+- /* ID control to traverse items */
+- ih->data->id_control++;
+-
+- /* Get hItem attributes */
+- item.hItem = hItem;
+- item.mask = TVIF_HANDLE|TVIF_PARAM;
+- SendMessage(ih->handle, TVM_GETITEM, 0, (LPARAM)(LPTVITEM)&item);
+- itemData = (winTreeItemData*)item.lParam;
+-
+- /* userdata founded! */
+- if(itemData->userdata == userdata)
+- return hItem;
+-
+- /* Check whether we have child items */
+- if (itemData->kind == ITREE_BRANCH)
+- {
+- /* Recursively traverse child items */
+- HTREEITEM hItemChild = (HTREEITEM)SendMessage(ih->handle, TVM_GETNEXTITEM, TVGN_CHILD, (LPARAM)hItem);
+- hItemChild = winTreeFindUserDataID(ih, hItemChild, userdata);
+-
+- /* userdata founded! */
+- if (hItemChild)
+- return hItemChild;
+- }
+-
+- /* Go to next sibling item */
+- hItem = (HTREEITEM)SendMessage(ih->handle, TVM_GETNEXTITEM, TVGN_NEXT, (LPARAM)hItem);
+- }
+-
+- return NULL;
++ TVHITTESTINFO info;
++ DWORD pos = GetMessagePos();
++ info.pt.x = LOWORD(pos);
++ info.pt.y = HIWORD(pos);
++ ScreenToClient(ih->handle, &info.pt);
++ return (HTREEITEM)SendMessage(ih->handle, TVM_HITTEST, 0, (LPARAM)(LPTVHITTESTINFO)&info);
+ }
+ 
+-static int winTreeGetUserDataId(Ihandle* ih, void* userdata)
++int iupwinGetColor(const char* value, COLORREF *color)
+ {
+- HTREEITEM hItemRoot = (HTREEITEM)SendMessage(ih->handle, TVM_GETNEXTITEM, TVGN_ROOT, 0);
+- ih->data->id_control = -1;
+- if (winTreeFindUserDataID(ih, hItemRoot, userdata))
+- return ih->data->id_control;
+- else
+- return -1;
++ unsigned char r, g, b;
++ if (iupStrToRGB(value, &r, &g, &b))
++ {
++ *color = RGB(r,g,b);
++ return 1;
++ }
++ return 0;
+ }
+ 
+-static HTREEITEM winTreeFindNodeFromID(Ihandle* ih, HTREEITEM hItem)
++static void winTreeChildCountRec(Ihandle* ih, HTREEITEM hItem, int *count)
+ {
+- TVITEM item;
+- winTreeItemData* itemData;
+-
++ hItem = (HTREEITEM)SendMessage(ih->handle, TVM_GETNEXTITEM, TVGN_CHILD, (LPARAM)hItem);
+ while(hItem != NULL)
+ {
+- /* ID control to traverse items */
+- ih->data->id_control--;
+-
+- /* StateID founded! */
+- if(ih->data->id_control < 0)
+- return hItem;
+-
+- /* Get hItem attributes */
+- item.hItem = hItem;
+- item.mask = TVIF_HANDLE|TVIF_PARAM;
+- SendMessage(ih->handle, TVM_GETITEM, 0, (LPARAM)(LPTVITEM)&item);
+- itemData = (winTreeItemData*)item.lParam;
+-
+- /* Check whether we have child items */
+- if (itemData->kind == ITREE_BRANCH)
+- {
+- /* Recursively traverse child items */
+- HTREEITEM hItemChild = (HTREEITEM)SendMessage(ih->handle, TVM_GETNEXTITEM, TVGN_CHILD, (LPARAM)hItem);
+- hItemChild = winTreeFindNodeFromID(ih, hItemChild);
++ (*count)++;
+ 
+- /* StateID founded! */
+- if(ih->data->id_control < 0)
+- return hItemChild;
+- }
++ /* go recursive to children */
++ winTreeChildCountRec(ih, hItem, count);
+ 
+ /* Go to next sibling item */
+ hItem = (HTREEITEM)SendMessage(ih->handle, TVM_GETNEXTITEM, TVGN_NEXT, (LPARAM)hItem);
+ }
+-
+- return hItem;
+ }
+ 
+-static HTREEITEM winTreeFindNodeFromString(Ihandle* ih, const char* name_id)
++int iupdrvTreeTotalChildCount(Ihandle* ih, HTREEITEM hItem)
+ {
+- if (name_id[0])
+- {
+- HTREEITEM hRoot = (HTREEITEM)SendMessage(ih->handle, TVM_GETNEXTITEM, TVGN_ROOT, 0);
+- iupStrToInt(name_id, &ih->data->id_control);
+- return winTreeFindNodeFromID(ih, hRoot);
+- }
+- else
+- return (HTREEITEM)SendMessage(ih->handle, TVM_GETNEXTITEM, TVGN_CARET, 0);
++ int count = 0;
++ winTreeChildCountRec(ih, hItem, &count);
++ return count;
+ }
+ 
+-/* Recursively, find a new brother for the item
+- that will have its depth changed. Returns the new brother. */
+-static HTREEITEM winTreeFindNewBrother(Ihandle* ih, HTREEITEM hBrotherItem)
++static void winTreeChildRebuildCacheRec(Ihandle* ih, HTREEITEM hItem, int *id)
+ {
+- TVITEM item;
+- winTreeItemData* itemData;
+-
+- while(hBrotherItem != NULL)
++ hItem = (HTREEITEM)SendMessage(ih->handle, TVM_GETNEXTITEM, TVGN_CHILD, (LPARAM)hItem);
++ while(hItem != NULL)
+ {
+- if(ih->data->id_control < 0)
+- return hBrotherItem;
+-
+- item.hItem = hBrotherItem;
+- item.mask = TVIF_HANDLE|TVIF_PARAM;
+- SendMessage(ih->handle, TVM_GETITEM, 0, (LPARAM)(LPTVITEM)&item);
+- itemData = (winTreeItemData*)item.lParam;
+-
+- if (itemData->kind == ITREE_BRANCH)
+- {
+- HTREEITEM hItemChild;
+-
+- ih->data->id_control--;
+- hItemChild = winTreeFindNewBrother(ih, (HTREEITEM)SendMessage(ih->handle, TVM_GETNEXTITEM, TVGN_CHILD, (LPARAM)hBrotherItem));
++ (*id)++;
++ ih->data->node_cache[*id].node_handle = hItem;
+ 
+- if(ih->data->id_control < 0)
+- return hItemChild;
+- }
++ /* go recursive to children */
++ winTreeChildRebuildCacheRec(ih, hItem, id);
+ 
+- hBrotherItem = (HTREEITEM)SendMessage(ih->handle, TVM_GETNEXTITEM, TVGN_NEXT, (LPARAM)hBrotherItem);
++ /* Go to next sibling item */
++ hItem = (HTREEITEM)SendMessage(ih->handle, TVM_GETNEXTITEM, TVGN_NEXT, (LPARAM)hItem);
+ }
+-
+- return hBrotherItem;
+ }
+ 
+-static HTREEITEM winTreeFindNodePointed(Ihandle* ih)
++static void winTreeRebuildNodeCache(Ihandle* ih, int id, HTREEITEM hItem)
+ {
+- TVHITTESTINFO info;
+- DWORD pos = GetMessagePos();
+- info.pt.x = LOWORD(pos);
+- info.pt.y = HIWORD(pos);
+-
+- ScreenToClient(ih->handle, &info.pt);
+- 
+- return (HTREEITEM)SendMessage(ih->handle, TVM_HITTEST, 0, (LPARAM)(LPTVHITTESTINFO)&info);
++ ih->data->node_cache[id].node_handle = hItem;
++ winTreeChildRebuildCacheRec(ih, hItem, &id);
+ }
+ 
+-int iupwinGetColor(const char* value, COLORREF *color)
+-{
+- unsigned char r, g, b;
+- if (iupStrToRGB(value, &r, &g, &b))
+- {
+- *color = RGB(r,g,b);
+- return 1;
+- }
+- return 0;
+-}
+ 
+ /*****************************************************************************/
+ /* ADDING ITEMS */
+ /*****************************************************************************/
++
++static void winTreeExpandItem(Ihandle* ih, HTREEITEM hItem, int expand);
++
+ void iupdrvTreeAddNode(Ihandle* ih, const char* name_id, int kind, const char* title, int add)
+ {
+- TVITEM item, tviPrevItem;
++ TVITEM item;
+ TVINSERTSTRUCT tvins;
+- HTREEITEM hPrevItem = winTreeFindNodeFromString(ih, name_id);
+- int kindPrev;
++ HTREEITEM hPrevItem = iupTreeGetNodeFromString(ih, name_id);
++ HTREEITEM hItemNew;
+ winTreeItemData* itemData;
+ 
+ if (!hPrevItem)
+- return;
++ {
++ /* check if the root was really specified */
++ int id = 0;
++ if (!iupStrToInt(name_id, &id) || id != -1)
++ return;
++ }
++
++ if (!title)
++ title = "";
+ 
+ itemData = calloc(1, sizeof(winTreeItemData));
+ itemData->image = -1;
+@@ -318,83 +188,71 @@ void iupdrvTreeAddNode(Ihandle* ih, const char* name_id, int kind, const char* t
+ iupwinGetColor(iupAttribGetStr(ih, "FGCOLOR"), &itemData->color);
+ 
+ if (kind == ITREE_BRANCH)
+- {
+ item.iSelectedImage = item.iImage = (int)ih->data->def_image_collapsed;
+-
+- if (ih->data->add_expanded)
+- {
+- item.mask |= TVIF_STATE;
+- item.state = item.stateMask = TVIS_EXPANDED;
+- item.iSelectedImage = item.iImage = (int)ih->data->def_image_expanded;
+- }
+- }
+ else
+ item.iSelectedImage = item.iImage = (int)ih->data->def_image_leaf;
+ 
+ /* Save the heading level in the node's application-defined data area */
+ tvins.item = item;
+ 
+- /* get the KIND attribute of node selected */ 
+- tviPrevItem.hItem = hPrevItem;
+- tviPrevItem.mask = TVIF_PARAM|TVIF_CHILDREN; 
+- SendMessage(ih->handle, TVM_GETITEM, 0, (LPARAM)(LPTVITEM)&tviPrevItem);
+- kindPrev = ((winTreeItemData*)tviPrevItem.lParam)->kind;
+-
+- /* Define the parent and the position to the new node inside
+- the list, using the KIND attribute of node selected */
+- if (kindPrev == ITREE_BRANCH && add)
+- {
+- tvins.hParent = hPrevItem;
+- tvins.hInsertAfter = TVI_FIRST; /* insert the new node after item selected, as first child */
+- }
+- else
+- {
+- tvins.hParent = (HTREEITEM)SendMessage(ih->handle, TVM_GETNEXTITEM, TVGN_PARENT, (LPARAM)hPrevItem);
+- tvins.hInsertAfter = hPrevItem; /* insert the new node after item selected */
+- }
+-
+- /* Add the node to the tree-view control */
+- SendMessage(ih->handle, TVM_INSERTITEM, 0, (LPARAM)(LPTVINSERTSTRUCT)&tvins);
+-
+- if (kindPrev == ITREE_BRANCH && tviPrevItem.cChildren==0)
++ if (hPrevItem)
+ {
+- /* this is the first child, redraw to update the '+'/'-' buttons */
+- iupdrvDisplayRedraw(ih);
+- }
+-}
++ int kindPrev;
++ TVITEM tviPrevItem;
+ 
+-static void winTreeAddRootNode(Ihandle* ih)
+-{
+- TVITEM item; 
+- TVINSERTSTRUCT tvins;
+- HTREEITEM hNewItem;
+- winTreeItemData* itemData;
++ /* get the KIND attribute of reference node */ 
++ tviPrevItem.hItem = hPrevItem;
++ tviPrevItem.mask = TVIF_PARAM|TVIF_CHILDREN; 
++ SendMessage(ih->handle, TVM_GETITEM, 0, (LPARAM)(LPTVITEM)&tviPrevItem);
++ kindPrev = ((winTreeItemData*)tviPrevItem.lParam)->kind;
+ 
+- itemData = calloc(1, sizeof(winTreeItemData));
+- itemData->image = -1;
+- itemData->image_expanded = -1;
+- itemData->kind = ITREE_BRANCH;
++ /* Define the parent and the position to the new node inside
++ the list, using the KIND attribute of reference node */
++ if (kindPrev == ITREE_BRANCH && add)
++ {
++ /* depth+1 */
++ tvins.hParent = hPrevItem;
++ tvins.hInsertAfter = TVI_FIRST; /* insert the new node after the reference node, as first child */
++ }
++ else
++ {
++ /* same depth */
++ tvins.hParent = (HTREEITEM)SendMessage(ih->handle, TVM_GETNEXTITEM, TVGN_PARENT, (LPARAM)hPrevItem);
++ tvins.hInsertAfter = hPrevItem; /* insert the new node after reference node */
++ }
+ 
+- item.mask = TVIF_PARAM | TVIF_STATE | TVIF_IMAGE | TVIF_SELECTEDIMAGE; 
+- item.state = item.stateMask = TVIS_EXPANDED;
+- item.iSelectedImage = item.iImage = (int)ih->data->def_image_expanded;
+- item.lParam = (LPARAM)itemData;
++ /* Add the new node */
++ hItemNew = (HTREEITEM)SendMessage(ih->handle, TVM_INSERTITEM, 0, (LPARAM)(LPTVINSERTSTRUCT)&tvins);
++ iupTreeAddToCache(ih, add, kindPrev, hPrevItem, hItemNew);
+ 
+- iupwinGetColor(iupAttribGetStr(ih, "FGCOLOR"), &itemData->color);
++ if (kindPrev == ITREE_BRANCH && tviPrevItem.cChildren==0) /* was 0, now is 1 */
++ {
++ /* this is the first child, redraw to update the '+'/'-' buttons */
++ if (ih->data->add_expanded)
++ winTreeExpandItem(ih, hPrevItem, 1);
++ else
++ winTreeExpandItem(ih, hPrevItem, 0);
++ }
+ 
+- /* Save the heading level in the node's application-defined data area */
+- tvins.item = item; 
+- tvins.hInsertAfter = TVI_FIRST;
+- tvins.hParent = TVI_ROOT;
++ }
++ else
++ {
++ tvins.hInsertAfter = TVI_FIRST;
++ tvins.hParent = TVI_ROOT;
+ 
+- /* Add the node to the tree-view control */
+- hNewItem = (HTREEITEM)SendMessage(ih->handle, TVM_INSERTITEM, 0, (LPARAM)(LPTVINSERTSTRUCT)&tvins);
++ /* Add the new node */
++ hItemNew = (HTREEITEM)SendMessage(ih->handle, TVM_INSERTITEM, 0, (LPARAM)(LPTVINSERTSTRUCT)&tvins);
++ iupTreeAddToCache(ih, 0, 0, NULL, hItemNew);
+ 
+- /* MarkStart node */
+- iupAttribSetStr(ih, "_IUPTREE_MARKSTART_NODE", (char*)hNewItem);
++ if (ih->data->node_count == 1)
++ {
++ /* MarkStart node */
++ iupAttribSetStr(ih, "_IUPTREE_MARKSTART_NODE", (char*)hItemNew);
+ 
+- /* Set the default VALUE */
+- winTreeSetFocusNode(ih, hNewItem);
++ /* Set the default VALUE */
++ winTreeSetFocusNode(ih, hItemNew);
++ }
++ }
+ }
+ 
+ static int winTreeIsItemExpanded(Ihandle* ih, HTREEITEM hItem)
+@@ -408,13 +266,28 @@ static int winTreeIsItemExpanded(Ihandle* ih, HTREEITEM hItem)
+ 
+ static void winTreeExpandItem(Ihandle* ih, HTREEITEM hItem, int expand)
+ {
+- if (expand == -1)
+- expand = !winTreeIsItemExpanded(ih, hItem); /* toggle */
++ TVITEM item;
++ winTreeItemData* itemData;
++
++ iupAttribSetStr(ih, "_IUPTREE_IGNORE_BRANCH_CB", "1");
++ /* it only works if the branch has children */
++ SendMessage(ih->handle, TVM_EXPAND, expand? TVE_EXPAND: TVE_COLLAPSE, (LPARAM)hItem);
++ iupAttribSetStr(ih, "_IUPTREE_IGNORE_BRANCH_CB", NULL);
++
++ /* update image */
++ item.hItem = hItem;
++ item.mask = TVIF_HANDLE|TVIF_PARAM;
++ SendMessage(ih->handle, TVM_GETITEM, 0, (LPARAM)(LPTVITEM)&item);
++ itemData = (winTreeItemData*)item.lParam;
+ 
+ if (expand)
+- SendMessage(ih->handle, TVM_EXPAND, TVE_EXPAND, (LPARAM)hItem);
++ item.iSelectedImage = item.iImage = (itemData->image_expanded!=-1)? itemData->image_expanded: (int)ih->data->def_image_expanded;
+ else
+- SendMessage(ih->handle, TVM_EXPAND, TVE_COLLAPSE, (LPARAM)hItem);
++ item.iSelectedImage = item.iImage = (itemData->image!=-1)? itemData->image: (int)ih->data->def_image_collapsed;
++
++ item.hItem = hItem;
++ item.mask = TVIF_HANDLE | TVIF_IMAGE | TVIF_SELECTEDIMAGE;
++ SendMessage(ih->handle, TVM_SETITEM, 0, (LPARAM)(LPTVITEM)&item);
+ }
+ 
+ /*****************************************************************************/
+@@ -445,12 +318,12 @@ static void winTreeExpandTree(Ihandle* ih, HTREEITEM hItem, int expand)
+ /* SELECTING ITEMS */
+ /*****************************************************************************/
+ 
+-static int winTreeIsItemSelected(Ihandle* ih, HTREEITEM hItem)
++static int winTreeIsNodeSelected(Ihandle* ih, HTREEITEM hItem)
+ {
+ return ((SendMessage(ih->handle, TVM_GETITEMSTATE, (WPARAM)hItem, TVIS_SELECTED)) & TVIS_SELECTED)!=0;
+ }
+ 
+-static void winTreeSelectItem(Ihandle* ih, HTREEITEM hItem, int select)
++static void winTreeSelectNode(Ihandle* ih, HTREEITEM hItem, int select)
+ {
+ TV_ITEM item;
+ item.mask = TVIF_STATE | TVIF_HANDLE;
+@@ -458,16 +331,13 @@ static void winTreeSelectItem(Ihandle* ih, HTREEITEM hItem, int select)
+ item.hItem = hItem;
+ 
+ if (select == -1)
+- select = !winTreeIsItemSelected(ih, hItem);
++ select = !winTreeIsNodeSelected(ih, hItem); /* toggle */
+ 
+ item.state = select ? TVIS_SELECTED : 0;
+ 
++ iupAttribSetStr(ih, "_IUPTREE_IGNORE_SELECTION_CB", "1");
+ SendMessage(ih->handle, TVM_SETITEM, 0, (LPARAM)&item);
+-}
+-
+-static HTREEITEM winTreeGetFocusNode(Ihandle* ih)
+-{
+- return (HTREEITEM)SendMessage(ih->handle, TVM_GETNEXTITEM, TVGN_CARET, 0);
++ iupAttribSetStr(ih, "_IUPTREE_IGNORE_SELECTION_CB", NULL);
+ }
+ 
+ /* ------------Comment from wxWidgets--------------------
+@@ -475,17 +345,17 @@ static HTREEITEM winTreeGetFocusNode(Ihandle* ih)
+ item without changing anything else. */
+ static void winTreeSetFocusNode(Ihandle* ih, HTREEITEM hItem)
+ {
+- HTREEITEM hItemFocus = winTreeGetFocusNode(ih);
++ HTREEITEM hItemFocus = iupdrvTreeGetFocusNode(ih);
+ if (hItem != hItemFocus)
+ {
+ /* remember the selection state of the item */
+- int wasSelected = winTreeIsItemSelected(ih, hItem);
++ int wasSelected = winTreeIsNodeSelected(ih, hItem);
+ int wasFocusSelected = 0;
+ 
+- if (iupwinIsVista())
++ if (iupwinIsVistaOrNew() && iupwin_comctl32ver6)
+ iupAttribSetStr(ih, "_IUPTREE_ALLOW_CHANGE", (char*)hItem); /* Vista Only */
+ else
+- wasFocusSelected = hItemFocus && winTreeIsItemSelected(ih, hItemFocus);
++ wasFocusSelected = hItemFocus && winTreeIsNodeSelected(ih, hItemFocus);
+ 
+ iupAttribSetStr(ih, "_IUPTREE_IGNORE_SELECTION_CB", "1");
+ 
+@@ -493,58 +363,42 @@ static void winTreeSetFocusNode(Ihandle* ih, HTREEITEM hItem)
+ {
+ /* prevent the tree from unselecting the old focus which it would do by default */
+ SendMessage(ih->handle, TVM_SELECTITEM, TVGN_CARET, (LPARAM)NULL); /* remove the focus */
+- winTreeSelectItem(ih, hItemFocus, 1); /* select again */
++ winTreeSelectNode(ih, hItemFocus, 1); /* select again */
+ }
+ 
+ SendMessage(ih->handle, TVM_SELECTITEM, TVGN_CARET, (LPARAM)hItem); /* set focus, selection, and unselect the previous focus */
+ 
+ if (!wasSelected)
+- winTreeSelectItem(ih, hItem, 0); /* need to clear the selection if was not selected */
++ winTreeSelectNode(ih, hItem, 0); /* need to clear the selection if was not selected */
+ 
+ iupAttribSetStr(ih, "_IUPTREE_IGNORE_SELECTION_CB", NULL);
+ iupAttribSetStr(ih, "_IUPTREE_ALLOW_CHANGE", NULL);
+ }
+ }
+ 
+-typedef struct _winTreeRange{
+- HTREEITEM hItem1, hItem2;
+- char inside, clear;
+-}winTreeRange;
+-
+-static int winTreeSelectRangeFunc(Ihandle* ih, HTREEITEM hItem, winTreeRange* range)
++static void winTreeSelectRange(Ihandle* ih, HTREEITEM hItem1, HTREEITEM hItem2, int clear)
+ {
+- int end_range = 0;
+-
+- if (range->inside == 0) /* detect the range start */
++ int i;
++ int id1 = iupTreeFindNodeId(ih, hItem1);
++ int id2 = iupTreeFindNodeId(ih, hItem2);
++ if (id2 == -1) id2 = ih->data->node_count-1;
++ if (id1 > id2)
+ {
+- if (range->hItem1 == hItem) range->inside=1;
+- else if (range->hItem2 == hItem) range->inside=1;
++ int tmp = id1;
++ id1 = id2;
++ id2 = tmp;
+ }
+- else if (range->inside == 1) /* detect the range end */
++
++ for (i = 0; i < ih->data->node_count; i++)
+ {
+- if (range->hItem1 == hItem) end_range=1;
+- else if (range->hItem2 == hItem) end_range=1;
++ if (i < id1 || i > id2)
++ {
++ if (clear)
++ winTreeSelectNode(ih, ih->data->node_cache[i].node_handle, 0);
++ }
++ else
++ winTreeSelectNode(ih, ih->data->node_cache[i].node_handle, 1);
+ }
+-
+- if (range->inside == 1) /* if inside, select */
+- winTreeSelectItem(ih, hItem, 1);
+- else if (range->clear) /* if outside and clear, unselect */
+- winTreeSelectItem(ih, hItem, 0);
+-
+- if (end_range || (range->inside && range->hItem1==range->hItem2))
+- range->inside=-1; /* update after selecting the node */
+-
+- return 1;
+-}
+-
+-static void winTreeSelectRange(Ihandle* ih, HTREEITEM hItemFrom, HTREEITEM hItemTo, int clear)
+-{
+- winTreeRange range;
+- range.hItem1 = hItemFrom;
+- range.hItem2 = hItemTo;
+- range.inside = 0;
+- range.clear = (char)clear;
+- winTreeForEach(ih, NULL, (winTreeNodeFunc)winTreeSelectRangeFunc, &range);
+ }
+ 
+ static void winTreeSelectAll(Ihandle* ih)
+@@ -558,9 +412,10 @@ static void winTreeClearSelection(Ihandle* ih, HTREEITEM hItemExcept)
+ winTreeSelectRange(ih, hItemExcept, hItemExcept, 1);
+ }
+ 
+-static int winTreeInvertSelectFunc(Ihandle* ih, HTREEITEM hItem, void* userdata)
++static int winTreeInvertSelectFunc(Ihandle* ih, HTREEITEM hItem, int id, void* userdata)
+ {
+- winTreeSelectItem(ih, hItem, -1);
++ (void)id;
++ winTreeSelectNode(ih, hItem, -1);
+ (void)userdata;
+ return 1;
+ }
+@@ -568,14 +423,11 @@ static int winTreeInvertSelectFunc(Ihandle* ih, HTREEITEM hItem, void* userdata)
+ typedef struct _winTreeSelArray{
+ Iarray* markedArray;
+ char is_handle;
+- int id_control;
+ }winTreeSelArray;
+ 
+-static int winTreeSelectedArrayFunc(Ihandle* ih, HTREEITEM hItem, winTreeSelArray* selarray)
++static int winTreeSelectedArrayFunc(Ihandle* ih, HTREEITEM hItem, int id, winTreeSelArray* selarray)
+ { 
+- selarray->id_control++;
+-
+- if (winTreeIsItemSelected(ih, hItem))
++ if (winTreeIsNodeSelected(ih, hItem))
+ {
+ if (selarray->is_handle)
+ {
+@@ -587,7 +439,7 @@ static int winTreeSelectedArrayFunc(Ihandle* ih, HTREEITEM hItem, winTreeSelArra
+ {
+ int* intArrayData = (int*)iupArrayInc(selarray->markedArray);
+ int i = iupArrayCount(selarray->markedArray);
+- intArrayData[i-1] = selarray->id_control;
++ intArrayData[i-1] = id;
+ }
+ }
+ 
+@@ -599,10 +451,9 @@ static Iarray* winTreeGetSelectedArray(Ihandle* ih)
+ Iarray* markedArray = iupArrayCreate(1, sizeof(HTREEITEM));
+ winTreeSelArray selarray;
+ selarray.markedArray = markedArray;
+- selarray.id_control = -1;
+ selarray.is_handle = 1;
+ 
+- winTreeForEach(ih, NULL, (winTreeNodeFunc)winTreeSelectedArrayFunc, &selarray);
++ iupTreeForEach(ih, (iupTreeNodeFunc)winTreeSelectedArrayFunc, &selarray);
+ 
+ return markedArray;
+ }
+@@ -612,10 +463,9 @@ static Iarray* winTreeGetSelectedArrayId(Ihandle* ih)
+ Iarray* markedArray = iupArrayCreate(1, sizeof(int));
+ winTreeSelArray selarray;
+ selarray.markedArray = markedArray;
+- selarray.id_control = -1;
+ selarray.is_handle = 0;
+ 
+- winTreeForEach(ih, NULL, (winTreeNodeFunc)winTreeSelectedArrayFunc, &selarray);
++ iupTreeForEach(ih, (iupTreeNodeFunc)winTreeSelectedArrayFunc, &selarray);
+ 
+ return markedArray;
+ }
+@@ -625,7 +475,7 @@ static Iarray* winTreeGetSelectedArrayId(Ihandle* ih)
+ /* COPYING ITEMS (Branches and its children) */
+ /*****************************************************************************/
+ /* Insert the copied item in a new location. Returns the new item. */
+-static HTREEITEM winTreeCopyItem(Ihandle* ih, HTREEITEM hItem, HTREEITEM hParent, HTREEITEM hPosition, int full_copy)
++static HTREEITEM winTreeCopyItem(Ihandle* ih, HTREEITEM hItem, HTREEITEM hParent, HTREEITEM hPosition, int is_copy)
+ {
+ TVITEM item; 
+ TVINSERTSTRUCT tvins;
+@@ -637,34 +487,34 @@ static HTREEITEM winTreeCopyItem(Ihandle* ih, HTREEITEM hItem, HTREEITEM hParent
+ item.cchTextMax = 255;
+ SendMessage(ih->handle, TVM_GETITEM, 0, (LPARAM)(LPTVITEM)&item);
+ 
+- if (full_copy) /* during a full copy the userdata reference is not copied */
++ if (is_copy) /* during a copy the itemdata reference is not reused */
+ {
+ /* create a new one */
+ winTreeItemData* itemDataNew = malloc(sizeof(winTreeItemData));
+ memcpy(itemDataNew, (void*)item.lParam, sizeof(winTreeItemData));
+- itemDataNew->userdata = NULL;
+ item.lParam = (LPARAM)itemDataNew;
+ }
+ 
+- /* Copy everything including user data reference */
++ /* Copy everything including itemdata reference */
+ tvins.item = item; 
+ tvins.hInsertAfter = hPosition;
+ tvins.hParent = hParent;
+ 
+- /* Add the node to the tree-view control */
++ /* Add the new node */
++ ih->data->node_count++;
+ return (HTREEITEM)SendMessage(ih->handle, TVM_INSERTITEM, 0, (LPARAM)(LPTVINSERTSTRUCT)&tvins);
+ }
+ 
+-static void winTreeCopyChildren(Ihandle* ih, HTREEITEM hItemSrc, HTREEITEM hItemDst, int full_copy)
++static void winTreeCopyChildren(Ihandle* ih, HTREEITEM hItemSrc, HTREEITEM hItemDst, int is_copy)
+ {
+ HTREEITEM hChildSrc = (HTREEITEM)SendMessage(ih->handle, TVM_GETNEXTITEM, TVGN_CHILD, (LPARAM)hItemSrc);
+- HTREEITEM hNewItem = TVI_FIRST;
++ HTREEITEM hItemNew = TVI_FIRST;
+ while (hChildSrc != NULL)
+ {
+- hNewItem = winTreeCopyItem(ih, hChildSrc, hItemDst, hNewItem, full_copy); /* Use the same order they where enumerated */
++ hItemNew = winTreeCopyItem(ih, hChildSrc, hItemDst, hItemNew, is_copy); /* Use the same order they where enumerated */
+ 
+ /* Recursively transfer all the items */
+- winTreeCopyChildren(ih, hChildSrc, hNewItem, full_copy); 
++ winTreeCopyChildren(ih, hChildSrc, hItemNew, is_copy); 
+ 
+ /* Go to next sibling item */
+ hChildSrc = (HTREEITEM)SendMessage(ih->handle, TVM_GETNEXTITEM, TVGN_NEXT, (LPARAM)hChildSrc);
+@@ -672,11 +522,18 @@ static void winTreeCopyChildren(Ihandle* ih, HTREEITEM hItemSrc, HTREEITEM hItem
+ }
+ 
+ /* Copies all items in a branch to a new location. Returns the new branch node. */
+-static HTREEITEM winTreeCopyNode(Ihandle* ih, HTREEITEM hItemSrc, HTREEITEM hItemDst, int full_copy)
++static HTREEITEM winTreeCopyMoveNode(Ihandle* ih, HTREEITEM hItemSrc, HTREEITEM hItemDst, int is_copy)
+ {
+- HTREEITEM hNewItem, hParent;
++ HTREEITEM hItemNew, hParent;
+ TVITEM item;
+ winTreeItemData* itemDataDst;
++ int id_new, count, id_src, id_dst;
++
++ int old_count = ih->data->node_count;
++
++ id_src = iupTreeFindNodeId(ih, hItemSrc);
++ id_dst = iupTreeFindNodeId(ih, hItemDst);
++ id_new = id_dst+1; /* contains the position for a copy operation */
+ 
+ /* Get DST node attributes */
+ item.hItem = hItemDst;
+@@ -691,31 +548,64 @@ static HTREEITEM winTreeCopyNode(Ihandle* ih, HTREEITEM hItemSrc, HTREEITEM hIte
+ hItemDst = TVI_FIRST;
+ }
+ else
+- { 
++ { 
++ if (itemDataDst->kind == ITREE_BRANCH)
++ {
++ int child_count = iupdrvTreeTotalChildCount(ih, hItemDst);
++ id_new += child_count;
++ }
++
+ /* copy as next brother of item or collapsed branch */
+ hParent = (HTREEITEM)SendMessage(ih->handle, TVM_GETNEXTITEM, TVGN_PARENT, (LPARAM)hItemDst);
+ }
+ 
+- hNewItem = winTreeCopyItem(ih, hItemSrc, hParent, hItemDst, full_copy);
++ /* move to the same place does nothing */
++ if (!is_copy && id_new == id_src)
++ return NULL;
++
++ hItemNew = winTreeCopyItem(ih, hItemSrc, hParent, hItemDst, is_copy);
++
++ winTreeCopyChildren(ih, hItemSrc, hItemNew, is_copy);
++
++ count = ih->data->node_count - old_count;
++ iupTreeCopyMoveCache(ih, id_src, id_new, count, is_copy);
++
++ if (!is_copy)
++ {
++ /* Deleting the node (and its children) from the old position */
++ /* do not delete the itemdata, we reuse the references in CopyNode */
++ iupAttribSetStr(ih, "_IUPTREE_IGNORE_SELECTION_CB", "1");
++ SendMessage(ih->handle, TVM_DELETEITEM, 0, (LPARAM)hItemSrc);
++ iupAttribSetStr(ih, "_IUPTREE_IGNORE_SELECTION_CB", NULL);
+ 
+- winTreeCopyChildren(ih, hItemSrc, hNewItem, full_copy);
++ /* restore count, because we remove src */
++ ih->data->node_count = old_count;
+ 
+- return hNewItem;
++ /* compensate position for a move */
++ if (id_new > id_src)
++ id_new -= count;
++ }
++
++ winTreeRebuildNodeCache(ih, id_new, hItemNew);
++
++ return hItemNew;
+ }
+ 
+ /*****************************************************************************/
+ /* MANIPULATING IMAGES */
+ /*****************************************************************************/
+-static void winTreeUpdateImages(Ihandle* ih, HTREEITEM hItem, int mode)
++static void winTreeUpdateImages(Ihandle* ih, int mode)
+ {
+- HTREEITEM hItemChild;
++ HTREEITEM hItem;
+ TVITEM item;
+ winTreeItemData* itemData;
++ int i;
+ 
+ /* called when one of the default images is changed */
+-
+- while(hItem != NULL)
++ for (i = 0; i < ih->data->node_count; i++)
+ {
++ hItem = ih->data->node_cache[i].node_handle;
++
+ /* Get node attributes */
+ item.hItem = hItem;
+ item.mask = TVIF_HANDLE | TVIF_PARAM | TVIF_IMAGE | TVIF_SELECTEDIMAGE | TVIF_STATE;
+@@ -742,10 +632,6 @@ static void winTreeUpdateImages(Ihandle* ih, HTREEITEM hItem, int mode)
+ SendMessage(ih->handle, TVM_SETITEM, 0, (LPARAM)(LPTVITEM)&item);
+ }
+ }
+-
+- /* Recursively traverse child items */
+- hItemChild = (HTREEITEM)SendMessage(ih->handle, TVM_GETNEXTITEM, TVGN_CHILD, (LPARAM)hItem);
+- winTreeUpdateImages(ih, hItemChild, mode);
+ }
+ else
+ {
+@@ -756,9 +642,6 @@ static void winTreeUpdateImages(Ihandle* ih, HTREEITEM hItem, int mode)
+ SendMessage(ih->handle, TVM_SETITEM, 0, (LPARAM)(LPTVITEM)&item);
+ }
+ }
+-
+- /* Go to next sibling node */
+- hItem = (HTREEITEM)SendMessage(ih->handle, TVM_GETNEXTITEM, TVGN_NEXT, (LPARAM)hItem);
+ }
+ }
+ 
+@@ -828,29 +711,57 @@ static int winTreeCallBranchLeafCb(Ihandle* ih, HTREEITEM hItem)
+ 
+ if (itemData->kind == ITREE_BRANCH)
+ {
++ if (iupAttribGet(ih, "_IUPTREE_IGNORE_BRANCH_CB"))
++ return IUP_DEFAULT;
++
+ if (item.state & TVIS_EXPANDED)
+ {
+ IFni cbBranchClose = (IFni)IupGetCallback(ih, "BRANCHCLOSE_CB");
+ if (cbBranchClose)
+- return cbBranchClose(ih, winTreeGetNodeId(ih, hItem));
++ return cbBranchClose(ih, iupTreeFindNodeId(ih, hItem));
+ }
+ else
+ {
+ IFni cbBranchOpen = (IFni)IupGetCallback(ih, "BRANCHOPEN_CB");
+ if (cbBranchOpen)
+- return cbBranchOpen(ih, winTreeGetNodeId(ih, hItem));
++ return cbBranchOpen(ih, iupTreeFindNodeId(ih, hItem));
+ }
+ }
+ else
+ {
+ IFni cbExecuteLeaf = (IFni)IupGetCallback(ih, "EXECUTELEAF_CB");
+ if (cbExecuteLeaf)
+- return cbExecuteLeaf(ih, winTreeGetNodeId(ih, hItem));
++ return cbExecuteLeaf(ih, iupTreeFindNodeId(ih, hItem));
+ }
+ 
+ return IUP_DEFAULT;
+ }
+ 
++static void winTreeCallMultiUnSelectionCb(Ihandle* ih)
++{
++ IFnIi cbMulti = (IFnIi)IupGetCallback(ih, "MULTIUNSELECTION_CB");
++ IFnii cbSelec = (IFnii)IupGetCallback(ih, "SELECTION_CB");
++ if (cbSelec || cbMulti)
++ {
++ Iarray* markedArray = winTreeGetSelectedArrayId(ih);
++ int* id_hitem = (int*)iupArrayGetData(markedArray);
++ int i, count = iupArrayCount(markedArray);
++
++ if (count > 1)
++ {
++ if (cbMulti)
++ cbMulti(ih, id_hitem, iupArrayCount(markedArray));
++ else
++ {
++ for (i=0; i<count; i++)
++ cbSelec(ih, id_hitem[i], 0);
++ }
++ }
++
++ iupArrayDestroy(markedArray);
++ }
++}
++
+ static void winTreeCallMultiSelectionCb(Ihandle* ih)
+ {
+ IFnIi cbMulti = (IFnIi)IupGetCallback(ih, "MULTISELECTION_CB");
+@@ -885,6 +796,8 @@ static void winTreeCallSelectionCb(Ihandle* ih, int status, HTREEITEM hItem)
+ IFnii cbSelec = (IFnii)IupGetCallback(ih, "SELECTION_CB");
+ if (cbSelec)
+ {
++ int id;
++
+ if (ih->data->mark_mode == ITREE_MARK_MULTIPLE && IupGetCallback(ih,"MULTISELECTION_CB"))
+ {
+ if ((GetKeyState(VK_SHIFT) & 0x8000))
+@@ -894,7 +807,9 @@ static void winTreeCallSelectionCb(Ihandle* ih, int status, HTREEITEM hItem)
+ if (iupAttribGet(ih, "_IUPTREE_IGNORE_SELECTION_CB"))
+ return;
+ 
+- cbSelec(ih, winTreeGetNodeId(ih, hItem), status);
++ id = iupTreeFindNodeId(ih, hItem);
++ if (id != -1)
++ cbSelec(ih, id, status);
+ }
+ }
+ 
+@@ -911,8 +826,8 @@ static int winTreeCallDragDropCb(Ihandle* ih, HTREEITEM hItemDrag, HTREEITEM hIt
+ 
+ if (cbDragDrop)
+ {
+- int drag_id = winTreeGetNodeId(ih, hItemDrag);
+- int drop_id = winTreeGetNodeId(ih, hItemDrop);
++ int drag_id = iupTreeFindNodeId(ih, hItemDrag);
++ int drop_id = iupTreeFindNodeId(ih, hItemDrop);
+ return cbDragDrop(ih, drag_id, drop_id, is_shift, *is_ctrl);
+ }
+ 
+@@ -929,8 +844,8 @@ static int winTreeSetImageBranchExpandedAttrib(Ihandle* ih, const char* value)
+ {
+ ih->data->def_image_expanded = (void*)winTreeGetImageIndex(ih, value);
+ 
+- /* Update all images, starting at root node */
+- winTreeUpdateImages(ih, (HTREEITEM)SendMessage(ih->handle, TVM_GETNEXTITEM, TVGN_ROOT, 0), ITREE_UPDATEIMAGE_EXPANDED);
++ /* Update all images */
++ winTreeUpdateImages(ih, ITREE_UPDATEIMAGE_EXPANDED);
+ 
+ return 1;
+ }
+@@ -939,8 +854,8 @@ static int winTreeSetImageBranchCollapsedAttrib(Ihandle* ih, const char* value)
+ {
+ ih->data->def_image_collapsed = (void*)winTreeGetImageIndex(ih, value);
+ 
+- /* Update all images, starting at root node */
+- winTreeUpdateImages(ih, (HTREEITEM)SendMessage(ih->handle, TVM_GETNEXTITEM, TVGN_ROOT, 0), ITREE_UPDATEIMAGE_COLLAPSED);
++ /* Update all images */
++ winTreeUpdateImages(ih, ITREE_UPDATEIMAGE_COLLAPSED);
+ 
+ return 1;
+ }
+@@ -949,8 +864,8 @@ static int winTreeSetImageLeafAttrib(Ihandle* ih, const char* value)
+ {
+ ih->data->def_image_leaf = (void*)winTreeGetImageIndex(ih, value);
+ 
+- /* Update all images, starting at root node */
+- winTreeUpdateImages(ih, (HTREEITEM)SendMessage(ih->handle, TVM_GETNEXTITEM, TVGN_ROOT, 0), ITREE_UPDATEIMAGE_LEAF);
++ /* Update all images */
++ winTreeUpdateImages(ih, ITREE_UPDATEIMAGE_LEAF);
+ 
+ return 1;
+ }
+@@ -959,7 +874,7 @@ static int winTreeSetImageExpandedAttrib(Ihandle* ih, const char* name_id, const
+ {
+ TVITEM item;
+ winTreeItemData* itemData;
+- HTREEITEM hItem = winTreeFindNodeFromString(ih, name_id);
++ HTREEITEM hItem = iupTreeGetNodeFromString(ih, name_id);
+ if (!hItem)
+ return 0;
+ 
+@@ -986,7 +901,7 @@ static int winTreeSetImageAttrib(Ihandle* ih, const char* name_id, const char* v
+ {
+ TVITEM item;
+ winTreeItemData* itemData;
+- HTREEITEM hItem = winTreeFindNodeFromString(ih, name_id);
++ HTREEITEM hItem = iupTreeGetNodeFromString(ih, name_id);
+ if (!hItem)
+ return 0;
+ 
+@@ -1025,7 +940,7 @@ static int winTreeSetImageAttrib(Ihandle* ih, const char* name_id, const char* v
+ 
+ static int winTreeSetTopItemAttrib(Ihandle* ih, const char* value)
+ {
+- HTREEITEM hItem = winTreeFindNodeFromString(ih, value);
++ HTREEITEM hItem = iupTreeGetNodeFromString(ih, value);
+ if (hItem)
+ SendMessage(ih->handle, TVM_ENSUREVISIBLE, 0, (LPARAM)hItem);
+ return 0;
+@@ -1056,9 +971,8 @@ static int winTreeSetSpacingAttrib(Ihandle* ih, const char* value)
+ static int winTreeSetExpandAllAttrib(Ihandle* ih, const char* value)
+ {
+ HTREEITEM hItemRoot = (HTREEITEM)SendMessage(ih->handle, TVM_GETNEXTITEM, TVGN_ROOT, 0);
+- HTREEITEM hItem = (HTREEITEM)SendMessage(ih->handle, TVM_GETNEXTITEM, TVGN_CHILD, (LPARAM)hItemRoot); /* skip the root node that is always expanded */
+ int expand = iupStrBoolean(value);
+- winTreeExpandTree(ih, hItem, expand);
++ winTreeExpandTree(ih, hItemRoot, expand);
+ return 0;
+ }
+ 
+@@ -1131,7 +1045,7 @@ static char* winTreeGetTitle(Ihandle* ih, HTREEITEM hItem)
+ 
+ static char* winTreeGetTitleAttrib(Ihandle* ih, const char* name_id)
+ {
+- HTREEITEM hItem = winTreeFindNodeFromString(ih, name_id);
++ HTREEITEM hItem = iupTreeGetNodeFromString(ih, name_id);
+ if (!hItem)
+ return NULL;
+ return winTreeGetTitle(ih, hItem);
+@@ -1140,10 +1054,13 @@ static char* winTreeGetTitleAttrib(Ihandle* ih, const char* name_id)
+ static int winTreeSetTitleAttrib(Ihandle* ih, const char* name_id, const char* value)
+ {
+ TVITEM item; 
+- HTREEITEM hItem = winTreeFindNodeFromString(ih, name_id);
++ HTREEITEM hItem = iupTreeGetNodeFromString(ih, name_id);
+ if (!hItem)
+ return 0;
+ 
++ if (!value)
++ value = "";
++
+ item.hItem = hItem;
+ item.mask = TVIF_HANDLE | TVIF_TEXT; 
+ item.pszText = (char*)value;
+@@ -1151,60 +1068,11 @@ static int winTreeSetTitleAttrib(Ihandle* ih, const char* name_id, const char* v
+ return 0;
+ }
+ 
+-static char* winTreeGetFindUserDataAttrib(Ihandle* ih, const char* name_id)
+-{
+- int id;
+- char* str = (char*)(name_id+1); /* skip ':' */
+- void* userdata = NULL;
+- if (sscanf(str, "%p", &userdata)!=1)
+- return NULL;
+- id = winTreeGetUserDataId(ih, userdata);
+- if (id == -1)
+- return NULL;
+- str = iupStrGetMemory(16);
+- sprintf(str, "%d", id);
+- return str;
+-}
+-
+-static char* winTreeGetUserDataAttrib(Ihandle* ih, const char* name_id)
+-{
+- TVITEM item;
+- winTreeItemData* itemData;
+- HTREEITEM hItem = winTreeFindNodeFromString(ih, name_id);
+- if (!hItem)
+- return NULL;
+-
+- item.hItem = hItem;
+- item.mask = TVIF_HANDLE | TVIF_PARAM;
+- SendMessage(ih->handle, TVM_GETITEM, 0, (LPARAM)(LPTVITEM)&item);
+- itemData = (winTreeItemData*)item.lParam;
+-
+- return itemData->userdata;
+-}
+-
+-static int winTreeSetUserDataAttrib(Ihandle* ih, const char* name_id, const char* value)
+-{
+- TVITEM item; 
+- winTreeItemData* itemData;
+- HTREEITEM hItem = winTreeFindNodeFromString(ih, name_id);
+- if (!hItem)
+- return 0;
+-
+- item.hItem = hItem;
+- item.mask = TVIF_HANDLE | TVIF_PARAM;
+- SendMessage(ih->handle, TVM_GETITEM, 0, (LPARAM)(LPTVITEM)&item);
+- itemData = (winTreeItemData*)item.lParam;
+-
+- itemData->userdata = (void*)value;
+-
+- return 0;
+-}
+-
+ static char* winTreeGetTitleFontAttrib(Ihandle* ih, const char* name_id)
+ {
+ TVITEM item;
+ winTreeItemData* itemData;
+- HTREEITEM hItem = winTreeFindNodeFromString(ih, name_id);
++ HTREEITEM hItem = iupTreeGetNodeFromString(ih, name_id);
+ if (!hItem)
+ return NULL;
+ 
+@@ -1220,7 +1088,7 @@ static int winTreeSetTitleFontAttrib(Ihandle* ih, const char* name_id, const cha
+ {
+ TVITEM item; 
+ winTreeItemData* itemData;
+- HTREEITEM hItem = winTreeFindNodeFromString(ih, name_id);
++ HTREEITEM hItem = iupTreeGetNodeFromString(ih, name_id);
+ if (!hItem)
+ return 0;
+ 
+@@ -1230,11 +1098,23 @@ static int winTreeSetTitleFontAttrib(Ihandle* ih, const char* name_id, const cha
+ itemData = (winTreeItemData*)item.lParam;
+ 
+ if (value)
++ {
+ itemData->hFont = iupwinGetHFont(value);
++ if (itemData->hFont)
++ {
++ TV_ITEM item;
++ item.mask = TVIF_STATE | TVIF_HANDLE | TVIF_TEXT;
++ item.stateMask = TVIS_BOLD;
++ item.hItem = hItem;
++ item.pszText = winTreeGetTitle(ih, hItem); /* reset text to resize item */
++ item.state = (strstr(value, "Bold")||strstr(value, "BOLD"))? TVIS_BOLD: 0;
++ SendMessage(ih->handle, TVM_SETITEM, 0, (LPARAM)&item);
++ }
++ }
+ else
+ itemData->hFont = NULL;
+ 
+- iupdrvDisplayUpdate(ih);
++ iupdrvPostRedraw(ih);
+ 
+ return 0;
+ }
+@@ -1259,7 +1139,7 @@ static char* winTreeGetStateAttrib(Ihandle* ih, const char* name_id)
+ {
+ TVITEM item;
+ winTreeItemData* itemData;
+- HTREEITEM hItem = winTreeFindNodeFromString(ih, name_id);
++ HTREEITEM hItem = iupTreeGetNodeFromString(ih, name_id);
+ if (!hItem)
+ return NULL;
+ 
+@@ -1281,25 +1161,34 @@ static char* winTreeGetStateAttrib(Ihandle* ih, const char* name_id)
+ 
+ static int winTreeSetStateAttrib(Ihandle* ih, const char* name_id, const char* value)
+ {
+- HTREEITEM hItem = winTreeFindNodeFromString(ih, name_id);
++ TVITEM item;
++ winTreeItemData* itemData;
++ HTREEITEM hItem = iupTreeGetNodeFromString(ih, name_id);
+ if (!hItem)
+ return 0;
+ 
+- winTreeExpandItem(ih, hItem, iupStrEqualNoCase(value, "EXPANDED"));
++ /* Get Children: branch or leaf */
++ item.mask = TVIF_HANDLE|TVIF_PARAM; 
++ item.hItem = hItem;
++ SendMessage(ih->handle, TVM_GETITEM, 0, (LPARAM)(LPTVITEM)&item);
++ itemData = (winTreeItemData*)item.lParam;
++
++ if (itemData->kind == ITREE_BRANCH)
++ winTreeExpandItem(ih, hItem, iupStrEqualNoCase(value, "EXPANDED"));
++
+ return 0;
+ }
+ 
+ static char* winTreeGetDepthAttrib(Ihandle* ih, const char* name_id)
+ {
+- HTREEITEM hItem = winTreeFindNodeFromString(ih, name_id);
+- HTREEITEM hItemRoot = (HTREEITEM)SendMessage(ih->handle, TVM_GETNEXTITEM, TVGN_ROOT, 0);
+- int depth = 0;
++ HTREEITEM hItem = iupTreeGetNodeFromString(ih, name_id);
++ int depth = -1;
+ char* str;
+ 
+- if (!hItem)
++ if (!hItem) 
+ return NULL;
+ 
+- while((hItemRoot != hItem) && (hItem != NULL))
++ while(hItem != NULL)
+ {
+ hItem = (HTREEITEM)SendMessage(ih->handle, TVM_GETNEXTITEM, TVGN_PARENT, (LPARAM)hItem);
+ depth++;
+@@ -1314,12 +1203,13 @@ static int winTreeSetMoveNodeAttrib(Ihandle* ih, const char* name_id, const char
+ {
+ HTREEITEM hItemDst, hParent, hItemSrc;
+ 
+- if (!ih->handle) /* do not store the action before map */
++ if (!ih->handle) /* do not do the action before map */
+ return 0;
+- hItemSrc = winTreeFindNodeFromString(ih, name_id);
++
++ hItemSrc = iupTreeGetNodeFromString(ih, name_id);
+ if (!hItemSrc)
+ return 0;
+- hItemDst = winTreeFindNodeFromString(ih, value);
++ hItemDst = iupTreeGetNodeFromString(ih, value);
+ if (!hItemDst)
+ return 0;
+ 
+@@ -1332,11 +1222,8 @@ static int winTreeSetMoveNodeAttrib(Ihandle* ih, const char* name_id, const char
+ return 0;
+ }
+ 
+- /* Copying the node and its children to the new position */
+- winTreeCopyNode(ih, hItemSrc, hItemDst, 0); /* not a full copy, preserve user data */
+-
+- /* do not delete the user data, we copy the references in CopyNode */
+- SendMessage(ih->handle, TVM_DELETEITEM, 0, (LPARAM)hItemSrc);
++ /* Move the node and its children to the new position */
++ winTreeCopyMoveNode(ih, hItemSrc, hItemDst, 0);
+ 
+ return 0;
+ }
+@@ -1345,12 +1232,13 @@ static int winTreeSetCopyNodeAttrib(Ihandle* ih, const char* name_id, const char
+ {
+ HTREEITEM hItemDst, hParent, hItemSrc;
+ 
+- if (!ih->handle) /* do not store the action before map */
++ if (!ih->handle) /* do not do the action before map */
+ return 0;
+- hItemSrc = winTreeFindNodeFromString(ih, name_id);
++
++ hItemSrc = iupTreeGetNodeFromString(ih, name_id);
+ if (!hItemSrc)
+ return 0;
+- hItemDst = winTreeFindNodeFromString(ih, value);
++ hItemDst = iupTreeGetNodeFromString(ih, value);
+ if (!hItemDst)
+ return 0;
+ 
+@@ -1363,8 +1251,8 @@ static int winTreeSetCopyNodeAttrib(Ihandle* ih, const char* name_id, const char
+ return 0;
+ }
+ 
+- /* Copying the node and its children to the new position */
+- winTreeCopyNode(ih, hItemSrc, hItemDst, 1);
++ /* Copy the node and its children to the new position */
++ winTreeCopyMoveNode(ih, hItemSrc, hItemDst, 1);
+ 
+ return 0;
+ }
+@@ -1375,7 +1263,7 @@ static char* winTreeGetColorAttrib(Ihandle* ih, const char* name_id)
+ char* str;
+ TVITEM item;
+ winTreeItemData* itemData;
+- HTREEITEM hItem = winTreeFindNodeFromString(ih, name_id);
++ HTREEITEM hItem = iupTreeGetNodeFromString(ih, name_id);
+ if (!hItem)
+ return NULL;
+ 
+@@ -1398,7 +1286,7 @@ static int winTreeSetColorAttrib(Ihandle* ih, const char* name_id, const char* v
+ unsigned char r, g, b;
+ TVITEM item;
+ winTreeItemData* itemData;
+- HTREEITEM hItem = winTreeFindNodeFromString(ih, name_id);
++ HTREEITEM hItem = iupTreeGetNodeFromString(ih, name_id);
+ if (!hItem)
+ return 0;
+ 
+@@ -1410,7 +1298,7 @@ static int winTreeSetColorAttrib(Ihandle* ih, const char* name_id, const char* v
+ if (iupStrToRGB(value, &r, &g, &b))
+ {
+ itemData->color = RGB(r,g,b);
+- iupdrvDisplayUpdate(ih);
++ iupdrvPostRedraw(ih);
+ }
+ 
+ return 0;
+@@ -1435,7 +1323,7 @@ static char* winTreeGetChildCountAttrib(Ihandle* ih, const char* name_id)
+ {
+ int count;
+ char* str;
+- HTREEITEM hItem = winTreeFindNodeFromString(ih, name_id);
++ HTREEITEM hItem = iupTreeGetNodeFromString(ih, name_id);
+ if (!hItem)
+ return NULL;
+ 
+@@ -1454,18 +1342,11 @@ static char* winTreeGetChildCountAttrib(Ihandle* ih, const char* name_id)
+ return str;
+ }
+ 
+-static char* winTreeGetCountAttrib(Ihandle* ih)
+-{
+- char* str = iupStrGetMemory(10);
+- sprintf(str, "%d", (int)SendMessage(ih->handle, TVM_GETCOUNT, 0, 0));
+- return str;
+-}
+-
+ static char* winTreeGetKindAttrib(Ihandle* ih, const char* name_id)
+ {
+ TVITEM item; 
+ winTreeItemData* itemData;
+- HTREEITEM hItem = winTreeFindNodeFromString(ih, name_id);
++ HTREEITEM hItem = iupTreeGetNodeFromString(ih, name_id);
+ if (!hItem)
+ return NULL;
+ 
+@@ -1483,7 +1364,7 @@ static char* winTreeGetKindAttrib(Ihandle* ih, const char* name_id)
+ static char* winTreeGetParentAttrib(Ihandle* ih, const char* name_id)
+ {
+ char* str;
+- HTREEITEM hItem = winTreeFindNodeFromString(ih, name_id);
++ HTREEITEM hItem = iupTreeGetNodeFromString(ih, name_id);
+ if (!hItem)
+ return NULL;
+ 
+@@ -1492,15 +1373,13 @@ static char* winTreeGetParentAttrib(Ihandle* ih, const char* name_id)
+ return NULL;
+ 
+ str = iupStrGetMemory(10);
+- sprintf(str, "%d", winTreeGetNodeId(ih, hItem));
++ sprintf(str, "%d", iupTreeFindNodeId(ih, hItem));
+ return str;
+ }
+ 
+-static void winTreeDelNodeData(Ihandle* ih, HTREEITEM hItem)
++static void winTreeRemoveItemData(Ihandle* ih, HTREEITEM hItem, IFns cb, int id)
+ {
+ TVITEM item; 
+- HTREEITEM hChildItem;
+-
+ item.hItem = hItem;
+ item.mask = TVIF_HANDLE|TVIF_PARAM; 
+ if (SendMessage(ih->handle, TVM_GETITEM, 0, (LPARAM)(LPTVITEM)&item))
+@@ -1508,81 +1387,153 @@ static void winTreeDelNodeData(Ihandle* ih, HTREEITEM hItem)
+ winTreeItemData* itemData = (winTreeItemData*)item.lParam;
+ if (itemData)
+ {
+- IFnis cb = (IFnis)IupGetCallback(ih, "NODEREMOVED_CB");
+- if (cb) cb(ih, winTreeGetNodeId(ih, hItem), (char*)itemData->userdata);
++ if (cb) 
++ cb(ih, (char*)ih->data->node_cache[id].userdata);
++
+ free(itemData);
+ item.lParam = (LPARAM)NULL;
+ SendMessage(ih->handle, TVM_SETITEM, 0, (LPARAM)(LPTVITEM)&item);
+ }
+ }
++}
++
++static void winTreeRemoveNodeDataRec(Ihandle* ih, HTREEITEM hItem, IFns cb, int *id)
++{
++ int old_id = *id;
+ 
+- hChildItem = (HTREEITEM)SendMessage(ih->handle, TVM_GETNEXTITEM, TVGN_CHILD, (LPARAM)hItem);
++ /* Check whether we have child items */
++ /* remove from children first */
++ HTREEITEM hChildItem = (HTREEITEM)SendMessage(ih->handle, TVM_GETNEXTITEM, TVGN_CHILD, (LPARAM)hItem);
+ while (hChildItem)
+ {
+- winTreeDelNodeData(ih, hChildItem);
++ /* go recursive to children */
++ winTreeRemoveNodeDataRec(ih, hChildItem, cb, id);
++
++ /* Go to next sibling item */
+ hChildItem = (HTREEITEM)SendMessage(ih->handle, TVM_GETNEXTITEM, TVGN_NEXT, (LPARAM)hChildItem);
+ }
++
++ /* actually do it for the node */
++ ih->data->node_count--;
++ (*id)++;
++
++ winTreeRemoveItemData(ih, hItem, cb, old_id);
++}
++
++static void winTreeRemoveNodeData(Ihandle* ih, HTREEITEM hItem, int call_cb)
++{
++ IFns cb = call_cb? (IFns)IupGetCallback(ih, "NODEREMOVED_CB"): NULL;
++ int old_count = ih->data->node_count;
++ int id = iupTreeFindNodeId(ih, hItem);
++ int old_id = id;
++
++ winTreeRemoveNodeDataRec(ih, hItem, cb, &id);
++
++ if (call_cb)
++ iupTreeDelFromCache(ih, old_id, old_count-ih->data->node_count);
++}
++
++static void winTreeRemoveAllNodeData(Ihandle* ih, int call_cb)
++{
++ IFns cb = call_cb? (IFns)IupGetCallback(ih, "NODEREMOVED_CB"): NULL;
++ int i, old_count = ih->data->node_count;
++ HTREEITEM hItem;
++
++ for (i = 0; i < ih->data->node_count; i++)
++ {
++ hItem = ih->data->node_cache[i].node_handle;
++ winTreeRemoveItemData(ih, hItem, cb, i);
++ }
++
++ ih->data->node_count = 0;
++
++ if (call_cb)
++ iupTreeDelFromCache(ih, 0, old_count);
+ }
+ 
+ static int winTreeSetDelNodeAttrib(Ihandle* ih, const char* name_id, const char* value)
+ {
+- if (!ih->handle) /* do not store the action before map */
++ if (!ih->handle) /* do not do the action before map */
+ return 0;
+- if(iupStrEqualNoCase(value, "SELECTED")) /* selected here means the specified one */
++ if (iupStrEqualNoCase(value, "ALL"))
+ {
+- HTREEITEM hItem = winTreeFindNodeFromString(ih, name_id);
+- HTREEITEM hItemRoot = (HTREEITEM)SendMessage(ih->handle, TVM_GETNEXTITEM, TVGN_ROOT, 0);
++ winTreeRemoveAllNodeData(ih, 1);
+ 
+- /* the root node can't be deleted */
+- if(!hItem || hItem == hItemRoot)
++ iupAttribSetStr(ih, "_IUPTREE_IGNORE_SELECTION_CB", "1");
++ SendMessage(ih->handle, TVM_DELETEITEM, 0, (LPARAM)TVI_ROOT);
++ iupAttribSetStr(ih, "_IUPTREE_IGNORE_SELECTION_CB", NULL);
++ return 0;
++ }
++ if (iupStrEqualNoCase(value, "SELECTED")) /* selected here means the reference one */
++ {
++ HTREEITEM hItem = iupTreeGetNodeFromString(ih, name_id);
++ if(!hItem)
+ return 0;
+ 
+- /* deleting the specified node (and it's children) */
+- winTreeDelNodeData(ih, hItem);
++ /* deleting the reference node (and it's children) */
++ winTreeRemoveNodeData(ih, hItem, 1);
++ iupAttribSetStr(ih, "_IUPTREE_IGNORE_SELECTION_CB", "1");
+ SendMessage(ih->handle, TVM_DELETEITEM, 0, (LPARAM)hItem);
++ iupAttribSetStr(ih, "_IUPTREE_IGNORE_SELECTION_CB", NULL);
+ 
+ return 0;
+ }
+- else if(iupStrEqualNoCase(value, "CHILDREN")) /* children of the specified one */
++ else if(iupStrEqualNoCase(value, "CHILDREN")) /* children of the reference node */
+ {
+- HTREEITEM hItem = winTreeFindNodeFromString(ih, name_id);
++ HTREEITEM hItem = iupTreeGetNodeFromString(ih, name_id);
+ HTREEITEM hChildItem = (HTREEITEM)SendMessage(ih->handle, TVM_GETNEXTITEM, TVGN_CHILD, (LPARAM)hItem);
+ 
+ if(!hItem)
+ return 0;
+ 
+- /* deleting the selected node's children */
++ iupAttribSetStr(ih, "_IUPTREE_IGNORE_SELECTION_CB", "1");
++
++ /* deleting the reference node children */
+ while (hChildItem)
+ {
+- winTreeDelNodeData(ih, hChildItem);
++ winTreeRemoveNodeData(ih, hChildItem, 1);
+ SendMessage(ih->handle, TVM_DELETEITEM, 0, (LPARAM)hChildItem);
+ hChildItem = (HTREEITEM)SendMessage(ih->handle, TVM_GETNEXTITEM, TVGN_CHILD, (LPARAM)hItem);
+ }
+ 
++ iupAttribSetStr(ih, "_IUPTREE_IGNORE_SELECTION_CB", NULL);
+ return 0;
+ }
+ else if(iupStrEqualNoCase(value, "MARKED"))
+ {
+- int i, count;
+- Iarray* markedArray;
+- HTREEITEM* hItemArrayData;
+- HTREEITEM hItemRoot = (HTREEITEM)SendMessage(ih->handle, TVM_GETNEXTITEM, TVGN_ROOT, 0);
++ int i, del_focus = 0;
++ HTREEITEM hItemFocus;
+ 
+- /* Delete the array of marked nodes */
+- markedArray = winTreeGetSelectedArray(ih);
+- hItemArrayData = (HTREEITEM*)iupArrayGetData(markedArray);
+- count = iupArrayCount(markedArray);
++ iupAttribSetStr(ih, "_IUPTREE_IGNORE_SELECTION_CB", "1");
++ hItemFocus = iupdrvTreeGetFocusNode(ih);
+ 
+- for(i = 0; i < count; i++)
++ for(i = 1; i < ih->data->node_count; /* increment only if not removed */)
+ {
+- if (hItemArrayData[i] != hItemRoot) /* the root node can't be deleted */
++ if (winTreeIsNodeSelected(ih, ih->data->node_cache[i].node_handle))
+ {
+- winTreeDelNodeData(ih, hItemArrayData[i]);
+- SendMessage(ih->handle, TVM_DELETEITEM, 0, (LPARAM)hItemArrayData[i]);
++ HTREEITEM hItem = ih->data->node_cache[i].node_handle;
++ if (hItemFocus == hItem)
++ {
++ del_focus = 1;
++ i++;
++ }
++ else
++ {
++ winTreeRemoveNodeData(ih, hItem, 1);
++ SendMessage(ih->handle, TVM_DELETEITEM, 0, (LPARAM)hItem);
++ }
+ }
++ else
++ i++;
+ }
+ 
+- iupArrayDestroy(markedArray);
++ if (del_focus)
++ {
++ winTreeRemoveNodeData(ih, hItemFocus, 1);
++ SendMessage(ih->handle, TVM_DELETEITEM, 0, (LPARAM)hItemFocus);
++ }
++
++ iupAttribSetStr(ih, "_IUPTREE_IGNORE_SELECTION_CB", NULL);
+ 
+ return 0;
+ }
+@@ -1592,22 +1543,13 @@ static int winTreeSetDelNodeAttrib(Ihandle* ih, const char* name_id, const char*
+ 
+ static int winTreeSetRenameAttrib(Ihandle* ih, const char* value)
+ { 
+- HTREEITEM hItemFocus = winTreeGetFocusNode(ih);
+ if (ih->data->show_rename)
+ {
+- IFni cbShowRename = (IFni)IupGetCallback(ih, "SHOWRENAME_CB");
+- if (cbShowRename)
+- cbShowRename(ih, winTreeGetNodeId(ih, hItemFocus));
+-
++ HTREEITEM hItemFocus;
+ SetFocus(ih->handle); /* the tree must have focus to activate the edit */
++ hItemFocus = iupdrvTreeGetFocusNode(ih);
+ SendMessage(ih->handle, TVM_EDITLABEL, 0, (LPARAM)hItemFocus);
+ }
+- else
+- {
+- IFnis cbRenameNode = (IFnis)IupGetCallback(ih, "RENAMENODE_CB");
+- if (cbRenameNode)
+- cbRenameNode(ih, winTreeGetNodeId(ih, hItemFocus), winTreeGetTitle(ih, hItemFocus)); 
+- }
+ 
+ (void)value;
+ return 0;
+@@ -1615,11 +1557,11 @@ static int winTreeSetRenameAttrib(Ihandle* ih, const char* value)
+ 
+ static char* winTreeGetMarkedAttrib(Ihandle* ih, const char* name_id)
+ {
+- HTREEITEM hItem = winTreeFindNodeFromString(ih, name_id);
++ HTREEITEM hItem = iupTreeGetNodeFromString(ih, name_id);
+ if (!hItem)
+ return NULL;
+ 
+- if (winTreeIsItemSelected(ih, hItem))
++ if (winTreeIsNodeSelected(ih, hItem))
+ return "YES";
+ else 
+ return "NO";
+@@ -1627,17 +1569,23 @@ static char* winTreeGetMarkedAttrib(Ihandle* ih, const char* name_id)
+ 
+ static int winTreeSetMarkedAttrib(Ihandle* ih, const char* name_id, const char* value)
+ {
+- HTREEITEM hItem = winTreeFindNodeFromString(ih, name_id);
++ HTREEITEM hItem = iupTreeGetNodeFromString(ih, name_id);
+ if (!hItem)
+ return 0;
+ 
+- winTreeSelectItem(ih, hItem, iupStrBoolean(value));
++ if (ih->data->mark_mode==ITREE_MARK_SINGLE)
++ {
++ HTREEITEM hItemFocus = iupdrvTreeGetFocusNode(ih);
++ winTreeSelectNode(ih, hItemFocus, 0);
++ }
++
++ winTreeSelectNode(ih, hItem, iupStrBoolean(value));
+ return 0;
+ }
+ 
+ static int winTreeSetMarkStartAttrib(Ihandle* ih, const char* name_id)
+ {
+- HTREEITEM hItem = winTreeFindNodeFromString(ih, name_id);
++ HTREEITEM hItem = iupTreeGetNodeFromString(ih, name_id);
+ if (!hItem)
+ return 0;
+ 
+@@ -1649,15 +1597,59 @@ static int winTreeSetMarkStartAttrib(Ihandle* ih, const char* name_id)
+ static char* winTreeGetValueAttrib(Ihandle* ih)
+ {
+ char* str;
+- HTREEITEM hItemFocus = winTreeGetFocusNode(ih);
++ HTREEITEM hItemFocus = iupdrvTreeGetFocusNode(ih);
+ if (!hItemFocus)
+- return "0"; /* default VALUE is root */
++ {
++ if (ih->data->node_count)
++ return "0"; /* default VALUE is root */
++ else
++ return "-1";
++ }
+ 
+ str = iupStrGetMemory(16);
+- sprintf(str, "%d", winTreeGetNodeId(ih, hItemFocus));
++ sprintf(str, "%d", iupTreeFindNodeId(ih, hItemFocus));
++ return str;
++}
++
++static char* winTreeGetMarkedNodesAttrib(Ihandle* ih)
++{
++ char* str = iupStrGetMemory(ih->data->node_count+1);
++ int i;
++
++ for (i=0; i<ih->data->node_count; i++)
++ {
++ if (winTreeIsNodeSelected(ih, ih->data->node_cache[i].node_handle))
++ str[i] = '+';
++ else
++ str[i] = '-';
++ }
++
++ str[ih->data->node_count] = 0;
+ return str;
+ }
+ 
++static int winTreeSetMarkedNodesAttrib(Ihandle* ih, const char* value)
++{
++ int count, i;
++
++ if (ih->data->mark_mode==ITREE_MARK_SINGLE || !value)
++ return 0;
++
++ count = strlen(value);
++ if (count > ih->data->node_count)
++ count = ih->data->node_count;
++
++ for (i=0; i<count; i++)
++ {
++ if (value[i] == '+')
++ winTreeSelectNode(ih, ih->data->node_cache[i].node_handle, 1);
++ else
++ winTreeSelectNode(ih, ih->data->node_cache[i].node_handle, 0);
++ }
++
++ return 0;
++}
++
+ static int winTreeSetMarkAttrib(Ihandle* ih, const char* value)
+ {
+ if (ih->data->mark_mode==ITREE_MARK_SINGLE)
+@@ -1665,7 +1657,7 @@ static int winTreeSetMarkAttrib(Ihandle* ih, const char* value)
+ 
+ if(iupStrEqualNoCase(value, "BLOCK"))
+ {
+- HTREEITEM hItemFocus = winTreeGetFocusNode(ih);
++ HTREEITEM hItemFocus = iupdrvTreeGetFocusNode(ih);
+ winTreeSelectRange(ih, (HTREEITEM)iupAttribGet(ih, "_IUPTREE_MARKSTART_NODE"), hItemFocus, 0);
+ }
+ else if(iupStrEqualNoCase(value, "CLEARALL"))
+@@ -1673,14 +1665,14 @@ static int winTreeSetMarkAttrib(Ihandle* ih, const char* value)
+ else if(iupStrEqualNoCase(value, "MARKALL"))
+ winTreeSelectAll(ih);
+ else if(iupStrEqualNoCase(value, "INVERTALL")) /* INVERTALL *MUST* appear before INVERT, or else INVERTALL will never be called. */
+- winTreeForEach(ih, NULL, (winTreeNodeFunc)winTreeInvertSelectFunc, NULL);
++ iupTreeForEach(ih, (iupTreeNodeFunc)winTreeInvertSelectFunc, NULL);
+ else if(iupStrEqualPartial(value, "INVERT")) /* iupStrEqualPartial allows the use of "INVERTid" form */
+ {
+- HTREEITEM hItem = winTreeFindNodeFromString(ih, &value[strlen("INVERT")]);
++ HTREEITEM hItem = iupTreeGetNodeFromString(ih, &value[strlen("INVERT")]);
+ if (!hItem)
+ return 0;
+ 
+- winTreeSelectItem(ih, hItem, -1); /* toggle */
++ winTreeSelectNode(ih, hItem, -1); /* toggle */
+ }
+ else
+ {
+@@ -1690,10 +1682,10 @@ static int winTreeSetMarkAttrib(Ihandle* ih, const char* value)
+ if (iupStrToStrStr(value, str1, str2, '-')!=2)
+ return 0;
+ 
+- hItem1 = winTreeFindNodeFromString(ih, str1);
++ hItem1 = iupTreeGetNodeFromString(ih, str1);
+ if (!hItem1) 
+ return 0;
+- hItem2 = winTreeFindNodeFromString(ih, str2);
++ hItem2 = iupTreeGetNodeFromString(ih, str2);
+ if (!hItem2) 
+ return 0;
+ 
+@@ -1711,9 +1703,9 @@ static int winTreeSetValueAttrib(Ihandle* ih, const char* value)
+ if (winTreeSetMarkAttrib(ih, value))
+ return 0;
+ 
+- hItemFocus = winTreeGetFocusNode(ih);
++ hItemFocus = iupdrvTreeGetFocusNode(ih);
+ 
+- if(iupStrEqualNoCase(value, "ROOT"))
++ if(iupStrEqualNoCase(value, "ROOT") || iupStrEqualNoCase(value, "FIRST"))
+ hItem = (HTREEITEM)SendMessage(ih->handle, TVM_GETNEXTITEM, TVGN_ROOT, 0);
+ else if(iupStrEqualNoCase(value, "LAST"))
+ hItem = (HTREEITEM)SendMessage(ih->handle, TVM_GETNEXTITEM, TVGN_LASTVISIBLE, 0);
+@@ -1759,15 +1751,14 @@ static int winTreeSetValueAttrib(Ihandle* ih, const char* value)
+ else if(iupStrEqualNoCase(value, "PREVIOUS"))
+ hItem = (HTREEITEM)SendMessage(ih->handle, TVM_GETNEXTITEM, TVGN_PREVIOUSVISIBLE, (LPARAM)hItemFocus);
+ else
+- hItem = winTreeFindNodeFromString(ih, value);
++ hItem = iupTreeGetNodeFromString(ih, value);
+ 
+ if (hItem)
+ {
+ if (ih->data->mark_mode==ITREE_MARK_SINGLE)
+ {
+- iupAttribSetStr(ih, "_IUPTREE_IGNORE_SELECTION_CB", "1");
+- winTreeSelectItem(ih, hItem, 1);
+- iupAttribSetStr(ih, "_IUPTREE_IGNORE_SELECTION_CB", NULL);
++ winTreeSelectNode(ih, hItemFocus, 0);
++ winTreeSelectNode(ih, hItem, 1);
+ }
+ winTreeSetFocusNode(ih, hItem);
+ }
+@@ -1832,27 +1823,60 @@ static LRESULT CALLBACK winTreeEditWinProc(HWND hwnd, UINT msg, WPARAM wp, LPARA
+ return CallWindowProc(oldProc, hwnd, msg, wp, lp);
+ }
+ 
+-static void winTreeDrag(Ihandle* ih, int x, int y)
++static void winTreeBeginDrag(Ihandle* ih, int x, int y)
+ {
+- HTREEITEM hItemDrop;
++ HIMAGELIST dragImageList;
++
++ HTREEITEM hItemDrag = winTreeFindNodeXY(ih, x, y);
++ if (!hItemDrag)
++ return;
++
++ SendMessage(ih->handle, TVM_ENDEDITLABELNOW, TRUE, 0);
++
++ /* store the drag-and-drop item */
++ iupAttribSetStr(ih, "_IUPTREE_DRAGITEM", (char*)hItemDrag);
+ 
++ /* get the image list for dragging */
++ dragImageList = (HIMAGELIST)SendMessage(ih->handle, TVM_CREATEDRAGIMAGE, 0, (LPARAM)hItemDrag);
++ if (dragImageList)
++ {
++ POINT pt;
++ ImageList_BeginDrag(dragImageList, 0, 0, 0);
++
++ pt.x = x;
++ pt.y = y;
++
++ ClientToScreen(ih->handle, &pt);
++ ImageList_DragEnter(NULL, pt.x, pt.y);
++
++ iupAttribSetStr(ih, "_IUPTREE_DRAGIMAGELIST", (char*)dragImageList);
++ }
++
++ ShowCursor(FALSE);
++ SetCapture(ih->handle); /* drag only inside the tree */
++}
++
++static void winTreeDrag(Ihandle* ih, int x, int y)
++{
++ HTREEITEM hItemDrop = winTreeFindNodeXY(ih, x, y);
++ HTREEITEM hItemDrag = (HTREEITEM)iupAttribGet(ih, "_IUPTREE_DRAGITEM");
+ HIMAGELIST dragImageList = (HIMAGELIST)iupAttribGet(ih, "_IUPTREE_DRAGIMAGELIST");
++
+ if (dragImageList)
+ {
+- POINT pnt;
+- pnt.x = x;
+- pnt.y = y;
+- GetCursorPos(&pnt);
+- ClientToScreen(GetDesktopWindow(), &pnt) ;
+- ImageList_DragMove(pnt.x, pnt.y);
++ POINT pt;
++ pt.x = x;
++ pt.y = y;
++ ClientToScreen(ih->handle, &pt);
++ ImageList_DragMove(pt.x, pt.y);
+ }
+ 
+- if ((hItemDrop = winTreeFindNodePointed(ih)) != NULL)
++ if (hItemDrop && hItemDrop!=hItemDrag)
+ {
+ if(dragImageList)
+ ImageList_DragShowNolock(FALSE);
+ 
+- SendMessage(ih->handle, TVM_SELECTITEM, TVGN_DROPHILITE, (LPARAM)hItemDrop);
++ SendMessage(ih->handle, TVM_SETINSERTMARK, TRUE, (LPARAM)hItemDrop);
+ 
+ /* store the drop item to be executed */
+ iupAttribSetStr(ih, "_IUPTREE_DROPITEM", (char*)hItemDrop);
+@@ -1860,6 +1884,8 @@ static void winTreeDrag(Ihandle* ih, int x, int y)
+ if(dragImageList)
+ ImageList_DragShowNolock(TRUE);
+ }
++ else
++ iupAttribSetStr(ih, "_IUPTREE_DROPITEM", NULL);
+ }
+ 
+ static void winTreeDrop(Ihandle* ih)
+@@ -1882,7 +1908,7 @@ static void winTreeDrop(Ihandle* ih)
+ ShowCursor(TRUE);
+ 
+ /* Remove drop target highlighting */
+- SendMessage(ih->handle, TVM_SELECTITEM, TVGN_DROPHILITE, (LPARAM)NULL);
++ SendMessage(ih->handle, TVM_SETINSERTMARK, 0, (LPARAM)NULL);
+ 
+ iupAttribSetStr(ih, "_IUPTREE_DRAGITEM", NULL);
+ iupAttribSetStr(ih, "_IUPTREE_DROPITEM", NULL);
+@@ -1901,16 +1927,12 @@ static void winTreeDrop(Ihandle* ih)
+ 
+ if (winTreeCallDragDropCb(ih, hItemDrag, hItemDrop, &is_ctrl) == IUP_CONTINUE)
+ {
+- /* Copy the dragged item to the new position. */
+- HTREEITEM hItemNew = winTreeCopyNode(ih, hItemDrag, hItemDrop, is_ctrl);
+-
+- if (!is_ctrl)
+- {
+- /* do not delete the user data, we copy the references in CopyNode */
+- SendMessage(ih->handle, TVM_DELETEITEM, 0, (LPARAM)hItemDrag);
+- }
++ /* Copy or move the dragged item to the new position. */
++ HTREEITEM hItemNew = winTreeCopyMoveNode(ih, hItemDrag, hItemDrop, is_ctrl);
+ 
+- SendMessage(ih->handle, TVM_SELECTITEM, TVGN_CARET, (LPARAM)hItemNew); /* set focus and selection */
++ /* Set focus and selection */
++ if (hItemNew)
++ SendMessage(ih->handle, TVM_SELECTITEM, TVGN_CARET, (LPARAM)hItemNew); 
+ }
+ } 
+ 
+@@ -1929,9 +1951,7 @@ static void winTreeExtendSelect(Ihandle* ih, int x, int y)
+ hItemFirstSel = (HTREEITEM)iupAttribGet(ih, "_IUPTREE_FIRSTSELITEM");
+ if (hItemFirstSel)
+ {
+- iupAttribSetStr(ih, "_IUPTREE_IGNORE_SELECTION_CB", "1");
+ winTreeSelectRange(ih, hItemFirstSel, hItem, 1);
+- iupAttribSetStr(ih, "_IUPTREE_IGNORE_SELECTION_CB", NULL);
+ 
+ iupAttribSetStr(ih, "_IUPTREE_LASTSELITEM", (char*)hItem);
+ winTreeSetFocusNode(ih, hItem);
+@@ -1952,10 +1972,10 @@ static int winTreeMouseMultiSelect(Ihandle* ih, int x, int y)
+ if (GetKeyState(VK_CONTROL) & 0x8000) /* Control key is down */
+ {
+ /* Toggle selection state */
+- winTreeSelectItem(ih, hItem, -1);
++ winTreeSelectNode(ih, hItem, -1);
+ iupAttribSetStr(ih, "_IUPTREE_FIRSTSELITEM", (char*)hItem);
+ 
+- winTreeCallSelectionCb(ih, winTreeIsItemSelected(ih, hItem), hItem);
++ winTreeCallSelectionCb(ih, winTreeIsNodeSelected(ih, hItem), hItem);
+ winTreeSetFocusNode(ih, hItem);
+ 
+ return 1;
+@@ -1965,9 +1985,11 @@ static int winTreeMouseMultiSelect(Ihandle* ih, int x, int y)
+ HTREEITEM hItemFirstSel = (HTREEITEM)iupAttribGet(ih, "_IUPTREE_FIRSTSELITEM");
+ if (hItemFirstSel)
+ {
+- iupAttribSetStr(ih, "_IUPTREE_IGNORE_SELECTION_CB", "1");
++ int last_id = iupTreeFindNodeId(ih, hItem);
+ winTreeSelectRange(ih, hItemFirstSel, hItem, 1);
+- iupAttribSetStr(ih, "_IUPTREE_IGNORE_SELECTION_CB", NULL);
++
++ /* if last selected item is a branch, then select its children */
++ iupTreeSelectLastCollapsedBranch(ih, &last_id);
+ 
+ winTreeCallMultiSelectionCb(ih);
+ winTreeSetFocusNode(ih, hItem);
+@@ -1975,11 +1997,15 @@ static int winTreeMouseMultiSelect(Ihandle* ih, int x, int y)
+ }
+ }
+ 
++ winTreeCallMultiUnSelectionCb(ih);
++
+ /* simple click */
+ winTreeClearSelection(ih, hItem);
+ iupAttribSetStr(ih, "_IUPTREE_FIRSTSELITEM", (char*)hItem);
+ iupAttribSetStr(ih, "_IUPTREE_EXTENDSELECT", "1");
+ 
++ /* Call SELECT_CB for all unselected nodes */
++
+ return 0;
+ }
+ 
+@@ -2039,7 +2065,7 @@ static int winTreeProc(Ihandle* ih, UINT msg, WPARAM wp, LPARAM lp, LRESULT *res
+ 
+ if (wp == VK_RETURN)
+ {
+- HTREEITEM hItemFocus = winTreeGetFocusNode(ih);
++ HTREEITEM hItemFocus = iupdrvTreeGetFocusNode(ih);
+ if (winTreeCallBranchLeafCb(ih, hItemFocus) != IUP_IGNORE)
+ winTreeExpandItem(ih, hItemFocus, -1);
+ 
+@@ -2056,14 +2082,14 @@ static int winTreeProc(Ihandle* ih, UINT msg, WPARAM wp, LPARAM lp, LRESULT *res
+ {
+ if (GetKeyState(VK_CONTROL) & 0x8000)
+ {
+- HTREEITEM hItemFocus = winTreeGetFocusNode(ih);
++ HTREEITEM hItemFocus = iupdrvTreeGetFocusNode(ih);
+ /* Toggle selection state */
+- winTreeSelectItem(ih, hItemFocus, -1);
++ winTreeSelectNode(ih, hItemFocus, -1);
+ }
+ }
+ else if (wp == VK_UP || wp == VK_DOWN)
+ {
+- HTREEITEM hItemFocus = winTreeGetFocusNode(ih);
++ HTREEITEM hItemFocus = iupdrvTreeGetFocusNode(ih);
+ if (wp == VK_UP)
+ hItemFocus = (HTREEITEM)SendMessage(ih->handle, TVM_GETNEXTITEM, TVGN_PREVIOUSVISIBLE, (LPARAM)hItemFocus);
+ else
+@@ -2084,9 +2110,7 @@ static int winTreeProc(Ihandle* ih, UINT msg, WPARAM wp, LPARAM lp, LRESULT *res
+ HTREEITEM hItemFirstSel = (HTREEITEM)iupAttribGet(ih, "_IUPTREE_FIRSTSELITEM");
+ if (hItemFirstSel)
+ {
+- iupAttribSetStr(ih, "_IUPTREE_IGNORE_SELECTION_CB", "1");
+ winTreeSelectRange(ih, hItemFirstSel, hItemFocus, 1);
+- iupAttribSetStr(ih, "_IUPTREE_IGNORE_SELECTION_CB", NULL);
+ 
+ winTreeCallMultiSelectionCb(ih);
+ winTreeSetFocusNode(ih, hItemFocus);
+@@ -2138,10 +2162,20 @@ static int winTreeProc(Ihandle* ih, UINT msg, WPARAM wp, LPARAM lp, LRESULT *res
+ }
+ break;
+ case WM_MOUSEMOVE:
+- if (ih->data->show_dragdrop && (HTREEITEM)iupAttribGet(ih, "_IUPTREE_DRAGITEM") != NULL)
+- winTreeDrag(ih, (int)(short)LOWORD(lp), (int)(short)HIWORD(lp));
++ if (ih->data->show_dragdrop && (wp & MK_LBUTTON))
++ {
++ if (!iupAttribGet(ih, "_IUPTREE_DRAGITEM"))
++ winTreeBeginDrag(ih, (int)(short)LOWORD(lp), (int)(short)HIWORD(lp));
++ else 
++ winTreeDrag(ih, (int)(short)LOWORD(lp), (int)(short)HIWORD(lp));
++ }
+ else if (iupAttribGet(ih, "_IUPTREE_EXTENDSELECT"))
+- winTreeExtendSelect(ih, (int)(short)LOWORD(lp), (int)(short)HIWORD(lp));
++ {
++ if (wp & MK_LBUTTON)
++ winTreeExtendSelect(ih, (int)(short)LOWORD(lp), (int)(short)HIWORD(lp));
++ else
++ iupAttribSetStr(ih, "_IUPTREE_EXTENDSELECT", NULL);
++ }
+ 
+ iupwinMouseMove(ih, msg, wp, lp);
+ break;
+@@ -2157,6 +2191,7 @@ static int winTreeProc(Ihandle* ih, UINT msg, WPARAM wp, LPARAM lp, LRESULT *res
+ if (iupAttribGet(ih, "_IUPTREE_EXTENDSELECT"))
+ {
+ iupAttribSetStr(ih, "_IUPTREE_EXTENDSELECT", NULL);
++
+ if (iupAttribGet(ih, "_IUPTREE_LASTSELITEM"))
+ {
+ winTreeCallMultiSelectionCb(ih);
+@@ -2205,14 +2240,19 @@ static int winTreeWmNotify(Ihandle* ih, NMHDR* msg_info, int *result)
+ else if (msg_info->code == TVN_SELCHANGED)
+ {
+ NMTREEVIEW* info = (NMTREEVIEW*)msg_info;
+- winTreeCallSelectionCb(ih, 0, info->itemOld.hItem); /* node unselected */
+- winTreeCallSelectionCb(ih, 1, info->itemNew.hItem); /* node selected */
++ if (ih->data->mark_mode!=ITREE_MARK_MULTIPLE || /* (NOT) Multiple selection with Control or Shift key is down */
++ !(GetKeyState(VK_CONTROL) & 0x8000 || GetKeyState(VK_SHIFT) & 0x8000)) 
++ {
++ winTreeCallSelectionCb(ih, 0, info->itemOld.hItem); /* node unselected */
++ winTreeCallSelectionCb(ih, 1, info->itemNew.hItem); /* node selected */
++ }
+ }
+ else if(msg_info->code == TVN_BEGINLABELEDIT)
+ {
+ char* value;
+ HWND hEdit;
+ NMTVDISPINFO* info = (NMTVDISPINFO*)msg_info;
++ IFni cbShowRename;
+ 
+ if (iupAttribGet(ih, "_IUPTREE_EXTENDSELECT"))
+ {
+@@ -2220,6 +2260,13 @@ static int winTreeWmNotify(Ihandle* ih, NMHDR* msg_info, int *result)
+ return 1;
+ }
+ 
++ cbShowRename = (IFni)IupGetCallback(ih, "SHOWRENAME_CB");
++ if (cbShowRename && cbShowRename(ih, iupTreeFindNodeId(ih, info->item.hItem))==IUP_IGNORE)
++ {
++ *result = TRUE; /* prevent the change */
++ return 1;
++ }
++
+ hEdit = (HWND)SendMessage(ih->handle, TVM_GETEDITCONTROL, 0, 0);
+ 
+ /* save the edit box. */
+@@ -2253,57 +2300,30 @@ static int winTreeWmNotify(Ihandle* ih, NMHDR* msg_info, int *result)
+ }
+ else if(msg_info->code == TVN_ENDLABELEDIT)
+ {
++ IFnis cbRename;
+ NMTVDISPINFO* info = (NMTVDISPINFO*)msg_info;
+ 
+ iupAttribSetStr(ih, "_IUPWIN_EDITBOX", NULL);
+ 
+- if (info->item.pszText)
+- {
+- IFnis cbRename = (IFnis)IupGetCallback(ih, "RENAME_CB");
+- if (cbRename)
+- {
+- if (cbRename(ih, winTreeGetNodeId(ih, info->item.hItem), info->item.pszText) == IUP_IGNORE)
+- {
+- *result = FALSE;
+- return 1;
+- }
+- }
++ if (!info->item.pszText) /* cancel, so abort */
++ return 0;
+ 
+- *result = TRUE;
+- return 1;
+- }
+- }
+- else if(msg_info->code == TVN_BEGINDRAG)
+- {
+- if (ih->data->show_dragdrop)
++ cbRename = (IFnis)IupGetCallback(ih, "RENAME_CB");
++ if (cbRename)
+ {
+- NMTREEVIEW* pNMTreeView = (NMTREEVIEW*)msg_info;
+- HTREEITEM hItemDrag = pNMTreeView->itemNew.hItem;
+- HIMAGELIST dragImageList;
+-
+- /* store the drag-and-drop item */
+- iupAttribSetStr(ih, "_IUPTREE_DRAGITEM", (char*)hItemDrag);
+-
+- /* get the image list for dragging */
+- dragImageList = (HIMAGELIST)SendMessage(ih->handle, TVM_CREATEDRAGIMAGE, 0, (LPARAM)hItemDrag);
+- if (dragImageList)
++ if (cbRename(ih, iupTreeFindNodeId(ih, info->item.hItem), info->item.pszText) == IUP_IGNORE)
+ {
+- POINT pt = pNMTreeView->ptDrag;
+- ImageList_BeginDrag(dragImageList, 0, 0, 0);
+-
+- ClientToScreen(ih->handle, &pt);
+- ImageList_DragEnter(NULL, pt.x, pt.y);
+-
+- iupAttribSetStr(ih, "_IUPTREE_DRAGIMAGELIST", (char*)dragImageList);
++ *result = FALSE;
++ return 1;
+ }
+-
+- ShowCursor(FALSE);
+- SetCapture(ih->handle); /* drag only inside the tree */
+ }
++
++ *result = TRUE;
++ return 1;
+ }
+ else if(msg_info->code == NM_DBLCLK)
+ {
+- HTREEITEM hItemFocus = winTreeGetFocusNode(ih);
++ HTREEITEM hItemFocus = iupdrvTreeGetFocusNode(ih);
+ TVITEM item;
+ winTreeItemData* itemData;
+ 
+@@ -2317,7 +2337,7 @@ static int winTreeWmNotify(Ihandle* ih, NMHDR* msg_info, int *result)
+ {
+ IFni cbExecuteLeaf = (IFni)IupGetCallback(ih, "EXECUTELEAF_CB");
+ if(cbExecuteLeaf)
+- cbExecuteLeaf(ih, winTreeGetNodeId(ih, hItemFocus));
++ cbExecuteLeaf(ih, iupTreeFindNodeId(ih, hItemFocus));
+ }
+ }
+ else if(msg_info->code == TVN_ITEMEXPANDING)
+@@ -2351,7 +2371,7 @@ static int winTreeWmNotify(Ihandle* ih, NMHDR* msg_info, int *result)
+ HTREEITEM hItem = winTreeFindNodePointed(ih);
+ IFni cbRightClick = (IFni)IupGetCallback(ih, "RIGHTCLICK_CB");
+ if (cbRightClick)
+- cbRightClick(ih, winTreeGetNodeId(ih, hItem));
++ cbRightClick(ih, iupTreeFindNodeId(ih, hItem));
+ }
+ else if (msg_info->code == NM_CUSTOMDRAW)
+ {
+@@ -2374,7 +2394,7 @@ static int winTreeWmNotify(Ihandle* ih, NMHDR* msg_info, int *result)
+ SendMessage(ih->handle, TVM_GETITEM, 0, (LPARAM)(LPTVITEM)&item);
+ itemData = (winTreeItemData*)item.lParam;
+ 
+- if (winTreeIsItemSelected(ih, hItem))
++ if (GetFocus()==ih->handle && (customdraw->nmcd.uItemState & CDIS_SELECTED))
+ customdraw->clrText = winTreeInvertColor(itemData->color);
+ else
+ customdraw->clrText = itemData->color;
+@@ -2402,47 +2422,34 @@ static int winTreeConvertXYToPos(Ihandle* ih, int x, int y)
+ info.pt.y = y;
+ hItem = (HTREEITEM)SendMessage(ih->handle, TVM_HITTEST, 0, (LPARAM)&info);
+ if (hItem)
+- return winTreeGetNodeId(ih, hItem);
++ return iupTreeFindNodeId(ih, hItem);
+ return -1;
+ }
+ 
+ 
+ /*******************************************************************************************/
+ 
+-static void winTreeUnMapMethod(Ihandle* ih)
+-{
+- Iarray* bmp_array;
+- HIMAGELIST image_list;
+-
+- HTREEITEM itemRoot = (HTREEITEM)SendMessage(ih->handle, TVM_GETNEXTITEM, TVGN_ROOT, 0);
+- winTreeDelNodeData(ih, itemRoot);
+-
+- image_list = (HIMAGELIST)SendMessage(ih->handle, TVM_GETIMAGELIST, TVSIL_NORMAL, 0);
+- if (image_list)
+- ImageList_Destroy(image_list);
+-
+- bmp_array = (Iarray*)iupAttribGet(ih, "_IUPWIN_BMPARRAY");
+- if (bmp_array)
+- iupArrayDestroy(bmp_array);
+-
+- iupdrvBaseUnMapMethod(ih);
+-}
+ 
+ static int winTreeMapMethod(Ihandle* ih)
+ {
+- DWORD dwStyle = WS_CHILD | WS_BORDER | TVS_SHOWSELALWAYS;
++ DWORD dwStyle = WS_CHILD | WS_CLIPSIBLINGS | WS_BORDER | TVS_SHOWSELALWAYS;
+ 
+- /* can be set only on the Tree View creation */
++ /* styles can be set only on the Tree View creation */
+ 
+- if (!ih->data->show_dragdrop)
+- dwStyle |= TVS_DISABLEDRAGDROP;
++ /* always disable the internal drag&drop, because it affects our selection and drawing */
++ dwStyle |= TVS_DISABLEDRAGDROP;
+ 
+ if (ih->data->show_rename)
+ dwStyle |= TVS_EDITLABELS;
+ 
+ if (!iupAttribGetBoolean(ih, "HIDELINES"))
++ {
+ dwStyle |= TVS_HASLINES;
+ 
++ if (!iupAttribGetInt(ih, "ADDROOT"))
++ dwStyle |= TVS_LINESATROOT;
++ }
++
+ if (!iupAttribGetBoolean(ih, "HIDEBUTTONS"))
+ dwStyle |= TVS_HASBUTTONS;
+ 
+@@ -2455,6 +2462,11 @@ static int winTreeMapMethod(Ihandle* ih)
+ if (!iupwinCreateWindowEx(ih, WC_TREEVIEW, 0, dwStyle))
+ return IUP_ERROR;
+ 
++ if (!iupwin_comctl32ver6) /* To improve drawing of items when TITLEFONT is set */
++ SendMessage(ih->handle, CCM_SETVERSION, 5, 0); 
++ else
++ SendMessage(ih->handle, TVM_SETEXTENDEDSTYLE, TVS_EX_DOUBLEBUFFER, TVS_EX_DOUBLEBUFFER); 
++
+ IupSetCallback(ih, "_IUPWIN_CTRLPROC_CB", (Icallback)winTreeProc);
+ IupSetCallback(ih, "_IUPWIN_NOTIFY_CB", (Icallback)winTreeWmNotify);
+ 
+@@ -2466,7 +2478,7 @@ static int winTreeMapMethod(Ihandle* ih)
+ winTreeSetBgColorAttrib(ih, value);
+ iupAttribSetStr(ih, "BGCOLOR", NULL);
+ }
+- else if (iupwinGetSystemMajorVersion()<6) /* force background in XP because of the editbox background */
++ else if (!iupwin_comctl32ver6 || iupwinGetSystemMajorVersion()<6) /* force background in XP because of the editbox background */
+ winTreeSetBgColorAttrib(ih, IupGetGlobal("TXTBGCOLOR"));
+ }
+ 
+@@ -2475,8 +2487,8 @@ static int winTreeMapMethod(Ihandle* ih)
+ ih->data->def_image_collapsed = (void*)winTreeGetImageIndex(ih, "IMGCOLLAPSED");
+ ih->data->def_image_expanded = (void*)winTreeGetImageIndex(ih, "IMGEXPANDED");
+ 
+- /* Add the Root Node */
+- winTreeAddRootNode(ih);
++ if (iupAttribGetInt(ih, "ADDROOT"))
++ iupdrvTreeAddNode(ih, "-1", ITREE_BRANCH, "", 0);
+ 
+ /* configure for DRAG&DROP of files */
+ if (IupGetCallback(ih, "DROPFILES_CB"))
+@@ -2484,9 +2496,31 @@ static int winTreeMapMethod(Ihandle* ih)
+ 
+ IupSetCallback(ih, "_IUP_XY2POS_CB", (Icallback)winTreeConvertXYToPos);
+ 
++ iupdrvTreeUpdateMarkMode(ih);
++
+ return IUP_NOERROR;
+ }
+ 
++static void winTreeUnMapMethod(Ihandle* ih)
++{
++ Iarray* bmp_array;
++ HIMAGELIST image_list;
++
++ winTreeRemoveAllNodeData(ih, 0);
++
++ ih->data->node_count = 0;
++
++ image_list = (HIMAGELIST)SendMessage(ih->handle, TVM_GETIMAGELIST, TVSIL_NORMAL, 0);
++ if (image_list)
++ ImageList_Destroy(image_list);
++
++ bmp_array = (Iarray*)iupAttribGet(ih, "_IUPWIN_BMPARRAY");
++ if (bmp_array)
++ iupArrayDestroy(bmp_array);
++
++ iupdrvBaseUnMapMethod(ih);
++}
++
+ void iupdrvTreeInitClass(Iclass* ic)
+ {
+ /* Driver Dependent Class functions */
+@@ -2500,7 +2534,6 @@ void iupdrvTreeInitClass(Iclass* ic)
+ /* IupTree Attributes - GENERAL */
+ iupClassRegisterAttribute(ic, "EXPANDALL", NULL, winTreeSetExpandAllAttrib, NULL, NULL, IUPAF_WRITEONLY|IUPAF_NO_INHERIT);
+ iupClassRegisterAttribute(ic, "INDENTATION", winTreeGetIndentationAttrib, winTreeSetIndentationAttrib, NULL, NULL, IUPAF_DEFAULT);
+- iupClassRegisterAttribute(ic, "COUNT", winTreeGetCountAttrib, NULL, NULL, NULL, IUPAF_NO_DEFAULTVALUE|IUPAF_READONLY|IUPAF_NO_INHERIT);
+ iupClassRegisterAttribute(ic, "DRAGDROP", NULL, iupwinSetDragDropAttrib, NULL, NULL, IUPAF_NO_INHERIT);
+ iupClassRegisterAttribute(ic, "SPACING", iupTreeGetSpacingAttrib, winTreeSetSpacingAttrib, NULL, NULL, IUPAF_NOT_MAPPED);
+ iupClassRegisterAttribute(ic, "TOPITEM", NULL, winTreeSetTopItemAttrib, NULL, NULL, IUPAF_WRITEONLY|IUPAF_NO_INHERIT);
+@@ -2521,7 +2554,6 @@ void iupdrvTreeInitClass(Iclass* ic)
+ iupClassRegisterAttributeId(ic, "NAME", winTreeGetTitleAttrib, winTreeSetTitleAttrib, IUPAF_NO_INHERIT);
+ iupClassRegisterAttributeId(ic, "TITLE", winTreeGetTitleAttrib, winTreeSetTitleAttrib, IUPAF_NO_INHERIT);
+ iupClassRegisterAttributeId(ic, "CHILDCOUNT", winTreeGetChildCountAttrib, NULL, IUPAF_READONLY|IUPAF_NO_INHERIT);
+- iupClassRegisterAttributeId(ic, "USERDATA", winTreeGetUserDataAttrib, winTreeSetUserDataAttrib, IUPAF_NO_STRING|IUPAF_NO_INHERIT);
+ iupClassRegisterAttributeId(ic, "COLOR", winTreeGetColorAttrib, winTreeSetColorAttrib, IUPAF_NO_INHERIT);
+ iupClassRegisterAttributeId(ic, "TITLEFONT", winTreeGetTitleFontAttrib, winTreeSetTitleFontAttrib, IUPAF_NO_INHERIT);
+ 
+@@ -2530,6 +2562,7 @@ void iupdrvTreeInitClass(Iclass* ic)
+ iupClassRegisterAttribute (ic, "MARK", NULL, winTreeSetMarkAttrib, NULL, NULL, IUPAF_WRITEONLY|IUPAF_NO_INHERIT);
+ iupClassRegisterAttribute (ic, "STARTING", NULL, winTreeSetMarkStartAttrib, NULL, NULL, IUPAF_NO_DEFAULTVALUE|IUPAF_NO_INHERIT);
+ iupClassRegisterAttribute (ic, "MARKSTART", NULL, winTreeSetMarkStartAttrib, NULL, NULL, IUPAF_NO_DEFAULTVALUE|IUPAF_NO_INHERIT);
++ iupClassRegisterAttribute (ic, "MARKEDNODES", winTreeGetMarkedNodesAttrib, winTreeSetMarkedNodesAttrib, NULL, NULL, IUPAF_NO_DEFAULTVALUE|IUPAF_NO_INHERIT);
+ 
+ iupClassRegisterAttribute (ic, "VALUE", winTreeGetValueAttrib, winTreeSetValueAttrib, NULL, NULL, IUPAF_NO_DEFAULTVALUE|IUPAF_NO_INHERIT);
+ 
+@@ -2538,5 +2571,8 @@ void iupdrvTreeInitClass(Iclass* ic)
+ iupClassRegisterAttribute(ic, "RENAME", NULL, winTreeSetRenameAttrib, NULL, NULL, IUPAF_WRITEONLY|IUPAF_NO_INHERIT);
+ iupClassRegisterAttributeId(ic, "MOVENODE", NULL, winTreeSetMoveNodeAttrib, IUPAF_NOT_MAPPED|IUPAF_WRITEONLY|IUPAF_NO_INHERIT);
+ iupClassRegisterAttributeId(ic, "COPYNODE", NULL, winTreeSetCopyNodeAttrib, IUPAF_NOT_MAPPED|IUPAF_WRITEONLY|IUPAF_NO_INHERIT);
+- iupClassRegisterAttributeId(ic, "FINDUSERDATA", winTreeGetFindUserDataAttrib, NULL, IUPAF_READONLY|IUPAF_NO_INHERIT);
++
++ /* necessary because transparent background does not work when not using visual styles */
++ if (!iupwin_comctl32ver6) /* Used by iupdrvImageCreateImage */
++ iupClassRegisterAttribute(ic, "FLAT_ALPHA", NULL, NULL, IUPAF_SAMEASSYSTEM, "YES", IUPAF_NOT_MAPPED|IUPAF_NO_INHERIT);
+ }
+diff --git a/iup/src/win/iupwin_val.c b/iup/src/win/iupwin_val.c
+index 706c612..5c956d9 100755
+--- a/iup/src/win/iupwin_val.c
++++ b/iup/src/win/iupwin_val.c
+@@ -56,6 +56,13 @@ void iupdrvValGetMinSize(Ihandle* ih, int *w, int *h)
+ }
+ }
+ 
++static int winValSetBgColorAttrib(Ihandle *ih, const char *value)
++{
++ (void)value;
++ iupdrvPostRedraw(ih);
++ return 1;
++}
++
+ static int winValSetStepAttrib(Ihandle* ih, const char* value)
+ {
+ int linesize;
+@@ -110,18 +117,6 @@ static int winValSetValueAttrib(Ihandle* ih, const char* value)
+ /*********************************************************************************************/
+ 
+ 
+-static int winValCtlColor(Ihandle* ih, HDC hdc, LRESULT *result)
+-{
+- COLORREF cr;
+- if (iupwinGetParentBgColor(ih, &cr))
+- {
+- SetDCBrushColor(hdc, cr);
+- *result = (LRESULT)GetStockObject(DC_BRUSH);
+- return 1;
+- }
+- return 0;
+-}
+-
+ static int winValCustomScroll(Ihandle* ih, int msg)
+ {
+ double old_val = ih->data->val;
+@@ -190,6 +185,19 @@ static void winValIncPageValue(Ihandle *ih, int dir)
+ winValCustomScroll(ih, 0);
+ }
+ 
++static int winValCtlColor(Ihandle* ih, HDC hdc, LRESULT *result)
++{
++ COLORREF cr;
++ if (iupwinGetParentBgColor(ih, &cr))
++ {
++ SetBkColor(hdc, cr);
++ SetDCBrushColor(hdc, cr);
++ *result = (LRESULT)GetStockObject(DC_BRUSH);
++ return 1;
++ }
++ return 0;
++}
++
+ static int winValProc(Ihandle* ih, UINT msg, WPARAM wp, LPARAM lp, LRESULT *result)
+ {
+ (void)lp;
+@@ -240,7 +248,7 @@ static int winValProc(Ihandle* ih, UINT msg, WPARAM wp, LPARAM lp, LRESULT *resu
+ 
+ static int winValMapMethod(Ihandle* ih)
+ {
+- DWORD dwStyle = WS_CHILD | TBS_AUTOTICKS;
++ DWORD dwStyle = WS_CHILD | WS_CLIPSIBLINGS | TBS_AUTOTICKS;
+ int show_ticks;
+ 
+ if (!ih->parent)
+@@ -312,4 +320,7 @@ void iupdrvValInitClass(Iclass* ic)
+ iupClassRegisterAttribute(ic, "STEP", iupValGetStepAttrib, winValSetStepAttrib, "0.01", NULL, IUPAF_NO_INHERIT); /* force new default value */
+ 
+ iupClassRegisterAttribute(ic, "TICKSPOS", NULL, NULL, "NORMAL", NULL, IUPAF_NOT_MAPPED);
++
++ /* Visual */
++ iupClassRegisterAttribute(ic, "BGCOLOR", NULL, winValSetBgColorAttrib, IUPAF_SAMEASSYSTEM, "DLGBGCOLOR", IUPAF_DEFAULT);
+ }
+diff --git a/iup/srccd/Makefile b/iup/srccd/Makefile
+index 43a3f09..8b1d154 100755
+--- a/iup/srccd/Makefile
++++ b/iup/srccd/Makefile
+@@ -3,4 +3,4 @@
+ do_all: iupcd
+ 
+ iupcd:
+- @$(MAKE) --no-print-directory -f ../tecmake_compact.mak 
++ @$(MAKE) --no-print-directory -f ../tecmake.mak 
+diff --git a/iup/srccd/iup_cd.c b/iup/srccd/iup_cd.c
+index 5998775..619ded7 100755
+--- a/iup/srccd/iup_cd.c
++++ b/iup/srccd/iup_cd.c
+@@ -14,7 +14,6 @@
+ #include <cdiup.h>
+ #include <cdnative.h>
+ 
+-
+ static void (*cdcreatecanvasNATIVE)(cdCanvas* canvas, void* data) = NULL;
+ 
+ static void cdcreatecanvasIUP(cdCanvas* canvas, Ihandle *ih_canvas)
+@@ -24,8 +23,12 @@ static void cdcreatecanvasIUP(cdCanvas* canvas, Ihandle *ih_canvas)
+ #endif
+ char* data;
+ 
+- if (IupGetInt(ih_canvas, "CD_GDK"))
++ if (cdBaseDriver()==CD_BASE_GDK)
++ {
+ data = IupGetAttribute(ih_canvas, "DRAWABLE"); /* new IUP 3 attribute, works for GTK only */
++ if (!data)
++ return;
++ }
+ else
+ {
+ #ifdef WIN32
+diff --git a/iup/srcconsole/Makefile b/iup/srcconsole/Makefile
+index 876ca8d..505b103 100755
+--- a/iup/srcconsole/Makefile
++++ b/iup/srcconsole/Makefile
+@@ -3,10 +3,10 @@
+ do_all: iuplua5
+ 
+ iuplua5:
+- @$(MAKE) --no-print-directory -f ../tecmake_compact.mak 
++ @$(MAKE) --no-print-directory -f ../tecmake.mak 
+ 
+ iuplua5gtk:
+- @$(MAKE) --no-print-directory -f ../tecmake_compact.mak USE_GTK=Yes
++ @$(MAKE) --no-print-directory -f ../tecmake.mak USE_GTK=Yes
+ 
+ iuplua3:
+- @$(MAKE) --no-print-directory -f ../tecmake_compact.mak MF=iuplua3
++ @$(MAKE) --no-print-directory -f ../tecmake.mak MF=iuplua3
+diff --git a/iup/srcconsole/config.mak b/iup/srcconsole/config.mak
+index 612a3ab..568bed6 100755
+--- a/iup/srcconsole/config.mak
++++ b/iup/srcconsole/config.mak
+@@ -1,12 +1,23 @@
+ PROJNAME = iup
+ APPNAME = iuplua51
+-APPTYPE = console
++APPTYPE = CONSOLE
++
++ifdef GTK_DEFAULT
++ ifdef USE_MOTIF
++ # Build Motif version in Linux,Darwin,FreeBSD
++ APPNAME = iuplua51mot
++ endif
++else 
++ ifdef USE_GTK
++ # Build GTK version in IRIX,SunOS,AIX,Win32
++ APPNAME = iuplua51gtk
++ endif
++endif
+ 
+ LOHDIR = loh
+ SRCLUA = console5.lua
+ SRC = iup_lua51.c
+ 
+-
+ # Disable strip
+ STRIP = 
+ # Optimize
+@@ -35,6 +46,16 @@ ifdef DBG
+ USE_STATIC = Yes
+ USE_LUA51 = Yes
+ 
++ ifdef DBG_DIR
++ IUPLIB = $(IUP)/lib/$(TEC_UNAME)d
++ CDLIB = $(CD)/lib/$(TEC_UNAME)d
++ IMLIB = $(IM)/lib/$(TEC_UNAME)d
++ else
++ IUPLIB = $(IUP)/lib/$(TEC_UNAME)
++ CDLIB = $(CD)/lib/$(TEC_UNAME)
++ IMLIB = $(IM)/lib/$(TEC_UNAME)
++ endif 
++ 
+ DEFINES = USE_STATIC
+ 
+ USE_CDLUA = Yes
+@@ -42,7 +63,6 @@ ifdef DBG
+ ifneq ($(findstring Win, $(TEC_SYSNAME)), )
+ LIBS += iuplua_pplot$(LIBLUASUFX) iup_pplot
+ else
+- IUPLIB = $(IUP)/lib/$(TEC_UNAME)
+ SLIB += $(IUPLIB)/libiuplua_pplot$(LIBLUASUFX).a $(IUPLIB)/libiup_pplot.a
+ endif
+ 
+@@ -50,7 +70,6 @@ ifdef DBG
+ ifneq ($(findstring Win, $(TEC_SYSNAME)), )
+ LIBS += cdluaim$(LIBLUASUFX)
+ else
+- CDLIB = $(CD)/lib/$(TEC_UNAME)
+ SLIB += $(CDLIB)/libcdluaim$(LIBLUASUFX).a
+ endif
+ endif
+@@ -65,8 +84,6 @@ ifdef DBG
+ ifneq ($(findstring Win, $(TEC_SYSNAME)), )
+ LIBS += imlua_process$(LIBLUASUFX) iupluaim$(LIBLUASUFX) im_process iupim
+ else
+- IUPLIB = $(IUP)/lib/$(TEC_UNAME)
+- IMLIB = $(IM)/lib/$(TEC_UNAME)
+ SLIB += $(IMLIB)/libimlua_process$(LIBLUASUFX).a $(IUPLIB)/libiupluaim$(LIBLUASUFX).a $(IMLIB)/libim_process.a $(IUPLIB)/libiupim.a
+ endif
+ 
+@@ -77,20 +94,24 @@ ifdef DBG
+ ifneq ($(findstring Win, $(TEC_SYSNAME)), )
+ LIBS += iupluaimglib$(LIBLUASUFX) iupimglib
+ else
+- IUPLIB = $(IUP)/lib/$(TEC_UNAME)
+ SLIB += $(IUPLIB)/libiupluaimglib$(LIBLUASUFX).a $(IUPLIB)/libiupimglib.a
+ endif
+ endif
+ else
+ ifneq ($(findstring Win, $(TEC_SYSNAME)), )
+ # Dinamically link in Windows, when not debugging
+- # Must call "tecmake dll8"
++ # Must call "tecmake dll8" so USE_* will use the correct TEC_UNAME
+ USE_LUA51 = Yes
+ USE_DLL = Yes
+ GEN_MANIFEST = No
+ else
+ # In UNIX Lua is always statically linked, late binding is used.
+- USE_STATIC = Yes
++ # Except in Cygwin and MacOSX
++ ifeq ($(findstring cygw, $(TEC_UNAME)), )
++ ifeq ($(findstring Darwin, $(TEC_UNAME)), )
++ USE_STATIC = Yes
++ endif
++ endif
+ USE_LUA51 = Yes
+ endif
+ endif
+@@ -102,10 +123,13 @@ ifneq ($(findstring Win, $(TEC_SYSNAME)), )
+ endif
+ 
+ ifneq ($(findstring cygw, $(TEC_UNAME)), )
+- LDFLAGS = -s
+ LIBS += readline history
+ endif
+ 
++ifneq ($(findstring Darwin, $(TEC_UNAME)), )
++ LIBS += readline
++endif
++
+ ifneq ($(findstring Linux, $(TEC_UNAME)), )
+ LIBS += dl 
+ #To allow late binding
+@@ -129,10 +153,3 @@ ifneq ($(findstring AIX, $(TEC_UNAME)), )
+ LFLAGS = -Xlinker "-bbigtoc"
+ endif
+ 
+-ifeq ($(TEC_UNAME), vc8)
+- ifdef DBG
+- #debug info not working for vc8 linker
+- define DBG
+- endef
+- endif
+-endif 
+diff --git a/iup/srcconsole/console5.lua b/iup/srcconsole/console5.lua
+index 20f74b2..0b93641 100755
+--- a/iup/srcconsole/console5.lua
++++ b/iup/srcconsole/console5.lua
+@@ -1,67 +1,69 @@
+ require"iuplua"
+ 
+-iup.console = {}
+-
+ -- Utilities
++iup_console = {}
+ 
+-function iup.console.printtable(t)
+- local n,v = next(t, nil)
+- print("--printtable Start--")
+- while n do
+- print(tostring(n).."="..tostring(v))
+- n,v = next(t, n)
+- end
+- print("--printtable End--")
++function iup_console.concat(str, info)
++ return str .. info .. "\n"
+ end
+ 
+-function iup.console.print_version_info()
+- if (im) then print("IM " .. im._VERSION .. " " .. im._COPYRIGHT) end
++function iup_console.print_version_info()
++ iup_console.clear()
++ local str = ""
++ if (im) then str = iup_console.concat(str, "IM " .. im._VERSION .. " " .. im._COPYRIGHT) end
+ 
+- if (cd) then print("CD " .. cd._VERSION .. " " .. cd._COPYRIGHT) end
++ if (cd) then str = iup_console.concat(str, "CD " .. cd._VERSION .. " " .. cd._COPYRIGHT) end
+ 
+- print("IUP " .. iup._VERSION .. " " .. iup._COPYRIGHT)
+- print("")
+- print("IUP Info")
+- print(" System: " .. iup.GetGlobal("SYSTEM"))
+- print(" System Version: " .. iup.GetGlobal("SYSTEMVERSION"))
++ str = iup_console.concat(str, "IUP " .. iup._VERSION .. " " .. iup._COPYRIGHT)
++ str = iup_console.concat(str, "")
++ str = iup_console.concat(str, "IUP Info")
++ str = iup_console.concat(str, " System: " .. iup.GetGlobal("SYSTEM"))
++ str = iup_console.concat(str, " System Version: " .. iup.GetGlobal("SYSTEMVERSION"))
+ 
+ local mot = iup.GetGlobal("MOTIFVERSION")
+- if (mot) then print(" Motif Version: ", mot) end
++ if (mot) then str = iup_console.concat(str, " Motif Version: ", mot) end
+ 
+- print(" Screen Size: " .. iup.GetGlobal("SCREENSIZE"))
+- print(" Screen Depth: " .. iup.GetGlobal("SCREENDEPTH"))
++ str = iup_console.concat(str, " Screen Size: " .. iup.GetGlobal("SCREENSIZE"))
++ str = iup_console.concat(str, " Screen Depth: " .. iup.GetGlobal("SCREENDEPTH"))
+ 
+- if (iup.GL_VENDOR) then print(" OpenGL Vendor: " .. iup.GL_VENDOR) end
+- if (iup.GL_RENDERER) then print(" OpenGL Renderer: " .. iup.GL_RENDERER) end
+- if (iup.GL_VERSION) then print(" OpenGL Version: " .. iup.GL_VERSION) end
++ if (iup.GL_VENDOR) then str = iup_console.concat(str, " OpenGL Vendor: " .. iup.GL_VENDOR) end
++ if (iup.GL_RENDERER) then str = iup_console.concat(str, " OpenGL Renderer: " .. iup.GL_RENDERER) end
++ if (iup.GL_VERSION) then str = iup_console.concat(str, " OpenGL Version: " .. iup.GL_VERSION) end
++ 
++ iup_console.mlCode.value=str
+ end
+ 
+ -- Console Dialog
+ 
+-iup.console.lastfilename = nil -- Last file open
+-iup.console.mlCode = iup.multiline{expand="YES", size="200x120", font="COURIER_NORMAL_10"}
+-iup.console.lblPosition = iup.label{title="0:0", size="50x"}
+-iup.console.lblFileName = iup.label{title="", size="50x", expand="HORIZONTAL"}
++iup_console.lastfilename = nil -- Last file open
++iup_console.mlCode = iup.multiline{expand="YES", size="200x120", font="COURIER_NORMAL_10"}
++iup_console.lblPosition = iup.label{title="0:0", size="50x"}
++iup_console.lblFileName = iup.label{title="", size="50x", expand="HORIZONTAL"}
++
++function iup_console.mlCode:caret_cb(lin, col)
++ iup_console.lblPosition.title = lin..":"..col
++end
+ 
+-function iup.console.mlCode:caret_cb(lin, col)
+- iup.console.lblPosition.title = lin..":"..col
++function iup_console.clear()
++ iup_console.mlCode.value='' 
++ iup_console.lblFileName.title = '' 
++ iup_console.lastfilename = nil
+ end
+ 
+-iup.console.butExecute = iup.button{size="50x15", title="Execute",
+- action="iup.dostring(iup.console.mlCode.value)"}
+-iup.console.butClearCommands = iup.button{size="50x15", title="Clear",
+- action="iup.console.mlCode.value='' iup.console.lblFileName.title = '' iup.console.lastfilename = nil"}
+-iup.console.butLoadFile = iup.button{size="50x15", title="Load..."}
+-iup.console.butSaveasFile = iup.button{size="50x15", title="Save As..."}
+-iup.console.butSaveFile = iup.button{size="50x15", title="Save"}
+-
+-function iup.console.butSaveFile:action()
+- if (iup.console.lastfilename == nil) then
+- iup.console.butSaveasFile:action()
++iup_console.butExecute = iup.button{size="50x15", title="Execute",
++ action="iup.dostring(iup_console.mlCode.value)"}
++iup_console.butClearCommands = iup.button{size="50x15", title="Clear", action=iup_console.clear}
++iup_console.butLoadFile = iup.button{size="50x15", title="Load..."}
++iup_console.butSaveasFile = iup.button{size="50x15", title="Save As..."}
++iup_console.butSaveFile = iup.button{size="50x15", title="Save"}
++
++function iup_console.butSaveFile:action()
++ if (iup_console.lastfilename == nil) then
++ iup_console.butSaveasFile:action()
+ else
+- newfile = io.open(iup.console.lastfilename, "w+")
++ newfile = io.open(iup_console.lastfilename, "w+")
+ if (newfile) then
+- newfile:write(iup.console.mlCode.value)
++ newfile:write(iup_console.mlCode.value)
+ newfile:close()
+ else
+ error ("Cannot Save file "..filename)
+@@ -69,21 +71,26 @@ function iup.console.butSaveFile:action()
+ end
+ end
+ 
+-function iup.console.butSaveasFile:action()
+- local fd = iup.filedlg{dialogtype="SAVE", title="Save File",
++function iup_console.butSaveasFile:action()
++ local fd = iup.filedlg{dialogtype="SAVE", title="Save File", 
++ nochangedir="NO", directory=iup_console.last_directory,
+ filter="*.*", filterinfo="All files",allownew=yes}
++ 
+ fd:popup(iup.LEFT, iup.LEFT)
++ 
+ local status = fd.status
+- iup.console.lastfilename = fd.value
+- iup.console.lblFileName.title = iup.console.lastfilename
++ iup_console.lastfilename = fd.value
++ iup_console.lblFileName.title = fd.value
++ iup_console.last_directory = fd.directory
+ fd:destroy()
++ 
+ if status ~= "-1" then
+- if (iup.console.lastfilename == nil) then
++ if (iup_console.lastfilename == nil) then
+ error ("Cannot Save file "..filename)
+ end
+- local newfile=io.open(iup.console.lastfilename, "w+")
++ local newfile=io.open(iup_console.lastfilename, "w+")
+ if (newfile) then
+- newfile:write(iup.console.mlCode.value)
++ newfile:write(iup_console.mlCode.value)
+ newfile:close(newfile)
+ else
+ error ("Cannot Save file")
+@@ -91,24 +98,26 @@ function iup.console.butSaveasFile:action()
+ end
+ end
+ 
+-function iup.console.LoadFile(filename)
++function iup_console.LoadFile(filename)
+ local newfile = io.open (filename, "r")
+ if (newfile == nil) then
+ error ("Cannot load file "..filename)
+ else
+- iup.console.mlCode.value=newfile:read("*a")
++ iup_console.mlCode.value=newfile:read("*a")
+ newfile:close (newfile)
+- iup.console.lastfilename = filename
+- iup.console.lblFileName.title = iup.console.lastfilename
++ iup_console.lastfilename = filename
++ iup_console.lblFileName.title = iup_console.lastfilename
+ end
+ end
+ 
+-function iup.console.butLoadFile:action()
+- local fd=iup.filedlg{dialogtype="OPEN", title="Load File",
++function iup_console.butLoadFile:action()
++ local fd=iup.filedlg{dialogtype="OPEN", title="Load File", 
++ nochangedir="NO", directory=iup_console.last_directory,
+ filter="*.*", filterinfo="All Files", allownew="NO"}
+ fd:popup(iup.CENTER, iup.CENTER)
+ local status = fd.status
+ local filename = fd.value
++ iup_console.last_directory = fd.directory
+ fd:destroy()
+ 
+ if (status == "-1") or (status == "1") then
+@@ -116,21 +125,21 @@ function iup.console.butLoadFile:action()
+ error ("Cannot load file "..filename)
+ end
+ else
+- iup.console.LoadFile(filename)
++ iup_console.LoadFile(filename)
+ end
+ end
+ 
+-iup.console.vbxConsole = iup.vbox
++iup_console.vbxConsole = iup.vbox
+ {
+- iup.frame{iup.hbox{iup.vbox{iup.console.butLoadFile,
+- iup.console.butSaveFile,
+- iup.console.butSaveasFile,
+- iup.console.butClearCommands,
+- iup.console.butExecute;
++ iup.frame{iup.hbox{iup.vbox{iup_console.butLoadFile,
++ iup_console.butSaveFile,
++ iup_console.butSaveasFile,
++ iup_console.butClearCommands,
++ iup_console.butExecute;
+ margin="0x0", gap="10"},
+- iup.vbox{iup.console.lblFileName,
+- iup.console.mlCode,
+- iup.console.lblPosition;
++ iup.vbox{iup_console.lblFileName,
++ iup_console.mlCode,
++ iup_console.lblPosition;
+ alignment = "ARIGHT"};
+ alignment="ATOP"}; title="Commands"}
+ ;alignment="ACENTER", margin="5x5", gap="5"
+@@ -138,7 +147,7 @@ iup.console.vbxConsole = iup.vbox
+ 
+ -- Main Menu Definition.
+ 
+-iup.console.mnuMain = iup.menu
++iup_console.mnuMain = iup.menu
+ {
+ iup.submenu
+ {
+@@ -149,29 +158,29 @@ iup.console.mnuMain = iup.menu
+ },
+ iup.submenu{iup.menu
+ {
+- iup.item{title="Print Version Info...", action=iup.console.print_version_info},
+- iup.item{title="About...", action="iup.console.dlgAbout:popup(iup.CENTER, iup.CENTER)"}
++ iup.item{title="Print Version Info...", action=iup_console.print_version_info},
++ iup.item{title="About...", action="iup_console.dlgAbout:popup(iup.CENTER, iup.CENTER)"}
+ };title="Help"}
+ }
+ 
+ -- Main Dialog Definition.
+ 
+-iup.console.dlgMain = iup.dialog{iup.console.vbxConsole;
++iup_console.dlgMain = iup.dialog{iup_console.vbxConsole;
+ title="IupLua Console",
+- menu=iup.console.mnuMain,
++ menu=iup_console.mnuMain,
+ dragdrop = "YES",
+- defaultenter=iup.console.butExecute,
++ defaultenter=iup_console.butExecute,
+ close_cb = "return iup.CLOSE"}
+ 
+-function iup.console.dlgMain:dropfiles_cb(filename, num, x, y)
++function iup_console.dlgMain:dropfiles_cb(filename, num, x, y)
+ if (num == 0) then
+- iup.console.LoadFile(filename)
++ iup_console.LoadFile(filename)
+ end
+ end
+ 
+ -- About Dialog Definition.
+ 
+-iup.console.dlgAbout = iup.dialog
++iup_console.dlgAbout = iup.dialog
+ {
+ iup.vbox
+ {
+@@ -195,10 +204,12 @@ iup.console.dlgAbout = iup.dialog
+ 
+ -- Displays the Main Dialog
+ 
+-iup.console.dlgMain:show()
+-iup.SetFocus(iup.console.mlCode)
++iup_console.dlgMain:show()
++iup.SetFocus(iup_console.mlCode)
+ 
+-iup.MainLoop()
++if (not iup.MainLoopLevel or iup.MainLoopLevel()==0) then
++ iup.MainLoop()
++end
+ 
+-iup.console.dlgMain:destroy()
+-iup.console.dlgAbout:destroy()
++iup_console.dlgMain:destroy()
++iup_console.dlgAbout:destroy()
+diff --git a/iup/srcconsole/copy_all_so b/iup/srcconsole/copy_all_so
+index 52f1fea..ce3c248 100755
+--- a/iup/srcconsole/copy_all_so
++++ b/iup/srcconsole/copy_all_so
+@@ -2,10 +2,10 @@
+ 
+ foreach plat ( Linux24 Linux24g3 Linux24g3_64 Linux26 Linux26_64 Linux26g4 Linux26g4_64 Linux26_ia64 SunOS57 SunOS510 SunOS510x86 AIX43 IRIX65 IRIX6465 )
+ echo $plat
+- cp -f ../lib/$plat/*.so ../bin/$plat
+- cp -f ../../cd/lib/$plat/*.so ../bin/$plat
+- cp -f ../../im/lib/$plat/*.so ../bin/$plat
++# cp -f ../lib/$plat/*.so ../bin/$plat
++# cp -f ../../cd/lib/$plat/*.so ../bin/$plat
++# cp -f ../../im/lib/$plat/*.so ../bin/$plat
+ cp -f ../../luagl/lib/$plat/*.so ../bin/$plat
+ cp -f ../../lfs/lib/$plat/*.so ../bin/$plat
+- rm -f ../bin/$plat/*3.so
++# rm -f ../bin/$plat/*3.so
+ end
+diff --git a/iup/srcconsole/copy_so b/iup/srcconsole/copy_so
+index 2535766..e345d31 100755
+--- a/iup/srcconsole/copy_so
++++ b/iup/srcconsole/copy_so
+@@ -1,4 +1,6 @@
+ cp -f ../lib/${TEC_UNAME}/*.so ../bin/$TEC_UNAME
+ cp -f ../../cd/lib/${TEC_UNAME}/*.so ../bin/$TEC_UNAME
+ cp -f ../../im/lib/${TEC_UNAME}/*.so ../bin/$TEC_UNAME
++cp -f ../../luagl/lib/${TEC_UNAME}/*.so ../bin/${TEC_UNAME}
++cp -f ../../lfs/lib/${TEC_UNAME}/*.so ../bin/${TEC_UNAME}
+ rm -f ../bin/${TEC_UNAME}/*3.so
+diff --git a/iup/srcconsole/iuplua3.rc b/iup/srcconsole/iuplua3.rc
+index e741199..9fcc280 100755
+--- a/iup/srcconsole/iuplua3.rc
++++ b/iup/srcconsole/iuplua3.rc
+@@ -13,7 +13,7 @@ BEGIN
+ VALUE "CompanyName", "Tecgraf/PUC-Rio\0"
+ VALUE "FileDescription", "Lua Windows Standalone Interpreter with IUP\0"
+ VALUE "FileVersion", "3.0.0\0"
+- VALUE "LegalCopyright", "Copyright © 1994-2009 Tecgraf, PUC-Rio.\0"
++ VALUE "LegalCopyright", "Copyright © 1994-2010 Tecgraf, PUC-Rio.\0"
+ VALUE "OriginalFilename", "iuplua51.exe\0"
+ VALUE "ProductName", "IUP for Windows\0"
+ VALUE "ProductVersion", "3.0.0\0"
+diff --git a/iup/srcconsole/iuplua5.rc b/iup/srcconsole/iuplua5.rc
+index bc02e07..70e40a4 100755
+--- a/iup/srcconsole/iuplua5.rc
++++ b/iup/srcconsole/iuplua5.rc
+@@ -13,7 +13,7 @@ BEGIN
+ VALUE "CompanyName", "Tecgraf/PUC-Rio\0"
+ VALUE "FileDescription", "Lua Windows Standalone Interpreter with IUP\0"
+ VALUE "FileVersion", "3.0.0\0"
+- VALUE "LegalCopyright", "Copyright © 1994-2009 Tecgraf, PUC-Rio.\0"
++ VALUE "LegalCopyright", "Copyright © 1994-2010 Tecgraf, PUC-Rio.\0"
+ VALUE "OriginalFilename", "iuplua51.exe\0"
+ VALUE "ProductName", "IUP for Windows\0"
+ VALUE "ProductVersion", "3.0.0\0"
+diff --git a/iup/srcconsole/make_uname.bat b/iup/srcconsole/make_uname.bat
+index a5b1d9a..a0db110 100755
+--- a/iup/srcconsole/make_uname.bat
++++ b/iup/srcconsole/make_uname.bat
+@@ -6,24 +6,26 @@ if "%1"=="vc8_64" goto iupexe64
+ if "%1"=="all" goto iupexe
+ goto end
+ 
++REM Must use dll8 so USE_* will use the correct TEC_UNAME
++
+ :iupexe32
+ call tecmake dll8 relink %2 %3 %4 %5 %6 %7
+-REM call tecmake dll8 USE_GTK=Yes relink %2 %3 %4 %5 %6 %7
++REM call tecmake vc8 USE_GTK=Yes relink %2 %3 %4 %5 %6 %7
+ REM call tecmake vc8 "MF=iuplua3" relink %2 %3 %4 %5 %6 %7
+ goto end
+ 
+ :iupexe64
+ call tecmake dll8_64 relink %2 %3 %4 %5 %6 %7
+-REM call tecmake dll8_64 USE_GTK=Yes relink %2 %3 %4 %5 %6 %7
++REM call tecmake vc8_64 USE_GTK=Yes relink %2 %3 %4 %5 %6 %7
+ REM call tecmake vc8_64 "MF=iuplua3" relink %2 %3 %4 %5 %6 %7
+ goto end
+ 
+ :iupexe
+ call tecmake dll8 relink %2 %3 %4 %5 %6 %7
+-REM call tecmake dll8 USE_GTK=Yes relink %2 %3 %4 %5 %6 %7
++REM call tecmake vc8 USE_GTK=Yes relink %2 %3 %4 %5 %6 %7
+ REM call tecmake vc8 "MF=iuplua3" relink %2 %3 %4 %5 %6 %7
+ call tecmake dll8_64 relink %2 %3 %4 %5 %6 %7
+-REM call tecmake dll8_64 USE_GTK=Yes relink %2 %3 %4 %5 %6 %7
++REM call tecmake vc8_64 USE_GTK=Yes relink %2 %3 %4 %5 %6 %7
+ REM call tecmake vc8_64 "MF=iuplua3" relink %2 %3 %4 %5 %6 %7
+ goto end
+ 
+diff --git a/iup/srccontrols/Makefile b/iup/srccontrols/Makefile
+index d02bbc3..c928251 100755
+--- a/iup/srccontrols/Makefile
++++ b/iup/srccontrols/Makefile
+@@ -3,4 +3,4 @@
+ do_all: iupcontrols
+ 
+ iupcontrols:
+- @$(MAKE) --no-print-directory -f ../tecmake_compact.mak 
++ @$(MAKE) --no-print-directory -f ../tecmake.mak 
+diff --git a/iup/srccontrols/color/iup_colorbrowser.c b/iup/srccontrols/color/iup_colorbrowser.c
+index 82b4a88..51f8a30 100755
+--- a/iup/srccontrols/color/iup_colorbrowser.c
++++ b/iup/srccontrols/color/iup_colorbrowser.c
+@@ -681,7 +681,7 @@ static int iColorBrowserKeypress_CB(Ihandle* ih, int c, int press)
+ static char* iColorBrowserGetHSIAttrib(Ihandle* ih)
+ {
+ char* buffer = iupStrGetMemory(100);
+- sprintf(buffer, "%f %f %f", (double)ih->data->hue, (double)ih->data->saturation, (double)ih->data->intensity);
++ sprintf(buffer, "%g %g %g", (double)ih->data->hue, (double)ih->data->saturation, (double)ih->data->intensity);
+ return buffer;
+ }
+ 
+@@ -781,10 +781,16 @@ static int iColorBrowserMapMethod(Ihandle* ih)
+ static void iColorBrowserUnMapMethod(Ihandle* ih)
+ {
+ if (ih->data->cddbuffer)
++ {
+ cdKillCanvas(ih->data->cddbuffer);
++ ih->data->cddbuffer = NULL;
++ }
+ 
+ if (ih->data->cdcanvas)
++ {
+ cdKillCanvas(ih->data->cdcanvas);
++ ih->data->cdcanvas = NULL;
++ }
+ }
+ 
+ static int iColorBrowserCreateMethod(Ihandle* ih, void **params)
+diff --git a/iup/srccontrols/color/iup_colorbrowserdlg.c b/iup/srccontrols/color/iup_colorbrowserdlg.c
+index 65e4d37..dc52725 100755
+--- a/iup/srccontrols/color/iup_colorbrowserdlg.c
++++ b/iup/srccontrols/color/iup_colorbrowserdlg.c
+@@ -158,7 +158,7 @@ static void iColorBrowserDlgBrowserRGB_Update(IcolorDlgData* colordlg_data)
+ 
+ static void iColorBrowserDlgBrowserHSI_Update(IcolorDlgData* colordlg_data)
+ {
+- IupSetfAttribute(colordlg_data->color_browser, "HSI", "%f %f %f", (double)colordlg_data->hue, (double)colordlg_data->saturation, (double)colordlg_data->intensity);
++ IupSetfAttribute(colordlg_data->color_browser, "HSI", "%g %g %g", (double)colordlg_data->hue, (double)colordlg_data->saturation, (double)colordlg_data->intensity);
+ }
+ 
+ /*****************************************\
+@@ -575,10 +575,16 @@ static int iColorBrowserDlgColorCnvUnMap_CB(Ihandle* ih)
+ IcolorDlgData* colordlg_data = (IcolorDlgData*)iupAttribGetInherit(ih, "_IUP_GC_DATA");
+ 
+ if (colordlg_data->color_cddbuffer)
++ {
+ cdKillCanvas(colordlg_data->color_cddbuffer);
++ colordlg_data->color_cddbuffer = NULL;
++ }
+ 
+ if (colordlg_data->color_cdcanvas)
++ {
+ cdKillCanvas(colordlg_data->color_cdcanvas);
++ colordlg_data->color_cdcanvas = NULL;
++ }
+ 
+ return IUP_DEFAULT;
+ }
+diff --git a/iup/srccontrols/config.mak b/iup/srccontrols/config.mak
+index 394d607..10f11e1 100755
+--- a/iup/srccontrols/config.mak
++++ b/iup/srccontrols/config.mak
+@@ -13,7 +13,7 @@ SRCMATRIX = iupmat_key.c iupmat_mark.c iupmat_aux.c iupmat_mem.c iupmat_mouse.c
+ SRCMATRIX := $(addprefix matrix/, $(SRCMATRIX))
+ 
+ SRC = iup_cdutil.c iup_gauge.c iup_cells.c iup_colorbar.c iup_controls.c \
+- iup_dial.c iup_oldtabs.c iup_oldval.c iup_oldmask.c \
++ iup_dial.c iup_oldmask.c \
+ $(SRCCOLOR) $(SRCMATRIX)
+ 
+ LIBS = iup iupcd
+diff --git a/iup/srccontrols/iup_cells.c b/iup/srccontrols/iup_cells.c
+index d9a7fe4..c771d6e 100755
+--- a/iup/srccontrols/iup_cells.c
++++ b/iup/srccontrols/iup_cells.c
+@@ -882,10 +882,16 @@ static int iCellsMapMethod(Ihandle* ih)
+ static void iCellsUnMapMethod(Ihandle* ih)
+ {
+ if (ih->data->cddbuffer)
++ {
+ cdKillCanvas(ih->data->cddbuffer);
++ ih->data->cddbuffer = NULL;
++ }
+ 
+ if (ih->data->cdcanvas)
++ {
+ cdKillCanvas(ih->data->cdcanvas);
++ ih->data->cdcanvas = NULL;
++ }
+ }
+ 
+ static int iCellsCreateMethod(Ihandle* ih, void **params)
+diff --git a/iup/srccontrols/iup_colorbar.c b/iup/srccontrols/iup_colorbar.c
+index 72e717c..1cbcd59 100755
+--- a/iup/srccontrols/iup_colorbar.c
++++ b/iup/srccontrols/iup_colorbar.c
+@@ -978,10 +978,16 @@ static int iColorbarMapMethod(Ihandle* ih)
+ static void iColorbarUnMapMethod(Ihandle* ih)
+ {
+ if (ih->data->cddbuffer)
++ {
+ cdKillCanvas(ih->data->cddbuffer);
++ ih->data->cddbuffer = NULL;
++ }
+ 
+ if (ih->data->cdcanvas)
++ {
+ cdKillCanvas(ih->data->cdcanvas);
++ ih->data->cdcanvas = NULL;
++ }
+ }
+ 
+ static int iColorbarCreateMethod(Ihandle* ih, void **params)
+diff --git a/iup/srccontrols/iup_dial.c b/iup/srccontrols/iup_dial.c
+index 1dd2d0f..c8c5656 100755
+--- a/iup/srccontrols/iup_dial.c
++++ b/iup/srccontrols/iup_dial.c
+@@ -640,7 +640,7 @@ static int iDialWheel_CB(Ihandle* ih, float delta)
+ static char* iDialGetValueAttrib(Ihandle* ih)
+ {
+ char* str = iupStrGetMemory(20);
+- sprintf(str, "%f", ih->data->angle);
++ sprintf(str, "%g", ih->data->angle);
+ return str;
+ }
+ 
+@@ -665,7 +665,7 @@ static int iDialSetDensityAttrib(Ihandle* ih, const char* value)
+ static char* iDialGetDensityAttrib(Ihandle* ih)
+ {
+ char* str = iupStrGetMemory(20);
+- sprintf(str, "%f", ih->data->density);
++ sprintf(str, "%g", ih->data->density);
+ return str;
+ }
+ 
+@@ -780,10 +780,16 @@ static int iDialMapMethod(Ihandle* ih)
+ static void iDialUnMapMethod(Ihandle* ih)
+ {
+ if (ih->data->cddbuffer)
++ {
+ cdKillCanvas(ih->data->cddbuffer);
++ ih->data->cddbuffer = NULL;
++ }
+ 
+ if (ih->data->cdcanvas)
++ {
+ cdKillCanvas(ih->data->cdcanvas);
++ ih->data->cdcanvas = NULL;
++ }
+ }
+ 
+ static int iDialCreateMethod(Ihandle* ih, void **params)
+diff --git a/iup/srccontrols/iup_gauge.c b/iup/srccontrols/iup_gauge.c
+index 8732eee..300b28e 100755
+--- a/iup/srccontrols/iup_gauge.c
++++ b/iup/srccontrols/iup_gauge.c
+@@ -347,10 +347,16 @@ static char* iGaugeGetTextAttrib(Ihandle* ih)
+ static void iGaugeUnMapMethod(Ihandle* ih)
+ {
+ if (ih->data->cddbuffer)
++ {
+ cdKillCanvas(ih->data->cddbuffer);
++ ih->data->cddbuffer = NULL;
++ }
+ 
+ if (ih->data->cdcanvas)
++ {
+ cdKillCanvas(ih->data->cdcanvas);
++ ih->data->cdcanvas = NULL;
++ }
+ }
+ 
+ static int iGaugeMapMethod(Ihandle* ih)
+diff --git a/iup/srccontrols/iup_oldmask.c b/iup/srccontrols/iup_oldmask.c
+index fec10f3..2ec4012 100755
+--- a/iup/srccontrols/iup_oldmask.c
++++ b/iup/srccontrols/iup_oldmask.c
+@@ -42,14 +42,14 @@ int iupmaskMatSetInt(Ihandle *ih, int autofill, int min, int max, int lin, int c
+ int iupmaskSetFloat(Ihandle* ih, int autofill, float min, float max)
+ {
+ (void)autofill;
+- IupSetfAttribute(ih,"MASKFLOAT", "%f:%f", min, max);
++ IupSetfAttribute(ih,"MASKFLOAT", "%g:%g", min, max);
+ return 1;
+ }
+ 
+ int iupmaskMatSetFloat(Ihandle* ih, int autofill, float min, float max, int lin, int col)
+ {
+ (void)autofill;
+- IupMatSetfAttribute(ih,"MASKFLOAT", lin, col, "%f:%f", min, max);
++ IupMatSetfAttribute(ih,"MASKFLOAT", lin, col, "%g:%g", min, max);
+ return 0;
+ }
+ 
+diff --git a/iup/srccontrols/iup_oldtabs.c b/iup/srccontrols/iup_oldtabs.c
+index 43b0c57..5ea7f0a 100755
+--- a/iup/srccontrols/iup_oldtabs.c
++++ b/iup/srccontrols/iup_oldtabs.c
+@@ -2487,10 +2487,16 @@ static int iTabsMapMethod(Ihandle* ih)
+ static void iTabsUnMapMethod(Ihandle* ih)
+ {
+ if (ih->data->cddbuffer)
++ {
+ cdKillCanvas(ih->data->cddbuffer);
++ ih->data->cddbuffer = NULL;
++ }
+ 
+ if (ih->data->cdcanvas)
++ {
+ cdKillCanvas(ih->data->cdcanvas);
++ ih->data->cdcanvas = NULL;
++ }
+ }
+ 
+ static void iTabsDestroyMethod(Ihandle* ih)
+diff --git a/iup/srccontrols/iup_oldval.c b/iup/srccontrols/iup_oldval.c
+index 50dae8a..9c14c90 100755
+--- a/iup/srccontrols/iup_oldval.c
++++ b/iup/srccontrols/iup_oldval.c
+@@ -533,7 +533,7 @@ static char* iValGetTypeAttrib(Ihandle* ih)
+ static char* iValGetValueAttrib(Ihandle* ih)
+ {
+ char* str = iupStrGetMemory(20);
+- sprintf(str, "%f", ih->data->val);
++ sprintf(str, "%g", ih->data->val);
+ return str;
+ }
+ 
+@@ -576,7 +576,7 @@ static int iValSetStepAttrib(Ihandle* ih, const char* step)
+ static char* iValGetStepAttrib(Ihandle* ih)
+ {
+ char* str = iupStrGetMemory(20);
+- sprintf(str, "%f", ih->data->step);
++ sprintf(str, "%g", ih->data->step);
+ return str;
+ }
+ 
+@@ -590,7 +590,7 @@ static int iValSetPageStepAttrib(Ihandle* ih, const char* pagestep)
+ static char* iValGetPageStepAttrib(Ihandle* ih)
+ {
+ char* str = iupStrGetMemory(20);
+- sprintf(str, "%f", ih->data->pagestep);
++ sprintf(str, "%g", ih->data->pagestep);
+ return str;
+ }
+ 
+@@ -605,7 +605,7 @@ static int iValSetMaxAttrib(Ihandle* ih, const char* max)
+ static char* iValGetMaxAttrib(Ihandle* ih)
+ {
+ char* str = iupStrGetMemory(20);
+- sprintf(str, "%f", ih->data->vmax);
++ sprintf(str, "%g", ih->data->vmax);
+ return str;
+ }
+ 
+@@ -620,7 +620,7 @@ static int iValSetMinAttrib(Ihandle* ih, const char* min)
+ static char* iValGetMinAttrib(Ihandle* ih)
+ {
+ char* str = iupStrGetMemory(20);
+- sprintf(str, "%f", ih->data->vmin);
++ sprintf(str, "%g", ih->data->vmin);
+ return str;
+ }
+ 
+@@ -719,10 +719,16 @@ static int iValMapMethod(Ihandle* ih)
+ static void iValUnMapMethod(Ihandle* ih)
+ {
+ if (ih->data->cddbuffer)
++ {
+ cdKillCanvas(ih->data->cddbuffer);
++ ih->data->cddbuffer = NULL;
++ }
+ 
+ if (ih->data->cdcanvas)
++ {
+ cdKillCanvas(ih->data->cdcanvas);
++ ih->data->cdcanvas = NULL;
++ }
+ }
+ 
+ static void iValDestroyMethod(Ihandle* ih)
+diff --git a/iup/srccontrols/matrix/iupmat_aux.c b/iup/srccontrols/matrix/iupmat_aux.c
+index f8b85bb..1a8df57 100755
+--- a/iup/srccontrols/matrix/iupmat_aux.c
++++ b/iup/srccontrols/matrix/iupmat_aux.c
+@@ -24,16 +24,11 @@
+ #include "iupmat_getset.h"
+ 
+ 
+-static int iMatrixAuxIsFullVisibleLast(Ihandle* ih, int m)
++int iupMatrixAuxIsFullVisibleLast(ImatLinColData *p)
+ {
+ int i, sum = 0;
+- ImatLinColData *p;
+-
+- if (m == IMAT_PROCESS_LIN)
+- p = &(ih->data->lines);
+- else
+- p = &(ih->data->columns);
+ 
++ sum -= p->first_offset;
+ for(i = p->first; i <= p->last; i++)
+ sum += p->sizes[i];
+ 
+@@ -43,16 +38,20 @@ static int iMatrixAuxIsFullVisibleLast(Ihandle* ih, int m)
+ return 1;
+ }
+ 
+-int iupMatrixAuxIsCellFullVisible(Ihandle* ih, int lin, int col)
++int iupMatrixAuxIsCellStartVisible(Ihandle* ih, int lin, int col)
+ {
+ if(((lin >= ih->data->lines.first) &&
+ (lin <= ih->data->lines.last) &&
+ (col >= ih->data->columns.first) &&
+ (col <= ih->data->columns.last)))
+ {
+- if (col == ih->data->columns.last && !iMatrixAuxIsFullVisibleLast(ih, IMAT_PROCESS_COL))
++ if (col == ih->data->columns.first && ih->data->columns.first_offset!=0)
++ return 0;
++ if (lin == ih->data->lines.first && ih->data->lines.first_offset!=0)
+ return 0;
+- if (lin == ih->data->lines.last && !iMatrixAuxIsFullVisibleLast(ih, IMAT_PROCESS_LIN))
++ if (col == ih->data->columns.last && !iupMatrixAuxIsFullVisibleLast(&ih->data->columns))
++ return 0;
++ if (lin == ih->data->lines.last && !iupMatrixAuxIsFullVisibleLast(&ih->data->lines))
+ return 0;
+ 
+ return 1;
+@@ -81,18 +80,98 @@ void iupMatrixAuxGetVisibleCellDim(Ihandle* ih, int lin, int col, int* x, int* y
+ /* find the position where the column starts */
+ *x = ih->data->columns.sizes[0];
+ for(i = ih->data->columns.first; i < col; i++)
++ {
+ *x += ih->data->columns.sizes[i];
+ 
+- /* find the column size */
++ if (i == ih->data->columns.first)
++ *x -= ih->data->columns.first_offset;
++ }
++
++ /* get the column size */
+ *w = ih->data->columns.sizes[col] - 1;
++ if (col == ih->data->columns.first)
++ *w -= ih->data->columns.first_offset;
+ 
+ /* find the position where the line starts */
+ *y = ih->data->lines.sizes[0];
+ for(i = ih->data->lines.first; i < lin; i++)
++ {
+ *y += ih->data->lines.sizes[i];
+ 
+- /* find the line size */
++ if (i == ih->data->lines.first)
++ *y -= ih->data->lines.first_offset;
++ }
++
++ /* get the line size */
+ *h = ih->data->lines.sizes[lin] - 1;
++ if (lin == ih->data->lines.first)
++ *h -= ih->data->lines.first_offset;
++}
++
++void iupMatrixAuxAdjustFirstFromLast(ImatLinColData* p)
++{
++ int i, sum = 0;
++
++ /* adjust "first" according to "last" */
++
++ i = p->last;
++ sum = p->sizes[i];
++ while (i>1 && sum < p->visible_size)
++ {
++ i--;
++ sum += p->sizes[i];
++ }
++
++ if (i==1 && sum < p->visible_size)
++ {
++ /* if there are room for everyone then position at start */
++ p->first = 1;
++ p->first_offset = 0;
++ }
++ else
++ {
++ /* the "while" found an index for first */
++ p->first = i;
++
++ /* position at the remaing space */
++ p->first_offset = sum - p->visible_size;
++ }
++}
++
++void iupMatrixAuxAdjustFirstFromScrollPos(ImatLinColData* p, int scroll_pos)
++{
++ int index, sp, offset = 0;
++
++ sp = 0;
++ for(index = 1; index < p->num; index++)
++ {
++ sp += p->sizes[index];
++ if (sp > scroll_pos)
++ {
++ sp -= p->sizes[index]; /* get the previous value */
++ offset = scroll_pos - sp;
++ break;
++ }
++ }
++
++ if (index == p->num)
++ {
++ if (p->num == 1)
++ {
++ /* did NOT go trough the "for" above */
++ offset = scroll_pos;
++ index = 1;
++ }
++ else
++ {
++ /* go all the way trough the "for" above, but still sp < scroll_pos */
++ offset = scroll_pos - sp;
++ index = p->num-1;
++ }
++ }
++
++ p->first = index;
++ p->first_offset = offset;
+ }
+ 
+ /* Calculate the size, in pixels, of the invisible columns/lines,
+@@ -101,10 +180,11 @@ void iupMatrixAuxGetVisibleCellDim(Ihandle* ih, int lin, int col, int* x, int* y
+ Depends on the first visible column/line.
+ -> m : choose will operate on lines or columns [IMAT_PROCESS_LIN|IMAT_PROCESS_COL]
+ */
+-void iupMatrixAuxUpdateVisiblePos(Ihandle* ih, int m)
++void iupMatrixAuxUpdateScrollPos(Ihandle* ih, int m)
+ {
++ float pos;
++ int i, sb, scroll_pos;
+ char* POS;
+- int i, sb, visible_pos;
+ ImatLinColData *p;
+ 
+ if (m == IMAT_PROCESS_LIN)
+@@ -120,33 +200,44 @@ void iupMatrixAuxUpdateVisiblePos(Ihandle* ih, int m)
+ POS = "POSX";
+ }
+ 
+- visible_pos = 0;
+- for(i = 1; i < p->first; i++)
+- visible_pos += p->sizes[i];
++ /* "first" was changed, so update "last" and the scroll pos */
+ 
+- if (ih->data->canvas.sb & sb)
++ if (p->total_size <= p->visible_size)
+ {
+- float pos;
++ /* the matrix is fully visible */
++ p->first = 1;
++ p->first_offset = 0;
++ p->last = p->num==1? 1: p->num-1;
+ 
+- if (p->total_size)
+- {
+- while ((visible_pos + p->visible_size > p->total_size) && p->first>1)
+- {
+- /* invalid position, must recalculate first */
+- p->first--;
+- visible_pos -= p->sizes[p->first];
+- }
++ if (ih->data->canvas.sb & sb)
++ IupSetAttribute(ih, POS, "0");
+ 
+- pos = (float)visible_pos/(float)p->total_size;
+- }
+- else
+- pos = 0;
++ return;
++ }
++
++ /* must check if it is a valid position */
++ scroll_pos = 0;
++ for(i = 1; i < p->first; i++)
++ scroll_pos += p->sizes[i];
++ scroll_pos += p->first_offset;
++
++ if (scroll_pos + p->visible_size > p->total_size)
++ {
++ /* invalid condition, must recalculate so it is valid */
++ scroll_pos = p->total_size - p->visible_size;
+ 
+- iupMatrixAuxUpdateLast(p);
+- IupSetfAttribute(ih, POS, "%.5f", (double)pos);
++ /* position first and first_offset, according to scroll pos */
++ iupMatrixAuxAdjustFirstFromScrollPos(p, scroll_pos);
+ }
+- else
+- iupMatrixAuxUpdateLast(p);
++
++ pos = (float)scroll_pos/(float)p->total_size;
++
++ /* update last */
++ iupMatrixAuxUpdateLast(p);
++
++ /* update scroll pos */
++ if (ih->data->canvas.sb & sb)
++ IupSetfAttribute(ih, POS, "%g", (double)pos);
+ }
+ 
+ /* Calculate which is the last visible column/line of the matrix. 
+@@ -157,18 +248,24 @@ void iupMatrixAuxUpdateLast(ImatLinColData *p)
+ 
+ if (p->visible_size > 0)
+ {
+- /* Find which is the last column/line
++ /* Find which is the last column/line.
+ Start in the first visible and continue adding the widths
+- up to the visible size */
++ up to the visible size */
++ sum -= p->first_offset;
+ for(i = p->first; i < p->num; i++)
+ {
+- sum += p->sizes[i];
++ sum += p->sizes[i];
+ if(sum >= p->visible_size)
+ break;
+ }
+ 
+ if (i == p->num)
+- p->last = i-1;
++ {
++ if (p->num == 1)
++ p->last = 1;
++ else
++ p->last = p->num-1;
++ }
+ else
+ p->last = i;
+ }
+@@ -185,7 +282,7 @@ int iupMatrixAuxGetColumnWidth(Ihandle* ih, int col)
+ char* str = iupStrGetMemory(100);
+ char* value;
+ 
+- /* can only be called for valid columns */
++ /* can be called for invalid columns (col>numcol) */
+ 
+ sprintf(str, "WIDTH%d", col);
+ value = iupAttribGet(ih, str);
+@@ -219,7 +316,7 @@ int iupMatrixAuxGetColumnWidth(Ihandle* ih, int col)
+ width = max_width;
+ }
+ }
+- else if (ih->data->use_title_size)
++ else if (ih->data->use_title_size && (col>=0 && col<ih->data->columns.num))
+ {
+ char* title_value = iupMatrixCellGetValue(ih, 0, col);
+ if (title_value)
+@@ -257,7 +354,7 @@ int iupMatrixAuxGetLineHeight(Ihandle* ih, int lin)
+ char* str = iupStrGetMemory(100);
+ char* value;
+ 
+- /* can only be called for valid lines */
++ /* can be called for invalid lines (lin>numlin) */
+ 
+ sprintf(str, "HEIGHT%d", lin);
+ value = iupAttribGet(ih, str);
+@@ -291,7 +388,7 @@ int iupMatrixAuxGetLineHeight(Ihandle* ih, int lin)
+ height = max_height;
+ }
+ }
+- else if (ih->data->use_title_size)
++ else if (ih->data->use_title_size && (lin>=0 && lin<ih->data->lines.num))
+ {
+ char* title_value = iupMatrixCellGetValue(ih, lin, 0);
+ if (title_value && title_value[0])
+@@ -374,7 +471,7 @@ static void iMatrixAuxUpdateVisibleSize(Ihandle* ih, int m)
+ p->visible_size = p->total_size;
+ 
+ if (p->total_size)
+- IupSetfAttribute(ih, D, "%f", (double)p->visible_size/(double)p->total_size);
++ IupSetfAttribute(ih, D, "%g", (double)p->visible_size/(double)p->total_size);
+ else
+ IupSetAttribute(ih, D, "1.0");
+ }
+@@ -390,6 +487,7 @@ void iupMatrixAuxCalcSizes(Ihandle* ih)
+ /* when removing lines the first can be positioned after the last line */
+ if (ih->data->lines.first > ih->data->lines.num-1) 
+ {
++ ih->data->lines.first_offset = 0;
+ if (ih->data->lines.num==1)
+ ih->data->lines.first = 1;
+ else
+@@ -397,46 +495,50 @@ void iupMatrixAuxCalcSizes(Ihandle* ih)
+ }
+ if (ih->data->columns.first > ih->data->columns.num-1) 
+ {
++ ih->data->columns.first_offset = 0;
+ if (ih->data->columns.num == 1)
+ ih->data->columns.first = 1;
+ else
+ ih->data->columns.first = ih->data->columns.num-1;
+ }
+ 
+- iupMatrixAuxUpdateVisiblePos(ih, IMAT_PROCESS_COL);
+- iupMatrixAuxUpdateVisiblePos(ih, IMAT_PROCESS_LIN);
++ /* make sure scroll pos is consistent */
++ iupMatrixAuxUpdateScrollPos(ih, IMAT_PROCESS_COL);
++ iupMatrixAuxUpdateScrollPos(ih, IMAT_PROCESS_LIN);
+ 
+ ih->data->need_calcsize = 0;
+ }
+ 
+ int iupMatrixAuxGetLinColFromXY(Ihandle* ih, int x, int y, int* l, int* c)
+ {
+- int size, lin, col;
++ int x_col, y_col, lin, col;
+ 
+- size = ih->data->columns.sizes[0]; /* always visible when non zero */
+- if (x < size)
++ x_col = ih->data->columns.sizes[0]; /* always visible when non zero */
++ if (x < x_col)
+ col = 0; /* It is in the column of titles */
+ else
+ {
++ x_col -= ih->data->columns.first_offset;
+ for(col = ih->data->columns.first; col <= ih->data->columns.last; col++) /* for all visible columns */
+ {
+- size += ih->data->columns.sizes[col];
+- if (x < size)
++ x_col += ih->data->columns.sizes[col];
++ if (x < x_col)
+ break;
+ }
+ if (col > ih->data->columns.last)
+ col = -1;
+ }
+ 
+- size = ih->data->lines.sizes[0]; /* always visible when non zero */
+- if (y < size)
++ y_col = ih->data->lines.sizes[0]; /* always visible when non zero */
++ if (y < y_col)
+ lin = 0; /* It is in the line of titles */
+ else
+ {
++ y_col -= ih->data->lines.first_offset;
+ for(lin = ih->data->lines.first; lin <= ih->data->lines.last; lin++) /* for all visible lines */
+ {
+- size += ih->data->lines.sizes[lin];
+- if (y < size)
++ y_col += ih->data->lines.sizes[lin];
++ if (y < y_col)
+ break;
+ }
+ if(lin > ih->data->lines.last)
+diff --git a/iup/srccontrols/matrix/iupmat_aux.h b/iup/srccontrols/matrix/iupmat_aux.h
+index 296c1f5..01c77f1 100755
+--- a/iup/srccontrols/matrix/iupmat_aux.h
++++ b/iup/srccontrols/matrix/iupmat_aux.h
+@@ -12,19 +12,22 @@
+ extern "C" {
+ #endif
+ 
+-int iupMatrixAuxIsCellFullVisible(Ihandle* ih, int lin, int col);
++int iupMatrixAuxIsFullVisibleLast(ImatLinColData *p);
++int iupMatrixAuxIsCellStartVisible(Ihandle* ih, int lin, int col);
+ int iupMatrixAuxIsCellVisible(Ihandle* ih, int lin, int col);
+ void iupMatrixAuxGetVisibleCellDim (Ihandle* ih, int lin, int col, int* x, int* y, int* w, int* h);
+ 
+ void iupMatrixAuxCalcSizes(Ihandle* ih);
+ 
+-void iupMatrixAuxUpdateVisiblePos(Ihandle* ih, int m);
++void iupMatrixAuxAdjustFirstFromLast(ImatLinColData* p);
++void iupMatrixAuxAdjustFirstFromScrollPos(ImatLinColData* p, int scroll_pos);
++void iupMatrixAuxUpdateScrollPos(Ihandle* ih, int m);
+ void iupMatrixAuxUpdateLast(ImatLinColData *p);
+ 
+ int iupMatrixAuxGetColumnWidth(Ihandle* ih, int col);
+ int iupMatrixAuxGetLineHeight (Ihandle* ih, int lin);
+ 
+-int iupMatrixAuxGetLinColFromXY (Ihandle* ih, int x, int y, int* l, int* c);
++int iupMatrixAuxGetLinColFromXY (Ihandle* ih, int x, int y, int* l, int* c);
+ 
+ int iupMatrixAuxCallLeaveCellCb (Ihandle* ih);
+ void iupMatrixAuxCallEnterCellCb (Ihandle* ih);
+diff --git a/iup/srccontrols/matrix/iupmat_cd.h b/iup/srccontrols/matrix/iupmat_cd.h
+index 1a10f2b..beb616a 100755
+--- a/iup/srccontrols/matrix/iupmat_cd.h
++++ b/iup/srccontrols/matrix/iupmat_cd.h
+@@ -11,12 +11,12 @@
+ extern "C" {
+ #endif
+ 
+-#define IUPMAT_LINE(_ih,_x1,_y1,_x2,_y2) cdCanvasLine((_ih)->data->cddbuffer, (_x1), iupMatrixInvertYAxis(_ih, _y1), (_x2), iupMatrixInvertYAxis(_ih, _y2))
+-#define IUPMAT_VERTEX(_ih,_x,_y) cdCanvasVertex((_ih)->data->cddbuffer, (_x), iupMatrixInvertYAxis(_ih, _y))
+-#define IUPMAT_BOX(_ih,_xmin,_xmax,_ymin,_ymax) cdCanvasBox((_ih)->data->cddbuffer, (_xmin), (_xmax), iupMatrixInvertYAxis(_ih, _ymin), iupMatrixInvertYAxis(_ih, _ymax))
+-#define IUPMAT_RECT(_ih,_xmin,_xmax,_ymin,_ymax) cdCanvasRect((_ih)->data->cddbuffer, (_xmin), (_xmax), iupMatrixInvertYAxis(_ih, _ymin), iupMatrixInvertYAxis(_ih, _ymax))
+-#define IUPMAT_CLIPAREA(_ih,_xmin,_xmax,_ymin,_ymax) cdCanvasClipArea((_ih)->data->cddbuffer, (_xmin), (_xmax), iupMatrixInvertYAxis(_ih, _ymin), iupMatrixInvertYAxis(_ih, _ymax))
+-#define IUPMAT_TEXT(_ih,_x,_y,_text) cdCanvasText((_ih)->data->cddbuffer, (_x), iupMatrixInvertYAxis(_ih, _y), (_text))
++#define iupMATRIX_LINE(_ih,_x1,_y1,_x2,_y2) cdCanvasLine((_ih)->data->cddbuffer, (_x1), iupMATRIX_INVERTYAXIS(_ih, _y1), (_x2), iupMATRIX_INVERTYAXIS(_ih, _y2))
++#define iupMATRIX_VERTEX(_ih,_x,_y) cdCanvasVertex((_ih)->data->cddbuffer, (_x), iupMATRIX_INVERTYAXIS(_ih, _y))
++#define iupMATRIX_BOX(_ih,_xmin,_xmax,_ymin,_ymax) cdCanvasBox((_ih)->data->cddbuffer, (_xmin), (_xmax), iupMATRIX_INVERTYAXIS(_ih, _ymin), iupMATRIX_INVERTYAXIS(_ih, _ymax))
++#define iupMATRIX_RECT(_ih,_xmin,_xmax,_ymin,_ymax) cdCanvasRect((_ih)->data->cddbuffer, (_xmin), (_xmax), iupMATRIX_INVERTYAXIS(_ih, _ymin), iupMATRIX_INVERTYAXIS(_ih, _ymax))
++#define iupMATRIX_CLIPAREA(_ih,_xmin,_xmax,_ymin,_ymax) cdCanvasClipArea((_ih)->data->cddbuffer, (_xmin), (_xmax), iupMATRIX_INVERTYAXIS(_ih, _ymin), iupMATRIX_INVERTYAXIS(_ih, _ymax))
++#define iupMATRIX_TEXT(_ih,_x,_y,_text) cdCanvasText((_ih)->data->cddbuffer, (_x), iupMATRIX_INVERTYAXIS(_ih, _y), (_text))
+ 
+ #ifdef __cplusplus
+ }
+diff --git a/iup/srccontrols/matrix/iupmat_colres.c b/iup/srccontrols/matrix/iupmat_colres.c
+index d44b7df..79f389e 100755
+--- a/iup/srccontrols/matrix/iupmat_colres.c
++++ b/iup/srccontrols/matrix/iupmat_colres.c
+@@ -34,15 +34,17 @@
+ if so the resize is started */
+ int iupMatrixColResStart(Ihandle* ih, int x, int y)
+ {
+- if (ih->data->lines.sizes[0] && y < ih->data->lines.sizes[0] && iupAttribGetBoolean(ih, "RESIZEMATRIX"))
++ if (ih->data->lines.sizes[0] && 
++ y < ih->data->lines.sizes[0] && 
++ iupAttribGetBoolean(ih, "RESIZEMATRIX"))
+ {
+- int size, col;
++ int x_col, col;
+ 
+ /* Check if is the column of titles */
+- size = ih->data->columns.sizes[0];
+- if (abs(size-x) < IMAT_COLRES_TOL)
++ x_col = ih->data->columns.sizes[0];
++ if (abs(x_col-x) < IMAT_COLRES_TOL)
+ {
+- ih->data->colres_drag_col_start_x = 0;
++ ih->data->colres_drag_col_start_x = x;
+ ih->data->colres_dragging = 1;
+ ih->data->colres_drag_col_last_x = -1;
+ ih->data->colres_drag_col = 0;
+@@ -51,12 +53,13 @@ int iupMatrixColResStart(Ihandle* ih, int x, int y)
+ else
+ {
+ /* find the column */
++ x_col -= ih->data->columns.first_offset;
+ for(col = ih->data->columns.first; col <= ih->data->columns.last; col++)
+ {
+- ih->data->colres_drag_col_start_x = size;
+- size += ih->data->columns.sizes[col];
+- if (abs(size-x) < IMAT_COLRES_TOL)
++ x_col += ih->data->columns.sizes[col];
++ if (abs(x_col-x) < IMAT_COLRES_TOL)
+ {
++ ih->data->colres_drag_col_start_x = x;
+ ih->data->colres_dragging = 1;
+ ih->data->colres_drag_col_last_x = -1;
+ ih->data->colres_drag_col = col;
+@@ -71,7 +74,8 @@ int iupMatrixColResStart(Ihandle* ih, int x, int y)
+ void iupMatrixColResFinish(Ihandle* ih, int x)
+ {
+ char str[100];
+- int width = x - ih->data->colres_drag_col_start_x;
++ int delta = x - ih->data->colres_drag_col_start_x;
++ int width = ih->data->columns.sizes[ih->data->colres_drag_col] + delta;
+ if (width < 0)
+ width = 0;
+ 
+@@ -83,8 +87,8 @@ void iupMatrixColResFinish(Ihandle* ih, int x)
+ 
+ cdCanvasWriteMode(ih->data->cdcanvas, CD_XOR);
+ cdCanvasForeground(ih->data->cdcanvas, IMAT_RESIZE_COLOR); 
+- cdCanvasLine(ih->data->cdcanvas, ih->data->colres_drag_col_last_x, iupMatrixInvertYAxis(ih, y1), 
+- ih->data->colres_drag_col_last_x, iupMatrixInvertYAxis(ih, y2));
++ cdCanvasLine(ih->data->cdcanvas, ih->data->colres_drag_col_last_x, iupMATRIX_INVERTYAXIS(ih, y1), 
++ ih->data->colres_drag_col_last_x, iupMATRIX_INVERTYAXIS(ih, y2));
+ cdCanvasWriteMode(ih->data->cdcanvas, CD_REPLACE);
+ }
+ 
+@@ -106,7 +110,8 @@ void iupMatrixColResMove(Ihandle* ih, int x)
+ {
+ int y1, y2;
+ 
+- int width = x - ih->data->colres_drag_col_start_x;
++ int delta = x - ih->data->colres_drag_col_start_x;
++ int width = ih->data->columns.sizes[ih->data->colres_drag_col] + delta;
+ if (width < 0)
+ return;
+ 
+@@ -119,12 +124,12 @@ void iupMatrixColResMove(Ihandle* ih, int x)
+ /* If it is not the first time, move old line */
+ if (ih->data->colres_drag_col_last_x != -1)
+ {
+- cdCanvasLine(ih->data->cdcanvas, ih->data->colres_drag_col_last_x, iupMatrixInvertYAxis(ih, y1), 
+- ih->data->colres_drag_col_last_x, iupMatrixInvertYAxis(ih, y2));
++ cdCanvasLine(ih->data->cdcanvas, ih->data->colres_drag_col_last_x, iupMATRIX_INVERTYAXIS(ih, y1), 
++ ih->data->colres_drag_col_last_x, iupMATRIX_INVERTYAXIS(ih, y2));
+ }
+ 
+- cdCanvasLine(ih->data->cdcanvas, x, iupMatrixInvertYAxis(ih, y1), 
+- x, iupMatrixInvertYAxis(ih, y2));
++ cdCanvasLine(ih->data->cdcanvas, x, iupMATRIX_INVERTYAXIS(ih, y1), 
++ x, iupMATRIX_INVERTYAXIS(ih, y2));
+ 
+ ih->data->colres_drag_col_last_x = x;
+ cdCanvasWriteMode(ih->data->cdcanvas, CD_REPLACE);
+@@ -144,20 +149,23 @@ static void iMatrixColResResetMatrixCursor(Ihandle* ih)
+ /* Change the cursor when it passes over a group of the column titles. */
+ void iupMatrixColResCheckChangeCursor(Ihandle* ih, int x, int y)
+ {
+- if(ih->data->lines.sizes[0] && y < ih->data->lines.sizes[0] && iupAttribGetBoolean(ih, "RESIZEMATRIX"))
++ if(ih->data->lines.sizes[0] && 
++ y < ih->data->lines.sizes[0] && 
++ iupAttribGetBoolean(ih, "RESIZEMATRIX"))
+ {
+ /* It is in the column titles area and the resize mode is on */
+- int found = 0, size, col;
++ int found = 0, x_col, col;
+ 
+- size = ih->data->columns.sizes[0];
+- if (abs(size - x) < IMAT_COLRES_TOL)
++ x_col = ih->data->columns.sizes[0];
++ if (abs(x_col - x) < IMAT_COLRES_TOL)
+ found = 1; /* line titles */
+ else
+ {
++ x_col -= ih->data->columns.first_offset;
+ for(col = ih->data->columns.first; col <= ih->data->columns.last && !found; col++)
+ {
+- size += ih->data->columns.sizes[col];
+- if(abs(size - x) < IMAT_COLRES_TOL)
++ x_col += ih->data->columns.sizes[col];
++ if(abs(x_col - x) < IMAT_COLRES_TOL)
+ found = 1;
+ }
+ }
+@@ -168,7 +176,7 @@ void iupMatrixColResCheckChangeCursor(Ihandle* ih, int x, int y)
+ iupAttribStoreStr(ih, "_IUPMAT_CURSOR", IupGetAttribute(ih, "CURSOR"));
+ IupSetAttribute(ih, "CURSOR", "RESIZE_W");
+ }
+- else /* It is in the empty area after the last column */
++ else /* It is in the empty area after the last column, or inside a cell */
+ iMatrixColResResetMatrixCursor(ih); 
+ }
+ else
+diff --git a/iup/srccontrols/matrix/iupmat_def.h b/iup/srccontrols/matrix/iupmat_def.h
+index d45acde..225cc16 100755
+--- a/iup/srccontrols/matrix/iupmat_def.h
++++ b/iup/srccontrols/matrix/iupmat_def.h
+@@ -49,6 +49,7 @@ typedef struct _ImatLinColData
+ int num; /* Number of columns/lines in the matrix, default/minimum=1, always includes the title */
+ int num_alloc; /* Number of columns/lines allocated, default=5 */
+ 
++ int first_offset; /* scroll offset of the first visible column/line from right to left (or the invisible part of the first cell) */
+ int first; /* First visible column/line */
+ int last; /* Last visible column/line */
+ 
+@@ -84,7 +85,7 @@ struct _IcontrolData
+ 
+ /* attributes */
+ int mark_continuous, mark_mode, mark_multiple;
+- int checkframecolor;
++ int checkframecolor, hidden_text_marks;
+ 
+ /* Mouse and Keyboard AUX */
+ int leftpressed; /* left mouse button is pressed */
+@@ -92,8 +93,8 @@ struct _IcontrolData
+ 
+ /* ColRes AUX */
+ int colres_dragging, /* indicates if it is being made a column resize */
+- colres_drag_col, /* column being resized */
+- colres_drag_col_start_x, /* position of the start of the column being resized */
++ colres_drag_col, /* column being resized, handler is at right of the column */
++ colres_drag_col_start_x, /* handler start position */
+ colres_drag_col_last_x; /* previous position */
+ 
+ /* Mark AUX */
+@@ -107,12 +108,14 @@ struct _IcontrolData
+ IFniiIII fgcolor_cb;
+ IFniiIII bgcolor_cb;
+ char *bgcolor, *bgcolor_parent, *fgcolor, *font; /* not need to free */
++
++ int clip_x1, clip_x2, clip_y1, clip_y2; /* aux for cell clipping */
+ };
+ 
+ 
+ int iupMatrixIsValid(Ihandle* ih, int check_cells);
+ 
+-#define iupMatrixInvertYAxis(_ih, _y) ((_ih)->data->h-1 - (_y))
++#define iupMATRIX_INVERTYAXIS(_ih, _y) ((_ih)->data->h-1 - (_y))
+ 
+ 
+ #ifdef __cplusplus
+diff --git a/iup/srccontrols/matrix/iupmat_draw.c b/iup/srccontrols/matrix/iupmat_draw.c
+index 7c53fb5..ec3df59 100755
+--- a/iup/srccontrols/matrix/iupmat_draw.c
++++ b/iup/srccontrols/matrix/iupmat_draw.c
+@@ -47,13 +47,38 @@
+ #define IMAT_COMBOBOX_W 16
+ 
+ 
+-typedef int (*IFniiiiiiC)(Ihandle *h, int lin, int col,int x1, int x2, int y1, int y2, cdCanvas* cnv);
++typedef int (*IFniiiiiiC)(Ihandle *h, int lin, int col, int x1, int x2, int y1, int y2, cdCanvas* cnv);
+ 
+ 
+ /**************************************************************************/
+ /* Private functions */
+ /**************************************************************************/
+ 
++static void iMatrixDrawSetCellClipping(Ihandle* ih, int x1, int x2, int y1, int y2)
++{
++ int old_clip = cdCanvasClip(ih->data->cddbuffer, CD_QUERY);
++ if (old_clip == CD_CLIPAREA)
++ {
++ cdCanvasGetClipArea(ih->data->cddbuffer, &(ih->data->clip_x1), &(ih->data->clip_x2), &(ih->data->clip_y1), &(ih->data->clip_y2));
++ y1 = iupMATRIX_INVERTYAXIS(ih, y1);
++ y2 = iupMATRIX_INVERTYAXIS(ih, y2);
++ if (x1 > x2) {int tmp = x1; x1 = x2; x2 = tmp;}
++ if (y1 > y2) {int tmp = y1; y1 = y2; y2 = tmp;}
++ if (x1 < ih->data->clip_x1) x1 = ih->data->clip_x1;
++ if (x2 > ih->data->clip_x2) x2 = ih->data->clip_x2;
++ if (y1 < ih->data->clip_y1) y1 = ih->data->clip_y1;
++ if (y2 > ih->data->clip_y2) y2 = ih->data->clip_y2;
++ cdCanvasClipArea(ih->data->cddbuffer, x1, x2, y1, y2);
++ cdCanvasClip(ih->data->cddbuffer, CD_CLIPAREA);
++ }
++}
++
++static void iMatrixDrawResetCellClipping(Ihandle* ih)
++{
++ int old_clip = cdCanvasClip(ih->data->cddbuffer, CD_QUERY);
++ if (old_clip == CD_CLIPAREA)
++ cdCanvasClipArea(ih->data->cddbuffer, ih->data->clip_x1, ih->data->clip_x2, ih->data->clip_y1, ih->data->clip_y2);
++}
+ 
+ static int iMatrixDrawGetColAlignment(Ihandle* ih, int col, char* str)
+ {
+@@ -61,6 +86,8 @@ static int iMatrixDrawGetColAlignment(Ihandle* ih, int col, char* str)
+ sprintf(str, "ALIGNMENT%d", col);
+ align = iupAttribGet(ih, str);
+ if (!align)
++ align = iupAttribGet(ih, "ALIGNMENT");
++ if (!align)
+ {
+ if (col == 0)
+ return IMAT_T_LEFT;
+@@ -80,16 +107,15 @@ static int iMatrixDrawCallDrawCB(Ihandle* ih, int lin, int col, int x1, int x2,
+ int ret;
+ cdCanvas* old_cnv;
+ 
+- IUPMAT_CLIPAREA(ih, x1, x2, y1, y2);
+- cdCanvasClip(ih->data->cddbuffer, CD_CLIPAREA);
++ iMatrixDrawSetCellClipping(ih, x1, x2, y1, y2);
+ 
+ old_cnv = cdActiveCanvas();
+ if (old_cnv != ih->data->cddbuffer) /* backward compatibility code */
+ cdActivate(ih->data->cddbuffer);
+ 
+- ret = draw_cb(ih, lin, col, x1, x2, iupMatrixInvertYAxis(ih, y1), iupMatrixInvertYAxis(ih, y2), ih->data->cddbuffer);
++ ret = draw_cb(ih, lin, col, x1, x2, iupMATRIX_INVERTYAXIS(ih, y1), iupMATRIX_INVERTYAXIS(ih, y2), ih->data->cddbuffer);
+ 
+- cdCanvasClip(ih->data->cddbuffer, CD_CLIPOFF);
++ iMatrixDrawResetCellClipping(ih);
+ 
+ if (old_cnv && old_cnv != ih->data->cddbuffer) /* backward compatibility code */
+ {
+@@ -165,28 +191,36 @@ static void iMatrixDrawFrameHorizLineCell(Ihandle* ih, int lin, int col, int x1,
+ {
+ if (ih->data->checkframecolor && (ih->data->callback_mode || ih->data->cells[lin][col].flags & IUPMAT_FRAMEHCOLOR))
+ {
++ char* color;
+ unsigned char r,g,b;
+ sprintf(str, "FRAMEHORIZCOLOR%d:%d", lin, col);
+- if (iupStrToRGB(iupAttribGet(ih, str), &r, &g, &b))
++ color = iupAttribGet(ih, str);
++ if (iupStrEqual(color, "BGCOLOR"))
++ return;
++ if (iupStrToRGB(color, &r, &g, &b))
+ framecolor = cdEncodeColor(r, g, b);
+ }
+ 
+ cdCanvasForeground(ih->data->cddbuffer, framecolor);
+- IUPMAT_LINE(ih, x1, y, x2, y); /* bottom horizontal line */
++ iupMATRIX_LINE(ih, x1, y, x2, y); /* bottom horizontal line */
+ }
+ 
+ static void iMatrixDrawFrameVertLineCell(Ihandle* ih, int lin, int col, int x, int y1, int y2, long framecolor, char* str)
+ {
+ if (ih->data->checkframecolor && (ih->data->callback_mode || ih->data->cells[lin][col].flags & IUPMAT_FRAMEVCOLOR))
+ {
++ char* color;
+ unsigned char r,g,b;
+ sprintf(str, "FRAMEVERTCOLOR%d:%d", lin, col);
+- if (iupStrToRGB(iupAttribGet(ih, str), &r, &g, &b))
++ color = iupAttribGet(ih, str);
++ if (iupStrEqual(color, "BGCOLOR"))
++ return;
++ if (iupStrToRGB(color, &r, &g, &b))
+ framecolor = cdEncodeColor(r, g, b);
+ }
+ 
+ cdCanvasForeground(ih->data->cddbuffer, framecolor);
+- IUPMAT_LINE(ih, x, y1, x, y2); /* right vertical line */
++ iupMATRIX_LINE(ih, x, y1, x, y2); /* right vertical line */
+ }
+ 
+ static void iMatrixDrawFrameRectTitle(Ihandle* ih, int lin, int col, int x1, int x2, int y1, int y2, long framecolor, char* str)
+@@ -195,37 +229,43 @@ static void iMatrixDrawFrameRectTitle(Ihandle* ih, int lin, int col, int x1, int
+ x2 -= IMAT_FRAME_W/2;
+ y2 -= IMAT_FRAME_H/2;
+ 
+- iMatrixDrawFrameVertLineCell(ih, lin, col, x2, y1, y2, framecolor, str); /* right vertical line */
++ /* right vertical line */
++ iMatrixDrawFrameVertLineCell(ih, lin, col, x2, y1, y2, framecolor, str); 
+ if (col==0)
+ {
+- IUPMAT_LINE(ih, x1, y1, x1, y2); /* left vertical line, reuse Foreground */
++ /* left vertical line, reuse Foreground */
++ iupMATRIX_LINE(ih, x1, y1, x1, y2); 
+ x1++;
+ }
+ else if (col==1 && ih->data->columns.sizes[0] == 0)
+ {
+ /* If does not have line titles then draw the left line of the cell frame */
+- IUPMAT_LINE(ih, x1, y1, x1, y2-1);
++ iupMATRIX_LINE(ih, x1, y1, x1, y2-1);
+ x1++;
+ }
+ 
+- cdCanvasForeground(ih->data->cddbuffer, CD_WHITE); /* Titles have a white line near the frame */
+- IUPMAT_LINE(ih, x1, y1+1, x1, y2-1);
++ /* Titles have a white line near the frame, at left */
++ cdCanvasForeground(ih->data->cddbuffer, CD_WHITE); 
++ iupMATRIX_LINE(ih, x1, y1+1, x1, y2-1);
+ 
+- iMatrixDrawFrameHorizLineCell(ih, lin, col, x1, x2, y2, framecolor, str); /* bottom horizontal line */
++ /* bottom horizontal line */
++ iMatrixDrawFrameHorizLineCell(ih, lin, col, x1, x2, y2, framecolor, str); 
+ if (lin==0)
+ {
+- IUPMAT_LINE(ih, x1, y1, x2, y1); /* top horizontal line, reuse Foreground */
++ /* top horizontal line, reuse Foreground */
++ iupMATRIX_LINE(ih, x1, y1, x2, y1); 
+ y1++;
+ }
+ else if (lin==1 && ih->data->lines.sizes[0] == 0)
+ {
+ /* If does not have column titles then draw the top line of the cell frame */
+- IUPMAT_LINE(ih, x1, y1, x2-1, y1);
++ iupMATRIX_LINE(ih, x1, y1, x2-1, y1);
+ y1++;
+ }
+ 
+- cdCanvasForeground(ih->data->cddbuffer, CD_WHITE); /* Titles have a white line near the frame */
+- IUPMAT_LINE(ih, x1, y1, x2-1, y1);
++ /* Titles have a white line near the frame, at top */
++ cdCanvasForeground(ih->data->cddbuffer, CD_WHITE); 
++ iupMATRIX_LINE(ih, x1, y1, x2-1, y1);
+ }
+ 
+ static void iMatrixDrawFrameRectCell(Ihandle* ih, int lin, int col, int x1, int x2, int y1, int y2, long framecolor, char* str)
+@@ -233,20 +273,20 @@ static void iMatrixDrawFrameRectCell(Ihandle* ih, int lin, int col, int x1, int
+ if (col==1 && ih->data->columns.sizes[0] == 0)
+ {
+ /* If does not have line titles then draw the left line of the cell frame */
+- iMatrixDrawFrameVertLineCell(ih, lin, col, x1, y1, y2-1-1, framecolor, str);
++ iMatrixDrawFrameVertLineCell(ih, lin, col, x1, y1, y2-1, framecolor, str);
+ }
+ 
+ if (lin==1 && ih->data->lines.sizes[0] == 0)
+ {
+ /* If does not have column titles then draw the top line of the cell frame */
+- iMatrixDrawFrameHorizLineCell(ih, lin, col, x1, x2-1-1, y1, framecolor, str);
++ iMatrixDrawFrameHorizLineCell(ih, lin, col, x1, x2-1, y1, framecolor, str);
+ }
+ 
+ /* bottom line */
+ iMatrixDrawFrameHorizLineCell(ih, lin, col, x1, x2-1, y2-1, framecolor, str);
+ 
+ /* rigth line */
+- iMatrixDrawFrameVertLineCell(ih, lin, col, x2-1, y1, y2-1, framecolor, str);
++ iMatrixDrawFrameVertLineCell(ih, lin, col, x2-1, y1, y2-2, framecolor, str);
+ }
+ 
+ static int iMatrixDrawSortSign(Ihandle* ih, int x2, int y1, int y2, int col, int active, char* str)
+@@ -274,15 +314,15 @@ static int iMatrixDrawSortSign(Ihandle* ih, int x2, int y1, int y2, int col, int
+ 
+ if (iupStrEqualNoCase(sort, "DOWN"))
+ {
+- IUPMAT_VERTEX(ih, x2 - 5, yc + 2);
+- IUPMAT_VERTEX(ih, x2 - 1, yc - 2);
+- IUPMAT_VERTEX(ih, x2 - 9, yc - 2);
++ iupMATRIX_VERTEX(ih, x2 - 5, yc + 2);
++ iupMATRIX_VERTEX(ih, x2 - 1, yc - 2);
++ iupMATRIX_VERTEX(ih, x2 - 9, yc - 2);
+ }
+ else
+ {
+- IUPMAT_VERTEX(ih, x2 - 1, yc + 2);
+- IUPMAT_VERTEX(ih, x2 - 9, yc + 2);
+- IUPMAT_VERTEX(ih, x2 - 5, yc - 2);
++ iupMATRIX_VERTEX(ih, x2 - 1, yc + 2);
++ iupMATRIX_VERTEX(ih, x2 - 9, yc + 2);
++ iupMATRIX_VERTEX(ih, x2 - 5, yc - 2);
+ }
+ 
+ cdCanvasEnd(ih->data->cddbuffer);
+@@ -301,20 +341,20 @@ static void iMatrixDrawComboFeedback(Ihandle* ih, int x2, int y1, int y2, int ac
+ 
+ /* feedback background */
+ iMatrixDrawSetBgColor(ih, 0, 0, 0, active);
+- IUPMAT_BOX(ih, x1, x2, y1, y2);
++ iupMATRIX_BOX(ih, x1, x2, y1, y2);
+ 
+ /* feedback frame */
+ cdCanvasForeground(ih->data->cddbuffer, framecolor);
+- IUPMAT_RECT(ih, x1, x2, y1, y2);
++ iupMATRIX_RECT(ih, x1, x2, y1, y2);
+ 
+ /* feedback arrow */
+ xh2 = x2 - IMAT_COMBOBOX_W / 2;
+ yh2 = y2 - (y2 - y1) / 2;
+ 
+ cdCanvasBegin(ih->data->cddbuffer, CD_FILL);
+- IUPMAT_VERTEX(ih, xh2, yh2 + 3);
+- IUPMAT_VERTEX(ih, xh2 + 4, yh2 - 1);
+- IUPMAT_VERTEX(ih, xh2 - 4, yh2 - 1);
++ iupMATRIX_VERTEX(ih, xh2, yh2 + 3);
++ iupMATRIX_VERTEX(ih, xh2 + 4, yh2 - 1);
++ iupMATRIX_VERTEX(ih, xh2 - 4, yh2 - 1);
+ cdCanvasEnd(ih->data->cddbuffer);
+ }
+ 
+@@ -325,7 +365,7 @@ static void iMatrixDrawBackground(Ihandle* ih, int x1, int x2, int y1, int y2, i
+ y2 -= IMAT_FRAME_H/2;
+ 
+ iMatrixDrawSetBgColor(ih, lin, col, marked, active);
+- IUPMAT_BOX(ih, x1, x2, y1, y2);
++ iupMATRIX_BOX(ih, x1, x2, y1, y2);
+ }
+ 
+ /* Put the cell contents in the screen, using the specified color and alignment.
+@@ -372,7 +412,7 @@ static void iMatrixDrawCellValue(Ihandle* ih, int x1, int x2, int y1, int y2, in
+ if (text && *text)
+ {
+ int num_line, line_height, total_height;
+- int charheight, ypos;
++ int charheight, ypos, hidden_text_marks = 0;
+ 
+ num_line = iupStrLineCount(text);
+ iupdrvFontGetCharSize(ih, NULL, &charheight);
+@@ -380,12 +420,18 @@ static void iMatrixDrawCellValue(Ihandle* ih, int x1, int x2, int y1, int y2, in
+ line_height = charheight;
+ total_height = (line_height + IMAT_PADDING_H/2) * num_line - IMAT_PADDING_H/2 - IMAT_FRAME_H/2;
+ 
+- if (lin==0)
++ if (lin==0 || ih->data->hidden_text_marks)
+ {
+ int text_w;
+ iupdrvFontGetMultiLineStringSize(ih, text, &text_w, NULL);
+ if (text_w > x2 - x1 + 1 - IMAT_PADDING_W - IMAT_FRAME_W)
+- alignment = IMAT_T_LEFT;
++ {
++ if (lin == 0)
++ alignment = IMAT_T_LEFT;
++
++ if (ih->data->hidden_text_marks)
++ hidden_text_marks = 1;
++ }
+ }
+ 
+ /* Set the color used to draw the text */
+@@ -395,8 +441,13 @@ static void iMatrixDrawCellValue(Ihandle* ih, int x1, int x2, int y1, int y2, in
+ iMatrixDrawSetFgColor(ih, lin, col, marked);
+ 
+ /* Set the clip area to the cell region informed, the text maybe greatter than the cell */
+- IUPMAT_CLIPAREA(ih, x1, x2, y1, y2);
+- cdCanvasClip(ih->data->cddbuffer, CD_CLIPAREA);
++ if (hidden_text_marks)
++ {
++ int crop = iupdrvFontGetStringWidth(ih, "...") + 2;
++ iMatrixDrawSetCellClipping(ih, x1, x2-crop, y1, y2);
++ }
++ else
++ iMatrixDrawSetCellClipping(ih, x1, x2, y1, y2);
+ 
+ cdCanvasNativeFont(ih->data->cddbuffer, iupMatrixGetFont(ih, lin, col));
+ 
+@@ -417,11 +468,11 @@ static void iMatrixDrawCellValue(Ihandle* ih, int x1, int x2, int y1, int y2, in
+ 
+ /* Put the text */
+ if (alignment == IMAT_T_CENTER)
+- IUPMAT_TEXT(ih, (x1 + x2) / 2, ypos, text);
++ iupMATRIX_TEXT(ih, (x1 + x2) / 2, ypos, text);
+ else if(alignment == IMAT_T_LEFT)
+- IUPMAT_TEXT(ih, x1, ypos, text);
++ iupMATRIX_TEXT(ih, x1, ypos, text);
+ else
+- IUPMAT_TEXT(ih, x2, ypos, text);
++ iupMATRIX_TEXT(ih, x2, ypos, text);
+ }
+ else
+ {
+@@ -441,11 +492,11 @@ static void iMatrixDrawCellValue(Ihandle* ih, int x1, int x2, int y1, int y2, in
+ 
+ /* Draw the text */
+ if(alignment == IMAT_T_CENTER)
+- IUPMAT_TEXT(ih, (x1 + x2) / 2, ypos, p);
++ iupMATRIX_TEXT(ih, (x1 + x2) / 2, ypos, p);
+ else if(alignment == IMAT_T_LEFT)
+- IUPMAT_TEXT(ih, x1, ypos, p);
++ iupMATRIX_TEXT(ih, x1, ypos, p);
+ else
+- IUPMAT_TEXT(ih, x2, ypos, p);
++ iupMATRIX_TEXT(ih, x2, ypos, p);
+ 
+ /* Advance the string */
+ if (q) p = q + 1;
+@@ -457,7 +508,15 @@ static void iMatrixDrawCellValue(Ihandle* ih, int x1, int x2, int y1, int y2, in
+ free(newtext);
+ }
+ 
+- cdCanvasClip(ih->data->cddbuffer, CD_CLIPOFF);
++ iMatrixDrawResetCellClipping(ih);
++
++ if (hidden_text_marks)
++ {
++ cdCanvasTextAlignment(ih->data->cddbuffer, CD_EAST);
++ ypos = (int)((y1 + y2) / 2.0 - 0.5);
++ iupMATRIX_TEXT(ih, x2+IMAT_PADDING_W/2, ypos, "...");
++ }
++
+ }
+ }
+ 
+@@ -522,7 +581,7 @@ static void iMatrixDrawFocus(Ihandle* ih)
+ if (ih->data->lines.focus_cell == 1 && ih->data->lines.sizes[0] == 0)
+ y1++;
+ 
+- cdIupDrawFocusRect(ih, ih->data->cdcanvas, x1, iupMatrixInvertYAxis(ih, y1), x2, iupMatrixInvertYAxis(ih, y2));
++ cdIupDrawFocusRect(ih, ih->data->cdcanvas, x1, iupMATRIX_INVERTYAXIS(ih, y1), x2, iupMATRIX_INVERTYAXIS(ih, y2));
+ }
+ 
+ 
+@@ -560,6 +619,11 @@ void iupMatrixDrawLineTitle(Ihandle* ih, int lin1, int lin2)
+ x2 = ih->data->columns.sizes[0];
+ 
+ y1 = ih->data->lines.sizes[0];
++
++ iupMATRIX_CLIPAREA(ih, x1, x2, y1, ih->data->h-1);
++ cdCanvasClip(ih->data->cddbuffer, CD_CLIPAREA);
++
++ y1 -= ih->data->lines.first_offset;
+ for(lin = ih->data->lines.first; lin < lin1; lin++)
+ y1 += ih->data->lines.sizes[lin];
+ 
+@@ -592,6 +656,8 @@ void iupMatrixDrawLineTitle(Ihandle* ih, int lin1, int lin2)
+ 
+ y1 = y2;
+ }
++
++ cdCanvasClip(ih->data->cddbuffer, CD_CLIPOFF);
+ }
+ 
+ /* Draw the column titles, visible, between col and lastcol, include it. 
+@@ -623,6 +689,11 @@ void iupMatrixDrawColumnTitle(Ihandle* ih, int col1, int col2)
+ y2 = ih->data->lines.sizes[0];
+ 
+ x1 = ih->data->columns.sizes[0];
++
++ iupMATRIX_CLIPAREA(ih, x1, ih->data->w-1, y1, y2);
++ cdCanvasClip(ih->data->cddbuffer, CD_CLIPAREA);
++
++ x1 -= ih->data->columns.first_offset;
+ for(col = ih->data->columns.first; col < col1; col++)
+ x1 += ih->data->columns.sizes[col];
+ 
+@@ -657,6 +728,8 @@ void iupMatrixDrawColumnTitle(Ihandle* ih, int col1, int col2)
+ 
+ x1 = x2;
+ }
++
++ cdCanvasClip(ih->data->cddbuffer, CD_CLIPOFF);
+ }
+ 
+ /* Redraw a block of cells of the matrix. Handle marked cells, change
+@@ -673,13 +746,11 @@ void iupMatrixDrawCells(Ihandle* ih, int lin1, int col1, int lin2, int col2)
+ IFnii dropcheck_cb;
+ IFniiiiiiC draw_cb;
+ 
+- x1 = 0;
+ x2 = ih->data->w-1;
+- y1 = 0;
+ y2 = ih->data->h-1;
+ 
+ old_x2 = x2;
+- old_y1 = y1;
++ old_y1 = 0;
+ old_y2 = y2;
+ 
+ if (col1 > ih->data->columns.last ||
+@@ -697,8 +768,14 @@ void iupMatrixDrawCells(Ihandle* ih, int lin1, int col1, int lin2, int col2)
+ if (lin2 > ih->data->lines.last)
+ lin2 = ih->data->lines.last;
+ 
++ x1 = ih->data->columns.sizes[0];
++ y1 = ih->data->lines.sizes[0];
++
++ iupMATRIX_CLIPAREA(ih, x1, x2, y1, y2);
++ cdCanvasClip(ih->data->cddbuffer, CD_CLIPOFF); /* wait for background */
++
+ /* Find the initial position of the first column */
+- x1 += ih->data->columns.sizes[0];
++ x1 -= ih->data->columns.first_offset;
+ for(col = ih->data->columns.first; col < col1; col++)
+ x1 += ih->data->columns.sizes[col];
+ 
+@@ -708,7 +785,7 @@ void iupMatrixDrawCells(Ihandle* ih, int lin1, int col1, int lin2, int col2)
+ x2 += ih->data->columns.sizes[col];
+ 
+ /* Find the initial position of the first line */
+- y1 += ih->data->lines.sizes[0];
++ y1 -= ih->data->lines.first_offset;
+ for(lin = ih->data->lines.first; lin < lin1; lin++)
+ y1 += ih->data->lines.sizes[lin];
+ 
+@@ -724,7 +801,7 @@ void iupMatrixDrawCells(Ihandle* ih, int lin1, int col1, int lin2, int col2)
+ 
+ /* If it was drawn until the last column and remains space in the right of it,
+ then delete this area with the the background color. */
+- IUPMAT_BOX(ih, x2, old_x2, old_y1, old_y2);
++ iupMATRIX_BOX(ih, x2, old_x2, old_y1, old_y2);
+ }
+ 
+ if ((lin2 == ih->data->lines.num-1) && (old_y2 > y2))
+@@ -735,9 +812,12 @@ void iupMatrixDrawCells(Ihandle* ih, int lin1, int col1, int lin2, int col2)
+ 
+ /* If it was drawn until the last line visible and remains space below it,
+ then delete this area with the the background color. */
+- IUPMAT_BOX(ih, 0, old_x2, y2, old_y2);
++ iupMATRIX_BOX(ih, 0, old_x2, y2, old_y2);
+ }
+ 
++ /* after the background */
++ cdCanvasClip(ih->data->cddbuffer, CD_CLIPAREA);
++
+ /***** Draw the cell values and frame */
+ old_y1 = y1;
+ framecolor = cdIupConvertColor(iupAttribGetStr(ih, "FRAMECOLOR"));
+@@ -775,7 +855,7 @@ void iupMatrixDrawCells(Ihandle* ih, int lin1, int col1, int lin2, int col2)
+ 
+ if (dropcheck_cb && dropcheck_cb(ih, lin, col) == IUP_DEFAULT)
+ {
+- drop = IMAT_COMBOBOX_W;
++ drop = IMAT_COMBOBOX_W+IMAT_PADDING_W/2;
+ iMatrixDrawComboFeedback(ih, x2, y1, y2, active, framecolor);
+ }
+ 
+@@ -788,6 +868,8 @@ void iupMatrixDrawCells(Ihandle* ih, int lin1, int col1, int lin2, int col2)
+ x1 = x2;
+ y1 = old_y1; /* must reset also y */
+ }
++
++ cdCanvasClip(ih->data->cddbuffer, CD_CLIPOFF);
+ }
+ 
+ void iupMatrixDraw(Ihandle* ih, int update)
+diff --git a/iup/srccontrols/matrix/iupmat_edit.c b/iup/srccontrols/matrix/iupmat_edit.c
+index a7e0a74..551baed 100755
+--- a/iup/srccontrols/matrix/iupmat_edit.c
++++ b/iup/srccontrols/matrix/iupmat_edit.c
+@@ -67,7 +67,7 @@ static int iMatrixEditDropDownAction_CB(Ihandle* ih, char* t, int i, int v)
+ if (ret == IUP_CONTINUE)
+ {
+ iupMatrixEditHide(ih_matrix);
+- iupMatrixDrawUpdate(ih);
++ iupMatrixDrawUpdate(ih_matrix);
+ }
+ }
+ 
+@@ -137,13 +137,31 @@ static int iMatrixEditCancel(Ihandle* ih, int focus, int update, int ignore)
+ return IUP_DEFAULT;
+ }
+ 
++static int iMatrixEditDropDown_CB(Ihandle* ih, int state)
++{
++ /* In Motif if DROPDOWN=YES then when the dropdown button is clicked 
++ the list looses its focus and when the dropped list is closed 
++ the list regain the focus, also when that happen if the list looses its focus 
++ to another control the kill focus callback is not called. */
++ Ihandle* ih_matrix = ih->parent;
++ if (state == 1)
++ iupAttribSetStr(ih_matrix, "_IUPMAT_DROPDOWN", "1");
++
++ return IUP_DEFAULT;
++}
++
+ static int iMatrixEditKillFocus_CB(Ihandle* ih)
+ {
+ Ihandle* ih_matrix = ih->parent;
+- if (iupStrEqualNoCase(IupGetGlobal("DRIVER"), "Motif"))
++ if (IupGetGlobal("MOTIFVERSION"))
+ {
+- if (iupAttribGet(ih_matrix, "_IUPMAT_DOUBLE_CLICK"))
++ if (iupAttribGet(ih_matrix, "_IUPMAT_DROPDOWN") || /* from iMatrixEditDropDown_CB, in Motif */
++ iupAttribGet(ih_matrix, "_IUPMAT_DOUBLECLICK")) /* from iMatrixMouseLeftPress, in Motif */
++ {
++ iupAttribSetStr(ih_matrix, "_IUPMAT_DOUBLECLICK", NULL);
++ iupAttribSetStr(ih_matrix, "_IUPMAT_DROPDOWN", NULL);
+ return IUP_DEFAULT;
++ }
+ }
+ 
+ iupMatrixEditForceHidden(ih_matrix);
+@@ -200,7 +218,7 @@ int iupMatrixEditShow(Ihandle* ih)
+ 
+ /* position the cell to make it visible */
+ /* If the focus is not visible, a scroll is done for that the focus to be visible */
+- if (!iupMatrixAuxIsCellFullVisible(ih, ih->data->lines.focus_cell, ih->data->columns.focus_cell))
++ if (!iupMatrixAuxIsCellStartVisible(ih, ih->data->lines.focus_cell, ih->data->columns.focus_cell))
+ iupMatrixScrollToVisible(ih, ih->data->lines.focus_cell, ih->data->columns.focus_cell);
+ 
+ /* set attributes */
+@@ -235,7 +253,7 @@ int iupMatrixEditShow(Ihandle* ih)
+ ih->data->datah->y = y;
+ if (IupGetGlobal("GTKVERSION"))
+ {
+- /* In GTK, IupCanvas is not the actual container of the IupText/IupList */
++ /* In GTK, IupCanvas is NOT the actual container of the IupText/IupList */
+ ih->data->datah->x += ih->x;
+ ih->data->datah->y += ih->y;
+ }
+@@ -366,7 +384,7 @@ static int iMatrixEditTextKeyAny_CB(Ihandle* ih, int c)
+ 
+ if (iupMatrixAuxCallLeaveCellCb(ih_matrix) != IUP_IGNORE)
+ {
+- iupMatrixScrollKeyCr(ih_matrix);
++ iupMATRIX_ScrollKeyCr(ih_matrix);
+ iupMatrixAuxCallEnterCellCb(ih_matrix);
+ }
+ iupMatrixDrawUpdate(ih_matrix);
+@@ -399,7 +417,7 @@ static int iMatrixEditDropDownKeyAny_CB(Ihandle* ih, int c)
+ {
+ if (iupMatrixAuxCallLeaveCellCb(ih_matrix) != IUP_IGNORE)
+ {
+- iupMatrixScrollKeyCr(ih_matrix);
++ iupMATRIX_ScrollKeyCr(ih_matrix);
+ iupMatrixAuxCallEnterCellCb(ih_matrix);
+ }
+ iupMatrixDrawUpdate(ih_matrix);
+@@ -440,6 +458,9 @@ void iupMatrixEditCreate(Ihandle* ih)
+ ih->data->droph = IupList(NULL);
+ iupChildTreeAppend(ih, ih->data->droph);
+ 
++ if (IupGetGlobal("MOTIFVERSION"))
++ IupSetCallback(ih->data->droph, "DROPDOWN_CB", (Icallback)iMatrixEditDropDown_CB);
++
+ IupSetCallback(ih->data->droph, "ACTION", (Icallback)iMatrixEditDropDownAction_CB);
+ IupSetCallback(ih->data->droph, "KILLFOCUS_CB", (Icallback)iMatrixEditKillFocus_CB);
+ IupSetCallback(ih->data->droph, "K_ANY", (Icallback)iMatrixEditDropDownKeyAny_CB);
+diff --git a/iup/srccontrols/matrix/iupmat_focus.c b/iup/srccontrols/matrix/iupmat_focus.c
+index 3c000f8..0cf680d 100755
+--- a/iup/srccontrols/matrix/iupmat_focus.c
++++ b/iup/srccontrols/matrix/iupmat_focus.c
+@@ -35,13 +35,11 @@ int iupMatrixFocus_CB(Ihandle* ih, int focus)
+ if (!iupMatrixIsValid(ih, 1))
+ return IUP_DEFAULT;
+ 
+- if (iupStrEqualNoCase(IupGetGlobal("DRIVER"), "Motif"))
++ if (IupGetGlobal("MOTIFVERSION"))
+ {
+- if (focus && iupAttribGet(ih, "_IUPMAT_DOUBLE_CLICK"))
+- {
+- iupAttribSetStr(ih, "_IUPMAT_DOUBLE_CLICK", NULL);
++ if (iupAttribGet(ih, "_IUPMAT_DROPDOWN") || /* from iMatrixEditDropDown_CB, in Motif */
++ iupAttribGet(ih, "_IUPMAT_DOUBLECLICK")) /* from iMatrixMouseLeftPress, in Motif */
+ return IUP_DEFAULT;
+- }
+ }
+ 
+ ih->data->has_focus = focus;
+diff --git a/iup/srccontrols/matrix/iupmat_getset.c b/iup/srccontrols/matrix/iupmat_getset.c
+index 34947b6..4424948 100755
+--- a/iup/srccontrols/matrix/iupmat_getset.c
++++ b/iup/srccontrols/matrix/iupmat_getset.c
+@@ -313,7 +313,7 @@ char* iupMatrixGetFont(Ihandle* ih, int lin, int col)
+ return font;
+ }
+ 
+-char *iupMatrixGetSize(Ihandle* ih, int index, int m, int pixels)
++char *iupMatrixGetSize(Ihandle* ih, int index, int m, int pixels_unit)
+ {
+ char* str;
+ int size;
+@@ -342,7 +342,7 @@ char *iupMatrixGetSize(Ihandle* ih, int index, int m, int pixels)
+ else
+ size -= IMAT_PADDING_H + IMAT_FRAME_H;
+ 
+- if (!pixels)
++ if (!pixels_unit)
+ {
+ int charwidth, charheight;
+ iupdrvFontGetCharSize(ih, &charwidth, &charheight);
+diff --git a/iup/srccontrols/matrix/iupmat_getset.h b/iup/srccontrols/matrix/iupmat_getset.h
+index 9ae3d07..f26e01e 100755
+--- a/iup/srccontrols/matrix/iupmat_getset.h
++++ b/iup/srccontrols/matrix/iupmat_getset.h
+@@ -26,7 +26,7 @@ void iupMatrixGetFgRGB(Ihandle* ih, int lin, int col, unsigned char *r, unsigned
+ 
+ void iupMatrixCellUpdateValue(Ihandle* ih);
+ 
+-char* iupMatrixGetSize(Ihandle* ih, int index, int m, int pixels);
++char* iupMatrixGetSize(Ihandle* ih, int index, int m, int pixels_unit);
+ 
+ int iupMatrixCheckCellPos(Ihandle* ih, int lin, int col);
+ 
+diff --git a/iup/srccontrols/matrix/iupmat_key.c b/iup/srccontrols/matrix/iupmat_key.c
+index ae9ed55..4824438 100755
+--- a/iup/srccontrols/matrix/iupmat_key.c
++++ b/iup/srccontrols/matrix/iupmat_key.c
+@@ -37,7 +37,7 @@ int iupMatrixProcessKeyPress(Ihandle* ih, int c)
+ int ret = IUP_IGNORE; /* default for processed keys */
+ 
+ /* If the focus is not visible, a scroll is done for that the focus to be visible */
+- if (!iupMatrixAuxIsCellFullVisible(ih, ih->data->lines.focus_cell, ih->data->columns.focus_cell))
++ if (!iupMatrixAuxIsCellStartVisible(ih, ih->data->lines.focus_cell, ih->data->columns.focus_cell))
+ iupMatrixScrollToVisible(ih, ih->data->lines.focus_cell, ih->data->columns.focus_cell);
+ 
+ switch (c)
+@@ -47,7 +47,7 @@ int iupMatrixProcessKeyPress(Ihandle* ih, int c)
+ case K_HOME:
+ if(iupMatrixAuxCallLeaveCellCb(ih) == IUP_IGNORE)
+ break;
+- iupMatrixScrollKeyHome(ih);
++ iupMATRIX_ScrollKeyHome(ih);
+ ih->data->homekeycount++;
+ iupMatrixAuxCallEnterCellCb(ih);
+ break;
+@@ -57,7 +57,7 @@ int iupMatrixProcessKeyPress(Ihandle* ih, int c)
+ case K_END:
+ if(iupMatrixAuxCallLeaveCellCb(ih) == IUP_IGNORE)
+ break;
+- iupMatrixScrollKeyEnd(ih);
++ iupMATRIX_ScrollKeyEnd(ih);
+ ih->data->endkeycount++;
+ iupMatrixAuxCallEnterCellCb(ih);
+ break;
+@@ -71,7 +71,7 @@ int iupMatrixProcessKeyPress(Ihandle* ih, int c)
+ case K_LEFT:
+ if (iupMatrixAuxCallLeaveCellCb(ih) == IUP_IGNORE)
+ break;
+- iupMatrixScrollKeyLeft(ih);
++ iupMATRIX_ScrollKeyLeft(ih);
+ iupMatrixAuxCallEnterCellCb(ih);
+ break;
+ 
+@@ -80,7 +80,7 @@ int iupMatrixProcessKeyPress(Ihandle* ih, int c)
+ case K_RIGHT:
+ if(iupMatrixAuxCallLeaveCellCb(ih) == IUP_IGNORE)
+ break;
+- iupMatrixScrollKeyRight(ih);
++ iupMATRIX_ScrollKeyRight(ih);
+ iupMatrixAuxCallEnterCellCb(ih);
+ break;
+ 
+@@ -89,7 +89,7 @@ int iupMatrixProcessKeyPress(Ihandle* ih, int c)
+ case K_UP:
+ if(iupMatrixAuxCallLeaveCellCb(ih) == IUP_IGNORE)
+ break;
+- iupMatrixScrollKeyUp(ih);
++ iupMATRIX_ScrollKeyUp(ih);
+ iupMatrixAuxCallEnterCellCb(ih);
+ break ;
+ 
+@@ -98,7 +98,7 @@ int iupMatrixProcessKeyPress(Ihandle* ih, int c)
+ case K_DOWN:
+ if(iupMatrixAuxCallLeaveCellCb(ih) == IUP_IGNORE)
+ break;
+- iupMatrixScrollKeyDown(ih);
++ iupMATRIX_ScrollKeyDown(ih);
+ iupMatrixAuxCallEnterCellCb(ih);
+ break;
+ 
+@@ -106,7 +106,7 @@ int iupMatrixProcessKeyPress(Ihandle* ih, int c)
+ case K_PGUP:
+ if(iupMatrixAuxCallLeaveCellCb(ih) == IUP_IGNORE)
+ break;
+- iupMatrixScrollKeyPgUp(ih);
++ iupMATRIX_ScrollKeyPgUp(ih);
+ iupMatrixAuxCallEnterCellCb(ih);
+ break;
+ 
+@@ -114,7 +114,7 @@ int iupMatrixProcessKeyPress(Ihandle* ih, int c)
+ case K_PGDN:
+ if(iupMatrixAuxCallLeaveCellCb(ih) == IUP_IGNORE)
+ break;
+- iupMatrixScrollKeyPgDown(ih);
++ iupMATRIX_ScrollKeyPgDown(ih);
+ iupMatrixAuxCallEnterCellCb(ih);
+ break;
+ 
+diff --git a/iup/srccontrols/matrix/iupmat_mouse.c b/iup/srccontrols/matrix/iupmat_mouse.c
+index 33b5fe7..a3ffa82 100755
+--- a/iup/srccontrols/matrix/iupmat_mouse.c
++++ b/iup/srccontrols/matrix/iupmat_mouse.c
+@@ -80,12 +80,18 @@ static void iMatrixMouseLeftPress(Ihandle* ih, int lin, int col, int shift, int
+ 
+ if (iupMatrixEditShow(ih))
+ {
+- if(ih->data->datah == ih->data->droph) 
++ if (ih->data->datah == ih->data->droph)
+ IupSetAttribute(ih->data->datah, "SHOWDROPDOWN", "YES");
+ 
+- if (iupStrEqualNoCase(IupGetGlobal("DRIVER"), "Motif"))
+- if(atoi(IupGetGlobal("MOTIFNUMBER")) < 2203) /* since OpenMotif version 2.2.3 this is not necessary */
+- iupAttribSetStr(ih, "_IUPMAT_DOUBLE_CLICK", "1");
++ if (IupGetGlobal("MOTIFVERSION"))
++ {
++ /* Sequece of focus_cb in Motif from here:
++ Matrix-Focus(0) - ok
++ Edit-KillFocus - weird, must avoid using _IUPMAT_DOUBLECLICK
++ Since OpenMotif version 2.2.3 this is not necessary anymore. */
++ if (atoi(IupGetGlobal("MOTIFNUMBER")) < 2203) 
++ iupAttribSetStr(ih, "_IUPMAT_DOUBLECLICK", "1");
++ }
+ }
+ }
+ else /* single click */
+@@ -182,14 +188,14 @@ int iupMatrixMouseMove_CB(Ihandle* ih, int x, int y)
+ if (ih->data->leftpressed && ih->data->mark_multiple && ih->data->mark_mode != IMAT_MARK_NO)
+ {
+ if ((x < ih->data->columns.sizes[0] || x < IMAT_DRAG_SCROLL_DELTA) && (ih->data->columns.first > 1))
+- iupMatrixScrollLeft(ih);
++ iupMATRIX_ScrollLeft(ih);
+ else if ((x > ih->data->w - IMAT_DRAG_SCROLL_DELTA) && (ih->data->columns.last < ih->data->columns.num-1))
+- iupMatrixScrollRight(ih);
++ iupMATRIX_ScrollRight(ih);
+ 
+ if ((y < ih->data->lines.sizes[0] || y < IMAT_DRAG_SCROLL_DELTA) && (ih->data->lines.first > 1))
+- iupMatrixScrollUp(ih);
++ iupMATRIX_ScrollUp(ih);
+ else if ((y > ih->data->h - IMAT_DRAG_SCROLL_DELTA) && (ih->data->lines.last < ih->data->lines.num-1))
+- iupMatrixScrollDown(ih);
++ iupMATRIX_ScrollDown(ih);
+ 
+ if (iupMatrixAuxGetLinColFromXY(ih, x, y, &lin, &col))
+ {
+diff --git a/iup/srccontrols/matrix/iupmat_numlc.c b/iup/srccontrols/matrix/iupmat_numlc.c
+index e48720a..6e628b7 100755
+--- a/iup/srccontrols/matrix/iupmat_numlc.c
++++ b/iup/srccontrols/matrix/iupmat_numlc.c
+@@ -294,7 +294,7 @@ int iupMatrixSetAddLinAttrib(Ihandle* ih, const char* value)
+ {
+ int base, count, lines_num = ih->data->lines.num;
+ 
+- if (!ih->handle) /* do not store the action before map */
++ if (!ih->handle) /* do not do the action before map */
+ return 0;
+ 
+ if (!iMatrixGetStartEnd(value, &base, &count, lines_num, 0))
+@@ -326,7 +326,7 @@ int iupMatrixSetDelLinAttrib(Ihandle* ih, const char* value)
+ {
+ int base, count, lines_num = ih->data->lines.num;
+ 
+- if (!ih->handle) /* do not store the action before map */
++ if (!ih->handle) /* do not do the action before map */
+ return 0;
+ 
+ if (!iMatrixGetStartEnd(value, &base, &count, lines_num, 1))
+@@ -366,7 +366,7 @@ int iupMatrixSetAddColAttrib(Ihandle* ih, const char* value)
+ {
+ int base, count, columns_num = ih->data->columns.num;
+ 
+- if (!ih->handle) /* do not store the action before map */
++ if (!ih->handle) /* do not do the action before map */
+ return 0;
+ 
+ if (!iMatrixGetStartEnd(value, &base, &count, columns_num, 0))
+@@ -398,7 +398,7 @@ int iupMatrixSetDelColAttrib(Ihandle* ih, const char* value)
+ {
+ int base, count, columns_num = ih->data->columns.num;
+ 
+- if (!ih->handle) /* do not store the action before map */
++ if (!ih->handle) /* do not do the action before map */
+ return 0;
+ 
+ if (!iMatrixGetStartEnd(value, &base, &count, columns_num, 1))
+diff --git a/iup/srccontrols/matrix/iupmat_scroll.c b/iup/srccontrols/matrix/iupmat_scroll.c
+index 24bbef2..845d248 100755
+--- a/iup/srccontrols/matrix/iupmat_scroll.c
++++ b/iup/srccontrols/matrix/iupmat_scroll.c
+@@ -32,54 +32,32 @@
+ /* Private functions */
+ /**************************************************************************/
+ 
+-
+-static int iMatrixScrollIsFullVisibleLast(ImatLinColData *p)
+-{
+- int i, sum = 0;
+-
+- for(i = p->first; i <= p->last; i++)
+- sum += p->sizes[i];
+-
+- if (sum > p->visible_size)
+- return 0;
+- else
+- return 1;
+-}
+-
+-/* Scroll columns/lines in the left/top side of the matriz until the last column/line is FULLY visible.
+- -> m : Define the mode of operation: lines or columns [IMAT_PROCESS_LIN|IMAT_PROCESS_COL] */
+-static void iMatrixScrollToVisible(Ihandle* ih, int m, int index)
++static void iMatrixScrollToVisible(ImatLinColData* p, int index)
+ {
+- ImatLinColData* p;
++ /* The work here is just to position first and first_offset, 
++ so "index" is between "first" and "last". */
++ 
++ /* It is called only for discrete scrolling, 
++ so first_offset usually will be set to 0. */
++
++ /* already visible, change nothing */
++ if (index > p->first && index < p->last)
++ return;
+ 
+- if (m == IMAT_PROCESS_LIN)
+- p = &(ih->data->lines);
+- else
+- p = &(ih->data->columns);
++ /* scroll to visible, means position the cell so the start at left is visible */
+ 
+- if (index < p->first)
++ if (index <= p->first)
+ {
+ p->first = index;
++ p->first_offset = 0;
+ return;
+ }
+- else if (index > p->last)
++ else /* (index >= p->last) */
+ {
+- /* Increment the first column/line until the index is visible */
+- while(index > p->last && p->last != (p->num - 1))
+- {
+- p->first++;
+- iupMatrixAuxUpdateLast(p);
+- } 
+- }
++ p->last = index;
+ 
+- if (index == p->last)
+- {
+- /* must increment util the last is fully visible */
+- while(index == p->last && p->last != (p->num - 1) && !iMatrixScrollIsFullVisibleLast(p))
+- {
+- p->first++;
+- iupMatrixAuxUpdateLast(p);
+- } 
++ /* adjust "first" according to "last" */
++ iupMatrixAuxAdjustFirstFromLast(p);
+ }
+ }
+ 
+@@ -133,119 +111,114 @@ static int iMatrixScrollGetPrevNonEmpty(Ihandle* ih, int m, int index)
+ return index;
+ }
+ 
+-static void iMatrixScrollSetFocusScrollToVisible(Ihandle* ih, int m, int index)
++static void iMatrixScrollSetFocusScrollToVisible(Ihandle* ih, int lin, int col)
++{
++ /* moving focus and eventually scrolling */
++ iupMatrixFocusSet(ih, lin, col);
++
++ /* set for both because focus maybe hidden */
++ iMatrixScrollToVisible(&ih->data->columns, ih->data->columns.focus_cell);
++ iMatrixScrollToVisible(&ih->data->lines, ih->data->lines.focus_cell);
++}
++
++static void iMatrixScrollSetFocusScrollToVisibleLinCol(Ihandle* ih, int m, int index)
+ {
+ if (m == IMAT_PROCESS_COL)
+- iupMatrixFocusSet(ih, ih->data->lines.focus_cell, index);
++ iMatrixScrollSetFocusScrollToVisible(ih, ih->data->lines.focus_cell, index);
+ else
+- iupMatrixFocusSet(ih, index, ih->data->columns.focus_cell);
+-
+- /* set for both because current focus maybe hidden */
+- iMatrixScrollToVisible(ih, IMAT_PROCESS_COL, ih->data->columns.focus_cell);
+- iMatrixScrollToVisible(ih, IMAT_PROCESS_LIN, ih->data->lines.focus_cell);
++ iMatrixScrollSetFocusScrollToVisible(ih, index, ih->data->columns.focus_cell);
+ }
+ 
++
+ /**************************************************************************/
+ /* Exported functions */
+ /**************************************************************************/
+ 
+ 
+-/* Move using the cells of matrix.
+- Receive as a parameter a pointer to a function that will make the work,
+- in fact. This is done to avoid a test to each of the manipulation cursor
+- functions, verifying if it is necessary to call or not the scroll
+- callback. This is only done here.
+- -> func - pointer to the function that will make the movement
+- -> mode - parameter passed to func, specify if the movement request is of
+- the scrollbar or the keyboard
+- -> pos - parameter passed to func, that will be the handle position function
+- of the scrollbar, returning the scrollbar thumb position...
+- if func is other function, this parameter will be ignored
+- -> m - parameter passed to func, specify which is the mode of operation:
+- lines or columns [IMAT_PROCESS_LIN|IMAT_PROCESS_COL]
+-*/
+-void iupMatrixScrollMoveCursor(iupMatrixScrollMoveF func, Ihandle* ih, int mode, float pos, int m)
++void iupMatrixScrollToVisible(Ihandle* ih, int lin, int col)
+ {
+ int old_lines_first = ih->data->lines.first;
+ int old_columns_first = ih->data->columns.first;
++ int old_lines_first_offset = ih->data->lines.first_offset;
++ int old_columns_first_offset = ih->data->columns.first_offset;
+ 
+- iupMatrixEditForceHidden(ih);
++ iMatrixScrollToVisible(&ih->data->columns, col);
++ iMatrixScrollToVisible(&ih->data->lines, lin);
+ 
+- func(ih, mode, pos, m);
+-
+- if (ih->data->lines.first != old_lines_first || ih->data->columns.first != old_columns_first)
++ if ((ih->data->lines.first != old_lines_first || ih->data->lines.first_offset != old_lines_first_offset) ||
++ (ih->data->columns.first != old_columns_first || ih->data->columns.first_offset != old_columns_first_offset))
+ {
+- if (ih->data->columns.first != old_columns_first)
+- iupMatrixAuxUpdateVisiblePos(ih, IMAT_PROCESS_COL);
++ /* when "first" is changed must update scroll pos */
++ if (ih->data->columns.first != old_columns_first || ih->data->columns.first_offset != old_columns_first_offset)
++ iupMatrixAuxUpdateScrollPos(ih, IMAT_PROCESS_COL);
+ 
+- if (ih->data->lines.first != old_lines_first)
+- iupMatrixAuxUpdateVisiblePos(ih, IMAT_PROCESS_LIN);
++ if (ih->data->lines.first != old_lines_first || ih->data->lines.first_offset != old_lines_first_offset)
++ iupMatrixAuxUpdateScrollPos(ih, IMAT_PROCESS_LIN);
+ 
+ iMatrixScrollCallScrollTopCb(ih);
+ 
+- iupMatrixDraw(ih, 0);
++ iupMatrixDraw(ih, 1);
+ }
+ }
+ 
+-void iupMatrixScrollToVisible(Ihandle* ih, int lin, int col)
++void iupMatrixScrollMove(iupMatrixScrollMoveFunc func, Ihandle* ih, int mode, float pos, int m)
+ {
+ int old_lines_first = ih->data->lines.first;
+ int old_columns_first = ih->data->columns.first;
++ int old_lines_first_offset = ih->data->lines.first_offset;
++ int old_columns_first_offset = ih->data->columns.first_offset;
+ 
+- iMatrixScrollToVisible(ih, IMAT_PROCESS_COL, col);
+- iMatrixScrollToVisible(ih, IMAT_PROCESS_LIN, lin);
++ iupMatrixEditForceHidden(ih);
+ 
+- if (ih->data->lines.first != old_lines_first || ih->data->columns.first != old_columns_first)
++ func(ih, mode, pos, m);
++
++ if ((ih->data->lines.first != old_lines_first || ih->data->lines.first_offset != old_lines_first_offset) ||
++ (ih->data->columns.first != old_columns_first || ih->data->columns.first_offset != old_columns_first_offset))
+ {
+- if (ih->data->columns.first != old_columns_first)
+- iupMatrixAuxUpdateVisiblePos(ih, IMAT_PROCESS_COL);
++ /* when "first" is changed must update scroll pos */
++ if (ih->data->columns.first != old_columns_first || ih->data->columns.first_offset != old_columns_first_offset)
++ iupMatrixAuxUpdateScrollPos(ih, IMAT_PROCESS_COL);
+ 
+- if (ih->data->lines.first != old_lines_first)
+- iupMatrixAuxUpdateVisiblePos(ih, IMAT_PROCESS_LIN);
++ if (ih->data->lines.first != old_lines_first || ih->data->lines.first_offset != old_lines_first_offset)
++ iupMatrixAuxUpdateScrollPos(ih, IMAT_PROCESS_LIN);
+ 
+ iMatrixScrollCallScrollTopCb(ih);
+ 
+- iupMatrixDraw(ih, 1);
++ iupMatrixDraw(ih, 0);
+ }
+ }
+ 
++/************************************************************************************/
++
+ /* This function is called when the "home" key is pressed.
+ In the first time, go to the beginning of the line.
+ In the second time, go to the beginning of the page.
+ In the third time, go to the beginning of the matrix.
+ -> mode and pos : DO NOT USED.
+ */
+-void iupMatrixScrollHome(Ihandle* ih, int unused_mode, float unused_pos, int unused_m)
++void iupMatrixScrollHomeFunc(Ihandle* ih, int unused_mode, float unused_pos, int unused_m)
+ {
+ (void)unused_m;
+ (void)unused_mode;
+ (void)unused_pos;
+ 
+ /* called only for mode==IMAT_SCROLLKEY */
++ /* moving focus and eventually scrolling */
+ 
+ if(ih->data->homekeycount == 0) /* go to the beginning of the line */
+ {
+- ih->data->columns.first = iMatrixScrollGetNextNonEmpty(ih, IMAT_PROCESS_COL, 1);
+- iMatrixScrollSetFocusScrollToVisible(ih, IMAT_PROCESS_COL, ih->data->columns.first);
++ int col = iMatrixScrollGetNextNonEmpty(ih, IMAT_PROCESS_COL, 1);
++ iMatrixScrollSetFocusScrollToVisibleLinCol(ih, IMAT_PROCESS_COL, col);
+ }
+ else if(ih->data->homekeycount == 1) /* go to the beginning of the visible page */
+ {
+- iupMatrixFocusSet(ih, ih->data->lines.first, ih->data->columns.first);
+-
+- /* set for both because current focus maybe hidden */
+- iMatrixScrollToVisible(ih, IMAT_PROCESS_COL, ih->data->columns.focus_cell);
+- iMatrixScrollToVisible(ih, IMAT_PROCESS_LIN, ih->data->lines.focus_cell);
++ iMatrixScrollSetFocusScrollToVisible(ih, ih->data->lines.first, ih->data->columns.first);
+ }
+ else if(ih->data->homekeycount == 2) /* go to the beginning of the matrix 1:1 */
+ {
+- ih->data->columns.first = iMatrixScrollGetNextNonEmpty(ih, IMAT_PROCESS_COL, 1);
+- ih->data->lines.first = iMatrixScrollGetNextNonEmpty(ih, IMAT_PROCESS_LIN, 1);
+-
+- iupMatrixFocusSet(ih, ih->data->lines.first, ih->data->columns.first);
+-
+- /* set for both because current focus maybe hidden */
+- iMatrixScrollToVisible(ih, IMAT_PROCESS_COL, ih->data->columns.focus_cell);
+- iMatrixScrollToVisible(ih, IMAT_PROCESS_LIN, ih->data->lines.focus_cell);
++ int lin = iMatrixScrollGetNextNonEmpty(ih, IMAT_PROCESS_LIN, 1);
++ int col = iMatrixScrollGetNextNonEmpty(ih, IMAT_PROCESS_COL, 1);
++ iMatrixScrollSetFocusScrollToVisible(ih, lin, col);
+ }
+ }
+ 
+@@ -255,37 +228,29 @@ void iupMatrixScrollHome(Ihandle* ih, int unused_mode, float unused_pos, int unu
+ In the third time, go to the end of the matrix.
+ -> mode and pos : DO NOT USED.
+ */
+-void iupMatrixScrollEnd(Ihandle* ih, int unused_mode, float unused_pos, int unused_m)
++void iupMatrixScrollEndFunc(Ihandle* ih, int unused_mode, float unused_pos, int unused_m)
+ {
+ (void)unused_m;
+ (void)unused_mode;
+ (void)unused_pos;
+ 
+ /* called only for mode==IMAT_SCROLLKEY */
++ /* moving focus and eventually scrolling */
+ 
+ if(ih->data->endkeycount == 0) /* go to the end of the line */
+ {
+- int last_col = iMatrixScrollGetPrevNonEmpty(ih, IMAT_PROCESS_COL, ih->data->columns.num-1);
+- iMatrixScrollSetFocusScrollToVisible(ih, IMAT_PROCESS_COL, last_col);
++ int col = iMatrixScrollGetPrevNonEmpty(ih, IMAT_PROCESS_COL, ih->data->columns.num-1);
++ iMatrixScrollSetFocusScrollToVisibleLinCol(ih, IMAT_PROCESS_COL, col);
+ }
+ else if(ih->data->endkeycount == 1) /* go to the end of the visible page */
+ {
+- iupMatrixFocusSet(ih, ih->data->lines.last, ih->data->columns.last);
+-
+- /* set for both because current focus maybe hidden */
+- iMatrixScrollToVisible(ih, IMAT_PROCESS_COL, ih->data->columns.focus_cell);
+- iMatrixScrollToVisible(ih, IMAT_PROCESS_LIN, ih->data->lines.focus_cell);
++ iMatrixScrollSetFocusScrollToVisible(ih, ih->data->lines.last, ih->data->columns.last);
+ }
+ else if(ih->data->endkeycount == 2) /* go to the end of the matrix */
+ {
+- int last_col = iMatrixScrollGetPrevNonEmpty(ih, IMAT_PROCESS_COL, ih->data->columns.num-1);
+- int last_lin = iMatrixScrollGetPrevNonEmpty(ih, IMAT_PROCESS_LIN, ih->data->lines.num-1);
+-
+- iupMatrixFocusSet(ih, last_lin, last_col);
+-
+- /* set for both because current focus maybe hidden */
+- iMatrixScrollToVisible(ih, IMAT_PROCESS_COL, ih->data->columns.focus_cell);
+- iMatrixScrollToVisible(ih, IMAT_PROCESS_LIN, ih->data->lines.focus_cell);
++ int lin = iMatrixScrollGetPrevNonEmpty(ih, IMAT_PROCESS_LIN, ih->data->lines.num-1);
++ int col = iMatrixScrollGetPrevNonEmpty(ih, IMAT_PROCESS_COL, ih->data->columns.num-1);
++ iMatrixScrollSetFocusScrollToVisible(ih, lin, col);
+ }
+ }
+ 
+@@ -295,7 +260,7 @@ void iupMatrixScrollEnd(Ihandle* ih, int unused_mode, float unused_pos, int unus
+ -> pos : DO NOT USED
+ -> m : define the mode of operation: lines or columns [IMAT_PROCESS_LIN|IMAT_PROCESS_COL]
+ */
+-void iupMatrixScrollLeftUp(Ihandle* ih, int mode, float pos, int m)
++void iupMatrixScrollLeftUpFunc(Ihandle* ih, int mode, float pos, int m)
+ {
+ ImatLinColData* p;
+ (void)pos;
+@@ -307,12 +272,15 @@ void iupMatrixScrollLeftUp(Ihandle* ih, int mode, float pos, int m)
+ 
+ if (mode == IMAT_SCROLLKEY)
+ {
++ /* moving focus and eventually scrolling */
+ int next = iMatrixScrollGetPrevNonEmpty(ih, m, p->focus_cell-1);
+- iMatrixScrollSetFocusScrollToVisible(ih, m, next);
++ iMatrixScrollSetFocusScrollToVisibleLinCol(ih, m, next);
+ }
+ else /* IMAT_SCROLLBAR */
+ {
++ /* always scrolling without changing focus */
+ p->first = iMatrixScrollGetPrevNonEmpty(ih, m, p->first-1);
++ p->first_offset = 0;
+ }
+ }
+ 
+@@ -322,7 +290,7 @@ void iupMatrixScrollLeftUp(Ihandle* ih, int mode, float pos, int m)
+ -> pos : DO NOT USED
+ -> m : define the mode of operation: lines or columns [IMAT_PROCESS_LIN|IMAT_PROCESS_COL]
+ */
+-void iupMatrixScrollRightDown(Ihandle* ih, int mode, float pos, int m)
++void iupMatrixScrollRightDownFunc(Ihandle* ih, int mode, float pos, int m)
+ {
+ ImatLinColData* p;
+ (void)pos;
+@@ -334,12 +302,15 @@ void iupMatrixScrollRightDown(Ihandle* ih, int mode, float pos, int m)
+ 
+ if (mode == IMAT_SCROLLKEY)
+ {
++ /* moving focus and eventually scrolling */
+ int next = iMatrixScrollGetNextNonEmpty(ih, m, p->focus_cell+1);
+- iMatrixScrollSetFocusScrollToVisible(ih, m, next);
++ iMatrixScrollSetFocusScrollToVisibleLinCol(ih, m, next);
+ }
+ else /* IMAT_SCROLLBAR */
+ {
++ /* always scrolling without changing focus */
+ p->first = iMatrixScrollGetNextNonEmpty(ih, m, p->first+1);
++ p->first_offset = 0;
+ }
+ }
+ 
+@@ -349,7 +320,7 @@ void iupMatrixScrollRightDown(Ihandle* ih, int mode, float pos, int m)
+ -> pos : DO NOT USED
+ -> m : define the mode of operation: lines (PgLeft) or columns (PgUp) [IMAT_PROCESS_LIN|IMAT_PROCESS_COL]
+ */
+-void iupMatrixScrollPgLeftUp(Ihandle* ih, int mode, float pos, int m)
++void iupMatrixScrollPgLeftUpFunc(Ihandle* ih, int mode, float pos, int m)
+ {
+ ImatLinColData* p;
+ (void)pos;
+@@ -361,12 +332,15 @@ void iupMatrixScrollPgLeftUp(Ihandle* ih, int mode, float pos, int m)
+ 
+ if (mode == IMAT_SCROLLKEY)
+ {
++ /* moving focus and eventually scrolling */
+ int next = iMatrixScrollGetPrevNonEmpty(ih, m, p->focus_cell - (p->last - p->first));
+- iMatrixScrollSetFocusScrollToVisible(ih, m, next);
++ iMatrixScrollSetFocusScrollToVisibleLinCol(ih, m, next);
+ }
+ else /* IMAT_SCROLLBAR */
+ {
++ /* always scrolling without changing focus */
+ p->first = iMatrixScrollGetPrevNonEmpty(ih, m, p->first - (p->last - p->first));
++ p->first_offset = 0;
+ }
+ }
+ 
+@@ -376,7 +350,7 @@ void iupMatrixScrollPgLeftUp(Ihandle* ih, int mode, float pos, int m)
+ -> pos : DO NOT USED
+ -> m : define the mode of operation: lines (PgDown) or columns (PgRight) [IMAT_PROCESS_LIN|IMAT_PROCESS_COL]
+ */
+-void iupMatrixScrollPgRightDown(Ihandle* ih, int mode, float pos, int m)
++void iupMatrixScrollPgRightDownFunc(Ihandle* ih, int mode, float pos, int m)
+ {
+ ImatLinColData* p;
+ (void)pos;
+@@ -388,16 +362,19 @@ void iupMatrixScrollPgRightDown(Ihandle* ih, int mode, float pos, int m)
+ 
+ if (mode == IMAT_SCROLLKEY)
+ {
+- int next = iMatrixScrollGetNextNonEmpty(ih, IMAT_PROCESS_COL, p->focus_cell + (p->last - p->first));
+- iMatrixScrollSetFocusScrollToVisible(ih, m, next);
++ /* moving focus and eventually scrolling */
++ int next = iMatrixScrollGetNextNonEmpty(ih, m, p->focus_cell + (p->last - p->first));
++ iMatrixScrollSetFocusScrollToVisibleLinCol(ih, m, next);
+ }
+ else /* IMAT_SCROLLBAR */
+ {
++ /* always scrolling without changing focus */
+ p->first = iMatrixScrollGetPrevNonEmpty(ih, m, p->first + (p->last - p->first));
++ p->first_offset = 0;
+ }
+ }
+ 
+-void iupMatrixScrollCr(Ihandle* ih, int unused_mode, float unused_pos, int unused_m)
++void iupMatrixScrollCrFunc(Ihandle* ih, int unused_mode, float unused_pos, int unused_m)
+ {
+ int oldlin = ih->data->lines.focus_cell;
+ int oldcol = ih->data->columns.focus_cell;
+@@ -408,13 +385,13 @@ void iupMatrixScrollCr(Ihandle* ih, int unused_mode, float unused_pos, int unuse
+ /* called only for mode==IMAT_SCROLLKEY */
+ 
+ /* try the normal processing of next cell down */
+- iupMatrixScrollRightDown(ih, IMAT_SCROLLKEY, 0, IMAT_PROCESS_LIN);
++ iupMatrixScrollRightDownFunc(ih, IMAT_SCROLLKEY, 0, IMAT_PROCESS_LIN);
+ 
+ if(ih->data->lines.focus_cell == oldlin && ih->data->columns.focus_cell == oldcol)
+ {
+ /* If focus was not changed, it was because it is in the last line of the column.
+ Go to the next column of the same line. */
+- iupMatrixScrollRightDown(ih, IMAT_SCROLLKEY, 0, IMAT_PROCESS_COL);
++ iupMatrixScrollRightDownFunc(ih, IMAT_SCROLLKEY, 0, IMAT_PROCESS_COL);
+ }
+ }
+ 
+@@ -423,70 +400,51 @@ void iupMatrixScrollCr(Ihandle* ih, int unused_mode, float unused_pos, int unuse
+ -> mode : DO NOT USED
+ -> m : define the mode of operation: lines or columns [IMAT_PROCESS_LIN|IMAT_PROCESS_COL]
+ */
+-void iupMatrixScrollPos(Ihandle* ih, int mode, float pos, int m)
++void iupMatrixScrollPosFunc(Ihandle* ih, int mode, float pos, int m)
+ {
+- int scroll_pos, index, vp;
+- float d;
++ int scroll_pos;
+ ImatLinColData* p;
+ (void)mode;
+ 
+ if (m == IMAT_PROCESS_LIN)
+- {
+ p = &(ih->data->lines);
+- d = IupGetFloat(ih, "DY");
+- }
+ else
+- {
+ p = &(ih->data->columns);
+- d = IupGetFloat(ih, "DX");
+- }
+ 
+ if (p->num == 1)
+ {
+ p->first = 1;
++ p->first_offset = 0;
+ return;
+ }
+ 
+ scroll_pos = (int)(pos * p->total_size + 0.5);
+ 
+- vp = 0;
+- for(index = 1; index < p->num; index++)
+- {
+- vp += p->sizes[index];
+- if (vp > scroll_pos)
+- break;
+- }
+-
+- if (index == p->num)
+- {
+- if (p->num == 1)
+- index = 1;
+- else
+- index = p->num-1;
+- }
+-
+- p->first = index;
++ /* position first and first_offset, according to scroll pos */
++ iupMatrixAuxAdjustFirstFromScrollPos(p, scroll_pos);
+ }
+ 
+-int iupMatrixScroll_CB(Ihandle* ih, int action, float x, float y)
++/************************************************************************************/
++
++int iupMatrixScroll_CB(Ihandle* ih, int action, float posx, float posy)
+ {
+ if (!iupMatrixIsValid(ih, 0))
+ return IUP_DEFAULT;
+ 
+ switch(action)
+ {
+- case IUP_SBUP : iupMatrixScrollUp(ih); break;
+- case IUP_SBDN : iupMatrixScrollDown(ih); break;
+- case IUP_SBPGUP : iupMatrixScrollPgUp(ih); break;
+- case IUP_SBPGDN : iupMatrixScrollPgDown(ih); break;
+- case IUP_SBRIGHT : iupMatrixScrollRight(ih); break;
+- case IUP_SBLEFT : iupMatrixScrollLeft(ih); break;
+- case IUP_SBPGRIGHT : iupMatrixScrollPgRight(ih); break;
+- case IUP_SBPGLEFT : iupMatrixScrollPgLeft(ih); break;
+- case IUP_SBPOSV : iupMatrixScrollPosVer(ih,y); break;
+- case IUP_SBPOSH : iupMatrixScrollPosHor(ih,x); break;
+- case IUP_SBDRAGV : iupMatrixScrollPosVer(ih,y); break;
+- case IUP_SBDRAGH : iupMatrixScrollPosHor(ih,x); break;
++ case IUP_SBUP : iupMATRIX_ScrollUp(ih); break;
++ case IUP_SBDN : iupMATRIX_ScrollDown(ih); break;
++ case IUP_SBPGUP : iupMATRIX_ScrollPgUp(ih); break;
++ case IUP_SBPGDN : iupMATRIX_ScrollPgDown(ih); break;
++ case IUP_SBRIGHT : iupMATRIX_ScrollRight(ih); break;
++ case IUP_SBLEFT : iupMATRIX_ScrollLeft(ih); break;
++ case IUP_SBPGRIGHT : iupMATRIX_ScrollPgRight(ih); break;
++ case IUP_SBPGLEFT : iupMATRIX_ScrollPgLeft(ih); break;
++ case IUP_SBPOSV : iupMATRIX_ScrollPosVer(ih,posy); break;
++ case IUP_SBPOSH : iupMATRIX_ScrollPosHor(ih,posx); break;
++ case IUP_SBDRAGV : iupMATRIX_ScrollPosVer(ih,posy); break;
++ case IUP_SBDRAGH : iupMATRIX_ScrollPosHor(ih,posx); break;
+ }
+ 
+ iupMatrixDrawUpdate(ih);
+diff --git a/iup/srccontrols/matrix/iupmat_scroll.h b/iup/srccontrols/matrix/iupmat_scroll.h
+index 582442b..45d7417 100755
+--- a/iup/srccontrols/matrix/iupmat_scroll.h
++++ b/iup/srccontrols/matrix/iupmat_scroll.h
+@@ -12,54 +12,54 @@
+ extern "C" {
+ #endif
+ 
+-int iupMatrixScroll_CB(Ihandle* ih, int action, float x, float y);
++int iupMatrixScroll_CB(Ihandle* ih, int action, float posx, float posy);
+ 
+ void iupMatrixScrollToVisible(Ihandle* ih, int lin, int col);
+ 
+-typedef void (*iupMatrixScrollMoveF)(Ihandle* ih, int mode, float pos, int m);
+-void iupMatrixScrollMoveCursor(iupMatrixScrollMoveF func, Ihandle* ih, int mode, float pos, int m);
++typedef void (*iupMatrixScrollMoveFunc)(Ihandle* ih, int mode, float pos, int m);
++void iupMatrixScrollMove(iupMatrixScrollMoveFunc func, Ihandle* ih, int mode, float pos, int m);
+ 
+ /* Used only by the macros bellow */
+-void iupMatrixScrollHome (Ihandle* ih, int, float, int);
+-void iupMatrixScrollEnd (Ihandle* ih, int, float, int);
+-void iupMatrixScrollLeftUp (Ihandle* ih, int, float, int);
+-void iupMatrixScrollRightDown (Ihandle* ih, int, float, int);
+-void iupMatrixScrollPgLeftUp (Ihandle* ih, int, float, int);
+-void iupMatrixScrollPgRightDown(Ihandle* ih, int, float, int);
+-void iupMatrixScrollPos (Ihandle* ih, int, float, int);
+-void iupMatrixScrollCr (Ihandle* ih, int, float, int);
++void iupMatrixScrollHomeFunc (Ihandle* ih, int, float, int);
++void iupMatrixScrollEndFunc (Ihandle* ih, int, float, int);
++void iupMatrixScrollLeftUpFunc (Ihandle* ih, int, float, int);
++void iupMatrixScrollRightDownFunc (Ihandle* ih, int, float, int);
++void iupMatrixScrollPgLeftUpFunc (Ihandle* ih, int, float, int);
++void iupMatrixScrollPgRightDownFunc(Ihandle* ih, int, float, int);
++void iupMatrixScrollPosFunc (Ihandle* ih, int, float, int);
++void iupMatrixScrollCrFunc (Ihandle* ih, int, float, int);
+ 
+ /* Mode used to "walk" inside the matrix.
+ It shows if the movement request was from the scrollbar or from a key.
+- Possible values for the "mode" parameter of the iupMatrixScrollMoveCursor function.
++ Possible values for the "mode" parameter of the iupMatrixScrollMove function.
+ */
+ #define IMAT_SCROLLBAR 0
+ #define IMAT_SCROLLKEY 1
+ 
+-/* Macros to help during the call of iupMatrixScrollMoveCursor function */
++/* Macros to help during the call of iupMatrixScrollMove function */
+ 
+ /* used in the keyboard processing module */
+-#define iupMatrixScrollKeyHome(ih) iupMatrixScrollMoveCursor(iupMatrixScrollHome , ih, IMAT_SCROLLKEY, 0, 0)
+-#define iupMatrixScrollKeyEnd(ih) iupMatrixScrollMoveCursor(iupMatrixScrollEnd , ih, IMAT_SCROLLKEY, 0, 0)
+-#define iupMatrixScrollKeyPgUp(ih) iupMatrixScrollMoveCursor(iupMatrixScrollPgLeftUp , ih, IMAT_SCROLLKEY, 0, IMAT_PROCESS_LIN)
+-#define iupMatrixScrollKeyPgDown(ih) iupMatrixScrollMoveCursor(iupMatrixScrollPgRightDown, ih, IMAT_SCROLLKEY, 0, IMAT_PROCESS_LIN)
+-#define iupMatrixScrollKeyDown(ih) iupMatrixScrollMoveCursor(iupMatrixScrollRightDown , ih, IMAT_SCROLLKEY, 0, IMAT_PROCESS_LIN)
+-#define iupMatrixScrollKeyRight(ih) iupMatrixScrollMoveCursor(iupMatrixScrollRightDown , ih, IMAT_SCROLLKEY, 0, IMAT_PROCESS_COL)
+-#define iupMatrixScrollKeyUp(ih) iupMatrixScrollMoveCursor(iupMatrixScrollLeftUp , ih, IMAT_SCROLLKEY, 0, IMAT_PROCESS_LIN)
+-#define iupMatrixScrollKeyLeft(ih) iupMatrixScrollMoveCursor(iupMatrixScrollLeftUp , ih, IMAT_SCROLLKEY, 0, IMAT_PROCESS_COL)
+-#define iupMatrixScrollKeyCr(ih) iupMatrixScrollMoveCursor(iupMatrixScrollCr , ih, IMAT_SCROLLKEY, 0, 0)
++#define iupMATRIX_ScrollKeyHome(ih) iupMatrixScrollMove(iupMatrixScrollHomeFunc , ih, IMAT_SCROLLKEY, 0, 0)
++#define iupMATRIX_ScrollKeyEnd(ih) iupMatrixScrollMove(iupMatrixScrollEndFunc , ih, IMAT_SCROLLKEY, 0, 0)
++#define iupMATRIX_ScrollKeyPgUp(ih) iupMatrixScrollMove(iupMatrixScrollPgLeftUpFunc , ih, IMAT_SCROLLKEY, 0, IMAT_PROCESS_LIN)
++#define iupMATRIX_ScrollKeyPgDown(ih) iupMatrixScrollMove(iupMatrixScrollPgRightDownFunc, ih, IMAT_SCROLLKEY, 0, IMAT_PROCESS_LIN)
++#define iupMATRIX_ScrollKeyDown(ih) iupMatrixScrollMove(iupMatrixScrollRightDownFunc , ih, IMAT_SCROLLKEY, 0, IMAT_PROCESS_LIN)
++#define iupMATRIX_ScrollKeyRight(ih) iupMatrixScrollMove(iupMatrixScrollRightDownFunc , ih, IMAT_SCROLLKEY, 0, IMAT_PROCESS_COL)
++#define iupMATRIX_ScrollKeyUp(ih) iupMatrixScrollMove(iupMatrixScrollLeftUpFunc , ih, IMAT_SCROLLKEY, 0, IMAT_PROCESS_LIN)
++#define iupMATRIX_ScrollKeyLeft(ih) iupMatrixScrollMove(iupMatrixScrollLeftUpFunc , ih, IMAT_SCROLLKEY, 0, IMAT_PROCESS_COL)
++#define iupMATRIX_ScrollKeyCr(ih) iupMatrixScrollMove(iupMatrixScrollCrFunc , ih, IMAT_SCROLLKEY, 0, 0)
+ 
+ /* Used by the scrollbar callback only */
+-#define iupMatrixScrollUp(ih) iupMatrixScrollMoveCursor(iupMatrixScrollLeftUp , ih, IMAT_SCROLLBAR, 0, IMAT_PROCESS_LIN)
+-#define iupMatrixScrollLeft(ih) iupMatrixScrollMoveCursor(iupMatrixScrollLeftUp , ih, IMAT_SCROLLBAR, 0, IMAT_PROCESS_COL)
+-#define iupMatrixScrollDown(ih) iupMatrixScrollMoveCursor(iupMatrixScrollRightDown , ih, IMAT_SCROLLBAR, 0, IMAT_PROCESS_LIN)
+-#define iupMatrixScrollRight(ih) iupMatrixScrollMoveCursor(iupMatrixScrollRightDown , ih, IMAT_SCROLLBAR, 0, IMAT_PROCESS_COL)
+-#define iupMatrixScrollPgUp(ih) iupMatrixScrollMoveCursor(iupMatrixScrollPgLeftUp , ih, IMAT_SCROLLBAR, 0, IMAT_PROCESS_LIN)
+-#define iupMatrixScrollPgLeft(ih) iupMatrixScrollMoveCursor(iupMatrixScrollPgLeftUp , ih, IMAT_SCROLLBAR, 0, IMAT_PROCESS_COL)
+-#define iupMatrixScrollPgDown(ih) iupMatrixScrollMoveCursor(iupMatrixScrollPgRightDown, ih, IMAT_SCROLLBAR, 0, IMAT_PROCESS_LIN)
+-#define iupMatrixScrollPgRight(ih) iupMatrixScrollMoveCursor(iupMatrixScrollPgRightDown, ih, IMAT_SCROLLBAR, 0, IMAT_PROCESS_COL)
+-#define iupMatrixScrollPosVer(ih, y) iupMatrixScrollMoveCursor(iupMatrixScrollPos , ih, IMAT_SCROLLBAR, y, IMAT_PROCESS_LIN)
+-#define iupMatrixScrollPosHor(ih, x) iupMatrixScrollMoveCursor(iupMatrixScrollPos , ih, IMAT_SCROLLBAR, x, IMAT_PROCESS_COL)
++#define iupMATRIX_ScrollUp(ih) iupMatrixScrollMove(iupMatrixScrollLeftUpFunc , ih, IMAT_SCROLLBAR, 0, IMAT_PROCESS_LIN)
++#define iupMATRIX_ScrollLeft(ih) iupMatrixScrollMove(iupMatrixScrollLeftUpFunc , ih, IMAT_SCROLLBAR, 0, IMAT_PROCESS_COL)
++#define iupMATRIX_ScrollDown(ih) iupMatrixScrollMove(iupMatrixScrollRightDownFunc , ih, IMAT_SCROLLBAR, 0, IMAT_PROCESS_LIN)
++#define iupMATRIX_ScrollRight(ih) iupMatrixScrollMove(iupMatrixScrollRightDownFunc , ih, IMAT_SCROLLBAR, 0, IMAT_PROCESS_COL)
++#define iupMATRIX_ScrollPgUp(ih) iupMatrixScrollMove(iupMatrixScrollPgLeftUpFunc , ih, IMAT_SCROLLBAR, 0, IMAT_PROCESS_LIN)
++#define iupMATRIX_ScrollPgLeft(ih) iupMatrixScrollMove(iupMatrixScrollPgLeftUpFunc , ih, IMAT_SCROLLBAR, 0, IMAT_PROCESS_COL)
++#define iupMATRIX_ScrollPgDown(ih) iupMatrixScrollMove(iupMatrixScrollPgRightDownFunc, ih, IMAT_SCROLLBAR, 0, IMAT_PROCESS_LIN)
++#define iupMATRIX_ScrollPgRight(ih) iupMatrixScrollMove(iupMatrixScrollPgRightDownFunc, ih, IMAT_SCROLLBAR, 0, IMAT_PROCESS_COL)
++#define iupMATRIX_ScrollPosVer(ih, y) iupMatrixScrollMove(iupMatrixScrollPosFunc , ih, IMAT_SCROLLBAR, posy, IMAT_PROCESS_LIN)
++#define iupMATRIX_ScrollPosHor(ih, x) iupMatrixScrollMove(iupMatrixScrollPosFunc , ih, IMAT_SCROLLBAR, posx, IMAT_PROCESS_COL)
+ 
+ 
+ #ifdef __cplusplus
+diff --git a/iup/srccontrols/matrix/iupmatrix.c b/iup/srccontrols/matrix/iupmatrix.c
+index 20d618d..9e379e2 100755
+--- a/iup/srccontrols/matrix/iupmatrix.c
++++ b/iup/srccontrols/matrix/iupmatrix.c
+@@ -76,10 +76,13 @@ static int iMatrixSetOriginAttrib(Ihandle* ih, const char* value)
+ return 0;
+ 
+ ih->data->columns.first = col;
++ ih->data->columns.first_offset = 0;
+ ih->data->lines.first = lin;
++ ih->data->lines.first_offset = 0;
+ 
+- iupMatrixAuxUpdateVisiblePos(ih, IMAT_PROCESS_COL);
+- iupMatrixAuxUpdateVisiblePos(ih, IMAT_PROCESS_LIN);
++ /* when "first" is changed must update scroll pos */
++ iupMatrixAuxUpdateScrollPos(ih, IMAT_PROCESS_COL);
++ iupMatrixAuxUpdateScrollPos(ih, IMAT_PROCESS_LIN);
+ 
+ iupMatrixDraw(ih, 1);
+ return 0;
+@@ -109,7 +112,7 @@ static int iMatrixSetShowAttrib(Ihandle* ih, const char* value)
+ if((lin < 1) || (col < 1))
+ return 0;
+ 
+- if (!iupMatrixAuxIsCellFullVisible(ih, lin, col))
++ if (!iupMatrixAuxIsCellStartVisible(ih, lin, col))
+ iupMatrixScrollToVisible(ih, lin, col);
+ 
+ return 0;
+@@ -173,6 +176,23 @@ static char* iMatrixGetUseTitleSizeAttrib(Ihandle* ih)
+ return "NO";
+ }
+ 
++static int iMatrixSetHiddenTextMarksAttrib(Ihandle* ih, const char* value)
++{
++ if (iupStrBoolean(value))
++ ih->data->hidden_text_marks = 1;
++ else 
++ ih->data->hidden_text_marks = 0;
++ return 0;
++}
++
++static char* iMatrixGetHiddenTextMarksAttrib(Ihandle* ih)
++{
++ if (ih->data->hidden_text_marks)
++ return "YES";
++ else
++ return "NO";
++}
++
+ static int iMatrixSetValueAttrib(Ihandle* ih, const char* value)
+ {
+ if (IupGetInt(ih->data->datah, "VISIBLE"))
+@@ -228,14 +248,14 @@ static char* iMatrixGetMultilineAttrib(Ihandle* ih)
+ static char* iMatrixGetNumLinAttrib(Ihandle* ih)
+ {
+ char* num = iupStrGetMemory(100);
+- sprintf(num, "%d", ih->data->lines.num-1);
++ sprintf(num, "%d", ih->data->lines.num-1); /* the attribute does not include the title */
+ return num;
+ }
+ 
+ static char* iMatrixGetNumColAttrib(Ihandle* ih)
+ {
+ char* num = iupStrGetMemory(100);
+- sprintf(num, "%d", ih->data->columns.num-1);
++ sprintf(num, "%d", ih->data->columns.num-1); /* the attribute does not include the title */
+ return num;
+ }
+ 
+@@ -427,13 +447,19 @@ static char* iMatrixGetAlignmentAttrib(Ihandle* ih, const char* name_id)
+ align = iupAttribGet(ih, str);
+ if (!align)
+ {
+- int col;
+- if (iupStrToInt(name_id, &col))
++ align = iupAttribGet(ih, "ALIGNMENT");
++ if (align)
++ return align;
++ else
+ {
+- if (col == 0)
+- return "ALEFT";
+- else
+- return "ACENTER";
++ int col;
++ if (iupStrToInt(name_id, &col))
++ {
++ if (col == 0)
++ return "ALEFT";
++ else
++ return "ACENTER";
++ }
+ }
+ }
+ 
+@@ -642,7 +668,7 @@ static int iMatrixCreateMethod(Ihandle* ih, void **params)
+ /* Create the edit fields */
+ iupMatrixEditCreate(ih);
+ 
+- /* defaults */
++ /* defaults that are non zero */
+ ih->data->datah = ih->data->texth;
+ ih->data->mark_continuous = 1;
+ ih->data->columns.num = 1;
+@@ -656,7 +682,6 @@ static int iMatrixCreateMethod(Ihandle* ih, void **params)
+ ih->data->mark_col1 = -1;
+ ih->data->mark_lin2 = -1;
+ ih->data->mark_col2 = -1;
+- ih->data->use_title_size = 0;
+ 
+ return IUP_NOERROR;
+ }
+@@ -700,11 +725,34 @@ static void iMatrixUnMapMethod(Ihandle* ih)
+ iupMatrixMemRelease(ih);
+ }
+ 
++static char* iMatrixGetDefault(Ihandle* ih, const char* name)
++{
++ int inherit;
++ char *def_value;
++ iupClassObjectGetAttributeInfo(ih, name, &def_value, &inherit);
++ return def_value;
++}
++
++static int iMatrixGetInt(Ihandle* ih, const char* name)
++{
++ char *value = iupAttribGet(ih, name);
++ if (!value) value = iMatrixGetDefault(ih, name);
++ if (value)
++ {
++ int i = 0;
++ if (iupStrToInt(value, &i))
++ return i;
++ }
++ return 0;
++}
++
+ static int iMatrixGetNaturalWidth(Ihandle* ih)
+ {
+ int width = 0, num, col;
+ 
+- num = iupAttribGetInt(ih, "NUMCOL_VISIBLE")+1; /* include the title column */
++ /* must use this custom function because 
++ the get method for this attribute returns a value with a different meaning */
++ num = iMatrixGetInt(ih, "NUMCOL_VISIBLE")+1; /* include the title column */
+ 
+ if (iupAttribGetInt(ih, "NUMCOL_VISIBLE_LAST"))
+ {
+@@ -716,9 +764,7 @@ static int iMatrixGetNaturalWidth(Ihandle* ih)
+ }
+ else
+ {
+- if (num > ih->data->columns.num)
+- num = ih->data->columns.num;
+- for(col = 0; col < num; col++)
++ for(col = 0; col < num; col++) /* num can be > numcol */
+ width += iupMatrixAuxGetColumnWidth(ih, col);
+ }
+ 
+@@ -729,7 +775,9 @@ static int iMatrixGetNaturalHeight(Ihandle* ih)
+ {
+ int height = 0, num, lin;
+ 
+- num = iupAttribGetInt(ih, "NUMLIN_VISIBLE")+1; /* include the title line */
++ /* must use this custom function because 
++ the get method for this attribute returns a value with a different meaning */
++ num = iMatrixGetInt(ih, "NUMLIN_VISIBLE")+1; /* include the title line */
+ 
+ if (iupAttribGetInt(ih, "NUMLIN_VISIBLE_LAST"))
+ {
+@@ -741,9 +789,7 @@ static int iMatrixGetNaturalHeight(Ihandle* ih)
+ }
+ else
+ {
+- if (num > ih->data->lines.num)
+- num = ih->data->lines.num;
+- for(lin = 0; lin < num; lin++)
++ for(lin = 0; lin < num; lin++) /* num can be > numlin */
+ height += iupMatrixAuxGetLineHeight(ih, lin);
+ }
+ 
+@@ -902,6 +948,8 @@ Iclass* iupMatrixGetClass(void)
+ 
+ /* IupMatrix Attributes - GENERAL */
+ iupClassRegisterAttribute(ic, "USETITLESIZE", iMatrixGetUseTitleSizeAttrib, iMatrixSetUseTitleSizeAttrib, IUPAF_SAMEASSYSTEM, "NO", IUPAF_NOT_MAPPED|IUPAF_NO_INHERIT);
++ iupClassRegisterAttribute(ic, "HIDDENTEXTMARKS", iMatrixGetHiddenTextMarksAttrib, iMatrixSetHiddenTextMarksAttrib, IUPAF_SAMEASSYSTEM, "NO", IUPAF_NOT_MAPPED|IUPAF_NO_INHERIT);
++ 
+ iupClassRegisterAttribute(ic, "FRAMECOLOR", NULL, NULL, IUPAF_SAMEASSYSTEM, "100 100 100", IUPAF_NO_INHERIT);
+ iupClassRegisterAttribute(ic, "READONLY", NULL, NULL, NULL, NULL, IUPAF_NOT_MAPPED|IUPAF_NO_INHERIT);
+ iupClassRegisterAttribute(ic, "RESIZEMATRIX", NULL, NULL, NULL, NULL, IUPAF_NOT_MAPPED|IUPAF_NO_INHERIT);
+diff --git a/iup/srcgl/Makefile b/iup/srcgl/Makefile
+index 882d0d2..48037f0 100755
+--- a/iup/srcgl/Makefile
++++ b/iup/srcgl/Makefile
+@@ -3,4 +3,4 @@
+ do_all: iupgl
+ 
+ iupgl:
+- @$(MAKE) --no-print-directory -f ../tecmake_compact.mak 
++ @$(MAKE) --no-print-directory -f ../tecmake.mak 
+diff --git a/iup/srcim/Makefile b/iup/srcim/Makefile
+index 933ded1..d47e014 100755
+--- a/iup/srcim/Makefile
++++ b/iup/srcim/Makefile
+@@ -3,4 +3,4 @@
+ do_all: iupim
+ 
+ iupim:
+- @$(MAKE) --no-print-directory -f ../tecmake_compact.mak 
++ @$(MAKE) --no-print-directory -f ../tecmake.mak 
+diff --git a/iup/srcim/iup_im.c b/iup/srcim/iup_im.c
+index c26a3ff..ce58d80 100755
+--- a/iup/srcim/iup_im.c
++++ b/iup/srcim/iup_im.c
+@@ -23,7 +23,7 @@
+ #include "iup_image.h"
+ 
+ 
+-static void PrintError(int error)
++static void iSaveErrorMsg(int error)
+ {
+ char* lang = IupGetLanguage();
+ char* msg;
+@@ -31,20 +31,22 @@ static void PrintError(int error)
+ {
+ switch (error)
+ {
++ case IM_ERR_NONE:
++ msg = NULL;
+ case IM_ERR_OPEN:
+- msg = "Error Opening File.\n";
++ msg = "Error Opening Image File.\n";
+ break;
+ case IM_ERR_MEM:
+ msg = "Insuficient memory.\n";
+ break;
+ case IM_ERR_ACCESS:
+- msg = "Error Accessing File.\n";
++ msg = "Error Accessing Image File.\n";
+ break;
+ case IM_ERR_DATA:
+ msg = "Image type not Suported.\n";
+ break;
+ case IM_ERR_FORMAT:
+- msg = "Invalid Format.\n";
++ msg = "Invalid Image File Format.\n";
+ break;
+ case IM_ERR_COMPRESS:
+ msg = "Invalid or unsupported compression.\n";
+@@ -57,20 +59,22 @@ static void PrintError(int error)
+ {
+ switch (error)
+ {
++ case IM_ERR_NONE:
++ msg = NULL;
+ case IM_ERR_OPEN:
+- msg = "Erro Abrindo Arquivo.\n";
++ msg = "Erro Abrindo Arquivo de Imagem.\n";
+ break;
+ case IM_ERR_MEM:
+ msg = "Memória Insuficiente.\n";
+ break;
+ case IM_ERR_ACCESS:
+- msg = "Erro Acessando Arquivo.\n";
++ msg = "Erro Acessando Arquivo de Imagem.\n";
+ break;
+ case IM_ERR_DATA:
+ msg = "Tipo de Imagem não Suportado.\n";
+ break;
+ case IM_ERR_FORMAT:
+- msg = "Formato Inválido.\n";
++ msg = "Formato de Arquivo de Imagem Inválido.\n";
+ break;
+ case IM_ERR_COMPRESS:
+ msg = "Compressão Inválida ou não Suportada.\n";
+@@ -80,7 +84,7 @@ static void PrintError(int error)
+ }
+ }
+ 
+- IupMessage("Error", msg);
++ IupSetGlobal("IUPIM_LASTERROR", msg);
+ }
+ 
+ Ihandle* IupLoadImage(const char* file_name)
+@@ -165,7 +169,7 @@ load_finish:
+ imCounterSetCallback(NULL, old_callback);
+ if (ifile) imFileClose(ifile);
+ if (image_data) free(image_data);
+- if (error) PrintError(error);
++ iSaveErrorMsg(error);
+ return iup_image;
+ }
+ 
+@@ -188,7 +192,7 @@ int IupSaveImage(Ihandle* ih, const char* file_name, const char* format)
+ ifile = imFileNew(file_name, format, &error);
+ if (!ifile)
+ {
+- PrintError(error);
++ iSaveErrorMsg(error);
+ return 0;
+ }
+ 
+@@ -238,8 +242,7 @@ int IupSaveImage(Ihandle* ih, const char* file_name, const char* format)
+ 
+ imFileClose(ifile); 
+ 
+- if (error)
+- PrintError(error);
++ iSaveErrorMsg(error);
+ 
+ return error == IM_ERR_NONE? 1: 0;
+ }
+diff --git a/iup/srcimglib/Makefile b/iup/srcimglib/Makefile
+index 261537a..873715f 100755
+--- a/iup/srcimglib/Makefile
++++ b/iup/srcimglib/Makefile
+@@ -3,4 +3,4 @@
+ do_all: iupimglib
+ 
+ iupimglib:
+- @$(MAKE) --no-print-directory -f ../tecmake_compact.mak
++ @$(MAKE) --no-print-directory -f ../tecmake.mak
+diff --git a/iup/srcledc/Makefile b/iup/srcledc/Makefile
+index 8854269..71b9235 100755
+--- a/iup/srcledc/Makefile
++++ b/iup/srcledc/Makefile
+@@ -3,4 +3,4 @@
+ do_all: ledc
+ 
+ ledc:
+- @$(MAKE) --no-print-directory -f ../tecmake_compact.mak 
++ @$(MAKE) --no-print-directory -f ../tecmake.mak 
+diff --git a/iup/srclua3/Makefile b/iup/srclua3/Makefile
+index b63716a..0551725 100755
+--- a/iup/srclua3/Makefile
++++ b/iup/srclua3/Makefile
+@@ -3,19 +3,19 @@
+ do_all: iuplua iupluacd iupluacontrols iuplua_pplot iupluagl iupluaim
+ 
+ iuplua:
+- @$(MAKE) --no-print-directory -f ../tecmake_compact.mak 
++ @$(MAKE) --no-print-directory -f ../tecmake.mak 
+ 
+ iupluacd:
+- @$(MAKE) --no-print-directory -f ../tecmake_compact.mak MF=iupcd
++ @$(MAKE) --no-print-directory -f ../tecmake.mak MF=iupcd
+ 
+ iupluacontrols:
+- @$(MAKE) --no-print-directory -f ../tecmake_compact.mak MF=iupcontrols
++ @$(MAKE) --no-print-directory -f ../tecmake.mak MF=iupcontrols
+ 
+ iuplua_pplot:
+- @$(MAKE) --no-print-directory -f ../tecmake_compact.mak MF=iup_pplot
++ @$(MAKE) --no-print-directory -f ../tecmake.mak MF=iup_pplot
+ 
+ iupluagl:
+- @$(MAKE) --no-print-directory -f ../tecmake_compact.mak MF=iupgl
++ @$(MAKE) --no-print-directory -f ../tecmake.mak MF=iupgl
+ 
+ iupluaim:
+- @$(MAKE) --no-print-directory -f ../tecmake_compact.mak MF=iupim
++ @$(MAKE) --no-print-directory -f ../tecmake.mak MF=iupim
+diff --git a/iup/srclua3/config.mak b/iup/srclua3/config.mak
+index fae6145..a3ffb1d 100755
+--- a/iup/srclua3/config.mak
++++ b/iup/srclua3/config.mak
+@@ -6,9 +6,9 @@ OPT = YES
+ 
+ LOHDIR = loh
+ SRCLUA = iuplua.lua iuplua_widgets.lua constants.lua spin.lua \
+- sbox.lua val.lua tree.lua tabs.lua
++ sbox.lua split.lua val.lua tree.lua tabs.lua
+ SRC = iuplua.c iuplua_api.c iuplua_widgets.c il_scanf.c il_cbox.c \
+- il_sbox.c il_spin.c il_val.c il_tree.c il_tabs.c il_getcolor.c il_getparam.c
++ il_sbox.c il_split.c il_spin.c il_val.c il_tree.c il_tabs.c il_getcolor.c il_getparam.c
+ 
+ USE_LUA = Yes
+ 
+diff --git a/iup/srclua3/il.h b/iup/srclua3/il.h
+index 406ccc4..63f9866 100755
+--- a/iup/srclua3/il.h
++++ b/iup/srclua3/il.h
+@@ -15,6 +15,7 @@ int iupluaapi_open(void);
+ int iupluawidgets_open(int tag);
+ 
+ int sboxlua_open(void);
++int splitlua_open(void);
+ int spinlua_open(void);
+ int cboxlua_open(void);
+ int gclua_open (void);
+diff --git a/iup/srclua3/il_getparam.c b/iup/srclua3/il_getparam.c
+index 28a41be..6005ce8 100755
+--- a/iup/srclua3/il_getparam.c
++++ b/iup/srclua3/il_getparam.c
+@@ -93,6 +93,8 @@ static void GetParam(void)
+ param_data[i] = malloc(sizeof(float));
+ *(float*)(param_data[i]) = (float)luaL_check_number(lua_param_start); lua_param_start++;
+ break;
++ case 'f':
++ case 'c':
+ case 's':
+ case 'm':
+ s = luaL_check_string(lua_param_start); lua_param_start++;
+@@ -136,6 +138,8 @@ static void GetParam(void)
+ case 'r':
+ lua_pushnumber(*(float*)(param_data[i]));
+ break;
++ case 'f':
++ case 'c':
+ case 's':
+ case 'm':
+ lua_pushstring((char*)(param_data[i]));
+diff --git a/iup/srclua3/il_tree.c b/iup/srclua3/il_tree.c
+index 8d5fcf8..5d145bf 100755
+--- a/iup/srclua3/il_tree.c
++++ b/iup/srclua3/il_tree.c
+@@ -91,6 +91,29 @@ static int TREE_multiselection (Ihandle *handle, int *ids, int n)
+ return iuplua_call();
+ }
+ 
++static int TREE_multiunselection (Ihandle *handle, int *ids, int n)
++{
++ int i;
++ lua_Object tb;
++
++ iuplua_call_start(handle, "multiunselection");
++
++ tb = lua_createtable();
++ for (i = 0; i < n; i++) 
++ {
++ lua_beginblock();
++ lua_pushobject(tb);
++ lua_pushnumber(i+1);
++ lua_pushnumber(ids[i]);
++ lua_settable();
++ lua_endblock(); 
++ }
++ lua_pushobject(tb);
++
++ lua_pushnumber (n);
++ return iuplua_call();
++}
++
+ static int TREE_dragdrop(Ihandle* handle, int drag_id, int drop_id, int isshift, int iscontrol)
+ {
+ iuplua_call_start(handle, "dragdrop");
+@@ -232,6 +255,7 @@ int treelua_open(void)
+ lua_CFunction func;
+ } TreeAssocList [] = {
+ {"iup_tree_multiselection_cb", (lua_CFunction)TREE_multiselection},
++ {"iup_tree_multiunselection_cb", (lua_CFunction)TREE_multiunselection},
+ {"iup_tree_selection_cb", (lua_CFunction)TREE_selection},
+ {"iup_tree_branchopen_cb", (lua_CFunction)TREE_branchopen},
+ {"iup_tree_branchclose_cb", (lua_CFunction)TREE_branchclose},
+diff --git a/iup/srclua3/iuplua.c b/iup/srclua3/iuplua.c
+index 7789ce8..5563699 100755
+--- a/iup/srclua3/iuplua.c
++++ b/iup/srclua3/iuplua.c
+@@ -481,6 +481,7 @@ int iuplua_open(void)
+ iupluawidgets_open(iuplua_tag);
+ 
+ sboxlua_open();
++ splitlua_open();
+ spinlua_open();
+ cboxlua_open();
+ vallua_open();
+diff --git a/iup/srclua3/iuplua_api.c b/iup/srclua3/iuplua_api.c
+index 3221658..a9acf1d 100755
+--- a/iup/srclua3/iuplua_api.c
++++ b/iup/srclua3/iuplua_api.c
+@@ -182,7 +182,7 @@ static void GetAttribute(void)
+ char *name = luaL_check_string(2);
+ Ihandle* ih = iuplua_checkihandle(1);
+ char *value = IupGetAttribute(ih, name);
+- if (!value || iupAttribIsInternal(name))
++ if (!value || iupATTRIB_ISINTERNAL(name))
+ lua_pushnil();
+ else
+ {
+diff --git a/iup/srclua3/iuplua_widgets.c b/iup/srclua3/iuplua_widgets.c
+index f6b801b..7591580 100755
+--- a/iup/srclua3/iuplua_widgets.c
++++ b/iup/srclua3/iuplua_widgets.c
+@@ -170,6 +170,12 @@ static int iupluaUnMapCb(Ihandle* handle)
+ return iuplua_call();
+ }
+ 
++static int iupluaDestroyCb(Ihandle* handle)
++{
++ iuplua_call_start(handle, "destroycb");
++ return iuplua_call();
++}
++
+ static int iupluaMapCb(Ihandle* handle)
+ {
+ iuplua_call_start(handle, "mapcb");
+@@ -610,6 +616,7 @@ int iupluawidgets_open(int tag)
+ { "iup_show_cb", (lua_CFunction)dialog_show},
+ { "iup_map_cb", (lua_CFunction)iupluaMapCb},
+ { "iup_unmap_cb", (lua_CFunction)iupluaUnMapCb},
++ { "iup_destroy_cb", (lua_CFunction)iupluaDestroyCb},
+ { "iup_dropfiles_cb", (lua_CFunction)iupluaDropfilesCb},
+ { "iup_trayclick_cb", (lua_CFunction)dialog_trayclick},
+ { "iup_getfocus_cb", (lua_CFunction)iupluaGetfocusCb},
+diff --git a/iup/srclua3/iuplua_widgets.lua b/iup/srclua3/iuplua_widgets.lua
+index 33be9e3..a59bde6 100755
+--- a/iup/srclua3/iuplua_widgets.lua
++++ b/iup/srclua3/iuplua_widgets.lua
+@@ -875,6 +875,7 @@ iup_callbacks =
+ showcb = {"SHOW_CB", iup_show_cb},
+ mapcb = {"MAP_CB", iup_map_cb},
+ unmapcb = {"UNMAP_CB", iup_unmap_cb},
++ destroycb = {"DESTROY_CB", iup_destroy_cb},
+ dropfiles = {"DROPFILES_CB", iup_dropfiles_cb},
+ menuclose = {"MENUCLOSE_CB", iup_menuclose_cb},
+ highlight = {"HIGHLIGHT_CB", iup_highlight_cb},
+@@ -921,6 +922,7 @@ iup_callbacks.open_cb = iup_callbacks.open
+ iup_callbacks.show_cb = iup_callbacks.showcb 
+ iup_callbacks.map_cb = iup_callbacks.mapcb 
+ iup_callbacks.unmap_cb = iup_callbacks.unmapcb 
++iup_callbacks.destroy_cb = iup_callbacks.destroycb 
+ iup_callbacks.dropfiles_cb = iup_callbacks.dropfiles 
+ iup_callbacks.menuclose_cb = iup_callbacks.menuclose 
+ iup_callbacks.highlight_cb = iup_callbacks.highlight 
+diff --git a/iup/srclua3/tree.lua b/iup/srclua3/tree.lua
+index 659afdb..bf53bca 100755
+--- a/iup/srclua3/tree.lua
++++ b/iup/srclua3/tree.lua
+@@ -47,6 +47,7 @@ iup.TreeSetValue = TreeSetValue
+ 
+ iup_callbacks.selection = {"SELECTION_CB", iup_tree_selection_cb}
+ iup_callbacks.multiselection = {"MULTISELECTION_CB", iup_tree_multiselection_cb}
++iup_callbacks.multiunselection = {"MULTIUNSELECTION_CB", iup_tree_multiunselection_cb}
+ iup_callbacks.branchopen = {"BRANCHOPEN_CB", iup_tree_branchopen_cb}
+ iup_callbacks.branchclose = {"BRANCHCLOSE_CB", iup_tree_branchclose_cb}
+ iup_callbacks.executeleaf = {"EXECUTELEAF_CB", iup_tree_executeleaf_cb}
+@@ -58,6 +59,7 @@ iup_callbacks.dragdrop = {"DRAGDROP_CB", iup_tree_dragdrop_cb}
+ 
+ iup_callbacks.selection_cb = iup_callbacks.selection 
+ iup_callbacks.multiselection_cb = iup_callbacks.multiselection 
++iup_callbacks.multiunselection_cb = iup_callbacks.multiunselection 
+ iup_callbacks.branchopen_cb = iup_callbacks.branchopen 
+ iup_callbacks.branchclose_cb = iup_callbacks.branchclose 
+ iup_callbacks.executeleaf_cb = iup_callbacks.executeleaf 
+diff --git a/iup/srclua5/Makefile b/iup/srclua5/Makefile
+index 3942e79..1189d32 100755
+--- a/iup/srclua5/Makefile
++++ b/iup/srclua5/Makefile
+@@ -3,22 +3,22 @@
+ do_all: iuplua iupluacd iupluacontrols iuplua_pplot iupluagl iupluaim iupluaimglib
+ 
+ iuplua:
+- @$(MAKE) --no-print-directory -f ../tecmake_compact.mak 
++ @$(MAKE) --no-print-directory -f ../tecmake.mak 
+ 
+ iupluacd:
+- @$(MAKE) --no-print-directory -f ../tecmake_compact.mak MF=iupcd
++ @$(MAKE) --no-print-directory -f ../tecmake.mak MF=iupcd
+ 
+ iupluacontrols:
+- @$(MAKE) --no-print-directory -f ../tecmake_compact.mak MF=iupcontrols
++ @$(MAKE) --no-print-directory -f ../tecmake.mak MF=iupcontrols
+ 
+ iuplua_pplot:
+- @$(MAKE) --no-print-directory -f ../tecmake_compact.mak MF=iup_pplot
++ @$(MAKE) --no-print-directory -f ../tecmake.mak MF=iup_pplot
+ 
+ iupluagl:
+- @$(MAKE) --no-print-directory -f ../tecmake_compact.mak MF=iupgl
++ @$(MAKE) --no-print-directory -f ../tecmake.mak MF=iupgl
+ 
+ iupluaim:
+- @$(MAKE) --no-print-directory -f ../tecmake_compact.mak MF=iupim
++ @$(MAKE) --no-print-directory -f ../tecmake.mak MF=iupim
+ 
+ iupluaimglib:
+- @$(MAKE) --no-print-directory -f ../tecmake_compact.mak MF=iupimglib
++ @$(MAKE) --no-print-directory -f ../tecmake.mak MF=iupimglib
+diff --git a/iup/srclua5/button.lua b/iup/srclua5/button.lua
+index 946a05e..fc57b1a 100755
+--- a/iup/srclua5/button.lua
++++ b/iup/srclua5/button.lua
+@@ -3,16 +3,16 @@
+ ------------------------------------------------------------------------------
+ local ctrl = {
+ nick = "button",
+- parent = WIDGET,
++ parent = iup.WIDGET,
+ creation = "S-",
+ callback = {
+ action = "", 
+ }
+ } 
+ 
+-function ctrl.createElement(class, arg)
+- return Button(arg.title)
++function ctrl.createElement(class, param)
++ return iup.Button(param.title)
+ end
+ 
+-iupRegisterWidget(ctrl)
+-iupSetClass(ctrl, "iup widget")
++iup.RegisterWidget(ctrl)
++iup.SetClass(ctrl, "iup widget")
+diff --git a/iup/srclua5/canvas.lua b/iup/srclua5/canvas.lua
+index 562d671..101c4f4 100755
+--- a/iup/srclua5/canvas.lua
++++ b/iup/srclua5/canvas.lua
+@@ -3,7 +3,7 @@
+ ------------------------------------------------------------------------------
+ local ctrl = {
+ nick = "canvas",
+- parent = WIDGET,
++ parent = iup.WIDGET,
+ creation = "-",
+ callback = {
+ action = "ff",
+@@ -21,9 +21,9 @@ local ctrl = {
+ }
+ }
+ 
+-function ctrl.createElement(class, arg)
+- return Canvas()
++function ctrl.createElement(class, param)
++ return iup.Canvas()
+ end
+ 
+-iupRegisterWidget(ctrl)
+-iupSetClass(ctrl, "iup widget")
++iup.RegisterWidget(ctrl)
++iup.SetClass(ctrl, "iup widget")
+diff --git a/iup/srclua5/cbox.lua b/iup/srclua5/cbox.lua
+index 3533970..81ba9be 100755
+--- a/iup/srclua5/cbox.lua
++++ b/iup/srclua5/cbox.lua
+@@ -3,7 +3,7 @@
+ ------------------------------------------------------------------------------
+ local ctrl = {
+ nick = "cbox",
+- parent = WIDGET,
++ parent = iup.WIDGET,
+ creation = "v",
+ callback = {},
+ funcname = "Cboxv",
+@@ -20,9 +20,9 @@ static int Cboxv(lua_State *L)
+ ]],
+ }
+ 
+-function ctrl.createElement(class, arg)
+- return Cboxv(arg)
++function ctrl.createElement(class, param)
++ return iup.Cboxv(param)
+ end
+ 
+-iupRegisterWidget(ctrl)
+-iupSetClass(ctrl, "iup widget")
++iup.RegisterWidget(ctrl)
++iup.SetClass(ctrl, "iup widget")
+diff --git a/iup/srclua5/cells.lua b/iup/srclua5/cells.lua
+index 9c914f2..0355b17 100755
+--- a/iup/srclua5/cells.lua
++++ b/iup/srclua5/cells.lua
+@@ -3,7 +3,7 @@
+ ------------------------------------------------------------------------------
+ local ctrl = {
+ nick = "cells",
+- parent = WIDGET,
++ parent = iup.WIDGET,
+ creation = "",
+ callback = {
+ mouseclick_cb = "nnnnnns",
+@@ -24,9 +24,9 @@ function ctrl.redraw(handle)
+ handle.repaint = "YES"
+ end
+ 
+-function ctrl.createElement(class, arg)
+- return Cells()
++function ctrl.createElement(class, param)
++ return iup.Cells()
+ end
+ 
+-iupRegisterWidget(ctrl)
+-iupSetClass(ctrl, "iup widget")
++iup.RegisterWidget(ctrl)
++iup.SetClass(ctrl, "iup widget")
+diff --git a/iup/srclua5/clipboard.lua b/iup/srclua5/clipboard.lua
+index e60b8bd..663215b 100755
+--- a/iup/srclua5/clipboard.lua
++++ b/iup/srclua5/clipboard.lua
+@@ -3,15 +3,15 @@
+ ------------------------------------------------------------------------------
+ local ctrl = {
+ nick = "clipboard",
+- parent = WIDGET,
++ parent = iup.WIDGET,
+ creation = "",
+ callback = {
+ },
+ } 
+ 
+-function ctrl.createElement(class, arg)
+- return Clipboard()
++function ctrl.createElement(class, param)
++ return iup.Clipboard()
+ end
+ 
+-iupRegisterWidget(ctrl)
+-iupSetClass(ctrl, "iup widget")
++iup.RegisterWidget(ctrl)
++iup.SetClass(ctrl, "iup widget")
+diff --git a/iup/srclua5/colorbar.lua b/iup/srclua5/colorbar.lua
+index 524d5f3..7cc07db 100755
+--- a/iup/srclua5/colorbar.lua
++++ b/iup/srclua5/colorbar.lua
+@@ -3,7 +3,7 @@
+ ------------------------------------------------------------------------------
+ local ctrl = {
+ nick = "colorbar",
+- parent = WIDGET,
++ parent = iup.WIDGET,
+ creation = "",
+ callback = {
+ select_cb = "nn",
+@@ -15,12 +15,12 @@ local ctrl = {
+ include = "iupcontrols.h",
+ }
+ 
+-PRIMARY = -1
+-SECONDARY = -2
++iup.PRIMARY = -1
++iup.SECONDARY = -2
+ 
+-function ctrl.createElement(class, arg)
+- return Colorbar(arg.action)
++function ctrl.createElement(class, param)
++ return iup.Colorbar(param.action)
+ end
+ 
+-iupRegisterWidget(ctrl)
+-iupSetClass(ctrl, "iup widget")
++iup.RegisterWidget(ctrl)
++iup.SetClass(ctrl, "iup widget")
+diff --git a/iup/srclua5/colorbrowser.lua b/iup/srclua5/colorbrowser.lua
+index 16ac58f..496ce21 100755
+--- a/iup/srclua5/colorbrowser.lua
++++ b/iup/srclua5/colorbrowser.lua
+@@ -3,7 +3,7 @@
+ ------------------------------------------------------------------------------
+ local ctrl = {
+ nick = "colorbrowser",
+- parent = WIDGET,
++ parent = iup.WIDGET,
+ creation = "",
+ callback = {
+ drag_cb = "ccc",
+@@ -13,9 +13,9 @@ local ctrl = {
+ include = "iupcontrols.h",
+ }
+ 
+-function ctrl.createElement(class, arg)
+- return ColorBrowser(arg.action)
++function ctrl.createElement(class, param)
++ return iup.ColorBrowser(param.action)
+ end
+ 
+-iupRegisterWidget(ctrl)
+-iupSetClass(ctrl, "iup widget")
++iup.RegisterWidget(ctrl)
++iup.SetClass(ctrl, "iup widget")
+diff --git a/iup/srclua5/colordlg.lua b/iup/srclua5/colordlg.lua
+index 6eea53b..d6a71a4 100755
+--- a/iup/srclua5/colordlg.lua
++++ b/iup/srclua5/colordlg.lua
+@@ -3,24 +3,24 @@
+ ------------------------------------------------------------------------------
+ local ctrl = {
+ nick = "colordlg",
+- parent = WIDGET,
++ parent = iup.WIDGET,
+ creation = "",
+ funcname = "ColorDlg",
+ callback = {}
+ } 
+ 
+ function ctrl.popup(handle, x, y)
+- Popup(handle,x,y)
++ iup.Popup(handle,x,y)
+ end
+ 
+ function ctrl.destroy(handle)
+- return Destroy(handle)
++ return iup.Destroy(handle)
+ end
+ 
+-function ctrl.createElement(class, arg)
+- return ColorDlg()
++function ctrl.createElement(class, param)
++ return iup.ColorDlg()
+ end
+ 
+-iupRegisterWidget(ctrl)
+-iupSetClass(ctrl, "iup widget")
++iup.RegisterWidget(ctrl)
++iup.SetClass(ctrl, "iup widget")
+ 
+diff --git a/iup/srclua5/config.mak b/iup/srclua5/config.mak
+index 7979f0e..921aa29 100755
+--- a/iup/srclua5/config.mak
++++ b/iup/srclua5/config.mak
+@@ -17,7 +17,7 @@ CTRLUA = button.lua canvas.lua dialog.lua colordlg.lua clipboard.lua \
+ item.lua image.lua imagergb.lua imagergba.lua label.lua \
+ menu.lua multiline.lua list.lua separator.lua user.lua \
+ submenu.lua text.lua toggle.lua vbox.lua zbox.lua timer.lua \
+- sbox.lua spin.lua spinbox.lua cbox.lua messagedlg.lua \
++ sbox.lua split.lua spin.lua spinbox.lua cbox.lua messagedlg.lua \
+ radio.lua val.lua tabs.lua fontdlg.lua tree.lua progressbar.lua
+ 
+ GC := $(addsuffix .c, $(basename $(CTRLUA)))
+diff --git a/iup/srclua5/constants.lua b/iup/srclua5/constants.lua
+index 9a72f6a..2a1e76f 100755
+--- a/iup/srclua5/constants.lua
++++ b/iup/srclua5/constants.lua
+@@ -3,70 +3,70 @@
+ ----------------------------------------------------------------------------
+ -- Common return values 
+ ----------------------------------------------------------------------------
+-ERROR = 1
+-NOERROR = 0
+-OPENED = -1
+-INVALID = -1
++iup.ERROR = 1
++iup.NOERROR = 0
++iup.OPENED = -1
++iup.INVALID = -1
+ 
+ ----------------------------------------------------------------------------
+ -- Callback return values 
+ ----------------------------------------------------------------------------
+-IGNORE = -1
+-DEFAULT = -2
+-CLOSE = -3
+-CONTINUE = -4
++iup.IGNORE = -1
++iup.DEFAULT = -2
++iup.CLOSE = -3
++iup.CONTINUE = -4
+ 
+ ----------------------------------------------------------------------------
+ -- IupPopup e IupShowXY 
+ ------------------------------- \ No newline at end of file