]> git.sesse.net Git - vlc/commitdiff
* all: brand new skins interface ( still _experimental_) for x11 and
authorCyril Deguet <asmax@videolan.org>
Sat, 3 Jan 2004 23:31:34 +0000 (23:31 +0000)
committerCyril Deguet <asmax@videolan.org>
Sat, 3 Jan 2004 23:31:34 +0000 (23:31 +0000)
  win32, by ipkiss and myself...
 Among the features:
 - framework rewritten from scratch, heavily based on design patterns
  => new controls can be (hopefully) created more easily, portability
  to other OS is better, and the interface is less dependant from
  the vlc core
 - new concept of "layout", to provide a window with several different
  views (as in winamp3 skins)
 - controls can now be placed at a relative position to the edges of
  a window, which allow controls and layouts to be resizable (e.g
  for the playlist window)
 - Use of libpng and libfreetype2 for better portability between x11 and
   win32 => ttf fonts and antialiasing
 - New DTD for the xml theme ( *it will probably change again* )
 - Very very beginning of scripting in the xml file
 - And many things I miss
 - And probably many bugs ;)

175 files changed:
modules/gui/skins2/Modules.am [new file with mode: 0644]
modules/gui/skins2/commands/async_queue.cpp [new file with mode: 0644]
modules/gui/skins2/commands/async_queue.hpp [new file with mode: 0644]
modules/gui/skins2/commands/cmd_add_item.cpp [new file with mode: 0755]
modules/gui/skins2/commands/cmd_add_item.hpp [new file with mode: 0755]
modules/gui/skins2/commands/cmd_change_skin.cpp [new file with mode: 0644]
modules/gui/skins2/commands/cmd_change_skin.hpp [new file with mode: 0644]
modules/gui/skins2/commands/cmd_dialogs.hpp [new file with mode: 0755]
modules/gui/skins2/commands/cmd_dummy.hpp [new file with mode: 0644]
modules/gui/skins2/commands/cmd_generic.hpp [new file with mode: 0644]
modules/gui/skins2/commands/cmd_input.cpp [new file with mode: 0644]
modules/gui/skins2/commands/cmd_input.hpp [new file with mode: 0644]
modules/gui/skins2/commands/cmd_layout.cpp [new file with mode: 0755]
modules/gui/skins2/commands/cmd_layout.hpp [new file with mode: 0755]
modules/gui/skins2/commands/cmd_notify_playlist.cpp [new file with mode: 0644]
modules/gui/skins2/commands/cmd_notify_playlist.hpp [new file with mode: 0644]
modules/gui/skins2/commands/cmd_on_top.cpp [new file with mode: 0644]
modules/gui/skins2/commands/cmd_on_top.hpp [new file with mode: 0644]
modules/gui/skins2/commands/cmd_playlist.cpp [new file with mode: 0755]
modules/gui/skins2/commands/cmd_playlist.hpp [new file with mode: 0755]
modules/gui/skins2/commands/cmd_quit.cpp [new file with mode: 0644]
modules/gui/skins2/commands/cmd_quit.hpp [new file with mode: 0644]
modules/gui/skins2/commands/cmd_resize.cpp [new file with mode: 0644]
modules/gui/skins2/commands/cmd_resize.hpp [new file with mode: 0644]
modules/gui/skins2/commands/cmd_show_window.hpp [new file with mode: 0755]
modules/gui/skins2/controls/ctrl_button.cpp [new file with mode: 0755]
modules/gui/skins2/controls/ctrl_button.hpp [new file with mode: 0644]
modules/gui/skins2/controls/ctrl_checkbox.cpp [new file with mode: 0755]
modules/gui/skins2/controls/ctrl_checkbox.hpp [new file with mode: 0644]
modules/gui/skins2/controls/ctrl_flat.hpp [new file with mode: 0644]
modules/gui/skins2/controls/ctrl_generic.cpp [new file with mode: 0755]
modules/gui/skins2/controls/ctrl_generic.hpp [new file with mode: 0644]
modules/gui/skins2/controls/ctrl_image.cpp [new file with mode: 0755]
modules/gui/skins2/controls/ctrl_image.hpp [new file with mode: 0644]
modules/gui/skins2/controls/ctrl_list.cpp [new file with mode: 0644]
modules/gui/skins2/controls/ctrl_list.hpp [new file with mode: 0644]
modules/gui/skins2/controls/ctrl_move.cpp [new file with mode: 0755]
modules/gui/skins2/controls/ctrl_move.hpp [new file with mode: 0644]
modules/gui/skins2/controls/ctrl_radialslider.cpp [new file with mode: 0644]
modules/gui/skins2/controls/ctrl_radialslider.hpp [new file with mode: 0644]
modules/gui/skins2/controls/ctrl_resize.cpp [new file with mode: 0755]
modules/gui/skins2/controls/ctrl_resize.hpp [new file with mode: 0644]
modules/gui/skins2/controls/ctrl_slider.cpp [new file with mode: 0644]
modules/gui/skins2/controls/ctrl_slider.hpp [new file with mode: 0755]
modules/gui/skins2/controls/ctrl_text.cpp [new file with mode: 0755]
modules/gui/skins2/controls/ctrl_text.hpp [new file with mode: 0644]
modules/gui/skins2/events/evt_enter.hpp [new file with mode: 0644]
modules/gui/skins2/events/evt_focus.hpp [new file with mode: 0644]
modules/gui/skins2/events/evt_generic.hpp [new file with mode: 0644]
modules/gui/skins2/events/evt_input.cpp [new file with mode: 0644]
modules/gui/skins2/events/evt_input.hpp [new file with mode: 0644]
modules/gui/skins2/events/evt_key.cpp [new file with mode: 0755]
modules/gui/skins2/events/evt_key.hpp [new file with mode: 0644]
modules/gui/skins2/events/evt_leave.hpp [new file with mode: 0644]
modules/gui/skins2/events/evt_motion.hpp [new file with mode: 0644]
modules/gui/skins2/events/evt_mouse.cpp [new file with mode: 0755]
modules/gui/skins2/events/evt_mouse.hpp [new file with mode: 0644]
modules/gui/skins2/events/evt_refresh.hpp [new file with mode: 0644]
modules/gui/skins2/events/evt_scroll.cpp [new file with mode: 0755]
modules/gui/skins2/events/evt_scroll.hpp [new file with mode: 0644]
modules/gui/skins2/events/evt_special.cpp [new file with mode: 0755]
modules/gui/skins2/events/evt_special.hpp [new file with mode: 0644]
modules/gui/skins2/parser/builder.cpp [new file with mode: 0755]
modules/gui/skins2/parser/builder.hpp [new file with mode: 0644]
modules/gui/skins2/parser/builder_data.hpp [new file with mode: 0644]
modules/gui/skins2/parser/flex.c [new file with mode: 0644]
modules/gui/skins2/parser/gen.sh [new file with mode: 0755]
modules/gui/skins2/parser/gen_builder.py [new file with mode: 0755]
modules/gui/skins2/parser/interpreter.cpp [new file with mode: 0644]
modules/gui/skins2/parser/interpreter.hpp [new file with mode: 0644]
modules/gui/skins2/parser/parser_context.hpp [new file with mode: 0644]
modules/gui/skins2/parser/skin.act [new file with mode: 0644]
modules/gui/skins2/parser/skin.dtd [new file with mode: 0644]
modules/gui/skins2/parser/skin.h [new file with mode: 0644]
modules/gui/skins2/parser/skin.l [new file with mode: 0644]
modules/gui/skins2/parser/wrappers.cpp [new file with mode: 0644]
modules/gui/skins2/parser/wrappers.h [new file with mode: 0644]
modules/gui/skins2/src/anchor.cpp [new file with mode: 0755]
modules/gui/skins2/src/anchor.hpp [new file with mode: 0644]
modules/gui/skins2/src/dialogs.cpp [new file with mode: 0644]
modules/gui/skins2/src/dialogs.hpp [new file with mode: 0644]
modules/gui/skins2/src/ft2_bitmap.cpp [new file with mode: 0644]
modules/gui/skins2/src/ft2_bitmap.hpp [new file with mode: 0644]
modules/gui/skins2/src/ft2_font.cpp [new file with mode: 0644]
modules/gui/skins2/src/ft2_font.hpp [new file with mode: 0644]
modules/gui/skins2/src/generic_bitmap.hpp [new file with mode: 0644]
modules/gui/skins2/src/generic_font.hpp [new file with mode: 0644]
modules/gui/skins2/src/generic_layout.cpp [new file with mode: 0644]
modules/gui/skins2/src/generic_layout.hpp [new file with mode: 0644]
modules/gui/skins2/src/generic_window.cpp [new file with mode: 0644]
modules/gui/skins2/src/generic_window.hpp [new file with mode: 0644]
modules/gui/skins2/src/logger.cpp [new file with mode: 0644]
modules/gui/skins2/src/logger.hpp [new file with mode: 0644]
modules/gui/skins2/src/os_factory.cpp [new file with mode: 0644]
modules/gui/skins2/src/os_factory.hpp [new file with mode: 0644]
modules/gui/skins2/src/os_graphics.hpp [new file with mode: 0644]
modules/gui/skins2/src/os_loop.hpp [new file with mode: 0644]
modules/gui/skins2/src/os_timer.hpp [new file with mode: 0644]
modules/gui/skins2/src/os_tooltip.hpp [new file with mode: 0644]
modules/gui/skins2/src/os_window.hpp [new file with mode: 0644]
modules/gui/skins2/src/png_bitmap.cpp [new file with mode: 0644]
modules/gui/skins2/src/png_bitmap.hpp [new file with mode: 0644]
modules/gui/skins2/src/scaled_bitmap.cpp [new file with mode: 0644]
modules/gui/skins2/src/scaled_bitmap.hpp [new file with mode: 0644]
modules/gui/skins2/src/skin_common.hpp [new file with mode: 0644]
modules/gui/skins2/src/skin_main.cpp [new file with mode: 0644]
modules/gui/skins2/src/theme.cpp [new file with mode: 0755]
modules/gui/skins2/src/theme.hpp [new file with mode: 0755]
modules/gui/skins2/src/theme_loader.cpp [new file with mode: 0755]
modules/gui/skins2/src/theme_loader.hpp [new file with mode: 0755]
modules/gui/skins2/src/tooltip.cpp [new file with mode: 0644]
modules/gui/skins2/src/tooltip.hpp [new file with mode: 0644]
modules/gui/skins2/src/var_manager.cpp [new file with mode: 0644]
modules/gui/skins2/src/var_manager.hpp [new file with mode: 0644]
modules/gui/skins2/src/vlcproc.cpp [new file with mode: 0755]
modules/gui/skins2/src/vlcproc.hpp [new file with mode: 0755]
modules/gui/skins2/src/window_manager.cpp [new file with mode: 0755]
modules/gui/skins2/src/window_manager.hpp [new file with mode: 0644]
modules/gui/skins2/utils/bezier.cpp [new file with mode: 0644]
modules/gui/skins2/utils/bezier.hpp [new file with mode: 0644]
modules/gui/skins2/utils/fsm.cpp [new file with mode: 0755]
modules/gui/skins2/utils/fsm.hpp [new file with mode: 0644]
modules/gui/skins2/utils/observer.hpp [new file with mode: 0644]
modules/gui/skins2/utils/pointer.hpp [new file with mode: 0644]
modules/gui/skins2/utils/position.cpp [new file with mode: 0644]
modules/gui/skins2/utils/position.hpp [new file with mode: 0644]
modules/gui/skins2/utils/ustring.cpp [new file with mode: 0644]
modules/gui/skins2/utils/ustring.hpp [new file with mode: 0644]
modules/gui/skins2/utils/var_bool.cpp [new file with mode: 0755]
modules/gui/skins2/utils/var_bool.hpp [new file with mode: 0755]
modules/gui/skins2/utils/var_list.cpp [new file with mode: 0644]
modules/gui/skins2/utils/var_list.hpp [new file with mode: 0644]
modules/gui/skins2/utils/var_percent.cpp [new file with mode: 0644]
modules/gui/skins2/utils/var_percent.hpp [new file with mode: 0644]
modules/gui/skins2/utils/var_text.cpp [new file with mode: 0755]
modules/gui/skins2/utils/var_text.hpp [new file with mode: 0755]
modules/gui/skins2/utils/variable.hpp [new file with mode: 0644]
modules/gui/skins2/vars/playlist.cpp [new file with mode: 0644]
modules/gui/skins2/vars/playlist.hpp [new file with mode: 0644]
modules/gui/skins2/vars/time.cpp [new file with mode: 0755]
modules/gui/skins2/vars/time.hpp [new file with mode: 0755]
modules/gui/skins2/vars/vlcvars.cpp [new file with mode: 0644]
modules/gui/skins2/vars/vlcvars.hpp [new file with mode: 0644]
modules/gui/skins2/vars/volume.cpp [new file with mode: 0644]
modules/gui/skins2/vars/volume.hpp [new file with mode: 0755]
modules/gui/skins2/win32/win32_dragdrop.cpp [new file with mode: 0755]
modules/gui/skins2/win32/win32_dragdrop.hpp [new file with mode: 0755]
modules/gui/skins2/win32/win32_factory.cpp [new file with mode: 0644]
modules/gui/skins2/win32/win32_factory.hpp [new file with mode: 0644]
modules/gui/skins2/win32/win32_graphics.cpp [new file with mode: 0755]
modules/gui/skins2/win32/win32_graphics.hpp [new file with mode: 0644]
modules/gui/skins2/win32/win32_loop.cpp [new file with mode: 0755]
modules/gui/skins2/win32/win32_loop.hpp [new file with mode: 0644]
modules/gui/skins2/win32/win32_timer.cpp [new file with mode: 0644]
modules/gui/skins2/win32/win32_timer.hpp [new file with mode: 0644]
modules/gui/skins2/win32/win32_tooltip.cpp [new file with mode: 0755]
modules/gui/skins2/win32/win32_tooltip.hpp [new file with mode: 0644]
modules/gui/skins2/win32/win32_window.cpp [new file with mode: 0644]
modules/gui/skins2/win32/win32_window.hpp [new file with mode: 0644]
modules/gui/skins2/x11/x11_display.cpp [new file with mode: 0644]
modules/gui/skins2/x11/x11_display.hpp [new file with mode: 0644]
modules/gui/skins2/x11/x11_dragdrop.cpp [new file with mode: 0755]
modules/gui/skins2/x11/x11_dragdrop.hpp [new file with mode: 0755]
modules/gui/skins2/x11/x11_factory.cpp [new file with mode: 0644]
modules/gui/skins2/x11/x11_factory.hpp [new file with mode: 0644]
modules/gui/skins2/x11/x11_graphics.cpp [new file with mode: 0644]
modules/gui/skins2/x11/x11_graphics.hpp [new file with mode: 0644]
modules/gui/skins2/x11/x11_loop.cpp [new file with mode: 0644]
modules/gui/skins2/x11/x11_loop.hpp [new file with mode: 0644]
modules/gui/skins2/x11/x11_timer.cpp [new file with mode: 0644]
modules/gui/skins2/x11/x11_timer.hpp [new file with mode: 0644]
modules/gui/skins2/x11/x11_tooltip.cpp [new file with mode: 0644]
modules/gui/skins2/x11/x11_tooltip.hpp [new file with mode: 0644]
modules/gui/skins2/x11/x11_window.cpp [new file with mode: 0644]
modules/gui/skins2/x11/x11_window.hpp [new file with mode: 0644]

diff --git a/modules/gui/skins2/Modules.am b/modules/gui/skins2/Modules.am
new file mode 100644 (file)
index 0000000..3e631d4
--- /dev/null
@@ -0,0 +1,179 @@
+SOURCES_skins = \
+       commands/async_queue.cpp \
+       commands/async_queue.hpp \
+       commands/cmd_add_item.cpp \
+       commands/cmd_add_item.hpp \
+       commands/cmd_generic.hpp \
+       commands/cmd_change_skin.cpp \
+       commands/cmd_change_skin.hpp \
+       commands/cmd_dialogs.hpp \
+       commands/cmd_input.cpp \
+       commands/cmd_input.hpp \
+       commands/cmd_layout.cpp \
+       commands/cmd_layout.hpp \
+       commands/cmd_notify_playlist.cpp \
+       commands/cmd_notify_playlist.hpp \
+       commands/cmd_on_top.cpp \
+       commands/cmd_on_top.hpp \
+       commands/cmd_playlist.cpp \
+       commands/cmd_playlist.hpp \
+       commands/cmd_quit.cpp \
+       commands/cmd_quit.hpp \
+       commands/cmd_resize.cpp \
+       commands/cmd_resize.hpp \
+       commands/cmd_show_window.hpp \
+       \
+       controls/ctrl_button.cpp \
+       controls/ctrl_button.hpp \
+       controls/ctrl_checkbox.cpp \
+       controls/ctrl_checkbox.hpp \
+       controls/ctrl_flat.hpp \
+       controls/ctrl_generic.cpp \
+       controls/ctrl_generic.hpp \
+       controls/ctrl_image.cpp \
+       controls/ctrl_image.hpp \
+       controls/ctrl_list.cpp \
+       controls/ctrl_list.hpp \
+       controls/ctrl_move.cpp \
+       controls/ctrl_move.hpp \
+       controls/ctrl_resize.cpp \
+       controls/ctrl_resize.hpp \
+       controls/ctrl_slider.cpp \
+       controls/ctrl_slider.hpp \
+       controls/ctrl_radialslider.cpp \
+       controls/ctrl_radialslider.hpp \
+       controls/ctrl_text.hpp \
+       controls/ctrl_text.cpp \
+       \
+       events/evt_enter.hpp \
+       events/evt_generic.hpp \
+       events/evt_focus.hpp \
+       events/evt_input.cpp \
+       events/evt_input.hpp \
+       events/evt_key.cpp \
+       events/evt_key.hpp \
+       events/evt_leave.hpp \
+       events/evt_motion.hpp \
+       events/evt_mouse.cpp \
+       events/evt_mouse.hpp \
+       events/evt_refresh.hpp \
+       events/evt_special.cpp \
+       events/evt_special.hpp \
+       events/evt_scroll.cpp \
+       events/evt_scroll.hpp \
+       \
+       parser/builder.cpp \
+       parser/builder.hpp \
+       parser/builder_data.hpp \
+       parser/flex.c \
+       parser/interpreter.cpp \
+       parser/interpreter.hpp \
+       parser/parser_context.hpp \
+       parser/skin.c \
+       parser/skin.h \
+       parser/wrappers.cpp \
+       parser/wrappers.h \
+       \
+       src/anchor.cpp \
+       src/anchor.hpp \
+       src/dialogs.cpp \
+       src/dialogs.hpp \
+       src/ft2_bitmap.cpp \
+       src/ft2_bitmap.hpp \
+       src/ft2_font.cpp \
+       src/ft2_font.hpp \
+       src/generic_bitmap.hpp \
+       src/generic_font.hpp \
+       src/generic_layout.cpp \
+       src/generic_layout.hpp \
+       src/generic_window.cpp \
+       src/generic_window.hpp \
+       src/logger.cpp \
+       src/logger.hpp \
+       src/os_factory.cpp \
+       src/os_factory.hpp \
+       src/os_graphics.hpp \
+       src/os_loop.hpp \
+       src/os_timer.hpp \
+       src/os_window.hpp \
+       src/os_tooltip.hpp \
+       src/png_bitmap.cpp \
+       src/png_bitmap.hpp \
+       src/scaled_bitmap.cpp \
+       src/scaled_bitmap.hpp \
+       src/skin_main.cpp \
+       src/skin_common.hpp \
+       src/theme.cpp \
+       src/theme.hpp \
+       src/theme_loader.cpp \
+       src/theme_loader.hpp \
+       src/tooltip.cpp \
+       src/tooltip.hpp \
+       src/var_manager.cpp \
+       src/var_manager.hpp \
+       src/vlcproc.cpp \
+       src/vlcproc.hpp \
+       src/window_manager.cpp \
+       src/window_manager.hpp \
+       \
+       utils/bezier.cpp \
+       utils/bezier.hpp \
+       utils/fsm.cpp \
+       utils/fsm.hpp \
+       utils/observer.hpp \
+       utils/pointer.hpp \
+       utils/position.cpp \
+       utils/position.hpp \
+       utils/ustring.cpp \
+       utils/ustring.hpp \
+       utils/variable.hpp \
+       utils/var_bool.cpp \
+       utils/var_bool.hpp \
+       utils/var_list.cpp \
+       utils/var_list.hpp \
+       utils/var_percent.cpp \
+       utils/var_percent.hpp \
+       utils/var_text.cpp \
+       utils/var_text.hpp \
+\
+       vars/playlist.cpp \
+       vars/playlist.hpp \
+       vars/time.cpp \
+       vars/time.hpp \
+       vars/volume.cpp \
+       vars/volume.hpp \
+       vars/vlcvars.cpp \
+       vars/vlcvars.hpp \
+\
+       win32/win32_dragdrop.cpp \
+       win32/win32_dragdrop.hpp \
+       win32/win32_factory.cpp \
+       win32/win32_factory.hpp \
+       win32/win32_graphics.cpp \
+       win32/win32_graphics.hpp \
+       win32/win32_loop.cpp \
+       win32/win32_loop.hpp \
+       win32/win32_timer.cpp \
+       win32/win32_timer.hpp \
+       win32/win32_tooltip.cpp \
+       win32/win32_tooltip.hpp \
+       win32/win32_window.cpp \
+       win32/win32_window.hpp \
+       \
+       x11/x11_display.cpp \
+       x11/x11_display.hpp \
+       x11/x11_dragdrop.cpp \
+       x11/x11_dragdrop.hpp \
+       x11/x11_factory.cpp \
+       x11/x11_factory.hpp \
+       x11/x11_graphics.cpp \
+       x11/x11_graphics.hpp \
+       x11/x11_loop.cpp \
+       x11/x11_loop.hpp \
+       x11/x11_timer.cpp \
+       x11/x11_timer.hpp \
+       x11/x11_window.cpp \
+       x11/x11_window.hpp \
+       x11/x11_tooltip.cpp \
+       x11/x11_tooltip.hpp \
+       $(NULL)
diff --git a/modules/gui/skins2/commands/async_queue.cpp b/modules/gui/skins2/commands/async_queue.cpp
new file mode 100644 (file)
index 0000000..364ad56
--- /dev/null
@@ -0,0 +1,113 @@
+/*****************************************************************************
+ * async_queue.cpp
+ *****************************************************************************
+ * Copyright (C) 2003 VideoLAN
+ * $Id: async_queue.cpp,v 1.1 2004/01/03 23:31:33 asmax Exp $
+ *
+ * Authors: Cyril Deguet     <asmax@via.ecp.fr>
+ *          Olivier Teulière <ipkiss@via.ecp.fr>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111, USA.
+ *****************************************************************************/
+
+#include "async_queue.hpp"
+#include "../src/os_factory.hpp"
+#include "../src/os_timer.hpp"
+
+
+AsyncQueue::AsyncQueue( intf_thread_t *pIntf ): SkinObject( pIntf )
+{
+    // Create a timer
+    OSFactory *pOsFactory = OSFactory::instance( pIntf );
+    m_pTimer = pOsFactory->createOSTimer( Callback( this, &doFlush ) );
+
+    // Flush the queue every 10 ms
+    m_pTimer->start( 10, false );
+}
+
+
+AsyncQueue::~AsyncQueue()
+{
+}
+
+
+AsyncQueue *AsyncQueue::instance( intf_thread_t *pIntf )
+{
+    if( ! pIntf->p_sys->p_queue )
+    {
+        AsyncQueue *pQueue;
+        pQueue = new AsyncQueue( pIntf );
+        if( pQueue )
+        {
+             // Initialization succeeded
+             pIntf->p_sys->p_queue = pQueue;
+        }
+     }
+     return pIntf->p_sys->p_queue;
+}
+
+
+void AsyncQueue::destroy( intf_thread_t *pIntf )
+{
+    if( pIntf->p_sys->p_queue )
+    {
+        delete pIntf->p_sys->p_queue;
+        pIntf->p_sys->p_queue = NULL;
+    }
+}
+
+
+void AsyncQueue::push( const CmdGenericPtr &rcCommand )
+{
+    m_cmdList.push_back( rcCommand );
+}
+
+
+void AsyncQueue::remove( const string &rType )
+{
+    list<CmdGenericPtr>::iterator it;
+    for( it = m_cmdList.begin(); it != m_cmdList.end(); it++ )
+    {
+        // Remove the command if it is of the given type
+        if( (*it).get()->getType() == rType )
+        {
+            list<CmdGenericPtr>::iterator itNew = it;
+            itNew++;
+            m_cmdList.erase( it );
+            it = itNew;
+        }
+    }
+}
+
+
+void AsyncQueue::flush()
+{
+    while( m_cmdList.size() > 0 )
+    {
+        // Execute the first command in the queue
+        CmdGenericPtr &rcCommand = m_cmdList.front();
+        rcCommand.get()->execute();
+        // And remove it
+        m_cmdList.pop_front();
+    }
+}
+
+
+void AsyncQueue::doFlush( SkinObject *pObj )
+{
+    AsyncQueue *pThis = (AsyncQueue*)pObj;
+    // Flush the queue
+    pThis->flush();
+}
diff --git a/modules/gui/skins2/commands/async_queue.hpp b/modules/gui/skins2/commands/async_queue.hpp
new file mode 100644 (file)
index 0000000..8c78530
--- /dev/null
@@ -0,0 +1,71 @@
+/*****************************************************************************
+ * async_queue.hpp
+ *****************************************************************************
+ * Copyright (C) 2003 VideoLAN
+ * $Id: async_queue.hpp,v 1.1 2004/01/03 23:31:33 asmax Exp $
+ *
+ * Authors: Cyril Deguet     <asmax@via.ecp.fr>
+ *          Olivier Teulière <ipkiss@via.ecp.fr>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111, USA.
+ *****************************************************************************/
+
+#ifndef ASYNC_QUEUE_HPP
+#define ASYNC_QUEUE_HPP
+
+#include "cmd_generic.hpp"
+
+#include <list>
+#include <string>
+
+class OSTimer;
+
+
+/// Asynchronous queue for commands
+class AsyncQueue: public SkinObject
+{
+    public:
+        /// Get the instance of AsyncQueue
+        /// Returns NULL if initialization failed.
+        static AsyncQueue *instance( intf_thread_t *pIntf );
+
+        /// Destroy the instance of AsyncQueue
+        static void destroy( intf_thread_t *pIntf );
+
+        /// Add a command in the queue
+        void push( const CmdGenericPtr &rcCommand );
+
+        /// Remove the commands of the given type
+        void remove( const string &rType );
+
+        /// Flush the queue and execute the commands
+        void flush();
+
+    private:
+        /// Command queue
+        list<CmdGenericPtr> m_cmdList;
+        /// Timer
+        OSTimer *m_pTimer;
+
+        // Private because it is a singleton
+        AsyncQueue( intf_thread_t *pIntf );
+        virtual ~AsyncQueue();
+
+        /// Callback for the timer
+        static void doFlush( SkinObject *pObj );
+};
+
+
+#endif
diff --git a/modules/gui/skins2/commands/cmd_add_item.cpp b/modules/gui/skins2/commands/cmd_add_item.cpp
new file mode 100755 (executable)
index 0000000..b26c452
--- /dev/null
@@ -0,0 +1,49 @@
+/*****************************************************************************
+ * cmd_add_item.cpp
+ *****************************************************************************
+ * Copyright (C) 2003 VideoLAN
+ * $Id: cmd_add_item.cpp,v 1.1 2004/01/03 23:31:33 asmax Exp $
+ *
+ * Authors: Cyril Deguet     <asmax@via.ecp.fr>
+ *          Olivier Teulière <ipkiss@via.ecp.fr>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111, USA.
+ *****************************************************************************/
+
+#include <vlc/vlc.h>
+#include "cmd_add_item.hpp"
+
+
+void CmdAddItem::execute()
+{
+    playlist_t *pPlaylist = getIntf()->p_sys->p_playlist;
+    if( pPlaylist == NULL )
+    {
+        return;
+    }
+
+    if( m_playNow )
+    {
+        // Enqueue and play the item
+        playlist_Add( pPlaylist, m_name.c_str(), 0, 0,
+                      PLAYLIST_APPEND | PLAYLIST_GO, PLAYLIST_END );
+    }
+    else
+    {
+        // Enqueue the item only
+        playlist_Add( pPlaylist, m_name.c_str(), 0, 0,
+                      PLAYLIST_APPEND, PLAYLIST_END );
+    }
+}
diff --git a/modules/gui/skins2/commands/cmd_add_item.hpp b/modules/gui/skins2/commands/cmd_add_item.hpp
new file mode 100755 (executable)
index 0000000..1409fe7
--- /dev/null
@@ -0,0 +1,53 @@
+/*****************************************************************************
+ * cmd_add_item.hpp
+ *****************************************************************************
+ * Copyright (C) 2003 VideoLAN
+ * $Id: cmd_add_item.hpp,v 1.1 2004/01/03 23:31:33 asmax Exp $
+ *
+ * Authors: Cyril Deguet     <asmax@via.ecp.fr>
+ *          Olivier Teulière <ipkiss@via.ecp.fr>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111, USA.
+ *****************************************************************************/
+
+#ifndef CMD_ADD_ITEM_HPP
+#define CMD_ADD_ITEM_HPP
+
+#include "cmd_generic.hpp"
+#include <string>
+
+
+/// "Add item" command
+class CmdAddItem: public CmdGeneric
+{
+    public:
+        CmdAddItem( intf_thread_t *pIntf, const string &rName, bool playNow ):
+            CmdGeneric( pIntf ), m_name( rName ), m_playNow( playNow ) {}
+        virtual ~CmdAddItem() {}
+
+        /// This method does the real job of the command
+        virtual void execute();
+
+        /// Return the type of the command
+        virtual string getType() const { return "add item"; }
+
+    private:
+        /// Name of the item to enqueue
+        string m_name;
+        /// Should we play the item immediately?
+        bool m_playNow;
+};
+
+#endif
diff --git a/modules/gui/skins2/commands/cmd_change_skin.cpp b/modules/gui/skins2/commands/cmd_change_skin.cpp
new file mode 100644 (file)
index 0000000..65a4872
--- /dev/null
@@ -0,0 +1,69 @@
+/*****************************************************************************
+ * cmd_change_skin.cpp
+ *****************************************************************************
+ * Copyright (C) 2003 VideoLAN
+ * $Id: cmd_change_skin.cpp,v 1.1 2004/01/03 23:31:33 asmax Exp $
+ *
+ * Authors: Cyril Deguet     <asmax@via.ecp.fr>
+ *          Olivier Teulière <ipkiss@via.ecp.fr>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111, USA.
+ *****************************************************************************/
+
+#include "cmd_change_skin.hpp"
+#include "cmd_quit.hpp"
+#include "../src/os_factory.hpp"
+#include "../src/os_loop.hpp"
+#include "../src/theme.hpp"
+#include "../src/theme_loader.hpp"
+
+
+void CmdChangeSkin::execute()
+{
+    // Save the old theme to restore it in case of problem
+    Theme *pOldTheme = getIntf()->p_sys->p_theme;
+
+    if( pOldTheme )
+    {
+        pOldTheme->getWindowManager().hideAll();
+    }
+
+    ThemeLoader loader( getIntf() );
+    if( loader.load( m_file ) )
+    {
+        // Everything went well
+        msg_Dbg( getIntf(), "New theme successfully loaded (%s)",
+                 m_file.c_str() );
+        if( pOldTheme )
+        {
+            delete pOldTheme;
+        }
+    }
+    else if( pOldTheme )
+    {
+        msg_Err( getIntf(), "A problem occurred when loading the new theme,"
+                  " restoring the previous one" );
+        getIntf()->p_sys->p_theme = pOldTheme;
+        pOldTheme->getWindowManager().showAll();
+    }
+    else
+    {
+        msg_Err( getIntf(), "Cannot load the theme, aborting" );
+        // Quit
+        CmdQuit cmd( getIntf() );
+        cmd.execute();
+    }
+}
+
diff --git a/modules/gui/skins2/commands/cmd_change_skin.hpp b/modules/gui/skins2/commands/cmd_change_skin.hpp
new file mode 100644 (file)
index 0000000..8be56c3
--- /dev/null
@@ -0,0 +1,53 @@
+/*****************************************************************************
+ * cmd_change_skin.hpp
+ *****************************************************************************
+ * Copyright (C) 2003 VideoLAN
+ * $Id: cmd_change_skin.hpp,v 1.1 2004/01/03 23:31:33 asmax Exp $
+ *
+ * Authors: Cyril Deguet     <asmax@via.ecp.fr>
+ *          Olivier Teulière <ipkiss@via.ecp.fr>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111, USA.
+ *****************************************************************************/
+
+#ifndef CMD_CHANGE_SKIN_HPP
+#define CMD_CHANGE_SKIN_HPP
+
+#include "cmd_generic.hpp"
+
+
+class WindowManager;
+
+
+/// "Change Skin" command
+class CmdChangeSkin: public CmdGeneric
+{
+    public:
+        CmdChangeSkin( intf_thread_t *pIntf, const string &rFile ):
+            CmdGeneric( pIntf ), m_file( rFile ) {}
+        virtual ~CmdChangeSkin() {}
+
+        /// This method does the real job of the command
+        virtual void execute();
+
+        /// Return the type of the command
+        virtual string getType() const { return "change skin"; }
+
+    private:
+        /// Skin file to load
+        string m_file;
+};
+
+#endif
diff --git a/modules/gui/skins2/commands/cmd_dialogs.hpp b/modules/gui/skins2/commands/cmd_dialogs.hpp
new file mode 100755 (executable)
index 0000000..60b08bd
--- /dev/null
@@ -0,0 +1,109 @@
+/*****************************************************************************
+ * cmd_dialogs.hpp
+ *****************************************************************************
+ * Copyright (C) 2003 VideoLAN
+ * $Id: cmd_dialogs.hpp,v 1.1 2004/01/03 23:31:33 asmax Exp $
+ *
+ * Authors: Cyril Deguet     <asmax@via.ecp.fr>
+ *          Olivier Teulière <ipkiss@via.ecp.fr>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111, USA.
+ *****************************************************************************/
+
+#ifndef CMD_DIALOGS_HPP
+#define CMD_DIALOGS_HPP
+
+#include "cmd_generic.hpp"
+#include "../src/dialogs.hpp"
+#include "cmd_change_skin.hpp"
+
+
+template<int TYPE = 0> class CmdDialogs;
+
+// XXX use an enum instead
+typedef CmdDialogs<1> CmdDlgChangeSkin;
+typedef CmdDialogs<2> CmdDlgFileSimple;
+typedef CmdDialogs<3> CmdDlgFile;
+typedef CmdDialogs<4> CmdDlgDisc;
+typedef CmdDialogs<5> CmdDlgNet;
+typedef CmdDialogs<6> CmdDlgMessages;
+typedef CmdDialogs<7> CmdDlgPrefs;
+typedef CmdDialogs<8> CmdDlgFileInfo;
+typedef CmdDialogs<9> CmdDlgPopupMenu;
+typedef CmdDialogs<10> CmdDlgAdd;
+
+
+/// Generic "Open dialog" command
+template<int TYPE>
+class CmdDialogs: public CmdGeneric
+{
+    public:
+        CmdDialogs( intf_thread_t *pIntf ): CmdGeneric( pIntf ) {}
+        virtual ~CmdDialogs() {}
+
+        /// This method does the real job of the command
+        virtual void execute()
+        {
+            /// Get the dialogs provider
+            Dialogs *pDialogs = Dialogs::instance( getIntf() );
+            if( pDialogs == NULL )
+            {
+                return;
+            }
+
+            switch( TYPE )
+            {
+                case 1:
+                    pDialogs->showChangeSkin();
+                    break;
+                case 2:
+                    pDialogs->showFileSimple( true );
+                    break;
+                case 3:
+                    pDialogs->showFile( true );
+                    break;
+                case 4:
+                    pDialogs->showDisc( true );
+                    break;
+                case 5:
+                    pDialogs->showNet( true );
+                    break;
+                case 6:
+                    pDialogs->showMessages();
+                    break;
+                case 7:
+                    pDialogs->showPrefs();
+                    break;
+                case 8:
+                    pDialogs->showFileInfo();
+                    break;
+                case 9:
+                    pDialogs->showPopupMenu( true );
+                    break;
+                case 10:
+                    pDialogs->showFile( false );
+                    break;
+                default:
+                    msg_Warn( getIntf(), "Unknown dialog type" );
+                    break;
+            }
+        }
+
+        /// Return the type of the command
+        virtual string getType() const { return "dialog"; }
+};
+
+
+#endif
diff --git a/modules/gui/skins2/commands/cmd_dummy.hpp b/modules/gui/skins2/commands/cmd_dummy.hpp
new file mode 100644 (file)
index 0000000..47e18ac
--- /dev/null
@@ -0,0 +1,45 @@
+/*****************************************************************************
+ * cmd_dummy.hpp
+ *****************************************************************************
+ * Copyright (C) 2003 VideoLAN
+ * $Id: cmd_dummy.hpp,v 1.1 2004/01/03 23:31:33 asmax Exp $
+ *
+ * Authors: Cyril Deguet     <asmax@via.ecp.fr>
+ *          Olivier Teulière <ipkiss@via.ecp.fr>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111, USA.
+ *****************************************************************************/
+
+#ifndef CMD_DUMMY_HPP
+#define CMD_DUMMY_HPP
+
+#include "cmd_generic.hpp"
+
+
+/// Dummy command
+class CmdDummy: public CmdGeneric
+{
+    public:
+        CmdDummy( intf_thread_t *pIntf ): CmdGeneric( pIntf ) {}
+        virtual ~CmdDummy() {}
+
+        /// This method does the real job of the command
+        virtual void execute() {}
+
+        /// Return the type of the command
+        virtual string getType() const { return "dummy"; }
+};
+
+#endif
diff --git a/modules/gui/skins2/commands/cmd_generic.hpp b/modules/gui/skins2/commands/cmd_generic.hpp
new file mode 100644 (file)
index 0000000..d399df5
--- /dev/null
@@ -0,0 +1,67 @@
+/*****************************************************************************
+ * cmd_generic.hpp
+ *****************************************************************************
+ * Copyright (C) 2003 VideoLAN
+ * $Id: cmd_generic.hpp,v 1.1 2004/01/03 23:31:33 asmax Exp $
+ *
+ * Authors: Cyril Deguet     <asmax@via.ecp.fr>
+ *          Olivier Teulière <ipkiss@via.ecp.fr>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111, USA.
+ *****************************************************************************/
+
+#ifndef CMD_GENERIC_HPP
+#define CMD_GENERIC_HPP
+
+#include "../src/skin_common.hpp"
+#include "../utils/pointer.hpp"
+
+#include <string>
+
+
+/// Macro to define the prototype of simple commands
+#define DEFINE_COMMAND( name, type ) \
+class Cmd##name: public CmdGeneric \
+{ \
+    public: \
+        Cmd##name( intf_thread_t *pIntf ): CmdGeneric( pIntf ) {} \
+        virtual ~Cmd##name() {} \
+        virtual void execute(); \
+        virtual string getType() const { return type; } \
+\
+};
+
+
+/// Base class for skins commands
+class CmdGeneric: public SkinObject
+{
+    public:
+        virtual ~CmdGeneric() {}
+
+        /// This method does the real job of the command
+        virtual void execute() = 0;
+
+        /// Return the type of the command
+        virtual string getType() const { return ""; }
+
+    protected:
+        CmdGeneric( intf_thread_t *pIntf ): SkinObject( pIntf ) {}
+};
+
+
+typedef CountedPtr<CmdGeneric> CmdGenericPtr;
+
+
+#endif
diff --git a/modules/gui/skins2/commands/cmd_input.cpp b/modules/gui/skins2/commands/cmd_input.cpp
new file mode 100644 (file)
index 0000000..54a55ce
--- /dev/null
@@ -0,0 +1,70 @@
+/*****************************************************************************
+ * cmd_input.cpp
+ *****************************************************************************
+ * Copyright (C) 2003 VideoLAN
+ * $Id: cmd_input.cpp,v 1.1 2004/01/03 23:31:33 asmax Exp $
+ *
+ * Authors: Cyril Deguet     <asmax@via.ecp.fr>
+ *          Olivier Teulière <ipkiss@via.ecp.fr>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111, USA.
+ *****************************************************************************/
+
+#include "cmd_input.hpp"
+
+
+void CmdStop::execute()
+{
+    playlist_t *pPlaylist = getIntf()->p_sys->p_playlist;
+    if( pPlaylist == NULL )
+    {
+        return;
+    }
+
+    playlist_Stop( pPlaylist );
+}
+
+
+void CmdSlower::execute()
+{
+    input_thread_t *pInput =
+        (input_thread_t *)vlc_object_find( getIntf(), VLC_OBJECT_INPUT,
+                                           FIND_ANYWHERE );
+    if( pInput )
+    {
+        vlc_value_t val;
+        val.b_bool = VLC_TRUE;
+
+        var_Set( pInput, "rate-slower", val );
+        vlc_object_release( pInput );
+    }
+}
+
+
+void CmdFaster::execute()
+{
+    input_thread_t *pInput =
+        (input_thread_t *)vlc_object_find( getIntf(), VLC_OBJECT_INPUT,
+                                           FIND_ANYWHERE );
+    if( pInput )
+    {
+        vlc_value_t val;
+        val.b_bool = VLC_TRUE;
+
+        var_Set( pInput, "rate-faster", val );
+        vlc_object_release( pInput );
+    }
+}
+
diff --git a/modules/gui/skins2/commands/cmd_input.hpp b/modules/gui/skins2/commands/cmd_input.hpp
new file mode 100644 (file)
index 0000000..d6bd2b6
--- /dev/null
@@ -0,0 +1,36 @@
+/*****************************************************************************
+ * cmd_input.hpp
+ *****************************************************************************
+ * Copyright (C) 2003 VideoLAN
+ * $Id: cmd_input.hpp,v 1.1 2004/01/03 23:31:33 asmax Exp $
+ *
+ * Authors: Cyril Deguet     <asmax@via.ecp.fr>
+ *          Olivier Teulière <ipkiss@via.ecp.fr>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111, USA.
+ *****************************************************************************/
+
+#ifndef CMD_INPUT_HPP
+#define CMD_INPUT_HPP
+
+#include "cmd_generic.hpp"
+
+/// Commands to control the input
+DEFINE_COMMAND( Stop, "stop" )
+DEFINE_COMMAND( Slower, "slower" )
+DEFINE_COMMAND( Faster, "faster" )
+
+
+#endif
diff --git a/modules/gui/skins2/commands/cmd_layout.cpp b/modules/gui/skins2/commands/cmd_layout.cpp
new file mode 100755 (executable)
index 0000000..fe049dd
--- /dev/null
@@ -0,0 +1,59 @@
+/*****************************************************************************
+ * cmd_layout.cpp
+ *****************************************************************************
+ * Copyright (C) 2003 VideoLAN
+ * $Id: cmd_layout.cpp,v 1.1 2004/01/03 23:31:33 asmax Exp $
+ *
+ * Authors: Cyril Deguet     <asmax@via.ecp.fr>
+ *          Olivier Teulière <ipkiss@via.ecp.fr>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111, USA.
+ *****************************************************************************/
+
+#include "cmd_layout.hpp"
+#include "../src/generic_window.hpp"
+#include "../src/generic_layout.hpp"
+#include "../src/theme.hpp"
+
+
+CmdLayout::CmdLayout( intf_thread_t *pIntf, const string &windowId,
+                      const string &layoutId ):
+    CmdGeneric( pIntf ), m_windowId( windowId ), m_layoutId( layoutId )
+{
+}
+
+
+void CmdLayout::execute()
+{
+    // Get the window and the layout
+    if( !getIntf()->p_sys->p_theme )
+    {
+        return;
+    }
+    GenericWindow *pWindow =
+        getIntf()->p_sys->p_theme->getWindowById( m_windowId );
+    GenericLayout *pLayout =
+        getIntf()->p_sys->p_theme->getLayoutById( m_layoutId );
+    if( !pWindow || !pLayout )
+    {
+        msg_Err( getIntf(), "Cannot change layout (%s, %s)",
+                 m_windowId.c_str(), m_layoutId.c_str() );
+        return;
+    }
+
+    // XXX TODO: check that the layout isn't a layout of another window
+
+    pWindow->setActiveLayout( pLayout );
+}
diff --git a/modules/gui/skins2/commands/cmd_layout.hpp b/modules/gui/skins2/commands/cmd_layout.hpp
new file mode 100755 (executable)
index 0000000..cc30ec3
--- /dev/null
@@ -0,0 +1,51 @@
+/*****************************************************************************
+ * cmd_layout.hpp
+ *****************************************************************************
+ * Copyright (C) 2003 VideoLAN
+ * $Id: cmd_layout.hpp,v 1.1 2004/01/03 23:31:33 asmax Exp $
+ *
+ * Authors: Cyril Deguet     <asmax@via.ecp.fr>
+ *          Olivier Teulière <ipkiss@via.ecp.fr>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111, USA.
+ *****************************************************************************/
+
+#ifndef CMD_LAYOUT_HPP
+#define CMD_LAYOUT_HPP
+
+#include "cmd_generic.hpp"
+#include <string>
+
+
+/// "Change layout" command
+class CmdLayout: public CmdGeneric
+{
+    public:
+        CmdLayout( intf_thread_t *pIntf, const string &windowId,
+                   const string &layoutId );
+        virtual ~CmdLayout() {}
+
+        /// This method does the real job of the command
+        virtual void execute();
+
+        /// Return the type of the command
+        virtual string getType() const { return "change layout"; }
+
+    private:
+        string m_windowId;
+        string m_layoutId;
+};
+
+#endif
diff --git a/modules/gui/skins2/commands/cmd_notify_playlist.cpp b/modules/gui/skins2/commands/cmd_notify_playlist.cpp
new file mode 100644 (file)
index 0000000..92c1b17
--- /dev/null
@@ -0,0 +1,35 @@
+/*****************************************************************************
+ * cmd_notify_playlist.cpp
+ *****************************************************************************
+ * Copyright (C) 2003 VideoLAN
+ * $Id: cmd_notify_playlist.cpp,v 1.1 2004/01/03 23:31:33 asmax Exp $
+ *
+ * Authors: Cyril Deguet     <asmax@via.ecp.fr>
+ *          Olivier Teulière <ipkiss@via.ecp.fr>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111, USA.
+ *****************************************************************************/
+
+#include "cmd_notify_playlist.hpp"
+#include "../src/vlcproc.hpp"
+#include "../vars/playlist.hpp"
+
+
+void CmdNotifyPlaylist::execute()
+{
+    // Notify the playlist variable
+    Playlist &rVar = VlcProc::instance( getIntf() )->getPlaylistVar();
+    rVar.onChange();
+}
diff --git a/modules/gui/skins2/commands/cmd_notify_playlist.hpp b/modules/gui/skins2/commands/cmd_notify_playlist.hpp
new file mode 100644 (file)
index 0000000..576b9e6
--- /dev/null
@@ -0,0 +1,45 @@
+/*****************************************************************************
+ * cmd_notify_playlist.hpp
+ *****************************************************************************
+ * Copyright (C) 2003 VideoLAN
+ * $Id: cmd_notify_playlist.hpp,v 1.1 2004/01/03 23:31:33 asmax Exp $
+ *
+ * Authors: Cyril Deguet     <asmax@via.ecp.fr>
+ *          Olivier Teulière <ipkiss@via.ecp.fr>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111, USA.
+ *****************************************************************************/
+
+#ifndef CMD_NOTIFY_PLAYLIST_HPP
+#define CMD_NOTIFY_PLAYLIST_HPP
+
+#include "cmd_generic.hpp"
+
+
+/// Command to notify the playlist of a change
+class CmdNotifyPlaylist: public CmdGeneric
+{
+    public:
+        CmdNotifyPlaylist( intf_thread_t *pIntf ): CmdGeneric( pIntf ) {}
+        virtual ~CmdNotifyPlaylist() {}
+
+        /// This method does the real job of the command
+        virtual void execute();
+
+        /// Return the type of the command
+        virtual string getType() const { return "notify playlist"; }
+};
+
+#endif
diff --git a/modules/gui/skins2/commands/cmd_on_top.cpp b/modules/gui/skins2/commands/cmd_on_top.cpp
new file mode 100644 (file)
index 0000000..d6cdfa8
--- /dev/null
@@ -0,0 +1,33 @@
+/*****************************************************************************
+ * cmd_on_top.cpp
+ *****************************************************************************
+ * Copyright (C) 2003 VideoLAN
+ * $Id: cmd_on_top.cpp,v 1.1 2004/01/03 23:31:33 asmax Exp $
+ *
+ * Authors: Cyril Deguet     <asmax@via.ecp.fr>
+ *          Olivier Teulière <ipkiss@via.ecp.fr>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111, USA.
+ *****************************************************************************/
+
+#include "cmd_on_top.hpp"
+#include "../src/theme.hpp"
+#include "../src/window_manager.hpp"
+
+
+void CmdOnTop::execute()
+{
+    getIntf()->p_sys->p_theme->getWindowManager().toggleOnTop();
+}
diff --git a/modules/gui/skins2/commands/cmd_on_top.hpp b/modules/gui/skins2/commands/cmd_on_top.hpp
new file mode 100644 (file)
index 0000000..3a17f6c
--- /dev/null
@@ -0,0 +1,45 @@
+/*****************************************************************************
+ * cmd_on_top.hpp
+ *****************************************************************************
+ * Copyright (C) 2003 VideoLAN
+ * $Id: cmd_on_top.hpp,v 1.1 2004/01/03 23:31:33 asmax Exp $
+ *
+ * Authors: Cyril Deguet     <asmax@via.ecp.fr>
+ *          Olivier Teulière <ipkiss@via.ecp.fr>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111, USA.
+ *****************************************************************************/
+
+#ifndef CMD_ON_TOP_HPP
+#define CMD_ON_TOP_HPP
+
+#include "cmd_generic.hpp"
+
+
+/// "Always on top" command
+class CmdOnTop: public CmdGeneric
+{
+    public:
+        CmdOnTop( intf_thread_t *pIntf ): CmdGeneric( pIntf ) {}
+        virtual ~CmdOnTop() {}
+
+        /// This method does the real job of the command
+        virtual void execute();
+
+        /// Return the type of the command
+        virtual string getType() const { return "always on top"; }
+};
+
+#endif
diff --git a/modules/gui/skins2/commands/cmd_playlist.cpp b/modules/gui/skins2/commands/cmd_playlist.cpp
new file mode 100755 (executable)
index 0000000..599e789
--- /dev/null
@@ -0,0 +1,63 @@
+/*****************************************************************************
+ * cmd_playlist.cpp
+ *****************************************************************************
+ * Copyright (C) 2003 VideoLAN
+ * $Id: cmd_playlist.cpp,v 1.1 2004/01/03 23:31:33 asmax Exp $
+ *
+ * Authors: Cyril Deguet     <asmax@via.ecp.fr>
+ *          Olivier Teulière <ipkiss@via.ecp.fr>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111, USA.
+ *****************************************************************************/
+
+#include "cmd_playlist.hpp"
+
+
+void CmdPlaylistDel::execute()
+{
+    m_rList.delSelected();
+}
+
+
+void CmdPlaylistSort::execute()
+{
+    // XXX add the mode and type
+    playlist_t *pPlaylist = getIntf()->p_sys->p_playlist;
+    if( pPlaylist != NULL )
+    {
+        playlist_Sort( pPlaylist, SORT_TITLE, SORT_NORMAL );
+    }
+
+}
+
+
+void CmdPlaylistNext::execute()
+{
+    playlist_t *pPlaylist = getIntf()->p_sys->p_playlist;
+    if( pPlaylist != NULL )
+    {
+        playlist_Next( pPlaylist );
+    }
+}
+
+
+void CmdPlaylistPrevious::execute()
+{
+    playlist_t *pPlaylist = getIntf()->p_sys->p_playlist;
+    if( pPlaylist != NULL )
+    {
+        playlist_Prev( pPlaylist );
+    }
+}
diff --git a/modules/gui/skins2/commands/cmd_playlist.hpp b/modules/gui/skins2/commands/cmd_playlist.hpp
new file mode 100755 (executable)
index 0000000..9a68c65
--- /dev/null
@@ -0,0 +1,62 @@
+/*****************************************************************************
+ * cmd_playlist.hpp
+ *****************************************************************************
+ * Copyright (C) 2003 VideoLAN
+ * $Id: cmd_playlist.hpp,v 1.1 2004/01/03 23:31:33 asmax Exp $
+ *
+ * Authors: Cyril Deguet     <asmax@via.ecp.fr>
+ *          Olivier Teulière <ipkiss@via.ecp.fr>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111, USA.
+ *****************************************************************************/
+
+#ifndef CMD_PLAYLIST_HPP
+#define CMD_PLAYLIST_HPP
+
+#include "cmd_generic.hpp"
+#include "../utils/var_list.hpp"
+
+
+/// Command to delete the selected items from a list
+class CmdPlaylistDel: public CmdGeneric
+{
+    public:
+        CmdPlaylistDel( intf_thread_t *pIntf, VarList &rList ):
+            CmdGeneric( pIntf ), m_rList( rList ) {}
+        virtual ~CmdPlaylistDel() {}
+
+        /// This method does the real job of the command
+        virtual void execute();
+
+        /// Return the type of the command
+        virtual string getType() const { return "playlist del"; }
+
+    private:
+        /// List
+        VarList &m_rList;
+};
+
+
+/// Command to sort the playlist
+DEFINE_COMMAND( PlaylistSort, "playlist sort" )
+
+/// Command to jump to the next item
+DEFINE_COMMAND( PlaylistNext, "playlist next" )
+
+/// Command to jump to the previous item
+DEFINE_COMMAND( PlaylistPrevious, "playlist previous" )
+
+
+#endif
diff --git a/modules/gui/skins2/commands/cmd_quit.cpp b/modules/gui/skins2/commands/cmd_quit.cpp
new file mode 100644 (file)
index 0000000..a0aec39
--- /dev/null
@@ -0,0 +1,37 @@
+/*****************************************************************************
+ * cmd_quit.cpp
+ *****************************************************************************
+ * Copyright (C) 2003 VideoLAN
+ * $Id: cmd_quit.cpp,v 1.1 2004/01/03 23:31:33 asmax Exp $
+ *
+ * Authors: Cyril Deguet     <asmax@via.ecp.fr>
+ *          Olivier Teulière <ipkiss@via.ecp.fr>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111, USA.
+ *****************************************************************************/
+
+#include "cmd_quit.hpp"
+#include "../src/os_factory.hpp"
+#include "../src/os_loop.hpp"
+
+
+void CmdQuit::execute()
+{
+    // Get the instance of OSFactory
+    OSFactory *pOsFactory = OSFactory::instance( getIntf() );
+
+    // Exit the main OS loop
+    pOsFactory->getOSLoop()->exit();
+}
diff --git a/modules/gui/skins2/commands/cmd_quit.hpp b/modules/gui/skins2/commands/cmd_quit.hpp
new file mode 100644 (file)
index 0000000..0055bf4
--- /dev/null
@@ -0,0 +1,45 @@
+/*****************************************************************************
+ * cmd_quit.hpp
+ *****************************************************************************
+ * Copyright (C) 2003 VideoLAN
+ * $Id: cmd_quit.hpp,v 1.1 2004/01/03 23:31:33 asmax Exp $
+ *
+ * Authors: Cyril Deguet     <asmax@via.ecp.fr>
+ *          Olivier Teulière <ipkiss@via.ecp.fr>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111, USA.
+ *****************************************************************************/
+
+#ifndef CMD_QUIT_HPP
+#define CMD_QUIT_HPP
+
+#include "cmd_generic.hpp"
+
+
+/// "Quit" command
+class CmdQuit: public CmdGeneric
+{
+    public:
+        CmdQuit( intf_thread_t *pIntf ): CmdGeneric( pIntf ) {}
+        virtual ~CmdQuit() {}
+
+        /// This method does the real job of the command
+        virtual void execute();
+
+        /// Return the type of the command
+        virtual string getType() const { return "quit"; }
+};
+
+#endif
diff --git a/modules/gui/skins2/commands/cmd_resize.cpp b/modules/gui/skins2/commands/cmd_resize.cpp
new file mode 100644 (file)
index 0000000..1be6a25
--- /dev/null
@@ -0,0 +1,41 @@
+/*****************************************************************************
+ * cmd_resize.cpp
+ *****************************************************************************
+ * Copyright (C) 2003 VideoLAN
+ * $Id: cmd_resize.cpp,v 1.1 2004/01/03 23:31:33 asmax Exp $
+ *
+ * Authors: Cyril Deguet     <asmax@via.ecp.fr>
+ *          Olivier Teulière <ipkiss@via.ecp.fr>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111, USA.
+ *****************************************************************************/
+
+#include "cmd_resize.hpp"
+#include "../src/generic_layout.hpp"
+
+
+CmdResize::CmdResize( intf_thread_t *pIntf, GenericLayout &rLayout, int width,
+                      int height ):
+    CmdGeneric( pIntf ), m_rLayout( rLayout ), m_width( width ),
+    m_height( height )
+{
+}
+
+
+void CmdResize::execute()
+{
+    // Resize the layout
+    m_rLayout.resize( m_width, m_height );
+}
diff --git a/modules/gui/skins2/commands/cmd_resize.hpp b/modules/gui/skins2/commands/cmd_resize.hpp
new file mode 100644 (file)
index 0000000..04fbfbe
--- /dev/null
@@ -0,0 +1,53 @@
+/*****************************************************************************
+ * cmd_resize.hpp
+ *****************************************************************************
+ * Copyright (C) 2003 VideoLAN
+ * $Id: cmd_resize.hpp,v 1.1 2004/01/03 23:31:33 asmax Exp $
+ *
+ * Authors: Cyril Deguet     <asmax@via.ecp.fr>
+ *          Olivier Teulière <ipkiss@via.ecp.fr>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111, USA.
+ *****************************************************************************/
+
+#ifndef CMD_RESIZE_HPP
+#define CMD_RESIZE_HPP
+
+#include "cmd_generic.hpp"
+
+class GenericLayout;
+
+
+/// Command to resize a layout
+class CmdResize: public CmdGeneric
+{
+    public:
+        /// Resize the given layout
+        CmdResize( intf_thread_t *pIntf, GenericLayout &rLayout, int width,
+                   int height );
+        virtual ~CmdResize() {}
+
+        /// This method does the real job of the command
+        virtual void execute();
+
+        /// Return the type of the command
+        virtual string getType() const { return "resize"; }
+
+    private:
+        GenericLayout &m_rLayout;
+        int m_width, m_height;
+};
+
+#endif
diff --git a/modules/gui/skins2/commands/cmd_show_window.hpp b/modules/gui/skins2/commands/cmd_show_window.hpp
new file mode 100755 (executable)
index 0000000..1696340
--- /dev/null
@@ -0,0 +1,58 @@
+/*****************************************************************************
+ * cmd_show_window.hpp
+ *****************************************************************************
+ * Copyright (C) 2003 VideoLAN
+ * $Id: cmd_show_window.hpp,v 1.1 2004/01/03 23:31:33 asmax Exp $
+ *
+ * Authors: Cyril Deguet     <asmax@via.ecp.fr>
+ *          Olivier Teulière <ipkiss@via.ecp.fr>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111, USA.
+ *****************************************************************************/
+
+#ifndef CMD_SHOW_WINDOW_HPP
+#define CMD_SHOW_WINDOW_HPP
+
+#include "cmd_generic.hpp"
+#include "../utils/var_bool.hpp"
+
+
+template<bool newValue> class CmdShowHideWindow;
+
+typedef CmdShowHideWindow<true> CmdShowWindow;
+typedef CmdShowHideWindow<false> CmdHideWindow;
+
+
+/// "Show/Hide window" command
+template<bool newValue>
+class CmdShowHideWindow: public CmdGeneric
+{
+    public:
+        CmdShowHideWindow( intf_thread_t *pIntf, VarBool &rVariable ):
+            CmdGeneric( pIntf ), m_rVariable( rVariable ) {}
+        virtual ~CmdShowHideWindow() {}
+
+        /// This method does the real job of the command
+        virtual void execute() { m_rVariable.set( newValue ); }
+
+        /// Return the type of the command
+        virtual string getType() const { return "show/hide window"; }
+
+    private:
+        /// Reference to the observed variable
+        VarBool &m_rVariable;
+};
+
+#endif
diff --git a/modules/gui/skins2/controls/ctrl_button.cpp b/modules/gui/skins2/controls/ctrl_button.cpp
new file mode 100755 (executable)
index 0000000..7ef3a35
--- /dev/null
@@ -0,0 +1,202 @@
+/*****************************************************************************
+ * ctrl_button.cpp
+ *****************************************************************************
+ * Copyright (C) 2003 VideoLAN
+ * $Id: ctrl_button.cpp,v 1.1 2004/01/03 23:31:33 asmax Exp $
+ *
+ * Authors: Cyril Deguet     <asmax@via.ecp.fr>
+ *          Olivier Teulière <ipkiss@via.ecp.fr>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111, USA.
+ *****************************************************************************/
+
+#include "ctrl_button.hpp"
+#include "../events/evt_generic.hpp"
+#include "../src/generic_bitmap.hpp"
+#include "../src/os_factory.hpp"
+#include "../src/os_graphics.hpp"
+#include "../commands/cmd_generic.hpp"
+
+
+CtrlButton::CtrlButton( intf_thread_t *pIntf, const GenericBitmap &rBmpUp,
+                        const GenericBitmap &rBmpOver,
+                        const GenericBitmap &rBmpDown, CmdGeneric &rCommand,
+                        const UString &rTooltip, const UString &rHelp ):
+    CtrlGeneric( pIntf, rHelp ), m_fsm( pIntf ), m_rCommand( rCommand ),
+    m_tooltip( rTooltip ),
+    m_cmdUpOverDownOver( this, &transUpOverDownOver ),
+    m_cmdDownOverUpOver( this, &transDownOverUpOver ),
+    m_cmdDownOverDown( this, &transDownOverDown ),
+    m_cmdDownDownOver( this, &transDownDownOver ),
+    m_cmdUpOverUp( this, &transUpOverUp ),
+    m_cmdUpUpOver( this, &transUpUpOver ),
+    m_cmdDownUp( this, &transDownUp ),
+    m_cmdUpHidden( this, &transUpHidden ),
+    m_cmdHiddenUp( this, &transHiddenUp )
+{
+    // Build the images of the button
+    OSFactory *pOsFactory = OSFactory::instance( pIntf );
+    m_pImgUp = pOsFactory->createOSGraphics( rBmpUp.getWidth(),
+                                             rBmpUp.getHeight() );
+    m_pImgUp->drawBitmap( rBmpUp, 0, 0 );
+    m_pImgDown = pOsFactory->createOSGraphics( rBmpDown.getWidth(),
+                                               rBmpDown.getHeight() );
+    m_pImgDown->drawBitmap( rBmpDown, 0, 0 );
+    m_pImgOver = pOsFactory->createOSGraphics( rBmpOver.getWidth(),
+                                               rBmpOver.getHeight() );
+    m_pImgOver->drawBitmap( rBmpOver, 0, 0 );
+
+    // States
+    m_fsm.addState( "up" );
+    m_fsm.addState( "down" );
+    m_fsm.addState( "upOver" );
+    m_fsm.addState( "downOver" );
+    m_fsm.addState( "hidden" );
+
+    // Transitions
+    m_fsm.addTransition( "upOver", "mouse:left:down", "downOver",
+                         &m_cmdUpOverDownOver );
+    m_fsm.addTransition( "downOver", "mouse:left:up", "upOver",
+                         &m_cmdDownOverUpOver );
+    m_fsm.addTransition( "downOver", "leave", "down", &m_cmdDownOverDown );
+    m_fsm.addTransition( "down", "enter", "downOver", &m_cmdDownDownOver );
+    m_fsm.addTransition( "upOver", "leave", "up", &m_cmdUpOverUp );
+    m_fsm.addTransition( "up", "enter", "upOver", &m_cmdUpUpOver );
+    m_fsm.addTransition( "down", "mouse:left:up", "up", &m_cmdDownUp );
+    // XXX: It would be easy to use a "ANY" initial state to handle these
+    // four lines in only one. But till now it isn't worthwhile...
+    m_fsm.addTransition( "up", "special:hide", "hidden", &m_cmdUpHidden );
+    m_fsm.addTransition( "down", "special:hide", "hidden", &m_cmdUpHidden );
+    m_fsm.addTransition( "upOver", "special:hide", "hidden", &m_cmdUpHidden );
+    m_fsm.addTransition( "downOver", "special:hide", "hidden", &m_cmdUpHidden );
+    m_fsm.addTransition( "hidden", "special:show", "up", &m_cmdHiddenUp );
+
+    // Initial state
+    m_fsm.setState( "up" );
+    m_pImg = m_pImgUp;
+}
+
+
+CtrlButton::~CtrlButton()
+{
+    SKINS_DELETE( m_pImgUp );
+    SKINS_DELETE( m_pImgDown );
+    SKINS_DELETE( m_pImgOver );
+}
+
+
+void CtrlButton::handleEvent( EvtGeneric &rEvent )
+{
+    m_fsm.handleTransition( rEvent.getAsString() );
+}
+
+
+bool CtrlButton::mouseOver( int x, int y ) const
+{
+    if( m_pImg )
+    {
+        return m_pImg->hit( x, y );
+    }
+    else
+    {
+        return false;
+    }
+}
+
+
+void CtrlButton::draw( OSGraphics &rImage, int xDest, int yDest )
+{
+    if( m_pImg )
+    {
+        // Draw the current image
+        rImage.drawGraphics( *m_pImg, 0, 0, xDest, yDest );
+    }
+}
+
+
+void CtrlButton::transUpOverDownOver( SkinObject *pCtrl )
+{
+    CtrlButton *pThis = (CtrlButton*)pCtrl;
+    pThis->captureMouse();
+    pThis->m_pImg = pThis->m_pImgDown;
+    pThis->notifyLayout();
+}
+
+
+void CtrlButton::transDownOverUpOver( SkinObject *pCtrl )
+{
+    CtrlButton *pThis = (CtrlButton*)pCtrl;
+    pThis->releaseMouse();
+    pThis->m_pImg = pThis->m_pImgUp;
+    pThis->notifyLayout();
+    // Execute the command associated to this button
+    pThis->m_rCommand.execute();
+}
+
+
+void CtrlButton::transDownOverDown( SkinObject *pCtrl )
+{
+    CtrlButton *pThis = (CtrlButton*)pCtrl;
+    pThis->m_pImg = pThis->m_pImgUp;
+    pThis->notifyLayout();
+}
+
+
+void CtrlButton::transDownDownOver( SkinObject *pCtrl )
+{
+    CtrlButton *pThis = (CtrlButton*)pCtrl;
+    pThis->m_pImg = pThis->m_pImgDown;
+    pThis->notifyLayout();
+}
+
+
+void CtrlButton::transUpUpOver( SkinObject *pCtrl )
+{
+    CtrlButton *pThis = (CtrlButton*)pCtrl;
+    pThis->m_pImg = pThis->m_pImgOver;
+    pThis->notifyLayout();
+}
+
+
+void CtrlButton::transUpOverUp( SkinObject *pCtrl )
+{
+    CtrlButton *pThis = (CtrlButton*)pCtrl;
+    pThis->m_pImg = pThis->m_pImgUp;
+    pThis->notifyLayout();
+}
+
+
+void CtrlButton::transDownUp( SkinObject *pCtrl )
+{
+    CtrlButton *pThis = (CtrlButton*)pCtrl;
+    pThis->releaseMouse();
+}
+
+
+void CtrlButton::transUpHidden( SkinObject *pCtrl )
+{
+    CtrlButton *pThis = (CtrlButton*)pCtrl;
+    pThis->m_pImg = NULL;
+    pThis->notifyLayout();
+}
+
+
+void CtrlButton::transHiddenUp( SkinObject *pCtrl )
+{
+    CtrlButton *pThis = (CtrlButton*)pCtrl;
+    pThis->m_pImg = pThis->m_pImgUp;
+    pThis->notifyLayout();
+}
+
diff --git a/modules/gui/skins2/controls/ctrl_button.hpp b/modules/gui/skins2/controls/ctrl_button.hpp
new file mode 100644 (file)
index 0000000..bf605a8
--- /dev/null
@@ -0,0 +1,96 @@
+/*****************************************************************************
+ * ctrl_button.hpp
+ *****************************************************************************
+ * Copyright (C) 2003 VideoLAN
+ * $Id: ctrl_button.hpp,v 1.1 2004/01/03 23:31:33 asmax Exp $
+ *
+ * Authors: Cyril Deguet     <asmax@via.ecp.fr>
+ *          Olivier Teulière <ipkiss@via.ecp.fr>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111, USA.
+ *****************************************************************************/
+
+#ifndef CTRL_BUTTON_HPP
+#define CTRL_BUTTON_HPP
+
+#include "ctrl_generic.hpp"
+#include "../utils/fsm.hpp"
+
+class GenericBitmap;
+class OSGraphics;
+class CmdGeneric;
+
+
+/// Base class for button controls
+class CtrlButton: public CtrlGeneric
+{
+    public:
+        /// Create a button with 3 images
+        CtrlButton( intf_thread_t *pIntf, const GenericBitmap &rBmpUp,
+                    const GenericBitmap &rBmpOver,
+                    const GenericBitmap &rBmpDown,
+                    CmdGeneric &rCommand, const UString &rTooltip,
+                    const UString &rHelp );
+
+        virtual ~CtrlButton();
+
+        /// Handle an event
+        virtual void handleEvent( EvtGeneric &rEvent );
+
+        /// Check whether coordinates are inside the control
+        virtual bool mouseOver( int x, int y ) const;
+
+        /// Draw the control on the given graphics
+        virtual void draw( OSGraphics &rImage, int xDest, int yDest );
+
+        /// Get the text of the tooltip
+        virtual UString getTooltipText() const { return m_tooltip; }
+
+    private:
+        /// Finite state machine of the control
+        FSM m_fsm;
+        /// Command triggered by the button
+        CmdGeneric &m_rCommand;
+        /// Tooltip text
+        const UString m_tooltip;
+        /// Callbacks objects
+        Callback m_cmdUpOverDownOver;
+        Callback m_cmdDownOverUpOver;
+        Callback m_cmdDownOverDown;
+        Callback m_cmdDownDownOver;
+        Callback m_cmdUpOverUp;
+        Callback m_cmdUpUpOver;
+        Callback m_cmdDownUp;
+        Callback m_cmdUpHidden;
+        Callback m_cmdHiddenUp;
+        /// Images of the button in the different states
+        OSGraphics *m_pImgUp, *m_pImgOver, *m_pImgDown;
+        /// Current image
+        OSGraphics *m_pImg;
+
+        /// Callback functions
+        static void transUpOverDownOver( SkinObject *pCtrl );
+        static void transDownOverUpOver( SkinObject *pCtrl );
+        static void transDownOverDown( SkinObject *pCtrl );
+        static void transDownDownOver( SkinObject *pCtrl );
+        static void transUpOverUp( SkinObject *pCtrl );
+        static void transUpUpOver( SkinObject *pCtrl );
+        static void transDownUp( SkinObject *pCtrl );
+        static void transUpHidden( SkinObject *pCtrl );
+        static void transHiddenUp( SkinObject *pCtrl );
+};
+
+
+#endif
diff --git a/modules/gui/skins2/controls/ctrl_checkbox.cpp b/modules/gui/skins2/controls/ctrl_checkbox.cpp
new file mode 100755 (executable)
index 0000000..088bcf7
--- /dev/null
@@ -0,0 +1,284 @@
+/*****************************************************************************
+ * ctrl_checkbox.cpp
+ *****************************************************************************
+ * Copyright (C) 2003 VideoLAN
+ * $Id: ctrl_checkbox.cpp,v 1.1 2004/01/03 23:31:33 asmax Exp $
+ *
+ * Authors: Cyril Deguet     <asmax@via.ecp.fr>
+ *          Olivier Teulière <ipkiss@via.ecp.fr>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111, USA.
+ *****************************************************************************/
+
+#include "ctrl_checkbox.hpp"
+#include "../events/evt_generic.hpp"
+#include "../commands/cmd_generic.hpp"
+#include "../src/generic_bitmap.hpp"
+#include "../src/os_factory.hpp"
+#include "../src/os_graphics.hpp"
+#include "../utils/var_bool.hpp"
+
+
+CtrlCheckbox::CtrlCheckbox( intf_thread_t *pIntf,
+                            const GenericBitmap &rBmpUp1,
+                            const GenericBitmap &rBmpOver1,
+                            const GenericBitmap &rBmpDown1,
+                            const GenericBitmap &rBmpUp2,
+                            const GenericBitmap &rBmpOver2,
+                            const GenericBitmap &rBmpDown2,
+                            CmdGeneric &rCommand1, CmdGeneric &rCommand2,
+                            const UString &rTooltip1,
+                            const UString &rTooltip2,
+                            VarBool &rVariable, const UString &rHelp ):
+    CtrlGeneric( pIntf, rHelp ), m_fsm( pIntf ), m_rVariable( rVariable ),
+    m_rCommand1( rCommand1 ), m_rCommand2( rCommand2 ),
+    m_tooltip1( rTooltip1 ), m_tooltip2( rTooltip2 ),
+    m_cmdUpOverDownOver( this, &transUpOverDownOver ),
+    m_cmdDownOverUpOver( this, &transDownOverUpOver ),
+    m_cmdDownOverDown( this, &transDownOverDown ),
+    m_cmdDownDownOver( this, &transDownDownOver ),
+    m_cmdUpOverUp( this, &transUpOverUp ),
+    m_cmdUpUpOver( this, &transUpUpOver ),
+    m_cmdDownUp( this, &transDownUp ),
+    m_cmdUpHidden( this, &transUpHidden ),
+    m_cmdHiddenUp( this, &transHiddenUp )
+{
+    // Build the images of the checkbox
+    OSFactory *pOsFactory = OSFactory::instance( pIntf );
+    m_pImgUp1 = pOsFactory->createOSGraphics( rBmpUp1.getWidth(),
+                                              rBmpUp1.getHeight() );
+    m_pImgUp1->drawBitmap( rBmpUp1, 0, 0 );
+    m_pImgDown1 = pOsFactory->createOSGraphics( rBmpDown1.getWidth(),
+                                                rBmpDown1.getHeight() );
+    m_pImgDown1->drawBitmap( rBmpDown1, 0, 0 );
+    m_pImgOver1 = pOsFactory->createOSGraphics( rBmpOver1.getWidth(),
+                                                rBmpOver1.getHeight() );
+    m_pImgOver1->drawBitmap( rBmpOver1, 0, 0 );
+
+    m_pImgUp2 = pOsFactory->createOSGraphics( rBmpUp2.getWidth(),
+                                              rBmpUp2.getHeight() );
+    m_pImgUp2->drawBitmap( rBmpUp2, 0, 0 );
+    m_pImgDown2 = pOsFactory->createOSGraphics( rBmpDown2.getWidth(),
+                                                rBmpDown2.getHeight() );
+    m_pImgDown2->drawBitmap( rBmpDown2, 0, 0 );
+    m_pImgOver2 = pOsFactory->createOSGraphics( rBmpOver2.getWidth(),
+                                                rBmpOver2.getHeight() );
+    m_pImgOver2->drawBitmap( rBmpOver2, 0, 0 );
+
+    // States
+    m_fsm.addState( "up" );
+    m_fsm.addState( "down" );
+    m_fsm.addState( "upOver" );
+    m_fsm.addState( "downOver" );
+    m_fsm.addState( "hidden" );
+
+    // Transitions
+    m_fsm.addTransition( "upOver", "mouse:left:down", "downOver",
+                         &m_cmdUpOverDownOver );
+    m_fsm.addTransition( "downOver", "mouse:left:up", "upOver",
+                         &m_cmdDownOverUpOver );
+    m_fsm.addTransition( "downOver", "leave", "down", &m_cmdDownOverDown );
+    m_fsm.addTransition( "down", "enter", "downOver", &m_cmdDownDownOver );
+    m_fsm.addTransition( "upOver", "leave", "up", &m_cmdUpOverUp );
+    m_fsm.addTransition( "up", "enter", "upOver", &m_cmdUpUpOver );
+    m_fsm.addTransition( "down", "mouse:left:up", "up", &m_cmdDownUp );
+    // XXX: It would be easy to use a "ANY" initial state to handle these
+    // four lines in only one. But till now it isn't worthwhile...
+    m_fsm.addTransition( "up", "special:hide", "hidden", &m_cmdUpHidden );
+    m_fsm.addTransition( "down", "special:hide", "hidden", &m_cmdUpHidden );
+    m_fsm.addTransition( "upOver", "special:hide", "hidden", &m_cmdUpHidden );
+    m_fsm.addTransition( "downOver", "special:hide", "hidden", &m_cmdUpHidden );
+    m_fsm.addTransition( "hidden", "special:show", "up", &m_cmdHiddenUp );
+
+    // Observe the variable
+    m_rVariable.addObserver( this );
+
+    // Initial state
+    m_fsm.setState( "up" );
+    if( !m_rVariable.get() )
+    {
+        m_pImgUp = m_pImgUp1;
+        m_pImgOver = m_pImgOver1;
+        m_pImgDown = m_pImgDown1;
+        m_pImgCurrent = m_pImgUp;
+        m_pCommand = &m_rCommand1;
+        m_pTooltip = &m_tooltip1;
+    }
+    else
+    {
+        m_pImgUp = m_pImgUp2;
+        m_pImgOver = m_pImgOver2;
+        m_pImgDown = m_pImgDown2;
+        m_pImgCurrent = m_pImgDown;
+        m_pCommand = &m_rCommand2;
+        m_pTooltip = &m_tooltip2;
+    }
+}
+
+
+CtrlCheckbox::~CtrlCheckbox()
+{
+    m_rVariable.delObserver( this );
+    SKINS_DELETE( m_pImgUp1 );
+    SKINS_DELETE( m_pImgDown1 );
+    SKINS_DELETE( m_pImgOver1 );
+    SKINS_DELETE( m_pImgUp2 );
+    SKINS_DELETE( m_pImgDown2 );
+    SKINS_DELETE( m_pImgOver2 );
+}
+
+
+void CtrlCheckbox::handleEvent( EvtGeneric &rEvent )
+{
+    m_fsm.handleTransition( rEvent.getAsString() );
+}
+
+
+bool CtrlCheckbox::mouseOver( int x, int y ) const
+{
+    if( m_pImgCurrent )
+    {
+        return m_pImgCurrent->hit( x, y );
+    }
+    else
+    {
+        return false;
+    }
+}
+
+
+void CtrlCheckbox::draw( OSGraphics &rImage, int xDest, int yDest )
+{
+    if( m_pImgCurrent )
+    {
+        // Draw the current image
+        rImage.drawGraphics( *m_pImgCurrent, 0, 0, xDest, yDest );
+    }
+}
+
+
+void CtrlCheckbox::transUpOverDownOver( SkinObject *pCtrl )
+{
+    CtrlCheckbox *pThis = (CtrlCheckbox*)pCtrl;
+    pThis->captureMouse();
+    pThis->m_pImgCurrent = pThis->m_pImgDown;
+    pThis->notifyLayout();
+}
+
+
+void CtrlCheckbox::transDownOverUpOver( SkinObject *pCtrl )
+{
+    CtrlCheckbox *pThis = (CtrlCheckbox*)pCtrl;
+    pThis->releaseMouse();
+
+    // Invert the state variable
+    pThis->m_rVariable.set( !pThis->m_rVariable.get() );
+    pThis->m_pImgCurrent = pThis->m_pImgUp;
+    pThis->notifyLayout();
+
+    // Execute the command
+    pThis->m_pCommand->execute();
+}
+
+
+void CtrlCheckbox::transDownOverDown( SkinObject *pCtrl )
+{
+    CtrlCheckbox *pThis = (CtrlCheckbox*)pCtrl;
+    pThis->m_pImgCurrent = pThis->m_pImgUp;
+    pThis->notifyLayout();
+}
+
+
+void CtrlCheckbox::transDownDownOver( SkinObject *pCtrl )
+{
+    CtrlCheckbox *pThis = (CtrlCheckbox*)pCtrl;
+    pThis->m_pImgCurrent = pThis->m_pImgDown;
+    pThis->notifyLayout();
+}
+
+
+void CtrlCheckbox::transUpUpOver( SkinObject *pCtrl )
+{
+    CtrlCheckbox *pThis = (CtrlCheckbox*)pCtrl;
+    pThis->m_pImgCurrent = pThis->m_pImgOver;
+    pThis->notifyLayout();
+}
+
+
+void CtrlCheckbox::transUpOverUp( SkinObject *pCtrl )
+{
+    CtrlCheckbox *pThis = (CtrlCheckbox*)pCtrl;
+    pThis->m_pImgCurrent = pThis->m_pImgUp;
+    pThis->notifyLayout();
+}
+
+
+void CtrlCheckbox::transDownUp( SkinObject *pCtrl )
+{
+    CtrlCheckbox *pThis = (CtrlCheckbox*)pCtrl;
+    pThis->releaseMouse();
+}
+
+
+void CtrlCheckbox::transUpHidden( SkinObject *pCtrl )
+{
+    CtrlCheckbox *pThis = (CtrlCheckbox*)pCtrl;
+    pThis->m_pImgCurrent = NULL;
+    pThis->notifyLayout();
+}
+
+
+void CtrlCheckbox::transHiddenUp( SkinObject *pCtrl )
+{
+    CtrlCheckbox *pThis = (CtrlCheckbox*)pCtrl;
+    pThis->m_pImgCurrent = pThis->m_pImgUp;
+    pThis->notifyLayout();
+}
+
+
+void CtrlCheckbox::onUpdate( Subject<VarBool> &rVariable )
+{
+    changeButton();
+}
+
+
+void CtrlCheckbox::changeButton()
+{
+    // Are we using the first set of images or the second one?
+    if( m_pImgUp == m_pImgUp1 )
+    {
+        m_pImgUp = m_pImgUp2;
+        m_pImgOver = m_pImgOver2;
+        m_pImgDown = m_pImgDown2;
+        m_pTooltip = &m_tooltip2;
+        m_pCommand = &m_rCommand2;
+    }
+    else
+    {
+        m_pImgUp = m_pImgUp1;
+        m_pImgOver = m_pImgOver1;
+        m_pImgDown = m_pImgDown1;
+        m_pTooltip = &m_tooltip1;
+        m_pCommand = &m_rCommand1;
+    }
+    // XXX: We assume that the checkbox is up
+    m_pImgCurrent = m_pImgUp;
+
+    // Notify the window the tooltip has changed
+    notifyTooltipChange();
+    // Refresh
+    notifyLayout();
+}
+
diff --git a/modules/gui/skins2/controls/ctrl_checkbox.hpp b/modules/gui/skins2/controls/ctrl_checkbox.hpp
new file mode 100644 (file)
index 0000000..7dbd244
--- /dev/null
@@ -0,0 +1,122 @@
+/*****************************************************************************
+ * ctrl_checkbox.hpp
+ *****************************************************************************
+ * Copyright (C) 2003 VideoLAN
+ * $Id: ctrl_checkbox.hpp,v 1.1 2004/01/03 23:31:33 asmax Exp $
+ *
+ * Authors: Cyril Deguet     <asmax@via.ecp.fr>
+ *          Olivier Teulière <ipkiss@via.ecp.fr>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111, USA.
+ *****************************************************************************/
+
+#ifndef CTRL_CHECKBOX_HPP
+#define CTRL_CHECKBOX_HPP
+
+#include "ctrl_generic.hpp"
+#include "../utils/fsm.hpp"
+#include "../utils/observer.hpp"
+
+class GenericBitmap;
+class OSGraphics;
+class CmdGeneric;
+class VarBool;
+
+
+/// Base class for checkbox controls
+class CtrlCheckbox: public CtrlGeneric, public Observer<VarBool>
+{
+    public:
+        /// Create a checkbox with 6 images
+        CtrlCheckbox( intf_thread_t *pIntf,
+                      const GenericBitmap &rBmpUp1,
+                      const GenericBitmap &rBmpOver1,
+                      const GenericBitmap &rBmpDown1,
+                      const GenericBitmap &rBmpUp2,
+                      const GenericBitmap &rBmpOver2,
+                      const GenericBitmap &rBmpDown2,
+                      CmdGeneric &rCommand1, CmdGeneric &rCommand2,
+                      const UString &rTooltip1, const UString &rTooltip2,
+                      VarBool &rVariable, const UString &rHelp );
+
+        virtual ~CtrlCheckbox();
+
+        /// Handle an event
+        virtual void handleEvent( EvtGeneric &rEvent );
+
+        /// Check whether coordinates are inside the control
+        virtual bool mouseOver( int x, int y ) const;
+
+        /// Draw the control on the given graphics
+        virtual void draw( OSGraphics &rImage, int xDest, int yDest );
+
+        /// Get the text of the tooltip XXX
+        virtual UString getTooltipText() const { return *m_pTooltip; }
+
+    private:
+        /// Finite state machine of the control
+        FSM m_fsm;
+        /// Observed variable
+        VarBool &m_rVariable;
+        /// Commands for the 2 states
+        CmdGeneric &m_rCommand1, &m_rCommand2;
+        /// Current command
+        CmdGeneric *m_pCommand;
+        /// Tooltip texts for the 2 states
+        const UString m_tooltip1, m_tooltip2;
+        /// Current tooltip
+        const UString *m_pTooltip;
+        /// Callbacks objects
+        Callback m_cmdUpOverDownOver;
+        Callback m_cmdDownOverUpOver;
+        Callback m_cmdDownOverDown;
+        Callback m_cmdDownDownOver;
+        Callback m_cmdUpOverUp;
+        Callback m_cmdUpUpOver;
+        Callback m_cmdDownUp;
+        Callback m_cmdUpHidden;
+        Callback m_cmdHiddenUp;
+        /// Images of the checkbox in the different states
+        OSGraphics *m_pImgUp1, *m_pImgOver1, *m_pImgDown1;
+        OSGraphics *m_pImgUp2, *m_pImgOver2, *m_pImgDown2;
+        /// Current set of images (pointing to 1 or 2)
+        /// In fact, we consider here that a checkbox acts like 2 buttons, in a
+        /// symetric way; this is a small trick to avoid multiplicating the
+        /// callbacks (and it could be extended easily to support 3 buttons or
+        /// more...)
+        OSGraphics *m_pImgUp, *m_pImgOver, *m_pImgDown;
+        /// Current image
+        OSGraphics *m_pImgCurrent;
+
+        /// Callback functions
+        static void transUpOverDownOver( SkinObject *pCtrl );
+        static void transDownOverUpOver( SkinObject *pCtrl );
+        static void transDownOverDown( SkinObject *pCtrl );
+        static void transDownDownOver( SkinObject *pCtrl );
+        static void transUpOverUp( SkinObject *pCtrl );
+        static void transUpUpOver( SkinObject *pCtrl );
+        static void transDownUp( SkinObject *pCtrl );
+        static void transUpHidden( SkinObject *pCtrl );
+        static void transHiddenUp( SkinObject *pCtrl );
+
+        /// Method called when the observed variable is modified
+        virtual void onUpdate( Subject<VarBool> &rVariable );
+
+        /// Helper function to update the current state of images
+        void changeButton();
+};
+
+
+#endif
diff --git a/modules/gui/skins2/controls/ctrl_flat.hpp b/modules/gui/skins2/controls/ctrl_flat.hpp
new file mode 100644 (file)
index 0000000..f113e26
--- /dev/null
@@ -0,0 +1,40 @@
+/*****************************************************************************
+ * ctrl_flat.hpp
+ *****************************************************************************
+ * Copyright (C) 2003 VideoLAN
+ * $Id: ctrl_flat.hpp,v 1.1 2004/01/03 23:31:33 asmax Exp $
+ *
+ * Authors: Cyril Deguet     <asmax@via.ecp.fr>
+ *          Olivier Teulière <ipkiss@via.ecp.fr>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111, USA.
+ *****************************************************************************/
+
+#ifndef CTRL_FLAT_HPP
+#define CTRL_FLAT_HPP
+
+#include "ctrl_generic.hpp"
+
+
+/// Base class for "mover controls" and images
+class CtrlFlat: public CtrlGeneric
+{
+    protected:
+        CtrlFlat( intf_thread_t *pIntf, const UString &rHelp ):
+            CtrlGeneric( pIntf, rHelp ) {}
+        virtual ~CtrlFlat() {}
+};
+
+#endif
diff --git a/modules/gui/skins2/controls/ctrl_generic.cpp b/modules/gui/skins2/controls/ctrl_generic.cpp
new file mode 100755 (executable)
index 0000000..d6dabfa
--- /dev/null
@@ -0,0 +1,110 @@
+/*****************************************************************************
+ * ctrl_generic.cpp
+ *****************************************************************************
+ * Copyright (C) 2003 VideoLAN
+ * $Id: ctrl_generic.cpp,v 1.1 2004/01/03 23:31:33 asmax Exp $
+ *
+ * Authors: Cyril Deguet     <asmax@via.ecp.fr>
+ *          Olivier Teulière <ipkiss@via.ecp.fr>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111, USA.
+ *****************************************************************************/
+
+#include "ctrl_generic.hpp"
+#include "../src/generic_layout.hpp"
+#include "../src/generic_window.hpp"
+#include "../src/os_graphics.hpp"
+#include "../utils/position.hpp"
+
+
+CtrlGeneric::CtrlGeneric( intf_thread_t *pIntf, const UString &rHelp ):
+    SkinObject( pIntf ), m_pLayout( NULL ), m_pPosition( NULL ),
+    m_help( rHelp )
+{
+}
+
+
+CtrlGeneric::~CtrlGeneric()
+{
+    if( m_pPosition )
+    {
+        delete m_pPosition;
+    }
+}
+
+
+void CtrlGeneric::setLayout( GenericLayout *pLayout,
+                             const Position &rPosition )
+{
+    m_pLayout = pLayout;
+    if( m_pPosition )
+    {
+        delete m_pPosition;
+    }
+    m_pPosition = new Position( rPosition );
+    onPositionChange();
+}
+
+
+void CtrlGeneric::notifyLayout() const
+{
+    // Notify the layout
+    if( m_pLayout )
+    {
+        m_pLayout->onControlUpdate( *this );
+    }
+}
+
+
+void CtrlGeneric::captureMouse() const
+{
+    // Tell the layout we want to capture the mouse
+    if( m_pLayout )
+    {
+        m_pLayout->onControlCapture( *this );
+    }
+}
+
+
+void CtrlGeneric::releaseMouse() const
+{
+    // Tell the layout we want to release the mouse
+    if( m_pLayout )
+    {
+        m_pLayout->onControlRelease( *this );
+    }
+}
+
+
+void CtrlGeneric::notifyTooltipChange() const
+{
+    GenericWindow *pWin = getWindow();
+    if( pWin )
+    {
+        // Notify the window
+        pWin->onTooltipChange( *this );
+    }
+}
+
+
+GenericWindow *CtrlGeneric::getWindow() const
+{
+    if( m_pLayout )
+    {
+        return m_pLayout->getWindow();
+    }
+    return NULL;
+}
+
diff --git a/modules/gui/skins2/controls/ctrl_generic.hpp b/modules/gui/skins2/controls/ctrl_generic.hpp
new file mode 100644 (file)
index 0000000..447417c
--- /dev/null
@@ -0,0 +1,110 @@
+/*****************************************************************************
+ * ctrl_generic.hpp
+ *****************************************************************************
+ * Copyright (C) 2003 VideoLAN
+ * $Id: ctrl_generic.hpp,v 1.1 2004/01/03 23:31:33 asmax Exp $
+ *
+ * Authors: Cyril Deguet     <asmax@via.ecp.fr>
+ *          Olivier Teulière <ipkiss@via.ecp.fr>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111, USA.
+ *****************************************************************************/
+
+#ifndef CTRL_GENERIC_HPP
+#define CTRL_GENERIC_HPP
+
+#include "../src/skin_common.hpp"
+#include "../utils/pointer.hpp"
+#include "../utils/fsm.hpp"
+#include "../utils/ustring.hpp"
+
+class EvtGeneric;
+class OSGraphics;
+class GenericLayout;
+class Position;
+class GenericWindow;
+
+
+/// Base class for controls
+class CtrlGeneric: public SkinObject
+{
+    public:
+        virtual ~CtrlGeneric();
+
+        /// Handle an event on the control
+        virtual void handleEvent( EvtGeneric &rEvent ) {}
+
+        /// Check whether coordinates are inside the control
+        virtual bool mouseOver( int x, int y ) const { return false; }
+
+        /// Draw the control on the given graphics
+        virtual void draw( OSGraphics &rImage, int xDest, int yDest ) {}
+
+        /// Set the position and the associated layout of the control
+        virtual void setLayout( GenericLayout *pLayout,
+                                const Position &rPosition );
+
+        /// Get the position of the control in the layout, if any
+        virtual const Position *getPosition() const { return m_pPosition; }
+
+        /// Get the text of the tooltip
+        virtual UString getTooltipText() const
+            { return UString( getIntf(), "" ); }
+
+        /// Overload this method if you want to do something special when
+        /// the layout is resized
+        virtual void onResize() {}
+
+        /// Get the help text
+        virtual const UString &getHelpText() const { return m_help; }
+
+        /// Return true if the control can gain the focus
+        virtual bool isFocusable() const { return false; }
+
+    protected:
+        CtrlGeneric( intf_thread_t *pIntf, const UString &rHelp );
+
+        /// Tell the layout when the image has changed
+        virtual void notifyLayout() const;
+
+        /// Ask the layout to capture the mouse
+        virtual void captureMouse() const;
+
+        /// Ask the layout to release the mouse
+        virtual void releaseMouse() const;
+
+        /// Notify the window the tooltip has changed
+        virtual void notifyTooltipChange() const;
+
+        /// Get the associated window, if any
+        virtual GenericWindow *getWindow() const;
+
+        /// Overload this method if you want to do something special when
+        /// the Position object is set
+        virtual void onPositionChange() {}
+
+    private:
+        /// Associated layout
+        GenericLayout *m_pLayout;
+        /// Position in the layout
+        Position *m_pPosition;
+        /// Help text
+        UString m_help;
+};
+
+typedef CountedPtr<CtrlGeneric> CtrlGenericPtr;
+
+
+#endif
diff --git a/modules/gui/skins2/controls/ctrl_image.cpp b/modules/gui/skins2/controls/ctrl_image.cpp
new file mode 100755 (executable)
index 0000000..4871b86
--- /dev/null
@@ -0,0 +1,88 @@
+/*****************************************************************************
+ * ctrl_image.cpp
+ *****************************************************************************
+ * Copyright (C) 2003 VideoLAN
+ * $Id: ctrl_image.cpp,v 1.1 2004/01/03 23:31:33 asmax Exp $
+ *
+ * Authors: Cyril Deguet     <asmax@via.ecp.fr>
+ *          Olivier Teulière <ipkiss@via.ecp.fr>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111, USA.
+ *****************************************************************************/
+
+#include "ctrl_image.hpp"
+#include "../commands/cmd_dialogs.hpp"
+#include "../events/evt_generic.hpp"
+#include "../src/os_factory.hpp"
+#include "../src/os_graphics.hpp"
+#include "../src/scaled_bitmap.hpp"
+#include "../utils/position.hpp"
+
+
+CtrlImage::CtrlImage( intf_thread_t *pIntf, const GenericBitmap &rBitmap,
+                      const UString &rHelp ):
+    CtrlFlat( pIntf, rHelp ), m_rBitmap( rBitmap )
+{
+    OSFactory *pOsFactory = OSFactory::instance( pIntf );
+    // Create an initial unscaled image in the buffer
+    m_pImage = pOsFactory->createOSGraphics( rBitmap.getWidth(),
+                                             rBitmap.getHeight() );
+    m_pImage->drawBitmap( m_rBitmap );
+}
+
+
+CtrlImage::~CtrlImage()
+{
+    SKINS_DELETE( m_pImage );
+}
+
+
+void CtrlImage::handleEvent( EvtGeneric &rEvent )
+{
+    // No FSM for this simple transition
+    if( rEvent.getAsString() == "mouse:right:down:none" )
+    {
+        CmdDlgPopupMenu cmd( getIntf() );
+        cmd.execute();
+    }
+}
+
+
+bool CtrlImage::mouseOver( int x, int y ) const
+{
+    return m_pImage->hit( x, y );
+}
+
+
+void CtrlImage::draw( OSGraphics &rImage, int xDest, int yDest )
+{
+    const Position *pPos = getPosition();
+    if( pPos )
+    {
+        int width = pPos->getWidth();
+        int height = pPos->getHeight();
+        if( width != m_pImage->getWidth() || height != m_pImage->getHeight() )
+        {
+            OSFactory *pOsFactory = OSFactory::instance( getIntf() );
+            // Rescale the image with the actual size of the control
+            ScaledBitmap bmp( getIntf(), m_rBitmap, width, height );
+            SKINS_DELETE( m_pImage );
+            m_pImage = pOsFactory->createOSGraphics( width, height );
+            m_pImage->drawBitmap( bmp, 0, 0 );
+        }
+        rImage.drawGraphics( *m_pImage, 0, 0, xDest, yDest );
+    }
+}
+
diff --git a/modules/gui/skins2/controls/ctrl_image.hpp b/modules/gui/skins2/controls/ctrl_image.hpp
new file mode 100644 (file)
index 0000000..705d477
--- /dev/null
@@ -0,0 +1,60 @@
+/*****************************************************************************
+ * ctrl_image.hpp
+ *****************************************************************************
+ * Copyright (C) 2003 VideoLAN
+ * $Id: ctrl_image.hpp,v 1.1 2004/01/03 23:31:33 asmax Exp $
+ *
+ * Authors: Cyril Deguet     <asmax@via.ecp.fr>
+ *          Olivier Teulière <ipkiss@via.ecp.fr>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111, USA.
+ *****************************************************************************/
+
+#ifndef CTRL_IMAGE_HPP
+#define CTRL_IMAGE_HPP
+
+#include "../commands/cmd_generic.hpp"
+#include "ctrl_flat.hpp"
+
+class GenericBitmap;
+class OSGraphics;
+
+
+/// Control image
+class CtrlImage: public CtrlFlat
+{
+    public:
+        // Create an image with the given bitmap (which is NOT copied)
+        CtrlImage( intf_thread_t *pIntf, const GenericBitmap &rBitmap,
+                   const UString &rHelp );
+        virtual ~CtrlImage();
+
+        /// Handle an event on the control
+        virtual void handleEvent( EvtGeneric &rEvent );
+
+        /// Check whether coordinates are inside the control
+        virtual bool mouseOver( int x, int y ) const;
+
+        /// Draw the control on the given graphics
+        virtual void draw( OSGraphics &rImage, int xDest, int yDest );
+
+    private:
+        /// Bitmap
+        const GenericBitmap &m_rBitmap;
+        /// Buffer to stored the rendered bitmap
+        OSGraphics *m_pImage;
+};
+
+#endif
diff --git a/modules/gui/skins2/controls/ctrl_list.cpp b/modules/gui/skins2/controls/ctrl_list.cpp
new file mode 100644 (file)
index 0000000..6b0dc72
--- /dev/null
@@ -0,0 +1,387 @@
+/*****************************************************************************
+ * ctrl_list.cpp
+ *****************************************************************************
+ * Copyright (C) 2003 VideoLAN
+ * $Id: ctrl_list.cpp,v 1.1 2004/01/03 23:31:33 asmax Exp $
+ *
+ * Authors: Cyril Deguet     <asmax@via.ecp.fr>
+ *          Olivier Teulière <ipkiss@via.ecp.fr>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111, USA.
+ *****************************************************************************/
+
+#include <math.h>
+#include "ctrl_list.hpp"
+#include "../src/os_factory.hpp"
+#include "../src/os_graphics.hpp"
+#include "../src/generic_bitmap.hpp"
+#include "../src/generic_font.hpp"
+#include "../utils/position.hpp"
+#include "../utils/ustring.hpp"
+#include "../events/evt_key.hpp"
+#include "../events/evt_mouse.hpp"
+#include "../events/evt_scroll.hpp"
+#include "vlc_keys.h"
+
+#define SCROLL_STEP 0.05
+
+
+CtrlList::CtrlList( intf_thread_t *pIntf, VarList &rList, GenericFont &rFont,
+                    uint32_t fgColor, uint32_t playColor, uint32_t bgColor1,
+                    uint32_t bgColor2, uint32_t selColor,
+                    const UString &rHelp ):
+    CtrlGeneric( pIntf, rHelp ), m_rList( rList ), m_rFont( rFont ),
+    m_fgColor( fgColor ), m_playColor( playColor ), m_bgColor1( bgColor1 ),
+    m_bgColor2( bgColor2 ), m_selColor( selColor ), m_pLastSelected( NULL ),
+    m_pImage( NULL ), m_lastPos( 0 )
+{
+    // Observe the list and position variables
+    m_rList.addObserver( this );
+    m_rList.getPositionVar().addObserver( this );
+
+    makeImage();
+}
+
+
+CtrlList::~CtrlList()
+{
+    m_rList.getPositionVar().delObserver( this );
+    m_rList.delObserver( this );
+    if( m_pImage )
+    {
+        delete m_pImage;
+    }
+}
+
+
+void CtrlList::onUpdate( Subject<VarList> &rList )
+{
+    makeImage();
+    notifyLayout();
+    m_pLastSelected = NULL;
+}
+
+
+void CtrlList::onUpdate( Subject<VarPercent> &rPercent )
+{
+    // Get the size of the control
+    const Position *pPos = getPosition();
+    if( !pPos )
+    {
+        return;
+    }
+    int height = pPos->getHeight();
+
+    // How many lines can be displayed ?
+    int itemHeight = m_rFont.getSize();
+    int maxItems = height / itemHeight;
+
+    // Determine what is the first item to display
+    VarPercent &rVarPos = m_rList.getPositionVar();
+    int firstItem = 0;
+    int excessItems = m_rList.size() - maxItems;
+    if( excessItems > 0 )
+    {
+        // a simple (int)(...) causes rounding errors !
+        firstItem = lrint( (1.0 - rVarPos.get()) * (double)excessItems );
+    }
+    if( m_lastPos != firstItem )
+    {
+        // Redraw the control if the position has changed
+        m_lastPos = firstItem;
+        makeImage();
+        notifyLayout();
+    }
+}
+
+
+void CtrlList::onResize()
+{
+    // Get the size of the control
+    const Position *pPos = getPosition();
+    if( !pPos )
+    {
+        return;
+    }
+    int height = pPos->getHeight();
+
+    // How many lines can be displayed ?
+    int itemHeight = m_rFont.getSize();
+    int maxItems = height / itemHeight;
+
+    // Update the position variable
+    VarPercent &rVarPos = m_rList.getPositionVar();
+    int excessItems = m_rList.size() - maxItems;
+    if( excessItems > 0 )
+    {
+        double newVal = 1.0 - (double)m_lastPos / excessItems;
+        if( newVal >= 0 )
+        {
+            // Change the position to keep the same first displayed item
+            rVarPos.set( 1.0 - (double)m_lastPos / excessItems );
+        }
+        else
+        {
+            // We cannot keep the current first item
+            m_lastPos = excessItems;
+        }
+    }
+
+    makeImage();
+    notifyLayout();
+}
+
+
+void CtrlList::onPositionChange()
+{
+    makeImage();
+    notifyLayout();
+}
+
+
+void CtrlList::handleEvent( EvtGeneric &rEvent )
+{
+    if( rEvent.getAsString().find( "key:down" ) != string::npos )
+    {
+        char key = ((EvtKey&)rEvent).getKey();
+    }
+
+    else if( rEvent.getAsString().find( "mouse:left" ) != string::npos )
+    {
+        EvtMouse &rEvtMouse = (EvtMouse&)rEvent;
+        const Position *pos = getPosition();
+        int yPos = m_lastPos +
+                ( rEvtMouse.getYPos() - pos->getTop() ) / m_rFont.getSize();
+        VarList::Iterator it;
+        int index = 0;
+
+        if( rEvent.getAsString().find( "mouse:left:down:ctrl,shift" ) !=
+                 string::npos )
+        {
+            // Flag to know if the current item must be selected
+            bool select = false;
+            for( it = m_rList.begin(); it != m_rList.end(); it++ )
+            {
+                bool nextSelect = select;
+                if( index == yPos || &*it == m_pLastSelected )
+                {
+                    if( select )
+                    {
+                        nextSelect = false;
+                    }
+                    else
+                    {
+                        select = true;
+                        nextSelect = true;
+                    }
+                }
+                (*it).m_selected = (*it).m_selected || select;
+                select = nextSelect;
+                index++;
+            }
+        }
+
+        else if( rEvent.getAsString().find( "mouse:left:down:ctrl" ) !=
+                 string::npos )
+        {
+            for( it = m_rList.begin(); it != m_rList.end(); it++ )
+            {
+                if( index == yPos )
+                {
+                    (*it).m_selected = ! (*it).m_selected;
+                    m_pLastSelected = &*it;
+                    break;
+                }
+                index++;
+            }
+        }
+
+        else if( rEvent.getAsString().find( "mouse:left:down:shift" ) !=
+                 string::npos )
+        {
+            // Flag to know if the current item must be selected
+            bool select = false;
+            for( it = m_rList.begin(); it != m_rList.end(); it++ )
+            {
+                bool nextSelect = select;
+                if( index == yPos ||  &*it == m_pLastSelected )
+                {
+                    if( select )
+                    {
+                        nextSelect = false;
+                    }
+                    else
+                    {
+                        select = true;
+                        nextSelect = true;
+                    }
+                }
+                (*it).m_selected = select;
+                select = nextSelect;
+                index++;
+            }
+        }
+
+        else if( rEvent.getAsString().find( "mouse:left:down" ) !=
+                 string::npos )
+        {
+            for( it = m_rList.begin(); it != m_rList.end(); it++ )
+            {
+                if( index == yPos )
+                {
+                    (*it).m_selected = true;
+                    m_pLastSelected = &*it;
+                }
+                else
+                {
+                    (*it).m_selected = false;
+                }
+                index++;
+            }
+        }
+
+        else if( rEvent.getAsString().find( "mouse:left:dblclick" ) !=
+                 string::npos )
+        {
+            for( it = m_rList.begin(); it != m_rList.end(); it++ )
+            {
+                if( index == yPos )
+                {
+                    (*it).m_selected = true;
+                    m_pLastSelected = &*it;
+                    // Execute the action associated to this item
+                    m_rList.action( &*it );
+                }
+                else
+                {
+                    (*it).m_selected = false;
+                }
+                index++;
+            }
+        }
+
+        // Redraw the control
+        makeImage();
+        notifyLayout();
+    }
+
+    else if( rEvent.getAsString().find( "scroll" ) != string::npos )
+    {
+        int direction = ((EvtScroll&)rEvent).getDirection();
+
+        double percentage = m_rList.getPositionVar().get();
+        if( direction == EvtScroll::kUp )
+        {
+            percentage += SCROLL_STEP;
+        }
+        else
+        {
+            percentage -= SCROLL_STEP;
+        }
+        m_rList.getPositionVar().set( percentage );
+    }
+}
+
+
+bool CtrlList::mouseOver( int x, int y ) const
+{
+    const Position *pPos = getPosition();
+    if( pPos )
+    {
+        int width = pPos->getWidth();
+        int height = pPos->getHeight();
+        return ( x >= 0 && x <= width && y >= 0 && y <= height );
+    }
+    return false;
+}
+
+
+void CtrlList::draw( OSGraphics &rImage, int xDest, int yDest )
+{
+    if( m_pImage )
+    {
+        rImage.drawGraphics( *m_pImage, 0, 0, xDest, yDest );
+    }
+}
+
+
+void CtrlList::makeImage()
+{
+    if( m_pImage )
+    {
+        delete m_pImage;
+    }
+
+    // Get the size of the control
+    const Position *pPos = getPosition();
+    if( !pPos )
+    {
+        return;
+    }
+    int width = pPos->getWidth();
+    int height = pPos->getHeight();
+    int itemHeight = m_rFont.getSize();
+
+    // Create an image
+    OSFactory *pOsFactory = OSFactory::instance( getIntf() );
+    m_pImage = pOsFactory->createOSGraphics( width, height );
+
+    // Current background color
+    uint32_t bgColor = m_bgColor1;
+
+    // Draw the background
+    VarList::ConstIterator it = m_rList[m_lastPos];
+    for( int yPos = 0; yPos < height; yPos += itemHeight )
+    {
+        int rectHeight = __MIN( itemHeight, height - yPos );
+        if( it != m_rList.end() )
+        {
+            uint32_t color = ( (*it).m_selected ? m_selColor : bgColor );
+            m_pImage->fillRect( 0, yPos, width, rectHeight, color );
+            it++;
+        }
+        else
+        {
+            m_pImage->fillRect( 0, yPos, width, rectHeight, bgColor );
+        }
+        // Flip the background color
+        bgColor = ( bgColor == m_bgColor1 ? m_bgColor2 : m_bgColor1 );
+    }
+
+    // Draw the items
+    int yPos = 0;
+    for( it = m_rList[m_lastPos]; it != m_rList.end() && yPos < height; it++ )
+    {
+        UString *pStr = (UString*)((*it).m_cString.get());
+        uint32_t color = ( (*it).m_playing ? m_playColor : m_fgColor );
+
+        // Draw the text
+        GenericBitmap *pText = m_rFont.drawString( *pStr, color, width );
+        yPos += itemHeight - pText->getHeight();
+        int ySrc = 0;
+        if( yPos < 0 )
+        {
+            ySrc = - yPos;
+            yPos = 0;
+        }
+        int lineHeight = __MIN( pText->getHeight() - ySrc, height - yPos );
+        m_pImage->drawBitmap( *pText, 0, ySrc, 0, yPos, pText->getWidth(),
+                              lineHeight );
+        yPos += (pText->getHeight() - ySrc );
+        delete pText;
+
+    }
+}
+
diff --git a/modules/gui/skins2/controls/ctrl_list.hpp b/modules/gui/skins2/controls/ctrl_list.hpp
new file mode 100644 (file)
index 0000000..bfbc1f7
--- /dev/null
@@ -0,0 +1,95 @@
+/*****************************************************************************
+ * ctrl_list.hpp
+ *****************************************************************************
+ * Copyright (C) 2003 VideoLAN
+ * $Id: ctrl_list.hpp,v 1.1 2004/01/03 23:31:33 asmax Exp $
+ *
+ * Authors: Cyril Deguet     <asmax@via.ecp.fr>
+ *          Olivier Teulière <ipkiss@via.ecp.fr>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111, USA.
+ *****************************************************************************/
+
+#ifndef CTRL_LIST_HPP
+#define CTRL_LIST_HPP
+
+#include "ctrl_generic.hpp"
+#include "../utils/observer.hpp"
+#include "../utils/var_list.hpp"
+
+class OSGraphics;
+class GenericFont;
+
+
+/// Class for control list
+class CtrlList: public CtrlGeneric, public Observer<VarList>,
+    public Observer<VarPercent>
+{
+    public:
+        CtrlList( intf_thread_t *pIntf, VarList &rList, GenericFont &rFont,
+                  uint32_t fgcolor, uint32_t playcolor, uint32_t bgcolor1,
+                  uint32_t bgcolor2, uint32_t selColor,
+                  const UString &rHelp );
+        virtual ~CtrlList();
+
+        /// Handle an event on the control.
+        virtual void handleEvent( EvtGeneric &rEvent );
+
+        /// Check whether coordinates are inside the control.
+        virtual bool mouseOver( int x, int y ) const;
+
+        /// Draw the control on the given graphics
+        virtual void draw( OSGraphics &rImage, int xDest, int yDest );
+
+        /// Called when the layout is resized
+        virtual void onResize();
+
+        /// Return true if the control can gain the focus
+        virtual bool isFocusable() const { return true; }
+
+    private:
+        /// List associated to the control
+        VarList &m_rList;
+        /// Font
+        GenericFont &m_rFont;
+        /// Color of normal text
+        uint32_t m_fgColor;
+        /// Color of the playing item
+        uint32_t m_playColor;
+        /// Background colors
+        uint32_t m_bgColor1, m_bgColor2;
+        /// Background of selected items
+        uint32_t m_selColor;
+        /// Pointer on the last selected item in the list
+        VarList::Elem_t *m_pLastSelected;
+        /// Image of the control
+        OSGraphics *m_pImage;
+        /// Last position
+        int m_lastPos;
+
+        /// Method called when the list variable is modified
+        virtual void onUpdate( Subject<VarList> &rList );
+
+        /// Method called when the position variable of the list is modified
+        virtual void onUpdate( Subject<VarPercent> &rPercent );
+
+        /// Called when the position is set
+        virtual void onPositionChange();
+
+        /// Draw the image of the control
+        void makeImage();
+};
+
+#endif
diff --git a/modules/gui/skins2/controls/ctrl_move.cpp b/modules/gui/skins2/controls/ctrl_move.cpp
new file mode 100755 (executable)
index 0000000..901f200
--- /dev/null
@@ -0,0 +1,134 @@
+/*****************************************************************************
+ * ctrl_move.cpp
+ *****************************************************************************
+ * Copyright (C) 2003 VideoLAN
+ * $Id: ctrl_move.cpp,v 1.1 2004/01/03 23:31:33 asmax Exp $
+ *
+ * Authors: Cyril Deguet     <asmax@via.ecp.fr>
+ *          Olivier Teulière <ipkiss@via.ecp.fr>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111, USA.
+ *****************************************************************************/
+
+#include "ctrl_move.hpp"
+#include "../events/evt_generic.hpp"
+#include "../events/evt_mouse.hpp"
+#include "../events/evt_motion.hpp"
+#include "../src/generic_window.hpp"
+#include "../src/window_manager.hpp"
+#include "../utils/position.hpp"
+
+
+CtrlMove::CtrlMove( intf_thread_t *pIntf, WindowManager &rWindowManager,
+                    CtrlFlat &rCtrl, GenericWindow &rWindow,
+                    const UString &rHelp ):
+    CtrlFlat( pIntf, rHelp ), m_fsm( pIntf ),
+    m_rWindowManager( rWindowManager ),
+    m_rCtrl( rCtrl ), m_rWindow( rWindow ),
+    m_cmdMovingMoving( this, &transMovingMoving ),
+    m_cmdStillMoving( this, &transStillMoving ),
+    m_cmdMovingStill( this, &transMovingStill )
+{
+    m_pEvt = NULL;
+    m_xPos = 0;
+    m_yPos = 0;
+
+    // States
+    m_fsm.addState( "moving" );
+    m_fsm.addState( "still" );
+
+    // Transitions
+    m_fsm.addTransition( "moving", "mouse:left:up:none", "still",
+                         &m_cmdMovingStill );
+    m_fsm.addTransition( "still", "mouse:left:down:none", "moving",
+                         &m_cmdStillMoving );
+    m_fsm.addTransition( "moving", "motion", "moving", &m_cmdMovingMoving );
+
+    m_fsm.setState( "still" );
+}
+
+
+bool CtrlMove::mouseOver( int x, int y ) const
+{
+    return m_rCtrl.mouseOver( x, y );
+}
+
+
+void CtrlMove::draw( OSGraphics &rImage, int xDest, int yDest )
+{
+    m_rCtrl.draw( rImage, xDest, yDest );
+}
+
+
+void CtrlMove::setLayout( GenericLayout *pLayout, const Position &rPosition )
+{
+    CtrlGeneric::setLayout( pLayout, rPosition );
+    // Set the layout of the decorated control as well
+    m_rCtrl.setLayout( pLayout, rPosition );
+}
+
+
+const Position *CtrlMove::getPosition() const
+{
+    return m_rCtrl.getPosition();
+}
+
+
+void CtrlMove::handleEvent( EvtGeneric &rEvent )
+{
+    m_pEvt = &rEvent;
+    m_fsm.handleTransition( rEvent.getAsString() );
+    // Transmit the event to the decorated control
+    // XXX: Is it really a good idea?
+    m_rCtrl.handleEvent( rEvent );
+}
+
+
+void CtrlMove::transStillMoving( SkinObject *pCtrl )
+{
+    CtrlMove *pThis = (CtrlMove*)pCtrl;
+    EvtMouse *pEvtMouse = (EvtMouse*)pThis->m_pEvt;
+
+    pThis->m_xPos = pEvtMouse->getXPos();
+    pThis->m_yPos = pEvtMouse->getYPos();
+
+    pThis->captureMouse();
+
+    pThis->m_rWindowManager.startMove( &pThis->m_rWindow );
+}
+
+
+void CtrlMove::transMovingMoving( SkinObject *pCtrl )
+{
+    CtrlMove *pThis = (CtrlMove*)pCtrl;
+    EvtMotion *pEvtMotion = (EvtMotion*)pThis->m_pEvt;
+
+    int xNewLeft = pEvtMotion->getXPos() - pThis->m_xPos +
+                   pThis->m_rWindow.getLeft();
+    int yNewTop = pEvtMotion->getYPos() - pThis->m_yPos +
+                  pThis->m_rWindow.getTop();
+
+    pThis->m_rWindowManager.move( &pThis->m_rWindow, xNewLeft, yNewTop );
+}
+
+
+void CtrlMove::transMovingStill( SkinObject *pCtrl )
+{
+    CtrlMove *pThis = (CtrlMove*)pCtrl;
+
+    pThis->releaseMouse();
+
+    pThis->m_rWindowManager.stopMove();
+}
diff --git a/modules/gui/skins2/controls/ctrl_move.hpp b/modules/gui/skins2/controls/ctrl_move.hpp
new file mode 100644 (file)
index 0000000..47dabb3
--- /dev/null
@@ -0,0 +1,83 @@
+/*****************************************************************************
+ * ctrl_move.hpp
+ *****************************************************************************
+ * Copyright (C) 2003 VideoLAN
+ * $Id: ctrl_move.hpp,v 1.1 2004/01/03 23:31:33 asmax Exp $
+ *
+ * Authors: Cyril Deguet     <asmax@via.ecp.fr>
+ *          Olivier Teulière <ipkiss@via.ecp.fr>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111, USA.
+ *****************************************************************************/
+
+#ifndef CTRL_MOVE_HPP
+#define CTRL_MOVE_HPP
+
+#include "../commands/cmd_generic.hpp"
+#include "../utils/fsm.hpp"
+#include "ctrl_flat.hpp"
+
+class GenericWindow;
+class WindowManager;
+
+
+/// Control for moving windows
+class CtrlMove: public CtrlFlat
+{
+    public:
+        CtrlMove( intf_thread_t *pIntf, WindowManager &rWindowManager,
+                  CtrlFlat &rCtrl, GenericWindow &rWindow,
+                  const UString &rHelp );
+        virtual ~CtrlMove() {}
+
+        /// Handle an event
+        virtual void handleEvent( EvtGeneric &rEvent );
+
+        /// Check whether coordinates are inside the decorated control
+        virtual bool mouseOver( int x, int y ) const;
+
+        /// Draw the control on the given graphics
+        virtual void draw( OSGraphics &rImage, int xDest, int yDest );
+
+        /// Set the position and the associated layout of the decorated control
+        virtual void setLayout( GenericLayout *pLayout,
+                                const Position &rPosition );
+
+        /// Get the position of the decorated control in the layout, if any
+        virtual const Position *getPosition() const;
+
+        static void transMovingMoving( SkinObject *pCtrl );
+        static void transStillMoving( SkinObject *pCtrl );
+        static void transMovingStill( SkinObject *pCtrl );
+
+    private:
+        FSM m_fsm;
+        /// Window manager
+        WindowManager &m_rWindowManager;
+        /// Decorated CtrlFlat
+        CtrlFlat &m_rCtrl;
+        /// The window moved by this control
+        GenericWindow &m_rWindow;
+        /// The last received event
+        EvtGeneric *m_pEvt;
+        /// Position of the click that started the move
+        int m_xPos, m_yPos;
+        /// Callbacks
+        Callback m_cmdMovingMoving;
+        Callback m_cmdStillMoving;
+        Callback m_cmdMovingStill;
+};
+
+#endif
diff --git a/modules/gui/skins2/controls/ctrl_radialslider.cpp b/modules/gui/skins2/controls/ctrl_radialslider.cpp
new file mode 100644 (file)
index 0000000..4431900
--- /dev/null
@@ -0,0 +1,174 @@
+/*****************************************************************************
+ * ctrl_radialslider.cpp
+ *****************************************************************************
+ * Copyright (C) 2003 VideoLAN
+ * $Id: ctrl_radialslider.cpp,v 1.1 2004/01/03 23:31:33 asmax Exp $
+ *
+ * Authors: Cyril Deguet     <asmax@via.ecp.fr>
+ *          Olivier Teulière <ipkiss@via.ecp.fr>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111, USA.
+ *****************************************************************************/
+
+#include <math.h>
+#include "ctrl_radialslider.hpp"
+#include "../events/evt_mouse.hpp"
+#include "../src/generic_bitmap.hpp"
+#include "../src/generic_window.hpp"
+#include "../src/os_factory.hpp"
+#include "../src/os_graphics.hpp"
+#include "../utils/position.hpp"
+#include "../utils/var_percent.hpp"
+
+
+CtrlRadialSlider::CtrlRadialSlider( intf_thread_t *pIntf,
+                                    const GenericBitmap &rBmpSeq, int numImg,
+                                    VarPercent &rVariable, double minAngle,
+                                    double maxAngle, const UString &rHelp ):
+    CtrlGeneric( pIntf, rHelp ), m_fsm( pIntf ), m_numImg( numImg ),
+    m_rVariable( rVariable ), m_minAngle( minAngle ), m_maxAngle( maxAngle ),
+    m_cmdUpDown( this, &transUpDown ), m_cmdDownUp( this, &transDownUp ),
+    m_cmdMove( this, &transMove ), m_position( 0 ), m_lastPos( 0 )
+{
+    // Build the images of the sequence
+    OSFactory *pOsFactory = OSFactory::instance( getIntf() );
+    m_pImgSeq = pOsFactory->createOSGraphics( rBmpSeq.getWidth(),
+                                              rBmpSeq.getHeight() );
+    m_pImgSeq->drawBitmap( rBmpSeq, 0, 0 );
+
+    m_width = rBmpSeq.getWidth();
+    m_height = rBmpSeq.getHeight() / numImg;
+
+    // States
+    m_fsm.addState( "up" );
+    m_fsm.addState( "down" );
+
+    // Transitions
+    m_fsm.addTransition( "up", "mouse:left:down", "down", &m_cmdUpDown );
+    m_fsm.addTransition( "down", "mouse:left:up", "up", &m_cmdDownUp );
+    m_fsm.addTransition( "down", "motion", "down", &m_cmdMove );
+
+    // Initial state
+    m_fsm.setState( "up" );
+
+    // Observe the variable
+    m_rVariable.addObserver( this );
+}
+
+
+CtrlRadialSlider::~CtrlRadialSlider()
+{
+    m_rVariable.delObserver( this );
+    SKINS_DELETE( m_pImgSeq );
+}
+
+
+void CtrlRadialSlider::handleEvent( EvtGeneric &rEvent )
+{
+    // Save the event to use it in callbacks
+    m_pEvt = &rEvent;
+
+    m_fsm.handleTransition( rEvent.getAsString() );
+}
+
+
+bool CtrlRadialSlider::mouseOver( int x, int y ) const
+{
+    return m_pImgSeq->hit( x, y + m_position * m_height );
+}
+
+
+void CtrlRadialSlider::draw( OSGraphics &rImage, int xDest, int yDest )
+{
+    rImage.drawGraphics( *m_pImgSeq, 0, m_position * m_height, xDest, yDest,
+                         m_width, m_height );
+}
+
+
+void CtrlRadialSlider::onUpdate( Subject<VarPercent> &rVariable )
+{
+    m_position = (int)( m_rVariable.get() * m_numImg );
+    notifyLayout();
+}
+
+
+void CtrlRadialSlider::transUpDown( SkinObject *pCtrl )
+{
+    CtrlRadialSlider *pThis = (CtrlRadialSlider*)pCtrl;
+
+    EvtMouse *pEvtMouse = (EvtMouse*)pThis->m_pEvt;
+
+    // Change the position of the cursor, in non-blocking mode
+    pThis->setCursor( pEvtMouse->getXPos(), pEvtMouse->getYPos(), false );
+
+    pThis->captureMouse();
+}
+
+
+void CtrlRadialSlider::transDownUp( SkinObject *pCtrl )
+{
+    CtrlRadialSlider *pThis = (CtrlRadialSlider*)pCtrl;
+
+    pThis->releaseMouse();
+}
+
+
+void CtrlRadialSlider::transMove( SkinObject *pCtrl )
+{
+    CtrlRadialSlider *pThis = (CtrlRadialSlider*)pCtrl;
+
+    EvtMouse *pEvtMouse = (EvtMouse*)pThis->m_pEvt;
+
+    // Change the position of the cursor, in blocking mode
+    pThis->setCursor( pEvtMouse->getXPos(), pEvtMouse->getYPos(), true );
+}
+
+
+void CtrlRadialSlider::setCursor( int posX, int posY, bool blocking )
+{
+    // Get the position of the control
+    const Position *pPos = getPosition();
+    if( !pPos )
+    {
+        return;
+    }
+
+    // Compute the position relative to the center
+    int x = posX - pPos->getLeft() - m_width / 2;
+    int y = posY - pPos->getTop() - m_width / 2;
+
+    // Compute the polar coordinates. angle is -(-j,OM)
+    double r = sqrt(x*x + y*y);
+    if( r == 0 )
+    {
+        return;
+    }
+    double angle = acos(y/r);
+    if( x > 0 )
+    {
+        angle = 2*M_PI - angle;
+    }
+
+    if( angle >= m_minAngle && angle <= m_maxAngle )
+    {
+        double newVal = (angle - m_minAngle) / (m_maxAngle - m_minAngle);
+        // Avoid too fast moves of the cursor if blocking mode
+        if( !blocking || fabs( m_rVariable.get() - newVal ) < 0.5 )
+        {
+            m_rVariable.set( newVal );
+        }
+    }
+}
+
diff --git a/modules/gui/skins2/controls/ctrl_radialslider.hpp b/modules/gui/skins2/controls/ctrl_radialslider.hpp
new file mode 100644 (file)
index 0000000..3083720
--- /dev/null
@@ -0,0 +1,98 @@
+/*****************************************************************************
+ * ctrl_radialslider.hpp
+ *****************************************************************************
+ * Copyright (C) 2003 VideoLAN
+ * $Id: ctrl_radialslider.hpp,v 1.1 2004/01/03 23:31:33 asmax Exp $
+ *
+ * Authors: Cyril Deguet     <asmax@via.ecp.fr>
+ *          Olivier Teulière <ipkiss@via.ecp.fr>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111, USA.
+ *****************************************************************************/
+
+#ifndef CTRL_RADIALSLIDER_HPP
+#define CTRL_RADIALSLIDER_HPP
+
+#include "ctrl_generic.hpp"
+#include "../utils/fsm.hpp"
+#include "../utils/observer.hpp"
+
+
+class GenericBitmap;
+class OSGraphics;
+class VarPercent;
+
+
+/// Radial slider
+class CtrlRadialSlider: public CtrlGeneric, public Observer<VarPercent>
+{
+    public:
+        /// Create a radial slider with the given image, which must be
+        /// composed of numImg subimages of the same size
+        CtrlRadialSlider( intf_thread_t *pIntf, const GenericBitmap &rBmpSeq,
+                          int numImg, VarPercent &rVariable, double minAngle,
+                          double maxAngle, const UString &rHelp );
+
+        virtual ~CtrlRadialSlider();
+
+        /// Handle an event
+        virtual void handleEvent( EvtGeneric &rEvent );
+
+        /// Check whether coordinates are inside the control
+        virtual bool mouseOver( int x, int y ) const;
+
+        /// Draw the control on the given graphics
+        virtual void draw( OSGraphics &rImage, int xDest, int yDest );
+
+    private:
+        /// Finite state machine of the control
+        FSM m_fsm;
+        /// Number of sub-images in the slider image
+        int m_numImg;
+        /// Variable associated to the slider
+        VarPercent &m_rVariable;
+        /// Min and max angles of the button
+        double m_minAngle, m_maxAngle;
+        /// Callbacks objects
+        Callback m_cmdUpDown;
+        Callback m_cmdDownUp;
+        Callback m_cmdMove;
+        /// Position of the cursor
+        int m_position;
+        /// Size of an image
+        int m_width, m_height;
+        /// The last received event
+        EvtGeneric *m_pEvt;
+        /// Sequence of images
+        OSGraphics *m_pImgSeq;
+        /// Last saved position
+        int m_lastPos;
+
+        /// Callback functions
+        static void transUpDown( SkinObject *pCtrl );
+        static void transDownUp( SkinObject *pCtrl );
+        static void transMove( SkinObject *pCtrl );
+
+        /// Method called when the observed variable is modified
+        virtual void onUpdate( Subject<VarPercent> &rVariable );
+
+        /// Change the position of the cursor, with the given position of
+        /// the mouse (relative to the layout). Is blocking is true, the
+        /// the cursor cannot do more than a half turn
+        void setCursor( int posX, int posY, bool blocking );
+};
+
+
+#endif
diff --git a/modules/gui/skins2/controls/ctrl_resize.cpp b/modules/gui/skins2/controls/ctrl_resize.cpp
new file mode 100755 (executable)
index 0000000..3cb5512
--- /dev/null
@@ -0,0 +1,154 @@
+/*****************************************************************************
+ * ctrl_resize.cpp
+ *****************************************************************************
+ * Copyright (C) 2003 VideoLAN
+ * $Id: ctrl_resize.cpp,v 1.1 2004/01/03 23:31:33 asmax Exp $
+ *
+ * Authors: Cyril Deguet     <asmax@via.ecp.fr>
+ *          Olivier Teulière <ipkiss@via.ecp.fr>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111, USA.
+ *****************************************************************************/
+
+#include "ctrl_resize.hpp"
+#include "../events/evt_generic.hpp"
+#include "../events/evt_mouse.hpp"
+#include "../events/evt_motion.hpp"
+#include "../src/generic_layout.hpp"
+#include "../utils/position.hpp"
+#include "../commands/async_queue.hpp"
+#include "../commands/cmd_resize.hpp"
+
+
+CtrlResize::CtrlResize( intf_thread_t *pIntf, CtrlFlat &rCtrl,
+                        GenericLayout &rLayout, const UString &rHelp ):
+    CtrlFlat( pIntf, rHelp ), m_fsm( pIntf ), m_rCtrl( rCtrl ),
+    m_rLayout( rLayout ), m_cmdResizeResize( this, &transResizeResize ),
+    m_cmdStillResize( this, &transStillResize ),
+    m_cmdResizeStill( this, &transResizeStill )
+{
+    m_pEvt = NULL;
+    m_xPos = 0;
+    m_yPos = 0;
+
+    // States
+    m_fsm.addState( "resize" );
+    m_fsm.addState( "still" );
+
+    // Transitions
+    m_fsm.addTransition( "resize", "mouse:left:up:none", "still",
+                         &m_cmdResizeStill );
+    m_fsm.addTransition( "still", "mouse:left:down:none", "resize",
+                         &m_cmdStillResize );
+    m_fsm.addTransition( "resize", "motion", "resize", &m_cmdResizeResize );
+
+    m_fsm.setState( "still" );
+}
+
+
+bool CtrlResize::mouseOver( int x, int y ) const
+{
+    return m_rCtrl.mouseOver( x, y );
+}
+
+
+void CtrlResize::draw( OSGraphics &rImage, int xDest, int yDest )
+{
+    m_rCtrl.draw( rImage, xDest, yDest );
+}
+
+
+void CtrlResize::setLayout( GenericLayout *pLayout, const Position &rPosition )
+{
+    CtrlGeneric::setLayout( pLayout, rPosition );
+    // Set the layout of the decorated control as well
+    m_rCtrl.setLayout( pLayout, rPosition );
+}
+
+
+const Position *CtrlResize::getPosition() const
+{
+    return m_rCtrl.getPosition();
+}
+
+
+void CtrlResize::handleEvent( EvtGeneric &rEvent )
+{
+    m_pEvt = &rEvent;
+    m_fsm.handleTransition( rEvent.getAsString() );
+    // Transmit the event to the decorated control
+    // XXX: Is it really a good idea?
+    m_rCtrl.handleEvent( rEvent );
+}
+
+
+void CtrlResize::transStillResize( SkinObject *pCtrl )
+{
+    CtrlResize *pThis = (CtrlResize*)pCtrl;
+    EvtMouse *pEvtMouse = (EvtMouse*)pThis->m_pEvt;
+
+    pThis->m_xPos = pEvtMouse->getXPos();
+    pThis->m_yPos = pEvtMouse->getYPos();
+
+    pThis->captureMouse();
+
+    pThis->m_width = pThis->m_rLayout.getWidth();
+    pThis->m_height = pThis->m_rLayout.getHeight();
+}
+
+
+void CtrlResize::transResizeResize( SkinObject *pCtrl )
+{
+    CtrlResize *pThis = (CtrlResize*)pCtrl;
+    EvtMotion *pEvtMotion = (EvtMotion*)pThis->m_pEvt;
+
+    int newWidth = pEvtMotion->getXPos() - pThis->m_xPos + pThis->m_width;
+    int newHeight = pEvtMotion->getYPos() - pThis->m_yPos + pThis->m_height;
+
+    // Check boundaries
+    if( newWidth < pThis->m_rLayout.getMinWidth() )
+    {
+        newWidth = pThis->m_rLayout.getMinWidth();
+    }
+    if( newWidth > pThis->m_rLayout.getMaxWidth() )
+    {
+        newWidth = pThis->m_rLayout.getMaxWidth();
+    }
+    if( newHeight < pThis->m_rLayout.getMinHeight() )
+    {
+        newHeight = pThis->m_rLayout.getMinHeight();
+    }
+    if( newHeight > pThis->m_rLayout.getMaxHeight() )
+    {
+        newHeight = pThis->m_rLayout.getMaxHeight();
+    }
+
+    // Create a resize command
+    CmdGeneric *pCmd = new CmdResize( pThis->getIntf(), pThis->m_rLayout,
+                                      newWidth, newHeight );
+    // Push the command in the asynchronous command queue
+    AsyncQueue *pQueue = AsyncQueue::instance( pThis->getIntf() );
+    pQueue->remove( "resize" );
+    pQueue->push( CmdGenericPtr( pCmd ) );
+}
+
+
+void CtrlResize::transResizeStill( SkinObject *pCtrl )
+{
+    CtrlResize *pThis = (CtrlResize*)pCtrl;
+
+    pThis->releaseMouse();
+}
+
diff --git a/modules/gui/skins2/controls/ctrl_resize.hpp b/modules/gui/skins2/controls/ctrl_resize.hpp
new file mode 100644 (file)
index 0000000..93e093e
--- /dev/null
@@ -0,0 +1,83 @@
+/*****************************************************************************
+ * ctrl_resize.hpp
+ *****************************************************************************
+ * Copyright (C) 2003 VideoLAN
+ * $Id: ctrl_resize.hpp,v 1.1 2004/01/03 23:31:33 asmax Exp $
+ *
+ * Authors: Cyril Deguet     <asmax@via.ecp.fr>
+ *          Olivier Teulière <ipkiss@via.ecp.fr>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111, USA.
+ *****************************************************************************/
+
+#ifndef CTRL_RESIZE_HPP
+#define CTRL_RESIZE_HPP
+
+#include "ctrl_flat.hpp"
+#include "../commands/cmd_generic.hpp"
+#include "../utils/fsm.hpp"
+
+class GenericLayout;
+
+
+/// Control decorator for resizing windows
+class CtrlResize: public CtrlFlat
+{
+    public:
+        CtrlResize( intf_thread_t *pIntf, CtrlFlat &rCtrl,
+                    GenericLayout &rLayout, const UString &rHelp );
+        virtual ~CtrlResize() {}
+
+        /// Handle an event
+        virtual void handleEvent( EvtGeneric &rEvent );
+
+        /// Check whether coordinates are inside the decorated control
+        virtual bool mouseOver( int x, int y ) const;
+
+        /// Draw the control on the given graphics
+        virtual void draw( OSGraphics &rImage, int xDest, int yDest );
+
+        /// Set the position and the associated layout of the decorated control
+        virtual void setLayout( GenericLayout *pLayout,
+                                const Position &rPosition );
+
+        /// Get the position of the decorated control in the layout, if any
+        virtual const Position *getPosition() const;
+
+        static void transResizeResize( SkinObject *pCtrl );
+        static void transStillResize( SkinObject *pCtrl );
+        static void transResizeStill( SkinObject *pCtrl );
+
+    private:
+        FSM m_fsm;
+        /// Decorated CtrlFlat
+        CtrlFlat &m_rCtrl;
+        /// The layout resized by this control
+        GenericLayout &m_rLayout;
+        /// The last received event
+        EvtGeneric *m_pEvt;
+        /// Position of the click that started the resizing
+        int m_xPos, m_yPos;
+        /// Callbacks
+        Callback m_cmdResizeResize;
+        Callback m_cmdStillResize;
+        Callback m_cmdResizeStill;
+
+        // Size of the layout, before resizing
+        int m_width, m_height;
+};
+
+#endif
+
diff --git a/modules/gui/skins2/controls/ctrl_slider.cpp b/modules/gui/skins2/controls/ctrl_slider.cpp
new file mode 100644 (file)
index 0000000..9564d39
--- /dev/null
@@ -0,0 +1,411 @@
+/*****************************************************************************
+ * ctrl_slider.cpp
+ *****************************************************************************
+ * Copyright (C) 2003 VideoLAN
+ * $Id: ctrl_slider.cpp,v 1.1 2004/01/03 23:31:33 asmax Exp $
+ *
+ * Authors: Cyril Deguet     <asmax@via.ecp.fr>
+ *          Olivier Teulière <ipkiss@via.ecp.fr>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111, USA.
+ *****************************************************************************/
+
+#include "ctrl_slider.hpp"
+#include "../events/evt_enter.hpp"
+#include "../events/evt_mouse.hpp"
+#include "../events/evt_scroll.hpp"
+#include "../src/generic_bitmap.hpp"
+#include "../src/generic_window.hpp"
+#include "../src/os_factory.hpp"
+#include "../src/os_graphics.hpp"
+#include "../utils/position.hpp"
+#include "../utils/var_percent.hpp"
+
+
+#define RANGE 40
+#define SCROLL_STEP 0.05
+
+
+CtrlSliderCursor::CtrlSliderCursor( intf_thread_t *pIntf,
+                                    const GenericBitmap &rBmpUp,
+                                    const GenericBitmap &rBmpOver,
+                                    const GenericBitmap &rBmpDown,
+                                    const Bezier &rCurve,
+                                    VarPercent &rVariable,
+                                    VarBool *pVisible,
+                                    const UString &rTooltip,
+                                    const UString &rHelp ):
+    CtrlGeneric( pIntf, rHelp ), m_fsm( pIntf ), m_rVariable( rVariable ),
+    m_pVisible( pVisible ), m_tooltip( rTooltip ),
+    m_width( rCurve.getWidth() ), m_height( rCurve.getHeight() ),
+    m_cmdOverDown( this, &transOverDown ),
+    m_cmdDownOver( this, &transDownOver ), m_cmdOverUp( this, &transOverUp ),
+    m_cmdUpOver( this, &transUpOver ), m_cmdMove( this, &transMove ),
+    m_cmdScroll( this, &transScroll ),
+    m_lastPercentage( 0 ), m_xOffset( 0 ), m_yOffset( 0 ),
+    m_pEvt( NULL ), m_curve( rCurve )
+{
+    // Build the images of the cursor
+    OSFactory *pOsFactory = OSFactory::instance( getIntf() );
+    m_pImgUp = pOsFactory->createOSGraphics( rBmpUp.getWidth(),
+                                             rBmpUp.getHeight() );
+    m_pImgUp->drawBitmap( rBmpUp, 0, 0 );
+    m_pImgDown = pOsFactory->createOSGraphics( rBmpDown.getWidth(),
+                                               rBmpDown.getHeight() );
+    m_pImgDown->drawBitmap( rBmpDown, 0, 0 );
+    m_pImgOver = pOsFactory->createOSGraphics( rBmpOver.getWidth(),
+                                               rBmpOver.getHeight() );
+    m_pImgOver->drawBitmap( rBmpOver, 0, 0 );
+
+    // States
+    m_fsm.addState( "up" );
+    m_fsm.addState( "over" );
+    m_fsm.addState( "down" );
+
+    // Transitions
+    m_fsm.addTransition( "over", "mouse:left:down", "down",
+                         &m_cmdOverDown );
+    m_fsm.addTransition( "down", "mouse:left:up", "over",
+                         &m_cmdDownOver );
+    m_fsm.addTransition( "over", "leave", "up", &m_cmdOverUp );
+    m_fsm.addTransition( "up", "enter", "over", &m_cmdUpOver );
+    m_fsm.addTransition( "down", "motion", "down", &m_cmdMove );
+    m_fsm.addTransition( "over", "scroll", "over", &m_cmdScroll );
+
+    // Initial state
+    m_fsm.setState( "up" );
+    m_pImg = m_pImgUp;
+
+    // Observe the position variable
+    m_rVariable.addObserver( this );
+
+    // Observe the visibility variable
+    if( m_pVisible )
+    {
+        m_pVisible->addObserver( this );
+    }
+
+    // Initial position of the cursor
+    m_lastPercentage = m_rVariable.get();
+}
+
+
+CtrlSliderCursor::~CtrlSliderCursor()
+{
+    m_rVariable.delObserver( this );
+    if( m_pVisible )
+    {
+        m_pVisible->delObserver( this );
+    }
+    SKINS_DELETE( m_pImgUp );
+    SKINS_DELETE( m_pImgDown );
+    SKINS_DELETE( m_pImgOver );
+}
+
+
+void CtrlSliderCursor::handleEvent( EvtGeneric &rEvent )
+{
+    // Save the event to use it in callbacks
+    m_pEvt = &rEvent;
+
+    m_fsm.handleTransition( rEvent.getAsString() );
+}
+
+
+bool CtrlSliderCursor::mouseOver( int x, int y ) const
+{
+    if( m_pImg )
+    {
+        // Compute the position of the cursor
+        int xPos, yPos;
+        m_curve.getPoint( m_rVariable.get(), xPos, yPos );
+
+        // Compute the resize factors
+        double factorX = 0, factorY = 0;
+        getResizeFactors( factorX, factorY );
+        xPos = (int)(xPos * factorX);
+        yPos = (int)(yPos * factorY);
+
+        return m_pImg->hit( x - xPos + m_pImg->getWidth() / 2,
+                            y - yPos + m_pImg->getHeight() / 2 );
+    }
+    else
+    {
+        return false;
+    }
+}
+
+
+void CtrlSliderCursor::draw( OSGraphics &rImage, int xDest, int yDest )
+{
+    if( m_pImg && (!m_pVisible || m_pVisible->get()) )
+    {
+        // Compute the position of the cursor
+        int xPos, yPos;
+        m_curve.getPoint( m_rVariable.get(), xPos, yPos );
+
+        // Compute the resize factors
+        double factorX = 0, factorY = 0;
+        getResizeFactors( factorX, factorY );
+        xPos = (int)(xPos * factorX);
+        yPos = (int)(yPos * factorY);
+
+        // Draw the current image
+        rImage.drawGraphics( *m_pImg, 0, 0,
+                             xDest + xPos - m_pImg->getWidth() / 2,
+                             yDest + yPos - m_pImg->getHeight() / 2 );
+    }
+}
+
+
+void CtrlSliderCursor::onUpdate( Subject<VarPercent> &rVariable )
+{
+    // The position has changed
+    notifyLayout();
+}
+
+
+void CtrlSliderCursor::onUpdate( Subject<VarBool> &rVariable )
+{
+    // The visibility variable has changed
+    notifyLayout();
+}
+
+
+void CtrlSliderCursor::transOverDown( SkinObject *pCtrl )
+{
+    CtrlSliderCursor *pThis = (CtrlSliderCursor*)pCtrl;
+    EvtMouse *pEvtMouse = (EvtMouse*)pThis->m_pEvt;
+
+    // Compute the resize factors
+    double factorX = 0, factorY = 0;
+    pThis->getResizeFactors( factorX, factorY );
+
+    // Compute the offset
+    int tempX, tempY;
+    pThis->m_curve.getPoint( pThis->m_rVariable.get(), tempX, tempY );
+    pThis->m_xOffset = pEvtMouse->getXPos() - (int)(tempX * factorX);
+    pThis->m_yOffset = pEvtMouse->getYPos() - (int)(tempY * factorY);
+
+    pThis->captureMouse();
+    pThis->m_pImg = pThis->m_pImgDown;
+    pThis->notifyLayout();
+}
+
+
+void CtrlSliderCursor::transDownOver( SkinObject *pCtrl )
+{
+    CtrlSliderCursor *pThis = (CtrlSliderCursor*)pCtrl;
+
+    // Save the position
+    pThis->m_lastPercentage = pThis->m_rVariable.get();
+
+    pThis->releaseMouse();
+    pThis->m_pImg = pThis->m_pImgUp;
+    pThis->notifyLayout();
+}
+
+
+void CtrlSliderCursor::transUpOver( SkinObject *pCtrl )
+{
+    CtrlSliderCursor *pThis = (CtrlSliderCursor*)pCtrl;
+
+    pThis->m_pImg = pThis->m_pImgOver;
+    pThis->notifyLayout();
+}
+
+
+void CtrlSliderCursor::transOverUp( SkinObject *pCtrl )
+{
+    CtrlSliderCursor *pThis = (CtrlSliderCursor*)pCtrl;
+
+    pThis->m_pImg = pThis->m_pImgUp;
+    pThis->notifyLayout();
+}
+
+
+void CtrlSliderCursor::transMove( SkinObject *pCtrl )
+{
+    CtrlSliderCursor *pThis = (CtrlSliderCursor*)pCtrl;
+    EvtMouse *pEvtMouse = (EvtMouse*)pThis->m_pEvt;
+
+    // Get the position of the control
+    const Position *pPos = pThis->getPosition();
+
+    // Compute the resize factors
+    double factorX = 0, factorY = 0;
+    pThis->getResizeFactors( factorX, factorY );
+
+    // XXX: This could be optimized a little bit
+    if( pThis->m_curve.getMinDist(
+        (int)((pEvtMouse->getXPos() - pPos->getLeft()) / factorX),
+        (int)((pEvtMouse->getYPos() - pPos->getTop()) / factorY) ) < RANGE )
+    {
+        double percentage = pThis->m_curve.getNearestPercent(
+            (int)((pEvtMouse->getXPos() - pThis->m_xOffset) / factorX),
+            (int)((pEvtMouse->getYPos() - pThis->m_yOffset) / factorY) );
+        pThis->m_rVariable.set( percentage );
+    }
+    else
+    {
+        pThis->m_rVariable.set( pThis->m_lastPercentage );
+    }
+}
+
+void CtrlSliderCursor::transScroll( SkinObject *pCtrl )
+{
+    CtrlSliderCursor *pThis = (CtrlSliderCursor*)pCtrl;
+    EvtScroll *pEvtScroll = (EvtScroll*)pThis->m_pEvt;
+
+    int direction = pEvtScroll->getDirection();
+
+    double percentage = pThis->m_rVariable.get();
+    if( direction == EvtScroll::kUp )
+    {
+        percentage += SCROLL_STEP;
+    }
+    else
+    {
+        percentage -= SCROLL_STEP;
+    }
+
+    pThis->m_rVariable.set( percentage );
+}
+
+
+void CtrlSliderCursor::getResizeFactors( double &rFactorX,
+                                         double &rFactorY ) const
+{
+    // Get the position of the control
+    const Position *pPos = getPosition();
+
+    rFactorX = 1.0;
+    rFactorY = 1.0;
+
+    // Compute the resize factors
+    if( m_width > 0 )
+    {
+        rFactorX = (double)pPos->getWidth() / (double)m_width;
+    }
+    if( m_height > 0 )
+    {
+        rFactorY = (double)pPos->getHeight() / (double)m_height;
+    }
+}
+
+
+
+CtrlSliderBg::CtrlSliderBg( intf_thread_t *pIntf, CtrlSliderCursor &rCursor,
+                            const Bezier &rCurve, VarPercent &rVariable,
+                            int thickness, VarBool *pVisible,
+                            const UString &rHelp ):
+    CtrlGeneric( pIntf, rHelp ), m_rCursor( rCursor ), m_rVariable( rVariable ),
+    m_thickness( thickness ), m_pVisible( pVisible ), m_curve( rCurve ),
+    m_width( rCurve.getWidth() ), m_height( rCurve.getHeight() )
+{
+}
+
+
+bool CtrlSliderBg::mouseOver( int x, int y ) const
+{
+    if( m_pVisible && !m_pVisible->get() )
+    {
+        return false;
+    }
+
+    // Compute the resize factors
+    double factorX = 0, factorY = 1.0;
+    getResizeFactors( factorX, factorY );
+
+    return (m_curve.getMinDist( (int)(x / factorY),
+                                (int)(y / factorY) ) < m_thickness );
+}
+
+
+void CtrlSliderBg::handleEvent( EvtGeneric &rEvent )
+{
+    if( rEvent.getAsString().find( "mouse:left:down" ) != string::npos )
+    {
+        // Compute the resize factors
+        double factorX = 0, factorY = 1.0;
+        getResizeFactors( factorX, factorY );
+
+        // Get the position of the control
+        const Position *pPos = getPosition();
+
+        // Get the value corresponding to the position of the mouse
+        EvtMouse &rEvtMouse = (EvtMouse&)rEvent;
+        int x = rEvtMouse.getXPos();
+        int y = rEvtMouse.getYPos();
+        m_rVariable.set( m_curve.getNearestPercent(
+                            (int)((x - pPos->getLeft()) / factorX),
+                            (int)((y - pPos->getTop()) / factorY) ) );
+
+        // Forward the clic to the cursor
+        EvtMouse evt( getIntf(), x, y, EvtMouse::kLeft, EvtMouse::kDown );
+        GenericWindow *pWin = getWindow();
+        if( pWin )
+        {
+            EvtEnter evtEnter( getIntf() );
+            // XXX It was not supposed to be implemented like that !!
+            pWin->forwardEvent( evtEnter, m_rCursor );
+            pWin->forwardEvent( evt, m_rCursor );
+        }
+    }
+    else if( rEvent.getAsString().find( "scroll" ) != string::npos )
+    {
+        int direction = ((EvtScroll&)rEvent).getDirection();
+
+        double percentage = m_rVariable.get();
+        if( direction == EvtScroll::kUp )
+        {
+            percentage += SCROLL_STEP;
+        }
+        else
+        {
+            percentage -= SCROLL_STEP;
+        }
+
+        m_rVariable.set( percentage );
+    }
+}
+
+
+void CtrlSliderBg::onUpdate( Subject<VarBool> &rVariable )
+{
+    // The visibility variable has changed
+    notifyLayout();
+}
+
+
+void CtrlSliderBg::getResizeFactors( double &rFactorX, double &rFactorY ) const
+{
+    // Get the position of the control
+    const Position *pPos = getPosition();
+
+    rFactorX = 1.0;
+    rFactorY = 1.0;
+
+    // Compute the resize factors
+    if( m_width > 0 )
+    {
+        rFactorX = (double)pPos->getWidth() / (double)m_width;
+    }
+    if( m_height > 0 )
+    {
+        rFactorY = (double)pPos->getHeight() / (double)m_height;
+    }
+}
+
diff --git a/modules/gui/skins2/controls/ctrl_slider.hpp b/modules/gui/skins2/controls/ctrl_slider.hpp
new file mode 100755 (executable)
index 0000000..13ed4c5
--- /dev/null
@@ -0,0 +1,158 @@
+/*****************************************************************************
+ * ctrl_slider.hpp
+ *****************************************************************************
+ * Copyright (C) 2003 VideoLAN
+ * $Id: ctrl_slider.hpp,v 1.1 2004/01/03 23:31:33 asmax Exp $
+ *
+ * Authors: Cyril Deguet     <asmax@via.ecp.fr>
+ *          Olivier Teulière <ipkiss@via.ecp.fr>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111, USA.
+ *****************************************************************************/
+
+#ifndef CTRL_SLIDER_HPP
+#define CTRL_SLIDER_HPP
+
+#include "ctrl_generic.hpp"
+#include "../utils/bezier.hpp"
+#include "../utils/fsm.hpp"
+#include "../utils/observer.hpp"
+
+
+class GenericBitmap;
+class OSGraphics;
+class VarPercent;
+class VarBool;
+
+
+/// Cursor of a slider
+class CtrlSliderCursor: public CtrlGeneric, public Observer<VarPercent>,
+    public Observer<VarBool>
+{
+    public:
+        /// Create a cursor with 3 images (which are NOT copied, be careful)
+        /// If pVisible is NULL, the control is always visible
+        CtrlSliderCursor( intf_thread_t *pIntf, const GenericBitmap &rBmpUp,
+                          const GenericBitmap &rBmpOver,
+                          const GenericBitmap &rBmpDown,
+                          const Bezier &rCurve, VarPercent &rVariable,
+                          VarBool *pVisible, const UString &rTooltip,
+                          const UString &rHelp );
+
+        virtual ~CtrlSliderCursor();
+
+        /// Handle an event
+        virtual void handleEvent( EvtGeneric &rEvent );
+
+        /// Check whether coordinates are inside the control
+        virtual bool mouseOver( int x, int y ) const;
+
+        /// Draw the control on the given graphics
+        virtual void draw( OSGraphics &rImage, int xDest, int yDest );
+
+        /// Get the text of the tooltip
+        virtual UString getTooltipText() const { return m_tooltip; }
+
+    private:
+        /// Finite state machine of the control
+        FSM m_fsm;
+        /// Variable associated to the cursor
+        VarPercent &m_rVariable;
+        /// Visibility variable
+        VarBool *m_pVisible;
+        /// Tooltip text
+        const UString m_tooltip;
+        /// Initial size of the control
+        int m_width, m_height;
+        /// Callback objects
+        Callback m_cmdOverDown;
+        Callback m_cmdDownOver;
+        Callback m_cmdOverUp;
+        Callback m_cmdUpOver;
+        Callback m_cmdMove;
+        Callback m_cmdScroll;
+        /// Position of the cursor
+        int m_xPosition, m_yPosition;
+        /// Last saved position of the cursor (stored as a percentage)
+        double m_lastPercentage;
+        /// Offset between the mouse pointer and the center of the cursor
+        int m_xOffset, m_yOffset;
+        /// The last received event
+        EvtGeneric *m_pEvt;
+        /// Images of the cursor in the differents states
+        OSGraphics *m_pImgUp, *m_pImgOver, *m_pImgDown;
+        /// Current image
+        OSGraphics *m_pImg;
+        /// Bezier curve of the slider
+        const Bezier m_curve;
+
+        /// Callback functions
+        static void transOverDown( SkinObject *pCtrl );
+        static void transDownOver( SkinObject *pCtrl );
+        static void transOverUp( SkinObject *pCtrl );
+        static void transUpOver( SkinObject *pCtrl );
+        static void transMove( SkinObject *pCtrl );
+        static void transScroll( SkinObject *pCtrl );
+
+        /// Method called when the position variable is modified
+        virtual void onUpdate( Subject<VarPercent> &rVariable );
+
+        /// Method called when the visibility variable is modified
+        virtual void onUpdate( Subject<VarBool> &rVariable );
+
+        /// Methode to compute the resize factors
+        void getResizeFactors( double &rFactorX, double &rFactorY ) const;
+};
+
+
+/// Slider background
+class CtrlSliderBg: public CtrlGeneric
+{
+    public:
+        /// If pVisible is NULL, the control is always visible
+        CtrlSliderBg( intf_thread_t *pIntf, CtrlSliderCursor &rCursor,
+                      const Bezier &rCurve, VarPercent &rVariable,
+                      int thickness, VarBool *pVisible, const UString &rHelp );
+        virtual ~CtrlSliderBg() {}
+
+        /// Tell whether the mouse is over the control
+        virtual bool mouseOver( int x, int y ) const;
+
+        /// Handle an event
+        virtual void handleEvent( EvtGeneric &rEvent );
+
+    private:
+        /// Cursor of the slider
+        CtrlSliderCursor &m_rCursor;
+        /// Variable associated to the slider
+        VarPercent &m_rVariable;
+        /// Thickness of the curve
+        int m_thickness;
+        /// Visibility variable
+        VarBool *m_pVisible;
+        /// Bezier curve of the slider
+        const Bezier m_curve;
+        /// Initial size of the control
+        int m_width, m_height;
+
+        /// Methode to compute the resize factors
+        void getResizeFactors( double &rFactorX, double &rFactorY ) const;
+
+        /// Method called when the visibility variable is modified
+        virtual void onUpdate( Subject<VarBool> &rVariable );
+};
+
+
+#endif
diff --git a/modules/gui/skins2/controls/ctrl_text.cpp b/modules/gui/skins2/controls/ctrl_text.cpp
new file mode 100755 (executable)
index 0000000..6c1cae8
--- /dev/null
@@ -0,0 +1,317 @@
+/*****************************************************************************
+ * ctrl_text.cpp
+ *****************************************************************************
+ * Copyright (C) 2003 VideoLAN
+ * $Id: ctrl_text.cpp,v 1.1 2004/01/03 23:31:33 asmax Exp $
+ *
+ * Authors: Cyril Deguet     <asmax@via.ecp.fr>
+ *          Olivier Teulière <ipkiss@via.ecp.fr>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111, USA.
+ *****************************************************************************/
+
+#include "ctrl_text.hpp"
+#include "../events/evt_generic.hpp"
+#include "../events/evt_mouse.hpp"
+#include "../src/generic_bitmap.hpp"
+#include "../src/generic_font.hpp"
+#include "../src/os_factory.hpp"
+#include "../src/os_graphics.hpp"
+#include "../src/os_timer.hpp"
+#include "../utils/position.hpp"
+#include "../utils/ustring.hpp"
+#include "../utils/var_text.hpp"
+
+
+#define MOVING_TEXT_STEP 3
+#define MOVING_TEXT_DELAY 200
+#define SEPARATOR_STRING "   "
+
+
+CtrlText::CtrlText( intf_thread_t *pIntf, VarText &rVariable,
+                    const GenericFont &rFont, const UString &rHelp,
+                    uint32_t color ):
+    CtrlGeneric( pIntf, rHelp ), m_fsm( pIntf ), m_rVariable( rVariable ),
+    m_cmdToManual( this, &transToManual ),
+    m_cmdManualMoving( this, &transManualMoving ),
+    m_cmdManualStill( this, &transManualStill ),
+    m_cmdMove( this, &transMove ),
+    m_pEvt( NULL ), m_rFont( rFont ), m_color( color ),
+    m_pImg( NULL ), m_pImgDouble( NULL ), m_pCurrImg( NULL ),
+    m_xPos( 0 ), m_xOffset( 0 )
+{
+    m_pTimer = OSFactory::instance( getIntf() )->createOSTimer(
+        Callback( this, &updateText ) );
+
+    // States
+    m_fsm.addState( "still" );
+    m_fsm.addState( "moving" );
+    m_fsm.addState( "manual1" );
+    m_fsm.addState( "manual2" );
+    m_fsm.addState( "outStill" );
+    m_fsm.addState( "outMoving" );
+
+    // Transitions
+    m_fsm.addTransition( "still", "mouse:left:down", "manual1",
+                         &m_cmdToManual );
+    m_fsm.addTransition( "manual1", "mouse:left:up", "moving",
+                         &m_cmdManualMoving );
+    m_fsm.addTransition( "moving", "mouse:left:down", "manual2",
+                         &m_cmdToManual );
+    m_fsm.addTransition( "manual2", "mouse:left:up", "still",
+                         &m_cmdManualStill );
+    m_fsm.addTransition( "manual1", "motion", "manual1", &m_cmdMove );
+    m_fsm.addTransition( "manual2", "motion", "manual2", &m_cmdMove );
+    m_fsm.addTransition( "still", "leave", "outStill" );
+    m_fsm.addTransition( "outStill", "enter", "still" );
+    m_fsm.addTransition( "moving", "leave", "outMoving" );
+    m_fsm.addTransition( "outMoving", "enter", "moving" );
+
+    // Initial state
+    m_fsm.setState( "outStill" );
+
+    // Observe the variable
+    m_rVariable.addObserver( this );
+
+    // Set the text
+    displayText( m_rVariable.get() );
+}
+
+
+CtrlText::~CtrlText()
+{
+    m_rVariable.delObserver( this );
+    if( m_pTimer )
+    {
+        delete m_pTimer;
+    }
+    if( m_pImg )
+    {
+        delete m_pImg;
+    }
+    if( m_pImgDouble )
+    {
+        delete m_pImgDouble;
+    }
+}
+
+
+void CtrlText::handleEvent( EvtGeneric &rEvent )
+{
+    // Save the event to use it in callbacks
+    m_pEvt = &rEvent;
+
+    m_fsm.handleTransition( rEvent.getAsString() );
+}
+
+
+bool CtrlText::mouseOver( int x, int y ) const
+{
+    if( m_pCurrImg )
+    {
+        // We have 3 different ways of deciding when to return true here:
+        //  1) the mouse is exactly over the text (so if you click between two
+        //     letters, the text control doesn't catch the event)
+        //  2) the mouse is over the rectangle of the control
+        //  3) the mouse is over the rectangle of the visible text
+        // I don't know which one is the best...
+#if 0
+        return( x >= 0 && x < getPosition()->getWidth()
+             && m_pCurrImg->hit( x - m_xPos, y ) );
+#endif
+#if 1
+        return( x >= 0 && x < getPosition()->getWidth()
+             && y >= 0 && y < getPosition()->getHeight() );
+#endif
+#if 0
+        return( x >= 0 && x < getPosition()->getWidth()
+             && y >= 0 && y < getPosition()->getHeight()
+             && x < m_pCurrImg->getWidth() && x < m_pCurrImg->getHeight() );
+#endif
+    }
+    else
+    {
+        return false;
+    }
+}
+
+
+void CtrlText::draw( OSGraphics &rImage, int xDest, int yDest )
+{
+    if( m_pCurrImg )
+    {
+        // Compute the dimensions to draw
+        int width = min( m_pCurrImg->getWidth() + m_xPos,
+                         getPosition()->getWidth() );
+        int height = min( m_pCurrImg->getHeight(), getPosition()->getHeight() );
+        // Draw the current image
+        rImage.drawBitmap( *m_pCurrImg, -m_xPos, 0, xDest, yDest,
+                           width, height );
+    }
+}
+
+
+void CtrlText::setText( const UString &rText, uint32_t color )
+{
+    // Change the color
+    if( color != 0xFFFFFFFF )
+    {
+        m_color = color;
+    }
+
+    // Change the text
+    m_rVariable.set( rText );
+}
+
+
+void CtrlText::onUpdate( Subject<VarText> &rVariable )
+{
+    displayText( m_rVariable.get() );
+}
+
+
+void CtrlText::displayText( const UString &rText )
+{
+    m_pTimer->stop();
+
+    // Create the images ('normal' and 'double') from the text
+    // 'Normal' image
+    if( m_pImg )
+    {
+        delete m_pImg;
+    }
+    m_pImg = m_rFont.drawString( rText, m_color );
+    // 'Double' image
+    const UString doubleStringWithSep = rText + SEPARATOR_STRING + rText;
+    if( m_pImgDouble )
+    {
+        delete m_pImgDouble;
+    }
+    m_pImgDouble = m_rFont.drawString( doubleStringWithSep, m_color );
+
+    // Update the current image used, as if the control size had changed
+    onChangePosition();
+
+    // XXX: will this always work?
+    m_fsm.setState( "outStill" );
+    notifyLayout();
+}
+
+
+void CtrlText::onChangePosition()
+{
+    if( getPosition() )
+    {
+        if( m_pImg->getWidth() < getPosition()->getWidth() )
+        {
+            m_pCurrImg = m_pImg;
+        }
+        else
+        {
+            m_pCurrImg = m_pImgDouble;
+        }
+    }
+    else
+    {
+        // m_pImg is a better default value than m_pImgDouble, but anyway we
+        // don't care because the control is never drawn without position :)
+        m_pCurrImg = m_pImg;
+    }
+}
+
+
+void CtrlText::transToManual( SkinObject *pCtrl )
+{
+    CtrlText *pThis = (CtrlText*)pCtrl;
+    EvtMouse *pEvtMouse = (EvtMouse*)pThis->m_pEvt;
+
+    // Compute the offset
+    pThis->m_xOffset = pEvtMouse->getXPos() - pThis->m_xPos;
+
+    pThis->m_pTimer->stop();
+    pThis->captureMouse();
+}
+
+
+void CtrlText::transManualMoving( SkinObject *pCtrl )
+{
+    CtrlText *pThis = (CtrlText*)pCtrl;
+    pThis->releaseMouse();
+
+    // Start the automatic movement, but only if the text is wider than the
+    // control
+    if( pThis->m_pImg->getWidth() >= pThis->getPosition()->getWidth() )
+    {
+        // The current image may have been set incorrectly in displayText(), so
+        // set the correct value
+        pThis->m_pCurrImg = pThis->m_pImgDouble;
+
+        pThis->m_pTimer->start( MOVING_TEXT_DELAY, false );
+    }
+}
+
+
+void CtrlText::transManualStill( SkinObject *pCtrl )
+{
+    CtrlText *pThis = (CtrlText*)pCtrl;
+    pThis->releaseMouse();
+}
+
+
+void CtrlText::transMove( SkinObject *pCtrl )
+{
+    CtrlText *pThis = (CtrlText*)pCtrl;
+    EvtMouse *pEvtMouse = (EvtMouse*)pThis->m_pEvt;
+
+    // Do nothing if the text fits in the control
+    if( pThis->m_pImg->getWidth() >= pThis->getPosition()->getWidth() )
+    {
+        // The current image may have been set incorrectly in displayText(), so
+        // we set the correct value
+        pThis->m_pCurrImg = pThis->m_pImgDouble;
+
+        // Compute the new position of the left side, and make sure it is
+        // in the correct range
+        pThis->m_xPos = (pEvtMouse->getXPos() - pThis->m_xOffset);
+        pThis->adjust( pThis->m_xPos );
+
+        pThis->notifyLayout();
+    }
+}
+
+
+void CtrlText::updateText( SkinObject *pCtrl )
+{
+    CtrlText *pThis = (CtrlText*)pCtrl;
+
+    pThis->m_xPos -= MOVING_TEXT_STEP;
+    pThis->adjust( pThis->m_xPos );
+
+    pThis->notifyLayout();
+}
+
+
+void CtrlText::adjust( int &position )
+{
+    // {m_pImgDouble->getWidth()  - m_pImg->getWidth()} is the period of the
+    // bitmap; remember that the string used to generate m_pImgDouble is of the
+    // form: "foo  foo", the number of spaces being a parameter
+    position %= m_pImgDouble->getWidth()  - m_pImg->getWidth();
+    if( position > 0 )
+    {
+        position -= m_pImgDouble->getWidth()  - m_pImg->getWidth();
+    }
+}
+
diff --git a/modules/gui/skins2/controls/ctrl_text.hpp b/modules/gui/skins2/controls/ctrl_text.hpp
new file mode 100644 (file)
index 0000000..1302549
--- /dev/null
@@ -0,0 +1,116 @@
+/*****************************************************************************
+ * ctrl_text.hpp
+ *****************************************************************************
+ * Copyright (C) 2003 VideoLAN
+ * $Id: ctrl_text.hpp,v 1.1 2004/01/03 23:31:33 asmax Exp $
+ *
+ * Authors: Cyril Deguet     <asmax@via.ecp.fr>
+ *          Olivier Teulière <ipkiss@via.ecp.fr>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111, USA.
+ *****************************************************************************/
+
+#ifndef CTRL_TEXT_HPP
+#define CTRL_TEXT_HPP
+
+#include "ctrl_generic.hpp"
+#include "../utils/fsm.hpp"
+#include "../utils/observer.hpp"
+#include <string>
+
+class GenericFont;
+class GenericBitmap;
+class OSTimer;
+class UString;
+class VarText;
+
+
+/// Class for control text
+class CtrlText: public CtrlGeneric, public Observer<VarText>
+{
+    public:
+        /// Create a text control with the optional given color
+        CtrlText( intf_thread_t *pIntf, VarText &rVariable,
+                  const GenericFont &rFont, const UString &rHelp,
+                  uint32_t color = 0 );
+        virtual ~CtrlText();
+
+        /// Handle an event
+        virtual void handleEvent( EvtGeneric &rEvent );
+
+        /// Check whether coordinates are inside the control
+        virtual bool mouseOver( int x, int y ) const;
+
+        /// Draw the control on the given graphics
+        virtual void draw( OSGraphics &rImage, int xDest, int yDest );
+
+        /// Set the text of the control, with an optional color
+        /// This takes effect immediatly
+        void setText( const UString &rText, uint32_t color = 0xFFFFFFFF );
+
+    private:
+        /// Finite state machine of the control
+        FSM m_fsm;
+        /// Variable associated to the control
+        VarText &m_rVariable;
+        /// Callback objects
+        Callback m_cmdToManual;
+        Callback m_cmdManualMoving;
+        Callback m_cmdManualStill;
+        Callback m_cmdMove;
+        /// The last received event
+        EvtGeneric *m_pEvt;
+        /// Font used to render the text
+        const GenericFont &m_rFont;
+        /// Color of the text
+        uint32_t m_color;
+        /// Image of the text
+        GenericBitmap *m_pImg;
+        /// Image of the text, repeated twice and with some blank between;
+        /// useful to display a 'circular' moving text...
+        GenericBitmap *m_pImgDouble;
+        /// Current image (should always be equal to m_pImg or m_pImgDouble)
+        GenericBitmap *m_pCurrImg;
+        /// Position of the left side of the moving text
+        int m_xPos;
+        /// Offset between the mouse pointer and the left side of the
+        /// moving text
+        int m_xOffset;
+         /// Timer to move the text
+        OSTimer *m_pTimer;
+
+        /// Callback functions
+        static void transToManual( SkinObject *pCtrl );
+        static void transManualMoving( SkinObject *pCtrl );
+        static void transManualStill( SkinObject *pCtrl );
+        static void transMove( SkinObject *pCtrl );
+        /// Callback for the timer
+        static void updateText( SkinObject *pCtrl );
+
+        /// Method called when the observed variable is modified
+        virtual void onUpdate( Subject<VarText> &rVariable );
+
+        /// Display the text on the control
+        void displayText( const UString &rText );
+
+        /// Helper function to set the position in the correct interval
+        void adjust( int &position );
+
+        /// Update the behaviour of the text whenever the control size changes
+        virtual void onChangePosition();
+};
+
+
+#endif
diff --git a/modules/gui/skins2/events/evt_enter.hpp b/modules/gui/skins2/events/evt_enter.hpp
new file mode 100644 (file)
index 0000000..3f30c54
--- /dev/null
@@ -0,0 +1,43 @@
+/*****************************************************************************
+ * evt_enter.hpp
+ *****************************************************************************
+ * Copyright (C) 2003 VideoLAN
+ * $Id: evt_enter.hpp,v 1.1 2004/01/03 23:31:33 asmax Exp $
+ *
+ * Authors: Cyril Deguet     <asmax@via.ecp.fr>
+ *          Olivier Teulière <ipkiss@via.ecp.fr>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111, USA.
+ *****************************************************************************/
+
+#ifndef EVT_ENTER_HPP
+#define EVT_ENTER_HPP
+
+#include "evt_input.hpp"
+
+
+/// Mouse enter event
+class EvtEnter: public EvtInput
+{
+    public:
+        EvtEnter( intf_thread_t *pIntf ): EvtInput( pIntf ) {}
+        virtual ~EvtEnter() {}
+
+        /// Return the type of event
+        virtual const string getAsString() const { return "enter"; }
+};
+
+
+#endif
diff --git a/modules/gui/skins2/events/evt_focus.hpp b/modules/gui/skins2/events/evt_focus.hpp
new file mode 100644 (file)
index 0000000..ca45ad9
--- /dev/null
@@ -0,0 +1,51 @@
+/*****************************************************************************
+ * evt_focus.hpp
+ *****************************************************************************
+ * Copyright (C) 2003 VideoLAN
+ * $Id: evt_focus.hpp,v 1.1 2004/01/03 23:31:33 asmax Exp $
+ *
+ * Authors: Cyril Deguet     <asmax@via.ecp.fr>
+ *          Olivier Teulière <ipkiss@via.ecp.fr>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111, USA.
+ *****************************************************************************/
+
+#ifndef EVT_FOCUS_HPP
+#define EVT_FOCUS_HPP
+
+#include "evt_generic.hpp"
+
+
+/// Focus change event
+class EvtFocus: public EvtGeneric
+{
+    public:
+        EvtFocus( intf_thread_t *pIntf, bool focus ): EvtGeneric( pIntf ),
+            m_focus( focus ) {}
+        virtual ~EvtFocus() {}
+
+        /// Return the type of event
+        virtual const string getAsString() const
+        {
+            return ( m_focus ? "focus:in" : "focus:out" );
+        }
+
+    private:
+        /// true for a focus in, and false for a focus out
+        bool m_focus;
+};
+
+
+#endif
diff --git a/modules/gui/skins2/events/evt_generic.hpp b/modules/gui/skins2/events/evt_generic.hpp
new file mode 100644 (file)
index 0000000..1c235f1
--- /dev/null
@@ -0,0 +1,46 @@
+/*****************************************************************************
+ * evt_generic.hpp
+ *****************************************************************************
+ * Copyright (C) 2003 VideoLAN
+ * $Id: evt_generic.hpp,v 1.1 2004/01/03 23:31:33 asmax Exp $
+ *
+ * Authors: Cyril Deguet     <asmax@via.ecp.fr>
+ *          Olivier Teulière <ipkiss@via.ecp.fr>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111, USA.
+ *****************************************************************************/
+
+#ifndef EVT_GENERIC_HPP
+#define EVT_GENERIC_HPP
+
+#include "../src/skin_common.hpp"
+#include <string>
+
+
+/// Base class for OS events
+class EvtGeneric: public SkinObject
+{
+    public:
+        virtual ~EvtGeneric() {}
+
+        /// Return the type of the event
+        virtual const string getAsString() const = 0;
+
+    protected:
+        EvtGeneric( intf_thread_t *pIntf ): SkinObject( pIntf ) {}
+};
+
+
+#endif
diff --git a/modules/gui/skins2/events/evt_input.cpp b/modules/gui/skins2/events/evt_input.cpp
new file mode 100644 (file)
index 0000000..f545ac5
--- /dev/null
@@ -0,0 +1,64 @@
+/*****************************************************************************
+ * evt_input.cpp
+ *****************************************************************************
+ * Copyright (C) 2003 VideoLAN
+ * $Id: evt_input.cpp,v 1.1 2004/01/03 23:31:33 asmax Exp $
+ *
+ * Authors: Cyril Deguet     <asmax@via.ecp.fr>
+ *          Olivier Teulière <ipkiss@via.ecp.fr>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111, USA.
+ *****************************************************************************/
+
+#include "evt_input.hpp"
+
+const int EvtInput::kModNone  = 0;
+const int EvtInput::kModAlt   = 1;
+const int EvtInput::kModCtrl  = 2;
+const int EvtInput::kModShift = 4;
+
+
+EvtInput::EvtInput( intf_thread_t *pIntf, int mod ):
+    EvtGeneric( pIntf), m_mod( mod )
+{
+}
+
+
+void EvtInput::addModifier( string &rEvtString ) const
+{
+    if( m_mod == kModNone )
+    {
+        rEvtString += ":none";
+    }
+    else
+    {
+        string modList = ":";
+        if( m_mod & kModAlt )
+        {
+            modList += "alt,";
+        }
+        if( m_mod & kModCtrl )
+        {
+            modList += "ctrl,";
+        }
+        if( m_mod & kModShift )
+        {
+            modList += "shift,";
+        }
+        // Remove the last ','
+        modList = modList.substr( 0, modList.size() - 1 );
+        rEvtString += modList;
+    }
+}
diff --git a/modules/gui/skins2/events/evt_input.hpp b/modules/gui/skins2/events/evt_input.hpp
new file mode 100644 (file)
index 0000000..59e0267
--- /dev/null
@@ -0,0 +1,57 @@
+/*****************************************************************************
+ * evt_input.hpp
+ *****************************************************************************
+ * Copyright (C) 2003 VideoLAN
+ * $Id: evt_input.hpp,v 1.1 2004/01/03 23:31:33 asmax Exp $
+ *
+ * Authors: Cyril Deguet     <asmax@via.ecp.fr>
+ *          Olivier Teulière <ipkiss@via.ecp.fr>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111, USA.
+ *****************************************************************************/
+
+#ifndef EVT_INPUT_HPP
+#define EVT_INPUT_HPP
+
+#include "evt_generic.hpp"
+
+
+/// Base class for mouse and key events
+class EvtInput: public EvtGeneric
+{
+    public:
+        virtual ~EvtInput() {}
+
+        /// Masks for modifier keys
+        static const int kModNone;
+        static const int kModAlt;
+        static const int kModCtrl;
+        static const int kModShift;
+
+        /// Get the modifiers
+        virtual int getMod() const { return m_mod; }
+
+    protected:
+        EvtInput( intf_thread_t *pIntf, int mod = kModNone );
+
+        /// Add the modifier to the event string
+        virtual void addModifier( string &rEvtString ) const;
+
+    private:
+        /// Modifiers (special key(s) pressed during the mouse event)
+        int m_mod;
+};
+
+#endif
diff --git a/modules/gui/skins2/events/evt_key.cpp b/modules/gui/skins2/events/evt_key.cpp
new file mode 100755 (executable)
index 0000000..76f71b8
--- /dev/null
@@ -0,0 +1,53 @@
+/*****************************************************************************
+ * evt_key.cpp
+ *****************************************************************************
+ * Copyright (C) 2003 VideoLAN
+ * $Id: evt_key.cpp,v 1.1 2004/01/03 23:31:33 asmax Exp $
+ *
+ * Authors: Cyril Deguet     <asmax@via.ecp.fr>
+ *          Olivier Teulière <ipkiss@via.ecp.fr>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111, USA.
+ *****************************************************************************/
+
+#include "evt_key.hpp"
+#include "vlc_keys.h"
+
+
+const string EvtKey::getAsString() const
+{
+    string event = "key";
+
+    // Add the action
+    if( m_action == kDown )
+        event += ":down";
+    else if( m_action == kUp )
+        event += ":up";
+    else
+        msg_Warn( getIntf(), "Unknown action type" );
+
+    // Add the key
+    char *keyName = KeyToString( m_key );
+    if( keyName )
+        event += (string)":" + keyName;
+    else
+        msg_Warn( getIntf(), "Unknown key: %d", m_key );
+
+    // Add the modifier
+    addModifier( event );
+
+    return event;
+}
+
diff --git a/modules/gui/skins2/events/evt_key.hpp b/modules/gui/skins2/events/evt_key.hpp
new file mode 100644 (file)
index 0000000..1997d0b
--- /dev/null
@@ -0,0 +1,60 @@
+/*****************************************************************************
+ * evt_key.hpp
+ *****************************************************************************
+ * Copyright (C) 2003 VideoLAN
+ * $Id: evt_key.hpp,v 1.1 2004/01/03 23:31:33 asmax Exp $
+ *
+ * Authors: Cyril Deguet     <asmax@via.ecp.fr>
+ *          Olivier Teulière <ipkiss@via.ecp.fr>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111, USA.
+ *****************************************************************************/
+
+#ifndef EVT_KEY_HPP
+#define EVT_KEY_HPP
+
+#include "evt_input.hpp"
+
+
+/// Class for keyboard events
+class EvtKey: public EvtInput
+{
+    public:
+        typedef enum
+        {
+            kDown,
+            kUp
+        } ActionType_t;
+
+        EvtKey( intf_thread_t *pIntf, int key, ActionType_t action,
+                int mod = kModNone ):
+            EvtInput( pIntf, mod ), m_key( key ), m_action( action ) {}
+        virtual ~EvtKey() {}
+
+        /// Return the type of event
+        virtual const string getAsString() const;
+
+        int getKey() const { return m_key; }
+
+    private:
+        /// The concerned key, stored according to the '#define's in vlc_keys.h
+        /// but without the modifiers (which are stored in EvtInput)
+        int m_key;
+        /// Type of action
+        ActionType_t m_action;
+};
+
+
+#endif
diff --git a/modules/gui/skins2/events/evt_leave.hpp b/modules/gui/skins2/events/evt_leave.hpp
new file mode 100644 (file)
index 0000000..0717846
--- /dev/null
@@ -0,0 +1,43 @@
+/*****************************************************************************
+ * evt_leave.hpp
+ *****************************************************************************
+ * Copyright (C) 2003 VideoLAN
+ * $Id: evt_leave.hpp,v 1.1 2004/01/03 23:31:33 asmax Exp $
+ *
+ * Authors: Cyril Deguet     <asmax@via.ecp.fr>
+ *          Olivier Teulière <ipkiss@via.ecp.fr>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111, USA.
+ *****************************************************************************/
+
+#ifndef EVT_LEAVE_HPP
+#define EVT_LEAVE_HPP
+
+#include "evt_input.hpp"
+
+
+/// Mouse leave event
+class EvtLeave: public EvtInput
+{
+    public:
+        EvtLeave( intf_thread_t *pIntf ): EvtInput( pIntf ) {}
+        virtual ~EvtLeave() {}
+
+        /// Return the type of event
+        virtual const string getAsString() const { return "leave"; }
+};
+
+
+#endif
diff --git a/modules/gui/skins2/events/evt_motion.hpp b/modules/gui/skins2/events/evt_motion.hpp
new file mode 100644 (file)
index 0000000..b32cf69
--- /dev/null
@@ -0,0 +1,55 @@
+/*****************************************************************************
+ * evt_motion.hpp
+ *****************************************************************************
+ * Copyright (C) 2003 VideoLAN
+ * $Id: evt_motion.hpp,v 1.1 2004/01/03 23:31:33 asmax Exp $
+ *
+ * Authors: Cyril Deguet     <asmax@via.ecp.fr>
+ *          Olivier Teulière <ipkiss@via.ecp.fr>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111, USA.
+ *****************************************************************************/
+
+#ifndef EVT_MOTION_HPP
+#define EVT_MOTION_HPP
+
+#include "evt_input.hpp"
+
+
+/// Mouse move event
+class EvtMotion: public EvtInput
+{
+    public:
+        EvtMotion( intf_thread_t *pIntf, int xPos, int yPos ):
+            EvtInput( pIntf ), m_xPos( xPos ), m_yPos( yPos ) {}
+        virtual ~EvtMotion() {}
+
+        /// Return the type of event
+        virtual const string getAsString() const { return "motion"; }
+
+        // Getters
+        int getXPos() const { return m_xPos; }
+        int getYPos() const { return m_yPos; }
+
+    private:
+        /// Coordinates of the mouse (absolute or relative)
+        /// The coordinates are absolute when the event is sent to the
+        /// GenericWindow, but are relative to the window when the event is
+        /// forwarded to the controls
+        int m_xPos, m_yPos;
+};
+
+
+#endif
diff --git a/modules/gui/skins2/events/evt_mouse.cpp b/modules/gui/skins2/events/evt_mouse.cpp
new file mode 100755 (executable)
index 0000000..cb1725f
--- /dev/null
@@ -0,0 +1,57 @@
+/*****************************************************************************
+ * evt_mouse.cpp
+ *****************************************************************************
+ * Copyright (C) 2003 VideoLAN
+ * $Id: evt_mouse.cpp,v 1.1 2004/01/03 23:31:33 asmax Exp $
+ *
+ * Authors: Cyril Deguet     <asmax@via.ecp.fr>
+ *          Olivier Teulière <ipkiss@via.ecp.fr>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111, USA.
+ *****************************************************************************/
+
+#include "evt_mouse.hpp"
+
+
+const string EvtMouse::getAsString() const
+{
+    string event = "mouse";
+
+    // Add the button
+    if( m_button == kLeft )
+        event += ":left";
+    else if( m_button == kMiddle )
+        event += ":middle";
+    else if( m_button == kRight )
+        event += ":right";
+    else
+        msg_Warn( getIntf(), "Unknown button type" );
+
+    // Add the action
+    if( m_action == kDown )
+        event += ":down";
+    else if( m_action == kUp )
+        event += ":up";
+    else if( m_action == kDblClick )
+        event += ":dblclick";
+    else
+        msg_Warn( getIntf(), "Unknown action type" );
+
+    // Add the modifier
+    addModifier( event );
+
+    return event;
+}
+
diff --git a/modules/gui/skins2/events/evt_mouse.hpp b/modules/gui/skins2/events/evt_mouse.hpp
new file mode 100644 (file)
index 0000000..e9d73a0
--- /dev/null
@@ -0,0 +1,75 @@
+/*****************************************************************************
+ * evt_mouse.hpp
+ *****************************************************************************
+ * Copyright (C) 2003 VideoLAN
+ * $Id: evt_mouse.hpp,v 1.1 2004/01/03 23:31:33 asmax Exp $
+ *
+ * Authors: Cyril Deguet     <asmax@via.ecp.fr>
+ *          Olivier Teulière <ipkiss@via.ecp.fr>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111, USA.
+ *****************************************************************************/
+
+#ifndef EVT_MOUSE_HPP
+#define EVT_MOUSE_HPP
+
+#include "evt_input.hpp"
+
+
+/// Class for mouse button events
+class EvtMouse: public EvtInput
+{
+    public:
+        typedef enum
+        {
+            kLeft,
+            kMiddle,
+            kRight
+        } ButtonType_t;
+
+        typedef enum
+        {
+            kDown,
+            kUp,
+            kDblClick
+        } ActionType_t;
+
+        EvtMouse( intf_thread_t *pIntf, int xPos, int yPos, ButtonType_t button,
+                  ActionType_t action, int mod = kModNone ):
+            EvtInput( pIntf, mod ), m_xPos( xPos ), m_yPos( yPos ),
+            m_button( button ), m_action( action ) {}
+        virtual ~EvtMouse() {}
+
+        // Return the event coordinates
+        int getXPos() const { return m_xPos; }
+        int getYPos() const { return m_yPos; }
+
+        // Return the button and the action
+        ButtonType_t getButton() const { return m_button; }
+        ActionType_t getAction() const { return m_action; }
+
+        virtual const string getAsString() const;
+
+    private:
+        /// Coordinates of the mouse relative to the window
+        int m_xPos, m_yPos;
+        /// Mouse button involved in the event
+        ButtonType_t m_button;
+        /// Type of action
+        ActionType_t m_action;
+};
+
+
+#endif
diff --git a/modules/gui/skins2/events/evt_refresh.hpp b/modules/gui/skins2/events/evt_refresh.hpp
new file mode 100644 (file)
index 0000000..4a04700
--- /dev/null
@@ -0,0 +1,58 @@
+/*****************************************************************************
+ * evt_refresh.hpp
+ *****************************************************************************
+ * Copyright (C) 2003 VideoLAN
+ * $Id: evt_refresh.hpp,v 1.1 2004/01/03 23:31:33 asmax Exp $
+ *
+ * Authors: Cyril Deguet     <asmax@via.ecp.fr>
+ *          Olivier Teulière <ipkiss@via.ecp.fr>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111, USA.
+ *****************************************************************************/
+
+#ifndef EVT_REFRESH_HPP
+#define EVT_REFRESH_HPP
+
+#include "evt_generic.hpp"
+
+
+/// Refresh window event
+class EvtRefresh: public EvtGeneric
+{
+    public:
+        /// Constructor with the coordinates of the area to refresh
+        EvtRefresh( intf_thread_t *pIntf, int xStart, int yStart, int width,
+                    int height ):
+            EvtGeneric( pIntf ), m_xStart( xStart ), m_yStart( yStart ),
+            m_width( width ), m_height( height ) {}
+
+        virtual ~EvtRefresh() {}
+
+        /// Return the type of event
+        virtual const string getAsString() const { return "refresh"; }
+
+        /// Getters
+        int getXStart() const { return m_xStart; }
+        int getYStart() const { return m_yStart; }
+        int getWidth()  const { return m_width; }
+        int getHeight() const { return m_height; }
+
+    private:
+        /// Coordinates and size of the area to refresh
+        int m_xStart, m_yStart, m_width, m_height;
+};
+
+
+#endif
diff --git a/modules/gui/skins2/events/evt_scroll.cpp b/modules/gui/skins2/events/evt_scroll.cpp
new file mode 100755 (executable)
index 0000000..555d8d8
--- /dev/null
@@ -0,0 +1,45 @@
+/*****************************************************************************
+ * evt_scroll.cpp
+ *****************************************************************************
+ * Copyright (C) 2003 VideoLAN
+ * $Id: evt_scroll.cpp,v 1.1 2004/01/03 23:31:33 asmax Exp $
+ *
+ * Authors: Cyril Deguet     <asmax@via.ecp.fr>
+ *          Olivier Teulière <ipkiss@via.ecp.fr>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111, USA.
+ *****************************************************************************/
+
+#include "evt_scroll.hpp"
+
+
+const string EvtScroll::getAsString() const
+{
+    string event = "scroll";
+
+    // Add the direction
+    if( m_direction == kUp )
+        event += ":up";
+    else if( m_direction == kDown )
+        event += ":down";
+    else
+        msg_Warn( getIntf(), "Unknown scrolling direction" );
+
+    // Add the modifier
+    addModifier( event );
+
+    return event;
+}
+
diff --git a/modules/gui/skins2/events/evt_scroll.hpp b/modules/gui/skins2/events/evt_scroll.hpp
new file mode 100644 (file)
index 0000000..0043916
--- /dev/null
@@ -0,0 +1,64 @@
+/*****************************************************************************
+ * evt_scroll.hpp
+ *****************************************************************************
+ * Copyright (C) 2003 VideoLAN
+ * $Id: evt_scroll.hpp,v 1.1 2004/01/03 23:31:33 asmax Exp $
+ *
+ * Authors: Cyril Deguet     <asmax@via.ecp.fr>
+ *          Olivier Teulière <ipkiss@via.ecp.fr>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111, USA.
+ *****************************************************************************/
+
+#ifndef EVT_SCROLL_HPP
+#define EVT_SCROLL_HPP
+
+#include "evt_input.hpp"
+
+
+/// Class for mouse scroll events
+class EvtScroll: public EvtInput
+{
+    public:
+        typedef enum
+        {
+            kUp,
+            kDown,
+        } Direction_t;
+
+        EvtScroll( intf_thread_t *pIntf, int xPos, int yPos,
+                   Direction_t direction, int mod = kModNone ):
+            EvtInput( pIntf, mod ), m_xPos( xPos ), m_yPos( yPos ),
+            m_direction( direction ) {}
+        virtual ~EvtScroll() {}
+
+        // Return the event coordinates
+        int getXPos() const { return m_xPos; }
+        int getYPos() const { return m_yPos; }
+
+        // Return the direction
+        Direction_t getDirection() const { return m_direction; }
+
+        virtual const string getAsString() const;
+
+    private:
+        /// Coordinates of the mouse relative to the window
+        int m_xPos, m_yPos;
+        /// Scroll direction
+        Direction_t m_direction;
+};
+
+
+#endif
diff --git a/modules/gui/skins2/events/evt_special.cpp b/modules/gui/skins2/events/evt_special.cpp
new file mode 100755 (executable)
index 0000000..c4673e1
--- /dev/null
@@ -0,0 +1,46 @@
+/*****************************************************************************
+ * evt_special.cpp
+ *****************************************************************************
+ * Copyright (C) 2003 VideoLAN
+ * $Id: evt_special.cpp,v 1.1 2004/01/03 23:31:33 asmax Exp $
+ *
+ * Authors: Cyril Deguet     <asmax@via.ecp.fr>
+ *          Olivier Teulière <ipkiss@via.ecp.fr>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111, USA.
+ *****************************************************************************/
+
+#include "evt_special.hpp"
+
+
+const string EvtSpecial::getAsString() const
+{
+    string event = "special";
+
+    // Add the action
+    if( m_action == kShow )
+        event += ":show";
+    else if( m_action == kHide )
+        event += ":hide";
+    else if( m_action == kEnable )
+        event += ":enable";
+    else if( m_action == kDisable )
+        event += ":disable";
+    else
+        msg_Warn( getIntf(), "Unknown action type" );
+
+    return event;
+}
+
diff --git a/modules/gui/skins2/events/evt_special.hpp b/modules/gui/skins2/events/evt_special.hpp
new file mode 100644 (file)
index 0000000..c75f1d2
--- /dev/null
@@ -0,0 +1,56 @@
+/*****************************************************************************
+ * evt_special.hpp
+ *****************************************************************************
+ * Copyright (C) 2003 VideoLAN
+ * $Id: evt_special.hpp,v 1.1 2004/01/03 23:31:33 asmax Exp $
+ *
+ * Authors: Cyril Deguet     <asmax@via.ecp.fr>
+ *          Olivier Teulière <ipkiss@via.ecp.fr>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111, USA.
+ *****************************************************************************/
+
+#ifndef EVT_SPECIAL_HPP
+#define EVT_SPECIAL_HPP
+
+#include "evt_generic.hpp"
+
+
+/// Class for non-genuine events
+class EvtSpecial: public EvtGeneric
+{
+    public:
+        typedef enum
+        {
+            kShow,
+            kHide,
+            kEnable,
+            kDisable
+        } ActionType_t;
+
+        EvtSpecial( intf_thread_t *pIntf, ActionType_t action ):
+            EvtGeneric( pIntf ), m_action( action ) {}
+        virtual ~EvtSpecial() {}
+
+        /// Return the type of event
+        virtual const string getAsString() const;
+
+    private:
+        /// Type of action
+        ActionType_t m_action;
+};
+
+
+#endif
diff --git a/modules/gui/skins2/parser/builder.cpp b/modules/gui/skins2/parser/builder.cpp
new file mode 100755 (executable)
index 0000000..372d166
--- /dev/null
@@ -0,0 +1,678 @@
+/*****************************************************************************
+ * builder.cpp
+ *****************************************************************************
+ * Copyright (C) 2003 VideoLAN
+ * $Id: builder.cpp,v 1.1 2004/01/03 23:31:33 asmax Exp $
+ *
+ * Authors: Cyril Deguet     <asmax@via.ecp.fr>
+ *          Olivier Teulière <ipkiss@via.ecp.fr>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111, USA.
+ *****************************************************************************/
+
+#include <string.h>
+#include "builder.hpp"
+#include "builder_data.hpp"
+#include "interpreter.hpp"
+#include "../src/png_bitmap.hpp"
+#include "../src/os_factory.hpp"
+#include "../src/generic_bitmap.hpp"
+#include "../src/generic_window.hpp"
+#include "../src/anchor.hpp"
+#include "../src/ft2_font.hpp"
+#include "../src/theme.hpp"
+#include "../controls/ctrl_button.hpp"
+#include "../controls/ctrl_checkbox.hpp"
+#include "../controls/ctrl_image.hpp"
+#include "../controls/ctrl_list.hpp"
+#include "../controls/ctrl_move.hpp"
+#include "../controls/ctrl_resize.hpp"
+#include "../controls/ctrl_slider.hpp"
+#include "../controls/ctrl_radialslider.hpp"
+#include "../controls/ctrl_text.hpp"
+#include "../utils/position.hpp"
+#include "../utils/var_bool.hpp"
+#include "../utils/var_text.hpp"
+
+
+Builder::Builder( intf_thread_t *pIntf, BuilderData &rData):
+    SkinObject( pIntf ), m_rData( rData ), m_interpreter( pIntf ),
+    m_pTheme( NULL )
+{
+}
+
+
+CmdGeneric *Builder::parseAction( const string &rAction )
+{
+    return m_interpreter.parseAction( rAction, m_pTheme );
+}
+
+
+// Useful macro
+#define ADD_OBJECTS( type ) \
+    list<BuilderData::type>::const_iterator it##type; \
+    for( it##type = m_rData.m_list##type.begin(); \
+         it##type != m_rData.m_list##type.end(); it##type++ ) \
+    { \
+        add##type( *it##type ); \
+    }
+
+
+Theme *Builder::build()
+{
+    m_pTheme = new Theme( getIntf() );
+    if( m_pTheme == NULL )
+    {
+        return NULL;
+    }
+
+    // Create everything from the data in the XML
+    ADD_OBJECTS( Theme );
+    ADD_OBJECTS( Bitmap );
+    ADD_OBJECTS( Font );
+    ADD_OBJECTS( Window );
+    ADD_OBJECTS( Layout );
+    ADD_OBJECTS( Anchor );
+    ADD_OBJECTS( Button );
+    ADD_OBJECTS( Checkbox );
+    ADD_OBJECTS( Image );
+    ADD_OBJECTS( Text );
+    ADD_OBJECTS( RadialSlider );
+    ADD_OBJECTS( Slider );
+    ADD_OBJECTS( List );
+
+    return m_pTheme;
+}
+
+
+// Macro to get a bitmap by its ID in the builder
+#define GET_BMP( pBmp, id ) \
+    if( id != "none" ) \
+    { \
+        pBmp = m_pTheme->m_bitmaps[id].get(); \
+        if( pBmp == NULL ) \
+        { \
+            msg_Err( getIntf(), "Unknown Bitmap id: %s", id.c_str() ); \
+            return; \
+        } \
+    }
+
+void Builder::addTheme( const BuilderData::Theme &rData )
+{
+    m_pTheme->getWindowManager().setMagnetValue( rData.m_magnet );
+    m_pTheme->getWindowManager().setAlphaValue( rData.m_alpha );
+    m_pTheme->getWindowManager().setMoveAlphaValue( rData.m_moveAlpha );
+}
+
+
+void Builder::addBitmap( const BuilderData::Bitmap &rData )
+{
+    GenericBitmap *pBmp = new PngBitmap( getIntf(), rData.m_fileName,
+                                         rData.m_alphaColor );
+    m_pTheme->m_bitmaps[rData.m_id] = GenericBitmapPtr( pBmp );
+}
+
+
+void Builder::addFont( const BuilderData::Font &rData )
+{
+    GenericFont *pFont = new FT2Font( getIntf(), rData.m_fontName,
+                                      rData.m_size );
+    pFont->init();
+    m_pTheme->m_fonts[rData.m_id] = GenericFontPtr( pFont );
+}
+
+
+void Builder::addWindow( const BuilderData::Window &rData )
+{
+    // XXX:  font to fix
+    GenericFont *pFont = new FT2Font( getIntf(), "FreeSans.ttf", 12 );
+    pFont->init();
+    GenericWindow *pWin =
+        new GenericWindow( getIntf(), rData.m_xPos, rData.m_yPos,
+                           m_pTheme->getWindowManager(), *pFont,
+                           rData.m_dragDrop, rData.m_playOnDrop );
+
+    m_pTheme->m_windows[uniqueId( rData.m_id) ] = GenericWindowPtr( pWin );
+}
+
+
+void Builder::addLayout( const BuilderData::Layout &rData )
+{
+    GenericWindow *pWin = m_pTheme->m_windows[rData.m_windowId].get();
+    if( pWin == NULL )
+    {
+        msg_Err( getIntf(), "Unknown Window id: %s", rData.m_windowId.c_str() );
+        return;
+    }
+
+    int minWidth = rData.m_minWidth != -1 ? rData.m_minWidth : rData.m_width;
+    int maxWidth = rData.m_maxWidth != -1 ? rData.m_maxWidth : rData.m_width;
+    int minHeight = rData.m_minHeight != -1 ? rData.m_minHeight :
+                    rData.m_height;
+    int maxHeight = rData.m_maxHeight != -1 ? rData.m_maxHeight :
+                    rData.m_height;
+    GenericLayout *pLayout = new GenericLayout( getIntf(), rData.m_width,
+                                                rData.m_height,
+                                                minWidth, maxWidth, minHeight,
+                                                maxHeight );
+    m_pTheme->m_layouts[uniqueId( rData.m_id) ] = GenericLayoutPtr( pLayout );
+
+    // Attach the layout to its window
+    pWin->setActiveLayout( pLayout );
+}
+
+
+void Builder::addAnchor( const BuilderData::Anchor &rData )
+{
+    GenericWindow *pWin = m_pTheme->m_windows[rData.m_windowId].get();
+    if( pWin == NULL )
+    {
+        msg_Err( getIntf(), "Unknown Window id: %s", rData.m_windowId.c_str() );
+        return;
+    }
+
+    Anchor *pAnc = new Anchor( getIntf(), rData.m_xPos, rData.m_yPos,
+                               rData.m_range, rData.m_priority, *pWin );
+    pWin->addAnchor( pAnc );
+}
+
+
+void Builder::addButton( const BuilderData::Button &rData )
+{
+    // Get the bitmaps of the button
+    GenericBitmap *pBmpUp = NULL;
+    GET_BMP( pBmpUp, rData.m_upId );
+
+    GenericBitmap *pBmpDown = pBmpUp;
+    GET_BMP( pBmpDown, rData.m_downId );
+
+    GenericBitmap *pBmpOver = pBmpUp;
+    GET_BMP( pBmpOver, rData.m_overId );
+
+    GenericLayout *pLayout = m_pTheme->m_layouts[rData.m_layoutId].get();
+    if( pLayout == NULL )
+    {
+        msg_Err( getIntf(), "Unknown Layout id: %s", rData.m_layoutId.c_str() );
+        return;
+    }
+
+    CmdGeneric *pCommand = parseAction( rData.m_actionId );
+    if( pCommand == NULL )
+    {
+        msg_Err( getIntf(), "Invalid action: %s", rData.m_actionId.c_str() );
+        return;
+    }
+
+    CtrlButton *pButton = new CtrlButton( getIntf(), *pBmpUp, *pBmpOver,
+        *pBmpDown, *pCommand, UString( getIntf(), rData.m_tooltip.c_str() ),
+        UString( getIntf(), rData.m_help.c_str() ) );
+
+    // Compute the position of the control
+    // XXX (we suppose all the images have the same size...)
+    const Position pos = makePosition( rData.m_leftTop, rData.m_rightBottom,
+                                       rData.m_xPos, rData.m_yPos,
+                                       pBmpUp->getWidth(),
+                                       pBmpUp->getHeight(), *pLayout );
+
+    pLayout->addControl( pButton, pos, rData.m_layer );
+
+    m_pTheme->m_controls[uniqueId( rData.m_id) ] = CtrlGenericPtr( pButton );
+}
+
+
+void Builder::addCheckbox( const BuilderData::Checkbox &rData )
+{
+    // Get the bitmaps of the checkbox
+    GenericBitmap *pBmpUp1 = NULL;
+    GET_BMP( pBmpUp1, rData.m_up1Id );
+
+    GenericBitmap *pBmpDown1 = pBmpUp1;
+    GET_BMP( pBmpDown1, rData.m_down1Id );
+
+    GenericBitmap *pBmpOver1 = pBmpUp1;
+    GET_BMP( pBmpOver1, rData.m_over1Id );
+
+    GenericBitmap *pBmpUp2 = NULL;
+    GET_BMP( pBmpUp2, rData.m_up2Id );
+
+    GenericBitmap *pBmpDown2 = pBmpUp2;
+    GET_BMP( pBmpDown2, rData.m_down2Id );
+
+    GenericBitmap *pBmpOver2 = pBmpUp2;
+    GET_BMP( pBmpOver2, rData.m_over2Id );
+
+    GenericLayout *pLayout = m_pTheme->m_layouts[rData.m_layoutId].get();
+    if( pLayout == NULL )
+    {
+        msg_Err( getIntf(), "Unknown Layout id: %s", rData.m_layoutId.c_str() );
+        return;
+    }
+
+    CmdGeneric *pCommand1 = parseAction( rData.m_action1 );
+    if( pCommand1 == NULL )
+    {
+        msg_Err( getIntf(), "Invalid action: %s", rData.m_action1.c_str() );
+        return;
+    }
+
+    CmdGeneric *pCommand2 = parseAction( rData.m_action2 );
+    if( pCommand2 == NULL )
+    {
+        msg_Err( getIntf(), "Invalid action: %s", rData.m_action2.c_str() );
+        return;
+    }
+
+    // Get the state variable
+    VarBool *pVar = m_interpreter.getVarBool( rData.m_state, m_pTheme );
+    if( pVar == NULL )
+    {
+        // TODO: default state
+        return;
+    }
+
+    // Create the control
+    CtrlCheckbox *pCheckbox = new CtrlCheckbox( getIntf(), *pBmpUp1,
+        *pBmpOver1, *pBmpDown1, *pBmpUp2, *pBmpOver2, *pBmpDown2, *pCommand1,
+        *pCommand2, UString( getIntf(), rData.m_tooltip1.c_str() ),
+        UString( getIntf(), rData.m_tooltip2.c_str() ), *pVar,
+        UString( getIntf(), rData.m_help.c_str() ) );
+
+    // Compute the position of the control
+    // XXX (we suppose all the images have the same size...)
+    const Position pos = makePosition( rData.m_leftTop, rData.m_rightBottom,
+                                       rData.m_xPos, rData.m_yPos,
+                                       pBmpUp1->getWidth(),
+                                       pBmpUp1->getHeight(), *pLayout );
+
+    pLayout->addControl( pCheckbox, pos, rData.m_layer );
+
+    m_pTheme->m_controls[uniqueId( rData.m_id) ] = CtrlGenericPtr( pCheckbox );
+}
+
+
+void Builder::addImage( const BuilderData::Image &rData )
+{
+    GenericBitmap *pBmp = NULL;
+    GET_BMP( pBmp, rData.m_bmpId );
+
+    GenericLayout *pLayout = m_pTheme->m_layouts[rData.m_layoutId].get();
+    if( pLayout == NULL )
+    {
+        msg_Err( getIntf(), "Unknown Layout id: %s", rData.m_layoutId.c_str() );
+        return;
+    }
+
+    GenericWindow *pWindow = m_pTheme->m_windows[rData.m_windowId].get();
+    if( pWindow == NULL )
+    {
+        msg_Err( getIntf(), "Unknown Window id: %s", rData.m_windowId.c_str() );
+        return;
+    }
+
+    CtrlImage *pImage = new CtrlImage( getIntf(), *pBmp,
+                                UString( getIntf(), rData.m_help.c_str() ) );
+
+    // Compute the position of the control
+    const Position pos = makePosition( rData.m_leftTop, rData.m_rightBottom,
+                                       rData.m_xPos,
+                                       rData.m_yPos, pBmp->getWidth(),
+                                       pBmp->getHeight(), *pLayout );
+
+    // XXX: test to be changed! XXX
+    if( rData.m_onclickId == "move" )
+    {
+        CtrlMove *pMove = new CtrlMove( getIntf(), m_pTheme->getWindowManager(),
+             *pImage, *pWindow, UString( getIntf(), rData.m_help.c_str() ) );
+        pLayout->addControl( pMove, pos, rData.m_layer );
+    }
+    else if( rData.m_onclickId == "resize" )
+    {
+        CtrlResize *pResize = new CtrlResize( getIntf(), *pImage, *pLayout,
+                UString( getIntf(), rData.m_help.c_str() ) );
+        pLayout->addControl( pResize, pos, rData.m_layer );
+    }
+    else
+    {
+        pLayout->addControl( pImage, pos, rData.m_layer );
+    }
+
+    m_pTheme->m_controls[uniqueId( rData.m_id) ] = CtrlGenericPtr( pImage );
+}
+
+
+void Builder::addText( const BuilderData::Text &rData )
+{
+    GenericLayout *pLayout = m_pTheme->m_layouts[rData.m_layoutId].get();
+    if( pLayout == NULL )
+    {
+        msg_Err( getIntf(), "Unknown Layout id: %s", rData.m_layoutId.c_str() );
+        return;
+    }
+
+    GenericFont *pFont = m_pTheme->m_fonts[rData.m_fontId].get();
+    if( pFont == NULL )
+    {
+        msg_Err( getIntf(), "Unknown font id: %s", rData.m_fontId.c_str() );
+        return;
+    }
+
+    // Create a text variable
+    VarText *pVar = new VarText( getIntf() );
+    UString msg( getIntf(), rData.m_text.c_str() );
+    pVar->set( msg );
+    m_pTheme->m_vars.push_back( VariablePtr( pVar ) );
+
+    CtrlText *pText = new CtrlText( getIntf(), *pVar, *pFont,
+            UString( getIntf(), rData.m_help.c_str() ) );
+
+    int height = pFont->getSize();
+
+    pLayout->addControl( pText, Position( rData.m_xPos, rData.m_yPos,
+                                          rData.m_xPos + rData.m_width,
+                                          rData.m_yPos + height, *pLayout ),
+                         rData.m_layer );
+
+    m_pTheme->m_controls[uniqueId( rData.m_id) ] = CtrlGenericPtr( pText );
+}
+
+
+void Builder::addRadialSlider( const BuilderData::RadialSlider &rData )
+{
+    // Get the bitmaps of the slider
+    GenericBitmap *pSeq = NULL;
+    GET_BMP( pSeq, rData.m_sequence );
+
+    GenericLayout *pLayout = m_pTheme->m_layouts[rData.m_layoutId].get();
+    if( pLayout == NULL )
+    {
+        msg_Err( getIntf(), "Unknown Layout id: %s", rData.m_layoutId.c_str() );
+        return;
+    }
+
+    // Get the variable associated to the slider
+    VarPercent *pVar = m_interpreter.getVarPercent( rData.m_value, m_pTheme );
+    if( pVar == NULL )
+    {
+        msg_Err( getIntf(), "Unknown slider value: %s", rData.m_value.c_str() );
+        return;
+    }
+
+    // Create the control
+    CtrlRadialSlider *pRadial =
+        new CtrlRadialSlider( getIntf(), *pSeq, rData.m_nbImages, *pVar,
+                              rData.m_minAngle, rData.m_maxAngle,
+                              UString( getIntf(), rData.m_help.c_str() ) );
+
+    // XXX: resizing is not supported
+    // Compute the position of the control
+    const Position pos =
+        makePosition( rData.m_leftTop, rData.m_rightBottom, rData.m_xPos,
+                      rData.m_yPos, pSeq->getWidth(),
+                      pSeq->getHeight() / rData.m_nbImages, *pLayout );
+
+    pLayout->addControl( pRadial, pos, rData.m_layer );
+
+    m_pTheme->m_controls[uniqueId( rData.m_id) ] = CtrlGenericPtr( pRadial );
+}
+
+
+void Builder::addSlider( const BuilderData::Slider &rData )
+{
+    // Get the bitmaps of the slider
+    GenericBitmap *pBmpUp = NULL;
+    GET_BMP( pBmpUp, rData.m_upId );
+
+    GenericBitmap *pBmpDown = pBmpUp;
+    GET_BMP( pBmpDown, rData.m_downId );
+
+    GenericBitmap *pBmpOver = pBmpUp;
+    GET_BMP( pBmpOver, rData.m_overId );
+
+    GenericLayout *pLayout = m_pTheme->m_layouts[rData.m_layoutId].get();
+    if( pLayout == NULL )
+    {
+        msg_Err( getIntf(), "Unknown Layout id: %s", rData.m_layoutId.c_str() );
+        return;
+    }
+
+    // XXX: memory leak!
+    Bezier *pCurve = getPoints( rData.m_points.c_str() );
+    if( pCurve == NULL )
+    {
+        msg_Err( getIntf(), "Invalid format in tag points=\"%s\"",
+                 rData.m_points.c_str() );
+        return;
+    }
+
+    // Get the visibility variable
+    // XXX check when it is null
+    VarBool *pVisible = m_interpreter.getVarBool( rData.m_visible, m_pTheme );
+
+    // Get the variable associated to the slider
+    VarPercent *pVar = m_interpreter.getVarPercent( rData.m_value, m_pTheme );
+    if( pVar == NULL )
+    {
+        msg_Err( getIntf(), "Unknown slider value: %s", rData.m_value.c_str() );
+        return;
+    }
+
+    // Create the cursor and background controls
+    CtrlSliderCursor *pCursor = new CtrlSliderCursor( getIntf(), *pBmpUp,
+        *pBmpOver, *pBmpDown, *pCurve, *pVar, pVisible,
+        UString( getIntf(), rData.m_tooltip.c_str() ),
+        UString( getIntf(), rData.m_help.c_str() ) );
+
+    CtrlSliderBg *pBackground = new CtrlSliderBg( getIntf(), *pCursor,
+        *pCurve, *pVar, rData.m_thickness, pVisible,
+        UString( getIntf(), rData.m_help.c_str() ) );
+
+    // Compute the position of the control
+    const Position pos = makePosition( rData.m_leftTop, rData.m_rightBottom,
+                                       rData.m_xPos, rData.m_yPos,
+                                       pCurve->getWidth(), pCurve->getHeight(),
+                                       *pLayout );
+
+    pLayout->addControl( pBackground, pos, rData.m_layer );
+    pLayout->addControl( pCursor, pos, rData.m_layer );
+
+    string newId = uniqueId( rData.m_id );
+    m_pTheme->m_controls[newId] = CtrlGenericPtr( pCursor );
+    m_pTheme->m_controls[newId + "_bg"] = CtrlGenericPtr( pBackground );
+}
+
+
+void Builder::addList( const BuilderData::List &rData )
+{
+    GenericLayout *pLayout = m_pTheme->m_layouts[rData.m_layoutId].get();
+    if( pLayout == NULL )
+    {
+        msg_Err( getIntf(), "Unknown Layout id: %s", rData.m_layoutId.c_str() );
+        return;
+    }
+
+    GenericFont *pFont = m_pTheme->m_fonts[rData.m_fontId].get();
+    if( pFont == NULL )
+    {
+        msg_Err( getIntf(), "Unknown font id: %s", rData.m_fontId.c_str() );
+        return;
+    }
+
+    // Get the list variable
+    VarList *pVar = m_interpreter.getVarList( rData.m_var, m_pTheme );
+    if( pVar == NULL )
+    {
+        msg_Err( getIntf(), "No such list variable: %s", rData.m_var.c_str() );
+        return;
+    }
+
+    // Create the list control
+    CtrlList *pList = new CtrlList( getIntf(), *pVar, *pFont,
+       rData.m_fgColor, rData.m_playColor, rData.m_bgColor1,
+       rData.m_bgColor2, rData.m_selColor,
+       UString( getIntf(), rData.m_help.c_str() ) );
+
+    // Compute the position of the control
+    const Position pos = makePosition( rData.m_leftTop, rData.m_rightBottom,
+                                       rData.m_xPos, rData.m_yPos,
+                                       rData.m_width, rData.m_height,
+                                       *pLayout );
+
+    pLayout->addControl( pList, pos, rData.m_layer );
+
+    m_pTheme->m_controls[uniqueId( rData.m_id) ] = CtrlGenericPtr( pList );
+}
+
+
+const string Builder::generateId() const
+{
+    static int i = 1;
+
+    const string base = "_ReservedId_";
+    char genId[base.size() + 4];
+    snprintf( genId, base.size() + 4, "%s%i", base.c_str(), i );
+    i++;
+    return genId;
+}
+
+
+const string Builder::uniqueId( const string &id )
+{
+    string newId;
+
+    if( m_idSet.find( id ) != m_idSet.end() )
+    {
+        // The id was already used
+        if( id != "none" )
+        {
+            msg_Warn( getIntf(), "Non unique id: %s", id.c_str() );
+        }
+        newId = generateId();
+    }
+    else
+    {
+        // OK, this is a new id
+        newId = id;
+    }
+
+    // Add the id to the set
+    m_idSet.insert( newId );
+
+    return newId;
+}
+
+
+
+const Position Builder::makePosition( const string &rLeftTop,
+                                      const string &rRightBottom,
+                                      int xPos, int yPos, int width,
+                                      int height, const Box &rBox ) const
+{
+    int left = 0, top = 0, right = 0, bottom = 0;
+    Position::Ref_t refLeftTop = Position::kLeftTop;
+    Position::Ref_t refRightBottom = Position::kLeftTop;
+
+    int boxWidth = rBox.getWidth();
+    int boxHeight = rBox.getHeight();
+
+    // Position of the left top corner
+    if( rLeftTop == "lefttop" )
+    {
+        left = xPos;
+        top = yPos;
+        refLeftTop = Position::kLeftTop;
+    }
+    else if( rLeftTop == "righttop" )
+    {
+        left = xPos - boxWidth + 1;
+        top = yPos;
+        refLeftTop = Position::kRightTop;
+    }
+    else if( rLeftTop == "leftbottom" )
+    {
+        left = xPos;
+        top = yPos - boxHeight + 1;
+        refLeftTop = Position::kLeftBottom;
+    }
+    else if( rLeftTop == "rightbottom" )
+    {
+        left = xPos - boxWidth + 1;
+        top = yPos - boxHeight + 1;
+        refLeftTop = Position::kRightBottom;
+    }
+
+    // Position of the right bottom corner
+    if( rRightBottom == "lefttop" )
+    {
+        right = xPos + width - 1;
+        bottom = yPos + height - 1;
+        refRightBottom = Position::kLeftTop;
+    }
+    else if( rRightBottom == "righttop" )
+    {
+        right = xPos + width - boxWidth;
+        bottom = yPos + height - 1;
+        refRightBottom = Position::kRightTop;
+    }
+    else if( rRightBottom == "leftbottom" )
+    {
+        right = xPos + width - 1;
+        bottom = yPos + height - boxHeight;
+        refRightBottom = Position::kLeftBottom;
+    }
+    else if( rRightBottom == "rightbottom" )
+    {
+        right = xPos + width - boxWidth;
+        bottom = yPos + height - boxHeight;
+        refRightBottom = Position::kRightBottom;
+    }
+
+    return Position( left, top, right, bottom, rBox, refLeftTop,
+                     refRightBottom );
+}
+
+
+Bezier *Builder::getPoints( const char *pTag ) const
+{
+    vector<double> xBez, yBez;
+    int x, y, n;
+    while( 1 )
+    {
+        if( sscanf( pTag, "(%d,%d)%n", &x, &y, &n ) < 2 )
+        {
+            return NULL;
+        }
+        if( x < 0 || y < 0 )
+        {
+            msg_Err( getIntf(),
+                     "Slider points cannot have negative coordinates!" );
+            return NULL;
+        }
+        xBez.push_back( x );
+        yBez.push_back( y );
+        pTag += n;
+        if( *pTag == '\0' )
+        {
+            break;
+        }
+        if( *(pTag++) != ',' )
+        {
+            return NULL;
+        }
+    }
+
+    // Create the Bezier curve
+    return new Bezier( getIntf(), xBez, yBez );
+}
+
diff --git a/modules/gui/skins2/parser/builder.hpp b/modules/gui/skins2/parser/builder.hpp
new file mode 100644 (file)
index 0000000..67fa3fd
--- /dev/null
@@ -0,0 +1,105 @@
+/*****************************************************************************
+ * builder.hpp
+ *****************************************************************************
+ * Copyright (C) 2003 VideoLAN
+ * $Id: builder.hpp,v 1.1 2004/01/03 23:31:33 asmax Exp $
+ *
+ * Authors: Cyril Deguet     <asmax@via.ecp.fr>
+ *          Olivier Teulière <ipkiss@via.ecp.fr>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111, USA.
+ *****************************************************************************/
+
+#ifndef BUILDER_HPP
+#define BUILDER_HPP
+
+#include "builder_data.hpp"
+#include "interpreter.hpp"
+#include "../src/os_graphics.hpp"
+#include "../src/generic_window.hpp"
+#include "../src/generic_layout.hpp"
+#include "../src/generic_bitmap.hpp"
+#include "../src/generic_font.hpp"
+#include "../commands/cmd_generic.hpp"
+#include "../controls/ctrl_generic.hpp"
+#include "../utils/bezier.hpp"
+
+#include <string>
+#include <list>
+#include <set>
+#include <map>
+
+class Theme;
+
+
+/// Class for skin construction
+class Builder: public SkinObject
+{
+    public:
+        Builder( intf_thread_t *pIntf, BuilderData &rData );
+        virtual ~Builder() {}
+
+        /// Create a Theme object, ready to use.
+        /// Return NULL in case of problem
+        Theme *build();
+
+        /// Parse an action tag and returns a command
+        CmdGeneric *parseAction( const string &rAction );
+
+    private:
+        /// Data from the XML
+        BuilderData &m_rData;
+
+        /// Script interpreter
+        Interpreter m_interpreter;
+
+        /// Theme under construction
+        Theme *m_pTheme;
+
+        /// Set of used id
+        set<string> m_idSet;
+
+        void addTheme( const BuilderData::Theme &rData );
+        void addBitmap( const BuilderData::Bitmap &rData );
+        void addFont( const BuilderData::Font &rData );
+        void addWindow( const BuilderData::Window &rData );
+        void addLayout( const BuilderData::Layout &rData );
+        void addAnchor( const BuilderData::Anchor &rData );
+        void addButton( const BuilderData::Button &rData );
+        void addCheckbox( const BuilderData::Checkbox &rData );
+        void addImage( const BuilderData::Image &rData );
+        void addText( const BuilderData::Text &rData );
+        void addRadialSlider( const BuilderData::RadialSlider &rData );
+        void addSlider( const BuilderData::Slider &rData );
+        void addList( const BuilderData::List &rData );
+
+        /// Generate a new id
+        const string generateId() const;
+
+        /// Check if the id is unique, and if not generate a new one
+        const string uniqueId( const string &id );
+
+        /// Compute the position of a control
+        const Position makePosition( const string &rLeftTop,
+                                     const string &rRightBottom,
+                                     int xPos, int yPos, int width, int height,
+                                     const Box &rBox ) const;
+
+        /// Function to parse "points" tags
+        Bezier *getPoints( const char *pTag ) const;
+};
+
+#endif
+
diff --git a/modules/gui/skins2/parser/builder_data.hpp b/modules/gui/skins2/parser/builder_data.hpp
new file mode 100644 (file)
index 0000000..d20a423
--- /dev/null
@@ -0,0 +1,311 @@
+/*****************************************************************************
+ * builder_data.hpp
+ *****************************************************************************
+ * Copyright (C) 2003 VideoLAN
+ * $Id: builder_data.hpp,v 1.1 2004/01/03 23:31:33 asmax Exp $
+ *
+ * Authors: Cyril Deguet     <asmax@via.ecp.fr>
+ *          Olivier Teulière <ipkiss@via.ecp.fr>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111, USA.
+ *****************************************************************************/
+
+//File generated by gen_builder.py
+//DO NOT EDIT BY HAND !
+
+#ifndef BUILDER_DATA_HPP
+#define BUILDER_DATA_HPP
+
+using namespace std;
+
+#include <vlc/vlc.h>
+#include <list>
+#include <map>
+#include <string>
+
+/// Structure for mapping data from XML file
+struct BuilderData
+{
+
+    /// Type definition
+    struct Theme
+    {
+        Theme( int magnet, uint32_t alpha, uint32_t moveAlpha, uint32_t fadeTime ):
+m_magnet( magnet ), m_alpha( alpha ), m_moveAlpha( moveAlpha ), m_fadeTime( fadeTime ) {}
+
+        int m_magnet;
+        uint32_t m_alpha;
+        uint32_t m_moveAlpha;
+        uint32_t m_fadeTime;
+    };
+    /// List
+    list<Theme> m_listTheme;
+
+    /// Type definition
+    struct Bitmap
+    {
+        Bitmap( const string & id, const string & fileName, uint32_t alphaColor ):
+m_id( id ), m_fileName( fileName ), m_alphaColor( alphaColor ) {}
+
+        const string m_id;
+        const string m_fileName;
+        uint32_t m_alphaColor;
+    };
+    /// List
+    list<Bitmap> m_listBitmap;
+
+    /// Type definition
+    struct Font
+    {
+        Font( const string & id, const string & fontName, int size ):
+m_id( id ), m_fontName( fontName ), m_size( size ) {}
+
+        const string m_id;
+        const string m_fontName;
+        int m_size;
+    };
+    /// List
+    list<Font> m_listFont;
+
+    /// Type definition
+    struct Window
+    {
+        Window( const string & id, int xPos, int yPos, bool visible, bool dragDrop, bool playOnDrop ):
+m_id( id ), m_xPos( xPos ), m_yPos( yPos ), m_visible( visible ), m_dragDrop( dragDrop ), m_playOnDrop( playOnDrop ) {}
+
+        const string m_id;
+        int m_xPos;
+        int m_yPos;
+        bool m_visible;
+        bool m_dragDrop;
+        bool m_playOnDrop;
+    };
+    /// List
+    list<Window> m_listWindow;
+
+    /// Type definition
+    struct Layout
+    {
+        Layout( const string & id, int width, int height, int minWidth, int maxWidth, int minHeight, int maxHeight, const string & windowId ):
+m_id( id ), m_width( width ), m_height( height ), m_minWidth( minWidth ), m_maxWidth( maxWidth ), m_minHeight( minHeight ), m_maxHeight( maxHeight ), m_windowId( windowId ) {}
+
+        const string m_id;
+        int m_width;
+        int m_height;
+        int m_minWidth;
+        int m_maxWidth;
+        int m_minHeight;
+        int m_maxHeight;
+        const string m_windowId;
+    };
+    /// List
+    list<Layout> m_listLayout;
+
+    /// Type definition
+    struct Anchor
+    {
+        Anchor( int xPos, int yPos, int range, int priority, const string & windowId ):
+m_xPos( xPos ), m_yPos( yPos ), m_range( range ), m_priority( priority ), m_windowId( windowId ) {}
+
+        int m_xPos;
+        int m_yPos;
+        int m_range;
+        int m_priority;
+        const string m_windowId;
+    };
+    /// List
+    list<Anchor> m_listAnchor;
+
+    /// Type definition
+    struct Button
+    {
+        Button( const string & id, int xPos, int yPos, const string & leftTop, const string & rightBottom, const string & upId, const string & downId, const string & overId, const string & actionId, const string & tooltip, const string & help, int layer, const string & windowId, const string & layoutId ):
+m_id( id ), m_xPos( xPos ), m_yPos( yPos ), m_leftTop( leftTop ), m_rightBottom( rightBottom ), m_upId( upId ), m_downId( downId ), m_overId( overId ), m_actionId( actionId ), m_tooltip( tooltip ), m_help( help ), m_layer( layer ), m_windowId( windowId ), m_layoutId( layoutId ) {}
+
+        const string m_id;
+        int m_xPos;
+        int m_yPos;
+        const string m_leftTop;
+        const string m_rightBottom;
+        const string m_upId;
+        const string m_downId;
+        const string m_overId;
+        const string m_actionId;
+        const string m_tooltip;
+        const string m_help;
+        int m_layer;
+        const string m_windowId;
+        const string m_layoutId;
+    };
+    /// List
+    list<Button> m_listButton;
+
+    /// Type definition
+    struct Checkbox
+    {
+        Checkbox( const string & id, int xPos, int yPos, const string & leftTop, const string & rightBottom, const string & up1Id, const string & down1Id, const string & over1Id, const string & up2Id, const string & down2Id, const string & over2Id, const string & state, const string & action1, const string & action2, const string & tooltip1, const string & tooltip2, const string & help, int layer, const string & windowId, const string & layoutId ):
+m_id( id ), m_xPos( xPos ), m_yPos( yPos ), m_leftTop( leftTop ), m_rightBottom( rightBottom ), m_up1Id( up1Id ), m_down1Id( down1Id ), m_over1Id( over1Id ), m_up2Id( up2Id ), m_down2Id( down2Id ), m_over2Id( over2Id ), m_state( state ), m_action1( action1 ), m_action2( action2 ), m_tooltip1( tooltip1 ), m_tooltip2( tooltip2 ), m_help( help ), m_layer( layer ), m_windowId( windowId ), m_layoutId( layoutId ) {}
+
+        const string m_id;
+        int m_xPos;
+        int m_yPos;
+        const string m_leftTop;
+        const string m_rightBottom;
+        const string m_up1Id;
+        const string m_down1Id;
+        const string m_over1Id;
+        const string m_up2Id;
+        const string m_down2Id;
+        const string m_over2Id;
+        const string m_state;
+        const string m_action1;
+        const string m_action2;
+        const string m_tooltip1;
+        const string m_tooltip2;
+        const string m_help;
+        int m_layer;
+        const string m_windowId;
+        const string m_layoutId;
+    };
+    /// List
+    list<Checkbox> m_listCheckbox;
+
+    /// Type definition
+    struct Image
+    {
+        Image( const string & id, int xPos, int yPos, const string & leftTop, const string & rightBottom, bool visible, const string & bmpId, const string & onclickId, const string & help, int layer, const string & windowId, const string & layoutId ):
+m_id( id ), m_xPos( xPos ), m_yPos( yPos ), m_leftTop( leftTop ), m_rightBottom( rightBottom ), m_visible( visible ), m_bmpId( bmpId ), m_onclickId( onclickId ), m_help( help ), m_layer( layer ), m_windowId( windowId ), m_layoutId( layoutId ) {}
+
+        const string m_id;
+        int m_xPos;
+        int m_yPos;
+        const string m_leftTop;
+        const string m_rightBottom;
+        bool m_visible;
+        const string m_bmpId;
+        const string m_onclickId;
+        const string m_help;
+        int m_layer;
+        const string m_windowId;
+        const string m_layoutId;
+    };
+    /// List
+    list<Image> m_listImage;
+
+    /// Type definition
+    struct Text
+    {
+        Text( const string & id, int xPos, int yPos, const string & fontId, const string & text, int width, const string & help, int layer, const string & windowId, const string & layoutId ):
+m_id( id ), m_xPos( xPos ), m_yPos( yPos ), m_fontId( fontId ), m_text( text ), m_width( width ), m_help( help ), m_layer( layer ), m_windowId( windowId ), m_layoutId( layoutId ) {}
+
+        const string m_id;
+        int m_xPos;
+        int m_yPos;
+        const string m_fontId;
+        const string m_text;
+        int m_width;
+        const string m_help;
+        int m_layer;
+        const string m_windowId;
+        const string m_layoutId;
+    };
+    /// List
+    list<Text> m_listText;
+
+    /// Type definition
+    struct RadialSlider
+    {
+        RadialSlider( const string & id, const string & visible, int xPos, int yPos, const string & leftTop, const string & rightBottom, const string & sequence, int nbImages, double minAngle, double maxAngle, const string & value, const string & tooltip, const string & help, int layer, const string & windowId, const string & layoutId ):
+m_id( id ), m_visible( visible ), m_xPos( xPos ), m_yPos( yPos ), m_leftTop( leftTop ), m_rightBottom( rightBottom ), m_sequence( sequence ), m_nbImages( nbImages ), m_minAngle( minAngle ), m_maxAngle( maxAngle ), m_value( value ), m_tooltip( tooltip ), m_help( help ), m_layer( layer ), m_windowId( windowId ), m_layoutId( layoutId ) {}
+
+        const string m_id;
+        const string m_visible;
+        int m_xPos;
+        int m_yPos;
+        const string m_leftTop;
+        const string m_rightBottom;
+        const string m_sequence;
+        int m_nbImages;
+        double m_minAngle;
+        double m_maxAngle;
+        const string m_value;
+        const string m_tooltip;
+        const string m_help;
+        int m_layer;
+        const string m_windowId;
+        const string m_layoutId;
+    };
+    /// List
+    list<RadialSlider> m_listRadialSlider;
+
+    /// Type definition
+    struct Slider
+    {
+        Slider( const string & id, const string & visible, int xPos, int yPos, const string & leftTop, const string & rightBottom, const string & upId, const string & downId, const string & overId, const string & points, int thickness, const string & value, const string & tooltip, const string & help, int layer, const string & windowId, const string & layoutId ):
+m_id( id ), m_visible( visible ), m_xPos( xPos ), m_yPos( yPos ), m_leftTop( leftTop ), m_rightBottom( rightBottom ), m_upId( upId ), m_downId( downId ), m_overId( overId ), m_points( points ), m_thickness( thickness ), m_value( value ), m_tooltip( tooltip ), m_help( help ), m_layer( layer ), m_windowId( windowId ), m_layoutId( layoutId ) {}
+
+        const string m_id;
+        const string m_visible;
+        int m_xPos;
+        int m_yPos;
+        const string m_leftTop;
+        const string m_rightBottom;
+        const string m_upId;
+        const string m_downId;
+        const string m_overId;
+        const string m_points;
+        int m_thickness;
+        const string m_value;
+        const string m_tooltip;
+        const string m_help;
+        int m_layer;
+        const string m_windowId;
+        const string m_layoutId;
+    };
+    /// List
+    list<Slider> m_listSlider;
+
+    /// Type definition
+    struct List
+    {
+        List( const string & id, int xPos, int yPos, int width, int height, const string & leftTop, const string & rightBottom, const string & fontId, const string & var, uint32_t fgColor, uint32_t playColor, uint32_t bgColor1, uint32_t bgColor2, uint32_t selColor, const string & help, int layer, const string & windowId, const string & layoutId ):
+m_id( id ), m_xPos( xPos ), m_yPos( yPos ), m_width( width ), m_height( height ), m_leftTop( leftTop ), m_rightBottom( rightBottom ), m_fontId( fontId ), m_var( var ), m_fgColor( fgColor ), m_playColor( playColor ), m_bgColor1( bgColor1 ), m_bgColor2( bgColor2 ), m_selColor( selColor ), m_help( help ), m_layer( layer ), m_windowId( windowId ), m_layoutId( layoutId ) {}
+
+        const string m_id;
+        int m_xPos;
+        int m_yPos;
+        int m_width;
+        int m_height;
+        const string m_leftTop;
+        const string m_rightBottom;
+        const string m_fontId;
+        const string m_var;
+        uint32_t m_fgColor;
+        uint32_t m_playColor;
+        uint32_t m_bgColor1;
+        uint32_t m_bgColor2;
+        uint32_t m_selColor;
+        const string m_help;
+        int m_layer;
+        const string m_windowId;
+        const string m_layoutId;
+    };
+    /// List
+    list<List> m_listList;
+
+
+};
+
+#endif
diff --git a/modules/gui/skins2/parser/flex.c b/modules/gui/skins2/parser/flex.c
new file mode 100644 (file)
index 0000000..6605519
--- /dev/null
@@ -0,0 +1,7916 @@
+/* A lexical scanner generated by flex */
+
+/* Scanner skeleton version:
+ * $Header: /root/vlc-cvs/modules/gui/skins2/parser/Attic/flex.c,v 1.1 2004/01/03 23:31:33 asmax Exp $
+ */
+
+#define FLEX_SCANNER
+#define YY_FLEX_MAJOR_VERSION 2
+#define YY_FLEX_MINOR_VERSION 5
+
+#include <stdio.h>
+#include <errno.h>
+
+/* cfront 1.2 defines "c_plusplus" instead of "__cplusplus" */
+#ifdef c_plusplus
+#ifndef __cplusplus
+#define __cplusplus
+#endif
+#endif
+
+
+#ifdef __cplusplus
+
+#include <stdlib.h>
+#ifndef _WIN32
+#include <unistd.h>
+#else
+#ifndef YY_ALWAYS_INTERACTIVE
+#ifndef YY_NEVER_INTERACTIVE
+extern int isatty YY_PROTO(( int ));
+#endif
+#endif
+#endif
+
+/* Use prototypes in function declarations. */
+#define YY_USE_PROTOS
+
+/* The "const" storage-class-modifier is valid. */
+#define YY_USE_CONST
+
+#else  /* ! __cplusplus */
+
+#if __STDC__
+
+#define YY_USE_PROTOS
+#define YY_USE_CONST
+
+#endif /* __STDC__ */
+#endif /* ! __cplusplus */
+
+#ifdef __TURBOC__
+ #pragma warn -rch
+ #pragma warn -use
+#include <io.h>
+#include <stdlib.h>
+#define YY_USE_CONST
+#define YY_USE_PROTOS
+#endif
+
+#ifdef YY_USE_CONST
+#define yyconst const
+#else
+#define yyconst
+#endif
+
+
+#ifdef YY_USE_PROTOS
+#define YY_PROTO(proto) proto
+#else
+#define YY_PROTO(proto) ()
+#endif
+
+/* Returned upon end-of-file. */
+#define YY_NULL 0
+
+/* Promotes a possibly negative, possibly signed char to an unsigned
+ * integer for use as an array index.  If the signed char is negative,
+ * we want to instead treat it as an 8-bit unsigned char, hence the
+ * double cast.
+ */
+#define YY_SC_TO_UI(c) ((unsigned int) (unsigned char) c)
+
+/* Enter a start condition.  This macro really ought to take a parameter,
+ * but we do it the disgusting crufty way forced on us by the ()-less
+ * definition of BEGIN.
+ */
+#define BEGIN yy_start = 1 + 2 *
+
+/* Translate the current start state into a value that can be later handed
+ * to BEGIN to return to the state.  The YYSTATE alias is for lex
+ * compatibility.
+ */
+#define YY_START ((yy_start - 1) / 2)
+#define YYSTATE YY_START
+
+/* Action number for EOF rule of a given start state. */
+#define YY_STATE_EOF(state) (YY_END_OF_BUFFER + state + 1)
+
+/* Special action meaning "start processing a new file". */
+#define YY_NEW_FILE yyrestart( yyin )
+
+#define YY_END_OF_BUFFER_CHAR 0
+
+/* Size of default input buffer. */
+#define YY_BUF_SIZE 16384
+
+typedef struct yy_buffer_state *YY_BUFFER_STATE;
+
+extern int yyleng;
+extern FILE *yyin, *yyout;
+
+#define EOB_ACT_CONTINUE_SCAN 0
+#define EOB_ACT_END_OF_FILE 1
+#define EOB_ACT_LAST_MATCH 2
+
+/* The funky do-while in the following #define is used to turn the definition
+ * int a single C statement (which needs a semi-colon terminator).  This
+ * avoids problems with code like:
+ *
+ *     if ( condition_holds )
+ *             yyless( 5 );
+ *     else
+ *             do_something_else();
+ *
+ * Prior to using the do-while the compiler would get upset at the
+ * "else" because it interpreted the "if" statement as being all
+ * done when it reached the ';' after the yyless() call.
+ */
+
+/* Return all but the first 'n' matched characters back to the input stream. */
+
+#define yyless(n) \
+       do \
+               { \
+               /* Undo effects of setting up yytext. */ \
+               *yy_cp = yy_hold_char; \
+               YY_RESTORE_YY_MORE_OFFSET \
+               yy_c_buf_p = yy_cp = yy_bp + n - YY_MORE_ADJ; \
+               YY_DO_BEFORE_ACTION; /* set up yytext again */ \
+               } \
+       while ( 0 )
+
+#define unput(c) yyunput( c, yytext_ptr )
+
+/* The following is because we cannot portably get our hands on size_t
+ * (without autoconf's help, which isn't available because we want
+ * flex-generated scanners to compile on their own).
+ */
+typedef unsigned int yy_size_t;
+
+
+struct yy_buffer_state
+       {
+       FILE *yy_input_file;
+
+       char *yy_ch_buf;                /* input buffer */
+       char *yy_buf_pos;               /* current position in input buffer */
+
+       /* Size of input buffer in bytes, not including room for EOB
+        * characters.
+        */
+       yy_size_t yy_buf_size;
+
+       /* Number of characters read into yy_ch_buf, not including EOB
+        * characters.
+        */
+       int yy_n_chars;
+
+       /* Whether we "own" the buffer - i.e., we know we created it,
+        * and can realloc() it to grow it, and should free() it to
+        * delete it.
+        */
+       int yy_is_our_buffer;
+
+       /* Whether this is an "interactive" input source; if so, and
+        * if we're using stdio for input, then we want to use getc()
+        * instead of fread(), to make sure we stop fetching input after
+        * each newline.
+        */
+       int yy_is_interactive;
+
+       /* Whether we're considered to be at the beginning of a line.
+        * If so, '^' rules will be active on the next match, otherwise
+        * not.
+        */
+       int yy_at_bol;
+
+       /* Whether to try to fill the input buffer when we reach the
+        * end of it.
+        */
+       int yy_fill_buffer;
+
+       int yy_buffer_status;
+#define YY_BUFFER_NEW 0
+#define YY_BUFFER_NORMAL 1
+       /* When an EOF's been seen but there's still some text to process
+        * then we mark the buffer as YY_EOF_PENDING, to indicate that we
+        * shouldn't try reading from the input source any more.  We might
+        * still have a bunch of tokens to match, though, because of
+        * possible backing-up.
+        *
+        * When we actually see the EOF, we change the status to "new"
+        * (via yyrestart()), so that the user can continue scanning by
+        * just pointing yyin at a new input file.
+        */
+#define YY_BUFFER_EOF_PENDING 2
+       };
+
+static YY_BUFFER_STATE yy_current_buffer = 0;
+
+/* We provide macros for accessing buffer states in case in the
+ * future we want to put the buffer states in a more general
+ * "scanner state".
+ */
+#define YY_CURRENT_BUFFER yy_current_buffer
+
+
+/* yy_hold_char holds the character lost when yytext is formed. */
+static char yy_hold_char;
+
+static int yy_n_chars;         /* number of characters read into yy_ch_buf */
+
+
+int yyleng;
+
+/* Points to current character in buffer. */
+static char *yy_c_buf_p = (char *) 0;
+static int yy_init = 1;                /* whether we need to initialize */
+static int yy_start = 0;       /* start state number */
+
+/* Flag which is used to allow yywrap()'s to do buffer switches
+ * instead of setting up a fresh yyin.  A bit of a hack ...
+ */
+static int yy_did_buffer_switch_on_eof;
+
+void yyrestart YY_PROTO(( FILE *input_file ));
+
+void yy_switch_to_buffer YY_PROTO(( YY_BUFFER_STATE new_buffer ));
+void yy_load_buffer_state YY_PROTO(( void ));
+YY_BUFFER_STATE yy_create_buffer YY_PROTO(( FILE *file, int size ));
+void yy_delete_buffer YY_PROTO(( YY_BUFFER_STATE b ));
+void yy_init_buffer YY_PROTO(( YY_BUFFER_STATE b, FILE *file ));
+void yy_flush_buffer YY_PROTO(( YY_BUFFER_STATE b ));
+#define YY_FLUSH_BUFFER yy_flush_buffer( yy_current_buffer )
+
+YY_BUFFER_STATE yy_scan_buffer YY_PROTO(( char *base, yy_size_t size ));
+YY_BUFFER_STATE yy_scan_string YY_PROTO(( yyconst char *yy_str ));
+YY_BUFFER_STATE yy_scan_bytes YY_PROTO(( yyconst char *bytes, int len ));
+
+static void *yy_flex_alloc YY_PROTO(( yy_size_t ));
+static void *yy_flex_realloc YY_PROTO(( void *, yy_size_t ));
+static void yy_flex_free YY_PROTO(( void * ));
+
+#define yy_new_buffer yy_create_buffer
+
+#define yy_set_interactive(is_interactive) \
+       { \
+       if ( ! yy_current_buffer ) \
+               yy_current_buffer = yy_create_buffer( yyin, YY_BUF_SIZE ); \
+       yy_current_buffer->yy_is_interactive = is_interactive; \
+       }
+
+#define yy_set_bol(at_bol) \
+       { \
+       if ( ! yy_current_buffer ) \
+               yy_current_buffer = yy_create_buffer( yyin, YY_BUF_SIZE ); \
+       yy_current_buffer->yy_at_bol = at_bol; \
+       }
+
+#define YY_AT_BOL() (yy_current_buffer->yy_at_bol)
+
+
+#define yywrap() 1
+#define YY_SKIP_YYWRAP
+typedef unsigned char YY_CHAR;
+FILE *yyin = (FILE *) 0, *yyout = (FILE *) 0;
+typedef int yy_state_type;
+extern char *yytext;
+#define yytext_ptr yytext
+
+static yy_state_type yy_get_previous_state YY_PROTO(( void ));
+static yy_state_type yy_try_NUL_trans YY_PROTO(( yy_state_type current_state ));
+static int yy_get_next_buffer YY_PROTO(( void ));
+static void yy_fatal_error YY_PROTO(( yyconst char msg[] ));
+
+/* Done after the current pattern has been matched and before the
+ * corresponding action - sets up yytext.
+ */
+#define YY_DO_BEFORE_ACTION \
+       yytext_ptr = yy_bp; \
+       yyleng = (int) (yy_cp - yy_bp); \
+       yy_hold_char = *yy_cp; \
+       *yy_cp = '\0'; \
+       yy_c_buf_p = yy_cp;
+
+#define YY_NUM_RULES 472
+#define YY_END_OF_BUFFER 473
+static yyconst short int yy_accept[2803] =
+    {   0,
+        0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
+        0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
+        0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
+        0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
+        0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
+        0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
+        0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
+        0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
+        0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
+        0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
+
+        0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
+        0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
+        0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
+        0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
+        0,    0,    0,    0,    0,    0,  473,  471,   31,   10,
+       10,   31,   31,  450,   10,  450,    5,    6,    5,    8,
+        9,    8,  466,  458,  459,  467,  464,  467,  465,  470,
+      458,  459,  470,  472,  472,   45,   10,   45,   45,   45,
+       43,   45,   45,   45,   45,  472,   49,   10,   49,  472,
+       49,  472,   59,   10,   59,   59,   59,   57,   59,   59,
+
+       59,   63,   10,   63,  472,   73,   10,   73,   73,   73,
+       71,   73,   73,   73,   77,   10,   77,  472,   93,   10,
+       93,   93,   93,   91,   93,   93,   93,   93,   93,   97,
+       10,   97,  109,   10,  109,  109,  109,  107,  109,  109,
+      109,  109,  113,   10,  113,  472,  129,   10,  129,  129,
+      129,  127,  129,  129,  129,  129,  129,  129,  472,  133,
+       10,  133,  133,  151,   10,  151,  151,  151,  149,  151,
+      151,  151,  151,  472,  155,   10,  155,  163,   10,  163,
+      163,  163,  161,  163,  163,  472,  167,   10,  167,  167,
+      472,  179,   10,  179,  179,  179,  177,  179,  179,  179,
+
+      179,  183,   10,  183,  472,  205,   10,  205,  205,  205,
+      203,  205,  205,  205,  205,  205,  205,  205,  205,  209,
+       10,  209,  472,  231,   10,  231,  231,  231,  229,  231,
+      231,  231,  231,  231,  231,  231,  231,  235,   10,  235,
+      472,  261,   10,  261,  261,  261,  259,  261,  261,  261,
+      261,  261,  261,  261,  261,  261,  261,  261,  265,   10,
+      265,  472,  303,   10,  303,  303,  303,  301,  303,  303,
+      303,  303,  303,  303,  303,  303,  303,  303,  303,  303,
+      307,   10,  307,  472,  339,   10,  339,  339,  339,  337,
+      339,  339,  339,  339,  339,  339,  339,  339,  339,  339,
+
+      339,  339,  343,   10,  343,  472,  373,   10,  373,  373,
+      373,  371,  373,  373,  373,  373,  373,  373,  373,  373,
+      373,  373,  373,  377,   10,  377,  472,  405,   10,  405,
+      405,  405,  403,  405,  405,  405,  405,  405,  405,  405,
+      405,  405,  405,  405,  409,   10,  409,  472,  445,   10,
+      445,  445,  445,  443,  445,  445,  445,  445,  445,  445,
+      445,  445,  445,  445,  445,  445,  449,   10,  449,  466,
+      458,  459,  467,  467,  466,   10,    0,    2,    2,    0,
+        4,    7,  461,  460,    0,    0,    0,    0,    0,  469,
+        0,   44,   46,   46,   46,   46,   46,   46,    0,    0,
+
+        0,    0,    0,    0,   58,   60,   60,   60,   60,    0,
+       72,   74,   74,   74,   74,    0,   92,   94,   94,   94,
+       94,   94,   94,   94,    0,  108,  110,  110,  110,  110,
+      110,    0,  128,  130,  130,  130,  130,  130,    0,    0,
+        0,    0,    0,    0,  150,  152,  152,  152,  152,  152,
+      152,    0,    0,  162,  164,    0,    0,    0,    0,    0,
+        0,    0,    0,    0,    0,    0,    0,    0,  178,  180,
+      180,  180,    0,    0,    0,    0,    0,  204,  206,  206,
+      206,  206,  206,  206,  206,  206,    0,    0,    0,    0,
+        0,    0,  230,  232,  232,    0,    0,  232,  232,  232,
+
+      232,    0,    0,    0,    0,    0,    0,    0,  260,  262,
+      262,  262,  262,  262,  262,  262,  262,  262,  262,    0,
+        0,    0,    0,    0,  302,  304,  304,  304,  304,  304,
+      304,  304,  304,  304,  304,  304,    0,    0,    0,    0,
+        0,  338,  340,  340,  340,  340,  340,  340,  340,  340,
+      340,  340,  340,  340,  340,    0,    0,    0,    0,    0,
+        0,  372,  374,  374,  374,  374,  374,  374,  374,  374,
+      374,  374,  374,  374,    0,    0,    0,    0,    0,  404,
+      406,  406,  406,  406,  406,  406,  406,  406,  406,  406,
+        0,    0,    0,    0,    0,  444,  446,  446,  446,  446,
+
+      446,  446,  446,  446,  446,  446,  446,  446,  446,    0,
+        0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
+        3,    0,    0,    0,    0,    0,    0,    0,  468,    0,
+       46,   46,   46,   46,   46,    0,    0,    0,    0,    0,
+        0,    0,   60,   60,    0,    0,    0,    0,   74,    0,
+        0,   74,    0,    0,   94,   94,    0,    0,   94,   94,
+       94,    0,    0,  110,  110,  110,  110,    0,    0,  130,
+        0,    0,  130,  130,    0,  120,  119,    0,  122,  121,
+        0,    0,    0,  152,    0,    0,  152,  152,  152,    0,
+        0,    0,    0,  158,  157,    0,  160,  159,    0,    0,
+
+        0,    0,    0,    0,    0,    0,    0,    0,    0,  180,
+      180,    0,  170,  169,    0,  172,  171,    0,    0,  206,
+        0,    0,  206,  206,  206,  206,  206,    0,  190,  189,
+        0,  192,  191,    0,    0,  232,    0,  222,  221,  232,
+        0,    0,  232,  232,    0,  220,  219,    0,  216,  215,
+        0,  218,  217,    0,    0,  262,  262,  262,    0,    0,
+      262,  262,  262,  262,    0,    0,    0,  240,  239,    0,
+      242,  241,    0,    0,  304,  304,  304,    0,    0,  304,
+      304,  304,  304,  304,  304,  304,    0,  270,  269,    0,
+      272,  271,    0,    0,  340,  340,    0,    0,  340,  340,
+
+      340,  340,  340,  340,    0,    0,  340,  340,    0,  314,
+      313,    0,  316,  315,    0,    0,  374,    0,    0,  374,
+      374,  374,  374,  374,  374,  374,  374,  374,    0,  350,
+      349,    0,  352,  351,    0,    0,  406,  406,  406,  406,
+        0,    0,  406,  406,  406,  406,    0,  384,  383,    0,
+      386,  385,    0,    0,  446,  446,  446,  446,  446,    0,
+        0,  446,  446,  446,  446,  446,  446,  446,    0,  416,
+      415,    0,  418,  417,    0,    0,    0,  463,    0,   30,
+        1,    0,    0,  456,    0,    0,    0,  453,  452,    0,
+        0,   46,   46,   46,   46,   46,    0,    0,    0,   48,
+
+        0,    0,    0,    0,    0,   60,   60,    0,   52,   51,
+        0,    0,   62,    0,   74,    0,   66,   65,    0,    0,
+        0,    0,   76,    0,   94,   94,    0,   80,   79,   94,
+       94,   94,    0,    0,   96,    0,  110,  110,  110,  110,
+        0,    0,  112,    0,  130,    0,  116,  115,  130,  130,
+        0,    0,    0,  132,    0,  152,    0,  136,  135,  152,
+      152,  152,  152,  152,    0,    0,    0,  154,    0,    0,
+        0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
+      166,    0,  180,  180,    0,    0,  182,    0,  206,    0,
+      186,  185,  206,  206,  206,  206,  206,    0,    0,  208,
+
+        0,  232,  232,    0,  212,  211,  232,  232,    0,    0,
+      234,    0,  262,  262,  262,    0,  238,  237,  262,  262,
+      262,  262,    0,  248,  247,    0,    0,  264,    0,  304,
+      304,  304,    0,  268,  267,  304,  304,  304,  304,  304,
+        0,    0,    0,    0,    0,    0,  306,    0,  340,  340,
+        0,  310,  309,  340,  340,  340,  340,  340,  340,    0,
+      322,  321,  340,  340,    0,    0,  342,    0,  374,    0,
+      346,  345,  374,  374,  374,  374,  374,  374,  374,  374,
+      374,    0,    0,  376,    0,  406,  406,  406,  406,    0,
+      380,  379,  406,  406,  406,  406,    0,    0,  408,    0,
+
+      446,  446,  446,  446,  446,    0,  412,  411,  446,  446,
+      446,  446,    0,    0,  446,  446,    0,    0,  448,    0,
+        0,    0,    0,  457,  451,    0,    0,    0,   46,   46,
+       46,   46,   46,    0,    0,    0,    0,   78,    0,   60,
+        0,    0,    0,   74,    0,   70,   69,    0,   94,    0,
+        0,   94,    0,    0,   94,    0,  110,  110,    0,    0,
+      110,    0,  130,  130,  130,    0,    0,  152,  152,  152,
+      152,  152,  152,    0,    0,    0,    0,    0,    0,    0,
+        0,    0,    0,  378,    0,  180,  180,    0,    0,    0,
+      206,  206,  206,  206,  206,    0,  232,    0,    0,  232,
+
+      232,    0,  262,    0,    0,    0,    0,  262,    0,    0,
+      262,  262,    0,  304,  304,  304,    0,    0,  304,  304,
+      304,  304,  304,  304,    0,  278,  277,    0,  284,  283,
+        0,    0,    0,    0,    0,  340,    0,    0,  340,  340,
+      340,  340,  340,  340,    0,    0,    0,  374,  374,  374,
+      374,  374,  374,  374,  374,  374,    0,  406,  406,    0,
+        0,    0,    0,  406,    0,    0,  406,  406,    0,  446,
+      446,    0,    0,  446,    0,    0,  446,  446,  446,  446,
+        0,  430,  429,  446,  446,    0,    0,    0,    0,    0,
+       12,    0,  454,  455,   32,    0,    0,   46,   46,   46,
+
+       46,    0,    0,    0,   64,   78,    0,   60,    0,   54,
+       53,    0,    0,    0,    0,    0,    0,    0,   82,   81,
+       94,    0,   84,   83,   94,    0,  110,    0,    0,    0,
+      100,   99,  110,    0,  130,  130,  130,    0,    0,  152,
+      152,  152,  152,  152,    0,    0,  156,    0,    0,    0,
+        0,  184,    0,    0,    0,    0,  378,    0,  180,    0,
+        0,    0,    0,  202,  201,    0,    0,  206,  206,  206,
+      206,    0,    0,    0,    0,  228,  227,  232,  232,    0,
+      262,    0,  250,  249,    0,  258,  257,  262,    0,  252,
+      251,  262,  262,    0,  304,    0,    0,    0,    0,    0,
+
+      300,  299,  304,    0,    0,    0,    0,  304,    0,    0,
+      304,    0,    0,  324,  323,    0,  336,  335,  340,    0,
+      326,  325,  340,  340,  340,  340,    0,    0,  340,    0,
+        0,  370,  369,  374,  374,  374,  374,  374,  374,  374,
+        0,    0,  374,    0,    0,    0,  406,    0,  390,  389,
+        0,  402,  401,  406,    0,  388,  387,  406,    0,    0,
+        0,  446,  446,    0,  428,  427,  446,    0,  442,  441,
+      446,  446,  446,  446,  446,    0,    0,    0,    0,    0,
+        0,   11,   32,    0,   38,   37,   46,    0,    0,   46,
+       46,    0,    0,   50,   64,  114,   60,    0,    0,   68,
+
+       67,    0,    0,   86,   85,    0,    0,   94,    0,   95,
+        0,    0,    0,  104,  103,  110,    0,  130,  130,  130,
+      134,    0,    0,    0,  152,  152,  152,  152,    0,  138,
+      137,  156,    0,  168,  236,    0,  184,    0,    0,    0,
+      308,    0,  180,    0,  176,  175,    0,    0,  198,  197,
+      206,  206,  206,  206,    0,    0,  224,  223,  232,  232,
+        0,    0,    0,  262,  262,  262,    0,  304,  304,    0,
+      280,  279,    0,  286,  285,  304,    0,  282,  281,    0,
+      288,  287,  304,    0,  290,  289,  304,    0,  340,    0,
+        0,  340,  340,  340,    0,  332,  331,  340,    0,  374,
+
+      374,  374,  374,  374,  374,  374,    0,  366,  365,  374,
+        0,    0,  392,  391,  406,    0,    0,  406,  406,    0,
+      394,  393,    0,  407,  446,  446,    0,    0,  446,  446,
+      446,  446,  446,    0,  420,  419,    0,    0,    0,    0,
+       46,    0,   36,   35,   46,    0,    0,    0,    0,   47,
+       50,  114,   60,    0,    0,   75,    0,   88,   87,   94,
+        0,  102,  101,    0,    0,    0,  130,  130,    0,    0,
+      134,    0,    0,  140,  139,  152,  152,  152,  152,    0,
+      168,  236,    0,    0,    0,    0,  308,    0,  165,  180,
+        0,    0,    0,    0,    0,  206,    0,    0,    0,  207,
+
+        0,    0,    0,    0,    0,    0,  254,  253,    0,    0,
+      262,  262,    0,    0,    0,    0,    0,    0,    0,  304,
+      304,    0,    0,    0,    0,  328,  327,  340,  340,  340,
+        0,    0,    0,    0,    0,  374,  374,  374,  374,  374,
+      374,    0,    0,    0,    0,    0,    0,  398,  397,  406,
+        0,    0,  446,  446,    0,    0,    0,  422,  421,    0,
+        0,  446,  446,  446,    0,    0,    0,    0,    0,    0,
+        0,    0,   46,    0,   34,   33,    0,   60,    0,   61,
+       94,    0,  106,  105,    0,    0,    0,  130,    0,  118,
+      117,    0,  131,  152,    0,    0,  152,    0,    0,    0,
+
+      153,  266,  410,    0,    0,    0,    0,    0,  181,    0,
+      194,  193,    0,  200,  199,  206,    0,  188,  187,    0,
+      226,  225,    0,  214,  213,    0,    0,  244,  243,  262,
+      262,    0,  263,    0,  292,  291,    0,  294,  293,    0,
+      274,  273,  304,  304,    0,    0,  318,  317,  340,  340,
+      340,    0,  312,  311,    0,  341,    0,  354,  353,    0,
+        0,    0,    0,    0,    0,  374,    0,    0,  374,    0,
+      348,  347,    0,    0,  396,  395,  406,    0,  382,  381,
+        0,    0,    0,    0,    0,  432,  431,    0,  424,  423,
+      446,  446,    0,    0,    0,  414,  413,    0,  462,    0,
+
+        0,    0,   42,   41,    0,    0,   98,   60,    0,    0,
+        0,    0,  124,  123,  130,    0,    0,    0,  144,  143,
+        0,    0,    0,  142,  141,  266,  410,    0,  210,    0,
+      174,  173,  206,    0,  262,  262,  304,  304,    0,  340,
+        0,    0,  340,    0,  364,  363,    0,  362,  361,    0,
+      360,  359,  374,    0,  358,  357,  374,    0,  406,    0,
+      436,  435,    0,  438,  437,    0,    0,  446,    0,  440,
+      439,    0,    0,    0,    0,    0,    0,    0,    0,    0,
+        0,    0,    0,    0,    0,    0,    0,   40,   39,   98,
+        0,    0,    0,   90,   89,    0,    0,    0,    0,  148,
+
+      147,    0,  146,  145,    0,  210,  206,    0,  262,  262,
+      304,  304,    0,  305,  340,    0,  330,  329,  340,  374,
+      374,    0,  406,    0,  434,  433,  446,    0,  447,    0,
+        0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
+        0,    0,    0,    0,    0,    0,    0,   56,   55,    0,
+      111,    0,  126,  125,    0,    0,    0,    0,  233,    0,
+        0,    0,    0,    0,    0,  304,  304,    0,    0,    0,
+        0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
+        0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
+        0,    0,    0,    0,    0,    0,    0,  344,    0,  196,
+
+      195,    0,  246,  245,    0,  256,  255,    0,  276,  275,
+        0,    0,    0,    0,    0,  320,  319,    0,  334,  333,
+        0,  356,  355,    0,  368,  367,    0,    0,  400,  399,
+        0,  426,  425,    0,    0,    0,    0,    0,    0,    0,
+        0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
+        0,  344,    0,  296,  295,    0,  298,  297,    0,    0,
+        0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
+        0,    0,    0,    0,    0,    0,    0,    0,    0,  375,
+        0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
+        0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
+
+        0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
+        0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
+        0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
+        0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
+        0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
+        0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
+        0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
+        0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
+        0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
+        0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
+
+        0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
+        0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
+        0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
+        0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
+        0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
+        0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
+        0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
+        0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
+        0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
+        0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
+
+        0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
+        0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
+        0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
+        0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
+        0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
+        0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
+        0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
+        0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
+        0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
+        0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
+
+        0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
+        0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
+        0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
+        0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
+        0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
+        0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
+        0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
+        0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
+        0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
+        0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
+
+        0,    0,    0,    0,    0,    0,    0,    0,   22,    0,
+        0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
+        0,    0,   17,    0,    0,    0,    0,    0,    0,    0,
+        0,    0,    0,    0,   14,    0,   20,    0,   15,    0,
+        0,    0,    0,    0,    0,    0,    0,    0,   21,    0,
+        0,    0,    0,   19,    0,   28,    0,   27,    0,    0,
+        0,   13,    0,    0,    0,    0,    0,    0,    0,   25,
+        0,    0,    0,   29,    0,    0,    0,    0,    0,    0,
+        0,    0,    0,   26,    0,   16,    0,    0,    0,    0,
+        0,    0,    0,   18,    0,   24,    0,    0,    0,    0,
+
+       23,    0
+    } ;
+
+static yyconst int yy_ec[256] =
+    {   0,
+        1,    1,    1,    1,    1,    1,    1,    1,    2,    3,
+        1,    2,    4,    1,    1,    1,    1,    1,    1,    1,
+        1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
+        1,    2,    5,    6,    7,    1,    1,    8,    9,    1,
+        1,    1,    1,    1,   10,   11,   12,   13,   14,   15,
+       13,   13,   13,   13,   13,   13,   13,   16,   17,   18,
+       19,   20,   21,    1,   22,   23,   24,   25,   26,   27,
+       28,   16,   29,   16,   16,   30,   31,   16,   32,   33,
+       16,   34,   35,   36,   16,   16,   37,   16,   38,   16,
+       39,    1,   40,    1,   16,    1,   41,   42,   43,   44,
+
+       45,   46,   47,   48,   49,   16,   50,   51,   52,   53,
+       54,   55,   56,   57,   58,   59,   60,   61,   62,   63,
+       64,   65,    1,    1,    1,    1,    1,    1,    1,    1,
+        1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
+        1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
+        1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
+        1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
+        1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
+        1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
+        1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
+
+        1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
+        1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
+        1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
+        1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
+        1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
+        1,    1,    1,    1,    1
+    } ;
+
+static yyconst int yy_meta[66] =
+    {   0,
+        1,    2,    2,    2,    1,    1,    1,    1,    1,    3,
+        3,    1,    4,    4,    4,    5,    6,    1,    7,    8,
+        1,    9,    9,    9,    9,    9,    9,    5,    5,    5,
+        5,    5,    5,    5,    5,    5,    5,    5,    1,    1,
+        9,    9,    9,    9,    9,    9,    5,    5,    5,    5,
+        5,    5,    5,    5,    5,    5,    5,    5,    5,    5,
+        5,    5,    5,    5,    5
+    } ;
+
+static yyconst short int yy_base[3053] =
+    {   0,
+        0,    0,    0,    3,    6,    9,   12,   29,   16,   19,
+       14,   17,   33,   36,   49,   55,   45,   61,   66,   72,
+      101,  162,   75,   78,  121,  125,  128,  131,  134,  182,
+      186,  189,  192,  195,  223,  272,  243,  247,  250,  253,
+      321,  371,  292,  296,  299,  302,  421,    0,  341,  344,
+      347,  350,  486,  548,  391,  394,  397,  400,  610,    0,
+      506,  510,  514,  517,  568,  572,  576,  579,  674,  677,
+      695,  757,  715,  718,  721,  724,  727,  777,  819,  883,
+      780,  783,  786,  789,  839,  842,  845,  848,  851,  903,
+      947, 1011,  906,  909,  912,  915, 1075,    0,  967,  970,
+
+      973,  976, 1140,    0,  979, 1031, 1034, 1037, 1205,    0,
+     1040, 1043, 1269, 1272, 1290,    0, 1354, 1357, 1360, 1363,
+     1381,    0, 1445, 1448, 1451, 1454, 1472,    0, 1536, 1539,
+     1542, 1545, 1563,    0, 1627, 1630, 1633, 1636, 1654,    0,
+     1718, 1721, 1724, 1727, 1729, 1740, 7513, 9896, 9896,   84,
+       95,   29,   41, 9896,  152,   51, 9896, 9896, 7501, 9896,
+     9896, 7490, 9896, 7505, 7489, 1727, 9896, 9896, 9896, 9896,
+     7487, 7487, 7448, 9896, 1730, 9896,  155, 7467,    0,  139,
+     9896, 7434, 7443,  107, 7438, 1735, 9896,  213, 1749, 1736,
+      200,  517, 9896,  216, 7452,    0,  201, 9896, 7408, 7402,
+
+     7406, 9896,  256,  524,  579, 9896,  305, 7429,    0,  525,
+     9896, 7387, 7403, 7400, 9896,  353,  586,  727, 9896,  403,
+     7424,    0,  587, 9896, 7389, 7383,  693, 7383, 7367, 9896,
+      539,  856, 9896,  600, 7399,    0,  735, 9896, 7357, 7364,
+     7371, 7366, 9896,  680,  859, 1744, 9896,  683, 7390,    0,
+      789, 9896, 7352, 7364, 7356, 7356, 1785, 1788,  851, 9896,
+      686, 1772,  920, 9896,  747, 7384,    0,  794, 9896, 7358,
+     7354,   42, 7348,  915, 9896,  809,  923, 9896,  814, 7375,
+        0,  857, 9896, 1792, 1795, 1810, 9896,  871, 7381,  984,
+      979, 9896,  935, 7372,    0,  921, 9896, 7329, 7344, 1806,
+
+     1816, 9896, 1004, 1048, 1043, 9896, 1275, 7363,    0,  924,
+     9896, 7337,   48, 7326, 7317, 7320, 7313, 1838, 1845, 9896,
+     1278, 1800, 1795, 9896, 1281, 7331,    0,  988, 9896, 7284,
+     1848, 7286, 7276, 7279, 1851, 1856, 1859, 9896, 1366, 1801,
+     1780, 9896, 1457, 7307,    0, 1049, 9896, 7283, 7271, 7279,
+     7279, 7277, 7255, 7262, 7245, 7243, 1869, 1877, 9896, 1548,
+     1864, 1863, 9896, 1639, 7276,    0, 1052, 9896, 7252, 7236,
+     7244, 7244, 7240, 7223, 7233, 7218, 7222, 7216, 1887, 1895,
+     9896, 1824, 1889, 1881, 9896, 1901, 7250,    0, 1861, 9896,
+     7214, 7222, 7221, 7219, 7201, 7207, 7210,   12, 7203,  474,
+
+     1905, 1909, 9896, 1915, 1910, 1915, 9896, 1923, 7217,    0,
+     1916, 9896, 7191, 7190, 7184,  536, 7186, 7173, 7172, 7162,
+      697, 1931, 1936, 9896, 1939, 1939, 1925, 9896, 1950, 7193,
+        0, 1924, 9896, 7160, 7161, 7154, 7161, 7161, 7160, 7143,
+     7137, 7133, 1954, 1960, 9896, 1963, 1963, 1964, 9896, 1968,
+     7160,    0, 1927, 9896, 7132,  490, 7132, 7125, 7123, 7115,
+     7112, 7115,  759, 7109, 1974, 1979, 9896, 1984, 1984, 9896,
+     7149, 7149, 1967, 7145, 7104, 1988,   18, 7079, 9896, 7127,
+     7116, 9896, 9896, 9896, 1986,  215, 7067, 7066, 7063, 7095,
+     7066, 9896,    0, 7057, 7063, 7059, 7043, 7042, 7050, 7060,
+
+     7041, 7026, 7031, 7032, 9896,    0, 7017, 7020, 2000, 7046,
+     9896,    0, 7019, 2007, 6994, 7031, 9896,    0, 7004, 6990,
+     2013, 7001, 6967, 6987, 6994, 9896,    0, 6961, 6977, 6958,
+     6967, 6971, 9896,    0, 6965, 2018, 6962, 6943, 2025, 2032,
+     2043, 2048, 6956, 6948, 9896,    0, 6935, 2056, 6919, 6924,
+     6932, 6914, 6940, 9896,    0, 2061, 2064, 2074, 2079, 6915,
+     6899, 6910, 6904, 6904,  274, 6902, 6900, 6912, 9896,    0,
+     6890, 6884, 2087, 2092, 2100, 2105, 6910, 9896,    0, 6876,
+     2113, 6885, 6878, 6875, 6866, 6854, 2118, 2121, 2131, 2136,
+     6881, 6864, 9896,    0, 6856, 2144, 2149, 6844, 2157, 6851,
+
+     6833, 2162, 2165, 2175, 2180, 2188, 2193, 6847, 9896,    0,
+     6811, 6807, 6812, 2201, 6816, 6815, 6799, 6791, 2206, 2209,
+     2212, 2220, 2227, 6820, 9896,    0, 6783, 6778, 6783, 2238,
+     6787, 6768, 6765, 6769, 6751,   80, 2241, 2244, 2252, 2259,
+     6774, 9896,    0, 6734, 6744, 2270, 6747, 6736, 6730, 6727,
+     6724, 6717, 2273, 6708, 6700, 2276, 2279, 2294, 2297, 6717,
+     6708, 9896,    0, 6692, 2305, 6695, 6672, 6680, 6676, 6671,
+     6659, 6659, 6651, 6639, 2308, 2312, 2326, 2329, 6662, 9896,
+        0, 6645, 6631, 6631, 6632, 2337, 6624, 6612, 6615, 6624,
+     2340, 2344, 2358, 2361, 6631, 9896,    0, 6618, 6616, 6605,
+
+      160, 2369, 6605, 6608, 6601, 6594, 6587, 6584, 6597, 2372,
+     2376, 2390, 2393, 6606, 6598, 6609, 6604, 6613,  721, 6566,
+     9896, 2390,    0, 6562, 6561, 6597, 6595, 6552, 9896, 6560,
+     6540, 6542, 6532, 6526, 6512, 6523, 2408, 2411, 6504, 6517,
+     6507, 6502, 6506, 6507, 2414, 2417, 2432, 2435, 6494, 2438,
+     2441, 2458, 2461, 2465, 6492, 6485, 2468, 2486, 6488, 6487,
+     6481, 2471, 2476, 6474, 6471, 6474, 6458, 2495, 2498, 6463,
+     2501, 2504, 6437, 6444, 2519, 9896, 9896, 2529, 9896, 9896,
+     6428, 2537, 2540, 6439, 2545, 2549,  485,  547, 6426, 6429,
+     2559, 2563, 2566, 9896, 9896, 2578, 9896, 9896, 6429, 6412,
+
+     6421, 6424, 6418, 6410, 6410, 6402, 6379, 2574, 2588, 6381,
+     6387, 2593, 9896, 9896, 2603, 9896, 9896, 2611, 2614, 6377,
+     2617, 2620, 6374, 6361, 6367, 6365, 6363, 2635, 9896, 9896,
+     2644, 9896, 9896, 2652, 2655, 6356, 2659, 9896, 9896, 6350,
+     2667, 2674, 6353, 6353, 2685, 9896, 9896, 2693, 9896, 9896,
+     2702, 9896, 9896, 2710, 2713, 6352, 6339, 6332, 2716, 2719,
+     6327, 6327, 6329, 6325, 2734, 2737, 2745, 9896, 9896, 2753,
+     9896, 9896, 2761, 2764, 6324, 6317, 6310, 2767, 2770, 6303,
+     6304, 6307, 6294, 6292, 2785, 2788, 2791, 9896, 9896, 2799,
+     9896, 9896, 2807, 2810, 6277, 6272, 2813, 2816, 6258, 6255,
+
+     6214, 6218, 6221, 6203, 2831, 2834, 6172, 6158, 2842, 9896,
+     9896, 2850, 9896, 9896, 2858, 2861, 6147, 2864, 2867, 6130,
+     6145, 6135, 6077, 6054, 6029, 6011, 6001, 5987, 2882, 9896,
+     9896, 2890, 9896, 9896, 2898, 2901, 5986, 5960, 5943, 5937,
+     2904, 2907, 5936, 5928, 5935, 5906, 2922, 9896, 9896, 2930,
+     9896, 9896, 2941, 2944, 5910, 5905, 5887, 5855, 5846, 2947,
+     2950, 5840, 5834, 5823, 5818, 2965, 5784, 5746, 2968, 9896,
+     9896, 2976, 9896, 9896, 2984, 2988, 5776, 9896, 5778, 9896,
+     9896,  343, 5744, 9896, 5750, 5745, 5684, 9896, 9896, 5680,
+     5684, 5676, 5652, 5653, 5650, 5616, 5612, 2991, 2994, 9896,
+
+     2997, 5594, 5549, 5525, 5533, 5499, 3003, 3017, 9896, 9896,
+     3025, 3028, 9896, 3031, 5461, 3034, 9896, 9896, 3050, 3053,
+     3061, 3064, 9896, 3068, 5462, 3072, 3076, 9896, 9896, 5405,
+     3090, 5394, 3094, 3097, 9896, 3100, 5359, 5337, 3103, 5341,
+     3108, 3121, 9896, 3127, 5296, 3130, 9896, 9896, 5284, 5295,
+     5281, 3140, 3146, 9896, 3153, 5249, 3159, 9896, 9896, 5244,
+     5217, 5218, 5186, 5166, 5139, 3167, 3172, 9896, 3175, 5107,
+     5095, 5086, 5025, 4973, 4985, 4925, 4934, 4907, 3178, 3181,
+     9896, 3187, 4890, 4876, 3200, 3206, 9896, 3209, 3212, 3215,
+     9896, 9896, 3230, 3234, 3240, 3243, 3252, 3261, 3264, 9896,
+
+     3270, 4863, 3276, 3294, 9896, 9896, 4802, 4772, 3284, 3303,
+     9896, 3306, 4674, 3310, 3313, 3316, 9896, 9896, 4653, 3331,
+     4625, 4619, 3334, 9896, 9896, 3342, 3349, 9896, 3352, 4612,
+      136, 3355, 3361, 9896, 9896, 4600,  399, 4599, 4562, 4540,
+     3373, 3376, 3384, 3387, 3395, 3398, 9896, 3402, 3405, 3410,
+     3417, 9896, 9896, 3429, 3432, 3435, 3438, 3441, 3459, 3462,
+     9896, 9896, 3470, 3477, 3473, 3480, 9896, 3483, 3502, 3505,
+     9896, 9896, 3520, 3523, 3527, 3531, 3534, 3541, 3545, 3552,
+     3559, 3555, 3563, 9896, 3585, 4523, 4506, 3566, 3588, 3606,
+     9896, 9896, 4485, 3592, 4412, 4388, 3596, 3615, 9896, 3618,
+
+     4372, 4331, 3621, 4307, 3624, 3628, 9896, 9896, 4191, 4197,
+     4155, 4143, 3642, 3645, 4145, 4118, 3653, 3656, 9896, 3660,
+     4128, 2004, 3663, 9896, 9896, 4078, 4070, 4038, 3666, 3675,
+     3684, 3687, 3693, 3998, 3696, 3952, 3931, 3705, 3926, 3934,
+     3711, 3716, 3724, 3730, 3733, 9896, 9896, 3748, 3751, 3754,
+     3757, 3775, 3778, 3781, 3789, 3796, 3880, 3800, 3803, 3808,
+     3864, 3821, 3846, 3835, 3835, 3782, 3824, 3730, 3720, 3720,
+     3655, 3598, 3827, 3526, 3830, 3466, 3441, 3419, 3405, 3398,
+     3340, 3283, 3237, 3833, 3845, 3151, 3850, 3854, 3857, 3876,
+     3868, 3887, 3890, 3893, 3896, 3914, 3917, 3920, 3923, 3940,
+
+     3946, 3949, 3143, 3952, 3964, 3960, 3972, 3110, 3982, 3985,
+     3117, 3069, 3996, 3033, 4000, 4003, 4007, 4011, 2961, 4021,
+     4025, 2941, 4028, 2914, 4032, 9896, 9896, 4047, 9896, 9896,
+     4055, 4058, 4061, 4069, 4076, 2883, 4087, 4090, 2869, 2878,
+     2824, 2782, 4098, 2777, 4101, 4105, 4109, 2726, 2653, 2651,
+     2583, 2585, 2533, 2407, 4123, 2349, 4126, 4129, 4132, 4135,
+     4153, 4161, 4165, 4174, 4179, 4182, 4192, 4197, 4200, 2329,
+     2268, 4203, 4206, 2258, 4215, 4224, 2133, 2131, 2089, 2005,
+     4233, 9896, 9896, 1908, 4242, 4245, 1925,   51, 1816, 4249,
+     9896, 1759, 9896, 9896, 3860, 4252, 4264,   65, 4260,   71,
+
+       92,  149, 4272,  132, 4278, 4281,  177,  194, 4284, 9896,
+     9896, 4292, 4295, 4298, 4316, 4319, 4322, 4337, 9896, 9896,
+     4345, 4348, 9896, 9896, 4357, 4363, 4366, 4369, 4375, 4387,
+     9896, 9896, 4395, 4398,  212,  244,  252,  257, 4401, 4405,
+     4409, 4413, 4423, 4427, 4431, 4435, 4445, 4449,  280,  305,
+      341, 4455,  320,  336,  355,  360, 4458, 4461,  360, 4464,
+     4471, 4485, 4488, 9896, 9896, 4496, 4504,  447,  461,  480,
+      519, 4499, 4518, 4521, 4529, 9896, 9896,  523,  551, 4538,
+     4543, 4546, 9896, 9896, 4557, 9896, 9896, 4565, 4568, 9896,
+     9896, 4578, 4583, 4586,  679, 4589, 4592, 4607, 4610, 4619,
+
+     9896, 9896,  544, 4627, 4633, 4641, 4645,  552, 4653, 4659,
+      636, 4667, 4671, 9896, 9896, 4679, 9896, 9896,  656, 4687,
+     9896, 9896, 4695,  701,  728,  747, 4699, 4702,  758, 4717,
+     4720, 9896, 9896,  759,  784,  814,  822,  816,  833,  824,
+     4728, 4732,  854, 4740, 4746, 4749,  867, 4764, 9896, 9896,
+     4773, 9896, 9896, 4781, 4784, 9896, 9896,  889, 4792, 4795,
+     4803,  883,  906, 4806, 9896, 9896, 4814, 4818, 9896, 9896,
+      935,  941,  941,  944,  954, 4826, 4832, 4840,  967, 1797,
+     1986, 9896, 4601, 4844, 9896, 9896,  982, 4852, 4855, 1008,
+     4863, 1006, 4866, 4870, 4873, 4876, 1011, 4881, 4886, 9896,
+
+     9896, 4894, 4900, 9896, 9896, 4908, 4913, 1010, 4921, 9896,
+     4926, 4929, 4940, 9896, 9896, 4948, 4951, 1010, 1010, 4954,
+     4957, 4961, 4966, 4973, 1023, 1238, 1240, 1241, 4984, 9896,
+     9896, 4992, 4995, 4998, 5001, 1317, 5004, 1315, 1339, 1329,
+     5007, 5010, 1313, 5015, 9896, 9896, 5023, 5029, 9896, 9896,
+     5037, 5042, 5045, 5048, 5055, 5067, 9896, 9896, 5075, 5079,
+     5082, 5086, 5097, 5089, 5093, 5107, 5111, 5114, 5117, 5121,
+     9896, 9896, 5135, 9896, 9896, 5143, 5147, 9896, 9896, 5165,
+     9896, 9896, 5156, 5174, 9896, 9896, 5182, 5185, 5188, 5191,
+     5194, 5209, 5214, 5217, 5220, 9896, 9896, 5228, 5235, 5240,
+
+     5246, 5250, 5254, 5258, 5277, 5280, 5284, 9896, 9896, 5299,
+     5303, 5307, 9896, 9896, 5317, 5322, 5325, 5340, 5343, 5346,
+     9896, 9896, 5354, 9896, 1365, 5361, 5364, 5367, 5375, 1408,
+     1405, 1408, 5382, 5387, 9896, 9896, 5395, 1445, 1533, 1817,
+     5400, 5403, 9896, 9896, 5414, 5418, 5421, 1422, 5432, 9896,
+     5436, 5439, 1416, 5443, 5446, 9896, 5455, 9896, 9896, 1426,
+     5465, 9896, 9896, 5473, 5476, 5484, 5487, 1501, 5491, 5494,
+     5505, 5509, 5512, 9896, 9896, 1497, 5520, 1499, 5523, 5528,
+     5531, 5541, 1498, 1503, 1593, 1595, 5547, 5550, 9896, 5553,
+     5556, 5559, 5562, 5571, 5577, 5585, 5589, 5592, 5603, 9896,
+
+     5607, 5610, 5618, 5625, 5636, 5639, 9896, 9896, 5647, 5651,
+     5659, 5665, 5668, 5671, 5683, 5677, 5691, 5700, 5703, 5711,
+     5718, 5721, 5724, 5729, 5742, 9896, 9896, 5750, 5753, 5757,
+     5762, 5776, 5784, 5787, 5790, 5810, 5813, 5816, 5819, 5822,
+     5840, 5843, 5846, 5854, 5861, 5864, 5873, 9896, 9896, 5884,
+     5888, 5891, 5902, 5907, 5910, 5913, 5928, 9896, 9896, 5936,
+     5939, 1590, 1590, 5947, 5950, 5954, 5968, 1611, 5971, 1975,
+     5974, 5977, 5992, 5995, 9896, 9896, 1598, 1596, 6003, 9896,
+     6006, 6010, 9896, 9896, 6018, 6025, 6028, 1683, 6037, 9896,
+     9896, 6045, 9896, 6048, 6051, 6054, 6069, 6072, 6075, 6083,
+
+     9896, 6090, 6093, 1697, 1705, 6096, 6102, 6110, 9896, 6114,
+     9896, 9896, 6122, 9896, 9896, 6130, 6133, 9896, 9896, 6141,
+     9896, 9896, 6149, 9896, 9896, 6157, 6160, 9896, 9896, 6168,
+     6171, 6176, 9896, 6179, 9896, 9896, 6189, 9896, 9896, 6197,
+     9896, 9896, 6207, 6210, 6213, 6221, 9896, 9896, 6216, 6234,
+     6237, 6240, 9896, 9896, 6248, 9896, 6256, 9896, 9896, 6275,
+     6278, 6286, 6289, 6299, 6304, 6312, 6317, 6320, 6330, 6335,
+     9896, 9896, 6343, 6348, 9896, 9896, 6356, 6365, 9896, 9896,
+     6376, 6379, 6387, 6394, 6405, 9896, 9896, 6413, 9896, 9896,
+     6421, 1698, 6424, 6427, 6435, 9896, 9896, 6443, 9896, 6501,
+
+     1733, 6446, 9896, 9896, 6454, 6458, 6466, 6472, 6475, 6478,
+     6486, 6505, 9896, 9896, 6493, 6496, 6539, 6547, 9896, 9896,
+     6514, 6555, 6563, 9896, 9896, 6571, 6574, 1711, 6577, 6580,
+     9896, 9896, 6588, 6591, 6594, 6597, 6600, 6606, 6618, 6624,
+     6628, 6651, 6631, 6660, 9896, 9896, 6668, 9896, 9896, 6676,
+     9896, 9896, 6684, 6689, 9896, 9896, 6697, 6702, 6705, 6708,
+     9896, 9896, 6717, 9896, 9896, 6725, 6728, 1708, 6736, 9896,
+     9896, 6744, 1803, 1993, 1875, 1804, 2051, 2035, 1960, 2028,
+     1974, 2246, 2010, 2052, 2064, 2090, 6751, 9896, 9896, 6759,
+     6763, 6766, 6774, 9896, 9896, 6782, 6785, 6788, 6797, 9896,
+
+     9896, 6805, 9896, 9896, 1719, 6813, 6816, 6819, 6822, 6825,
+     6828, 6834, 6848, 9896, 6852, 6855, 9896, 9896, 6863, 6870,
+     6873, 6876, 6881, 6884, 9896, 9896, 6895, 6899, 9896, 1857,
+     2059, 2067, 2054, 2109, 2153, 2108, 2116, 2092, 2129, 2173,
+     2155, 2123, 2023, 2181, 2199, 2214, 6902, 9896, 9896, 6913,
+     9896, 6919, 9896, 9896, 1710, 6927, 6932, 6940, 9896, 6945,
+     6948, 6959, 6963, 6971, 6977, 6985, 6989, 6992, 6996, 7010,
+     7013, 7021, 7024, 7032, 7035, 7043, 7046, 7050, 7058, 7064,
+     2238, 1987, 2121, 2250, 2231, 2168, 2244, 2212, 2215, 2270,
+     2274, 2299, 2282, 2331, 2285, 2305, 7072, 7076, 7080, 9896,
+
+     9896, 7091, 9896, 9896, 7099, 9896, 9896, 7107, 9896, 9896,
+     7115, 7118, 7126, 7129, 7137, 9896, 9896, 7145, 9896, 9896,
+     7153, 9896, 9896, 7161, 9896, 9896, 7169, 7172, 9896, 9896,
+     7181, 9896, 9896, 2300, 2316, 2332, 2348, 2349, 7189, 2346,
+     2361, 2364, 2402, 2405, 2407, 2409, 7192, 2431, 2335, 7195,
+     7198, 7217, 7221, 9896, 9896, 7229, 9896, 9896, 7237, 2180,
+     2438, 2429, 2463, 7240, 7243, 7246, 7249, 2491, 2496, 2534,
+     2474, 2499, 7252, 7271, 2497, 7277, 7300, 7340, 7290, 9896,
+     7311, 7330, 7333, 2412, 7352, 2573, 7361, 7364, 7371, 2516,
+     2489, 2551, 7374, 2590, 7386, 2580, 7398, 7421, 7461, 7411,
+
+     7451, 7454, 2367, 2605, 2494, 2622, 2644, 7473, 2514, 2581,
+     2615, 7492, 2568, 2654, 2664, 7495, 2631, 2665, 2689, 2704,
+     7432, 2709, 2714, 2725, 2763, 2758, 7500, 2712, 2492, 2801,
+     2806, 2837, 2821, 2809, 2854, 2860, 2862, 7503, 2878, 2653,
+     2899, 2902, 2895, 7514, 2755, 7522, 2920, 2829, 2921, 7533,
+     2938, 2940, 2945, 2982, 3057, 2983, 2218, 2990, 3021, 3024,
+     3088, 2681, 7537, 3053, 2859, 3095, 7541, 3099, 3120, 3125,
+     3132, 3026, 2993, 7544, 3096, 3166, 3168, 3205, 2955, 3185,
+     3173, 7548, 3230, 3210, 3202, 3238, 3308, 3310, 3118, 7563,
+     7571, 7567, 7582, 3311, 3215, 7586, 3250, 3340, 7590, 7601,
+
+     3256, 3353, 7605, 7609, 7612, 3257, 7624, 2673, 2765, 7632,
+     7644, 7620, 3301, 7652, 3374, 7655, 3029, 3397, 7659, 3410,
+     7674, 7679, 7687, 7699, 3396, 3432, 3482, 2732, 2867, 3493,
+     3583, 3594, 3613, 7707, 3436, 3328, 3433, 7719, 3117, 3207,
+     3616, 3652, 3472, 7727, 3673, 3682, 3709, 3751, 3755, 3819,
+     7738, 3375, 3408, 2757, 3450, 3532, 3655, 3691, 3745, 3823,
+     3825, 7741, 3348, 3481, 3846, 3855, 3553, 3557, 3801, 3881,
+     3497, 3887, 3888, 3890, 3908, 3910, 3962, 3998, 4019, 7746,
+     3564, 3633, 2909, 3005, 3672, 3697, 3725, 3766, 4026, 4034,
+     7761, 3752, 7769, 4066, 4090, 3030, 3521, 3818, 3972, 7772,
+
+     4094, 4099, 4017, 4025, 4032, 4048, 4103, 4121, 3937, 4100,
+     4170, 4204, 1872, 2629, 4238, 4252, 4258, 4309, 4123, 4130,
+     4102, 4257, 3490, 7776, 4172, 4211, 2670, 3281, 4310, 4333,
+     7784, 4283, 4286, 4367, 4425, 4451, 4459, 4464, 4465, 4324,
+     4360, 4022, 4218, 3776, 3894, 4221, 4523, 4545, 4553, 4473,
+     4475, 4372, 4533, 3619, 4269, 4336, 4476, 4580, 3952, 4169,
+     4604, 4607, 4456, 4621, 4597, 4614, 4675, 4689, 4696, 4734,
+     4752, 4758, 4288, 4293, 4314, 4375, 3240, 3703, 4531, 4534,
+     4632, 4695, 4760, 4820, 4296, 4462, 7795, 4644, 4690, 4888,
+     4928, 4633, 4705, 4713, 4769, 4741, 4782, 4963, 5009, 4805,
+
+     4843, 4861, 4874, 4893, 4972, 4693, 4739, 4969, 5048, 5016,
+     5022, 5102, 5114, 5120, 5122, 5043, 5128, 4799, 4873, 7799,
+     4707, 4754, 5162, 5207, 5220, 5226, 5143, 5145, 4942, 5108,
+     5254, 5288, 5150, 5255, 5274, 5333, 5341, 5352, 5042, 5054,
+     5331, 5388, 3341, 4817, 5409, 5440, 5461, 5497, 5367, 5411,
+     5214, 5445, 4842, 4914, 4887, 5002, 5442, 5479, 4141, 5123,
+     5580, 5615, 5225, 5247, 5508, 5526, 5632, 5638, 5657, 5696,
+     5714, 5727, 5729, 5730, 5265, 5295, 7807, 5408, 5463, 5597,
+     5527, 5757, 5763, 5764, 5783, 5310, 5549, 5688, 5817, 5790,
+     5810, 7810, 5612, 5616, 5820, 5840, 5852, 5864, 5627, 5915,
+
+     5833, 5924, 5863, 5927, 5709, 5777, 7814, 7818, 9896, 7821,
+     7829, 5962, 5980, 5861, 5903, 5361, 5453, 5941, 5998, 5997,
+     6015, 7833, 9896, 7840, 6025, 6039, 6060, 6081, 7843, 7848,
+     7852, 6102, 6121, 7855, 9896, 7862, 9896, 7867, 9896, 7874,
+     6177, 6184, 5562, 5577, 5908, 6048, 7877, 7881, 9896, 6062,
+     6089, 7886, 7889, 9896, 7896, 9896, 7900, 9896, 6134, 6118,
+     7908, 9896, 6225, 6147, 5907, 6099, 6227, 6228, 7911, 9896,
+     6255, 6265, 7915, 9896, 7919, 7922, 6284, 6291, 6249, 6148,
+     6277, 6185, 7930, 9896, 7934, 9896, 6237, 6266, 7941, 7944,
+     6320, 6328, 7949, 9896, 7953, 9896, 6336, 6254, 7956, 7963,
+
+     9896, 9896, 7983, 7992, 8001, 8010, 8019, 8028, 8037, 8046,
+     8055, 8064, 8073, 8082, 8091, 8100, 8109, 8118, 8127, 8136,
+     8145, 8154, 8163, 8172, 8181, 8190, 8199, 8208, 8217, 8226,
+     8235, 8244, 8253, 8262, 8271, 8278, 8285, 8292, 8299, 8306,
+     8313, 8320, 8327, 8334, 8341, 8348, 8355, 8362, 8369, 8376,
+     8383, 8390, 8399, 8404, 8409, 8414, 8419, 8424, 8429, 8434,
+     8439, 8444, 8449, 8454, 8459, 8464, 8471, 8476, 8483, 8488,
+     8495, 8500, 8507, 8512, 8521, 8527, 8534, 8542, 8549, 8557,
+     8564, 8572, 8579, 8587, 8594, 8602, 8609, 8617, 8624, 8632,
+     8640, 8647, 8655, 8662, 8670, 8677, 8685, 8692, 8700, 8707,
+
+     8715, 8722, 8730, 8737, 8745, 8752, 8760, 8767, 8775, 8784,
+     8790, 8797, 8805, 8812, 8820, 8827, 8835, 8842, 8850, 8857,
+     8865, 8872, 8880, 8887, 8895, 8903, 8910, 8918, 8926, 8934,
+     8941, 8949, 8956, 8964, 8971, 8979, 8987, 8995, 9003, 9011,
+     9018, 9026, 9033, 9041, 9050, 9059, 9067, 9075, 9082, 9090,
+     9098, 9106, 9114, 9122, 9129, 9137, 9144, 9152, 9159, 9167,
+     9175, 9182, 9190, 9198, 9206, 9214, 9222, 9229, 9237, 9244,
+     9252, 9259, 9267, 9274, 9282, 9290, 9298, 9305, 9313, 9322,
+     9331, 9338, 9346, 9353, 9361, 9369, 9377, 9385, 9393, 9401,
+     9408, 9416, 9424, 9432, 9440, 9447, 9455, 9462, 9470, 9477,
+
+     9485, 9493, 9501, 9508, 9516, 9523, 9531, 9538, 9546, 9553,
+     9561, 9568, 9576, 9585, 9594, 9601, 9609, 9616, 9624, 9632,
+     9639, 9647, 9655, 9662, 9670, 9677, 9685, 9693, 9700, 9708,
+     9716, 9724, 9732, 9740, 9748, 9756, 9764, 9772, 9780, 9788,
+     9796, 9804, 9812, 9819, 9827, 9836, 9845, 9853, 9860, 9868,
+     9877, 9886
+    } ;
+
+static yyconst short int yy_def[3053] =
+    {   0,
+     2803, 2803, 2804, 2804, 2804, 2804, 2805, 2805, 2806, 2806,
+     2807, 2807, 2808, 2808, 2808, 2808, 2809, 2809, 2810, 2810,
+     2811, 2811, 2810, 2810, 2812, 2812, 2810, 2810, 2812, 2812,
+     2812, 2812, 2810, 2810, 2813, 2813, 2814, 2814, 2810, 2810,
+     2815, 2815, 2816, 2816, 2810, 2810, 2802,   47, 2817, 2817,
+     2810, 2810, 2818, 2818, 2819, 2819, 2810, 2810, 2802,   59,
+     2810, 2810, 2810, 2810, 2820, 2820, 2820, 2820, 2810, 2810,
+     2821, 2821, 2810, 2810, 2822, 2822, 2810, 2810, 2823, 2823,
+     2810, 2810, 2810, 2810, 2824, 2824, 2824, 2824, 2810, 2810,
+     2825, 2825, 2826, 2826, 2810, 2810, 2802,   97, 2827, 2827,
+
+     2810, 2810, 2802,  103, 2828, 2828, 2810, 2810, 2802,  109,
+     2829, 2829, 2810, 2810, 2802,  115, 2830, 2830, 2810, 2810,
+     2802,  121, 2831, 2831, 2810, 2810, 2802,  127, 2832, 2832,
+     2810, 2810, 2802,  133, 2833, 2833, 2810, 2810, 2802,  139,
+     2810, 2810, 2834, 2834, 2835, 2835, 2802, 2802, 2802, 2802,
+     2802, 2802, 2802, 2802, 2802, 2802, 2802, 2802, 2802, 2802,
+     2802, 2802, 2802, 2802, 2802, 2802, 2802, 2802, 2802, 2802,
+     2802, 2802, 2802, 2802, 2802, 2802, 2802, 2802, 2836, 2802,
+     2802, 2836, 2836, 2836, 2836, 2802, 2802, 2802, 2802, 2802,
+     2802, 2802, 2802, 2802, 2802, 2837, 2802, 2802, 2837, 2837,
+
+     2837, 2802, 2802, 2802, 2802, 2802, 2802, 2802, 2838, 2802,
+     2802, 2838, 2838, 2838, 2802, 2802, 2802, 2802, 2802, 2802,
+     2802, 2839, 2802, 2802, 2839, 2839, 2839, 2839, 2839, 2802,
+     2802, 2802, 2802, 2802, 2802, 2840, 2802, 2802, 2840, 2840,
+     2840, 2840, 2802, 2802, 2802, 2802, 2802, 2802, 2802, 2841,
+     2802, 2802, 2841, 2841, 2841, 2841, 2841, 2841, 2802, 2802,
+     2802, 2802, 2802, 2802, 2802, 2802, 2842, 2802, 2802, 2842,
+     2842, 2842, 2842, 2802, 2802, 2802, 2802, 2802, 2802, 2802,
+     2843, 2802, 2802, 2843, 2843, 2802, 2802, 2802,  286, 2802,
+     2802, 2802, 2802, 2802, 2844, 2802, 2802, 2844, 2844, 2844,
+
+     2844, 2802, 2802, 2802, 2802, 2802, 2802, 2802, 2845, 2802,
+     2802, 2845, 2845, 2845, 2845, 2845, 2845, 2845, 2845, 2802,
+     2802, 2802, 2802, 2802, 2802, 2802, 2846, 2802, 2802, 2846,
+     2846, 2846, 2846, 2846, 2846, 2846, 2846, 2802, 2802, 2802,
+     2802, 2802, 2802, 2802, 2847, 2802, 2802, 2847, 2847, 2847,
+     2847, 2847, 2847, 2847, 2847, 2847, 2847, 2847, 2802, 2802,
+     2802, 2802, 2802, 2802, 2802, 2848, 2802, 2802, 2848, 2848,
+     2848, 2848, 2848, 2848, 2848, 2848, 2848, 2848, 2848, 2848,
+     2802, 2802, 2802, 2802, 2802, 2802, 2802, 2849, 2802, 2802,
+     2849, 2849, 2849, 2849, 2849, 2849, 2849, 2849, 2849, 2849,
+
+     2849, 2849, 2802, 2802, 2802, 2802, 2802, 2802, 2802, 2850,
+     2802, 2802, 2850, 2850, 2850, 2850, 2850, 2850, 2850, 2850,
+     2850, 2850, 2850, 2802, 2802, 2802, 2802, 2802, 2802, 2802,
+     2851, 2802, 2802, 2851, 2851, 2851, 2851, 2851, 2851, 2851,
+     2851, 2851, 2851, 2851, 2802, 2802, 2802, 2802, 2802, 2802,
+     2802, 2852, 2802, 2802, 2852, 2852, 2852, 2852, 2852, 2852,
+     2852, 2852, 2852, 2852, 2852, 2852, 2802, 2802, 2802, 2802,
+     2802, 2802, 2802, 2802, 2802, 2802, 2853, 2802, 2802, 2802,
+     2802, 2802, 2802, 2802, 2802, 2802, 2802, 2802, 2802, 2802,
+     2802, 2802, 2836, 2836, 2836, 2836, 2836, 2836, 2802, 2854,
+
+     2802, 2802, 2802, 2802, 2802, 2837, 2837, 2837, 2837, 2855,
+     2802, 2838, 2838, 2838, 2838, 2856, 2802, 2839, 2839, 2839,
+     2839, 2839, 2839, 2839, 2857, 2802, 2840, 2840, 2840, 2840,
+     2840, 2858, 2802, 2841, 2841, 2841, 2841, 2841, 2802, 2802,
+     2802, 2802, 2802, 2859, 2802, 2842, 2842, 2842, 2842, 2842,
+     2842, 2802, 2860, 2802, 2843, 2802, 2802, 2802, 2802, 2802,
+     2802, 2802, 2802, 2802, 2802, 2802, 2802, 2861, 2802, 2844,
+     2844, 2844, 2802, 2802, 2802, 2802, 2862, 2802, 2845, 2845,
+     2845, 2845, 2845, 2845, 2845, 2845, 2802, 2802, 2802, 2802,
+     2863, 2802, 2802, 2846, 2846, 2802, 2802, 2846, 2846, 2846,
+
+     2846, 2802, 2802, 2802, 2802, 2802, 2802, 2864, 2802, 2847,
+     2847, 2847, 2847, 2847, 2847, 2847, 2847, 2847, 2847, 2802,
+     2802, 2802, 2802, 2865, 2802, 2848, 2848, 2848, 2848, 2848,
+     2848, 2848, 2848, 2848, 2848, 2848, 2802, 2802, 2802, 2802,
+     2866, 2802, 2867, 2867, 2867, 2867, 2867, 2867, 2867, 2867,
+     2867, 2867, 2867, 2867, 2867, 2802, 2802, 2802, 2802, 2868,
+     2802, 2802, 2869, 2869, 2869, 2869, 2869, 2869, 2869, 2869,
+     2869, 2869, 2869, 2869, 2802, 2802, 2802, 2802, 2870, 2802,
+     2871, 2871, 2871, 2871, 2871, 2871, 2871, 2871, 2871, 2871,
+     2802, 2802, 2802, 2802, 2872, 2802, 2873, 2873, 2873, 2873,
+
+     2873, 2873, 2873, 2873, 2873, 2873, 2873, 2873, 2873, 2802,
+     2802, 2802, 2802, 2874, 2802, 2802, 2875, 2802, 2875, 2802,
+     2802, 2802, 2876, 2802, 2802, 2802, 2802, 2802, 2802, 2802,
+     2877, 2877, 2877, 2877, 2877, 2802, 2878, 2878, 2802, 2802,
+     2802, 2802, 2879, 2879, 2802, 2802, 2880, 2880, 2881, 2802,
+     2802, 2881, 2882, 2882, 2883, 2883, 2802, 2802, 2883, 2883,
+     2883, 2884, 2884, 2885, 2885, 2885, 2885, 2886, 2886, 2887,
+     2802, 2802, 2887, 2887, 2802, 2802, 2802, 2802, 2802, 2802,
+     2802, 2888, 2888, 2889, 2802, 2802, 2889, 2889, 2889, 2802,
+     2890, 2890, 2802, 2802, 2802, 2802, 2802, 2802, 2802, 2802,
+
+     2802, 2802, 2802, 2802, 2802, 2802, 2802, 2891, 2891, 2892,
+     2892, 2802, 2802, 2802, 2802, 2802, 2802, 2893, 2893, 2894,
+     2802, 2802, 2894, 2894, 2894, 2894, 2894, 2802, 2802, 2802,
+     2802, 2802, 2802, 2895, 2895, 2896, 2802, 2802, 2802, 2896,
+     2802, 2802, 2896, 2896, 2802, 2802, 2802, 2802, 2802, 2802,
+     2802, 2802, 2802, 2897, 2897, 2898, 2898, 2898, 2802, 2802,
+     2898, 2898, 2898, 2898, 2802, 2802, 2802, 2802, 2802, 2802,
+     2802, 2802, 2899, 2899, 2900, 2900, 2900, 2802, 2802, 2900,
+     2900, 2900, 2900, 2900, 2900, 2900, 2802, 2802, 2802, 2802,
+     2802, 2802, 2901, 2901, 2902, 2902, 2802, 2802, 2902, 2902,
+
+     2902, 2902, 2902, 2902, 2802, 2802, 2902, 2902, 2802, 2802,
+     2802, 2802, 2802, 2802, 2903, 2903, 2904, 2802, 2802, 2904,
+     2904, 2904, 2904, 2904, 2904, 2904, 2904, 2904, 2802, 2802,
+     2802, 2802, 2802, 2802, 2905, 2905, 2906, 2906, 2906, 2906,
+     2802, 2802, 2906, 2906, 2906, 2906, 2802, 2802, 2802, 2802,
+     2802, 2802, 2907, 2907, 2908, 2908, 2908, 2908, 2908, 2802,
+     2802, 2908, 2908, 2908, 2908, 2908, 2908, 2908, 2802, 2802,
+     2802, 2802, 2802, 2802, 2909, 2909, 2802, 2802, 2910, 2802,
+     2802, 2910, 2802, 2802, 2911, 2802, 2802, 2802, 2802, 2802,
+     2802, 2912, 2912, 2912, 2912, 2912, 2802, 2802, 2913, 2802,
+
+     2913, 2802, 2802, 2802, 2802, 2914, 2914, 2802, 2802, 2802,
+     2802, 2915, 2802, 2915, 2916, 2802, 2802, 2802, 2802, 2802,
+     2802, 2917, 2802, 2917, 2918, 2918, 2802, 2802, 2802, 2918,
+     2918, 2918, 2802, 2919, 2802, 2919, 2920, 2920, 2920, 2920,
+     2802, 2921, 2802, 2921, 2922, 2802, 2802, 2802, 2922, 2922,
+     2802, 2802, 2923, 2802, 2923, 2924, 2802, 2802, 2802, 2924,
+     2924, 2924, 2924, 2924, 2802, 2802, 2925, 2802, 2925, 2802,
+     2802, 2802, 2802, 2802, 2802, 2802, 2802, 2802, 2802, 2926,
+     2802, 2926, 2927, 2927, 2802, 2928, 2802, 2928, 2929, 2802,
+     2802, 2802, 2929, 2929, 2929, 2929, 2929, 2802, 2930, 2802,
+
+     2930, 2931, 2931, 2802, 2802, 2802, 2931, 2931, 2802, 2932,
+     2802, 2932, 2933, 2933, 2933, 2802, 2802, 2802, 2933, 2933,
+     2933, 2933, 2802, 2802, 2802, 2802, 2934, 2802, 2934, 2935,
+     2935, 2935, 2802, 2802, 2802, 2935, 2935, 2935, 2935, 2935,
+     2802, 2802, 2802, 2802, 2802, 2936, 2802, 2936, 2937, 2937,
+     2802, 2802, 2802, 2937, 2937, 2937, 2937, 2937, 2937, 2802,
+     2802, 2802, 2937, 2937, 2802, 2938, 2802, 2938, 2939, 2802,
+     2802, 2802, 2939, 2939, 2939, 2939, 2939, 2939, 2939, 2939,
+     2939, 2802, 2940, 2802, 2940, 2941, 2941, 2941, 2941, 2802,
+     2802, 2802, 2941, 2941, 2941, 2941, 2802, 2942, 2802, 2942,
+
+     2943, 2943, 2943, 2943, 2943, 2802, 2802, 2802, 2943, 2943,
+     2943, 2943, 2802, 2802, 2943, 2943, 2802, 2944, 2802, 2944,
+     2802, 2945, 2946, 2802, 2802, 2802, 2802, 2802, 2947, 2947,
+     2947, 2947, 2947, 2802, 2948, 2802, 2802, 2802, 2802, 2949,
+     2802, 2802, 2950, 2951, 2802, 2802, 2802, 2952, 2953, 2802,
+     2802, 2953, 2802, 2802, 2953, 2954, 2955, 2955, 2802, 2802,
+     2955, 2956, 2957, 2957, 2957, 2802, 2958, 2959, 2959, 2959,
+     2959, 2959, 2959, 2802, 2960, 2802, 2802, 2802, 2802, 2802,
+     2802, 2802, 2802, 2802, 2961, 2962, 2962, 2963, 2802, 2802,
+     2964, 2964, 2964, 2964, 2964, 2965, 2966, 2802, 2802, 2966,
+
+     2966, 2967, 2968, 2802, 2802, 2802, 2802, 2968, 2802, 2802,
+     2968, 2968, 2969, 2970, 2970, 2970, 2802, 2802, 2970, 2970,
+     2970, 2970, 2970, 2970, 2802, 2802, 2802, 2802, 2802, 2802,
+     2971, 2802, 2802, 2802, 2802, 2972, 2802, 2802, 2972, 2972,
+     2972, 2972, 2972, 2972, 2973, 2802, 2802, 2974, 2974, 2974,
+     2974, 2974, 2974, 2974, 2974, 2974, 2975, 2976, 2976, 2802,
+     2802, 2802, 2802, 2976, 2802, 2802, 2976, 2976, 2977, 2978,
+     2978, 2802, 2802, 2978, 2802, 2802, 2978, 2978, 2978, 2978,
+     2802, 2802, 2802, 2978, 2978, 2979, 2802, 2980, 2981, 2981,
+     2802, 2981, 2802, 2802, 2802, 2802, 2802, 2982, 2982, 2982,
+
+     2982, 2802, 2983, 2802, 2802, 2802, 2802, 2984, 2802, 2802,
+     2802, 2985, 2802, 2802, 2986, 2802, 2802, 2802, 2802, 2802,
+     2987, 2802, 2802, 2802, 2987, 2988, 2989, 2802, 2802, 2802,
+     2802, 2802, 2989, 2990, 2991, 2991, 2991, 2802, 2992, 2993,
+     2993, 2993, 2993, 2993, 2802, 2802, 2802, 2994, 2802, 2802,
+     2802, 2802, 2802, 2802, 2802, 2802, 2802, 2995, 2996, 2802,
+     2802, 2997, 2802, 2802, 2802, 2802, 2802, 2998, 2998, 2998,
+     2998, 2999, 2802, 2802, 2802, 2802, 2802, 3000, 3000, 3001,
+     3002, 2802, 2802, 2802, 2802, 2802, 2802, 3002, 2802, 2802,
+     2802, 3002, 3002, 3003, 3004, 2802, 2802, 2802, 2802, 2802,
+
+     2802, 2802, 3004, 2802, 2802, 2802, 2802, 3004, 2802, 2802,
+     3004, 3005, 2802, 2802, 2802, 2802, 2802, 2802, 3006, 2802,
+     2802, 2802, 3006, 3006, 3006, 3006, 2802, 2802, 3006, 3007,
+     2802, 2802, 2802, 3008, 3008, 3008, 3008, 3008, 3008, 3008,
+     2802, 2802, 3008, 3009, 2802, 2802, 3010, 2802, 2802, 2802,
+     2802, 2802, 2802, 3010, 2802, 2802, 2802, 3010, 2802, 2802,
+     3011, 3012, 3012, 2802, 2802, 2802, 3012, 2802, 2802, 2802,
+     3012, 3012, 3012, 3012, 3012, 2802, 2802, 3013, 2802, 3014,
+     3015, 2802, 2802, 2802, 2802, 2802, 3016, 2802, 2802, 3016,
+     3016, 2802, 3017, 2802, 2802, 2802, 3018, 3019, 2802, 2802,
+
+     2802, 3020, 2802, 2802, 2802, 2802, 2802, 3021, 2802, 2802,
+     2802, 2802, 2802, 2802, 2802, 3022, 3023, 3024, 3024, 3024,
+     2802, 3025, 2802, 2802, 3026, 3026, 3026, 3026, 2802, 2802,
+     2802, 2802, 3027, 2802, 2802, 2802, 2802, 2802, 2802, 2802,
+     2802, 3028, 3029, 2802, 2802, 2802, 3030, 2802, 2802, 2802,
+     3031, 3031, 3031, 3031, 3032, 2802, 2802, 2802, 3033, 3033,
+     3034, 2802, 2802, 3035, 3035, 3035, 3036, 3037, 3037, 2802,
+     2802, 2802, 2802, 2802, 2802, 3037, 2802, 2802, 2802, 2802,
+     2802, 2802, 3037, 2802, 2802, 2802, 3037, 3038, 3039, 2802,
+     2802, 3039, 3039, 3039, 2802, 2802, 2802, 3039, 3040, 3041,
+
+     3041, 3041, 3041, 3041, 3041, 3041, 2802, 2802, 2802, 3041,
+     3042, 2802, 2802, 2802, 3043, 2802, 2802, 3043, 3043, 2802,
+     2802, 2802, 2802, 2802, 3044, 3044, 2802, 2802, 3044, 3044,
+     3044, 3044, 3044, 2802, 2802, 2802, 3045, 2802, 3046, 3047,
+     3048, 2802, 2802, 2802, 3048, 2802, 2802, 2802, 2802, 2802,
+     2802, 2802, 3049, 3050, 2802, 2802, 2802, 2802, 2802, 3021,
+     2802, 2802, 2802, 2802, 2802, 3023, 3024, 3024, 2802, 2802,
+     2802, 3025, 2802, 2802, 2802, 3026, 3026, 3026, 3026, 3027,
+     2802, 2802, 2802, 2802, 2802, 2802, 2802, 2802, 2802, 3029,
+     3030, 2802, 2802, 2802, 2802, 3031, 2802, 2802, 2802, 2802,
+
+     2802, 2802, 2802, 2802, 3034, 2802, 2802, 2802, 2802, 2802,
+     3035, 3035, 3036, 2802, 2802, 2802, 2802, 2802, 2802, 3037,
+     3037, 3038, 2802, 2802, 2802, 2802, 2802, 3039, 3039, 3039,
+     2802, 2802, 3040, 2802, 2802, 3041, 3041, 3041, 3041, 3041,
+     3041, 2802, 2802, 3042, 2802, 2802, 2802, 2802, 2802, 3043,
+     2802, 2802, 3044, 3044, 2802, 2802, 2802, 2802, 2802, 2802,
+     2802, 3044, 3044, 3044, 2802, 2802, 3045, 2802, 3046, 3047,
+     2802, 2802, 3048, 2802, 2802, 2802, 2802, 3049, 2802, 2802,
+     3021, 2802, 2802, 2802, 3023, 2802, 2802, 3024, 2802, 2802,
+     2802, 2802, 2802, 3026, 2802, 2802, 3026, 2802, 2802, 2802,
+
+     2802, 2802, 2802, 2802, 2802, 2802, 2802, 2802, 2802, 2802,
+     2802, 2802, 2802, 2802, 2802, 3031, 2802, 2802, 2802, 2802,
+     2802, 2802, 2802, 2802, 2802, 3034, 2802, 2802, 2802, 3035,
+     3035, 2802, 2802, 2802, 2802, 2802, 2802, 2802, 2802, 2802,
+     2802, 2802, 3037, 3037, 3038, 2802, 2802, 2802, 3039, 3039,
+     3039, 2802, 2802, 2802, 2802, 2802, 2802, 2802, 2802, 2802,
+     2802, 2802, 2802, 2802, 2802, 3041, 2802, 2802, 3041, 2802,
+     2802, 2802, 3042, 2802, 2802, 2802, 3043, 2802, 2802, 2802,
+     2802, 2802, 2802, 2802, 2802, 2802, 2802, 2802, 2802, 2802,
+     3044, 3044, 2802, 2802, 2802, 2802, 2802, 3045, 2802, 3046,
+
+     3047, 2802, 2802, 2802, 2802, 2802, 2802, 3049, 2802, 2802,
+     3023, 2802, 2802, 2802, 3024, 2802, 2802, 2802, 2802, 2802,
+     2802, 2802, 2802, 2802, 2802, 2802, 2802, 2802, 2802, 2802,
+     2802, 2802, 3031, 3034, 3035, 3035, 3037, 3037, 3038, 3039,
+     2802, 2802, 3039, 2802, 2802, 2802, 2802, 2802, 2802, 2802,
+     2802, 2802, 3041, 2802, 2802, 2802, 3041, 3042, 3043, 2802,
+     2802, 2802, 2802, 2802, 2802, 2802, 2802, 3044, 2802, 2802,
+     2802, 3045, 3046, 3046, 3046, 3046, 3046, 3046, 3046, 3046,
+     3046, 3046, 3046, 3046, 3046, 3047, 2802, 2802, 2802, 2802,
+     2802, 2802, 2802, 2802, 2802, 3023, 2802, 2802, 2802, 2802,
+
+     2802, 2802, 2802, 2802, 2802, 2802, 3031, 3034, 3035, 3035,
+     3037, 3037, 2802, 2802, 3039, 2802, 2802, 2802, 3039, 3041,
+     3041, 3042, 3043, 2802, 2802, 2802, 3044, 2802, 2802, 3046,
+     3046, 3046, 3046, 3046, 3046, 3046, 3046, 3046, 3046, 3046,
+     3046, 3046, 3046, 3046, 3046, 3047, 2802, 2802, 2802, 2802,
+     2802, 2802, 2802, 2802, 2802, 2802, 2802, 2802, 2802, 2802,
+     2802, 2802, 2802, 2802, 2802, 3037, 3037, 2802, 2802, 2802,
+     2802, 2802, 2802, 2802, 2802, 3042, 2802, 2802, 2802, 2802,
+     3046, 3046, 3046, 3046, 3046, 3046, 3046, 3046, 3046, 3046,
+     3046, 3046, 3046, 3046, 3046, 3046, 3047, 2802, 2802, 2802,
+
+     2802, 2802, 2802, 2802, 2802, 2802, 2802, 2802, 2802, 2802,
+     2802, 2802, 2802, 2802, 2802, 2802, 2802, 2802, 2802, 2802,
+     2802, 2802, 2802, 2802, 2802, 2802, 3042, 2802, 2802, 2802,
+     2802, 2802, 2802, 3046, 3046, 3046, 3046, 3046, 3046, 3046,
+     3046, 3046, 3046, 3046, 3046, 3046, 3046, 3046, 3046, 3047,
+     3047, 2802, 2802, 2802, 2802, 2802, 2802, 2802, 3042, 3046,
+     3046, 3046, 3046, 3046, 3046, 3046, 3046, 3046, 3046, 3046,
+     3046, 3046, 3046, 3046, 3046, 3047, 3051, 3052, 2802, 2802,
+     3046, 3046, 3046, 3046, 3046, 3046, 3046, 3046, 3046, 3046,
+     3046, 3046, 3046, 3046, 3046, 3046, 3046, 3051, 3052, 3046,
+
+     3046, 3046, 3046, 3046, 3046, 3046, 3046, 3046, 3046, 3046,
+     3046, 3046, 3046, 3046, 3046, 3046, 3047, 3046, 3046, 3046,
+     3046, 3046, 3046, 3046, 3046, 3046, 3046, 3046, 3046, 3046,
+     3046, 3046, 3046, 3046, 3046, 3046, 3046, 3046, 3046, 3046,
+     3046, 3046, 3046, 3046, 3046, 3046, 3046, 3046, 3046, 3046,
+     3046, 3046, 3046, 3046, 3046, 3046, 3046, 3046, 3046, 3046,
+     3046, 3046, 3046, 3046, 3046, 3046, 3046, 3046, 3046, 3046,
+     3046, 3046, 3046, 3046, 3046, 3046, 3046, 3046, 3046, 3046,
+     3046, 3046, 3046, 3046, 3046, 3046, 3046, 3046, 3046, 3046,
+     3046, 3046, 3046, 3046, 3046, 3046, 3046, 3046, 3046, 3046,
+
+     3046, 3046, 3046, 3046, 3046, 3046, 3046, 3046, 3046, 3046,
+     3046, 3046, 3046, 3046, 3046, 3046, 3046, 3046, 3046, 3046,
+     3046, 3046, 3046, 3046, 3046, 3046, 3046, 3046, 3046, 3046,
+     3046, 3046, 3046, 3046, 3046, 3046, 3046, 3046, 3046, 3046,
+     3046, 3046, 3046, 3046, 3046, 3046, 3046, 3046, 3046, 3046,
+     3046, 3046, 3046, 3046, 3046, 3046, 3046, 3046, 3046, 3046,
+     3046, 3046, 3046, 3046, 3046, 3046, 3046, 3046, 3046, 3046,
+     3046, 3046, 3046, 3046, 3046, 3046, 3046, 3046, 3046, 3046,
+     3046, 3046, 3046, 3046, 3046, 3046, 3046, 3046, 3046, 3046,
+     3046, 3046, 3046, 3046, 3046, 3046, 3046, 3046, 3046, 3046,
+
+     3046, 3046, 3046, 3046, 3046, 3046, 3046, 3046, 3046, 3046,
+     3046, 3046, 3046, 3046, 3046, 3046, 3046, 3046, 3046, 3046,
+     3046, 3046, 3046, 3046, 3046, 3046, 3046, 3046, 3046, 3046,
+     3046, 3046, 3046, 3046, 3046, 3046, 3046, 3046, 3046, 3046,
+     3046, 3046, 3046, 3046, 3046, 3046, 3046, 3046, 3046, 3046,
+     3046, 3046, 3046, 3046, 3046, 3046, 3046, 3046, 3046, 3046,
+     3046, 3046, 3046, 3046, 3046, 3046, 3046, 3046, 3046, 3046,
+     3046, 3046, 3046, 3046, 3046, 3046, 3046, 3046, 3046, 3046,
+     3046, 3046, 3046, 3046, 3046, 3046, 3046, 3046, 3046, 3046,
+     3046, 3046, 3046, 3046, 3046, 3046, 3046, 3046, 3046, 3046,
+
+     3046, 3046, 3046, 3046, 3046, 3046, 3046, 3046, 3046, 3046,
+     3046, 3046, 3046, 3046, 3046, 3046, 3046, 3046, 3046, 3046,
+     3046, 3046, 3046, 3046, 3046, 3046, 3046, 3046, 3046, 3046,
+     3046, 3046, 3046, 3046, 3046, 3046, 3046, 3046, 3046, 3046,
+     3046, 3046, 3046, 3046, 3046, 3046, 3046, 3046, 3046, 3046,
+     3046, 3046, 3046, 3046, 3046, 3046, 3046, 3046, 3046, 3046,
+     3046, 3046, 3046, 3046, 3046, 3046, 3046, 3046, 3046, 3046,
+     3046, 3046, 3046, 3046, 3046, 3046, 3046, 3046, 3046, 3046,
+     3046, 3046, 3046, 3046, 3046, 3046, 3046, 3046, 3046, 3046,
+     3046, 3046, 3046, 3046, 3046, 3046, 3046, 3046, 3046, 3046,
+
+     3046, 3046, 3046, 3046, 3046, 3046, 3046, 3046, 2802, 3046,
+     3046, 3046, 3046, 3046, 3046, 3046, 3046, 3046, 3046, 3046,
+     3046, 3046, 2802, 3046, 3046, 3046, 3046, 3046, 3046, 3046,
+     3046, 3046, 3046, 3046, 2802, 3046, 2802, 3046, 2802, 3046,
+     3046, 3046, 3046, 3046, 3046, 3046, 3046, 3046, 2802, 3046,
+     3046, 3046, 3046, 2802, 3046, 2802, 3046, 2802, 3046, 3046,
+     3046, 2802, 3046, 3046, 3046, 3046, 3046, 3046, 3046, 2802,
+     3046, 3046, 3046, 2802, 3046, 3046, 3046, 3046, 3046, 3046,
+     3046, 3046, 3046, 2802, 3046, 2802, 3046, 3046, 3046, 3046,
+     3046, 3046, 3046, 2802, 3046, 2802, 3046, 3046, 3046, 3046,
+
+     2802,    0, 2802, 2802, 2802, 2802, 2802, 2802, 2802, 2802,
+     2802, 2802, 2802, 2802, 2802, 2802, 2802, 2802, 2802, 2802,
+     2802, 2802, 2802, 2802, 2802, 2802, 2802, 2802, 2802, 2802,
+     2802, 2802, 2802, 2802, 2802, 2802, 2802, 2802, 2802, 2802,
+     2802, 2802, 2802, 2802, 2802, 2802, 2802, 2802, 2802, 2802,
+     2802, 2802, 2802, 2802, 2802, 2802, 2802, 2802, 2802, 2802,
+     2802, 2802, 2802, 2802, 2802, 2802, 2802, 2802, 2802, 2802,
+     2802, 2802, 2802, 2802, 2802, 2802, 2802, 2802, 2802, 2802,
+     2802, 2802, 2802, 2802, 2802, 2802, 2802, 2802, 2802, 2802,
+     2802, 2802, 2802, 2802, 2802, 2802, 2802, 2802, 2802, 2802,
+
+     2802, 2802, 2802, 2802, 2802, 2802, 2802, 2802, 2802, 2802,
+     2802, 2802, 2802, 2802, 2802, 2802, 2802, 2802, 2802, 2802,
+     2802, 2802, 2802, 2802, 2802, 2802, 2802, 2802, 2802, 2802,
+     2802, 2802, 2802, 2802, 2802, 2802, 2802, 2802, 2802, 2802,
+     2802, 2802, 2802, 2802, 2802, 2802, 2802, 2802, 2802, 2802,
+     2802, 2802, 2802, 2802, 2802, 2802, 2802, 2802, 2802, 2802,
+     2802, 2802, 2802, 2802, 2802, 2802, 2802, 2802, 2802, 2802,
+     2802, 2802, 2802, 2802, 2802, 2802, 2802, 2802, 2802, 2802,
+     2802, 2802, 2802, 2802, 2802, 2802, 2802, 2802, 2802, 2802,
+     2802, 2802, 2802, 2802, 2802, 2802, 2802, 2802, 2802, 2802,
+
+     2802, 2802, 2802, 2802, 2802, 2802, 2802, 2802, 2802, 2802,
+     2802, 2802, 2802, 2802, 2802, 2802, 2802, 2802, 2802, 2802,
+     2802, 2802, 2802, 2802, 2802, 2802, 2802, 2802, 2802, 2802,
+     2802, 2802, 2802, 2802, 2802, 2802, 2802, 2802, 2802, 2802,
+     2802, 2802, 2802, 2802, 2802, 2802, 2802, 2802, 2802, 2802,
+     2802, 2802
+    } ;
+
+static yyconst short int yy_nxt[9962] =
+    {   0,
+     2802,  150,  151,  150,  150,  151,  150,  150,  151,  150,
+      150,  151,  150,  155,  151,  155,  161,  152,  158,  161,
+      152,  158, 2802,  153, 2802,  159,  153,  718,  159,  156,
+      155,  151,  155,  477,  162,  164,  165,  162,  164,  165,
+      166,  167,  719,  166,  167,  477,  156,  171,  172,  478,
+      168,  164,  165,  168,  169,  480,  166,  164,  165,  651,
+      169,  479,  166,  171,  172,  652,  168,  151,  151,  151,
+      980,  479,  168,  151,  151,  151,  151,  151,  151,  151,
+      151,  151,  549,  175,  173,  476,  476,  476, 1580,  175,
+      550,  581,  186,  885,  886,  186,  476,  476,  476,  582,
+
+      173,  176,  177,  151,  177,  176,  176,  176,  176,  176,
+      176,  176,  178,  176,  176,  176, 1587,  176,  180,  176,
+      181,  176,  188,  151,  188, 1590,  188,  151,  188,  151,
+      151,  151,  151,  151,  151,  188,  151,  188,  189,  176,
+      176,  182,  189,  480, 1591,  190,  183,  496,  190, 1315,
+     1316,  189,  184,  476,  476,  476,  476,  476,  476,  479,
+      497,  185,  176,  177,  151,  177,  176,  176,  176,  176,
+      176,  176,  176,  178,  176,  176,  176, 1592,  176,  180,
+      176,  181,  176,  188,  151,  188, 1594,  188,  151,  188,
+      188,  151,  188,  151,  151,  151,  151,  151,  151,  189,
+
+      176,  176,  182,  191,  480,  480,  191,  183,  958,  192,
+      959,  500,  192,  184,  476,  476,  476,  476,  476,  476,
+      479,  479,  185,  193,  194,  151,  194,  193,  193,  193,
+      193,  193,  193,  193,  195,  193,  193,  193, 1596,  193,
+      197,  193,  198,  193,  203,  151,  203, 1597,  203,  151,
+      203,  151,  151,  151,  151,  151,  151,  476,  476,  476,
+      204,  193,  193,  199,  204, 1618,  724,  205,  200,  725,
+      205,  201,  193,  194,  151,  194,  193,  193,  193,  193,
+      193,  193,  193,  195,  193,  193,  193, 1619,  193,  197,
+      193,  198,  193,  216,  151,  216, 1620,  216,  151,  216,
+
+      151,  151,  151,  151,  151,  151,  476,  476,  476,  217,
+      193,  193,  199,  217,  804, 1621,  218,  200,  805,  218,
+      201,  206,  207,  151,  207,  206,  206,  206,  206,  206,
+      206,  206,  208,  206,  206,  206, 1634,  206,  210,  206,
+      211,  206,  231,  151,  231,  231,  151,  231,  151,  151,
+      151,  151,  151,  151,  476,  476,  476, 1635,  232,  206,
+      206,  232,  980, 1636,  186,  212, 1222,  186, 1638,  213,
+      214,  206,  207,  151,  207,  206,  206,  206,  206,  206,
+      206,  206,  208,  206,  206,  206, 1639,  206,  210,  206,
+      211,  206,  244,  151,  244,  244,  151,  244,  151,  151,
+
+      151,  151,  151,  151,  476,  476,  476, 1640,  245,  206,
+      206,  245, 1320, 1321,  246,  212, 1641,  246, 1643,  213,
+      214,  219,  220,  151,  220,  219,  219,  219,  219,  219,
+      219,  219,  221,  219,  219,  219,  222,  219,  223,  219,
+      224,  219,  222,  222,  222,  222,  222,  222,  222,  222,
+      222,  222,  222,  222,  222,  222,  222,  222,  222,  219,
+      219,  222,  222,  225,  222,  222,  226,  222,  222,  227,
+      222,  222,  222,  222,  222,  222,  222,  222,  228,  222,
+      229,  222,  222,  222,  222,  222,  233,  234,  151,  234,
+      233,  233,  233,  233,  233,  233,  233,  235,  233,  233,
+
+      233, 1651,  233,  237,  233,  238,  233,  151,  151,  151,
+     1652,  151,  151,  151,  654,  151,  151,  151,  151,  151,
+      151,  480,  655,  259,  233,  233,  239,  259,  480,  480,
+      240,  259, 1060, 1653,  259,  510,  699,  479,  241,  501,
+      476,  476,  476,  700,  479,  479, 1061,  242,  233,  234,
+      151,  234,  233,  233,  233,  233,  233,  233,  233,  235,
+      233,  233,  233, 1654,  233,  237,  233,  238,  233,  261,
+      151,  261, 1659,  261,  151,  261,  667,  261,  151,  261,
+      261,  151,  261,  480,  668,  262,  233,  233,  239,  262,
+      480,  480,  240,  263, 1062, 1660,  263,  516, 1676,  479,
+
+      241,  476,  476,  476,  502, 1683,  479,  479, 1063,  242,
+      247,  248,  151,  248,  247,  247,  247,  247,  247,  247,
+      247,  249,  247,  247,  247,  250,  247,  251,  247,  252,
+      247,  250,  250,  250,  250,  250,  250,  250,  250,  250,
+      250,  250,  250,  250,  250,  250,  250,  250,  247,  247,
+      250,  250,  250,  253,  250,  250,  250,  250,  254,  250,
+      250,  250,  250,  250,  255,  250,  250,  250,  250,  250,
+      256,  250,  257,  258,  250,  151,  151,  151,  151,  151,
+      151,  476,  476,  476,  476,  476,  476,  476,  476,  476,
+     1687,  259, 1668, 1669,  259,  264,  265,  151,  265,  264,
+
+      264,  264,  264,  264,  264,  264,  266,  264,  264,  264,
+     1689,  264,  268,  264,  269,  264,  151,  151,  151,  151,
+      151,  151,  276,  151,  276,  276,  151,  276,  151,  151,
+      151,  480,  274,  264,  264,  274,  521,  673,  277,  480,
+      980,  277,  270,  271,  274,  674,  272,  479,  476,  476,
+      476,  522,  982,  503, 1692,  479,  273,  264,  265,  151,
+      265,  264,  264,  264,  264,  264,  264,  264,  266,  264,
+      264,  264, 1693,  264,  268,  264,  269,  264,  151,  151,
+      151,  151,  151,  151,  151,  151,  151,  151,  151,  151,
+      151,  151,  151,  480,  274,  264,  264,  286,  480,  707,
+
+      286, 1694, 1698,  286,  270,  271,  286,  708,  272,  479,
+      476,  476,  476, 1700,  479,  476,  476,  476,  273,  278,
+      279,  151,  279,  278,  278,  278,  278,  278,  278,  278,
+      280,  278,  278,  278, 1701,  278,  282,  278,  283,  278,
+      288,  151,  288,  288,  151,  288,  288,  151,  288,  288,
+      151,  288,  151,  151,  151,  480,  289,  278,  278,  289,
+      480,  480,  290,  480, 1702,  290, 1703,  525,  291, 1704,
+      532,  479,  476,  476,  476, 1705,  479,  479, 1706,  479,
+      543,  284,  285,  278,  279,  151,  279,  278,  278,  278,
+      278,  278,  278,  278,  280,  278,  278,  278, 1710,  278,
+
+      282,  278,  283,  278,  151,  151,  151,  303,  151,  303,
+      303,  151,  303,  151,  151,  151,  151,  151,  151,  480,
+      291,  278,  278,  304,  480,  480,  304,  480,  480,  305,
+     1715,  544,  305, 1719,  553,  479,  476,  476,  476, 1725,
+      479,  479,  552,  479,  479,  284,  285,  292,  293,  151,
+      293,  292,  292,  292,  292,  292,  292,  292,  294,  292,
+      292,  292, 1726,  292,  296,  292,  297,  292,  321,  151,
+      321,  321,  151,  321,  151,  151,  151,  151,  151,  151,
+      339,  151,  339,  480,  322,  292,  292,  322,  480, 1729,
+      323, 1730,  480,  323, 1731,  568,  340, 1732, 1733,  479,
+
+      560,  298, 1738,  299,  479,  476,  476,  476,  479,  300,
+      301,  292,  293,  151,  293,  292,  292,  292,  292,  292,
+      292,  292,  294,  292,  292,  292, 1741,  292,  296,  292,
+      297,  292,  339,  151,  339,  151,  151,  151,  151,  151,
+      151,  360,  151,  360,  360,  151,  360,  480,  340,  292,
+      292,  341,  480,  480,  341, 1745,  480,  361, 1748,  577,
+      361, 1753, 1760,  479, 1767,  298, 1768,  299,  479,  479,
+     1776,  563,  479,  300,  301,  306,  307,  151,  307,  306,
+      306,  306,  306,  306,  306,  306,  308,  306,  306,  306,
+      309,  306,  310,  306,  311,  306,  309,  309,  309,  309,
+
+      309,  309,  309,  309,  309,  309,  309,  309,  309,  309,
+      309,  309,  309,  306,  306,  309,  309,  309,  309,  309,
+      309,  309,  312,  313,  309,  314,  309,  309,  315,  309,
+      309,  316,  309,  309,  309,  317,  309,  318,  319,  309,
+      324,  325,  151,  325,  324,  324,  324,  324,  324,  324,
+      324,  326,  324,  324,  324,  327,  324,  328,  324,  329,
+      324,  327,  327,  327,  327,  327,  327,  327,  327,  327,
+      327,  327,  327,  327,  327,  327,  327,  327,  324,  324,
+      327,  327,  330,  327,  327,  327,  327,  331,  332,  327,
+      327,  327,  327,  333,  327,  327,  327,  327,  327,  327,
+
+      334,  335,  336,  337,  327,  342,  343,  151,  343,  342,
+      342,  342,  342,  342,  342,  342,  344,  342,  342,  342,
+      345,  342,  346,  342,  347,  342,  345,  345,  345,  345,
+      345,  345,  345,  345,  345,  345,  345,  345,  345,  345,
+      345,  345,  345,  342,  342,  348,  345,  345,  349,  345,
+      345,  345,  350,  351,  345,  352,  345,  345,  353,  345,
+      345,  354,  345,  355,  356,  345,  345,  357,  358,  345,
+      151,  151,  151,  151,  151,  151,  476,  476,  476,  476,
+      476,  476,  476,  476,  476, 1777,  362, 1778, 1779,  362,
+      363,  364,  151,  364,  363,  363,  363,  363,  363,  363,
+
+      363,  365,  363,  363,  363,  366,  363,  367,  363,  368,
+      363,  366,  366,  366,  366,  366,  366,  366,  366,  366,
+      366,  366,  366,  366,  366,  366,  366,  366,  363,  363,
+      369,  366,  366,  370,  366,  366,  366,  371,  372,  366,
+      373,  366,  366,  374,  366,  366,  375,  376,  377,  378,
+      366,  366,  379,  380,  366,  382,  151,  382,  382,  151,
+      382,  151,  151,  151,  151,  151,  151,  476,  476,  476,
+     1783,  383, 1784, 1785,  383, 1786, 1790,  384, 1853, 1854,
+      384,  385,  386,  151,  386,  385,  385,  385,  385,  385,
+      385,  385,  387,  385,  385,  385,  388,  385,  389,  385,
+
+      390,  385,  388,  388,  388,  388,  388,  388,  388,  388,
+      388,  388,  388,  388,  388,  388,  388,  388,  388,  385,
+      385,  388,  388,  388,  391,  388,  388,  388,  392,  393,
+      388,  394,  388,  388,  395,  396,  388,  397,  388,  398,
+      399,  400,  388,  401,  402,  388,  404,  151,  404,  404,
+      151,  404,  151,  151,  151,  151,  151,  151,  476,  476,
+      476, 1862,  405, 1863, 1864,  405, 1868, 1877,  406, 1878,
+     1881,  406,  407,  408,  151,  408,  407,  407,  407,  407,
+      407,  407,  407,  409,  407,  407,  407,  410,  407,  411,
+      407,  412,  407,  410,  410,  410,  410,  410,  410,  410,
+
+      410,  410,  410,  410,  410,  410,  410,  410,  410,  410,
+      407,  407,  410,  410,  410,  410,  410,  410,  410,  413,
+      414,  410,  415,  416,  417,  410,  410,  410,  418,  419,
+      420,  410,  421,  410,  422,  423,  410,  425,  151,  425,
+      425,  151,  425,  151,  151,  151,  151,  151,  151,  476,
+      476,  476,  980,  426, 1888, 1894,  426, 1897, 1869,  427,
+     1902, 1903,  427,  428,  429,  151,  429,  428,  428,  428,
+      428,  428,  428,  428,  430,  428,  428,  428,  431,  428,
+      432,  428,  433,  428,  431,  431,  431,  431,  431,  431,
+      431,  431,  431,  431,  431,  431,  431,  431,  431,  431,
+
+      431,  428,  428,  434,  431,  431,  435,  431,  436,  431,
+      437,  438,  431,  431,  431,  431,  431,  431,  431,  431,
+      439,  440,  431,  441,  442,  443,  444,  431,  446,  151,
+      446,  446,  151,  446,  151,  151,  151,  151,  151,  151,
+      476,  476,  476, 1904,  447, 1905, 1991,  447, 1992, 1999,
+      448, 2007, 2008,  448,  449,  450,  151,  450,  449,  449,
+      449,  449,  449,  449,  449,  451,  449,  449,  449,  452,
+      449,  453,  449,  454,  449,  452,  452,  452,  452,  452,
+      452,  452,  452,  452,  452,  452,  452,  452,  452,  452,
+      452,  452,  449,  449,  452,  455,  452,  452,  452,  456,
+
+      452,  457,  458,  452,  459,  452,  452,  452,  460,  452,
+      461,  462,  452,  452,  463,  464,  465,  466,  452,  151,
+      151,  151,  151,  151,  151,  468,  151,  468,  468,  151,
+      468,  471,  472,  485,  480,  384,  473, 2015,  384,  480,
+      480,  469,  471,  472,  469, 2028,  474,  473,  480, 2029,
+      479, 2068, 1391,  480, 2105,  479,  479,  474,  501, 2127,
+      500,  502,  503, 2155,  479,  491, 2198,  486,  475,  479,
+      499,  501,  504,  487,  502,  503,  480,  488, 1582,  475,
+      504, 2086,  489,  544,  480,  504,  539,  539,  539,  541,
+      541,  541,  479,  556,  556,  556,  558,  558,  558,  480,
+
+      479,  543,  561,  540,  480,  480,  542,  573,  573,  573,
+      557,  591,  608,  559,  480,  479,  980,  575,  575,  575,
+      479,  479,  980,  980,  574,  476,  476,  476,  592, 1739,
+      479,  560,  561,  562,  576, 1391, 1391,  552,  563,  587,
+      587,  587,  564,  565,  566,  567,  589,  589,  589,  596,
+      596,  596,  602,  602,  602, 2130,  588,  604,  604,  604,
+      606,  606,  606,  590, 2134,  480,  597,  480,  480,  603,
+      620,  620,  620, 1870,  605,  624,  980,  607,  622,  622,
+      622,  479, 2544,  479,  479,  480,  562,  621,  637,  637,
+      637,  980,  598,  480,  980,  623,  639,  639,  639, 2181,
+
+      641,  479,  476,  476,  476,  638,  656,  656,  656,  479,
+      658,  658,  658,  640,  480,  566,  476,  476,  476,  480,
+      480,  660, 2133,  657,  476,  476,  476,  659,  480,  480,
+      479,  480,  675,  675,  675,  479,  479,  677,  677,  677,
+      476,  476,  476,  480,  479,  479, 1579,  479,  661,  676,
+      679,  476,  476,  476,  678,  691,  691,  691, 1575,  479,
+      567,  693,  693,  693,  476,  476,  476,  480,  480,  476,
+      476,  476,  692,  485,  695,  710,  710,  710,  694,  980,
+      712,  712,  712,  479,  479,  476,  476,  476,  480,  476,
+      476,  476,  711,  980, 1391,  714,  564,  713,  722,  722,
+
+      722,  745,  745,  745,  479, 1391,  980,  486,  750,  750,
+      750, 2137,  980,  487,  757,  757,  757,  488,  746,  771,
+      771,  771,  489,  980, 2139,  751,  539,  539,  539,  980,
+     1740,  758, 2001,  775,  775,  775,  772,  776, 2235, 1388,
+      777, 2131,  980,  540,  541,  541,  541,  980,  723,  778,
+      778,  778, 2132,  779,  980, 1574,  780,  785,  785,  785,
+     2142,  542,  556,  556,  556,  793,  793,  793, 2138,  794,
+      980,  980,  795,  980,  786,  558,  558,  558,  980,  557,
+      796,  796,  796,  980,  797, 2194,  980,  798,  573,  573,
+      573, 2136,  559,  812,  812,  812, 2143,  813, 2184, 2144,
+
+      814,  575,  575,  575, 2135,  574,  815,  815,  815, 1391,
+      816,  980, 2145,  817,  821,  821,  821, 2182,  576,  587,
+      587,  587,  828,  828,  828, 2183,  829,  980,  980,  830,
+     1573,  822,  589,  589,  589,  980,  588,  831,  831,  831,
+      980,  832,  980, 2146,  833,  596,  596,  596,  980,  590,
+      837,  837,  837, 2185,  838, 2189, 2188,  839,  841,  841,
+      841, 2187,  597,  602,  602,  602,  845,  845,  845, 2190,
+      846, 2193,  980,  847,  980,  842,  604,  604,  604, 2236,
+      603,  848,  848,  848, 1572,  849, 1571,  980,  850,  606,
+      606,  606,  980,  605,  851,  851,  851, 2192,  852,  980,
+
+      980,  853,  859,  859,  859, 2186,  607,  865,  865,  865,
+      620,  620,  620,  867,  867,  867, 2191,  868,  980,  860,
+      869,  622,  622,  622,  866, 2195, 2239,  621,  870,  870,
+      870,  980,  871, 1391,  980,  872, 2281,  980,  623,  878,
+      878,  878,  637,  637,  637,  887,  887,  887, 2374,  888,
+      980, 2196,  889,  639,  639,  639,  879,  980, 2241,  638,
+      890,  890,  890,  980,  891,  980, 2197,  892, 2242,  980,
+      640,  897,  897,  897,  905,  905,  905,  656,  656,  656,
+      909,  909,  909, 2238,  910, 2234, 2140,  911,  898,  980,
+     2141,  906, 2237,  980,  657,  658,  658,  658,  912,  912,
+
+      912,  980,  913, 2240,  980,  914,  918,  918,  918,  675,
+      675,  675,  659,  929,  929,  929, 1567,  930,  980,  980,
+      931, 1563, 2244,  919,  980, 2246,  676,  677,  677,  677,
+      932,  932,  932, 2243,  933,  980, 2248,  934,  941,  941,
+      941,  691,  691,  691,  678,  947,  947,  947, 2249,  948,
+      980,  980,  949, 2260,  980,  942, 2261, 2245,  692,  693,
+      693,  693,  950,  950,  950,  980,  951,  980,  980,  952,
+      960,  960,  960,  710,  710,  710,  694,  969,  969,  969,
+      980,  970, 1562,  980,  971, 2262,  980,  961, 2275, 2247,
+      711,  712,  712,  712,  972,  972,  972, 2263,  973, 1543,
+
+     2266,  974,  722,  722,  722, 2267,  984, 2264,  713,  998,
+      998,  998,  998,  998,  998,  745,  745,  745, 1008, 1008,
+     1008,  980, 1009, 2268,  980, 1010,  980, 1000,  980, 2321,
+     1000,  980,  746, 1011, 1011, 1011, 1011, 1011, 1011,  750,
+      750,  750, 1016, 1016, 1016, 2270, 1017, 2271,  980, 1018,
+      980, 1013, 2269, 2272, 1013, 1540,  751,  980, 1001, 1019,
+     1019, 1019, 1021, 1021, 1021, 2303, 1021, 1021, 1021,  757,
+      757,  757, 1033, 1033, 1033, 2274, 1020, 1033, 1033, 1033,
+     1023, 2283,  980, 1014, 1023, 2284,  758, 1027, 1027, 1027,
+     1035, 1028, 2282,  980, 1029, 1035, 1041, 1041, 1041, 1041,
+
+     1041, 1041,  771,  771,  771, 1046, 1046, 1046,  980, 1047,
+      980,  980, 1048,  980, 1043,  980,  980, 1043,  980,  772,
+      775,  775,  775, 2310,  776, 1024, 2292,  777, 2323, 1036,
+      778,  778,  778,  980,  779,  980, 2346,  780, 1052, 1052,
+     1052, 1052, 1052, 1052, 2290, 1044,  785,  785,  785, 2289,
+     1057, 1057, 1057,  980, 1058, 2293, 1054, 1059, 2297, 1054,
+     1066, 1066, 1066,  786, 1066, 1066, 1066,  793,  793,  793,
+      980,  794, 2327, 2309,  795, 1079, 1079, 1079, 1068,  796,
+      796,  796, 1068,  797, 2291, 1539,  798,  980, 1055, 1079,
+     1079, 1079,  980, 1081,  812,  812,  812, 2311,  813,  980,
+
+      980,  814, 2331, 1069,  815,  815,  815, 1081,  816,  980,
+     2305,  817, 1085, 1085, 1085, 1085, 1085, 1085,  821,  821,
+      821, 1090, 1090, 1090,  980, 1091, 1538, 2313, 1092, 1537,
+     1087, 2328, 2315, 1087,  980,  822,  828,  828,  828, 2545,
+      829,  980, 2322,  830, 1082,  831,  831,  831,  980,  832,
+     1391, 1392,  833, 1098, 1098, 1098, 1098, 1098, 1098, 2324,
+      837,  837,  837,  980,  838, 2329, 1088,  839,  841,  841,
+      841, 1100,  980,  980, 1100, 1104, 1104, 1104, 2357, 1105,
+     2559, 2325, 1106,  980,  980,  842,  845,  845,  845,  980,
+      846, 2332,  980,  847,  848,  848,  848, 1536,  849, 1535,
+
+      980,  850, 2335,  851,  851,  851, 1101,  852,  980, 2333,
+      853, 1109, 1109, 1109, 1109, 1109, 1109,  859,  859,  859,
+     1116, 1116, 1116,  980, 1117, 2379, 2336, 1118,  980, 1111,
+     2428,  980, 1111,  980,  860,  865,  865,  865, 1123, 1123,
+     1123, 2337, 1124, 2339,  980, 1125,  867,  867,  867, 2340,
+      868,  980,  866,  869,  870,  870,  870, 1112,  871, 2341,
+     2345,  872, 1126, 1126, 1126, 1126, 1126, 1126,  878,  878,
+      878, 1133, 1133, 1133,  980, 1134,  980,  980, 1135, 1534,
+     1128, 2454,  980, 1128,  980,  879, 1141, 1141, 1141, 1143,
+     1143, 1143,  887,  887,  887, 2343,  888, 2342, 2362,  889,
+
+      890,  890,  890, 1142,  891, 2483, 1144,  892, 1145, 1145,
+     1145, 1145, 1145, 1145,  897,  897,  897, 1151, 1151, 1151,
+      980, 1152, 2429, 1129, 1153,  980, 1147, 1529,  980, 1147,
+     1526,  898,  905,  905,  905, 1160, 1160, 1160, 2347, 1161,
+      980, 2348, 1162,  909,  909,  909, 2351,  910,  980,  906,
+      911,  912,  912,  912, 2365,  913,  980, 1148,  914, 1165,
+     1165, 1165, 1165, 1165, 1165,  918,  918,  918, 1170, 1170,
+     1170, 2349, 1171,  980, 2350, 1172, 1525, 1167,  980,  980,
+     1167,  980,  919,  929,  929,  929,  980,  930, 2352, 2382,
+      931,  932,  932,  932, 2353,  933, 2354,  980,  934, 1182,
+
+     1182, 1182, 1182, 1182, 1182,  941,  941,  941, 1190, 1190,
+     1190, 1168, 1191, 2356,  980, 1192, 2455, 1184,  980, 1524,
+     1184,  980,  942,  947,  947,  947, 1523,  948,  980, 2360,
+      949,  950,  950,  950, 2358,  951, 1519, 2359,  952,  980,
+      980, 1185, 1197, 1197, 1197, 1197, 1197, 1197,  960,  960,
+      960, 1206, 1206, 1206, 2364, 1207, 2366,  980, 1208,  980,
+     1199, 2513, 1511, 1199,  980,  961, 1213, 1213, 1213,  969,
+      969,  969, 2368,  970,  980, 2369,  971,  972,  972,  972,
+     2370,  973, 1508, 1214,  974, 1217, 1217, 1217, 1200, 1217,
+     1217, 1217,  998,  998,  998,  998,  998,  998,  998,  998,
+
+      998,  980,  980, 1219, 1241, 1241, 1241, 1219, 2373,  980,
+     1000, 2396,  980, 1000, 1503, 2375, 1000, 2371, 1008, 1008,
+     1008, 1242, 1009, 2390,  980, 1010, 1011, 1011, 1011, 1011,
+     1011, 1011, 1011, 1011, 1011, 1016, 1016, 1016, 1220, 1017,
+      980, 1235, 1018,  980, 1013,  980, 2376, 1013,  980,  980,
+     1013, 1019, 1019, 1019, 1245, 1245, 1245, 2514, 1246, 2377,
+     2389, 1247, 1021, 1021, 1021, 1021, 1021, 1021, 1020, 1021,
+     1021, 1021,  980, 1250, 1250, 1250,  980, 1027, 1027, 1027,
+     1023, 1028, 2527, 1023, 1029, 1495, 2439, 1023, 2381, 1243,
+     1251, 1253, 1253, 1253, 2372, 1033, 1033, 1033, 1033, 1033,
+
+     1033, 1033, 1033, 1033, 1259, 1259, 1259,  980, 1254, 1041,
+     1041, 1041, 1248, 1035,  980,  980, 1035, 1493,  980, 1035,
+     2383, 1260, 1041, 1041, 1041, 2378, 2392, 1043, 1041, 1041,
+     1041, 1046, 1046, 1046, 2385, 1047,  980,  980, 1048,  980,
+     1043, 1052, 1052, 1052,  980, 2386, 1043, 1052, 1052, 1052,
+     2387,  980, 1256, 2406, 1052, 1052, 1052, 2388, 1492, 1054,
+     1057, 1057, 1057, 1488, 1058, 1054, 2467, 1059, 1066, 1066,
+     1066, 1262, 1054, 1066, 1066, 1066, 1066, 1066, 1066, 1079,
+     1079, 1079, 1079, 1079, 1079,  980, 1068,  980, 1079, 1079,
+     1079, 1068,  980, 2394, 1068, 1481, 2393, 1081, 2398, 1459,
+
+     1081, 1085, 1085, 1085,  980, 1267, 1081, 1085, 1085, 1085,
+     1085, 1085, 1085, 1289, 1289, 1289, 1090, 1090, 1090, 1087,
+     1091,  980, 2397, 1092,  980, 1087,  980, 2402, 1087,  980,
+     1290, 2802, 2802, 2802,  980, 2802, 2802, 2802, 1275, 2395,
+     1285, 2802, 2802, 2802, 2802, 2802, 2802, 2401, 2802,  980,
+     2413, 1288, 2802, 2802, 2802, 2802, 2468,  980, 2802,  980,
+     2400, 2802, 1098, 1098, 1098, 1098, 1098, 1098, 2403,  980,
+     2802, 1098, 1098, 1098, 1291,  980,  980, 1298, 1298, 1298,
+     1100, 1456, 2425, 1100, 2415, 1109, 1109, 1109, 1293, 1100,
+     2420, 2560, 1292, 1295, 1299, 1104, 1104, 1104, 2610, 1105,
+
+      980, 1294, 1106, 1111, 1109, 1109, 1109, 1109, 1109, 1109,
+     1296, 1304, 1304, 1304, 1306, 1306, 1306, 1116, 1116, 1116,
+      980, 1117, 1111, 1455, 1118, 1111, 2435,  980, 1305,  980,
+      980, 1307, 1309, 1309, 1309, 1123, 1123, 1123, 2404, 1124,
+     2405, 2412, 1125, 1126, 1126, 1126, 2677,  980, 1302, 1310,
+     1126, 1126, 1126, 1126, 1126, 1126, 1317, 1317, 1317,  980,
+      980, 1128, 1133, 1133, 1133, 2463, 1134,  980, 1128, 1135,
+     2416, 1128,  980, 1318, 1141, 1141, 1141, 1325, 1325, 1325,
+     1454, 1326, 2492, 2421, 1327, 1143, 1143, 1143, 1328, 1328,
+     1328, 1142, 1329,  980,  980, 1330, 1145, 1145, 1145, 1145,
+
+     1145, 1145, 1144, 1145, 1145, 1145, 1332, 1332, 1332, 2437,
+     1313, 1334, 1334, 1334, 1147,  980,  980, 1147, 1151, 1151,
+     1151, 1147, 1152, 1333, 2481, 1153, 2451,  980, 1335,  980,
+     2802, 2802, 2802, 1337, 1337, 1337, 2802, 2802, 2802, 2802,
+     2802, 2802, 2802, 2802, 2802, 2443, 1331, 2802, 1453, 1452,
+     1338,  980,  980, 2802, 2440,  980, 2802, 2482, 2464, 2802,
+     2802, 2802, 2802, 1160, 1160, 1160, 2462, 1161, 1451,  980,
+     1162, 2802, 2802, 2802, 1165, 1165, 1165, 2802, 2802, 2802,
+     2802, 1165, 1165, 1165, 1165, 1165, 1165, 1336, 2802, 2452,
+     1341,  980, 1167, 1339, 1450, 2802, 1340, 2471, 2484, 1167,
+
+      980,  980, 1167, 1346, 1346, 1346, 1170, 1170, 1170,  980,
+     1171, 2493,  980, 1172, 1343, 2554,  980, 1342, 1344, 1449,
+     1347, 2802, 2802, 2802, 2802, 2802, 2802, 2500, 2802, 2802,
+     2802, 1345, 2802, 2802, 2802, 2802, 2802, 2802, 2802, 2453,
+      980, 2802, 2802, 2802, 2802, 2802, 2802, 2802, 2802, 2802,
+     2456,  980, 2802, 2802, 2802, 2802, 1182, 1182, 1182, 2802,
+     2802, 2802, 2802, 2802, 1182, 1182, 1182, 1360, 1360, 1360,
+     2802, 1351,  980, 2528, 1184, 1349,  980, 2802, 1348, 1350,
+     1447, 2485, 1184,  980, 1361, 1353, 1182, 1182, 1182, 1362,
+     1362, 1362, 1352, 1365, 1365, 1365, 1355, 1197, 1197, 1197,
+
+     1356, 2496,  980, 1354, 1184, 2497, 1363, 1190, 1190, 1190,
+     1366, 1191, 2511,  980, 1192, 1199, 1197, 1197, 1197, 1197,
+     1197, 1197, 1372, 1372, 1372, 1375, 1375, 1375, 1357, 1206,
+     1206, 1206,  980, 1207, 1199,  980, 1208, 1199,  980, 1373,
+     2457, 1444, 1376, 1213, 1213, 1213, 1381, 1381, 1381, 2587,
+     1382, 2458,  980, 1383, 1217, 1217, 1217, 1217, 1217, 1217,
+     1214, 1217, 1217, 1217, 1390, 1390, 1390, 1396, 1396, 1396,
+     2459,  980, 1219, 2469,  980, 1219, 2802, 2802, 2802, 1219,
+     1369, 2512, 1391, 1392, 1397, 2802, 2802, 2802, 2802, 2802,
+     2802,  980,  980, 2802, 2802, 2802, 2802,  998,  998,  998,
+
+     1386,  980, 2802, 1443, 2486, 2802, 1406, 1406, 1406, 2470,
+      980, 2802, 1241, 1241, 1241, 1000,  980, 1409, 1409, 1409,
+     2515, 1410,  980, 1398, 1411, 1011, 1011, 1011,  980, 1242,
+     2474, 1413, 1413, 1413, 1245, 1245, 1245, 1400, 1246, 2475,
+     2487, 1247, 1399, 1013,  980, 2516, 1401, 1403, 1414, 1021,
+     1021, 1021, 1416, 1416, 1416, 1250, 1250, 1250, 1418, 1418,
+     1418, 2611, 1419, 1442,  980, 1420, 2476, 1023, 1441, 1417,
+      980,  980, 1251, 2517,  980, 1412, 2802, 2802, 2802, 1253,
+     1253, 1253, 1422, 1422, 1422,  980, 1423, 2523, 1440, 1424,
+     2802, 2802, 2802, 2802, 2488,  980, 1254, 1033, 1033, 1033,
+
+     1415, 1428, 1428, 1428, 1259, 1259, 1259, 2802, 2477, 1430,
+     1430, 1430, 2478, 1431, 2518, 1035, 1432, 1421, 1429, 2577,
+      980, 1260, 1041, 1041, 1041, 1052, 1052, 1052, 1445, 1445,
+     1445, 1066, 1066, 1066, 1457, 1457, 1457,  980,  980, 1425,
+     1043, 1438,  980, 1054,  980, 1446, 1079, 1079, 1079, 1068,
+     2498, 1460, 1460, 1460, 1426, 1085, 1085, 1085, 1289, 1289,
+     1289, 1583, 1583, 1583, 1081,  980, 2529, 1439, 1461, 1466,
+     1466, 1466, 1434, 1087,  980, 1290, 2479, 1463, 1463, 1463,
+     2489, 1464, 2490, 1448, 1465, 1437, 1467, 1436, 2802, 2802,
+     2802, 2802, 2802, 2802, 2802, 2802, 2802, 2802, 2802, 2802,
+
+      980, 1462, 1435, 2494, 1458, 2802,  980,  980, 2802,  980,
+     1433, 2802, 2495,  980, 2802, 1098, 1098, 1098, 1473, 1473,
+     1473, 1298, 1298, 1298, 1475, 1475, 1475,  980, 1476,  980,
+     2499, 1477, 1469, 1100, 1470, 1474, 1427, 2578, 1299, 2503,
+     1468, 2802, 2802, 2802, 2501, 2502, 1471, 2802, 2802, 2802,
+     1109, 1109, 1109, 1304, 1304, 1304,  980, 2504, 2802, 2505,
+     1472, 1306, 1306, 1306, 2802, 1482, 1482, 1482, 1111, 1483,
+     1305,  980, 1484, 1485, 1485, 1485, 1408, 1486, 1307, 1407,
+     1487,  980, 1478, 1309, 1309, 1309, 1489, 1489, 1489, 1405,
+     1490,  980, 1404, 1491, 2540, 2592, 1479, 1126, 1126, 1126,
+
+     1310, 1496, 1496, 1496, 1498, 1498, 1498, 1480, 1317, 1317,
+     1317, 2506, 1500, 1500, 1500, 1128, 1501,  980, 1497, 1502,
+     2530, 1499, 1504, 1504, 1504, 1318, 1506, 1506, 1506, 1509,
+     1509, 1509, 2575, 1325, 1325, 1325,  980, 1326,  980, 1505,
+     1327,  980, 1402, 1507,  980,  980, 1510, 2507, 1328, 1328,
+     1328,  980, 1329,  980, 1494, 1330, 1145, 1145, 1145, 1332,
+     1332, 1332, 1513, 1513, 1513, 2534, 1514,  980, 2508, 1515,
+     1334, 1334, 1334, 2535, 1147, 2519, 1333, 1516, 1516, 1516,
+     2536, 1517, 1395, 2520, 1518,  980, 1394, 1335, 1337, 1337,
+     1337, 1520, 1520, 1520, 1393, 1521, 2537, 1512, 1522, 1527,
+
+     1527, 1527, 1165, 1165, 1165, 1338, 1346, 1346, 1346,  980,
+     1531, 1531, 1531,  980, 1532, 2525, 1528, 1533,  980,  980,
+     1167,  980,  980, 1347, 1541, 1541, 1541, 1182, 1182, 1182,
+     1545, 1545, 1545, 2802, 2802, 2802, 1360, 1360, 1360, 2526,
+      980, 1542,  980, 2532, 1530, 1184, 2692, 1546, 2533,  980,
+     2802, 2538, 1387, 1361, 1548, 1548, 1548, 2541, 1549, 2552,
+      980, 1550, 1362, 1362, 1362, 1385, 1551, 1551, 1551, 2539,
+     1552, 2550, 1547, 1553, 1544, 2802, 2802, 2802, 2551, 1363,
+     1365, 1365, 1365, 1555, 1555, 1555, 1384, 1556,  980,  980,
+     1557,  980, 2802, 2802, 2802, 2802, 1380, 1366, 1559, 1559,
+
+     1559, 1197, 1197, 1197, 1372, 1372, 1372, 1564, 1564, 1564,
+     2802, 1565, 2593, 1379, 1566, 1560, 1375, 1375, 1375, 1199,
+     2557, 1373, 2542,  980, 1554, 1568, 1568, 1568, 2576, 1569,
+      980, 2579, 1570, 1376, 1381, 1381, 1381,  980, 1382, 1378,
+      980, 1383, 1558, 1576, 1576, 1576, 1217, 1217, 1217, 1377,
+     1390, 1390, 1390, 1396, 1396, 1396, 2543,  980, 1561, 2558,
+     1577, 1588, 1588, 1588, 1219, 1584, 1584, 1584, 1391, 1585,
+     1397,  980, 1586,  998,  998,  998,  980,  980, 1589, 1595,
+     1595, 1595, 1406, 1406, 1406, 1409, 1409, 1409,  980, 1410,
+     2546, 1000, 1411, 1011, 1011, 1011, 1413, 1413, 1413, 1599,
+
+     1599, 1599,  980, 1600, 2547,  980, 1601,  980, 1578, 1581,
+     2548, 1013,  980, 1414, 2553,  980, 1593, 1021, 1021, 1021,
+     1416, 1416, 1416, 1603, 1603, 1603, 2588, 1604,  980,  980,
+     1605, 2565, 1598,  980, 2566, 1023, 2606, 1417, 1418, 1418,
+     1418, 2607, 1419,  980, 2618, 1420, 1606, 1606, 1606, 1422,
+     1422, 1422,  980, 1423, 1374,  980, 1424, 2608, 2802, 2802,
+     2802, 2549, 2561, 1607, 1609, 1609, 1609, 1611, 1611, 1611,
+     1428, 1428, 1428, 2573, 1602, 2802, 1613, 1613, 1613,  980,
+     1614, 1371, 1610, 1615, 1612, 2562,  980, 1429, 1430, 1430,
+     1430,  980, 1431, 2589,  980, 1432, 2802, 2802, 2802, 1041,
+
+     1041, 1041, 1052, 1052, 1052, 1608, 1623, 1623, 1623, 2574,
+     2802, 2802, 2802, 2802, 2802, 2802, 2802, 1043, 2609, 2567,
+     1054, 2585, 1370, 1624, 2802, 2802, 2802, 2802, 2802, 2802,
+     2802, 2802, 1445, 1445, 1445, 1368, 1629, 1629, 1629, 1616,
+     1630, 2802, 1617, 1631,  980, 2802, 1632, 1632, 1632, 1446,
+     1066, 1066, 1066, 1367, 1622, 1625, 1637, 1637, 1637, 1457,
+     1457, 1457, 1079, 1079, 1079, 1460, 1460, 1460, 1068, 1627,
+      980, 1626, 1644, 1644, 1644,  980, 1645, 2568,  980, 1646,
+     1081,  980, 1461,  980,  980, 1628, 1085, 1085, 1085, 1463,
+     1463, 1463,  980, 1464,  980,  980, 1465, 1466, 1466, 1466,
+
+     1098, 1098, 1098, 2569, 1087, 1648, 1648, 1648, 1633, 1649,
+     2619, 2570, 1650, 2596, 1467, 1642, 2571, 2572, 1100, 1473,
+     1473, 1473, 1656, 1656, 1656, 2583, 1657, 2584, 2590, 1658,
+     1475, 1475, 1475, 2580, 1476, 1364, 1474, 1477, 1647, 1109,
+     1109, 1109,  980, 1655, 1662, 1662, 1662, 1482, 1482, 1482,
+      980, 1483,  980,  980, 1484, 2581, 1359, 1111, 1485, 1485,
+     1485, 1663, 1486, 2582,  980, 1487, 2802, 2802, 2802, 1489,
+     1489, 1489,  980, 1490, 2612, 1358, 1491, 2613, 1661, 2802,
+     2802, 2802, 2586, 2802, 2802, 2802, 2802, 1126, 1126, 1126,
+     1496, 1496, 1496, 1670, 1670, 1670, 2802, 1671, 1324,  980,
+
+     1672, 2802, 1583, 1583, 1583, 1128, 1323, 1497, 1498, 1498,
+     1498, 1673, 1673, 1673, 2594, 1674,  980, 2595, 1675, 1664,
+     1500, 1500, 1500,  980, 1501, 1499,  980, 1502, 1504, 1504,
+     1504, 1665, 2591,  980, 1677, 1677, 1677, 1666, 1678, 1667,
+      980, 1679, 1506, 1506, 1506, 1505, 1680, 1680, 1680, 2598,
+     1681,  980,  980, 1682, 1509, 1509, 1509, 1322, 1319, 1507,
+     1684, 1684, 1684,  980, 1685, 1314, 2599, 1686, 1145, 1145,
+     1145, 1510, 1513, 1513, 1513, 2614, 1514, 1312, 2597, 1515,
+     1516, 1516, 1516, 1311, 1517, 2600, 1147, 1518, 1520, 1520,
+     1520, 2625, 1521, 2621,  980, 1522, 1690, 1690, 1690, 2601,
+
+     1527, 1527, 1527, 1695, 1695, 1695, 2602, 1696,  980,  980,
+     1697, 1308,  980, 1691,  980,  980, 1688, 1528, 1165, 1165,
+     1165, 1531, 1531, 1531,  980, 1532,  980, 1303, 1533, 1541,
+     1541, 1541,  980, 1707, 1707, 1707, 1167, 1708, 2615, 2622,
+     1709, 1182, 1182, 1182, 2603, 2639, 1542, 1545, 1545, 1545,
+     1712, 1712, 1712,  980, 1713, 2655, 2627, 1714,  980, 1184,
+      980, 1699, 2604, 2626, 1546, 1548, 1548, 1548, 2605, 1549,
+     2616,  980, 1550,  980, 1551, 1551, 1551,  980, 1552,  980,
+     1711, 1553, 1716, 1716, 1716, 1555, 1555, 1555,  980, 1556,
+     2629, 2640, 1557, 1559, 1559, 1559, 1720, 1720, 1720, 1717,
+
+     1721,  980, 2656, 1722, 1723, 1723, 1723, 1564, 1564, 1564,
+     1560, 1565, 2628, 1301, 1566, 1727, 1727, 1727,  980, 1568,
+     1568, 1568, 1724, 1569,  980, 2677, 1570, 1576, 1576, 1576,
+     2617, 2630, 1728, 1734, 1734, 1734,  980, 1735, 1718,  980,
+     1736, 1217, 1217, 1217, 1577, 1584, 1584, 1584, 2633, 1585,
+     1300, 2651, 1586, 1588, 1588, 1588, 1742, 1742, 1742, 1219,
+     1743,  980,  980, 1744, 1746, 1746, 1746, 1749, 1749, 1749,
+     1589, 1751, 1751, 1751, 1595, 1595, 1595, 1752, 1752, 1752,
+      980, 1747, 1011, 1011, 1011, 1750, 2634, 1599, 1599, 1599,
+     1737, 1600,  980,  980, 1601, 1755, 1755, 1755, 2623, 2686,
+
+     1013, 1603, 1603, 1603, 2635, 1604,  980,  980, 1605, 1606,
+     1606, 1606,  980, 1756, 1757, 1757, 1757, 2636, 1758, 1297,
+     1287, 1759, 1609, 1609, 1609, 2652, 1607, 1611, 1611, 1611,
+     1761, 1761, 1761,  980, 1762, 1754, 2637, 1763, 2624, 2688,
+     1610, 1613, 1613, 1613, 1612, 1614, 1286,  980, 1615, 1764,
+     1764, 1764, 1041, 1041, 1041, 1769, 1769, 1769, 1771, 1771,
+     1771,  980, 1052, 1052, 1052, 1284, 1765, 1623, 1623, 1623,
+     1043, 2687, 1770, 2631, 1773, 1773, 1773, 1283, 1774, 1766,
+     1054, 1775,  980, 1282, 1624, 1629, 1629, 1629,  980, 1630,
+     2663,  980, 1631, 1632, 1632, 1632, 1066, 1066, 1066, 1781,
+
+     1781, 1781, 1782, 1782, 1782, 1637, 1637, 1637, 1787, 1787,
+     1787, 1788, 1788, 1788, 1068, 2638, 1644, 1644, 1644, 2632,
+     1645,  980, 1772, 1646, 1085, 1085, 1085, 2641,  980, 1789,
+     1648, 1648, 1648, 1281, 1649,  980, 1280, 1650, 1792, 1792,
+     1792,  980, 1087, 1794, 1794, 1794, 2802, 2802, 2802, 1797,
+     1797, 1797, 2673, 1780, 2689, 1793, 1799, 1799, 1799, 2643,
+     1795,  980,  980, 2802, 2674, 2644, 1798,  980, 1656, 1656,
+     1656, 1279, 1657,  980, 1800, 1658, 1801, 1801, 1801, 1791,
+     1803, 1803, 1803, 1109, 1109, 1109, 2649, 1662, 1662, 1662,
+     1809, 1809, 1809, 1802, 2802, 2802, 2802, 1804, 1806, 1806,
+
+     1806, 1111, 1807, 1796, 1663, 1808, 2642, 1810, 2802, 2802,
+     2802, 2802, 1126, 1126, 1126, 1814, 1814, 1814, 1816, 1816,
+     1816,  980, 1670, 1670, 1670, 2802, 1671,  980, 1278, 1672,
+     1128, 2692, 1815,  980, 1805, 1817, 1673, 1673, 1673,  980,
+     1674,  980,  980, 1675, 1818, 1818, 1818,  980, 1677, 1677,
+     1677, 1811, 1678, 1277, 1276, 1679, 2664, 2802, 2802, 2802,
+     2645, 1819,  980, 1813,  980, 1812, 1680, 1680, 1680,  980,
+     1681, 2650, 2646, 1682, 2802, 1684, 1684, 1684, 2647, 1685,
+     2648,  980, 1686, 2802, 2802, 2802, 1145, 1145, 1145, 1823,
+     1823, 1823, 1690, 1690, 1690, 1825, 1825, 1825, 1274, 1826,
+
+     2802, 2661, 1827, 2662, 1147, 2657, 1824, 1822, 2667, 1691,
+     2802, 2802, 2802, 1273, 1820, 2802, 2802, 2802, 2802, 2802,
+     2802, 1695, 1695, 1695, 2684, 1696,  980, 2802, 1697, 1831,
+     1831, 1831, 2802,  980, 1272, 2802, 1165, 1165, 1165,  980,
+     1821, 1834, 1834, 1834,  980,  980, 1832, 2802, 2802, 2802,
+     2658, 2802, 2802, 2802, 1167, 2802, 2802, 2802, 1835, 2802,
+     2802, 2802, 1271, 2659, 2802, 1270,  980, 1828, 2802, 2660,
+     2707, 1829, 2802,  980,  980, 1830, 2802, 2695, 2802, 2802,
+     2802, 2802, 2802, 2802,  980, 1707, 1707, 1707, 1269, 1708,
+     1836, 1833, 1709,  980, 1837, 2802, 1268, 2665, 2802, 2696,
+
+     1842, 1842, 1842, 2707, 1182, 1182, 1182,  980, 1712, 1712,
+     1712, 1838, 1713, 2668,  980, 1714, 1839, 1843, 1845, 1845,
+     1845, 1840, 1184, 1716, 1716, 1716, 1847, 1847, 1847,  980,
+     1848, 2666, 2669, 1849, 1266, 1846, 1265, 1264, 1841, 1263,
+     1717, 2802, 2802, 2802, 1851, 1851, 1851, 1720, 1720, 1720,
+      980, 1721,  980, 1844, 1722, 1723, 1723, 1723, 2802, 2716,
+      980, 1852, 1855, 1855, 1855, 1727, 1727, 1727, 1857, 1857,
+     1857,  980, 1858, 1724, 2675, 1859, 1860, 1860, 1860, 1856,
+      980, 1261, 1728, 1865, 1865, 1865,  980, 1258, 1734, 1734,
+     1734, 2670, 1735, 1861, 1850, 1736, 1217, 1217, 1217, 2671,
+
+     1866, 1871, 1871, 1871, 1742, 1742, 1742,  980, 1743, 2743,
+     2672, 1744, 1257, 2710, 1219, 2802, 2802, 2802, 1872, 1746,
+     1746, 1746, 1874, 1874, 1874, 2682, 1875,  980,  980, 1876,
+      980, 2676, 2802, 1749, 1749, 1749, 1747, 1751, 1751, 1751,
+     1752, 1752, 1752, 1867, 1879, 1879, 1879, 1755, 1755, 1755,
+     1255, 1750, 2678, 1252, 1873, 2685, 1757, 1757, 1757,  980,
+     1758,  980, 1880, 1759,  980, 1756, 1761, 1761, 1761, 2683,
+     1762, 2710,  980, 1763, 1764, 1764, 1764, 1882, 1882, 1882,
+      980, 1883,  980, 2679, 1884, 1041, 1041, 1041, 1886, 1886,
+     1886, 1765, 1769, 1769, 1769, 1889, 1889, 1889,  980, 1890,
+
+     2690, 2744, 1891, 1043, 2680, 1887, 1771, 1771, 1771, 1770,
+     1892, 1892, 1892, 1773, 1773, 1773,  980, 1774, 1249, 1244,
+     1775, 1895, 1895, 1895, 1898, 1898, 1898,  980, 1893, 1900,
+     1900, 1900, 1781, 1781, 1781, 2711, 1885, 2691, 1896, 1240,
+     2681, 1899, 1782, 1782, 1782,  980,  980, 1901, 1787, 1787,
+     1787, 1788, 1788, 1788, 1906, 1906, 1906, 1908, 1908, 1908,
+     1792, 1792, 1792, 1910, 1910, 1910, 2697, 1911,  980, 1789,
+     1912, 1907, 1794, 1794, 1794, 1909, 1239, 1793, 1913, 1913,
+     1913,  980, 1914, 1238, 2698, 1915, 2802, 2802, 2802, 1795,
+     1797, 1797, 1797, 1917, 1917, 1917,  980, 1918, 2717,  980,
+
+     1919, 1237, 2711, 2802, 1799, 1799, 1799, 1798, 1801, 1801,
+     1801, 1920, 1920, 1920, 2765, 1921,  980, 2724, 1922, 1803,
+     1803, 1803, 1800, 2693, 2724, 1802, 1923, 1923, 1923, 2766,
+     1924,  980, 2729, 1925,  980,  980, 1804, 1109, 1109, 1109,
+     1806, 1806, 1806, 1916, 1807, 1236,  980, 1808, 1809, 1809,
+     1809,  980, 1927, 1927, 1927, 1111, 1928,  980, 2694, 1929,
+     2802, 2802, 2802, 1234, 1233, 1810, 2802, 2802, 2802, 1932,
+     1932, 1932, 1814, 1814, 1814, 2699,  980, 2802, 1816, 1816,
+     1816, 2700, 1926, 2802, 1934, 1934, 1934, 1933, 1935, 1815,
+     1232, 1936, 1937, 1937, 1937, 1817, 1938, 1231, 2718, 1939,
+
+     2701, 1818, 1818, 1818, 1940, 1940, 1940,  980, 1941, 1931,
+     1230, 1942, 2802, 2802, 2802,  980, 1229, 1930, 1819, 2802,
+     2802, 2802, 1145, 1145, 1145, 1823, 1823, 1823,  980, 2802,
+     1946, 1946, 1946,  980, 1947, 1228, 2802, 1948, 1227, 2702,
+     1147, 1226, 1824, 1825, 1825, 1825,  980, 1826,  980,  980,
+     1827, 2802, 2802, 2802, 2802, 2802, 2802, 2703, 2802, 2802,
+     2802, 1225, 1944, 1831, 1831, 1831, 1224, 2732, 2802, 1943,
+     2704, 2802, 2705, 2706, 1945, 2802,  980, 1952, 1952, 1952,
+     1832, 1953,  980,  980, 1954, 1955, 1955, 1955, 1834, 1834,
+     1834, 1957, 1957, 1957, 1223, 1958,  980,  980, 1959, 1221,
+
+     2712, 1951,  980, 1956, 1216, 1835, 2713, 2714, 1949,  980,
+     1950, 1960, 1960, 1960, 1962, 1962, 1962, 1964, 1964, 1964,
+     2802, 2802, 2802, 1967, 1967, 1967, 2715, 2719, 1961,  980,
+     2725, 1963, 1215, 2720, 1965, 2733,  980, 2802, 2730,  980,
+     1968, 2802, 2802, 2802, 1842, 1842, 1842, 1970, 1970, 1970,
+     2726, 1971,  980, 2721, 1972, 1182, 1182, 1182, 2802,  980,
+     1212, 1843, 1845, 1845, 1845, 1974, 1974, 1974, 2731, 1975,
+     1211,  980, 1976, 1184, 1847, 1847, 1847, 1966, 1848, 1846,
+      980, 1849,  980,  980, 1969, 2802, 2802, 2802, 1973, 1851,
+     1851, 1851, 1978, 1978, 1978, 2727, 1979, 1210, 1209, 1980,
+
+     1205, 1204, 2802, 1981, 1981, 1981, 1852, 2728, 1983, 1983,
+     1983, 1855, 1855, 1855, 1985, 1985, 1985, 2777, 1986, 2741,
+     1982, 1987,  980, 2729, 1977, 1984,  980,  980, 1856, 1857,
+     1857, 1857, 2730, 1858,  980, 2731, 1859, 1860, 1860, 1860,
+     1988, 1988, 1988,  980, 1989, 1203,  980, 1990, 1993, 1993,
+     1993, 1865, 1865, 1865, 1861, 1995, 1995, 1995, 1202, 1996,
+      980, 2742, 1997, 1201, 1196, 1994, 2767, 2740, 1866, 1217,
+     1217, 1217, 2000, 2000, 2000, 1871, 1871, 1871, 2002, 2002,
+     2002,  980, 2003, 1195, 2745, 2004, 1194, 1219, 2740, 1193,
+      980, 1189, 1872, 2005, 2005, 2005, 1874, 1874, 1874,  980,
+
+     1875, 1188, 2747, 1876, 1879, 1879, 1879, 2009, 2009, 2009,
+     2006, 1882, 1882, 1882, 1187, 1883,  980,  980, 1884, 1041,
+     1041, 1041, 1880, 2747, 2010, 1998, 1886, 1886, 1886, 2012,
+     2012, 2012, 1186, 2013,  980, 1181, 2014, 1043, 1889, 1889,
+     1889, 2746, 1890, 1887,  980, 1891, 1892, 1892, 1892, 2016,
+     2016, 2016, 1895, 1895, 1895, 2018, 2018, 2018,  980, 2019,
+     1180, 1179, 2020, 2011, 1893, 2752, 2017,  980, 2750, 1896,
+     2021, 2021, 2021, 1898, 1898, 1898, 2023, 2023, 2023,  980,
+     2024,  980, 2751, 2025, 1900, 1900, 1900, 2022, 1178, 2752,
+     1899, 2026, 2026, 2026, 2027, 2027, 2027, 1906, 1906, 1906,
+
+      980, 1177, 1901, 2030, 2030, 2030, 2768, 2031,  980, 2778,
+     2032, 1908, 1908, 1908, 1907, 1910, 1910, 1910,  980, 1911,
+     2771,  980, 1912, 1913, 1913, 1913, 2775, 1914, 1176, 1909,
+     1915, 2802, 2802, 2802, 1917, 1917, 1917,  980, 1918, 2775,
+      980, 1919, 1920, 1920, 1920, 2759, 1921, 2772, 2802, 1922,
+     1923, 1923, 1923,  980, 1924, 2776, 2789, 1925, 1109, 1109,
+     1109, 1927, 1927, 1927, 2760, 1928,  980,  980, 1929, 2802,
+     2802, 2802, 2802, 2802, 2802, 1175, 1111, 1932, 1932, 1932,
+     1934, 1934, 1934, 2033, 1935, 1174, 2802, 1936, 1173, 2802,
+     1937, 1937, 1937, 2790, 1938, 1933,  980, 1939, 1940, 1940,
+
+     1940, 1169, 1941,  980,  980, 1942, 1164, 2034, 2802, 2802,
+     2802, 2802, 2802, 2802, 1145, 1145, 1145, 2802, 2802, 2802,
+     2763, 2035, 1946, 1946, 1946, 2802, 1947, 2764, 2802, 1948,
+     2776, 1163, 1147, 2036, 2802, 2041, 2041, 2041, 2802, 2802,
+     2802, 1952, 1952, 1952,  980, 1953,  980,  980, 1954, 1955,
+     1955, 1955, 2042, 1159, 2789, 2802,  980, 1957, 1957, 1957,
+     2037, 1958, 2799, 1158, 1959, 1157, 1156, 1956,  980, 2040,
+     2779, 2780, 2038,  980,  980, 2039, 1960, 1960, 1960, 2044,
+     2044, 2044, 2790, 2045,  980,  980, 2046, 1962, 1962, 1962,
+     2047, 2047, 2047, 1961, 2048, 2791,  980, 2049, 2781, 2043,
+
+     1964, 1964, 1964,  980, 1963, 2050, 2050, 2050, 2782, 2051,
+      980, 1155, 2052, 2802, 2802, 2802, 1154, 1965, 1967, 1967,
+     1967, 2054, 2054, 2054, 2792, 2055, 1150, 2787, 2056, 1149,
+     2802, 2802, 2802, 2802, 2788, 1968, 1970, 1970, 1970,  980,
+     1971, 2799, 1140, 1972, 1182, 1182, 1182,  980, 2802, 1974,
+     1974, 1974, 1139, 1975, 1138,  980, 1976, 2802, 2802, 2802,
+     1137, 1136, 1184, 2797, 1132, 2053, 1978, 1978, 1978, 1131,
+     1979, 2798, 1130, 1980, 2802, 1122, 1121, 1981, 1981, 1981,
+     2060, 2060, 2060, 1120, 2061, 1119, 1115, 2062, 1983, 1983,
+     1983, 1114, 2057, 2058, 1982, 2063, 2063, 2063, 2059, 2064,
+
+     1113, 1108, 2065, 1107, 1103, 1984, 1985, 1985, 1985, 1102,
+     1986, 1097, 1096, 1987, 1988, 1988, 1988, 1095, 1989, 1094,
+     1093, 1990, 2066, 2066, 2066, 1993, 1993, 1993, 2069, 2069,
+     2069, 1089, 2070, 1084, 1083, 2071, 1995, 1995, 1995, 2067,
+     1996, 1078, 1994, 1997, 1217, 1217, 1217, 2002, 2002, 2002,
+     1077, 2003, 1076, 1075, 2004, 2005, 2005, 2005, 1074, 2087,
+     2087, 2087, 1219, 2088, 1073, 1072, 2089, 2090, 2090, 2090,
+     1071, 1070, 2006, 2091, 2091, 2091, 2009, 2009, 2009, 2093,
+     2093, 2093, 1065, 2094, 1064, 1056, 2095, 1041, 1041, 1041,
+     2092, 1051, 1050, 2010, 2097, 2097, 2097, 2016, 2016, 2016,
+
+     1049, 2072, 2000, 2000, 2000, 1043, 2012, 2012, 2012, 1045,
+     2013, 2098, 1040, 2014, 2017, 2021, 2021, 2021, 1039, 1038,
+      980, 1037, 2073, 2074, 2075, 1032, 2076, 2077, 2078, 2079,
+     2080, 1031, 2022, 2081, 2082, 2083, 2084, 2085, 1030, 2096,
+     2099, 2099, 2099, 1026, 2100, 1025, 1015, 2101, 2018, 2018,
+     2018, 1007, 2019, 1006, 1005, 2020, 2102, 2102, 2102, 1004,
+     2103, 1003, 1002, 2104, 2023, 2023, 2023,  997, 2024,  996,
+      995, 2025, 2026, 2026, 2026, 2027, 2027, 2027, 2106, 2106,
+     2106, 2030, 2030, 2030,  994, 2031,  993,  992, 2032, 2802,
+     2802, 2802, 1109, 1109, 1109, 2802, 2802, 2802, 2802, 2802,
+
+     2802, 2802, 2802, 2802,  991,  990, 2802, 2802, 2802, 2802,
+     1111,  989, 2802,  988,  987, 2802,  986,  983, 2802, 2113,
+     2113, 2113,  981,  980, 2802, 2802, 2802, 2802,  978, 2041,
+     2041, 2041, 2802, 2802, 2802, 2108,  977, 2114,  976, 2107,
+      968,  967, 2802,  966,  965, 2109, 2042,  964,  963, 2802,
+      962, 2111, 2116, 2116, 2116, 2110, 2117,  957,  956, 2118,
+      955, 2044, 2044, 2044, 2112, 2045,  954,  946, 2046, 2047,
+     2047, 2047,  945, 2048,  944, 2115, 2049, 2050, 2050, 2050,
+      943, 2051,  940,  939, 2052, 2802, 2802, 2802,  938, 2119,
+     2054, 2054, 2054,  937, 2055,  936,  928, 2056, 2802, 2802,
+
+     2802,  927, 2802, 1182, 1182, 1182, 2802, 2802, 2802, 2060,
+     2060, 2060,  926, 2061,  925, 2802, 2062,  924, 2063, 2063,
+     2063, 1184, 2064, 2802,  923, 2065, 2066, 2066, 2066, 2124,
+     2124, 2124,  922, 2125,  921, 2120, 2126, 2069, 2069, 2069,
+      920, 2070,  917, 2067, 2071, 2128, 2128, 2128,  804, 2123,
+     2122,  916, 2087, 2087, 2087, 2121, 2088,  908,  907, 2089,
+     2090, 2090, 2090, 2129, 2091, 2091, 2091, 2147, 2147, 2147,
+      904, 2148,  903,  902, 2149, 2093, 2093, 2093,  901, 2094,
+      900, 2092, 2095, 2150, 2150, 2150, 2097, 2097, 2097, 2152,
+     2152, 2152,  899, 2153,  896,  895, 2154,  894, 2099, 2099,
+
+     2099, 2151, 2100, 2098,  884, 2101, 2102, 2102, 2102,  883,
+     2103,  882,  881, 2104, 2106, 2106, 2106, 2156, 2156, 2156,
+     2158, 2158, 2158, 2160, 2160, 2160, 2162, 2162, 2162, 2164,
+     2164, 2164,  880,  877, 2157, 2802, 2802, 2802, 2159,  876,
+     2161,  875,  874, 2163,  864,  863, 2165, 2166, 2167, 2113,
+     2113, 2113, 2802, 2168, 2168, 2168, 2116, 2116, 2116,  862,
+     2117,  861,  858, 2118, 2170, 2170, 2170, 2114,  857,  856,
+     2169, 2172, 2172, 2172, 2174, 2174, 2174, 1182, 1182, 1182,
+      855, 2171, 2177, 2177, 2177, 2124, 2124, 2124, 2173, 2125,
+      844, 2175, 2126,  843,  840, 1184, 2179, 2179, 2179, 2178,
+
+     2128, 2128, 2128, 2147, 2147, 2147,  836, 2148,  805,  835,
+     2149,  827,  826, 2180, 2150, 2150, 2150,  825, 2129, 2176,
+     2152, 2152, 2152,  824, 2153,  823,  820, 2154, 2156, 2156,
+     2156,  819, 2151, 2199, 2199, 2199,  811, 2200,  810,  809,
+     2201, 2158, 2158, 2158,  807, 2157, 2160, 2160, 2160, 2202,
+     2202, 2202,  806, 2203,  803,  802, 2204,  801,  800, 2159,
+     2162, 2162, 2162, 2161, 2205, 2205, 2205,  799, 2206,  792,
+      790, 2207, 2164, 2164, 2164,  789,  788, 2163, 2208, 2208,
+     2208,  787, 2209,  784,  783, 2210, 2211, 2211, 2211, 2165,
+     2213, 2213, 2213, 2168, 2168, 2168,  781, 2215, 2215, 2215,
+
+      774, 2216,  773, 2212, 2217,  770,  769, 2214,  767,  766,
+     2169, 2170, 2170, 2170, 2218, 2218, 2218,  765, 2219,  764,
+      763, 2220, 2172, 2172, 2172, 2221, 2221, 2221, 2171, 2222,
+      761,  760, 2223, 2174, 2174, 2174, 2224, 2224, 2224, 2173,
+     2225,  759,  756, 2226, 1182, 1182, 1182, 2177, 2177, 2177,
+     2175, 2228, 2228, 2228,  755, 2229,  754,  752, 2230, 2179,
+     2179, 2179, 1184,  749, 2178, 2231, 2231, 2231,  748, 2232,
+      744,  743, 2233, 2250, 2250, 2250, 2180, 2252, 2252, 2252,
+      742, 2199, 2199, 2199,  741, 2200,  740, 2227, 2201,  739,
+     2251, 1391, 2202, 2202, 2202,  738, 2203,  736,  735, 2204,
+
+     2205, 2205, 2205,  734, 2206,  733,  732, 2207, 2208, 2208,
+     2208,  731, 2209,  730,  729, 2210, 2211, 2211, 2211, 2253,
+     2253, 2253,  728, 2254,  727,  726, 2255, 2213, 2213, 2213,
+     2256, 2256, 2256, 2212, 2257,  721,  718, 2258, 2215, 2215,
+     2215,  720, 2216,  716, 2214, 2217, 2218, 2218, 2218,  715,
+     2219,  484,  483, 2220, 2221, 2221, 2221,  709, 2222,  706,
+      705, 2223, 2224, 2224, 2224,  704, 2225,  703,  702, 2226,
+     1182, 1182, 1182, 2228, 2228, 2228,  701, 2229,  698,  696,
+     2230,  690, 2231, 2231, 2231,  689, 2232,  688, 1184, 2233,
+     2265, 2265, 2265, 2273, 2273, 2273, 2250, 2250, 2250, 2276,
+
+     2276, 2276,  687, 2277,  686,  685, 2278,  684,  980,  683,
+      682,  980,  680, 2251, 1391,  672,  671, 1391, 2252, 2252,
+     2252,  670, 2253, 2253, 2253, 2259, 2254,  669,  666, 2255,
+     2256, 2256, 2256,  665, 2257,  664,  662, 2258, 2279, 2279,
+     2279, 2285, 2285, 2285, 2265, 2265, 2265, 2287, 2287, 2287,
+     2288, 2288, 2288, 2273, 2273, 2273, 2280,  653,  650,  980,
+      649,  648,  980,  647,  646,  980,  645,  644,  980,  642,
+      636,  980, 2295, 2295, 2295,  635,  634, 2286, 2276, 2276,
+     2276,  633, 2277,  632,  631, 2278, 2294,  630,  629,  628,
+      980, 2279, 2279, 2279,  627,  625, 1391,  619,  618, 2296,
+
+     1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 2280,
+      617, 1389, 2300, 2300, 2300,  616, 1389, 1389, 1389, 1391,
+     1389,  615,  614,  613,  612,  611,  609,  601,  600,  599,
+      980, 2301, 2301, 2301, 2302, 2302, 2302,  595, 1389, 1389,
+     1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389,  980,
+      593, 1389,  980, 2285, 2285, 2285, 1389, 1389, 1389, 1391,
+     1389,  586, 2287, 2287, 2287, 2288, 2288, 2288,  585,  584,
+      583,  980, 2308, 2308, 2308, 2312, 2312, 2312, 1389, 1389,
+      980,  580,  578,  980,  572,  571, 2304, 2295, 2295, 2295,
+      980,  569,  568,  980,  554, 2306,  551,  548, 2307, 2316,
+
+     2316, 2316,  547,  545,  538,  980,  537,  536,  535,  533,
+      531,  530, 2300, 2300, 2300,  529,  528,  980,  526,  524,
+     2314, 1389, 1389, 1389, 1389, 1389, 2317, 1389, 1389, 1389,
+      980,  523, 1389, 2338, 2338, 2338,  520, 1389, 1389, 1389,
+     1391, 1389,  519,  517,  515, 2318,  514,  513,  511,  509,
+      508,  980, 2301, 2301, 2301, 2302, 2302, 2302,  507, 1389,
+     1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 2317,
+      980,  505, 1389,  980, 2308, 2308, 2308, 1389, 1389, 1389,
+     1391, 1389,  498,  495,  494, 2319,  492,  490, 2320,  484,
+      483,  484,  980, 2312, 2312, 2312, 2316, 2316, 2316, 1389,
+
+     1389, 2344, 2344, 2344, 2338, 2338, 2338, 2326,  483,  482,
+      481,  980, 2802, 2802,  980, 2344, 2344, 2344, 2802,  980,
+     2802, 2802,  980, 2363, 2363, 2363, 2330, 2802, 2802, 2334,
+     2802, 2802, 2802,  980, 2367, 2367, 2367, 2355, 2363, 2363,
+     2363,  980, 2367, 2367, 2367, 2391, 2391, 2391, 2361, 2399,
+     2399, 2399,  980, 2802, 2802, 2802,  980, 2802, 2802, 2802,
+      980, 2802, 2802,  980, 2407, 2407, 2407,  980, 2410, 2410,
+     2410, 2380, 2391, 2391, 2391, 2384, 2408, 2802, 2802, 2409,
+     2802, 2802,  980, 2411, 2411, 2411,  980, 2414, 2414, 2414,
+      980, 2399, 2399, 2399, 2802, 2417, 2802, 2802, 2418, 2802,
+
+     2802,  980, 2419, 2419, 2419,  980, 2422, 2422, 2422,  980,
+     2423, 2423, 2423, 2424, 2424, 2424, 2802, 2802, 2802, 2802,
+      980, 2434, 2434, 2434,  980, 2407, 2407, 2407,  980, 2426,
+     2802,  980, 2427, 2410, 2410, 2410, 2802, 2430, 2802,  980,
+     2431, 2802, 2802,  980, 2802, 2411, 2411, 2411, 2802, 2432,
+     2802,  980, 2433, 2414, 2414, 2414, 2438, 2438, 2438, 2802,
+     2419, 2419, 2419,  980, 2441, 2802, 2802, 2442, 2802, 2802,
+     2802,  980, 2802, 2802,  980, 2444, 2444, 2444,  980, 2802,
+     2422, 2422, 2422, 2802, 2445, 2802, 2436, 2446, 2423, 2423,
+     2423, 2802, 2447,  980, 2802, 2448, 2802, 2802,  980, 2802,
+
+     2424, 2424, 2424, 2802, 2449, 2802,  980, 2450, 2434, 2434,
+     2434, 2802, 2460, 2802, 2802, 2461, 2802, 2802,  980, 2802,
+     2438, 2438, 2438, 2802, 2465, 2802,  980, 2466, 2444, 2444,
+     2444, 2802, 2472, 2802, 2802, 2473, 2802, 2802,  980, 2480,
+     2480, 2480, 2491, 2491, 2491, 2802,  980, 2480, 2480, 2480,
+     2802, 2509, 2802, 2802, 2510, 2802, 2802,  980, 2802, 2802,
+      980, 2802, 2491, 2491, 2491,  980, 2521, 2802, 2802, 2522,
+     2524, 2524, 2524, 2531, 2531, 2531, 2802, 2524, 2524, 2524,
+      980, 2555, 2802, 2802, 2556, 2531, 2531, 2531,  980, 2563,
+     2802,  980, 2564, 2802, 2802,  980, 2620, 2620, 2620, 2802,
+
+     2620, 2620, 2620,  980, 2653, 2802, 2802, 2654, 2708, 2708,
+     2708, 2722, 2722, 2722,  980, 2734, 2734, 2734,  980, 2708,
+     2708, 2708, 2736, 2736, 2736, 2802, 2709, 2802, 2802, 2723,
+     2738, 2738, 2738, 2735, 2722, 2722, 2722, 2709, 2802, 2802,
+     2737, 2748, 2748, 2748, 2753, 2753, 2753, 2802, 2739, 2755,
+     2755, 2755, 2723, 2757, 2757, 2757, 2734, 2734, 2734, 2749,
+     2802, 2802, 2754, 2736, 2736, 2736, 2802, 2756, 2738, 2738,
+     2738, 2758, 2802, 2802, 2735, 2761, 2761, 2761, 2769, 2769,
+     2769, 2737, 2748, 2748, 2748, 2802, 2739, 2773, 2773, 2773,
+     2753, 2753, 2753, 2762, 2802, 2802, 2770, 2755, 2755, 2755,
+
+     2749, 2757, 2757, 2757, 2802, 2774, 2802, 2802, 2754, 2761,
+     2761, 2761, 2769, 2769, 2769, 2756, 2773, 2773, 2773, 2758,
+     2783, 2783, 2783, 2785, 2785, 2785, 2802, 2762, 2802, 2802,
+     2770, 2783, 2783, 2783, 2774, 2785, 2785, 2785, 2784, 2802,
+     2802, 2786, 2793, 2793, 2793, 2795, 2795, 2795, 2802, 2784,
+     2793, 2793, 2793, 2786, 2795, 2795, 2795, 2800, 2800, 2800,
+     2794, 2802, 2802, 2796, 2800, 2800, 2800, 2802, 2794, 2802,
+     2802, 2802, 2796, 2802, 2802, 2801, 2802, 2802, 2802, 2802,
+     2802, 2802, 2801,  148,  148,  148,  148,  148,  148,  148,
+      148,  148,  149,  149,  149,  149,  149,  149,  149,  149,
+
+      149,  154,  154,  154,  154,  154,  154,  154,  154,  154,
+      157,  157,  157,  157,  157,  157,  157,  157,  157,  160,
+      160,  160,  160,  160,  160,  160,  160,  160,  163,  163,
+      163,  163,  163,  163,  163,  163,  163,  170,  170,  170,
+      170,  170,  170,  170,  170,  170,  174,  174,  174,  174,
+      174,  174,  174,  174,  174,  179,  179,  179,  179,  179,
+      179,  179,  179,  179,  187,  187,  187,  187,  187,  187,
+      187,  187,  187,  196,  196,  196,  196,  196,  196,  196,
+      196,  196,  202,  202,  202,  202,  202,  202,  202,  202,
+      202,  209,  209,  209,  209,  209,  209,  209,  209,  209,
+
+      215,  215,  215,  215,  215,  215,  215,  215,  215,  230,
+      230,  230,  230,  230,  230,  230,  230,  230,  236,  236,
+      236,  236,  236,  236,  236,  236,  236,  243,  243,  243,
+      243,  243,  243,  243,  243,  243,  260,  260,  260,  260,
+      260,  260,  260,  260,  260,  267,  267,  267,  267,  267,
+      267,  267,  267,  267,  275,  275,  275,  275,  275,  275,
+      275,  275,  275,  281,  281,  281,  281,  281,  281,  281,
+      281,  281,  287,  287,  287,  287,  287,  287,  287,  287,
+      287,  295,  295,  295,  295,  295,  295,  295,  295,  295,
+      302,  302,  302,  302,  302,  302,  302,  302,  302,  320,
+
+      320,  320,  320,  320,  320,  320,  320,  320,  338,  338,
+      338,  338,  338,  338,  338,  338,  338,  359,  359,  359,
+      359,  359,  359,  359,  359,  359,  381,  381,  381,  381,
+      381,  381,  381,  381,  381,  403,  403,  403,  403,  403,
+      403,  403,  403,  403,  424,  424,  424,  424,  424,  424,
+      424,  424,  424,  445,  445,  445,  445,  445,  445,  445,
+      445,  445,  467,  467,  467,  467,  467,  467,  467,  467,
+      467,  470,  470,  470,  470,  470,  470,  470,  470,  470,
+      493,  493,  493, 2802, 2802, 2802,  493,  506,  506,  506,
+     2802, 2802, 2802,  506,  512,  512,  512, 2802, 2802, 2802,
+
+      512,  518,  518,  518, 2802, 2802, 2802,  518,  527,  527,
+      527, 2802, 2802, 2802,  527,  534,  534,  534, 2802, 2802,
+     2802,  534,  546,  546,  546, 2802, 2802, 2802,  546,  555,
+      555,  555, 2802, 2802, 2802,  555,  570,  570,  570, 2802,
+     2802, 2802,  570,  579,  579,  579, 2802, 2802, 2802,  579,
+      594,  594,  594, 2802, 2802, 2802,  594,  610,  610,  610,
+     2802, 2802, 2802,  610,  626,  626,  626, 2802, 2802, 2802,
+      626,  643,  643,  643, 2802, 2802, 2802,  643,  663,  663,
+      663, 2802, 2802, 2802,  663,  681,  681,  681, 2802, 2802,
+     2802,  681,  697,  697,  697, 2802, 2802, 2802,  697,  717,
+
+      717,  717,  717,  717,  717,  717, 2802,  717,  737, 2802,
+     2802, 2802,  737,  747, 2802, 2802, 2802,  747,  753, 2802,
+     2802, 2802,  753,  762, 2802, 2802, 2802,  762,  768, 2802,
+     2802, 2802,  768,  782, 2802, 2802, 2802,  782,  791, 2802,
+     2802, 2802,  791,  808, 2802, 2802, 2802,  808,  818, 2802,
+     2802, 2802,  818,  834, 2802, 2802, 2802,  834,  854, 2802,
+     2802, 2802,  854,  873, 2802, 2802, 2802,  873,  893, 2802,
+     2802, 2802,  893,  643,  643,  643, 2802, 2802, 2802,  643,
+      915, 2802, 2802, 2802,  915,  663,  663,  663, 2802, 2802,
+     2802,  663,  935, 2802, 2802, 2802,  935,  681,  681,  681,
+
+     2802, 2802, 2802,  681,  953, 2802, 2802, 2802,  953,  697,
+      697,  697, 2802, 2802, 2802,  697,  975, 2802, 2802, 2802,
+      975,  979,  979,  979,  979,  979,  979,  979,  979,  979,
+      985, 2802, 2802, 2802, 2802,  985,  493,  493,  493, 2802,
+     2802, 2802,  493,  999,  999,  999,  999, 2802, 2802,  999,
+      999,  506,  506,  506, 2802, 2802, 2802,  506, 1012, 1012,
+     1012, 1012, 2802, 2802, 1012, 1012,  512,  512,  512, 2802,
+     2802, 2802,  512, 1022, 1022, 1022, 1022, 2802, 2802, 1022,
+     1022,  518,  518,  518, 2802, 2802, 2802,  518, 1034, 1034,
+     1034, 1034, 2802, 2802, 1034, 1034,  527,  527,  527, 2802,
+
+     2802, 2802,  527, 1042, 1042, 1042, 1042, 2802, 2802, 1042,
+     1042,  534,  534,  534, 2802, 2802, 2802,  534, 1053, 1053,
+     1053, 1053, 2802, 2802, 1053, 1053,  546,  546,  546, 2802,
+     2802, 2802,  546, 1067, 1067, 1067, 1067, 2802, 2802, 1067,
+     1067, 1080, 1080, 1080, 1080, 2802, 2802, 1080, 1080,  570,
+      570,  570, 2802, 2802, 2802,  570, 1086, 1086, 1086, 1086,
+     2802, 2802, 1086, 1086,  579,  579,  579, 2802, 2802, 2802,
+      579, 1099, 1099, 1099, 1099, 2802, 2802, 1099, 1099,  594,
+      594,  594, 2802, 2802, 2802,  594, 1110, 1110, 1110, 1110,
+     2802, 2802, 1110, 1110,  610,  610,  610, 2802, 2802, 2802,
+
+      610, 1127, 1127, 1127, 1127, 2802, 2802, 1127, 1127,  626,
+      626,  626, 2802, 2802, 2802,  626, 1146, 1146, 1146, 1146,
+     2802, 2802, 1146, 1146,  643,  643,  643, 2802, 2802, 2802,
+      643, 1166, 1166, 1166, 1166, 2802, 2802, 1166, 1166,  663,
+      663,  663, 2802, 2802, 2802,  663, 1183, 1183, 1183, 1183,
+     2802, 2802, 1183, 1183,  681,  681,  681, 2802, 2802, 2802,
+      681, 1198, 1198, 1198, 1198, 2802, 2802, 1198, 1198,  697,
+      697,  697, 2802, 2802, 2802,  697, 1218, 1218, 1218, 1218,
+     2802, 2802, 1218, 1218,  979,  979,  979,  979,  979,  979,
+      979,  979,  979,  985, 2802,  985, 2802, 2802,  985,  493,
+
+      493,  493, 2802, 2802, 2802,  493,  999,  999,  999,  999,
+     2802, 2802,  999,  999,  506,  506,  506, 2802, 2802, 2802,
+      506, 1012, 1012, 1012, 1012, 2802, 2802, 1012, 1012,  512,
+      512,  512, 2802, 2802, 2802,  512, 1022, 1022, 1022, 1022,
+     2802, 2802, 1022, 1022,  518,  518,  518, 2802, 2802, 2802,
+      518, 1034, 1034, 1034, 1034, 2802, 2802, 1034, 1034,  527,
+      527,  527, 2802, 2802, 2802,  527, 1042, 1042, 1042, 1042,
+     2802, 2802, 1042, 1042,  534,  534,  534, 2802, 2802, 2802,
+      534, 1053, 1053, 1053, 1053, 2802, 2802, 1053, 1053,  546,
+      546,  546, 2802, 2802, 2802,  546, 1067, 1067, 1067, 1067,
+
+     2802, 2802, 1067, 1067, 1080, 1080, 1080, 1080, 2802, 2802,
+     1080, 1080,  570,  570,  570, 2802, 2802, 2802,  570, 1086,
+     1086, 1086, 1086, 2802, 2802, 1086, 1086,  579,  579,  579,
+      579, 2802,  579, 2802,  579, 1099, 1099, 1099, 1099, 2802,
+     2802, 1099, 1099,  594,  594,  594, 2802, 2802, 2802,  594,
+     1110, 1110, 1110, 1110, 2802, 2802, 1110, 1110,  610,  610,
+      610, 2802, 2802, 2802,  610, 1127, 1127, 1127, 1127, 2802,
+     2802, 1127, 1127,  626,  626,  626, 2802, 2802, 2802,  626,
+     1146, 1146, 1146, 1146, 2802, 2802, 1146, 1146,  643,  643,
+      643,  643, 2802,  643, 2802,  643, 1166, 1166, 1166, 1166,
+
+     2802, 2802, 1166, 1166,  663,  663,  663,  663, 2802,  663,
+     2802,  663, 1183, 1183, 1183, 1183, 2802, 2802, 1183, 1183,
+      681,  681,  681, 2802, 2802, 2802,  681, 1198, 1198, 1198,
+     1198, 2802, 2802, 1198, 1198,  697,  697,  697, 2802, 2802,
+     2802,  697, 1218, 1218, 1218, 1218, 2802, 2802, 1218, 1218,
+      979,  979,  979,  979,  979,  979,  979,  979,  979, 1389,
+     1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389,  493,  493,
+      493,  493, 2802,  493, 2802,  493,  999,  999,  999,  999,
+     2802, 2802,  999,  999,  506,  506,  506, 2802, 2802, 2802,
+      506, 1012, 1012, 1012, 1012, 2802, 2802, 1012, 1012,  512,
+
+      512,  512,  512, 2802,  512, 2802,  512, 1022, 1022, 1022,
+     1022, 2802, 2802, 1022, 1022,  518,  518,  518,  518, 2802,
+      518, 2802,  518, 1034, 1034, 1034, 1034, 2802, 2802, 1034,
+     1034,  527,  527,  527, 2802, 2802, 2802,  527, 1042, 1042,
+     1042, 1042, 2802, 2802, 1042, 1042,  534,  534,  534, 2802,
+     2802, 2802,  534, 1053, 1053, 1053, 1053, 2802, 2802, 1053,
+     1053,  546,  546,  546, 2802, 2802, 2802,  546, 1067, 1067,
+     1067, 1067, 2802, 2802, 1067, 1067, 1080, 1080, 1080, 1080,
+     2802, 2802, 1080, 1080,  570,  570,  570, 2802, 2802, 2802,
+      570, 1086, 1086, 1086, 1086, 2802, 2802, 1086, 1086,  579,
+
+      579,  579,  579, 2802,  579, 2802,  579, 1099, 1099, 1099,
+     1099, 2802, 2802, 1099, 1099,  594,  594,  594,  594, 2802,
+      594, 2802,  594, 1110, 1110, 1110, 1110, 2802, 2802, 1110,
+     1110,  610,  610,  610, 2802, 2802, 2802,  610, 1127, 1127,
+     1127, 1127, 2802, 2802, 1127, 1127,  626,  626,  626, 2802,
+     2802, 2802,  626, 1146, 1146, 1146, 1146, 2802, 2802, 1146,
+     1146,  643,  643,  643, 2802, 2802, 2802,  643, 1166, 1166,
+     1166, 1166, 2802, 2802, 1166, 1166,  663,  663,  663, 2802,
+     2802, 2802,  663, 1183, 1183, 1183, 1183, 2802, 2802, 1183,
+     1183,  681,  681,  681,  681, 2802,  681, 2802,  681, 1198,
+
+     1198, 1198, 1198, 2802, 2802, 1198, 1198,  697,  697,  697,
+     2802, 2802, 2802,  697, 1218, 1218, 1218, 1218, 2802, 2802,
+     1218, 1218,  979,  979,  979,  979,  979,  979,  979,  979,
+      979, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389, 1389,
+      493,  493,  493, 2802, 2802, 2802,  493,  999,  999,  999,
+      999, 2802, 2802,  999,  999,  506,  506,  506, 2802, 2802,
+     2802,  506, 1012, 1012, 1012, 1012, 2802, 2802, 1012, 1012,
+     1022, 1022, 1022, 1022, 2802, 2802, 1022, 1022,  518,  518,
+      518,  518, 2802,  518, 2802,  518, 1034, 1034, 1034, 1034,
+     2802, 2802, 1034, 1034,  527,  527,  527,  527, 2802,  527,
+
+     2802,  527, 1042, 1042, 1042, 1042, 2802, 2802, 1042, 1042,
+      534,  534,  534, 2802, 2802, 2802,  534, 1053, 1053, 1053,
+     1053, 2802, 2802, 1053, 1053,  546,  546,  546,  546, 2802,
+      546, 2802,  546, 1067, 1067, 1067, 1067, 2802, 2802, 1067,
+     1067, 1080, 1080, 1080, 1080, 2802, 2802, 1080, 1080,  570,
+      570,  570, 2802, 2802, 2802,  570, 1086, 1086, 1086, 1086,
+     2802, 2802, 1086, 1086,  579,  579,  579, 2802, 2802, 2802,
+      579, 1099, 1099, 1099, 1099, 2802, 2802, 1099, 1099,  594,
+      594,  594, 2802, 2802, 2802,  594, 1110, 1110, 1110, 1110,
+     2802, 2802, 1110, 1110,  610,  610,  610,  610, 2802,  610,
+
+     2802,  610, 1127, 1127, 1127, 1127, 2802, 2802, 1127, 1127,
+      626,  626,  626, 2802, 2802, 2802,  626, 1146, 1146, 1146,
+     1146, 2802, 2802, 1146, 1146,  643,  643,  643, 2802, 2802,
+     2802,  643, 1166, 1166, 1166, 1166, 2802, 2802, 1166, 1166,
+      663,  663,  663, 2802, 2802, 2802,  663, 1183, 1183, 1183,
+     1183, 2802, 2802, 1183, 1183,  681,  681,  681, 2802, 2802,
+     2802,  681, 1198, 1198, 1198, 1198, 2802, 2802, 1198, 1198,
+      697,  697,  697, 2802, 2802, 2802,  697, 1218, 1218, 1218,
+     1218, 2802, 2802, 1218, 1218,  979,  979,  979,  979,  979,
+      979,  979,  979,  979, 1389, 1389, 1389, 1389, 1389, 1389,
+
+     1389, 1389, 1389,  493,  493,  493, 2802, 2802, 2802,  493,
+      999,  999,  999,  999, 2802, 2802,  999,  999,  506,  506,
+      506, 2802, 2802, 2802,  506, 1012, 1012, 1012, 1012, 2802,
+     2802, 1012, 1012, 1022, 1022, 1022, 1022, 2802, 2802, 1022,
+     1022,  518,  518,  518, 2802, 2802, 2802,  518,  527,  527,
+      527,  527, 2802,  527, 2802,  527, 1042, 1042, 1042, 1042,
+     2802, 2802, 1042, 1042,  534,  534,  534, 2802, 2802, 2802,
+      534, 1053, 1053, 1053, 1053, 2802, 2802, 1053, 1053,  546,
+      546,  546, 2802, 2802, 2802,  546, 1067, 1067, 1067, 1067,
+     2802, 2802, 1067, 1067, 1080, 1080, 1080, 1080, 2802, 2802,
+
+     1080, 1080,  570,  570,  570, 2802, 2802, 2802,  570, 1086,
+     1086, 1086, 1086, 2802, 2802, 1086, 1086,  579,  579,  579,
+      579, 2802,  579, 2802,  579, 1099, 1099, 1099, 1099, 2802,
+     2802, 1099, 1099,  594,  594,  594,  594, 2802,  594, 2802,
+      594, 1110, 1110, 1110, 1110, 2802, 2802, 1110, 1110,  610,
+      610,  610,  610, 2802,  610, 2802,  610, 1127, 1127, 1127,
+     1127, 2802, 2802, 1127, 1127,  626,  626,  626,  626, 2802,
+      626, 2802,  626, 1146, 1146, 1146, 1146, 2802, 2802, 1146,
+     1146,  643,  643,  643,  643, 2802,  643, 2802,  643, 1166,
+     1166, 1166, 1166, 2802, 2802, 1166, 1166,  663,  663,  663,
+
+      663, 2802,  663, 2802,  663, 1183, 1183, 1183, 1183, 2802,
+     2802, 1183, 1183,  681,  681,  681,  681, 2802,  681, 2802,
+      681,  697,  697,  697, 2802, 2802, 2802,  697, 1218, 1218,
+     1218, 1218, 2802, 2802, 1218, 1218,  979,  979,  979,  979,
+      979,  979,  979,  979,  979, 1389, 1389, 1389, 1389, 1389,
+     1389, 1389, 1389, 1389,  493,  493,  493,  493, 2802,  493,
+     2802,  493,  506,  506,  506, 2802, 2802, 2802,  506, 1012,
+     1012, 1012, 1012, 2802, 2802, 1012, 1012, 2298, 2298, 2298,
+     2298, 2298, 2298, 2298, 2298, 2298, 2299, 2299, 2299, 2299,
+     2299, 2299, 2299, 2299, 2299,  147, 2802, 2802, 2802, 2802,
+
+     2802, 2802, 2802, 2802, 2802, 2802, 2802, 2802, 2802, 2802,
+     2802, 2802, 2802, 2802, 2802, 2802, 2802, 2802, 2802, 2802,
+     2802, 2802, 2802, 2802, 2802, 2802, 2802, 2802, 2802, 2802,
+     2802, 2802, 2802, 2802, 2802, 2802, 2802, 2802, 2802, 2802,
+     2802, 2802, 2802, 2802, 2802, 2802, 2802, 2802, 2802, 2802,
+     2802, 2802, 2802, 2802, 2802, 2802, 2802, 2802, 2802, 2802,
+     2802
+    } ;
+
+static yyconst short int yy_chk[9962] =
+    {   0,
+        0,    3,    3,    3,    4,    4,    4,    5,    5,    5,
+        6,    6,    6,    7,    7,    7,   11,    3,    9,   12,
+        4,   10,    0,    5,    0,    9,    6,  477,   10,    7,
+        8,    8,    8,  152,   11,   13,   13,   12,   14,   14,
+       13,   13,  477,   14,   14,  153,    8,   17,   17,  152,
+       13,   15,   15,   14,   15,  156,   15,   16,   16,  398,
+       16,  153,   16,   18,   18,  398,   15,   19,   19,   19,
+     1388,  156,   16,   20,   20,   20,   23,   23,   23,   24,
+       24,   24,  272,   19,   17,  150,  150,  150, 1388,   20,
+      272,  313,   23,  636,  636,   24,  151,  151,  151,  313,
+
+       18,   21,   21,   21,   21,   21,   21,   21,   21,   21,
+       21,   21,   21,   21,   21,   21, 1398,   21,   21,   21,
+       21,   21,   25,   25,   25, 1400,   26,   26,   26,   27,
+       27,   27,   28,   28,   28,   29,   29,   29,   25,   21,
+       21,   21,   26,  180, 1401,   27,   21,  184,   28, 1131,
+     1131,   29,   21,  155,  155,  155,  177,  177,  177,  180,
+      184,   21,   22,   22,   22,   22,   22,   22,   22,   22,
+       22,   22,   22,   22,   22,   22,   22, 1402,   22,   22,
+       22,   22,   22,   30,   30,   30, 1404,   31,   31,   31,
+       32,   32,   32,   33,   33,   33,   34,   34,   34,   30,
+
+       22,   22,   22,   31,  191,  197,   32,   22,  701,   33,
+      701,  191,   34,   22,  188,  188,  188,  194,  194,  194,
+      191,  197,   22,   35,   35,   35,   35,   35,   35,   35,
+       35,   35,   35,   35,   35,   35,   35,   35, 1407,   35,
+       35,   35,   35,   35,   37,   37,   37, 1408,   38,   38,
+       38,   39,   39,   39,   40,   40,   40,  203,  203,  203,
+       37,   35,   35,   35,   38, 1435,  486,   39,   35,  486,
+       40,   35,   36,   36,   36,   36,   36,   36,   36,   36,
+       36,   36,   36,   36,   36,   36,   36, 1436,   36,   36,
+       36,   36,   36,   43,   43,   43, 1437,   44,   44,   44,
+
+       45,   45,   45,   46,   46,   46,  207,  207,  207,   43,
+       36,   36,   36,   44,  565, 1438,   45,   36,  565,   46,
+       36,   41,   41,   41,   41,   41,   41,   41,   41,   41,
+       41,   41,   41,   41,   41,   41, 1449,   41,   41,   41,
+       41,   41,   49,   49,   49,   50,   50,   50,   51,   51,
+       51,   52,   52,   52,  216,  216,  216, 1450,   49,   41,
+       41,   50,  982, 1451,   51,   41,  982,   52, 1453,   41,
+       41,   42,   42,   42,   42,   42,   42,   42,   42,   42,
+       42,   42,   42,   42,   42,   42, 1454,   42,   42,   42,
+       42,   42,   55,   55,   55,   56,   56,   56,   57,   57,
+
+       57,   58,   58,   58,  220,  220,  220, 1455,   55,   42,
+       42,   56, 1137, 1137,   57,   42, 1456,   58, 1459,   42,
+       42,   47,   47,   47,   47,   47,   47,   47,   47,   47,
+       47,   47,   47,   47,   47,   47,   47,   47,   47,   47,
+       47,   47,   47,   47,   47,   47,   47,   47,   47,   47,
+       47,   47,   47,   47,   47,   47,   47,   47,   47,   47,
+       47,   47,   47,   47,   47,   47,   47,   47,   47,   47,
+       47,   47,   47,   47,   47,   47,   47,   47,   47,   47,
+       47,   47,   47,   47,   47,   47,   53,   53,   53,   53,
+       53,   53,   53,   53,   53,   53,   53,   53,   53,   53,
+
+       53, 1468,   53,   53,   53,   53,   53,   61,   61,   61,
+     1469,   62,   62,   62,  400,   63,   63,   63,   64,   64,
+       64,  192,  400,   61,   53,   53,   53,   62,  204,  210,
+       53,   63,  787, 1470,   64,  204,  456,  192,   53,  192,
+      231,  231,  231,  456,  204,  210,  787,   53,   54,   54,
+       54,   54,   54,   54,   54,   54,   54,   54,   54,   54,
+       54,   54,   54, 1471,   54,   54,   54,   54,   54,   65,
+       65,   65, 1478,   66,   66,   66,  416,   67,   67,   67,
+       68,   68,   68,  205,  416,   65,   54,   54,   54,   66,
+      217,  223,   54,   67,  788, 1479,   68,  217, 1503,  205,
+
+       54,  234,  234,  234,  205, 1508,  217,  223,  788,   54,
+       59,   59,   59,   59,   59,   59,   59,   59,   59,   59,
+       59,   59,   59,   59,   59,   59,   59,   59,   59,   59,
+       59,   59,   59,   59,   59,   59,   59,   59,   59,   59,
+       59,   59,   59,   59,   59,   59,   59,   59,   59,   59,
+       59,   59,   59,   59,   59,   59,   59,   59,   59,   59,
+       59,   59,   59,   59,   59,   59,   59,   59,   59,   59,
+       59,   59,   59,   59,   59,   69,   69,   69,   70,   70,
+       70,  244,  244,  244,  248,  248,  248,  261,  261,  261,
+     1511,   69, 1495, 1495,   70,   71,   71,   71,   71,   71,
+
+       71,   71,   71,   71,   71,   71,   71,   71,   71,   71,
+     1519,   71,   71,   71,   71,   71,   73,   73,   73,   74,
+       74,   74,   75,   75,   75,   76,   76,   76,   77,   77,
+       77,  218,   73,   71,   71,   74,  227,  421,   75,  237,
+      719,   76,   71,   71,   77,  421,   71,  218,  265,  265,
+      265,  227,  719,  218, 1524,  237,   71,   72,   72,   72,
+       72,   72,   72,   72,   72,   72,   72,   72,   72,   72,
+       72,   72, 1525,   72,   72,   72,   72,   72,   78,   78,
+       78,   81,   81,   81,   82,   82,   82,   83,   83,   83,
+       84,   84,   84,  251,   78,   72,   72,   81,  268,  463,
+
+       82, 1526, 1529,   83,   72,   72,   84,  463,   72,  251,
+      276,  276,  276, 1534,  268,  279,  279,  279,   72,   79,
+       79,   79,   79,   79,   79,   79,   79,   79,   79,   79,
+       79,   79,   79,   79, 1535,   79,   79,   79,   79,   79,
+       85,   85,   85,   86,   86,   86,   87,   87,   87,   88,
+       88,   88,   89,   89,   89,  259,   85,   79,   79,   86,
+      232,  282,   87,  245, 1536,   88, 1537,  232,   89, 1538,
+      245,  259,  288,  288,  288, 1539,  232,  282, 1540,  245,
+      259,   79,   79,   80,   80,   80,   80,   80,   80,   80,
+       80,   80,   80,   80,   80,   80,   80,   80, 1543,   80,
+
+       80,   80,   80,   80,   90,   90,   90,   93,   93,   93,
+       94,   94,   94,   95,   95,   95,   96,   96,   96,  274,
+       90,   80,   80,   93,  263,  296,   94,  277,  310,   95,
+     1547,  263,   96, 1558,  277,  274,  293,  293,  293, 1562,
+      263,  296,  274,  277,  310,   80,   80,   91,   91,   91,
+       91,   91,   91,   91,   91,   91,   91,   91,   91,   91,
+       91,   91, 1563,   91,   91,   91,   91,   91,   99,   99,
+       99,  100,  100,  100,  101,  101,  101,  102,  102,  102,
+      105,  105,  105,  291,   99,   91,   91,  100,  290, 1571,
+      101, 1572,  328,  102, 1573,  290,  105, 1574, 1575,  291,
+
+      291,   91, 1579,   91,  290,  303,  303,  303,  328,   91,
+       91,   92,   92,   92,   92,   92,   92,   92,   92,   92,
+       92,   92,   92,   92,   92,   92, 1587,   92,   92,   92,
+       92,   92,  106,  106,  106,  107,  107,  107,  108,  108,
+      108,  111,  111,  111,  112,  112,  112,  305,  106,   92,
+       92,  107,  304,  346,  108, 1590,  367,  111, 1592,  304,
+      112, 1597, 1608,  305, 1618,   92, 1619,   92,  304,  346,
+     1625,  305,  367,   92,   92,   97,   97,   97,   97,   97,
+       97,   97,   97,   97,   97,   97,   97,   97,   97,   97,
+       97,   97,   97,   97,   97,   97,   97,   97,   97,   97,
+
+       97,   97,   97,   97,   97,   97,   97,   97,   97,   97,
+       97,   97,   97,   97,   97,   97,   97,   97,   97,   97,
+       97,   97,   97,   97,   97,   97,   97,   97,   97,   97,
+       97,   97,   97,   97,   97,   97,   97,   97,   97,   97,
+      103,  103,  103,  103,  103,  103,  103,  103,  103,  103,
+      103,  103,  103,  103,  103,  103,  103,  103,  103,  103,
+      103,  103,  103,  103,  103,  103,  103,  103,  103,  103,
+      103,  103,  103,  103,  103,  103,  103,  103,  103,  103,
+      103,  103,  103,  103,  103,  103,  103,  103,  103,  103,
+      103,  103,  103,  103,  103,  103,  103,  103,  103,  103,
+
+      103,  103,  103,  103,  103,  109,  109,  109,  109,  109,
+      109,  109,  109,  109,  109,  109,  109,  109,  109,  109,
+      109,  109,  109,  109,  109,  109,  109,  109,  109,  109,
+      109,  109,  109,  109,  109,  109,  109,  109,  109,  109,
+      109,  109,  109,  109,  109,  109,  109,  109,  109,  109,
+      109,  109,  109,  109,  109,  109,  109,  109,  109,  109,
+      109,  109,  109,  109,  109,  109,  109,  109,  109,  109,
+      113,  113,  113,  114,  114,  114,  307,  307,  307,  321,
+      321,  321,  325,  325,  325, 1626,  113, 1627, 1628,  114,
+      115,  115,  115,  115,  115,  115,  115,  115,  115,  115,
+
+      115,  115,  115,  115,  115,  115,  115,  115,  115,  115,
+      115,  115,  115,  115,  115,  115,  115,  115,  115,  115,
+      115,  115,  115,  115,  115,  115,  115,  115,  115,  115,
+      115,  115,  115,  115,  115,  115,  115,  115,  115,  115,
+      115,  115,  115,  115,  115,  115,  115,  115,  115,  115,
+      115,  115,  115,  115,  115,  117,  117,  117,  118,  118,
+      118,  119,  119,  119,  120,  120,  120,  339,  339,  339,
+     1636,  117, 1638, 1639,  118, 1640, 1643,  119, 1725, 1725,
+      120,  121,  121,  121,  121,  121,  121,  121,  121,  121,
+      121,  121,  121,  121,  121,  121,  121,  121,  121,  121,
+
+      121,  121,  121,  121,  121,  121,  121,  121,  121,  121,
+      121,  121,  121,  121,  121,  121,  121,  121,  121,  121,
+      121,  121,  121,  121,  121,  121,  121,  121,  121,  121,
+      121,  121,  121,  121,  121,  121,  121,  121,  121,  121,
+      121,  121,  121,  121,  121,  121,  123,  123,  123,  124,
+      124,  124,  125,  125,  125,  126,  126,  126,  343,  343,
+      343, 1730,  123, 1731, 1732,  124, 1738, 1748,  125, 1753,
+     1760,  126,  127,  127,  127,  127,  127,  127,  127,  127,
+      127,  127,  127,  127,  127,  127,  127,  127,  127,  127,
+      127,  127,  127,  127,  127,  127,  127,  127,  127,  127,
+
+      127,  127,  127,  127,  127,  127,  127,  127,  127,  127,
+      127,  127,  127,  127,  127,  127,  127,  127,  127,  127,
+      127,  127,  127,  127,  127,  127,  127,  127,  127,  127,
+      127,  127,  127,  127,  127,  127,  127,  129,  129,  129,
+      130,  130,  130,  131,  131,  131,  132,  132,  132,  360,
+      360,  360, 1739,  129, 1768, 1776,  130, 1778, 1739,  131,
+     1783, 1784,  132,  133,  133,  133,  133,  133,  133,  133,
+      133,  133,  133,  133,  133,  133,  133,  133,  133,  133,
+      133,  133,  133,  133,  133,  133,  133,  133,  133,  133,
+      133,  133,  133,  133,  133,  133,  133,  133,  133,  133,
+
+      133,  133,  133,  133,  133,  133,  133,  133,  133,  133,
+      133,  133,  133,  133,  133,  133,  133,  133,  133,  133,
+      133,  133,  133,  133,  133,  133,  133,  133,  135,  135,
+      135,  136,  136,  136,  137,  137,  137,  138,  138,  138,
+      364,  364,  364, 1785,  135, 1786, 1862,  136, 1863, 1868,
+      137, 1877, 1878,  138,  139,  139,  139,  139,  139,  139,
+      139,  139,  139,  139,  139,  139,  139,  139,  139,  139,
+      139,  139,  139,  139,  139,  139,  139,  139,  139,  139,
+      139,  139,  139,  139,  139,  139,  139,  139,  139,  139,
+      139,  139,  139,  139,  139,  139,  139,  139,  139,  139,
+
+      139,  139,  139,  139,  139,  139,  139,  139,  139,  139,
+      139,  139,  139,  139,  139,  139,  139,  139,  139,  141,
+      141,  141,  142,  142,  142,  143,  143,  143,  144,  144,
+      144,  145,  145,  166,  175,  141,  145, 1888,  142,  186,
+      190,  143,  146,  146,  144, 1904,  145,  146,  246, 1905,
+      175, 1992, 2001,  189, 2028,  186,  190,  146,  190, 2068,
+      189,  190,  190, 2105,  246,  175, 2155,  166,  145,  189,
+      186,  189,  190,  166,  189,  189,  262,  166, 1392,  146,
+      246, 2001,  166,  262,  341,  189,  257,  257,  257,  258,
+      258,  258,  262,  284,  284,  284,  285,  285,  285,  323,
+
+      341,  262,  341,  257,  322,  340,  258,  300,  300,  300,
+      284,  322,  340,  285,  286,  323, 1580,  301,  301,  301,
+      322,  340, 2073, 2076,  300,  382,  382,  382,  323, 1580,
+      286,  286,  286,  286,  301, 1389, 1740,  286,  286,  318,
+      318,  318,  286,  286,  286,  286,  319,  319,  319,  331,
+      331,  331,  335,  335,  335, 2073,  318,  336,  336,  336,
+      337,  337,  337,  319, 2076,  389,  331,  362,  361,  335,
+      357,  357,  357, 1740,  336,  361, 2130,  337,  358,  358,
+      358,  389, 2513,  362,  361,  384,  362,  357,  379,  379,
+      379, 2513,  331,  383, 2075,  358,  380,  380,  380, 2130,
+
+      383,  384,  386,  386,  386,  379,  401,  401,  401,  383,
+      402,  402,  402,  380,  405,  384,  404,  404,  404,  406,
+      411,  405, 2075,  401,  408,  408,  408,  402,  432,  427,
+      405,  453,  422,  422,  422,  406,  411,  423,  423,  423,
+      425,  425,  425,  426,  432,  427, 1387,  453,  406,  422,
+      426,  429,  429,  429,  423,  443,  443,  443, 1384,  426,
+      427,  444,  444,  444,  446,  446,  446,  447,  448,  450,
+      450,  450,  443,  473,  447,  465,  465,  465,  444, 2079,
+      466,  466,  466,  447,  448,  468,  468,  468,  469,  476,
+      476,  476,  465, 2081, 1870,  469,  448,  466,  485,  485,
+
+      485,  509,  509,  509,  469, 1581, 2182,  473,  514,  514,
+      514, 2079, 2074,  473,  521,  521,  521,  473,  509,  536,
+      536,  536,  473, 1222, 2081,  514,  539,  539,  539, 2083,
+     1581,  521, 1870,  540,  540,  540,  536,  540, 2182, 1222,
+      540, 2074, 2143,  539,  541,  541,  541, 2080,  485,  542,
+      542,  542, 2074,  542, 2078, 1380,  542,  548,  548,  548,
+     2083,  541,  556,  556,  556,  557,  557,  557, 2080,  557,
+     2077, 2084,  557, 2133,  548,  558,  558,  558, 2131,  556,
+      559,  559,  559, 2085,  559, 2143, 2132,  559,  573,  573,
+      573, 2078,  558,  574,  574,  574, 2084,  574, 2133, 2084,
+
+      574,  575,  575,  575, 2077,  573,  576,  576,  576, 2086,
+      576, 2138, 2085,  576,  581,  581,  581, 2131,  575,  587,
+      587,  587,  588,  588,  588, 2132,  588, 2136, 2134,  588,
+     1379,  581,  589,  589,  589, 2137,  587,  590,  590,  590,
+     2183,  590, 2142, 2086,  590,  596,  596,  596, 2139,  589,
+      597,  597,  597, 2134,  597, 2138, 2137,  597,  599,  599,
+      599, 2136,  596,  602,  602,  602,  603,  603,  603, 2139,
+      603, 2142, 2135,  603, 2141,  599,  604,  604,  604, 2183,
+      602,  605,  605,  605, 1378,  605, 1377, 2186,  605,  606,
+      606,  606, 2140,  604,  607,  607,  607, 2141,  607, 2260,
+
+     2144,  607,  614,  614,  614, 2135,  606,  619,  619,  619,
+      620,  620,  620,  621,  621,  621, 2140,  621, 2145,  614,
+      621,  622,  622,  622,  619, 2144, 2186,  620,  623,  623,
+      623, 2188,  623, 2146, 2189,  623, 2260, 2357,  622,  630,
+      630,  630,  637,  637,  637,  638,  638,  638, 2357,  638,
+     2185, 2145,  638,  639,  639,  639,  630, 2181, 2188,  637,
+      640,  640,  640, 2187,  640, 2082, 2146,  640, 2189, 2184,
+      639,  646,  646,  646,  653,  653,  653,  656,  656,  656,
+      657,  657,  657, 2185,  657, 2181, 2082,  657,  646, 2190,
+     2082,  653, 2184, 2191,  656,  658,  658,  658,  659,  659,
+
+      659, 2193,  659, 2187, 2195,  659,  665,  665,  665,  675,
+      675,  675,  658,  676,  676,  676, 1374,  676, 2192, 2234,
+      676, 1371, 2191,  665, 2196, 2193,  675,  677,  677,  677,
+      678,  678,  678, 2190,  678, 2235, 2195,  678,  686,  686,
+      686,  691,  691,  691,  677,  692,  692,  692, 2196,  692,
+     2194, 2236,  692, 2234, 2249,  686, 2235, 2192,  691,  693,
+      693,  693,  694,  694,  694, 2240,  694, 2237, 2238,  694,
+      702,  702,  702,  710,  710,  710,  693,  711,  711,  711,
+     2241,  711, 1370, 2242,  711, 2236, 2303,  702, 2249, 2194,
+      710,  712,  712,  712,  713,  713,  713, 2237,  713, 1356,
+
+     2240,  713,  722,  722,  722, 2241,  722, 2238,  712,  737,
+      737,  737,  738,  738,  738,  745,  745,  745,  746,  746,
+      746, 2243,  746, 2242, 2244,  746, 2245,  737, 2246, 2303,
+      738, 2284,  745,  747,  747,  747,  748,  748,  748,  750,
+      750,  750,  751,  751,  751, 2244,  751, 2245, 2262,  751,
+     2248,  747, 2243, 2246,  748, 1354,  750, 2261,  738,  752,
+      752,  752,  753,  753,  753, 2284,  754,  754,  754,  757,
+      757,  757,  762,  762,  762, 2248,  752,  763,  763,  763,
+      753, 2262, 2263,  748,  754, 2263,  757,  758,  758,  758,
+      762,  758, 2261, 2271,  758,  763,  768,  768,  768,  769,
+
+      769,  769,  771,  771,  771,  772,  772,  772, 2291,  772,
+     2268, 2329,  772, 2305,  768, 2269, 2275,  769, 2272,  771,
+      775,  775,  775, 2291,  775,  754, 2271,  775, 2305,  763,
+      778,  778,  778, 2309,  778, 2290, 2329,  778,  782,  782,
+      782,  783,  783,  783, 2269,  769,  785,  785,  785, 2268,
+      786,  786,  786, 2270,  786, 2272,  782,  786, 2275,  783,
+      791,  791,  791,  785,  792,  792,  792,  793,  793,  793,
+     2292,  793, 2309, 2290,  793,  808,  808,  808,  791,  796,
+      796,  796,  792,  796, 2270, 1353,  796, 2313,  783,  809,
+      809,  809, 2286,  808,  812,  812,  812, 2292,  812, 2296,
+
+     2310,  812, 2313,  792,  815,  815,  815,  809,  815, 2294,
+     2286,  815,  818,  818,  818,  819,  819,  819,  821,  821,
+      821,  822,  822,  822, 2304,  822, 1352, 2294,  822, 1351,
+      818, 2310, 2296,  819, 2311,  821,  828,  828,  828, 2514,
+      828, 2306, 2304,  828,  809,  831,  831,  831, 2514,  831,
+     2317, 2317,  831,  834,  834,  834,  835,  835,  835, 2306,
+      837,  837,  837, 2307,  837, 2311,  819,  837,  841,  841,
+      841,  834, 2340, 2314,  835,  842,  842,  842, 2340,  842,
+     2527, 2307,  842, 2315, 2318,  841,  845,  845,  845, 2527,
+      845, 2314, 2408,  845,  848,  848,  848, 1350,  848, 1349,
+
+     2362,  848, 2318,  851,  851,  851,  835,  851, 2319, 2315,
+      851,  854,  854,  854,  855,  855,  855,  859,  859,  859,
+      860,  860,  860, 2320,  860, 2362, 2319,  860, 2322,  854,
+     2408, 2328,  855, 2323,  859,  865,  865,  865,  866,  866,
+      866, 2320,  866, 2322, 2324,  866,  867,  867,  867, 2323,
+      867, 2428,  865,  867,  870,  870,  870,  855,  870, 2324,
+     2328,  870,  873,  873,  873,  874,  874,  874,  878,  878,
+      878,  879,  879,  879, 2345,  879, 2454, 2326,  879, 1348,
+      873, 2428, 2325,  874, 2409,  878,  885,  885,  885,  886,
+      886,  886,  887,  887,  887, 2326,  887, 2325, 2345,  887,
+
+      890,  890,  890,  885,  890, 2454,  886,  890,  893,  893,
+      893,  894,  894,  894,  897,  897,  897,  898,  898,  898,
+     2330,  898, 2409,  874,  898, 2331,  893, 1344, 2334,  894,
+     1342,  897,  905,  905,  905,  906,  906,  906, 2330,  906,
+     2333, 2331,  906,  909,  909,  909, 2334,  909, 2348,  905,
+      909,  912,  912,  912, 2348,  912, 2332,  894,  912,  915,
+      915,  915,  916,  916,  916,  918,  918,  918,  919,  919,
+      919, 2332,  919, 2335, 2333,  919, 1341,  915, 2365, 2336,
+      916, 2337,  918,  929,  929,  929, 2429,  929, 2335, 2365,
+      929,  932,  932,  932, 2336,  932, 2337, 2339,  932,  935,
+
+      935,  935,  936,  936,  936,  941,  941,  941,  942,  942,
+      942,  916,  942, 2339, 2343,  942, 2429,  935, 2341, 1340,
+      936, 2342,  941,  947,  947,  947, 1339,  947, 2483, 2343,
+      947,  950,  950,  950, 2341,  950, 1336, 2342,  950, 2347,
+     2349,  936,  953,  953,  953,  954,  954,  954,  960,  960,
+      960,  961,  961,  961, 2347,  961, 2349, 2351,  961, 2352,
+      953, 2483, 1324,  954, 2353,  960,  966,  966,  966,  969,
+      969,  969, 2351,  969, 2379, 2352,  969,  972,  972,  972,
+     2353,  972, 1322,  966,  972,  975,  975,  975,  954,  976,
+      976,  976,  998,  998,  998,  999,  999,  999, 1001, 1001,
+
+     1001, 2354, 2356,  975, 1007, 1007, 1007,  976, 2356, 2358,
+      998, 2379, 2373,  999, 1319, 2358, 1001, 2354, 1008, 1008,
+     1008, 1007, 1008, 2373, 2484, 1008, 1011, 1011, 1011, 1012,
+     1012, 1012, 1014, 1014, 1014, 1016, 1016, 1016,  976, 1016,
+     2359, 1001, 1016, 2360, 1011, 2372, 2359, 1012, 2417, 2496,
+     1014, 1019, 1019, 1019, 1020, 1020, 1020, 2484, 1020, 2360,
+     2372, 1020, 1021, 1021, 1021, 1022, 1022, 1022, 1019, 1024,
+     1024, 1024, 2364, 1026, 1026, 1026, 2355, 1027, 1027, 1027,
+     1021, 1027, 2496, 1022, 1027, 1314, 2417, 1024, 2364, 1014,
+     1026, 1031, 1031, 1031, 2355, 1033, 1033, 1033, 1034, 1034,
+
+     1034, 1036, 1036, 1036, 1039, 1039, 1039, 2361, 1031, 1041,
+     1041, 1041, 1024, 1033, 2366, 2375, 1034, 1312, 2368, 1036,
+     2366, 1039, 1042, 1042, 1042, 2361, 2375, 1041, 1044, 1044,
+     1044, 1046, 1046, 1046, 2368, 1046, 2439, 2389, 1046, 2369,
+     1042, 1052, 1052, 1052, 2370, 2369, 1044, 1053, 1053, 1053,
+     2370, 2371, 1036, 2389, 1055, 1055, 1055, 2371, 1311, 1052,
+     1057, 1057, 1057, 1308, 1057, 1053, 2439, 1057, 1066, 1066,
+     1066, 1044, 1055, 1067, 1067, 1067, 1069, 1069, 1069, 1079,
+     1079, 1079, 1080, 1080, 1080, 2376, 1066, 2377, 1082, 1082,
+     1082, 1067, 2381, 2377, 1069, 1303, 2376, 1079, 2381, 1286,
+
+     1080, 1085, 1085, 1085, 2380, 1055, 1082, 1086, 1086, 1086,
+     1088, 1088, 1088, 1089, 1089, 1089, 1090, 1090, 1090, 1085,
+     1090, 2385, 2380, 1090, 2378, 1086, 2440, 2385, 1088, 2384,
+     1089, 1093, 1093, 1093, 2395, 1094, 1094, 1094, 1069, 2378,
+     1082, 1095, 1095, 1095, 1096, 1096, 1096, 2384, 1093, 2383,
+     2395, 1088, 1094, 1097, 1097, 1097, 2440, 2386, 1095, 2577,
+     2383, 1096, 1098, 1098, 1098, 1099, 1099, 1099, 2386, 2397,
+     1097, 1101, 1101, 1101, 1093, 2401, 2406, 1103, 1103, 1103,
+     1098, 1283, 2406, 1099, 2397, 1109, 1109, 1109, 1095, 1101,
+     2401, 2528, 1094, 1097, 1103, 1104, 1104, 1104, 2577, 1104,
+
+     2528, 1096, 1104, 1109, 1110, 1110, 1110, 1112, 1112, 1112,
+     1101, 1114, 1114, 1114, 1115, 1115, 1115, 1116, 1116, 1116,
+     2413, 1116, 1110, 1282, 1116, 1112, 2413, 2387, 1114, 2388,
+     2394, 1115, 1120, 1120, 1120, 1123, 1123, 1123, 2387, 1123,
+     2388, 2394, 1123, 1126, 1126, 1126, 2643, 2436, 1112, 1120,
+     1127, 1127, 1127, 1129, 1129, 1129, 1132, 1132, 1132, 2398,
+     2643, 1126, 1133, 1133, 1133, 2436, 1133, 2463, 1127, 1133,
+     2398, 1129, 2402, 1132, 1141, 1141, 1141, 1142, 1142, 1142,
+     1281, 1142, 2463, 2402, 1142, 1143, 1143, 1143, 1144, 1144,
+     1144, 1141, 1144, 2415, 2452, 1144, 1145, 1145, 1145, 1146,
+
+     1146, 1146, 1143, 1148, 1148, 1148, 1149, 1149, 1149, 2415,
+     1129, 1150, 1150, 1150, 1145, 2425, 2418, 1146, 1151, 1151,
+     1151, 1148, 1151, 1149, 2452, 1151, 2425, 2453, 1150, 2420,
+     1154, 1154, 1154, 1155, 1155, 1155, 1156, 1156, 1156, 1157,
+     1157, 1157, 1158, 1158, 1158, 2420, 1148, 1154, 1280, 1279,
+     1155, 2426, 2437, 1156, 2418, 2435, 1157, 2453, 2437, 1158,
+     1159, 1159, 1159, 1160, 1160, 1160, 2435, 1160, 1278, 2455,
+     1160, 1163, 1163, 1163, 1165, 1165, 1165, 1159, 1164, 1164,
+     1164, 1166, 1166, 1166, 1168, 1168, 1168, 1154, 1163, 2426,
+     1158, 2443, 1165, 1156, 1277, 1164, 1157, 2443, 2455, 1166,
+
+     2464, 2427, 1168, 1169, 1169, 1169, 1170, 1170, 1170, 2523,
+     1170, 2464, 2430, 1170, 1163, 2523, 2471, 1159, 1164, 1276,
+     1169, 1173, 1173, 1173, 1174, 1174, 1174, 2471, 1175, 1175,
+     1175, 1168, 1176, 1176, 1176, 1177, 1177, 1177, 1173, 2427,
+     2497, 1174, 1178, 1178, 1178, 1175, 1179, 1179, 1179, 1176,
+     2430, 2456, 1177, 1180, 1180, 1180, 1182, 1182, 1182, 1178,
+     1181, 1181, 1181, 1179, 1183, 1183, 1183, 1188, 1188, 1188,
+     1180, 1176, 2467, 2497, 1182, 1174, 2468, 1181, 1173, 1175,
+     1274, 2456, 1183, 2481, 1188, 1178, 1185, 1185, 1185, 1189,
+     1189, 1189, 1177, 1194, 1194, 1194, 1180, 1197, 1197, 1197,
+
+     1181, 2467, 2431, 1179, 1185, 2468, 1189, 1190, 1190, 1190,
+     1194, 1190, 2481, 2432, 1190, 1197, 1198, 1198, 1198, 1200,
+     1200, 1200, 1203, 1203, 1203, 1205, 1205, 1205, 1185, 1206,
+     1206, 1206, 2433, 1206, 1198, 2441, 1206, 1200, 2554, 1203,
+     2431, 1272, 1205, 1213, 1213, 1213, 1214, 1214, 1214, 2554,
+     1214, 2432, 2482, 1214, 1217, 1217, 1217, 1218, 1218, 1218,
+     1213, 1220, 1220, 1220, 1223, 1223, 1223, 1229, 1229, 1229,
+     2433, 2442, 1217, 2441, 2457, 1218, 1230, 1230, 1230, 1220,
+     1200, 2482, 1223, 1223, 1229, 1231, 1231, 1231, 1232, 1232,
+     1232, 2485, 2445, 1230, 1233, 1233, 1233, 1235, 1235, 1235,
+
+     1220, 2446, 1231, 1271, 2457, 1232, 1238, 1238, 1238, 2442,
+     2458, 1233, 1241, 1241, 1241, 1235, 2486, 1242, 1242, 1242,
+     2485, 1242, 2578, 1230, 1242, 1243, 1243, 1243, 2447, 1241,
+     2445, 1244, 1244, 1244, 1245, 1245, 1245, 1232, 1245, 2446,
+     2458, 1245, 1231, 1243, 2487, 2486, 1233, 1235, 1244, 1248,
+     1248, 1248, 1249, 1249, 1249, 1250, 1250, 1250, 1251, 1251,
+     1251, 2578, 1251, 1270, 2459, 1251, 2447, 1248, 1269, 1249,
+     2448, 2492, 1250, 2487, 2449, 1243, 1252, 1252, 1252, 1253,
+     1253, 1253, 1254, 1254, 1254, 2488, 1254, 2492, 1268, 1254,
+     1255, 1255, 1255, 1252, 2459, 2544, 1253, 1256, 1256, 1256,
+
+     1248, 1258, 1258, 1258, 1259, 1259, 1259, 1255, 2448, 1260,
+     1260, 1260, 2449, 1260, 2488, 1256, 1260, 1252, 1258, 2544,
+     2469, 1259, 1262, 1262, 1262, 1267, 1267, 1267, 1273, 1273,
+     1273, 1275, 1275, 1275, 1284, 1284, 1284, 2498, 2450, 1255,
+     1262, 1266, 2460, 1267, 2461, 1273, 1285, 1285, 1285, 1275,
+     2469, 1287, 1287, 1287, 1256, 1288, 1288, 1288, 1289, 1289,
+     1289, 1395, 1395, 1395, 1285, 2465, 2498, 1267, 1287, 1291,
+     1291, 1291, 1262, 1288, 2466, 1289, 2450, 1290, 1290, 1290,
+     2460, 1290, 2461, 1275, 1290, 1265, 1291, 1264, 1292, 1292,
+     1292, 1293, 1293, 1293, 1294, 1294, 1294, 1295, 1295, 1295,
+
+     2470, 1288, 1263, 2465, 1285, 1292, 2472, 2473, 1293, 2474,
+     1261, 1294, 2466, 2545, 1295, 1296, 1296, 1296, 1297, 1297,
+     1297, 1298, 1298, 1298, 1299, 1299, 1299, 2475, 1299, 2476,
+     2470, 1299, 1293, 1296, 1294, 1297, 1257, 2545, 1298, 2474,
+     1292, 1300, 1300, 1300, 2472, 2473, 1295, 1301, 1301, 1301,
+     1302, 1302, 1302, 1304, 1304, 1304, 2509, 2475, 1300, 2476,
+     1296, 1306, 1306, 1306, 1301, 1305, 1305, 1305, 1302, 1305,
+     1304, 2559, 1305, 1307, 1307, 1307, 1240, 1307, 1306, 1239,
+     1307, 2477, 1300, 1309, 1309, 1309, 1310, 1310, 1310, 1237,
+     1310, 2499, 1236, 1310, 2509, 2559, 1301, 1313, 1313, 1313,
+
+     1309, 1315, 1315, 1315, 1316, 1316, 1316, 1302, 1317, 1317,
+     1317, 2477, 1318, 1318, 1318, 1313, 1318, 2478, 1315, 1318,
+     2499, 1316, 1320, 1320, 1320, 1317, 1321, 1321, 1321, 1323,
+     1323, 1323, 2542, 1325, 1325, 1325, 2503, 1325, 2479, 1320,
+     1325, 2542, 1234, 1321, 2504, 2489, 1323, 2478, 1328, 1328,
+     1328, 2505, 1328, 2490, 1313, 1328, 1331, 1331, 1331, 1332,
+     1332, 1332, 1333, 1333, 1333, 2503, 1333, 2506, 2479, 1333,
+     1334, 1334, 1334, 2504, 1331, 2489, 1332, 1335, 1335, 1335,
+     2505, 1335, 1228, 2490, 1335, 2494, 1227, 1334, 1337, 1337,
+     1337, 1338, 1338, 1338, 1226, 1338, 2506, 1331, 1338, 1343,
+
+     1343, 1343, 1345, 1345, 1345, 1337, 1346, 1346, 1346, 2495,
+     1347, 1347, 1347, 2501, 1347, 2494, 1343, 1347, 2502, 2510,
+     1345, 2521, 2507, 1346, 1355, 1355, 1355, 1357, 1357, 1357,
+     1358, 1358, 1358, 1359, 1359, 1359, 1360, 1360, 1360, 2495,
+     2508, 1355, 2519, 2501, 1345, 1357, 2659, 1358, 2502, 2520,
+     1359, 2507, 1221, 1360, 1361, 1361, 1361, 2510, 1361, 2521,
+     2659, 1361, 1362, 1362, 1362, 1216, 1363, 1363, 1363, 2508,
+     1363, 2519, 1359, 1363, 1357, 1364, 1364, 1364, 2520, 1362,
+     1365, 1365, 1365, 1366, 1366, 1366, 1215, 1366, 2560, 2511,
+     1366, 2525, 1364, 1367, 1367, 1367, 1212, 1365, 1368, 1368,
+
+     1368, 1369, 1369, 1369, 1372, 1372, 1372, 1373, 1373, 1373,
+     1367, 1373, 2560, 1211, 1373, 1368, 1375, 1375, 1375, 1369,
+     2525, 1372, 2511, 2512, 1364, 1376, 1376, 1376, 2543, 1376,
+     2526, 2546, 1376, 1375, 1381, 1381, 1381, 2543, 1381, 1210,
+     2546, 1381, 1367, 1385, 1385, 1385, 1386, 1386, 1386, 1209,
+     1390, 1390, 1390, 1396, 1396, 1396, 2512, 2515, 1369, 2526,
+     1385, 1399, 1399, 1399, 1386, 1397, 1397, 1397, 1390, 1397,
+     1396, 2516, 1397, 1403, 1403, 1403, 2522, 2517, 1399, 1405,
+     1405, 1405, 1406, 1406, 1406, 1409, 1409, 1409, 2555, 1409,
+     2515, 1403, 1409, 1412, 1412, 1412, 1413, 1413, 1413, 1414,
+
+     1414, 1414, 2532, 1414, 2516, 2533, 1414, 2573, 1386, 1390,
+     2517, 1412, 2574, 1413, 2522, 2585, 1403, 1415, 1415, 1415,
+     1416, 1416, 1416, 1417, 1417, 1417, 2555, 1417, 2518, 2529,
+     1417, 2532, 1412, 2575, 2533, 1415, 2573, 1416, 1418, 1418,
+     1418, 2574, 1418, 2540, 2585, 1418, 1421, 1421, 1421, 1422,
+     1422, 1422, 2530, 1422, 1204, 2556, 1422, 2575, 1425, 1425,
+     1425, 2518, 2529, 1421, 1426, 1426, 1426, 1427, 1427, 1427,
+     1428, 1428, 1428, 2540, 1415, 1425, 1429, 1429, 1429, 2541,
+     1429, 1202, 1426, 1429, 1427, 2530, 2534, 1428, 1430, 1430,
+     1430, 2552, 1430, 2556, 2576, 1430, 1433, 1433, 1433, 1434,
+
+     1434, 1434, 1439, 1439, 1439, 1425, 1440, 1440, 1440, 2541,
+     1441, 1441, 1441, 1433, 1442, 1442, 1442, 1434, 2576, 2534,
+     1439, 2552, 1201, 1440, 1443, 1443, 1443, 1441, 1444, 1444,
+     1444, 1442, 1445, 1445, 1445, 1196, 1446, 1446, 1446, 1433,
+     1446, 1443, 1434, 1446, 2535, 1444, 1447, 1447, 1447, 1445,
+     1448, 1448, 1448, 1195, 1439, 1441, 1452, 1452, 1452, 1457,
+     1457, 1457, 1458, 1458, 1458, 1460, 1460, 1460, 1448, 1443,
+     2536, 1442, 1461, 1461, 1461, 2563, 1461, 2535, 2537, 1461,
+     1458, 2586, 1460, 2538, 2539, 1444, 1462, 1462, 1462, 1463,
+     1463, 1463, 2550, 1463, 2551, 2557, 1463, 1466, 1466, 1466,
+
+     1472, 1472, 1472, 2536, 1462, 1467, 1467, 1467, 1448, 1467,
+     2586, 2537, 1467, 2563, 1466, 1458, 2538, 2539, 1472, 1473,
+     1473, 1473, 1474, 1474, 1474, 2550, 1474, 2551, 2557, 1474,
+     1475, 1475, 1475, 2547, 1475, 1193, 1473, 1475, 1462, 1480,
+     1480, 1480, 2547, 1472, 1481, 1481, 1481, 1482, 1482, 1482,
+     2579, 1482, 2553, 2580, 1482, 2548, 1187, 1480, 1485, 1485,
+     1485, 1481, 1485, 2549, 2548, 1485, 1488, 1488, 1488, 1489,
+     1489, 1489, 2549, 1489, 2579, 1186, 1489, 2580, 1480, 1492,
+     1492, 1492, 2553, 1488, 1493, 1493, 1493, 1494, 1494, 1494,
+     1496, 1496, 1496, 1497, 1497, 1497, 1492, 1497, 1140, 2558,
+
+     1497, 1493, 1583, 1583, 1583, 1494, 1139, 1496, 1498, 1498,
+     1498, 1499, 1499, 1499, 2561, 1499, 2565, 2562, 1499, 1488,
+     1500, 1500, 1500, 2561, 1500, 1498, 2562, 1500, 1504, 1504,
+     1504, 1492, 2558, 2566, 1505, 1505, 1505, 1493, 1505, 1494,
+     2564, 1505, 1506, 1506, 1506, 1504, 1507, 1507, 1507, 2565,
+     1507, 2581, 2592, 1507, 1509, 1509, 1509, 1138, 1136, 1506,
+     1510, 1510, 1510, 2588, 1510, 1130, 2566, 1510, 1512, 1512,
+     1512, 1509, 1513, 1513, 1513, 2581, 1513, 1122, 2564, 1513,
+     1516, 1516, 1516, 1121, 1516, 2567, 1512, 1516, 1520, 1520,
+     1520, 2592, 1520, 2588, 2567, 1520, 1523, 1523, 1523, 2568,
+
+     1527, 1527, 1527, 1528, 1528, 1528, 2569, 1528, 2568, 2589,
+     1528, 1119, 2606, 1523, 2582, 2569, 1512, 1527, 1530, 1530,
+     1530, 1531, 1531, 1531, 2593, 1531, 2621, 1113, 1531, 1541,
+     1541, 1541, 2594, 1542, 1542, 1542, 1530, 1542, 2582, 2589,
+     1542, 1544, 1544, 1544, 2570, 2606, 1541, 1545, 1545, 1545,
+     1546, 1546, 1546, 2570, 1546, 2621, 2594, 1546, 2607, 1544,
+     2596, 1530, 2571, 2593, 1545, 1548, 1548, 1548, 2572, 1548,
+     2583, 2571, 1548, 2622, 1551, 1551, 1551, 2572, 1551, 2583,
+     1544, 1551, 1554, 1554, 1554, 1555, 1555, 1555, 2595, 1555,
+     2596, 2607, 1555, 1559, 1559, 1559, 1560, 1560, 1560, 1554,
+
+     1560, 2597, 2622, 1560, 1561, 1561, 1561, 1564, 1564, 1564,
+     1559, 1564, 2595, 1108, 1564, 1567, 1567, 1567, 2618, 1568,
+     1568, 1568, 1561, 1568, 2600, 2644, 1568, 1576, 1576, 1576,
+     2584, 2597, 1567, 1577, 1577, 1577, 2644, 1577, 1554, 2584,
+     1577, 1578, 1578, 1578, 1576, 1584, 1584, 1584, 2600, 1584,
+     1107, 2618, 1584, 1588, 1588, 1588, 1589, 1589, 1589, 1578,
+     1589, 2653, 2601, 1589, 1591, 1591, 1591, 1593, 1593, 1593,
+     1588, 1594, 1594, 1594, 1595, 1595, 1595, 1596, 1596, 1596,
+     2602, 1591, 1598, 1598, 1598, 1593, 2601, 1599, 1599, 1599,
+     1578, 1599, 2619, 2603, 1599, 1602, 1602, 1602, 2590, 2653,
+
+     1598, 1603, 1603, 1603, 2602, 1603, 2655, 2590, 1603, 1606,
+     1606, 1606, 2604, 1602, 1607, 1607, 1607, 2603, 1607, 1102,
+     1084, 1607, 1609, 1609, 1609, 2619, 1606, 1611, 1611, 1611,
+     1612, 1612, 1612, 2654, 1612, 1598, 2604, 1612, 2591, 2655,
+     1609, 1613, 1613, 1613, 1611, 1613, 1083, 2591, 1613, 1616,
+     1616, 1616, 1617, 1617, 1617, 1620, 1620, 1620, 1621, 1621,
+     1621, 2629, 1622, 1622, 1622, 1078, 1616, 1623, 1623, 1623,
+     1617, 2654, 1620, 2598, 1624, 1624, 1624, 1077, 1624, 1617,
+     1622, 1624, 2598, 1076, 1623, 1629, 1629, 1629, 2608, 1629,
+     2629, 2605, 1629, 1632, 1632, 1632, 1633, 1633, 1633, 1634,
+
+     1634, 1634, 1635, 1635, 1635, 1637, 1637, 1637, 1641, 1641,
+     1641, 1642, 1642, 1642, 1633, 2605, 1644, 1644, 1644, 2599,
+     1644, 2656, 1622, 1644, 1647, 1647, 1647, 2608, 2599, 1642,
+     1648, 1648, 1648, 1075, 1648, 2610, 1074, 1648, 1651, 1651,
+     1651, 2611, 1647, 1652, 1652, 1652, 1653, 1653, 1653, 1654,
+     1654, 1654, 2639, 1633, 2656, 1651, 1655, 1655, 1655, 2610,
+     1652, 2639, 2616, 1653, 2640, 2611, 1654, 2609, 1656, 1656,
+     1656, 1073, 1656, 2640, 1655, 1656, 1659, 1659, 1659, 1647,
+     1660, 1660, 1660, 1661, 1661, 1661, 2616, 1662, 1662, 1662,
+     1664, 1664, 1664, 1659, 1665, 1665, 1665, 1660, 1663, 1663,
+
+     1663, 1661, 1663, 1653, 1662, 1663, 2609, 1664, 1666, 1666,
+     1666, 1665, 1667, 1667, 1667, 1668, 1668, 1668, 1669, 1669,
+     1669, 2612, 1670, 1670, 1670, 1666, 1670, 2630, 1072, 1670,
+     1667, 2660, 1668, 2613, 1661, 1669, 1673, 1673, 1673, 2614,
+     1673, 2615, 2660, 1673, 1676, 1676, 1676, 2617, 1677, 1677,
+     1677, 1665, 1677, 1071, 1070, 1677, 2630, 1683, 1683, 1683,
+     2612, 1676, 2627, 1667, 2628, 1666, 1680, 1680, 1680, 2633,
+     1680, 2617, 2613, 1680, 1683, 1684, 1684, 1684, 2614, 1684,
+     2615, 2623, 1684, 1687, 1687, 1687, 1688, 1688, 1688, 1689,
+     1689, 1689, 1690, 1690, 1690, 1691, 1691, 1691, 1065, 1691,
+
+     1687, 2627, 1691, 2628, 1688, 2623, 1689, 1688, 2633, 1690,
+     1692, 1692, 1692, 1064, 1683, 1693, 1693, 1693, 1694, 1694,
+     1694, 1695, 1695, 1695, 2651, 1695, 2624, 1692, 1695, 1698,
+     1698, 1698, 1693, 2651, 1063, 1694, 1699, 1699, 1699, 2625,
+     1687, 1700, 1700, 1700, 2663, 2626, 1698, 1701, 1701, 1701,
+     2624, 1702, 1702, 1702, 1699, 1703, 1703, 1703, 1700, 1704,
+     1704, 1704, 1062, 2625, 1701, 1061, 2664, 1692, 1702, 2626,
+     2675, 1693, 1703, 2631, 2634, 1694, 1704, 2663, 1705, 1705,
+     1705, 1706, 1706, 1706, 2675, 1707, 1707, 1707, 1060, 1707,
+     1701, 1699, 1707, 2635, 1702, 1705, 1056, 2631, 1706, 2664,
+
+     1710, 1710, 1710, 2676, 1711, 1711, 1711, 2632, 1712, 1712,
+     1712, 1703, 1712, 2634, 2676, 1712, 1704, 1710, 1715, 1715,
+     1715, 1705, 1711, 1716, 1716, 1716, 1717, 1717, 1717, 2686,
+     1717, 2632, 2635, 1717, 1051, 1715, 1050, 1049, 1706, 1045,
+     1716, 1718, 1718, 1718, 1719, 1719, 1719, 1720, 1720, 1720,
+     2641, 1720, 2636, 1711, 1720, 1723, 1723, 1723, 1718, 2686,
+     2637, 1719, 1726, 1726, 1726, 1727, 1727, 1727, 1728, 1728,
+     1728, 2638, 1728, 1723, 2641, 1728, 1729, 1729, 1729, 1726,
+     2716, 1040, 1727, 1733, 1733, 1733, 2649, 1038, 1734, 1734,
+     1734, 2636, 1734, 1729, 1718, 1734, 1737, 1737, 1737, 2637,
+
+     1733, 1741, 1741, 1741, 1742, 1742, 1742, 2642, 1742, 2716,
+     2638, 1742, 1037, 2678, 1737, 1745, 1745, 1745, 1741, 1746,
+     1746, 1746, 1747, 1747, 1747, 2649, 1747, 2678, 2645, 1747,
+     2650, 2642, 1745, 1749, 1749, 1749, 1746, 1751, 1751, 1751,
+     1752, 1752, 1752, 1737, 1754, 1754, 1754, 1755, 1755, 1755,
+     1032, 1749, 2645, 1030, 1745, 2652, 1757, 1757, 1757, 2646,
+     1757, 2657, 1754, 1757, 2652, 1755, 1761, 1761, 1761, 2650,
+     1761, 2679, 2717, 1761, 1764, 1764, 1764, 1765, 1765, 1765,
+     2647, 1765, 2679, 2646, 1765, 1766, 1766, 1766, 1767, 1767,
+     1767, 1764, 1769, 1769, 1769, 1770, 1770, 1770, 2658, 1770,
+
+     2657, 2717, 1770, 1766, 2647, 1767, 1771, 1771, 1771, 1769,
+     1772, 1772, 1772, 1773, 1773, 1773, 2648, 1773, 1025, 1015,
+     1773, 1777, 1777, 1777, 1779, 1779, 1779, 2665, 1772, 1780,
+     1780, 1780, 1781, 1781, 1781, 2681, 1766, 2658, 1777, 1006,
+     2648, 1779, 1782, 1782, 1782, 2666, 2681, 1780, 1787, 1787,
+     1787, 1788, 1788, 1788, 1790, 1790, 1790, 1791, 1791, 1791,
+     1792, 1792, 1792, 1793, 1793, 1793, 2665, 1793, 2687, 1788,
+     1793, 1790, 1794, 1794, 1794, 1791, 1005, 1792, 1795, 1795,
+     1795, 2743, 1795, 1004, 2666, 1795, 1796, 1796, 1796, 1794,
+     1797, 1797, 1797, 1798, 1798, 1798, 2744, 1798, 2687, 2661,
+
+     1798, 1003, 2680, 1796, 1799, 1799, 1799, 1797, 1801, 1801,
+     1801, 1802, 1802, 1802, 2743, 1802, 2680, 2693, 1802, 1803,
+     1803, 1803, 1799, 2661, 2694, 1801, 1804, 1804, 1804, 2744,
+     1804, 2693, 2699, 1804, 2662, 2694, 1803, 1805, 1805, 1805,
+     1806, 1806, 1806, 1796, 1806, 1002, 2699, 1806, 1809, 1809,
+     1809, 2667, 1810, 1810, 1810, 1805, 1810, 2668, 2662, 1810,
+     1811, 1811, 1811,  997,  996, 1809, 1812, 1812, 1812, 1813,
+     1813, 1813, 1814, 1814, 1814, 2667, 2669, 1811, 1816, 1816,
+     1816, 2668, 1805, 1812, 1815, 1815, 1815, 1813, 1815, 1814,
+      995, 1815, 1817, 1817, 1817, 1816, 1817,  994, 2688, 1817,
+
+     2669, 1818, 1818, 1818, 1819, 1819, 1819, 2688, 1819, 1812,
+      993, 1819, 1820, 1820, 1820, 2670,  992, 1811, 1818, 1821,
+     1821, 1821, 1822, 1822, 1822, 1823, 1823, 1823, 2705, 1820,
+     1824, 1824, 1824, 2671, 1824,  991, 1821, 1824,  990, 2670,
+     1822,  987, 1823, 1825, 1825, 1825, 2672, 1825, 2673, 2674,
+     1825, 1828, 1828, 1828, 1829, 1829, 1829, 2671, 1830, 1830,
+     1830,  986, 1821, 1831, 1831, 1831,  985, 2705, 1828, 1820,
+     2672, 1829, 2673, 2674, 1822, 1830, 2682, 1832, 1832, 1832,
+     1831, 1832, 2683, 2684, 1832, 1833, 1833, 1833, 1834, 1834,
+     1834, 1835, 1835, 1835,  983, 1835, 2706,  979, 1835,  977,
+
+     2682, 1830, 2685, 1833,  968, 1834, 2683, 2684, 1828, 2690,
+     1829, 1836, 1836, 1836, 1837, 1837, 1837, 1838, 1838, 1838,
+     1839, 1839, 1839, 1840, 1840, 1840, 2685, 2689, 1836, 2691,
+     2695, 1837,  967, 2690, 1838, 2706, 2689, 1839, 2701, 2695,
+     1840, 1841, 1841, 1841, 1842, 1842, 1842, 1843, 1843, 1843,
+     2696, 1843, 2701, 2691, 1843, 1844, 1844, 1844, 1841, 2696,
+      965, 1842, 1845, 1845, 1845, 1846, 1846, 1846, 2703, 1846,
+      964, 2697, 1846, 1844, 1847, 1847, 1847, 1839, 1847, 1845,
+     2714, 1847, 2703, 2698, 1841, 1850, 1850, 1850, 1844, 1851,
+     1851, 1851, 1852, 1852, 1852, 2697, 1852,  963,  962, 1852,
+
+      959,  958, 1850, 1853, 1853, 1853, 1851, 2698, 1854, 1854,
+     1854, 1855, 1855, 1855, 1856, 1856, 1856, 2765, 1856, 2714,
+     1853, 1856, 2715, 2700, 1850, 1854, 2765, 2745, 1855, 1857,
+     1857, 1857, 2702, 1857, 2700, 2704, 1857, 1860, 1860, 1860,
+     1861, 1861, 1861, 2702, 1861,  957, 2704, 1861, 1864, 1864,
+     1864, 1865, 1865, 1865, 1860, 1866, 1866, 1866,  956, 1866,
+     2718, 2715, 1866,  955,  946, 1864, 2745, 2712, 1865, 1867,
+     1867, 1867, 1869, 1869, 1869, 1871, 1871, 1871, 1872, 1872,
+     1872, 2712, 1872,  945, 2718, 1872,  944, 1867, 2713,  943,
+     1869,  940, 1871, 1873, 1873, 1873, 1874, 1874, 1874, 2713,
+
+     1874,  939, 2720, 1874, 1879, 1879, 1879, 1881, 1881, 1881,
+     1873, 1882, 1882, 1882,  938, 1882, 2720, 2719, 1882, 1885,
+     1885, 1885, 1879, 2721, 1881, 1867, 1886, 1886, 1886, 1887,
+     1887, 1887,  937, 1887, 2721,  928, 1887, 1885, 1889, 1889,
+     1889, 2719, 1889, 1886, 2725, 1889, 1892, 1892, 1892, 1894,
+     1894, 1894, 1895, 1895, 1895, 1896, 1896, 1896, 2726, 1896,
+      927,  926, 1896, 1885, 1892, 2727, 1894, 2746, 2725, 1895,
+     1897, 1897, 1897, 1898, 1898, 1898, 1899, 1899, 1899, 2727,
+     1899, 2750, 2726, 1899, 1900, 1900, 1900, 1897,  925, 2728,
+     1898, 1902, 1902, 1902, 1903, 1903, 1903, 1906, 1906, 1906,
+
+     2728,  924, 1900, 1907, 1907, 1907, 2746, 1907, 2751, 2766,
+     1907, 1908, 1908, 1908, 1906, 1910, 1910, 1910, 2766, 1910,
+     2750, 2732, 1910, 1913, 1913, 1913, 2760, 1913,  923, 1908,
+     1913, 1916, 1916, 1916, 1917, 1917, 1917, 2760, 1917, 2759,
+     2733, 1917, 1920, 1920, 1920, 2732, 1920, 2751, 1916, 1920,
+     1923, 1923, 1923, 2759, 1923, 2764, 2780, 1923, 1926, 1926,
+     1926, 1927, 1927, 1927, 2733, 1927, 2764, 2780, 1927, 1930,
+     1930, 1930, 1931, 1931, 1931,  922, 1926, 1932, 1932, 1932,
+     1934, 1934, 1934, 1916, 1934,  921, 1930, 1934,  920, 1931,
+     1937, 1937, 1937, 2782, 1937, 1932, 2741, 1937, 1940, 1940,
+
+     1940,  917, 1940, 2742, 2782, 1940,  908, 1926, 1943, 1943,
+     1943, 1944, 1944, 1944, 1945, 1945, 1945, 1949, 1949, 1949,
+     2741, 1930, 1946, 1946, 1946, 1943, 1946, 2742, 1944, 1946,
+     2763,  907, 1945, 1931, 1949, 1950, 1950, 1950, 1951, 1951,
+     1951, 1952, 1952, 1952, 2763, 1952, 2767, 2768, 1952, 1955,
+     1955, 1955, 1950,  904, 2779, 1951, 2787, 1957, 1957, 1957,
+     1943, 1957, 2798,  903, 1957,  902,  901, 1955, 2779, 1949,
+     2767, 2768, 1944, 2798, 2771, 1945, 1960, 1960, 1960, 1961,
+     1961, 1961, 2781, 1961, 2772, 2788, 1961, 1962, 1962, 1962,
+     1963, 1963, 1963, 1960, 1963, 2787, 2781, 1963, 2771, 1951,
+
+     1964, 1964, 1964, 2777, 1962, 1965, 1965, 1965, 2772, 1965,
+     2778,  900, 1965, 1966, 1966, 1966,  899, 1964, 1967, 1967,
+     1967, 1968, 1968, 1968, 2788, 1968,  896, 2777, 1968,  895,
+     1966, 1969, 1969, 1969, 2778, 1967, 1970, 1970, 1970, 2791,
+     1970, 2797,  884, 1970, 1973, 1973, 1973, 2792, 1969, 1974,
+     1974, 1974,  883, 1974,  882, 2797, 1974, 1977, 1977, 1977,
+      881,  880, 1973, 2791,  877, 1966, 1978, 1978, 1978,  876,
+     1978, 2792,  875, 1978, 1977,  864,  863, 1981, 1981, 1981,
+     1982, 1982, 1982,  862, 1982,  861,  858, 1982, 1983, 1983,
+     1983,  857, 1969, 1973, 1981, 1984, 1984, 1984, 1977, 1984,
+
+      856,  844, 1984,  843,  840, 1983, 1985, 1985, 1985,  836,
+     1985,  827,  826, 1985, 1988, 1988, 1988,  825, 1988,  824,
+      823, 1988, 1991, 1991, 1991, 1993, 1993, 1993, 1994, 1994,
+     1994,  820, 1994,  811,  810, 1994, 1995, 1995, 1995, 1991,
+     1995,  807, 1993, 1995, 1998, 1998, 1998, 2002, 2002, 2002,
+      806, 2002,  805,  804, 2002, 2005, 2005, 2005,  803, 2006,
+     2006, 2006, 1998, 2006,  802,  801, 2006, 2007, 2007, 2007,
+      800,  799, 2005, 2008, 2008, 2008, 2009, 2009, 2009, 2010,
+     2010, 2010,  790, 2010,  789,  784, 2010, 2011, 2011, 2011,
+     2008,  781,  774, 2009, 2015, 2015, 2015, 2016, 2016, 2016,
+
+      773, 1998, 2000, 2000, 2000, 2011, 2012, 2012, 2012,  770,
+     2012, 2015,  767, 2012, 2016, 2021, 2021, 2021,  766,  765,
+     2000,  764, 2000, 2000, 2000,  761, 2000, 2000, 2000, 2000,
+     2000,  760, 2021, 2000, 2000, 2000, 2000, 2000,  759, 2011,
+     2017, 2017, 2017,  756, 2017,  755,  749, 2017, 2018, 2018,
+     2018,  744, 2018,  743,  742, 2018, 2022, 2022, 2022,  741,
+     2022,  740,  739, 2022, 2023, 2023, 2023,  736, 2023,  735,
+      734, 2023, 2026, 2026, 2026, 2027, 2027, 2027, 2029, 2029,
+     2029, 2030, 2030, 2030,  733, 2030,  732,  731, 2030, 2033,
+     2033, 2033, 2034, 2034, 2034, 2035, 2035, 2035, 2036, 2036,
+
+     2036, 2037, 2037, 2037,  730,  728, 2033, 2038, 2038, 2038,
+     2034,  727, 2035,  726,  725, 2036,  724,  720, 2037, 2039,
+     2039, 2039,  718,  717, 2038, 2040, 2040, 2040,  716, 2041,
+     2041, 2041, 2043, 2043, 2043, 2034,  715, 2039,  714, 2033,
+      709,  708, 2040,  707,  706, 2035, 2041,  705,  704, 2043,
+      703, 2037, 2042, 2042, 2042, 2036, 2042,  700,  699, 2042,
+      698, 2044, 2044, 2044, 2038, 2044,  695,  690, 2044, 2047,
+     2047, 2047,  689, 2047,  688, 2040, 2047, 2050, 2050, 2050,
+      687, 2050,  685,  684, 2050, 2053, 2053, 2053,  683, 2043,
+     2054, 2054, 2054,  682, 2054,  679,  674, 2054, 2057, 2057,
+
+     2057,  673, 2053, 2058, 2058, 2058, 2059, 2059, 2059, 2060,
+     2060, 2060,  672, 2060,  671, 2057, 2060,  670, 2063, 2063,
+     2063, 2058, 2063, 2059,  669, 2063, 2066, 2066, 2066, 2067,
+     2067, 2067,  668, 2067,  667, 2053, 2067, 2069, 2069, 2069,
+      666, 2069,  664, 2066, 2069, 2072, 2072, 2072,  661, 2059,
+     2058,  660, 2087, 2087, 2087, 2057, 2087,  655,  654, 2087,
+     2090, 2090, 2090, 2072, 2091, 2091, 2091, 2092, 2092, 2092,
+      652, 2092,  651,  650, 2092, 2093, 2093, 2093,  649, 2093,
+      648, 2091, 2093, 2096, 2096, 2096, 2097, 2097, 2097, 2098,
+     2098, 2098,  647, 2098,  645,  644, 2098,  641, 2099, 2099,
+
+     2099, 2096, 2099, 2097,  635, 2099, 2102, 2102, 2102,  634,
+     2102,  633,  632, 2102, 2106, 2106, 2106, 2107, 2107, 2107,
+     2108, 2108, 2108, 2109, 2109, 2109, 2110, 2110, 2110, 2111,
+     2111, 2111,  631,  629, 2107, 2112, 2112, 2112, 2108,  628,
+     2109,  627,  624, 2110,  618,  617, 2111, 2112, 2112, 2113,
+     2113, 2113, 2112, 2115, 2115, 2115, 2116, 2116, 2116,  616,
+     2116,  615,  613, 2116, 2119, 2119, 2119, 2113,  612,  611,
+     2115, 2120, 2120, 2120, 2121, 2121, 2121, 2122, 2122, 2122,
+      608, 2119, 2123, 2123, 2123, 2124, 2124, 2124, 2120, 2124,
+      601, 2121, 2124,  600,  598, 2122, 2127, 2127, 2127, 2123,
+
+     2128, 2128, 2128, 2147, 2147, 2147,  595, 2147,  592,  591,
+     2147,  586,  585, 2127, 2150, 2150, 2150,  584, 2128, 2122,
+     2152, 2152, 2152,  583, 2152,  582,  580, 2152, 2156, 2156,
+     2156,  577, 2150, 2157, 2157, 2157,  572, 2157,  571,  568,
+     2157, 2158, 2158, 2158,  567, 2156, 2160, 2160, 2160, 2161,
+     2161, 2161,  566, 2161,  564,  563, 2161,  562,  561, 2158,
+     2162, 2162, 2162, 2160, 2163, 2163, 2163,  560, 2163,  553,
+      552, 2163, 2164, 2164, 2164,  551,  550, 2162, 2165, 2165,
+     2165,  549, 2165,  547,  544, 2165, 2166, 2166, 2166, 2164,
+     2167, 2167, 2167, 2168, 2168, 2168,  543, 2169, 2169, 2169,
+
+      538, 2169,  537, 2166, 2169,  535,  532, 2167,  531,  530,
+     2168, 2170, 2170, 2170, 2171, 2171, 2171,  529, 2171,  528,
+      525, 2171, 2172, 2172, 2172, 2173, 2173, 2173, 2170, 2173,
+      524,  523, 2173, 2174, 2174, 2174, 2175, 2175, 2175, 2172,
+     2175,  522,  520, 2175, 2176, 2176, 2176, 2177, 2177, 2177,
+     2174, 2178, 2178, 2178,  519, 2178,  516,  515, 2178, 2179,
+     2179, 2179, 2176,  513, 2177, 2180, 2180, 2180,  510, 2180,
+      508,  507, 2180, 2197, 2197, 2197, 2179, 2198, 2198, 2198,
+      504, 2199, 2199, 2199,  503, 2199,  502, 2176, 2199,  501,
+     2197, 2197, 2202, 2202, 2202,  500, 2202,  499,  498, 2202,
+
+     2205, 2205, 2205,  497, 2205,  496,  495, 2205, 2208, 2208,
+     2208,  494, 2208,  491,  490, 2208, 2211, 2211, 2211, 2212,
+     2212, 2212,  489, 2212,  488,  487, 2212, 2213, 2213, 2213,
+     2214, 2214, 2214, 2211, 2214,  481,  480, 2214, 2215, 2215,
+     2215,  478, 2215,  475, 2213, 2215, 2218, 2218, 2218,  474,
+     2218,  472,  471, 2218, 2221, 2221, 2221,  464, 2221,  462,
+      461, 2221, 2224, 2224, 2224,  460, 2224,  459,  458, 2224,
+     2227, 2227, 2227, 2228, 2228, 2228,  457, 2228,  455,  451,
+     2228,  442, 2231, 2231, 2231,  441, 2231,  440, 2227, 2231,
+     2239, 2239, 2239, 2247, 2247, 2247, 2250, 2250, 2250, 2251,
+
+     2251, 2251,  439, 2251,  438,  437, 2251,  436, 2239,  435,
+      434, 2247,  430, 2250, 2250,  420,  419, 2251, 2252, 2252,
+     2252,  418, 2253, 2253, 2253, 2227, 2253,  417,  415, 2253,
+     2256, 2256, 2256,  414, 2256,  413,  409, 2256, 2259, 2259,
+     2259, 2264, 2264, 2264, 2265, 2265, 2265, 2266, 2266, 2266,
+     2267, 2267, 2267, 2273, 2273, 2273, 2259,  399,  397, 2264,
+      396,  395, 2265,  394,  393, 2266,  392,  391, 2267,  387,
+      378, 2273, 2274, 2274, 2274,  377,  376, 2265, 2276, 2276,
+     2276,  375, 2276,  374,  373, 2276, 2273,  372,  371,  370,
+     2274, 2279, 2279, 2279,  369,  365, 2276,  356,  355, 2274,
+
+     2277, 2277, 2277, 2277, 2277, 2277, 2277, 2277, 2277, 2279,
+      354, 2277, 2281, 2281, 2281,  353, 2277, 2277, 2277, 2277,
+     2277,  352,  351,  350,  349,  348,  344,  334,  333,  332,
+     2281, 2282, 2282, 2282, 2283, 2283, 2283,  330, 2277, 2277,
+     2278, 2278, 2278, 2278, 2278, 2278, 2278, 2278, 2278, 2282,
+      326, 2278, 2283, 2285, 2285, 2285, 2278, 2278, 2278, 2278,
+     2278,  317, 2287, 2287, 2287, 2288, 2288, 2288,  316,  315,
+      314, 2285, 2289, 2289, 2289, 2293, 2293, 2293, 2278, 2278,
+     2287,  312,  308, 2288,  299,  298, 2285, 2295, 2295, 2295,
+     2289,  294,  289, 2293,  280, 2287,  273,  271, 2288, 2297,
+
+     2297, 2297,  270,  266,  256, 2295,  255,  254,  253,  249,
+      242,  241, 2300, 2300, 2300,  240,  239, 2297,  235,  229,
+     2295, 2298, 2298, 2298, 2298, 2298, 2298, 2298, 2298, 2298,
+     2300,  228, 2298, 2321, 2321, 2321,  226, 2298, 2298, 2298,
+     2298, 2298,  225,  221,  214, 2300,  213,  212,  208,  201,
+      200, 2321, 2301, 2301, 2301, 2302, 2302, 2302,  199, 2298,
+     2298, 2299, 2299, 2299, 2299, 2299, 2299, 2299, 2299, 2299,
+     2301,  195, 2299, 2302, 2308, 2308, 2308, 2299, 2299, 2299,
+     2299, 2299,  185,  183,  182, 2301,  178,  173, 2302,  172,
+      171,  165, 2308, 2312, 2312, 2312, 2316, 2316, 2316, 2299,
+
+     2299, 2327, 2327, 2327, 2338, 2338, 2338, 2308,  164,  162,
+      159, 2312,  147,    0, 2316, 2344, 2344, 2344,    0, 2327,
+        0,    0, 2338, 2346, 2346, 2346, 2312,    0,    0, 2316,
+        0,    0,    0, 2344, 2350, 2350, 2350, 2338, 2363, 2363,
+     2363, 2346, 2367, 2367, 2367, 2374, 2374, 2374, 2344, 2382,
+     2382, 2382, 2350,    0,    0,    0, 2363,    0,    0,    0,
+     2367,    0,    0, 2374, 2390, 2390, 2390, 2382, 2392, 2392,
+     2392, 2363, 2391, 2391, 2391, 2367, 2391,    0,    0, 2391,
+        0,    0, 2390, 2393, 2393, 2393, 2392, 2396, 2396, 2396,
+     2391, 2399, 2399, 2399,    0, 2399,    0,    0, 2399,    0,
+
+        0, 2393, 2400, 2400, 2400, 2396, 2403, 2403, 2403, 2399,
+     2404, 2404, 2404, 2405, 2405, 2405,    0,    0,    0,    0,
+     2400, 2412, 2412, 2412, 2403, 2407, 2407, 2407, 2404, 2407,
+        0, 2405, 2407, 2410, 2410, 2410,    0, 2410,    0, 2412,
+     2410,    0,    0, 2407,    0, 2411, 2411, 2411,    0, 2411,
+        0, 2410, 2411, 2414, 2414, 2414, 2416, 2416, 2416,    0,
+     2419, 2419, 2419, 2411, 2419,    0,    0, 2419,    0,    0,
+        0, 2414,    0,    0, 2416, 2421, 2421, 2421, 2419,    0,
+     2422, 2422, 2422,    0, 2422,    0, 2414, 2422, 2423, 2423,
+     2423,    0, 2423, 2421,    0, 2423,    0,    0, 2422,    0,
+
+     2424, 2424, 2424,    0, 2424,    0, 2423, 2424, 2434, 2434,
+     2434,    0, 2434,    0,    0, 2434,    0,    0, 2424,    0,
+     2438, 2438, 2438,    0, 2438,    0, 2434, 2438, 2444, 2444,
+     2444,    0, 2444,    0,    0, 2444,    0,    0, 2438, 2451,
+     2451, 2451, 2462, 2462, 2462,    0, 2444, 2480, 2480, 2480,
+        0, 2480,    0,    0, 2480,    0,    0, 2451,    0,    0,
+     2462,    0, 2491, 2491, 2491, 2480, 2491,    0,    0, 2491,
+     2493, 2493, 2493, 2500, 2500, 2500,    0, 2524, 2524, 2524,
+     2491, 2524,    0,    0, 2524, 2531, 2531, 2531, 2493, 2531,
+        0, 2500, 2531,    0,    0, 2524, 2587, 2587, 2587,    0,
+
+     2620, 2620, 2620, 2531, 2620,    0,    0, 2620, 2677, 2677,
+     2677, 2692, 2692, 2692, 2587, 2707, 2707, 2707, 2620, 2708,
+     2708, 2708, 2710, 2710, 2710,    0, 2677,    0,    0, 2692,
+     2711, 2711, 2711, 2707, 2722, 2722, 2722, 2708,    0,    0,
+     2710, 2724, 2724, 2724, 2729, 2729, 2729,    0, 2711, 2730,
+     2730, 2730, 2722, 2731, 2731, 2731, 2734, 2734, 2734, 2724,
+        0,    0, 2729, 2736, 2736, 2736,    0, 2730, 2738, 2738,
+     2738, 2731,    0,    0, 2734, 2740, 2740, 2740, 2747, 2747,
+     2747, 2736, 2748, 2748, 2748,    0, 2738, 2752, 2752, 2752,
+     2753, 2753, 2753, 2740,    0,    0, 2747, 2755, 2755, 2755,
+
+     2748, 2757, 2757, 2757,    0, 2752,    0,    0, 2753, 2761,
+     2761, 2761, 2769, 2769, 2769, 2755, 2773, 2773, 2773, 2757,
+     2775, 2775, 2775, 2776, 2776, 2776,    0, 2761,    0,    0,
+     2769, 2783, 2783, 2783, 2773, 2785, 2785, 2785, 2775,    0,
+        0, 2776, 2789, 2789, 2789, 2790, 2790, 2790,    0, 2783,
+     2793, 2793, 2793, 2785, 2795, 2795, 2795, 2799, 2799, 2799,
+     2789,    0,    0, 2790, 2800, 2800, 2800,    0, 2793,    0,
+        0,    0, 2795,    0,    0, 2799,    0,    0,    0,    0,
+        0,    0, 2800, 2803, 2803, 2803, 2803, 2803, 2803, 2803,
+     2803, 2803, 2804, 2804, 2804, 2804, 2804, 2804, 2804, 2804,
+
+     2804, 2805, 2805, 2805, 2805, 2805, 2805, 2805, 2805, 2805,
+     2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2806, 2807,
+     2807, 2807, 2807, 2807, 2807, 2807, 2807, 2807, 2808, 2808,
+     2808, 2808, 2808, 2808, 2808, 2808, 2808, 2809, 2809, 2809,
+     2809, 2809, 2809, 2809, 2809, 2809, 2810, 2810, 2810, 2810,
+     2810, 2810, 2810, 2810, 2810, 2811, 2811, 2811, 2811, 2811,
+     2811, 2811, 2811, 2811, 2812, 2812, 2812, 2812, 2812, 2812,
+     2812, 2812, 2812, 2813, 2813, 2813, 2813, 2813, 2813, 2813,
+     2813, 2813, 2814, 2814, 2814, 2814, 2814, 2814, 2814, 2814,
+     2814, 2815, 2815, 2815, 2815, 2815, 2815, 2815, 2815, 2815,
+
+     2816, 2816, 2816, 2816, 2816, 2816, 2816, 2816, 2816, 2817,
+     2817, 2817, 2817, 2817, 2817, 2817, 2817, 2817, 2818, 2818,
+     2818, 2818, 2818, 2818, 2818, 2818, 2818, 2819, 2819, 2819,
+     2819, 2819, 2819, 2819, 2819, 2819, 2820, 2820, 2820, 2820,
+     2820, 2820, 2820, 2820, 2820, 2821, 2821, 2821, 2821, 2821,
+     2821, 2821, 2821, 2821, 2822, 2822, 2822, 2822, 2822, 2822,
+     2822, 2822, 2822, 2823, 2823, 2823, 2823, 2823, 2823, 2823,
+     2823, 2823, 2824, 2824, 2824, 2824, 2824, 2824, 2824, 2824,
+     2824, 2825, 2825, 2825, 2825, 2825, 2825, 2825, 2825, 2825,
+     2826, 2826, 2826, 2826, 2826, 2826, 2826, 2826, 2826, 2827,
+
+     2827, 2827, 2827, 2827, 2827, 2827, 2827, 2827, 2828, 2828,
+     2828, 2828, 2828, 2828, 2828, 2828, 2828, 2829, 2829, 2829,
+     2829, 2829, 2829, 2829, 2829, 2829, 2830, 2830, 2830, 2830,
+     2830, 2830, 2830, 2830, 2830, 2831, 2831, 2831, 2831, 2831,
+     2831, 2831, 2831, 2831, 2832, 2832, 2832, 2832, 2832, 2832,
+     2832, 2832, 2832, 2833, 2833, 2833, 2833, 2833, 2833, 2833,
+     2833, 2833, 2834, 2834, 2834, 2834, 2834, 2834, 2834, 2834,
+     2834, 2835, 2835, 2835, 2835, 2835, 2835, 2835, 2835, 2835,
+     2836, 2836, 2836,    0,    0,    0, 2836, 2837, 2837, 2837,
+        0,    0,    0, 2837, 2838, 2838, 2838,    0,    0,    0,
+
+     2838, 2839, 2839, 2839,    0,    0,    0, 2839, 2840, 2840,
+     2840,    0,    0,    0, 2840, 2841, 2841, 2841,    0,    0,
+        0, 2841, 2842, 2842, 2842,    0,    0,    0, 2842, 2843,
+     2843, 2843,    0,    0,    0, 2843, 2844, 2844, 2844,    0,
+        0,    0, 2844, 2845, 2845, 2845,    0,    0,    0, 2845,
+     2846, 2846, 2846,    0,    0,    0, 2846, 2847, 2847, 2847,
+        0,    0,    0, 2847, 2848, 2848, 2848,    0,    0,    0,
+     2848, 2849, 2849, 2849,    0,    0,    0, 2849, 2850, 2850,
+     2850,    0,    0,    0, 2850, 2851, 2851, 2851,    0,    0,
+        0, 2851, 2852, 2852, 2852,    0,    0,    0, 2852, 2853,
+
+     2853, 2853, 2853, 2853, 2853, 2853,    0, 2853, 2854,    0,
+        0,    0, 2854, 2855,    0,    0,    0, 2855, 2856,    0,
+        0,    0, 2856, 2857,    0,    0,    0, 2857, 2858,    0,
+        0,    0, 2858, 2859,    0,    0,    0, 2859, 2860,    0,
+        0,    0, 2860, 2861,    0,    0,    0, 2861, 2862,    0,
+        0,    0, 2862, 2863,    0,    0,    0, 2863, 2864,    0,
+        0,    0, 2864, 2865,    0,    0,    0, 2865, 2866,    0,
+        0,    0, 2866, 2867, 2867, 2867,    0,    0,    0, 2867,
+     2868,    0,    0,    0, 2868, 2869, 2869, 2869,    0,    0,
+        0, 2869, 2870,    0,    0,    0, 2870, 2871, 2871, 2871,
+
+        0,    0,    0, 2871, 2872,    0,    0,    0, 2872, 2873,
+     2873, 2873,    0,    0,    0, 2873, 2874,    0,    0,    0,
+     2874, 2875, 2875, 2875, 2875, 2875, 2875, 2875, 2875, 2875,
+     2876,    0,    0,    0,    0, 2876, 2877, 2877, 2877,    0,
+        0,    0, 2877, 2878, 2878, 2878, 2878,    0,    0, 2878,
+     2878, 2879, 2879, 2879,    0,    0,    0, 2879, 2880, 2880,
+     2880, 2880,    0,    0, 2880, 2880, 2881, 2881, 2881,    0,
+        0,    0, 2881, 2882, 2882, 2882, 2882,    0,    0, 2882,
+     2882, 2883, 2883, 2883,    0,    0,    0, 2883, 2884, 2884,
+     2884, 2884,    0,    0, 2884, 2884, 2885, 2885, 2885,    0,
+
+        0,    0, 2885, 2886, 2886, 2886, 2886,    0,    0, 2886,
+     2886, 2887, 2887, 2887,    0,    0,    0, 2887, 2888, 2888,
+     2888, 2888,    0,    0, 2888, 2888, 2889, 2889, 2889,    0,
+        0,    0, 2889, 2890, 2890, 2890, 2890,    0,    0, 2890,
+     2890, 2891, 2891, 2891, 2891,    0,    0, 2891, 2891, 2892,
+     2892, 2892,    0,    0,    0, 2892, 2893, 2893, 2893, 2893,
+        0,    0, 2893, 2893, 2894, 2894, 2894,    0,    0,    0,
+     2894, 2895, 2895, 2895, 2895,    0,    0, 2895, 2895, 2896,
+     2896, 2896,    0,    0,    0, 2896, 2897, 2897, 2897, 2897,
+        0,    0, 2897, 2897, 2898, 2898, 2898,    0,    0,    0,
+
+     2898, 2899, 2899, 2899, 2899,    0,    0, 2899, 2899, 2900,
+     2900, 2900,    0,    0,    0, 2900, 2901, 2901, 2901, 2901,
+        0,    0, 2901, 2901, 2902, 2902, 2902,    0,    0,    0,
+     2902, 2903, 2903, 2903, 2903,    0,    0, 2903, 2903, 2904,
+     2904, 2904,    0,    0,    0, 2904, 2905, 2905, 2905, 2905,
+        0,    0, 2905, 2905, 2906, 2906, 2906,    0,    0,    0,
+     2906, 2907, 2907, 2907, 2907,    0,    0, 2907, 2907, 2908,
+     2908, 2908,    0,    0,    0, 2908, 2909, 2909, 2909, 2909,
+        0,    0, 2909, 2909, 2910, 2910, 2910, 2910, 2910, 2910,
+     2910, 2910, 2910, 2911,    0, 2911,    0,    0, 2911, 2912,
+
+     2912, 2912,    0,    0,    0, 2912, 2913, 2913, 2913, 2913,
+        0,    0, 2913, 2913, 2914, 2914, 2914,    0,    0,    0,
+     2914, 2915, 2915, 2915, 2915,    0,    0, 2915, 2915, 2916,
+     2916, 2916,    0,    0,    0, 2916, 2917, 2917, 2917, 2917,
+        0,    0, 2917, 2917, 2918, 2918, 2918,    0,    0,    0,
+     2918, 2919, 2919, 2919, 2919,    0,    0, 2919, 2919, 2920,
+     2920, 2920,    0,    0,    0, 2920, 2921, 2921, 2921, 2921,
+        0,    0, 2921, 2921, 2922, 2922, 2922,    0,    0,    0,
+     2922, 2923, 2923, 2923, 2923,    0,    0, 2923, 2923, 2924,
+     2924, 2924,    0,    0,    0, 2924, 2925, 2925, 2925, 2925,
+
+        0,    0, 2925, 2925, 2926, 2926, 2926, 2926,    0,    0,
+     2926, 2926, 2927, 2927, 2927,    0,    0,    0, 2927, 2928,
+     2928, 2928, 2928,    0,    0, 2928, 2928, 2929, 2929, 2929,
+     2929,    0, 2929,    0, 2929, 2930, 2930, 2930, 2930,    0,
+        0, 2930, 2930, 2931, 2931, 2931,    0,    0,    0, 2931,
+     2932, 2932, 2932, 2932,    0,    0, 2932, 2932, 2933, 2933,
+     2933,    0,    0,    0, 2933, 2934, 2934, 2934, 2934,    0,
+        0, 2934, 2934, 2935, 2935, 2935,    0,    0,    0, 2935,
+     2936, 2936, 2936, 2936,    0,    0, 2936, 2936, 2937, 2937,
+     2937, 2937,    0, 2937,    0, 2937, 2938, 2938, 2938, 2938,
+
+        0,    0, 2938, 2938, 2939, 2939, 2939, 2939,    0, 2939,
+        0, 2939, 2940, 2940, 2940, 2940,    0,    0, 2940, 2940,
+     2941, 2941, 2941,    0,    0,    0, 2941, 2942, 2942, 2942,
+     2942,    0,    0, 2942, 2942, 2943, 2943, 2943,    0,    0,
+        0, 2943, 2944, 2944, 2944, 2944,    0,    0, 2944, 2944,
+     2945, 2945, 2945, 2945, 2945, 2945, 2945, 2945, 2945, 2946,
+     2946, 2946, 2946, 2946, 2946, 2946, 2946, 2946, 2947, 2947,
+     2947, 2947,    0, 2947,    0, 2947, 2948, 2948, 2948, 2948,
+        0,    0, 2948, 2948, 2949, 2949, 2949,    0,    0,    0,
+     2949, 2950, 2950, 2950, 2950,    0,    0, 2950, 2950, 2951,
+
+     2951, 2951, 2951,    0, 2951,    0, 2951, 2952, 2952, 2952,
+     2952,    0,    0, 2952, 2952, 2953, 2953, 2953, 2953,    0,
+     2953,    0, 2953, 2954, 2954, 2954, 2954,    0,    0, 2954,
+     2954, 2955, 2955, 2955,    0,    0,    0, 2955, 2956, 2956,
+     2956, 2956,    0,    0, 2956, 2956, 2957, 2957, 2957,    0,
+        0,    0, 2957, 2958, 2958, 2958, 2958,    0,    0, 2958,
+     2958, 2959, 2959, 2959,    0,    0,    0, 2959, 2960, 2960,
+     2960, 2960,    0,    0, 2960, 2960, 2961, 2961, 2961, 2961,
+        0,    0, 2961, 2961, 2962, 2962, 2962,    0,    0,    0,
+     2962, 2963, 2963, 2963, 2963,    0,    0, 2963, 2963, 2964,
+
+     2964, 2964, 2964,    0, 2964,    0, 2964, 2965, 2965, 2965,
+     2965,    0,    0, 2965, 2965, 2966, 2966, 2966, 2966,    0,
+     2966,    0, 2966, 2967, 2967, 2967, 2967,    0,    0, 2967,
+     2967, 2968, 2968, 2968,    0,    0,    0, 2968, 2969, 2969,
+     2969, 2969,    0,    0, 2969, 2969, 2970, 2970, 2970,    0,
+        0,    0, 2970, 2971, 2971, 2971, 2971,    0,    0, 2971,
+     2971, 2972, 2972, 2972,    0,    0,    0, 2972, 2973, 2973,
+     2973, 2973,    0,    0, 2973, 2973, 2974, 2974, 2974,    0,
+        0,    0, 2974, 2975, 2975, 2975, 2975,    0,    0, 2975,
+     2975, 2976, 2976, 2976, 2976,    0, 2976,    0, 2976, 2977,
+
+     2977, 2977, 2977,    0,    0, 2977, 2977, 2978, 2978, 2978,
+        0,    0,    0, 2978, 2979, 2979, 2979, 2979,    0,    0,
+     2979, 2979, 2980, 2980, 2980, 2980, 2980, 2980, 2980, 2980,
+     2980, 2981, 2981, 2981, 2981, 2981, 2981, 2981, 2981, 2981,
+     2982, 2982, 2982,    0,    0,    0, 2982, 2983, 2983, 2983,
+     2983,    0,    0, 2983, 2983, 2984, 2984, 2984,    0,    0,
+        0, 2984, 2985, 2985, 2985, 2985,    0,    0, 2985, 2985,
+     2986, 2986, 2986, 2986,    0,    0, 2986, 2986, 2987, 2987,
+     2987, 2987,    0, 2987,    0, 2987, 2988, 2988, 2988, 2988,
+        0,    0, 2988, 2988, 2989, 2989, 2989, 2989,    0, 2989,
+
+        0, 2989, 2990, 2990, 2990, 2990,    0,    0, 2990, 2990,
+     2991, 2991, 2991,    0,    0,    0, 2991, 2992, 2992, 2992,
+     2992,    0,    0, 2992, 2992, 2993, 2993, 2993, 2993,    0,
+     2993,    0, 2993, 2994, 2994, 2994, 2994,    0,    0, 2994,
+     2994, 2995, 2995, 2995, 2995,    0,    0, 2995, 2995, 2996,
+     2996, 2996,    0,    0,    0, 2996, 2997, 2997, 2997, 2997,
+        0,    0, 2997, 2997, 2998, 2998, 2998,    0,    0,    0,
+     2998, 2999, 2999, 2999, 2999,    0,    0, 2999, 2999, 3000,
+     3000, 3000,    0,    0,    0, 3000, 3001, 3001, 3001, 3001,
+        0,    0, 3001, 3001, 3002, 3002, 3002, 3002,    0, 3002,
+
+        0, 3002, 3003, 3003, 3003, 3003,    0,    0, 3003, 3003,
+     3004, 3004, 3004,    0,    0,    0, 3004, 3005, 3005, 3005,
+     3005,    0,    0, 3005, 3005, 3006, 3006, 3006,    0,    0,
+        0, 3006, 3007, 3007, 3007, 3007,    0,    0, 3007, 3007,
+     3008, 3008, 3008,    0,    0,    0, 3008, 3009, 3009, 3009,
+     3009,    0,    0, 3009, 3009, 3010, 3010, 3010,    0,    0,
+        0, 3010, 3011, 3011, 3011, 3011,    0,    0, 3011, 3011,
+     3012, 3012, 3012,    0,    0,    0, 3012, 3013, 3013, 3013,
+     3013,    0,    0, 3013, 3013, 3014, 3014, 3014, 3014, 3014,
+     3014, 3014, 3014, 3014, 3015, 3015, 3015, 3015, 3015, 3015,
+
+     3015, 3015, 3015, 3016, 3016, 3016,    0,    0,    0, 3016,
+     3017, 3017, 3017, 3017,    0,    0, 3017, 3017, 3018, 3018,
+     3018,    0,    0,    0, 3018, 3019, 3019, 3019, 3019,    0,
+        0, 3019, 3019, 3020, 3020, 3020, 3020,    0,    0, 3020,
+     3020, 3021, 3021, 3021,    0,    0,    0, 3021, 3022, 3022,
+     3022, 3022,    0, 3022,    0, 3022, 3023, 3023, 3023, 3023,
+        0,    0, 3023, 3023, 3024, 3024, 3024,    0,    0,    0,
+     3024, 3025, 3025, 3025, 3025,    0,    0, 3025, 3025, 3026,
+     3026, 3026,    0,    0,    0, 3026, 3027, 3027, 3027, 3027,
+        0,    0, 3027, 3027, 3028, 3028, 3028, 3028,    0,    0,
+
+     3028, 3028, 3029, 3029, 3029,    0,    0,    0, 3029, 3030,
+     3030, 3030, 3030,    0,    0, 3030, 3030, 3031, 3031, 3031,
+     3031,    0, 3031,    0, 3031, 3032, 3032, 3032, 3032,    0,
+        0, 3032, 3032, 3033, 3033, 3033, 3033,    0, 3033,    0,
+     3033, 3034, 3034, 3034, 3034,    0,    0, 3034, 3034, 3035,
+     3035, 3035, 3035,    0, 3035,    0, 3035, 3036, 3036, 3036,
+     3036,    0,    0, 3036, 3036, 3037, 3037, 3037, 3037,    0,
+     3037,    0, 3037, 3038, 3038, 3038, 3038,    0,    0, 3038,
+     3038, 3039, 3039, 3039, 3039,    0, 3039,    0, 3039, 3040,
+     3040, 3040, 3040,    0,    0, 3040, 3040, 3041, 3041, 3041,
+
+     3041,    0, 3041,    0, 3041, 3042, 3042, 3042, 3042,    0,
+        0, 3042, 3042, 3043, 3043, 3043, 3043,    0, 3043,    0,
+     3043, 3044, 3044, 3044,    0,    0,    0, 3044, 3045, 3045,
+     3045, 3045,    0,    0, 3045, 3045, 3046, 3046, 3046, 3046,
+     3046, 3046, 3046, 3046, 3046, 3047, 3047, 3047, 3047, 3047,
+     3047, 3047, 3047, 3047, 3048, 3048, 3048, 3048,    0, 3048,
+        0, 3048, 3049, 3049, 3049,    0,    0,    0, 3049, 3050,
+     3050, 3050, 3050,    0,    0, 3050, 3050, 3051, 3051, 3051,
+     3051, 3051, 3051, 3051, 3051, 3051, 3052, 3052, 3052, 3052,
+     3052, 3052, 3052, 3052, 3052, 2802, 2802, 2802, 2802, 2802,
+
+     2802, 2802, 2802, 2802, 2802, 2802, 2802, 2802, 2802, 2802,
+     2802, 2802, 2802, 2802, 2802, 2802, 2802, 2802, 2802, 2802,
+     2802, 2802, 2802, 2802, 2802, 2802, 2802, 2802, 2802, 2802,
+     2802, 2802, 2802, 2802, 2802, 2802, 2802, 2802, 2802, 2802,
+     2802, 2802, 2802, 2802, 2802, 2802, 2802, 2802, 2802, 2802,
+     2802, 2802, 2802, 2802, 2802, 2802, 2802, 2802, 2802, 2802,
+     2802
+    } ;
+
+static yy_state_type yy_last_accepting_state;
+static char *yy_last_accepting_cpos;
+
+/* The intent behind this definition is that it'll catch
+ * any uses of REJECT which flex missed.
+ */
+#define REJECT reject_used_but_not_detected
+#define yymore() yymore_used_but_not_detected
+#define YY_MORE_ADJ 0
+#define YY_RESTORE_YY_MORE_OFFSET
+char *yytext;
+#define INITIAL 0
+/* Validating XML processor for skin.dtd.
+ * Generated 2004/01/03 15:23:36.
+ *
+ * This program was generated with the FleXML XML processor generator,
+ * (Id: flexml.pl,v 1.24 1999/12/13 16:18:30 krisrose Exp).
+ * Copyright © 1999 Kristoffer Rose.  All rights reserved.
+ *
+ * You can redistribute and/or modify this program provided the following
+ * two conditions hold:
+ *
+ * 1. The program is distributed WITHOUT ANY WARRANTY from the author of
+ *    FleXML; without even the implied warranty of MERCHANTABILITY or
+ *    FITNESS FOR A PARTICULAR PURPOSE.
+ *
+ * 2. The program distribution conditions do not in any way affect the
+ *    distribution conditions of the FleXML system used to generate this
+ *    file or any version of FleXML derived from that system.
+ *
+ * Notice that these are explicit rights granted to you for files
+ * generated by the FleXML system.  For your rights in connection with
+ * the FleXML system itself please consult the GNU General Public License.
+ */
+
+/* Version strings. */
+const char rcs_flexml_skeleton[] =
+ "$" "Id: skel,v 1.16 1999/12/09 04:01:51 krisrose Exp $";
+const char rcs_flexml[] =
+ "$" "Id: flexml.pl,v 1.24 1999/12/13 16:18:30 krisrose Exp $";
+
+/* ANSI headers. */
+#include <unistd.h>
+#include <stdio.h>
+#include <string.h>
+#include <assert.h>
+#include <stdarg.h>
+#include <ctype.h>
+
+/* Generated definitions. */
+#define FLEXML_BUFFERSTACKSIZE 100000
+
+/* XML processor api. */
+#include "skin.h"
+
+/* FleXML-provided data. */
+char* pcdata;
+AT_Text_id A_Text_id;
+AT_ThemeInfo_author A_ThemeInfo_author;
+AT_Playlist_fgcolor A_Playlist_fgcolor;
+AT_CheckBox_down2 A_CheckBox_down2;
+AT_Image_lefttop A_Image_lefttop;
+AT_Slider_visible A_Slider_visible;
+AT_CheckBox_down1 A_CheckBox_down1;
+AT_Image_rightbottom A_Image_rightbottom;
+AT_Event_id A_Event_id;
+AT_Rectangle_h A_Rectangle_h;
+AT_Slider_lefttop A_Slider_lefttop;
+AT_Slider_over A_Slider_over;
+AT_Window_id A_Window_id;
+AT_Theme_alpha A_Theme_alpha;
+AT_Text_text A_Text_text;
+AT_Playlist_rightbottom A_Playlist_rightbottom;
+AT_Event_event A_Event_event;
+AT_Slider_value A_Slider_value;
+AT_Font_underline A_Font_underline;
+AT_Image_onclick A_Image_onclick;
+AT_Anchor_priority A_Anchor_priority;
+AT_Font_italic A_Font_italic;
+AT_Button_y A_Button_y;
+AT_RadialSlider_sequence A_RadialSlider_sequence;
+AT_Playlist_var A_Playlist_var;
+AT_CheckBox_y A_CheckBox_y;
+AT_Window_playondrop A_Window_playondrop;
+AT_RadialSlider_minangle A_RadialSlider_minangle;
+AT_RadialSlider_visible A_RadialSlider_visible;
+AT_Playlist_playcolor A_Playlist_playcolor;
+AT_Anchor_range A_Anchor_range;
+AT_Theme_fadetime A_Theme_fadetime;
+AT_CheckBox_x A_CheckBox_x;
+AT_Bitmap_file A_Bitmap_file;
+AT_Slider_down A_Slider_down;
+AT_CheckBox_over2 A_CheckBox_over2;
+AT_Slider_y A_Slider_y;
+AT_Slider_id A_Slider_id;
+AT_Window_dragdrop A_Window_dragdrop;
+AT_Text_x A_Text_x;
+AT_Image_y A_Image_y;
+AT_Font_color A_Font_color;
+AT_Slider_rightbottom A_Slider_rightbottom;
+AT_Group_y A_Group_y;
+AT_Text_font A_Text_font;
+AT_Button_over A_Button_over;
+AT_Theme_version A_Theme_version;
+AT_Image_id A_Image_id;
+AT_CheckBox_lefttop A_CheckBox_lefttop;
+AT_Text_scrollspace A_Text_scrollspace;
+AT_Button_action A_Button_action;
+AT_Button_lefttop A_Button_lefttop;
+AT_Button_id A_Button_id;
+AT_Rectangle_visible A_Rectangle_visible;
+AT_Rectangle_color A_Rectangle_color;
+AT_Playlist_width A_Playlist_width;
+AT_RadialSlider_maxangle A_RadialSlider_maxangle;
+AT_Window_y A_Window_y;
+AT_Slider_help A_Slider_help;
+AT_Text_width A_Text_width;
+AT_Slider_points A_Slider_points;
+AT_CheckBox_up1 A_CheckBox_up1;
+AT_Theme_magnet A_Theme_magnet;
+AT_Theme_movealpha A_Theme_movealpha;
+AT_RadialSlider_lefttop A_RadialSlider_lefttop;
+AT_Button_up A_Button_up;
+AT_RadialSlider_y A_RadialSlider_y;
+AT_CheckBox_action1 A_CheckBox_action1;
+AT_Playlist_id A_Playlist_id;
+AT_Text_align A_Text_align;
+AT_CheckBox_tooltiptext1 A_CheckBox_tooltiptext1;
+AT_Group_x A_Group_x;
+AT_Text_display A_Text_display;
+AT_Bitmap_id A_Bitmap_id;
+AT_Playlist_y A_Playlist_y;
+AT_Text_scroll A_Text_scroll;
+AT_Playlist_lefttop A_Playlist_lefttop;
+AT_Rectangle_x A_Rectangle_x;
+AT_Layout_minheight A_Layout_minheight;
+AT_Button_rightbottom A_Button_rightbottom;
+AT_Slider_thickness A_Slider_thickness;
+AT_RadialSlider_tooltiptext A_RadialSlider_tooltiptext;
+AT_RadialSlider_value A_RadialSlider_value;
+AT_Text_visible A_Text_visible;
+AT_Slider_tooltiptext A_Slider_tooltiptext;
+AT_Rectangle_onclick A_Rectangle_onclick;
+AT_Layout_width A_Layout_width;
+AT_Rectangle_help A_Rectangle_help;
+AT_CheckBox_tooltiptext2 A_CheckBox_tooltiptext2;
+AT_Layout_maxheight A_Layout_maxheight;
+AT_RadialSlider_help A_RadialSlider_help;
+AT_Playlist_font A_Playlist_font;
+AT_Rectangle_id A_Rectangle_id;
+AT_CheckBox_help A_CheckBox_help;
+AT_Image_help A_Image_help;
+AT_Playlist_bgcolor1 A_Playlist_bgcolor1;
+AT_Bitmap_alphacolor A_Bitmap_alphacolor;
+AT_Image_image A_Image_image;
+AT_Font_id A_Font_id;
+AT_Button_x A_Button_x;
+AT_CheckBox_id A_CheckBox_id;
+AT_Layout_id A_Layout_id;
+AT_Event_key A_Event_key;
+AT_CheckBox_over1 A_CheckBox_over1;
+AT_Slider_up A_Slider_up;
+AT_Layout_minwidth A_Layout_minwidth;
+AT_CheckBox_rightbottom A_CheckBox_rightbottom;
+AT_Anchor_x A_Anchor_x;
+AT_Font_font A_Font_font;
+AT_Layout_maxwidth A_Layout_maxwidth;
+AT_Playlist_help A_Playlist_help;
+AT_Playlist_visible A_Playlist_visible;
+AT_Slider_x A_Slider_x;
+AT_CheckBox_up2 A_CheckBox_up2;
+AT_Text_help A_Text_help;
+AT_CheckBox_action2 A_CheckBox_action2;
+AT_CheckBox_state A_CheckBox_state;
+AT_Font_size A_Font_size;
+AT_ThemeInfo_webpage A_ThemeInfo_webpage;
+AT_RadialSlider_x A_RadialSlider_x;
+AT_Button_tooltiptext A_Button_tooltiptext;
+AT_Image_visible A_Image_visible;
+AT_Window_visible A_Window_visible;
+AT_RadialSlider_id A_RadialSlider_id;
+AT_Anchor_y A_Anchor_y;
+AT_RadialSlider_nbimages A_RadialSlider_nbimages;
+AT_Playlist_bgcolor2 A_Playlist_bgcolor2;
+AT_Playlist_x A_Playlist_x;
+AT_ThemeInfo_email A_ThemeInfo_email;
+AT_Window_x A_Window_x;
+AT_Button_down A_Button_down;
+AT_Playlist_height A_Playlist_height;
+AT_Layout_height A_Layout_height;
+AT_ThemeInfo_name A_ThemeInfo_name;
+AT_Button_help A_Button_help;
+AT_Text_y A_Text_y;
+AT_Rectangle_w A_Rectangle_w;
+AT_Image_x A_Image_x;
+AT_Rectangle_y A_Rectangle_y;
+AT_Playlist_selcolor A_Playlist_selcolor;
+AT_RadialSlider_rightbottom A_RadialSlider_rightbottom;
+
+/* XML state. */
+#ifdef FLEX_DEBUG
+# define ENTER(state)  debug_enter(state,#state)
+# define LEAVE         debug_leave()
+# define SET(state)    debug_set(state,#state)
+  static void debug_enter(int, char*);
+  static void debug_leave(void);
+  static void debug_set(int, char*);
+#else
+# define ENTER(state)  (yy_push_state(state))
+# define LEAVE         (yy_pop_state())
+# define SET(state)    BEGIN(state)
+#endif
+
+/* Generic actions. */
+#define SKIP   /*skip*/
+#define SUCCEED        return 0
+
+#define FAIL   return fail
+static int fail(const char*, ...);
+
+/* Text buffer stack handling. */
+char bufferstack[FLEXML_BUFFERSTACKSIZE];
+char* limit = bufferstack + FLEXML_BUFFERSTACKSIZE;
+typedef struct BufferLast_s {
+  struct BufferLast_s *old; char* saved; char new[1];
+} BufferLast;
+BufferLast* last = (BufferLast*)0;
+char* next = bufferstack;
+
+#define BUFFERSET(P)  (P = next)
+#define BUFFERPUTC(C) (assert(next<limit), *(next++) = (C))
+#define BUFFERDONE    (BUFFERPUTC('\0'))
+
+#define BUFFERLITERAL(C,P) bufferliteral(C,&(P),yytext)
+static void bufferliteral(char c, char** pp, char* text)
+{
+  char *s = strchr(text,c), *e = strrchr(text,c);
+  assert(s <= e); BUFFERSET(*pp);
+  while (++s<e) {
+    if (isspace(*s)) { BUFFERPUTC(' '); while (isspace(*s)) ++s; }
+    else BUFFERPUTC(*s);
+  } 
+  BUFFERDONE;
+}
+
+#ifdef FLEXML_HasMixed
+static void pushbuffer(char* p)
+{
+  BufferLast* l = (BufferLast*)next;
+  assert(next < limit);
+  l->old = last;
+  l->saved = p;
+  next = l->new;
+  last = l;
+}
+
+static char* popbuffer(void)
+{
+  BufferLast* l = last;
+  assert(last != (BufferLast*)0);
+  last = l->old;
+  next = (char*)l;
+  return l->saved;
+}
+#endif
+
+/* General internal entities are `unput' back onto the input stream... */
+#define ENTITYTEXT(T) \
+  { char *s = (T), *e = s+strlen(s);\
+    while (--e >= s) { unput(*e); }}
+/* Flex standard options. */
+#define YY_STACK_USED 1
+#define YY_NO_TOP_STATE 1
+#define YY_NO_INPUT 1
+/* Flex user-requested options. */
+#define YY_NO_UNPUT 1
+/* XML character classes (currently restricted to ASCII). */
+/* "Common syntactic structures." */
+/* "Names and Tokens." */
+/* Miscellaneous. */
+/* Parser states (flex `exclusive start conditions'):
+ *
+ * PROLOG      the XML prolog of the document before <?xml...>
+ * DOCTYPE     the XML prolog of the document after <?xml...>
+ * EPILOG      after the root element
+ * INCOMMENT   inside an XML comment <!--....-->
+ * INPI                inside an XML PI <?...?>
+ * VALUE1      inside a '...'-delimited literal
+ * VALUE2      inside a "..."-delimited literal
+ * CDATA       inside a <![CDATA[...]]> section.
+ * ROOT_<tag>  expect root element <tag>
+ * AL_<tag>    inside the attribute list for <tag>
+ * IN_<tag>    inside a <tag> with element contents (ready for end tag)
+ * IMPOSSIBLE  dummy to permit disabling rules; must be last
+ */
+#define PROLOG 1
+#define DOCTYPE 2
+#define EPILOG 3
+#define INCOMMENT 4
+#define INPI 5
+#define VALUE1 6
+#define VALUE2 7
+#define CDATA 8
+
+#define ROOT_Theme 9
+#define AL_Theme 10
+#define S_Theme 11
+#define S_Theme_1 12
+#define S_Theme_2 13
+#define S_Theme_3 14
+#define E_Theme 15
+
+#define ROOT_Bitmap 16
+#define AL_Bitmap 17
+#define E_Bitmap 18
+
+#define ROOT_Event 19
+#define AL_Event 20
+#define E_Event 21
+
+#define ROOT_Font 22
+#define AL_Font 23
+#define E_Font 24
+
+#define ROOT_ThemeInfo 25
+#define AL_ThemeInfo 26
+#define E_ThemeInfo 27
+
+#define ROOT_Window 28
+#define AL_Window 29
+#define S_Window 30
+#define S_Window_1 31
+#define S_Window_2 32
+#define E_Window 33
+
+#define ROOT_Layout 34
+#define AL_Layout 35
+#define S_Layout 36
+#define E_Layout 37
+
+#define ROOT_Group 38
+#define AL_Group 39
+#define S_Group 40
+#define S_Group_1 41
+#define S_Group_2 42
+#define E_Group 43
+
+#define ROOT_Anchor 44
+#define AL_Anchor 45
+#define E_Anchor 46
+
+#define ROOT_Image 47
+#define AL_Image 48
+#define E_Image 49
+
+#define ROOT_Rectangle 50
+#define AL_Rectangle 51
+#define E_Rectangle 52
+
+#define ROOT_Button 53
+#define AL_Button 54
+#define E_Button 55
+
+#define ROOT_CheckBox 56
+#define AL_CheckBox 57
+#define E_CheckBox 58
+
+#define ROOT_Slider 59
+#define AL_Slider 60
+#define E_Slider 61
+
+#define ROOT_RadialSlider 62
+#define AL_RadialSlider 63
+#define E_RadialSlider 64
+
+#define ROOT_Text 65
+#define AL_Text 66
+#define E_Text 67
+
+#define ROOT_Playlist 68
+#define AL_Playlist 69
+#define S_Playlist 70
+#define E_Playlist 71
+
+#define IMPOSSIBLE 72
+
+/* State names. */
+char* statenames[IMPOSSIBLE];
+
+void FleXML_init(void)
+{
+  statenames[PROLOG] = NULL;
+  statenames[DOCTYPE] = NULL;
+  statenames[EPILOG] = NULL;
+  statenames[INCOMMENT] = NULL;
+  statenames[INPI] = NULL;
+  statenames[VALUE1] = NULL;
+  statenames[VALUE2] = NULL;
+  statenames[CDATA] = NULL;
+  statenames[ROOT_Theme] = NULL;
+  statenames[AL_Theme] = NULL;
+  statenames[S_Theme] = "Theme";
+  statenames[S_Theme_1] = "Theme";
+  statenames[S_Theme_2] = "Theme";
+  statenames[S_Theme_3] = "Theme";
+  statenames[E_Theme] = "Theme";
+  statenames[ROOT_Bitmap] = NULL;
+  statenames[AL_Bitmap] = NULL;
+  statenames[E_Bitmap] = "Bitmap";
+  statenames[ROOT_Event] = NULL;
+  statenames[AL_Event] = NULL;
+  statenames[E_Event] = "Event";
+  statenames[ROOT_Font] = NULL;
+  statenames[AL_Font] = NULL;
+  statenames[E_Font] = "Font";
+  statenames[ROOT_ThemeInfo] = NULL;
+  statenames[AL_ThemeInfo] = NULL;
+  statenames[E_ThemeInfo] = "ThemeInfo";
+  statenames[ROOT_Window] = NULL;
+  statenames[AL_Window] = NULL;
+  statenames[S_Window] = "Window";
+  statenames[S_Window_1] = "Window";
+  statenames[S_Window_2] = "Window";
+  statenames[E_Window] = "Window";
+  statenames[ROOT_Layout] = NULL;
+  statenames[AL_Layout] = NULL;
+  statenames[S_Layout] = "Layout";
+  statenames[E_Layout] = "Layout";
+  statenames[ROOT_Group] = NULL;
+  statenames[AL_Group] = NULL;
+  statenames[S_Group] = "Group";
+  statenames[S_Group_1] = "Group";
+  statenames[S_Group_2] = "Group";
+  statenames[E_Group] = "Group";
+  statenames[ROOT_Anchor] = NULL;
+  statenames[AL_Anchor] = NULL;
+  statenames[E_Anchor] = "Anchor";
+  statenames[ROOT_Image] = NULL;
+  statenames[AL_Image] = NULL;
+  statenames[E_Image] = "Image";
+  statenames[ROOT_Rectangle] = NULL;
+  statenames[AL_Rectangle] = NULL;
+  statenames[E_Rectangle] = "Rectangle";
+  statenames[ROOT_Button] = NULL;
+  statenames[AL_Button] = NULL;
+  statenames[E_Button] = "Button";
+  statenames[ROOT_CheckBox] = NULL;
+  statenames[AL_CheckBox] = NULL;
+  statenames[E_CheckBox] = "CheckBox";
+  statenames[ROOT_Slider] = NULL;
+  statenames[AL_Slider] = NULL;
+  statenames[E_Slider] = "Slider";
+  statenames[ROOT_RadialSlider] = NULL;
+  statenames[AL_RadialSlider] = NULL;
+  statenames[E_RadialSlider] = "RadialSlider";
+  statenames[ROOT_Text] = NULL;
+  statenames[AL_Text] = NULL;
+  statenames[E_Text] = "Text";
+  statenames[ROOT_Playlist] = NULL;
+  statenames[AL_Playlist] = NULL;
+  statenames[S_Playlist] = "Playlist";
+  statenames[E_Playlist] = "Playlist";
+}
+
+/* Macros after this point can all be overridden by user definitions in
+ * section 1.
+ */
+
+#ifndef YY_SKIP_YYWRAP
+#ifdef __cplusplus
+extern "C" int yywrap YY_PROTO(( void ));
+#else
+extern int yywrap YY_PROTO(( void ));
+#endif
+#endif
+
+#ifndef YY_NO_UNPUT
+static void yyunput YY_PROTO(( int c, char *buf_ptr ));
+#endif
+
+#ifndef yytext_ptr
+static void yy_flex_strncpy YY_PROTO(( char *, yyconst char *, int ));
+#endif
+
+#ifdef YY_NEED_STRLEN
+static int yy_flex_strlen YY_PROTO(( yyconst char * ));
+#endif
+
+#ifndef YY_NO_INPUT
+#ifdef __cplusplus
+static int yyinput YY_PROTO(( void ));
+#else
+static int input YY_PROTO(( void ));
+#endif
+#endif
+
+#if YY_STACK_USED
+static int yy_start_stack_ptr = 0;
+static int yy_start_stack_depth = 0;
+static int *yy_start_stack = 0;
+#ifndef YY_NO_PUSH_STATE
+static void yy_push_state YY_PROTO(( int new_state ));
+#endif
+#ifndef YY_NO_POP_STATE
+static void yy_pop_state YY_PROTO(( void ));
+#endif
+#ifndef YY_NO_TOP_STATE
+static int yy_top_state YY_PROTO(( void ));
+#endif
+
+#else
+#define YY_NO_PUSH_STATE 1
+#define YY_NO_POP_STATE 1
+#define YY_NO_TOP_STATE 1
+#endif
+
+#ifdef YY_MALLOC_DECL
+YY_MALLOC_DECL
+#else
+#if __STDC__
+#ifndef __cplusplus
+#include <stdlib.h>
+#endif
+#else
+/* Just try to get by without declaring the routines.  This will fail
+ * miserably on non-ANSI systems for which sizeof(size_t) != sizeof(int)
+ * or sizeof(void*) != sizeof(int).
+ */
+#endif
+#endif
+
+/* Amount of stuff to slurp up with each read. */
+#ifndef YY_READ_BUF_SIZE
+#define YY_READ_BUF_SIZE 8192
+#endif
+
+/* Copy whatever the last rule matched to the standard output. */
+
+#ifndef ECHO
+/* This used to be an fputs(), but since the string might contain NUL's,
+ * we now use fwrite().
+ */
+#define ECHO (void) fwrite( yytext, yyleng, 1, yyout )
+#endif
+
+/* Gets input and stuffs it into "buf".  number of characters read, or YY_NULL,
+ * is returned in "result".
+ */
+#ifndef YY_INPUT
+#define YY_INPUT(buf,result,max_size) \
+       if ( yy_current_buffer->yy_is_interactive ) \
+               { \
+               int c = '*', n; \
+               for ( n = 0; n < max_size && \
+                            (c = getc( yyin )) != EOF && c != '\n'; ++n ) \
+                       buf[n] = (char) c; \
+               if ( c == '\n' ) \
+                       buf[n++] = (char) c; \
+               if ( c == EOF && ferror( yyin ) ) \
+                       YY_FATAL_ERROR( "input in flex scanner failed" ); \
+               result = n; \
+               } \
+       else \
+               { \
+               errno=0; \
+               while ( (result = fread(buf, 1, max_size, yyin))==0 && ferror(yyin)) \
+                       { \
+                       if( errno != EINTR) \
+                               { \
+                               YY_FATAL_ERROR( "input in flex scanner failed" ); \
+                               break; \
+                               } \
+                       errno=0; \
+                       clearerr(yyin); \
+                       } \
+               }
+#endif
+
+/* No semi-colon after return; correct usage is to write "yyterminate();" -
+ * we don't want an extra ';' after the "return" because that will cause
+ * some compilers to complain about unreachable statements.
+ */
+#ifndef yyterminate
+#define yyterminate() return YY_NULL
+#endif
+
+/* Number of entries by which start-condition stack grows. */
+#ifndef YY_START_STACK_INCR
+#define YY_START_STACK_INCR 25
+#endif
+
+/* Report a fatal error. */
+#ifndef YY_FATAL_ERROR
+#define YY_FATAL_ERROR(msg) yy_fatal_error( msg )
+#endif
+
+/* Default declaration of generated scanner - a define so the user can
+ * easily add parameters.
+ */
+#ifndef YY_DECL
+#define YY_DECL int yylex YY_PROTO(( void ))
+#endif
+
+/* Code executed at the beginning of each rule, after yytext and yyleng
+ * have been set up.
+ */
+#ifndef YY_USER_ACTION
+#define YY_USER_ACTION
+#endif
+
+/* Code executed at the end of each rule. */
+#ifndef YY_BREAK
+#define YY_BREAK break;
+#endif
+
+#define YY_RULE_SETUP \
+       YY_USER_ACTION
+
+YY_DECL
+       {
+       register yy_state_type yy_current_state;
+       register char *yy_cp, *yy_bp;
+       register int yy_act;
+
+
+
+ /* Bypass Flex's default INITIAL state and begin by parsing the XML prolog. */
+ SET(PROLOG); FleXML_init();
+
+ /* COMMENTS and PIs: handled uniformly for efficiency. */
+
+
+       if ( yy_init )
+               {
+               yy_init = 0;
+
+#ifdef YY_USER_INIT
+               YY_USER_INIT;
+#endif
+
+               if ( ! yy_start )
+                       yy_start = 1;   /* first start state */
+
+               if ( ! yyin )
+                       yyin = stdin;
+
+               if ( ! yyout )
+                       yyout = stdout;
+
+               if ( ! yy_current_buffer )
+                       yy_current_buffer =
+                               yy_create_buffer( yyin, YY_BUF_SIZE );
+
+               yy_load_buffer_state();
+               }
+
+       while ( 1 )             /* loops until end-of-file is reached */
+               {
+               yy_cp = yy_c_buf_p;
+
+               /* Support of yytext. */
+               *yy_cp = yy_hold_char;
+
+               /* yy_bp points to the position in yy_ch_buf of the start of
+                * the current run.
+                */
+               yy_bp = yy_cp;
+
+               yy_current_state = yy_start;
+yy_match:
+               do
+                       {
+                       register YY_CHAR yy_c = yy_ec[YY_SC_TO_UI(*yy_cp)];
+                       if ( yy_accept[yy_current_state] )
+                               {
+                               yy_last_accepting_state = yy_current_state;
+                               yy_last_accepting_cpos = yy_cp;
+                               }
+                       while ( yy_chk[yy_base[yy_current_state] + yy_c] != yy_current_state )
+                               {
+                               yy_current_state = (int) yy_def[yy_current_state];
+                               if ( yy_current_state >= 2803 )
+                                       yy_c = yy_meta[(unsigned int) yy_c];
+                               }
+                       yy_current_state = yy_nxt[yy_base[yy_current_state] + (unsigned int) yy_c];
+                       ++yy_cp;
+                       }
+               while ( yy_current_state != 2802 );
+               yy_cp = yy_last_accepting_cpos;
+               yy_current_state = yy_last_accepting_state;
+
+yy_find_action:
+               yy_act = yy_accept[yy_current_state];
+
+               YY_DO_BEFORE_ACTION;
+
+
+do_action:     /* This label is used only to access EOF actions. */
+
+
+               switch ( yy_act )
+       { /* beginning of action switch */
+                       case 0: /* must back up */
+                       /* undo the effects of YY_DO_BEFORE_ACTION */
+                       *yy_cp = yy_hold_char;
+                       yy_cp = yy_last_accepting_cpos;
+                       yy_current_state = yy_last_accepting_state;
+                       goto yy_find_action;
+
+
+case 1:
+YY_RULE_SETUP
+ENTER(INCOMMENT);
+       YY_BREAK
+case 2:
+YY_RULE_SETUP
+ENTER(INPI);
+       YY_BREAK
+
+
+case 3:
+YY_RULE_SETUP
+LEAVE;
+       YY_BREAK
+case 4:
+case 5:
+case 6:
+YY_RULE_SETUP
+SKIP;
+       YY_BREAK
+case YY_STATE_EOF(INCOMMENT):
+FAIL("EOF in comment.");
+       YY_BREAK
+
+
+case 7:
+YY_RULE_SETUP
+LEAVE;
+       YY_BREAK
+case 8:
+case 9:
+YY_RULE_SETUP
+SKIP;
+       YY_BREAK
+case YY_STATE_EOF(INPI):
+FAIL("EOF in PI (processing instruction).");
+       YY_BREAK
+
+/* SPACES: skipped uniformly */
+case 10:
+YY_RULE_SETUP
+SKIP;
+       YY_BREAK
+/* PROLOG: determine root element and process it. */
+
+case 11:
+YY_RULE_SETUP
+SET(DOCTYPE);
+       YY_BREAK
+case 12:
+YY_RULE_SETUP
+FAIL("Bad declaration %s.",yytext);
+       YY_BREAK
+
+
+case 13:
+YY_RULE_SETUP
+SET(ROOT_Layout);
+       YY_BREAK
+case 14:
+YY_RULE_SETUP
+SET(ROOT_Event);
+       YY_BREAK
+case 15:
+YY_RULE_SETUP
+SET(ROOT_Image);
+       YY_BREAK
+case 16:
+YY_RULE_SETUP
+SET(ROOT_Playlist);
+       YY_BREAK
+case 17:
+YY_RULE_SETUP
+SET(ROOT_Text);
+       YY_BREAK
+case 18:
+YY_RULE_SETUP
+SET(ROOT_Rectangle);
+       YY_BREAK
+case 19:
+YY_RULE_SETUP
+SET(ROOT_Anchor);
+       YY_BREAK
+case 20:
+YY_RULE_SETUP
+SET(ROOT_Group);
+       YY_BREAK
+case 21:
+YY_RULE_SETUP
+SET(ROOT_Theme);
+       YY_BREAK
+case 22:
+YY_RULE_SETUP
+SET(ROOT_Font);
+       YY_BREAK
+case 23:
+YY_RULE_SETUP
+SET(ROOT_RadialSlider);
+       YY_BREAK
+case 24:
+YY_RULE_SETUP
+SET(ROOT_ThemeInfo);
+       YY_BREAK
+case 25:
+YY_RULE_SETUP
+SET(ROOT_Slider);
+       YY_BREAK
+case 26:
+YY_RULE_SETUP
+SET(ROOT_CheckBox);
+       YY_BREAK
+case 27:
+YY_RULE_SETUP
+SET(ROOT_Button);
+       YY_BREAK
+case 28:
+YY_RULE_SETUP
+SET(ROOT_Bitmap);
+       YY_BREAK
+case 29:
+YY_RULE_SETUP
+SET(ROOT_Window);
+       YY_BREAK
+case 30:
+YY_RULE_SETUP
+FAIL("Bad declaration %s.",yytext);
+       YY_BREAK
+case 31:
+YY_RULE_SETUP
+FAIL("Unexpected character `%c' in prolog.", yytext[0]);
+       YY_BREAK
+case YY_STATE_EOF(PROLOG):
+case YY_STATE_EOF(DOCTYPE):
+FAIL("EOF in prolog.");
+       YY_BREAK
+
+/* RULES DERIVED FROM DTD. */
+/* <!--
+  * -->  */
+/*         version     CDATA   "1.0"
+  *         magnet      CDATA   "15"
+  *         alpha       CDATA   "255"
+  *         movealpha   CDATA   "255"
+  *         fadetime    CDATA   "400"
+  *     >  */
+case 32:
+YY_RULE_SETUP
+{
+  A_Theme_version = "1.0";
+  A_Theme_magnet = "15";
+  A_Theme_alpha = "255";
+  A_Theme_movealpha = "255";
+  A_Theme_fadetime = "400";
+  ENTER(AL_Theme);
+}
+       YY_BREAK
+
+case 33:
+YY_RULE_SETUP
+ENTER(VALUE1); BUFFERSET(A_Theme_version);
+       YY_BREAK
+case 34:
+YY_RULE_SETUP
+ENTER(VALUE2); BUFFERSET(A_Theme_version);
+       YY_BREAK
+case 35:
+YY_RULE_SETUP
+ENTER(VALUE1); BUFFERSET(A_Theme_magnet);
+       YY_BREAK
+case 36:
+YY_RULE_SETUP
+ENTER(VALUE2); BUFFERSET(A_Theme_magnet);
+       YY_BREAK
+case 37:
+YY_RULE_SETUP
+ENTER(VALUE1); BUFFERSET(A_Theme_alpha);
+       YY_BREAK
+case 38:
+YY_RULE_SETUP
+ENTER(VALUE2); BUFFERSET(A_Theme_alpha);
+       YY_BREAK
+case 39:
+YY_RULE_SETUP
+ENTER(VALUE1); BUFFERSET(A_Theme_movealpha);
+       YY_BREAK
+case 40:
+YY_RULE_SETUP
+ENTER(VALUE2); BUFFERSET(A_Theme_movealpha);
+       YY_BREAK
+case 41:
+YY_RULE_SETUP
+ENTER(VALUE1); BUFFERSET(A_Theme_fadetime);
+       YY_BREAK
+case 42:
+YY_RULE_SETUP
+ENTER(VALUE2); BUFFERSET(A_Theme_fadetime);
+       YY_BREAK
+case 43:
+YY_RULE_SETUP
+{
+  LEAVE; STag_Theme(pContext); pcdata = NULL; ENTER(S_Theme);
+ }
+       YY_BREAK
+case 44:
+YY_RULE_SETUP
+FAIL("`Theme' element cannot be empty.");
+       YY_BREAK
+case 45:
+YY_RULE_SETUP
+FAIL("Unexpected character `%c' in attribute list of Theme element.", yytext[0]);
+       YY_BREAK
+case 46:
+YY_RULE_SETUP
+FAIL("Bad attribute `%s' in `Theme' element start tag.",yytext);
+       YY_BREAK
+case YY_STATE_EOF(AL_Theme):
+FAIL("EOF in attribute list of `Theme' element.");
+       YY_BREAK
+
+
+case 47:
+YY_RULE_SETUP
+{
+  LEAVE;
+  ETag_Theme(pContext);
+  switch (YY_START) {
+   case ROOT_Theme: SET(EPILOG); break;
+  }
+ }
+       YY_BREAK
+case 48:
+YY_RULE_SETUP
+FAIL("Unexpected end-tag `%s': `</Theme>' expected.",yytext);
+       YY_BREAK
+case 49:
+YY_RULE_SETUP
+FAIL("Unexpected character `%c': `</Theme>' expected.",yytext[0]);
+       YY_BREAK
+case YY_STATE_EOF(E_Theme):
+case YY_STATE_EOF(S_Theme_1):
+case YY_STATE_EOF(S_Theme_3):
+FAIL("Premature EOF: `</Theme>' expected.");
+       YY_BREAK
+
+/* <!-- main elements -->  */
+/*         id          CDATA   #REQUIRED
+  *         file        CDATA   #REQUIRED
+  *         alphacolor  CDATA   #REQUIRED
+  *     >  */
+case 50:
+YY_RULE_SETUP
+{
+  A_Bitmap_id = NULL;
+  A_Bitmap_file = NULL;
+  A_Bitmap_alphacolor = NULL;
+  ENTER(AL_Bitmap);
+}
+       YY_BREAK
+
+case 51:
+YY_RULE_SETUP
+ENTER(VALUE1); BUFFERSET(A_Bitmap_id);
+       YY_BREAK
+case 52:
+YY_RULE_SETUP
+ENTER(VALUE2); BUFFERSET(A_Bitmap_id);
+       YY_BREAK
+case 53:
+YY_RULE_SETUP
+ENTER(VALUE1); BUFFERSET(A_Bitmap_file);
+       YY_BREAK
+case 54:
+YY_RULE_SETUP
+ENTER(VALUE2); BUFFERSET(A_Bitmap_file);
+       YY_BREAK
+case 55:
+YY_RULE_SETUP
+ENTER(VALUE1); BUFFERSET(A_Bitmap_alphacolor);
+       YY_BREAK
+case 56:
+YY_RULE_SETUP
+ENTER(VALUE2); BUFFERSET(A_Bitmap_alphacolor);
+       YY_BREAK
+case 57:
+YY_RULE_SETUP
+{
+  if (!A_Bitmap_id) FAIL("Required attribute `id' not set for `Bitmap' element.");
+  if (!A_Bitmap_file) FAIL("Required attribute `file' not set for `Bitmap' element.");
+  if (!A_Bitmap_alphacolor) FAIL("Required attribute `alphacolor' not set for `Bitmap' element.");
+  LEAVE; STag_Bitmap(pContext); pcdata = NULL; ENTER(E_Bitmap);
+ }
+       YY_BREAK
+case 58:
+YY_RULE_SETUP
+{
+  if (!A_Bitmap_id) FAIL("Required attribute `id' not set for `Bitmap' element.");
+  if (!A_Bitmap_file) FAIL("Required attribute `file' not set for `Bitmap' element.");
+  if (!A_Bitmap_alphacolor) FAIL("Required attribute `alphacolor' not set for `Bitmap' element.");
+  LEAVE; STag_Bitmap(pContext); pcdata = NULL; ETag_Bitmap(pContext);
+  switch (YY_START) {
+   case S_Theme_2: case S_Theme_1: case S_Theme_3: SET(S_Theme_3); break;
+   case ROOT_Bitmap: SET(EPILOG); break;
+  }
+ }
+       YY_BREAK
+case 59:
+YY_RULE_SETUP
+FAIL("Unexpected character `%c' in attribute list of Bitmap element.", yytext[0]);
+       YY_BREAK
+case 60:
+YY_RULE_SETUP
+FAIL("Bad attribute `%s' in `Bitmap' element start tag.",yytext);
+       YY_BREAK
+case YY_STATE_EOF(AL_Bitmap):
+FAIL("EOF in attribute list of `Bitmap' element.");
+       YY_BREAK
+
+
+case 61:
+YY_RULE_SETUP
+{
+  LEAVE;
+  ETag_Bitmap(pContext);
+  switch (YY_START) {
+   case S_Theme_2: case S_Theme_1: case S_Theme_3: SET(S_Theme_3); break;
+   case ROOT_Bitmap: SET(EPILOG); break;
+  }
+ }
+       YY_BREAK
+case 62:
+YY_RULE_SETUP
+FAIL("Unexpected end-tag `%s': `</Bitmap>' expected.",yytext);
+       YY_BREAK
+case 63:
+YY_RULE_SETUP
+FAIL("Unexpected character `%c': `</Bitmap>' expected.",yytext[0]);
+       YY_BREAK
+case YY_STATE_EOF(E_Bitmap):
+FAIL("Premature EOF: `</Bitmap>' expected.");
+       YY_BREAK
+
+/*         id          CDATA   #REQUIRED
+  *         event       CDATA   #REQUIRED
+  *         key         CDATA   "none"
+  *     >  */
+case 64:
+YY_RULE_SETUP
+{
+  A_Event_id = NULL;
+  A_Event_event = NULL;
+  A_Event_key = "none";
+  ENTER(AL_Event);
+}
+       YY_BREAK
+
+case 65:
+YY_RULE_SETUP
+ENTER(VALUE1); BUFFERSET(A_Event_id);
+       YY_BREAK
+case 66:
+YY_RULE_SETUP
+ENTER(VALUE2); BUFFERSET(A_Event_id);
+       YY_BREAK
+case 67:
+YY_RULE_SETUP
+ENTER(VALUE1); BUFFERSET(A_Event_event);
+       YY_BREAK
+case 68:
+YY_RULE_SETUP
+ENTER(VALUE2); BUFFERSET(A_Event_event);
+       YY_BREAK
+case 69:
+YY_RULE_SETUP
+ENTER(VALUE1); BUFFERSET(A_Event_key);
+       YY_BREAK
+case 70:
+YY_RULE_SETUP
+ENTER(VALUE2); BUFFERSET(A_Event_key);
+       YY_BREAK
+case 71:
+YY_RULE_SETUP
+{
+  if (!A_Event_id) FAIL("Required attribute `id' not set for `Event' element.");
+  if (!A_Event_event) FAIL("Required attribute `event' not set for `Event' element.");
+  LEAVE; STag_Event(pContext); pcdata = NULL; ENTER(E_Event);
+ }
+       YY_BREAK
+case 72:
+YY_RULE_SETUP
+{
+  if (!A_Event_id) FAIL("Required attribute `id' not set for `Event' element.");
+  if (!A_Event_event) FAIL("Required attribute `event' not set for `Event' element.");
+  LEAVE; STag_Event(pContext); pcdata = NULL; ETag_Event(pContext);
+  switch (YY_START) {
+   case S_Theme_2: case S_Theme_1: case S_Theme_3: SET(S_Theme_3); break;
+   case ROOT_Event: SET(EPILOG); break;
+  }
+ }
+       YY_BREAK
+case 73:
+YY_RULE_SETUP
+FAIL("Unexpected character `%c' in attribute list of Event element.", yytext[0]);
+       YY_BREAK
+case 74:
+YY_RULE_SETUP
+FAIL("Bad attribute `%s' in `Event' element start tag.",yytext);
+       YY_BREAK
+case YY_STATE_EOF(AL_Event):
+FAIL("EOF in attribute list of `Event' element.");
+       YY_BREAK
+
+
+case 75:
+YY_RULE_SETUP
+{
+  LEAVE;
+  ETag_Event(pContext);
+  switch (YY_START) {
+   case S_Theme_2: case S_Theme_1: case S_Theme_3: SET(S_Theme_3); break;
+   case ROOT_Event: SET(EPILOG); break;
+  }
+ }
+       YY_BREAK
+case 76:
+YY_RULE_SETUP
+FAIL("Unexpected end-tag `%s': `</Event>' expected.",yytext);
+       YY_BREAK
+case 77:
+YY_RULE_SETUP
+FAIL("Unexpected character `%c': `</Event>' expected.",yytext[0]);
+       YY_BREAK
+case YY_STATE_EOF(E_Event):
+FAIL("Premature EOF: `</Event>' expected.");
+       YY_BREAK
+
+/*         id          CDATA   #REQUIRED
+  *         font        CDATA   "arial"
+  *         size        CDATA   "12"
+  *         color       CDATA   "#000000"
+  *         italic      CDATA   "false"
+  *         underline   CDATA   "false"
+  *     >  */
+case 78:
+YY_RULE_SETUP
+{
+  A_Font_id = NULL;
+  A_Font_font = "arial";
+  A_Font_size = "12";
+  A_Font_color = "#000000";
+  A_Font_italic = "false";
+  A_Font_underline = "false";
+  ENTER(AL_Font);
+}
+       YY_BREAK
+
+case 79:
+YY_RULE_SETUP
+ENTER(VALUE1); BUFFERSET(A_Font_id);
+       YY_BREAK
+case 80:
+YY_RULE_SETUP
+ENTER(VALUE2); BUFFERSET(A_Font_id);
+       YY_BREAK
+case 81:
+YY_RULE_SETUP
+ENTER(VALUE1); BUFFERSET(A_Font_font);
+       YY_BREAK
+case 82:
+YY_RULE_SETUP
+ENTER(VALUE2); BUFFERSET(A_Font_font);
+       YY_BREAK
+case 83:
+YY_RULE_SETUP
+ENTER(VALUE1); BUFFERSET(A_Font_size);
+       YY_BREAK
+case 84:
+YY_RULE_SETUP
+ENTER(VALUE2); BUFFERSET(A_Font_size);
+       YY_BREAK
+case 85:
+YY_RULE_SETUP
+ENTER(VALUE1); BUFFERSET(A_Font_color);
+       YY_BREAK
+case 86:
+YY_RULE_SETUP
+ENTER(VALUE2); BUFFERSET(A_Font_color);
+       YY_BREAK
+case 87:
+YY_RULE_SETUP
+ENTER(VALUE1); BUFFERSET(A_Font_italic);
+       YY_BREAK
+case 88:
+YY_RULE_SETUP
+ENTER(VALUE2); BUFFERSET(A_Font_italic);
+       YY_BREAK
+case 89:
+YY_RULE_SETUP
+ENTER(VALUE1); BUFFERSET(A_Font_underline);
+       YY_BREAK
+case 90:
+YY_RULE_SETUP
+ENTER(VALUE2); BUFFERSET(A_Font_underline);
+       YY_BREAK
+case 91:
+YY_RULE_SETUP
+{
+  if (!A_Font_id) FAIL("Required attribute `id' not set for `Font' element.");
+  LEAVE; STag_Font(pContext); pcdata = NULL; ENTER(E_Font);
+ }
+       YY_BREAK
+case 92:
+YY_RULE_SETUP
+{
+  if (!A_Font_id) FAIL("Required attribute `id' not set for `Font' element.");
+  LEAVE; STag_Font(pContext); pcdata = NULL; ETag_Font(pContext);
+  switch (YY_START) {
+   case ROOT_Font: SET(EPILOG); break;
+   case S_Theme_2: case S_Theme_1: case S_Theme_3: SET(S_Theme_3); break;
+  }
+ }
+       YY_BREAK
+case 93:
+YY_RULE_SETUP
+FAIL("Unexpected character `%c' in attribute list of Font element.", yytext[0]);
+       YY_BREAK
+case 94:
+YY_RULE_SETUP
+FAIL("Bad attribute `%s' in `Font' element start tag.",yytext);
+       YY_BREAK
+case YY_STATE_EOF(AL_Font):
+FAIL("EOF in attribute list of `Font' element.");
+       YY_BREAK
+
+
+case 95:
+YY_RULE_SETUP
+{
+  LEAVE;
+  ETag_Font(pContext);
+  switch (YY_START) {
+   case ROOT_Font: SET(EPILOG); break;
+   case S_Theme_2: case S_Theme_1: case S_Theme_3: SET(S_Theme_3); break;
+  }
+ }
+       YY_BREAK
+case 96:
+YY_RULE_SETUP
+FAIL("Unexpected end-tag `%s': `</Font>' expected.",yytext);
+       YY_BREAK
+case 97:
+YY_RULE_SETUP
+FAIL("Unexpected character `%c': `</Font>' expected.",yytext[0]);
+       YY_BREAK
+case YY_STATE_EOF(E_Font):
+FAIL("Premature EOF: `</Font>' expected.");
+       YY_BREAK
+
+/*         name        CDATA   #IMPLIED
+  *         author      CDATA   #IMPLIED
+  *         email       CDATA   #IMPLIED
+  *         webpage     CDATA   #IMPLIED
+  *     >  */
+case 98:
+YY_RULE_SETUP
+{
+  A_ThemeInfo_name = NULL;
+  A_ThemeInfo_author = NULL;
+  A_ThemeInfo_email = NULL;
+  A_ThemeInfo_webpage = NULL;
+  ENTER(AL_ThemeInfo);
+}
+       YY_BREAK
+
+case 99:
+YY_RULE_SETUP
+ENTER(VALUE1); BUFFERSET(A_ThemeInfo_name);
+       YY_BREAK
+case 100:
+YY_RULE_SETUP
+ENTER(VALUE2); BUFFERSET(A_ThemeInfo_name);
+       YY_BREAK
+case 101:
+YY_RULE_SETUP
+ENTER(VALUE1); BUFFERSET(A_ThemeInfo_author);
+       YY_BREAK
+case 102:
+YY_RULE_SETUP
+ENTER(VALUE2); BUFFERSET(A_ThemeInfo_author);
+       YY_BREAK
+case 103:
+YY_RULE_SETUP
+ENTER(VALUE1); BUFFERSET(A_ThemeInfo_email);
+       YY_BREAK
+case 104:
+YY_RULE_SETUP
+ENTER(VALUE2); BUFFERSET(A_ThemeInfo_email);
+       YY_BREAK
+case 105:
+YY_RULE_SETUP
+ENTER(VALUE1); BUFFERSET(A_ThemeInfo_webpage);
+       YY_BREAK
+case 106:
+YY_RULE_SETUP
+ENTER(VALUE2); BUFFERSET(A_ThemeInfo_webpage);
+       YY_BREAK
+case 107:
+YY_RULE_SETUP
+{
+  LEAVE; STag_ThemeInfo(pContext); pcdata = NULL; ENTER(E_ThemeInfo);
+ }
+       YY_BREAK
+case 108:
+YY_RULE_SETUP
+{
+  LEAVE; STag_ThemeInfo(pContext); pcdata = NULL; ETag_ThemeInfo(pContext);
+  switch (YY_START) {
+   case S_Theme: SET(S_Theme_1); break;
+   case ROOT_ThemeInfo: SET(EPILOG); break;
+  }
+ }
+       YY_BREAK
+case 109:
+YY_RULE_SETUP
+FAIL("Unexpected character `%c' in attribute list of ThemeInfo element.", yytext[0]);
+       YY_BREAK
+case 110:
+YY_RULE_SETUP
+FAIL("Bad attribute `%s' in `ThemeInfo' element start tag.",yytext);
+       YY_BREAK
+case YY_STATE_EOF(AL_ThemeInfo):
+FAIL("EOF in attribute list of `ThemeInfo' element.");
+       YY_BREAK
+
+
+case 111:
+YY_RULE_SETUP
+{
+  LEAVE;
+  ETag_ThemeInfo(pContext);
+  switch (YY_START) {
+   case S_Theme: SET(S_Theme_1); break;
+   case ROOT_ThemeInfo: SET(EPILOG); break;
+  }
+ }
+       YY_BREAK
+case 112:
+YY_RULE_SETUP
+FAIL("Unexpected end-tag `%s': `</ThemeInfo>' expected.",yytext);
+       YY_BREAK
+case 113:
+YY_RULE_SETUP
+FAIL("Unexpected character `%c': `</ThemeInfo>' expected.",yytext[0]);
+       YY_BREAK
+case YY_STATE_EOF(E_ThemeInfo):
+FAIL("Premature EOF: `</ThemeInfo>' expected.");
+       YY_BREAK
+
+/*         id          CDATA   #REQUIRED
+  *         visible     CDATA   "true"
+  *         x           CDATA   "\0"
+  *         y           CDATA   "\0"
+  *         dragdrop    CDATA   "true"
+  *         playondrop  CDATA   "true"
+  *     >  */
+case 114:
+YY_RULE_SETUP
+{
+  A_Window_id = NULL;
+  A_Window_visible = "true";
+  A_Window_x = "\0";
+  A_Window_y = "\0";
+  A_Window_dragdrop = "true";
+  A_Window_playondrop = "true";
+  ENTER(AL_Window);
+}
+       YY_BREAK
+
+case 115:
+YY_RULE_SETUP
+ENTER(VALUE1); BUFFERSET(A_Window_id);
+       YY_BREAK
+case 116:
+YY_RULE_SETUP
+ENTER(VALUE2); BUFFERSET(A_Window_id);
+       YY_BREAK
+case 117:
+YY_RULE_SETUP
+ENTER(VALUE1); BUFFERSET(A_Window_visible);
+       YY_BREAK
+case 118:
+YY_RULE_SETUP
+ENTER(VALUE2); BUFFERSET(A_Window_visible);
+       YY_BREAK
+case 119:
+YY_RULE_SETUP
+ENTER(VALUE1); BUFFERSET(A_Window_x);
+       YY_BREAK
+case 120:
+YY_RULE_SETUP
+ENTER(VALUE2); BUFFERSET(A_Window_x);
+       YY_BREAK
+case 121:
+YY_RULE_SETUP
+ENTER(VALUE1); BUFFERSET(A_Window_y);
+       YY_BREAK
+case 122:
+YY_RULE_SETUP
+ENTER(VALUE2); BUFFERSET(A_Window_y);
+       YY_BREAK
+case 123:
+YY_RULE_SETUP
+ENTER(VALUE1); BUFFERSET(A_Window_dragdrop);
+       YY_BREAK
+case 124:
+YY_RULE_SETUP
+ENTER(VALUE2); BUFFERSET(A_Window_dragdrop);
+       YY_BREAK
+case 125:
+YY_RULE_SETUP
+ENTER(VALUE1); BUFFERSET(A_Window_playondrop);
+       YY_BREAK
+case 126:
+YY_RULE_SETUP
+ENTER(VALUE2); BUFFERSET(A_Window_playondrop);
+       YY_BREAK
+case 127:
+YY_RULE_SETUP
+{
+  if (!A_Window_id) FAIL("Required attribute `id' not set for `Window' element.");
+  LEAVE; STag_Window(pContext); pcdata = NULL; ENTER(S_Window);
+ }
+       YY_BREAK
+case 128:
+YY_RULE_SETUP
+FAIL("`Window' element cannot be empty.");
+       YY_BREAK
+case 129:
+YY_RULE_SETUP
+FAIL("Unexpected character `%c' in attribute list of Window element.", yytext[0]);
+       YY_BREAK
+case 130:
+YY_RULE_SETUP
+FAIL("Bad attribute `%s' in `Window' element start tag.",yytext);
+       YY_BREAK
+case YY_STATE_EOF(AL_Window):
+FAIL("EOF in attribute list of `Window' element.");
+       YY_BREAK
+
+
+case 131:
+YY_RULE_SETUP
+{
+  LEAVE;
+  ETag_Window(pContext);
+  switch (YY_START) {
+   case ROOT_Window: SET(EPILOG); break;
+   case S_Theme_2: case S_Theme_1: case S_Theme_3: SET(S_Theme_3); break;
+  }
+ }
+       YY_BREAK
+case 132:
+YY_RULE_SETUP
+FAIL("Unexpected end-tag `%s': `</Window>' expected.",yytext);
+       YY_BREAK
+case 133:
+YY_RULE_SETUP
+FAIL("Unexpected character `%c': `</Window>' expected.",yytext[0]);
+       YY_BREAK
+case YY_STATE_EOF(S_Window_2):
+case YY_STATE_EOF(E_Window):
+FAIL("Premature EOF: `</Window>' expected.");
+       YY_BREAK
+
+/*         id          CDATA   "none"
+  *         width       CDATA   #REQUIRED
+  *         height      CDATA   #REQUIRED
+  *         minwidth    CDATA   "-1"
+  *         maxwidth    CDATA   "-1"
+  *         minheight   CDATA   "-1"
+  *         maxheight   CDATA   "-1"
+  *     >  */
+case 134:
+YY_RULE_SETUP
+{
+  A_Layout_id = "none";
+  A_Layout_width = NULL;
+  A_Layout_height = NULL;
+  A_Layout_minwidth = "-1";
+  A_Layout_maxwidth = "-1";
+  A_Layout_minheight = "-1";
+  A_Layout_maxheight = "-1";
+  ENTER(AL_Layout);
+}
+       YY_BREAK
+
+case 135:
+YY_RULE_SETUP
+ENTER(VALUE1); BUFFERSET(A_Layout_id);
+       YY_BREAK
+case 136:
+YY_RULE_SETUP
+ENTER(VALUE2); BUFFERSET(A_Layout_id);
+       YY_BREAK
+case 137:
+YY_RULE_SETUP
+ENTER(VALUE1); BUFFERSET(A_Layout_width);
+       YY_BREAK
+case 138:
+YY_RULE_SETUP
+ENTER(VALUE2); BUFFERSET(A_Layout_width);
+       YY_BREAK
+case 139:
+YY_RULE_SETUP
+ENTER(VALUE1); BUFFERSET(A_Layout_height);
+       YY_BREAK
+case 140:
+YY_RULE_SETUP
+ENTER(VALUE2); BUFFERSET(A_Layout_height);
+       YY_BREAK
+case 141:
+YY_RULE_SETUP
+ENTER(VALUE1); BUFFERSET(A_Layout_minwidth);
+       YY_BREAK
+case 142:
+YY_RULE_SETUP
+ENTER(VALUE2); BUFFERSET(A_Layout_minwidth);
+       YY_BREAK
+case 143:
+YY_RULE_SETUP
+ENTER(VALUE1); BUFFERSET(A_Layout_maxwidth);
+       YY_BREAK
+case 144:
+YY_RULE_SETUP
+ENTER(VALUE2); BUFFERSET(A_Layout_maxwidth);
+       YY_BREAK
+case 145:
+YY_RULE_SETUP
+ENTER(VALUE1); BUFFERSET(A_Layout_minheight);
+       YY_BREAK
+case 146:
+YY_RULE_SETUP
+ENTER(VALUE2); BUFFERSET(A_Layout_minheight);
+       YY_BREAK
+case 147:
+YY_RULE_SETUP
+ENTER(VALUE1); BUFFERSET(A_Layout_maxheight);
+       YY_BREAK
+case 148:
+YY_RULE_SETUP
+ENTER(VALUE2); BUFFERSET(A_Layout_maxheight);
+       YY_BREAK
+case 149:
+YY_RULE_SETUP
+{
+  if (!A_Layout_width) FAIL("Required attribute `width' not set for `Layout' element.");
+  if (!A_Layout_height) FAIL("Required attribute `height' not set for `Layout' element.");
+  LEAVE; STag_Layout(pContext); pcdata = NULL; ENTER(S_Layout);
+ }
+       YY_BREAK
+case 150:
+YY_RULE_SETUP
+FAIL("`Layout' element cannot be empty.");
+       YY_BREAK
+case 151:
+YY_RULE_SETUP
+FAIL("Unexpected character `%c' in attribute list of Layout element.", yytext[0]);
+       YY_BREAK
+case 152:
+YY_RULE_SETUP
+FAIL("Bad attribute `%s' in `Layout' element start tag.",yytext);
+       YY_BREAK
+case YY_STATE_EOF(AL_Layout):
+FAIL("EOF in attribute list of `Layout' element.");
+       YY_BREAK
+
+
+case 153:
+YY_RULE_SETUP
+{
+  LEAVE;
+  ETag_Layout(pContext);
+  switch (YY_START) {
+   case S_Window: case S_Window_1: case S_Window_2: SET(S_Window_2); break;
+   case ROOT_Layout: SET(EPILOG); break;
+  }
+ }
+       YY_BREAK
+case 154:
+YY_RULE_SETUP
+FAIL("Unexpected end-tag `%s': `</Layout>' expected.",yytext);
+       YY_BREAK
+case 155:
+YY_RULE_SETUP
+FAIL("Unexpected character `%c': `</Layout>' expected.",yytext[0]);
+       YY_BREAK
+case YY_STATE_EOF(E_Layout):
+FAIL("Premature EOF: `</Layout>' expected.");
+       YY_BREAK
+
+/*                  Rectangle|Anchor)+>  */
+/*         x           CDATA   "\0"
+  *         y           CDATA   "\0"
+  *     >  */
+case 156:
+YY_RULE_SETUP
+{
+  A_Group_x = "\0";
+  A_Group_y = "\0";
+  ENTER(AL_Group);
+}
+       YY_BREAK
+
+case 157:
+YY_RULE_SETUP
+ENTER(VALUE1); BUFFERSET(A_Group_x);
+       YY_BREAK
+case 158:
+YY_RULE_SETUP
+ENTER(VALUE2); BUFFERSET(A_Group_x);
+       YY_BREAK
+case 159:
+YY_RULE_SETUP
+ENTER(VALUE1); BUFFERSET(A_Group_y);
+       YY_BREAK
+case 160:
+YY_RULE_SETUP
+ENTER(VALUE2); BUFFERSET(A_Group_y);
+       YY_BREAK
+case 161:
+YY_RULE_SETUP
+{
+  LEAVE; STag_Group(pContext); pcdata = NULL; ENTER(S_Group);
+ }
+       YY_BREAK
+case 162:
+YY_RULE_SETUP
+FAIL("`Group' element cannot be empty.");
+       YY_BREAK
+case 163:
+YY_RULE_SETUP
+FAIL("Unexpected character `%c' in attribute list of Group element.", yytext[0]);
+       YY_BREAK
+case 164:
+YY_RULE_SETUP
+FAIL("Bad attribute `%s' in `Group' element start tag.",yytext);
+       YY_BREAK
+case YY_STATE_EOF(AL_Group):
+FAIL("EOF in attribute list of `Group' element.");
+       YY_BREAK
+
+
+case 165:
+YY_RULE_SETUP
+{
+  LEAVE;
+  ETag_Group(pContext);
+  switch (YY_START) {
+   case S_Group_2: case S_Group_1: case S_Group: SET(S_Group_2); break;
+   case S_Layout: SET(E_Layout); break;
+   case ROOT_Group: SET(EPILOG); break;
+  }
+ }
+       YY_BREAK
+case 166:
+YY_RULE_SETUP
+FAIL("Unexpected end-tag `%s': `</Group>' expected.",yytext);
+       YY_BREAK
+case 167:
+YY_RULE_SETUP
+FAIL("Unexpected character `%c': `</Group>' expected.",yytext[0]);
+       YY_BREAK
+case YY_STATE_EOF(S_Group_2):
+case YY_STATE_EOF(E_Group):
+FAIL("Premature EOF: `</Group>' expected.");
+       YY_BREAK
+
+/* <!-- Anchors -->  */
+/*         x           CDATA   "\0"
+  *         y           CDATA   "\0"
+  *         priority    CDATA   #REQUIRED
+  *         range       CDATA   "10"
+  *     >  */
+case 168:
+YY_RULE_SETUP
+{
+  A_Anchor_x = "\0";
+  A_Anchor_y = "\0";
+  A_Anchor_priority = NULL;
+  A_Anchor_range = "10";
+  ENTER(AL_Anchor);
+}
+       YY_BREAK
+
+case 169:
+YY_RULE_SETUP
+ENTER(VALUE1); BUFFERSET(A_Anchor_x);
+       YY_BREAK
+case 170:
+YY_RULE_SETUP
+ENTER(VALUE2); BUFFERSET(A_Anchor_x);
+       YY_BREAK
+case 171:
+YY_RULE_SETUP
+ENTER(VALUE1); BUFFERSET(A_Anchor_y);
+       YY_BREAK
+case 172:
+YY_RULE_SETUP
+ENTER(VALUE2); BUFFERSET(A_Anchor_y);
+       YY_BREAK
+case 173:
+YY_RULE_SETUP
+ENTER(VALUE1); BUFFERSET(A_Anchor_priority);
+       YY_BREAK
+case 174:
+YY_RULE_SETUP
+ENTER(VALUE2); BUFFERSET(A_Anchor_priority);
+       YY_BREAK
+case 175:
+YY_RULE_SETUP
+ENTER(VALUE1); BUFFERSET(A_Anchor_range);
+       YY_BREAK
+case 176:
+YY_RULE_SETUP
+ENTER(VALUE2); BUFFERSET(A_Anchor_range);
+       YY_BREAK
+case 177:
+YY_RULE_SETUP
+{
+  if (!A_Anchor_priority) FAIL("Required attribute `priority' not set for `Anchor' element.");
+  LEAVE; STag_Anchor(pContext); pcdata = NULL; ENTER(E_Anchor);
+ }
+       YY_BREAK
+case 178:
+YY_RULE_SETUP
+{
+  if (!A_Anchor_priority) FAIL("Required attribute `priority' not set for `Anchor' element.");
+  LEAVE; STag_Anchor(pContext); pcdata = NULL; ETag_Anchor(pContext);
+  switch (YY_START) {
+   case S_Group_2: case S_Group_1: case S_Group: SET(S_Group_2); break;
+   case ROOT_Anchor: SET(EPILOG); break;
+  }
+ }
+       YY_BREAK
+case 179:
+YY_RULE_SETUP
+FAIL("Unexpected character `%c' in attribute list of Anchor element.", yytext[0]);
+       YY_BREAK
+case 180:
+YY_RULE_SETUP
+FAIL("Bad attribute `%s' in `Anchor' element start tag.",yytext);
+       YY_BREAK
+case YY_STATE_EOF(AL_Anchor):
+FAIL("EOF in attribute list of `Anchor' element.");
+       YY_BREAK
+
+
+case 181:
+YY_RULE_SETUP
+{
+  LEAVE;
+  ETag_Anchor(pContext);
+  switch (YY_START) {
+   case S_Group_2: case S_Group_1: case S_Group: SET(S_Group_2); break;
+   case ROOT_Anchor: SET(EPILOG); break;
+  }
+ }
+       YY_BREAK
+case 182:
+YY_RULE_SETUP
+FAIL("Unexpected end-tag `%s': `</Anchor>' expected.",yytext);
+       YY_BREAK
+case 183:
+YY_RULE_SETUP
+FAIL("Unexpected character `%c': `</Anchor>' expected.",yytext[0]);
+       YY_BREAK
+case YY_STATE_EOF(E_Anchor):
+FAIL("Premature EOF: `</Anchor>' expected.");
+       YY_BREAK
+
+/* <!-- Controls -->  */
+/*         id          CDATA   "none"
+  *         visible     CDATA   "true"
+  *         x           CDATA   "\0"
+  *         y           CDATA   "\0"
+  *         lefttop     CDATA   "lefttop"
+  *         rightbottom CDATA   "lefttop"
+  *         image       CDATA   #REQUIRED
+  *         onclick     CDATA   "none"
+  *         help        CDATA   "\0"
+  *     >  */
+case 184:
+YY_RULE_SETUP
+{
+  A_Image_id = "none";
+  A_Image_visible = "true";
+  A_Image_x = "\0";
+  A_Image_y = "\0";
+  A_Image_lefttop = "lefttop";
+  A_Image_rightbottom = "lefttop";
+  A_Image_image = NULL;
+  A_Image_onclick = "none";
+  A_Image_help = "\0";
+  ENTER(AL_Image);
+}
+       YY_BREAK
+
+case 185:
+YY_RULE_SETUP
+ENTER(VALUE1); BUFFERSET(A_Image_id);
+       YY_BREAK
+case 186:
+YY_RULE_SETUP
+ENTER(VALUE2); BUFFERSET(A_Image_id);
+       YY_BREAK
+case 187:
+YY_RULE_SETUP
+ENTER(VALUE1); BUFFERSET(A_Image_visible);
+       YY_BREAK
+case 188:
+YY_RULE_SETUP
+ENTER(VALUE2); BUFFERSET(A_Image_visible);
+       YY_BREAK
+case 189:
+YY_RULE_SETUP
+ENTER(VALUE1); BUFFERSET(A_Image_x);
+       YY_BREAK
+case 190:
+YY_RULE_SETUP
+ENTER(VALUE2); BUFFERSET(A_Image_x);
+       YY_BREAK
+case 191:
+YY_RULE_SETUP
+ENTER(VALUE1); BUFFERSET(A_Image_y);
+       YY_BREAK
+case 192:
+YY_RULE_SETUP
+ENTER(VALUE2); BUFFERSET(A_Image_y);
+       YY_BREAK
+case 193:
+YY_RULE_SETUP
+ENTER(VALUE1); BUFFERSET(A_Image_lefttop);
+       YY_BREAK
+case 194:
+YY_RULE_SETUP
+ENTER(VALUE2); BUFFERSET(A_Image_lefttop);
+       YY_BREAK
+case 195:
+YY_RULE_SETUP
+ENTER(VALUE1); BUFFERSET(A_Image_rightbottom);
+       YY_BREAK
+case 196:
+YY_RULE_SETUP
+ENTER(VALUE2); BUFFERSET(A_Image_rightbottom);
+       YY_BREAK
+case 197:
+YY_RULE_SETUP
+ENTER(VALUE1); BUFFERSET(A_Image_image);
+       YY_BREAK
+case 198:
+YY_RULE_SETUP
+ENTER(VALUE2); BUFFERSET(A_Image_image);
+       YY_BREAK
+case 199:
+YY_RULE_SETUP
+ENTER(VALUE1); BUFFERSET(A_Image_onclick);
+       YY_BREAK
+case 200:
+YY_RULE_SETUP
+ENTER(VALUE2); BUFFERSET(A_Image_onclick);
+       YY_BREAK
+case 201:
+YY_RULE_SETUP
+ENTER(VALUE1); BUFFERSET(A_Image_help);
+       YY_BREAK
+case 202:
+YY_RULE_SETUP
+ENTER(VALUE2); BUFFERSET(A_Image_help);
+       YY_BREAK
+case 203:
+YY_RULE_SETUP
+{
+  if (!A_Image_image) FAIL("Required attribute `image' not set for `Image' element.");
+  LEAVE; STag_Image(pContext); pcdata = NULL; ENTER(E_Image);
+ }
+       YY_BREAK
+case 204:
+YY_RULE_SETUP
+{
+  if (!A_Image_image) FAIL("Required attribute `image' not set for `Image' element.");
+  LEAVE; STag_Image(pContext); pcdata = NULL; ETag_Image(pContext);
+  switch (YY_START) {
+   case S_Group_2: case S_Group_1: case S_Group: SET(S_Group_2); break;
+   case ROOT_Image: SET(EPILOG); break;
+  }
+ }
+       YY_BREAK
+case 205:
+YY_RULE_SETUP
+FAIL("Unexpected character `%c' in attribute list of Image element.", yytext[0]);
+       YY_BREAK
+case 206:
+YY_RULE_SETUP
+FAIL("Bad attribute `%s' in `Image' element start tag.",yytext);
+       YY_BREAK
+case YY_STATE_EOF(AL_Image):
+FAIL("EOF in attribute list of `Image' element.");
+       YY_BREAK
+
+
+case 207:
+YY_RULE_SETUP
+{
+  LEAVE;
+  ETag_Image(pContext);
+  switch (YY_START) {
+   case S_Group_2: case S_Group_1: case S_Group: SET(S_Group_2); break;
+   case ROOT_Image: SET(EPILOG); break;
+  }
+ }
+       YY_BREAK
+case 208:
+YY_RULE_SETUP
+FAIL("Unexpected end-tag `%s': `</Image>' expected.",yytext);
+       YY_BREAK
+case 209:
+YY_RULE_SETUP
+FAIL("Unexpected character `%c': `</Image>' expected.",yytext[0]);
+       YY_BREAK
+case YY_STATE_EOF(E_Image):
+FAIL("Premature EOF: `</Image>' expected.");
+       YY_BREAK
+
+/*         id          CDATA   "none"
+  *         visible     CDATA   "true"
+  *         x           CDATA   "\0"
+  *         y           CDATA   "\0"
+  *         w           CDATA   "50"
+  *         h           CDATA   "50"
+  *         color       CDATA   "#C0C0C0"
+  *         onclick     CDATA   "none"
+  *         help        CDATA   "\0"
+  *     >  */
+case 210:
+YY_RULE_SETUP
+{
+  A_Rectangle_id = "none";
+  A_Rectangle_visible = "true";
+  A_Rectangle_x = "\0";
+  A_Rectangle_y = "\0";
+  A_Rectangle_w = "50";
+  A_Rectangle_h = "50";
+  A_Rectangle_color = "#C0C0C0";
+  A_Rectangle_onclick = "none";
+  A_Rectangle_help = "\0";
+  ENTER(AL_Rectangle);
+}
+       YY_BREAK
+
+case 211:
+YY_RULE_SETUP
+ENTER(VALUE1); BUFFERSET(A_Rectangle_id);
+       YY_BREAK
+case 212:
+YY_RULE_SETUP
+ENTER(VALUE2); BUFFERSET(A_Rectangle_id);
+       YY_BREAK
+case 213:
+YY_RULE_SETUP
+ENTER(VALUE1); BUFFERSET(A_Rectangle_visible);
+       YY_BREAK
+case 214:
+YY_RULE_SETUP
+ENTER(VALUE2); BUFFERSET(A_Rectangle_visible);
+       YY_BREAK
+case 215:
+YY_RULE_SETUP
+ENTER(VALUE1); BUFFERSET(A_Rectangle_x);
+       YY_BREAK
+case 216:
+YY_RULE_SETUP
+ENTER(VALUE2); BUFFERSET(A_Rectangle_x);
+       YY_BREAK
+case 217:
+YY_RULE_SETUP
+ENTER(VALUE1); BUFFERSET(A_Rectangle_y);
+       YY_BREAK
+case 218:
+YY_RULE_SETUP
+ENTER(VALUE2); BUFFERSET(A_Rectangle_y);
+       YY_BREAK
+case 219:
+YY_RULE_SETUP
+ENTER(VALUE1); BUFFERSET(A_Rectangle_w);
+       YY_BREAK
+case 220:
+YY_RULE_SETUP
+ENTER(VALUE2); BUFFERSET(A_Rectangle_w);
+       YY_BREAK
+case 221:
+YY_RULE_SETUP
+ENTER(VALUE1); BUFFERSET(A_Rectangle_h);
+       YY_BREAK
+case 222:
+YY_RULE_SETUP
+ENTER(VALUE2); BUFFERSET(A_Rectangle_h);
+       YY_BREAK
+case 223:
+YY_RULE_SETUP
+ENTER(VALUE1); BUFFERSET(A_Rectangle_color);
+       YY_BREAK
+case 224:
+YY_RULE_SETUP
+ENTER(VALUE2); BUFFERSET(A_Rectangle_color);
+       YY_BREAK
+case 225:
+YY_RULE_SETUP
+ENTER(VALUE1); BUFFERSET(A_Rectangle_onclick);
+       YY_BREAK
+case 226:
+YY_RULE_SETUP
+ENTER(VALUE2); BUFFERSET(A_Rectangle_onclick);
+       YY_BREAK
+case 227:
+YY_RULE_SETUP
+ENTER(VALUE1); BUFFERSET(A_Rectangle_help);
+       YY_BREAK
+case 228:
+YY_RULE_SETUP
+ENTER(VALUE2); BUFFERSET(A_Rectangle_help);
+       YY_BREAK
+case 229:
+YY_RULE_SETUP
+{
+  LEAVE; STag_Rectangle(pContext); pcdata = NULL; ENTER(E_Rectangle);
+ }
+       YY_BREAK
+case 230:
+YY_RULE_SETUP
+{
+  LEAVE; STag_Rectangle(pContext); pcdata = NULL; ETag_Rectangle(pContext);
+  switch (YY_START) {
+   case S_Group_2: case S_Group_1: case S_Group: SET(S_Group_2); break;
+   case ROOT_Rectangle: SET(EPILOG); break;
+  }
+ }
+       YY_BREAK
+case 231:
+YY_RULE_SETUP
+FAIL("Unexpected character `%c' in attribute list of Rectangle element.", yytext[0]);
+       YY_BREAK
+case 232:
+YY_RULE_SETUP
+FAIL("Bad attribute `%s' in `Rectangle' element start tag.",yytext);
+       YY_BREAK
+case YY_STATE_EOF(AL_Rectangle):
+FAIL("EOF in attribute list of `Rectangle' element.");
+       YY_BREAK
+
+
+case 233:
+YY_RULE_SETUP
+{
+  LEAVE;
+  ETag_Rectangle(pContext);
+  switch (YY_START) {
+   case S_Group_2: case S_Group_1: case S_Group: SET(S_Group_2); break;
+   case ROOT_Rectangle: SET(EPILOG); break;
+  }
+ }
+       YY_BREAK
+case 234:
+YY_RULE_SETUP
+FAIL("Unexpected end-tag `%s': `</Rectangle>' expected.",yytext);
+       YY_BREAK
+case 235:
+YY_RULE_SETUP
+FAIL("Unexpected character `%c': `</Rectangle>' expected.",yytext[0]);
+       YY_BREAK
+case YY_STATE_EOF(E_Rectangle):
+FAIL("Premature EOF: `</Rectangle>' expected.");
+       YY_BREAK
+
+/*         id          CDATA   "none"
+  *         x           CDATA   "\0"
+  *         y           CDATA   "\0"
+  *         lefttop     CDATA   "lefttop"
+  *         rightbottom CDATA   "lefttop"
+  *         up          CDATA   #REQUIRED
+  *         down        CDATA   "none"
+  *         over        CDATA   "none"
+  *         action      CDATA   "none"
+  *         tooltiptext CDATA   "\0"
+  *         help        CDATA   "\0"
+  *     >  */
+case 236:
+YY_RULE_SETUP
+{
+  A_Button_id = "none";
+  A_Button_x = "\0";
+  A_Button_y = "\0";
+  A_Button_lefttop = "lefttop";
+  A_Button_rightbottom = "lefttop";
+  A_Button_up = NULL;
+  A_Button_down = "none";
+  A_Button_over = "none";
+  A_Button_action = "none";
+  A_Button_tooltiptext = "\0";
+  A_Button_help = "\0";
+  ENTER(AL_Button);
+}
+       YY_BREAK
+
+case 237:
+YY_RULE_SETUP
+ENTER(VALUE1); BUFFERSET(A_Button_id);
+       YY_BREAK
+case 238:
+YY_RULE_SETUP
+ENTER(VALUE2); BUFFERSET(A_Button_id);
+       YY_BREAK
+case 239:
+YY_RULE_SETUP
+ENTER(VALUE1); BUFFERSET(A_Button_x);
+       YY_BREAK
+case 240:
+YY_RULE_SETUP
+ENTER(VALUE2); BUFFERSET(A_Button_x);
+       YY_BREAK
+case 241:
+YY_RULE_SETUP
+ENTER(VALUE1); BUFFERSET(A_Button_y);
+       YY_BREAK
+case 242:
+YY_RULE_SETUP
+ENTER(VALUE2); BUFFERSET(A_Button_y);
+       YY_BREAK
+case 243:
+YY_RULE_SETUP
+ENTER(VALUE1); BUFFERSET(A_Button_lefttop);
+       YY_BREAK
+case 244:
+YY_RULE_SETUP
+ENTER(VALUE2); BUFFERSET(A_Button_lefttop);
+       YY_BREAK
+case 245:
+YY_RULE_SETUP
+ENTER(VALUE1); BUFFERSET(A_Button_rightbottom);
+       YY_BREAK
+case 246:
+YY_RULE_SETUP
+ENTER(VALUE2); BUFFERSET(A_Button_rightbottom);
+       YY_BREAK
+case 247:
+YY_RULE_SETUP
+ENTER(VALUE1); BUFFERSET(A_Button_up);
+       YY_BREAK
+case 248:
+YY_RULE_SETUP
+ENTER(VALUE2); BUFFERSET(A_Button_up);
+       YY_BREAK
+case 249:
+YY_RULE_SETUP
+ENTER(VALUE1); BUFFERSET(A_Button_down);
+       YY_BREAK
+case 250:
+YY_RULE_SETUP
+ENTER(VALUE2); BUFFERSET(A_Button_down);
+       YY_BREAK
+case 251:
+YY_RULE_SETUP
+ENTER(VALUE1); BUFFERSET(A_Button_over);
+       YY_BREAK
+case 252:
+YY_RULE_SETUP
+ENTER(VALUE2); BUFFERSET(A_Button_over);
+       YY_BREAK
+case 253:
+YY_RULE_SETUP
+ENTER(VALUE1); BUFFERSET(A_Button_action);
+       YY_BREAK
+case 254:
+YY_RULE_SETUP
+ENTER(VALUE2); BUFFERSET(A_Button_action);
+       YY_BREAK
+case 255:
+YY_RULE_SETUP
+ENTER(VALUE1); BUFFERSET(A_Button_tooltiptext);
+       YY_BREAK
+case 256:
+YY_RULE_SETUP
+ENTER(VALUE2); BUFFERSET(A_Button_tooltiptext);
+       YY_BREAK
+case 257:
+YY_RULE_SETUP
+ENTER(VALUE1); BUFFERSET(A_Button_help);
+       YY_BREAK
+case 258:
+YY_RULE_SETUP
+ENTER(VALUE2); BUFFERSET(A_Button_help);
+       YY_BREAK
+case 259:
+YY_RULE_SETUP
+{
+  if (!A_Button_up) FAIL("Required attribute `up' not set for `Button' element.");
+  LEAVE; STag_Button(pContext); pcdata = NULL; ENTER(E_Button);
+ }
+       YY_BREAK
+case 260:
+YY_RULE_SETUP
+{
+  if (!A_Button_up) FAIL("Required attribute `up' not set for `Button' element.");
+  LEAVE; STag_Button(pContext); pcdata = NULL; ETag_Button(pContext);
+  switch (YY_START) {
+   case S_Group_2: case S_Group_1: case S_Group: SET(S_Group_2); break;
+   case ROOT_Button: SET(EPILOG); break;
+  }
+ }
+       YY_BREAK
+case 261:
+YY_RULE_SETUP
+FAIL("Unexpected character `%c' in attribute list of Button element.", yytext[0]);
+       YY_BREAK
+case 262:
+YY_RULE_SETUP
+FAIL("Bad attribute `%s' in `Button' element start tag.",yytext);
+       YY_BREAK
+case YY_STATE_EOF(AL_Button):
+FAIL("EOF in attribute list of `Button' element.");
+       YY_BREAK
+
+
+case 263:
+YY_RULE_SETUP
+{
+  LEAVE;
+  ETag_Button(pContext);
+  switch (YY_START) {
+   case S_Group_2: case S_Group_1: case S_Group: SET(S_Group_2); break;
+   case ROOT_Button: SET(EPILOG); break;
+  }
+ }
+       YY_BREAK
+case 264:
+YY_RULE_SETUP
+FAIL("Unexpected end-tag `%s': `</Button>' expected.",yytext);
+       YY_BREAK
+case 265:
+YY_RULE_SETUP
+FAIL("Unexpected character `%c': `</Button>' expected.",yytext[0]);
+       YY_BREAK
+case YY_STATE_EOF(E_Button):
+FAIL("Premature EOF: `</Button>' expected.");
+       YY_BREAK
+
+/*         id           CDATA   "none"
+  *         x            CDATA   "\0"
+  *         y            CDATA   "\0"
+  *         lefttop      CDATA   "lefttop"
+  *         rightbottom  CDATA   "lefttop"
+  *         up1          CDATA   #REQUIRED
+  *         down1        CDATA   "none"
+  *         over1        CDATA   "none"
+  *         up2          CDATA   #REQUIRED
+  *         down2        CDATA   "none"
+  *         over2        CDATA   "none"
+  *         state        CDATA   #REQUIRED
+  *         action1      CDATA   "none"
+  *         action2      CDATA   "none"
+  *         tooltiptext1 CDATA   "\0"
+  *         tooltiptext2 CDATA   "\0"
+  *         help         CDATA   "\0"
+  *     >  */
+case 266:
+YY_RULE_SETUP
+{
+  A_CheckBox_id = "none";
+  A_CheckBox_x = "\0";
+  A_CheckBox_y = "\0";
+  A_CheckBox_lefttop = "lefttop";
+  A_CheckBox_rightbottom = "lefttop";
+  A_CheckBox_up1 = NULL;
+  A_CheckBox_down1 = "none";
+  A_CheckBox_over1 = "none";
+  A_CheckBox_up2 = NULL;
+  A_CheckBox_down2 = "none";
+  A_CheckBox_over2 = "none";
+  A_CheckBox_state = NULL;
+  A_CheckBox_action1 = "none";
+  A_CheckBox_action2 = "none";
+  A_CheckBox_tooltiptext1 = "\0";
+  A_CheckBox_tooltiptext2 = "\0";
+  A_CheckBox_help = "\0";
+  ENTER(AL_CheckBox);
+}
+       YY_BREAK
+
+case 267:
+YY_RULE_SETUP
+ENTER(VALUE1); BUFFERSET(A_CheckBox_id);
+       YY_BREAK
+case 268:
+YY_RULE_SETUP
+ENTER(VALUE2); BUFFERSET(A_CheckBox_id);
+       YY_BREAK
+case 269:
+YY_RULE_SETUP
+ENTER(VALUE1); BUFFERSET(A_CheckBox_x);
+       YY_BREAK
+case 270:
+YY_RULE_SETUP
+ENTER(VALUE2); BUFFERSET(A_CheckBox_x);
+       YY_BREAK
+case 271:
+YY_RULE_SETUP
+ENTER(VALUE1); BUFFERSET(A_CheckBox_y);
+       YY_BREAK
+case 272:
+YY_RULE_SETUP
+ENTER(VALUE2); BUFFERSET(A_CheckBox_y);
+       YY_BREAK
+case 273:
+YY_RULE_SETUP
+ENTER(VALUE1); BUFFERSET(A_CheckBox_lefttop);
+       YY_BREAK
+case 274:
+YY_RULE_SETUP
+ENTER(VALUE2); BUFFERSET(A_CheckBox_lefttop);
+       YY_BREAK
+case 275:
+YY_RULE_SETUP
+ENTER(VALUE1); BUFFERSET(A_CheckBox_rightbottom);
+       YY_BREAK
+case 276:
+YY_RULE_SETUP
+ENTER(VALUE2); BUFFERSET(A_CheckBox_rightbottom);
+       YY_BREAK
+case 277:
+YY_RULE_SETUP
+ENTER(VALUE1); BUFFERSET(A_CheckBox_up1);
+       YY_BREAK
+case 278:
+YY_RULE_SETUP
+ENTER(VALUE2); BUFFERSET(A_CheckBox_up1);
+       YY_BREAK
+case 279:
+YY_RULE_SETUP
+ENTER(VALUE1); BUFFERSET(A_CheckBox_down1);
+       YY_BREAK
+case 280:
+YY_RULE_SETUP
+ENTER(VALUE2); BUFFERSET(A_CheckBox_down1);
+       YY_BREAK
+case 281:
+YY_RULE_SETUP
+ENTER(VALUE1); BUFFERSET(A_CheckBox_over1);
+       YY_BREAK
+case 282:
+YY_RULE_SETUP
+ENTER(VALUE2); BUFFERSET(A_CheckBox_over1);
+       YY_BREAK
+case 283:
+YY_RULE_SETUP
+ENTER(VALUE1); BUFFERSET(A_CheckBox_up2);
+       YY_BREAK
+case 284:
+YY_RULE_SETUP
+ENTER(VALUE2); BUFFERSET(A_CheckBox_up2);
+       YY_BREAK
+case 285:
+YY_RULE_SETUP
+ENTER(VALUE1); BUFFERSET(A_CheckBox_down2);
+       YY_BREAK
+case 286:
+YY_RULE_SETUP
+ENTER(VALUE2); BUFFERSET(A_CheckBox_down2);
+       YY_BREAK
+case 287:
+YY_RULE_SETUP
+ENTER(VALUE1); BUFFERSET(A_CheckBox_over2);
+       YY_BREAK
+case 288:
+YY_RULE_SETUP
+ENTER(VALUE2); BUFFERSET(A_CheckBox_over2);
+       YY_BREAK
+case 289:
+YY_RULE_SETUP
+ENTER(VALUE1); BUFFERSET(A_CheckBox_state);
+       YY_BREAK
+case 290:
+YY_RULE_SETUP
+ENTER(VALUE2); BUFFERSET(A_CheckBox_state);
+       YY_BREAK
+case 291:
+YY_RULE_SETUP
+ENTER(VALUE1); BUFFERSET(A_CheckBox_action1);
+       YY_BREAK
+case 292:
+YY_RULE_SETUP
+ENTER(VALUE2); BUFFERSET(A_CheckBox_action1);
+       YY_BREAK
+case 293:
+YY_RULE_SETUP
+ENTER(VALUE1); BUFFERSET(A_CheckBox_action2);
+       YY_BREAK
+case 294:
+YY_RULE_SETUP
+ENTER(VALUE2); BUFFERSET(A_CheckBox_action2);
+       YY_BREAK
+case 295:
+YY_RULE_SETUP
+ENTER(VALUE1); BUFFERSET(A_CheckBox_tooltiptext1);
+       YY_BREAK
+case 296:
+YY_RULE_SETUP
+ENTER(VALUE2); BUFFERSET(A_CheckBox_tooltiptext1);
+       YY_BREAK
+case 297:
+YY_RULE_SETUP
+ENTER(VALUE1); BUFFERSET(A_CheckBox_tooltiptext2);
+       YY_BREAK
+case 298:
+YY_RULE_SETUP
+ENTER(VALUE2); BUFFERSET(A_CheckBox_tooltiptext2);
+       YY_BREAK
+case 299:
+YY_RULE_SETUP
+ENTER(VALUE1); BUFFERSET(A_CheckBox_help);
+       YY_BREAK
+case 300:
+YY_RULE_SETUP
+ENTER(VALUE2); BUFFERSET(A_CheckBox_help);
+       YY_BREAK
+case 301:
+YY_RULE_SETUP
+{
+  if (!A_CheckBox_up1) FAIL("Required attribute `up1' not set for `CheckBox' element.");
+  if (!A_CheckBox_up2) FAIL("Required attribute `up2' not set for `CheckBox' element.");
+  if (!A_CheckBox_state) FAIL("Required attribute `state' not set for `CheckBox' element.");
+  LEAVE; STag_CheckBox(pContext); pcdata = NULL; ENTER(E_CheckBox);
+ }
+       YY_BREAK
+case 302:
+YY_RULE_SETUP
+{
+  if (!A_CheckBox_up1) FAIL("Required attribute `up1' not set for `CheckBox' element.");
+  if (!A_CheckBox_up2) FAIL("Required attribute `up2' not set for `CheckBox' element.");
+  if (!A_CheckBox_state) FAIL("Required attribute `state' not set for `CheckBox' element.");
+  LEAVE; STag_CheckBox(pContext); pcdata = NULL; ETag_CheckBox(pContext);
+  switch (YY_START) {
+   case S_Group_2: case S_Group_1: case S_Group: SET(S_Group_2); break;
+   case ROOT_CheckBox: SET(EPILOG); break;
+  }
+ }
+       YY_BREAK
+case 303:
+YY_RULE_SETUP
+FAIL("Unexpected character `%c' in attribute list of CheckBox element.", yytext[0]);
+       YY_BREAK
+case 304:
+YY_RULE_SETUP
+FAIL("Bad attribute `%s' in `CheckBox' element start tag.",yytext);
+       YY_BREAK
+case YY_STATE_EOF(AL_CheckBox):
+FAIL("EOF in attribute list of `CheckBox' element.");
+       YY_BREAK
+
+
+case 305:
+YY_RULE_SETUP
+{
+  LEAVE;
+  ETag_CheckBox(pContext);
+  switch (YY_START) {
+   case S_Group_2: case S_Group_1: case S_Group: SET(S_Group_2); break;
+   case ROOT_CheckBox: SET(EPILOG); break;
+  }
+ }
+       YY_BREAK
+case 306:
+YY_RULE_SETUP
+FAIL("Unexpected end-tag `%s': `</CheckBox>' expected.",yytext);
+       YY_BREAK
+case 307:
+YY_RULE_SETUP
+FAIL("Unexpected character `%c': `</CheckBox>' expected.",yytext[0]);
+       YY_BREAK
+case YY_STATE_EOF(E_CheckBox):
+FAIL("Premature EOF: `</CheckBox>' expected.");
+       YY_BREAK
+
+/*         id          CDATA   "none"
+  *         visible     CDATA   "true"
+  *         x           CDATA   "\0"
+  *         y           CDATA   "\0"
+  *         lefttop     CDATA   "lefttop"
+  *         rightbottom CDATA   "lefttop"
+  *         up          CDATA   #REQUIRED
+  *         down        CDATA   "none"
+  *         over        CDATA   "none"
+  *         points      CDATA   #REQUIRED
+  *         thickness   CDATA   "10"
+  *         value       CDATA   "none"
+  *         tooltiptext CDATA   "\0"
+  *         help        CDATA   "\0"
+  *     >  */
+case 308:
+YY_RULE_SETUP
+{
+  A_Slider_id = "none";
+  A_Slider_visible = "true";
+  A_Slider_x = "\0";
+  A_Slider_y = "\0";
+  A_Slider_lefttop = "lefttop";
+  A_Slider_rightbottom = "lefttop";
+  A_Slider_up = NULL;
+  A_Slider_down = "none";
+  A_Slider_over = "none";
+  A_Slider_points = NULL;
+  A_Slider_thickness = "10";
+  A_Slider_value = "none";
+  A_Slider_tooltiptext = "\0";
+  A_Slider_help = "\0";
+  ENTER(AL_Slider);
+}
+       YY_BREAK
+
+case 309:
+YY_RULE_SETUP
+ENTER(VALUE1); BUFFERSET(A_Slider_id);
+       YY_BREAK
+case 310:
+YY_RULE_SETUP
+ENTER(VALUE2); BUFFERSET(A_Slider_id);
+       YY_BREAK
+case 311:
+YY_RULE_SETUP
+ENTER(VALUE1); BUFFERSET(A_Slider_visible);
+       YY_BREAK
+case 312:
+YY_RULE_SETUP
+ENTER(VALUE2); BUFFERSET(A_Slider_visible);
+       YY_BREAK
+case 313:
+YY_RULE_SETUP
+ENTER(VALUE1); BUFFERSET(A_Slider_x);
+       YY_BREAK
+case 314:
+YY_RULE_SETUP
+ENTER(VALUE2); BUFFERSET(A_Slider_x);
+       YY_BREAK
+case 315:
+YY_RULE_SETUP
+ENTER(VALUE1); BUFFERSET(A_Slider_y);
+       YY_BREAK
+case 316:
+YY_RULE_SETUP
+ENTER(VALUE2); BUFFERSET(A_Slider_y);
+       YY_BREAK
+case 317:
+YY_RULE_SETUP
+ENTER(VALUE1); BUFFERSET(A_Slider_lefttop);
+       YY_BREAK
+case 318:
+YY_RULE_SETUP
+ENTER(VALUE2); BUFFERSET(A_Slider_lefttop);
+       YY_BREAK
+case 319:
+YY_RULE_SETUP
+ENTER(VALUE1); BUFFERSET(A_Slider_rightbottom);
+       YY_BREAK
+case 320:
+YY_RULE_SETUP
+ENTER(VALUE2); BUFFERSET(A_Slider_rightbottom);
+       YY_BREAK
+case 321:
+YY_RULE_SETUP
+ENTER(VALUE1); BUFFERSET(A_Slider_up);
+       YY_BREAK
+case 322:
+YY_RULE_SETUP
+ENTER(VALUE2); BUFFERSET(A_Slider_up);
+       YY_BREAK
+case 323:
+YY_RULE_SETUP
+ENTER(VALUE1); BUFFERSET(A_Slider_down);
+       YY_BREAK
+case 324:
+YY_RULE_SETUP
+ENTER(VALUE2); BUFFERSET(A_Slider_down);
+       YY_BREAK
+case 325:
+YY_RULE_SETUP
+ENTER(VALUE1); BUFFERSET(A_Slider_over);
+       YY_BREAK
+case 326:
+YY_RULE_SETUP
+ENTER(VALUE2); BUFFERSET(A_Slider_over);
+       YY_BREAK
+case 327:
+YY_RULE_SETUP
+ENTER(VALUE1); BUFFERSET(A_Slider_points);
+       YY_BREAK
+case 328:
+YY_RULE_SETUP
+ENTER(VALUE2); BUFFERSET(A_Slider_points);
+       YY_BREAK
+case 329:
+YY_RULE_SETUP
+ENTER(VALUE1); BUFFERSET(A_Slider_thickness);
+       YY_BREAK
+case 330:
+YY_RULE_SETUP
+ENTER(VALUE2); BUFFERSET(A_Slider_thickness);
+       YY_BREAK
+case 331:
+YY_RULE_SETUP
+ENTER(VALUE1); BUFFERSET(A_Slider_value);
+       YY_BREAK
+case 332:
+YY_RULE_SETUP
+ENTER(VALUE2); BUFFERSET(A_Slider_value);
+       YY_BREAK
+case 333:
+YY_RULE_SETUP
+ENTER(VALUE1); BUFFERSET(A_Slider_tooltiptext);
+       YY_BREAK
+case 334:
+YY_RULE_SETUP
+ENTER(VALUE2); BUFFERSET(A_Slider_tooltiptext);
+       YY_BREAK
+case 335:
+YY_RULE_SETUP
+ENTER(VALUE1); BUFFERSET(A_Slider_help);
+       YY_BREAK
+case 336:
+YY_RULE_SETUP
+ENTER(VALUE2); BUFFERSET(A_Slider_help);
+       YY_BREAK
+case 337:
+YY_RULE_SETUP
+{
+  if (!A_Slider_up) FAIL("Required attribute `up' not set for `Slider' element.");
+  if (!A_Slider_points) FAIL("Required attribute `points' not set for `Slider' element.");
+  LEAVE; STag_Slider(pContext); pcdata = NULL; ENTER(E_Slider);
+ }
+       YY_BREAK
+case 338:
+YY_RULE_SETUP
+{
+  if (!A_Slider_up) FAIL("Required attribute `up' not set for `Slider' element.");
+  if (!A_Slider_points) FAIL("Required attribute `points' not set for `Slider' element.");
+  LEAVE; STag_Slider(pContext); pcdata = NULL; ETag_Slider(pContext);
+  switch (YY_START) {
+   case S_Playlist: SET(E_Playlist); break;
+   case S_Group_2: case S_Group_1: case S_Group: SET(S_Group_2); break;
+   case ROOT_Slider: SET(EPILOG); break;
+  }
+ }
+       YY_BREAK
+case 339:
+YY_RULE_SETUP
+FAIL("Unexpected character `%c' in attribute list of Slider element.", yytext[0]);
+       YY_BREAK
+case 340:
+YY_RULE_SETUP
+FAIL("Bad attribute `%s' in `Slider' element start tag.",yytext);
+       YY_BREAK
+case YY_STATE_EOF(AL_Slider):
+FAIL("EOF in attribute list of `Slider' element.");
+       YY_BREAK
+
+
+case 341:
+YY_RULE_SETUP
+{
+  LEAVE;
+  ETag_Slider(pContext);
+  switch (YY_START) {
+   case S_Playlist: SET(E_Playlist); break;
+   case S_Group_2: case S_Group_1: case S_Group: SET(S_Group_2); break;
+   case ROOT_Slider: SET(EPILOG); break;
+  }
+ }
+       YY_BREAK
+case 342:
+YY_RULE_SETUP
+FAIL("Unexpected end-tag `%s': `</Slider>' expected.",yytext);
+       YY_BREAK
+case 343:
+YY_RULE_SETUP
+FAIL("Unexpected character `%c': `</Slider>' expected.",yytext[0]);
+       YY_BREAK
+case YY_STATE_EOF(E_Slider):
+FAIL("Premature EOF: `</Slider>' expected.");
+       YY_BREAK
+
+/*         id          CDATA   "none"
+  *         visible     CDATA   "true"
+  *         x           CDATA   "\0"
+  *         y           CDATA   "\0"
+  *         lefttop     CDATA   "lefttop"
+  *         rightbottom CDATA   "lefttop"
+  *         sequence    CDATA   #REQUIRED
+  *         nbimages    CDATA   #REQUIRED
+  *         minangle    CDATA   "\0"
+  *         maxangle    CDATA   "360"
+  *         value       CDATA   "none"
+  *         tooltiptext CDATA   "\0"
+  *         help        CDATA   "\0"
+  *     >  */
+case 344:
+YY_RULE_SETUP
+{
+  A_RadialSlider_id = "none";
+  A_RadialSlider_visible = "true";
+  A_RadialSlider_x = "\0";
+  A_RadialSlider_y = "\0";
+  A_RadialSlider_lefttop = "lefttop";
+  A_RadialSlider_rightbottom = "lefttop";
+  A_RadialSlider_sequence = NULL;
+  A_RadialSlider_nbimages = NULL;
+  A_RadialSlider_minangle = "\0";
+  A_RadialSlider_maxangle = "360";
+  A_RadialSlider_value = "none";
+  A_RadialSlider_tooltiptext = "\0";
+  A_RadialSlider_help = "\0";
+  ENTER(AL_RadialSlider);
+}
+       YY_BREAK
+
+case 345:
+YY_RULE_SETUP
+ENTER(VALUE1); BUFFERSET(A_RadialSlider_id);
+       YY_BREAK
+case 346:
+YY_RULE_SETUP
+ENTER(VALUE2); BUFFERSET(A_RadialSlider_id);
+       YY_BREAK
+case 347:
+YY_RULE_SETUP
+ENTER(VALUE1); BUFFERSET(A_RadialSlider_visible);
+       YY_BREAK
+case 348:
+YY_RULE_SETUP
+ENTER(VALUE2); BUFFERSET(A_RadialSlider_visible);
+       YY_BREAK
+case 349:
+YY_RULE_SETUP
+ENTER(VALUE1); BUFFERSET(A_RadialSlider_x);
+       YY_BREAK
+case 350:
+YY_RULE_SETUP
+ENTER(VALUE2); BUFFERSET(A_RadialSlider_x);
+       YY_BREAK
+case 351:
+YY_RULE_SETUP
+ENTER(VALUE1); BUFFERSET(A_RadialSlider_y);
+       YY_BREAK
+case 352:
+YY_RULE_SETUP
+ENTER(VALUE2); BUFFERSET(A_RadialSlider_y);
+       YY_BREAK
+case 353:
+YY_RULE_SETUP
+ENTER(VALUE1); BUFFERSET(A_RadialSlider_lefttop);
+       YY_BREAK
+case 354:
+YY_RULE_SETUP
+ENTER(VALUE2); BUFFERSET(A_RadialSlider_lefttop);
+       YY_BREAK
+case 355:
+YY_RULE_SETUP
+ENTER(VALUE1); BUFFERSET(A_RadialSlider_rightbottom);
+       YY_BREAK
+case 356:
+YY_RULE_SETUP
+ENTER(VALUE2); BUFFERSET(A_RadialSlider_rightbottom);
+       YY_BREAK
+case 357:
+YY_RULE_SETUP
+ENTER(VALUE1); BUFFERSET(A_RadialSlider_sequence);
+       YY_BREAK
+case 358:
+YY_RULE_SETUP
+ENTER(VALUE2); BUFFERSET(A_RadialSlider_sequence);
+       YY_BREAK
+case 359:
+YY_RULE_SETUP
+ENTER(VALUE1); BUFFERSET(A_RadialSlider_nbimages);
+       YY_BREAK
+case 360:
+YY_RULE_SETUP
+ENTER(VALUE2); BUFFERSET(A_RadialSlider_nbimages);
+       YY_BREAK
+case 361:
+YY_RULE_SETUP
+ENTER(VALUE1); BUFFERSET(A_RadialSlider_minangle);
+       YY_BREAK
+case 362:
+YY_RULE_SETUP
+ENTER(VALUE2); BUFFERSET(A_RadialSlider_minangle);
+       YY_BREAK
+case 363:
+YY_RULE_SETUP
+ENTER(VALUE1); BUFFERSET(A_RadialSlider_maxangle);
+       YY_BREAK
+case 364:
+YY_RULE_SETUP
+ENTER(VALUE2); BUFFERSET(A_RadialSlider_maxangle);
+       YY_BREAK
+case 365:
+YY_RULE_SETUP
+ENTER(VALUE1); BUFFERSET(A_RadialSlider_value);
+       YY_BREAK
+case 366:
+YY_RULE_SETUP
+ENTER(VALUE2); BUFFERSET(A_RadialSlider_value);
+       YY_BREAK
+case 367:
+YY_RULE_SETUP
+ENTER(VALUE1); BUFFERSET(A_RadialSlider_tooltiptext);
+       YY_BREAK
+case 368:
+YY_RULE_SETUP
+ENTER(VALUE2); BUFFERSET(A_RadialSlider_tooltiptext);
+       YY_BREAK
+case 369:
+YY_RULE_SETUP
+ENTER(VALUE1); BUFFERSET(A_RadialSlider_help);
+       YY_BREAK
+case 370:
+YY_RULE_SETUP
+ENTER(VALUE2); BUFFERSET(A_RadialSlider_help);
+       YY_BREAK
+case 371:
+YY_RULE_SETUP
+{
+  if (!A_RadialSlider_sequence) FAIL("Required attribute `sequence' not set for `RadialSlider' element.");
+  if (!A_RadialSlider_nbimages) FAIL("Required attribute `nbimages' not set for `RadialSlider' element.");
+  LEAVE; STag_RadialSlider(pContext); pcdata = NULL; ENTER(E_RadialSlider);
+ }
+       YY_BREAK
+case 372:
+YY_RULE_SETUP
+{
+  if (!A_RadialSlider_sequence) FAIL("Required attribute `sequence' not set for `RadialSlider' element.");
+  if (!A_RadialSlider_nbimages) FAIL("Required attribute `nbimages' not set for `RadialSlider' element.");
+  LEAVE; STag_RadialSlider(pContext); pcdata = NULL; ETag_RadialSlider(pContext);
+  switch (YY_START) {
+   case S_Group_2: case S_Group_1: case S_Group: SET(S_Group_2); break;
+   case ROOT_RadialSlider: SET(EPILOG); break;
+  }
+ }
+       YY_BREAK
+case 373:
+YY_RULE_SETUP
+FAIL("Unexpected character `%c' in attribute list of RadialSlider element.", yytext[0]);
+       YY_BREAK
+case 374:
+YY_RULE_SETUP
+FAIL("Bad attribute `%s' in `RadialSlider' element start tag.",yytext);
+       YY_BREAK
+case YY_STATE_EOF(AL_RadialSlider):
+FAIL("EOF in attribute list of `RadialSlider' element.");
+       YY_BREAK
+
+
+case 375:
+YY_RULE_SETUP
+{
+  LEAVE;
+  ETag_RadialSlider(pContext);
+  switch (YY_START) {
+   case S_Group_2: case S_Group_1: case S_Group: SET(S_Group_2); break;
+   case ROOT_RadialSlider: SET(EPILOG); break;
+  }
+ }
+       YY_BREAK
+case 376:
+YY_RULE_SETUP
+FAIL("Unexpected end-tag `%s': `</RadialSlider>' expected.",yytext);
+       YY_BREAK
+case 377:
+YY_RULE_SETUP
+FAIL("Unexpected character `%c': `</RadialSlider>' expected.",yytext[0]);
+       YY_BREAK
+case YY_STATE_EOF(E_RadialSlider):
+FAIL("Premature EOF: `</RadialSlider>' expected.");
+       YY_BREAK
+
+/*         id          CDATA   "none"
+  *         visible     CDATA   "true"
+  *         x           CDATA   "\0"
+  *         y           CDATA   "\0"
+  *         text        CDATA   ""
+  *         font        CDATA   #REQUIRED
+  *         align       CDATA   "left"
+  *         width       CDATA   "\0"
+  *         display     CDATA   "none"
+  *         scroll      CDATA   "true"
+  *         scrollspace CDATA   "20"
+  *         help        CDATA   "\0"
+  *     >  */
+case 378:
+YY_RULE_SETUP
+{
+  A_Text_id = "none";
+  A_Text_visible = "true";
+  A_Text_x = "\0";
+  A_Text_y = "\0";
+  A_Text_text = NULL;
+  A_Text_font = NULL;
+  A_Text_align = "left";
+  A_Text_width = "\0";
+  A_Text_display = "none";
+  A_Text_scroll = "true";
+  A_Text_scrollspace = "20";
+  A_Text_help = "\0";
+  ENTER(AL_Text);
+}
+       YY_BREAK
+
+case 379:
+YY_RULE_SETUP
+ENTER(VALUE1); BUFFERSET(A_Text_id);
+       YY_BREAK
+case 380:
+YY_RULE_SETUP
+ENTER(VALUE2); BUFFERSET(A_Text_id);
+       YY_BREAK
+case 381:
+YY_RULE_SETUP
+ENTER(VALUE1); BUFFERSET(A_Text_visible);
+       YY_BREAK
+case 382:
+YY_RULE_SETUP
+ENTER(VALUE2); BUFFERSET(A_Text_visible);
+       YY_BREAK
+case 383:
+YY_RULE_SETUP
+ENTER(VALUE1); BUFFERSET(A_Text_x);
+       YY_BREAK
+case 384:
+YY_RULE_SETUP
+ENTER(VALUE2); BUFFERSET(A_Text_x);
+       YY_BREAK
+case 385:
+YY_RULE_SETUP
+ENTER(VALUE1); BUFFERSET(A_Text_y);
+       YY_BREAK
+case 386:
+YY_RULE_SETUP
+ENTER(VALUE2); BUFFERSET(A_Text_y);
+       YY_BREAK
+case 387:
+YY_RULE_SETUP
+ENTER(VALUE1); BUFFERSET(A_Text_text);
+       YY_BREAK
+case 388:
+YY_RULE_SETUP
+ENTER(VALUE2); BUFFERSET(A_Text_text);
+       YY_BREAK
+case 389:
+YY_RULE_SETUP
+ENTER(VALUE1); BUFFERSET(A_Text_font);
+       YY_BREAK
+case 390:
+YY_RULE_SETUP
+ENTER(VALUE2); BUFFERSET(A_Text_font);
+       YY_BREAK
+case 391:
+YY_RULE_SETUP
+ENTER(VALUE1); BUFFERSET(A_Text_align);
+       YY_BREAK
+case 392:
+YY_RULE_SETUP
+ENTER(VALUE2); BUFFERSET(A_Text_align);
+       YY_BREAK
+case 393:
+YY_RULE_SETUP
+ENTER(VALUE1); BUFFERSET(A_Text_width);
+       YY_BREAK
+case 394:
+YY_RULE_SETUP
+ENTER(VALUE2); BUFFERSET(A_Text_width);
+       YY_BREAK
+case 395:
+YY_RULE_SETUP
+ENTER(VALUE1); BUFFERSET(A_Text_display);
+       YY_BREAK
+case 396:
+YY_RULE_SETUP
+ENTER(VALUE2); BUFFERSET(A_Text_display);
+       YY_BREAK
+case 397:
+YY_RULE_SETUP
+ENTER(VALUE1); BUFFERSET(A_Text_scroll);
+       YY_BREAK
+case 398:
+YY_RULE_SETUP
+ENTER(VALUE2); BUFFERSET(A_Text_scroll);
+       YY_BREAK
+case 399:
+YY_RULE_SETUP
+ENTER(VALUE1); BUFFERSET(A_Text_scrollspace);
+       YY_BREAK
+case 400:
+YY_RULE_SETUP
+ENTER(VALUE2); BUFFERSET(A_Text_scrollspace);
+       YY_BREAK
+case 401:
+YY_RULE_SETUP
+ENTER(VALUE1); BUFFERSET(A_Text_help);
+       YY_BREAK
+case 402:
+YY_RULE_SETUP
+ENTER(VALUE2); BUFFERSET(A_Text_help);
+       YY_BREAK
+case 403:
+YY_RULE_SETUP
+{
+  if (!A_Text_font) FAIL("Required attribute `font' not set for `Text' element.");
+  LEAVE; STag_Text(pContext); pcdata = NULL; ENTER(E_Text);
+ }
+       YY_BREAK
+case 404:
+YY_RULE_SETUP
+{
+  if (!A_Text_font) FAIL("Required attribute `font' not set for `Text' element.");
+  LEAVE; STag_Text(pContext); pcdata = NULL; ETag_Text(pContext);
+  switch (YY_START) {
+   case S_Group_2: case S_Group_1: case S_Group: SET(S_Group_2); break;
+   case ROOT_Text: SET(EPILOG); break;
+  }
+ }
+       YY_BREAK
+case 405:
+YY_RULE_SETUP
+FAIL("Unexpected character `%c' in attribute list of Text element.", yytext[0]);
+       YY_BREAK
+case 406:
+YY_RULE_SETUP
+FAIL("Bad attribute `%s' in `Text' element start tag.",yytext);
+       YY_BREAK
+case YY_STATE_EOF(AL_Text):
+FAIL("EOF in attribute list of `Text' element.");
+       YY_BREAK
+
+
+case 407:
+YY_RULE_SETUP
+{
+  LEAVE;
+  ETag_Text(pContext);
+  switch (YY_START) {
+   case S_Group_2: case S_Group_1: case S_Group: SET(S_Group_2); break;
+   case ROOT_Text: SET(EPILOG); break;
+  }
+ }
+       YY_BREAK
+case 408:
+YY_RULE_SETUP
+FAIL("Unexpected end-tag `%s': `</Text>' expected.",yytext);
+       YY_BREAK
+case 409:
+YY_RULE_SETUP
+FAIL("Unexpected character `%c': `</Text>' expected.",yytext[0]);
+       YY_BREAK
+case YY_STATE_EOF(E_Text):
+FAIL("Premature EOF: `</Text>' expected.");
+       YY_BREAK
+
+/*         id          CDATA   #REQUIRED
+  *         visible     CDATA   "true"
+  *         x           CDATA   "\0"
+  *         y           CDATA   "\0"
+  *         width       CDATA   "\0"
+  *         height      CDATA   "\0"
+  *         lefttop     CDATA   "lefttop"
+  *         rightbottom CDATA   "lefttop"
+  *         font        CDATA   #REQUIRED
+  *         var         CDATA   "playlist"
+  *         fgcolor     CDATA   "#000000"
+  *         playcolor   CDATA   "#FF0000"
+  *         bgcolor1    CDATA   "#FFFFFF"
+  *         bgcolor2    CDATA   "#FFFFFF"
+  *         selcolor    CDATA   "#0000FF"
+  *         help        CDATA   "\0"
+  *     >  */
+case 410:
+YY_RULE_SETUP
+{
+  A_Playlist_id = NULL;
+  A_Playlist_visible = "true";
+  A_Playlist_x = "\0";
+  A_Playlist_y = "\0";
+  A_Playlist_width = "\0";
+  A_Playlist_height = "\0";
+  A_Playlist_lefttop = "lefttop";
+  A_Playlist_rightbottom = "lefttop";
+  A_Playlist_font = NULL;
+  A_Playlist_var = "playlist";
+  A_Playlist_fgcolor = "#000000";
+  A_Playlist_playcolor = "#FF0000";
+  A_Playlist_bgcolor1 = "#FFFFFF";
+  A_Playlist_bgcolor2 = "#FFFFFF";
+  A_Playlist_selcolor = "#0000FF";
+  A_Playlist_help = "\0";
+  ENTER(AL_Playlist);
+}
+       YY_BREAK
+
+case 411:
+YY_RULE_SETUP
+ENTER(VALUE1); BUFFERSET(A_Playlist_id);
+       YY_BREAK
+case 412:
+YY_RULE_SETUP
+ENTER(VALUE2); BUFFERSET(A_Playlist_id);
+       YY_BREAK
+case 413:
+YY_RULE_SETUP
+ENTER(VALUE1); BUFFERSET(A_Playlist_visible);
+       YY_BREAK
+case 414:
+YY_RULE_SETUP
+ENTER(VALUE2); BUFFERSET(A_Playlist_visible);
+       YY_BREAK
+case 415:
+YY_RULE_SETUP
+ENTER(VALUE1); BUFFERSET(A_Playlist_x);
+       YY_BREAK
+case 416:
+YY_RULE_SETUP
+ENTER(VALUE2); BUFFERSET(A_Playlist_x);
+       YY_BREAK
+case 417:
+YY_RULE_SETUP
+ENTER(VALUE1); BUFFERSET(A_Playlist_y);
+       YY_BREAK
+case 418:
+YY_RULE_SETUP
+ENTER(VALUE2); BUFFERSET(A_Playlist_y);
+       YY_BREAK
+case 419:
+YY_RULE_SETUP
+ENTER(VALUE1); BUFFERSET(A_Playlist_width);
+       YY_BREAK
+case 420:
+YY_RULE_SETUP
+ENTER(VALUE2); BUFFERSET(A_Playlist_width);
+       YY_BREAK
+case 421:
+YY_RULE_SETUP
+ENTER(VALUE1); BUFFERSET(A_Playlist_height);
+       YY_BREAK
+case 422:
+YY_RULE_SETUP
+ENTER(VALUE2); BUFFERSET(A_Playlist_height);
+       YY_BREAK
+case 423:
+YY_RULE_SETUP
+ENTER(VALUE1); BUFFERSET(A_Playlist_lefttop);
+       YY_BREAK
+case 424:
+YY_RULE_SETUP
+ENTER(VALUE2); BUFFERSET(A_Playlist_lefttop);
+       YY_BREAK
+case 425:
+YY_RULE_SETUP
+ENTER(VALUE1); BUFFERSET(A_Playlist_rightbottom);
+       YY_BREAK
+case 426:
+YY_RULE_SETUP
+ENTER(VALUE2); BUFFERSET(A_Playlist_rightbottom);
+       YY_BREAK
+case 427:
+YY_RULE_SETUP
+ENTER(VALUE1); BUFFERSET(A_Playlist_font);
+       YY_BREAK
+case 428:
+YY_RULE_SETUP
+ENTER(VALUE2); BUFFERSET(A_Playlist_font);
+       YY_BREAK
+case 429:
+YY_RULE_SETUP
+ENTER(VALUE1); BUFFERSET(A_Playlist_var);
+       YY_BREAK
+case 430:
+YY_RULE_SETUP
+ENTER(VALUE2); BUFFERSET(A_Playlist_var);
+       YY_BREAK
+case 431:
+YY_RULE_SETUP
+ENTER(VALUE1); BUFFERSET(A_Playlist_fgcolor);
+       YY_BREAK
+case 432:
+YY_RULE_SETUP
+ENTER(VALUE2); BUFFERSET(A_Playlist_fgcolor);
+       YY_BREAK
+case 433:
+YY_RULE_SETUP
+ENTER(VALUE1); BUFFERSET(A_Playlist_playcolor);
+       YY_BREAK
+case 434:
+YY_RULE_SETUP
+ENTER(VALUE2); BUFFERSET(A_Playlist_playcolor);
+       YY_BREAK
+case 435:
+YY_RULE_SETUP
+ENTER(VALUE1); BUFFERSET(A_Playlist_bgcolor1);
+       YY_BREAK
+case 436:
+YY_RULE_SETUP
+ENTER(VALUE2); BUFFERSET(A_Playlist_bgcolor1);
+       YY_BREAK
+case 437:
+YY_RULE_SETUP
+ENTER(VALUE1); BUFFERSET(A_Playlist_bgcolor2);
+       YY_BREAK
+case 438:
+YY_RULE_SETUP
+ENTER(VALUE2); BUFFERSET(A_Playlist_bgcolor2);
+       YY_BREAK
+case 439:
+YY_RULE_SETUP
+ENTER(VALUE1); BUFFERSET(A_Playlist_selcolor);
+       YY_BREAK
+case 440:
+YY_RULE_SETUP
+ENTER(VALUE2); BUFFERSET(A_Playlist_selcolor);
+       YY_BREAK
+case 441:
+YY_RULE_SETUP
+ENTER(VALUE1); BUFFERSET(A_Playlist_help);
+       YY_BREAK
+case 442:
+YY_RULE_SETUP
+ENTER(VALUE2); BUFFERSET(A_Playlist_help);
+       YY_BREAK
+case 443:
+YY_RULE_SETUP
+{
+  if (!A_Playlist_id) FAIL("Required attribute `id' not set for `Playlist' element.");
+  if (!A_Playlist_font) FAIL("Required attribute `font' not set for `Playlist' element.");
+  LEAVE; STag_Playlist(pContext); pcdata = NULL; ENTER(S_Playlist);
+ }
+       YY_BREAK
+case 444:
+YY_RULE_SETUP
+FAIL("`Playlist' element cannot be empty.");
+       YY_BREAK
+case 445:
+YY_RULE_SETUP
+FAIL("Unexpected character `%c' in attribute list of Playlist element.", yytext[0]);
+       YY_BREAK
+case 446:
+YY_RULE_SETUP
+FAIL("Bad attribute `%s' in `Playlist' element start tag.",yytext);
+       YY_BREAK
+case YY_STATE_EOF(AL_Playlist):
+FAIL("EOF in attribute list of `Playlist' element.");
+       YY_BREAK
+
+
+case 447:
+YY_RULE_SETUP
+{
+  LEAVE;
+  ETag_Playlist(pContext);
+  switch (YY_START) {
+   case S_Group_2: case S_Group_1: case S_Group: SET(S_Group_2); break;
+   case ROOT_Playlist: SET(EPILOG); break;
+  }
+ }
+       YY_BREAK
+case 448:
+YY_RULE_SETUP
+FAIL("Unexpected end-tag `%s': `</Playlist>' expected.",yytext);
+       YY_BREAK
+case 449:
+YY_RULE_SETUP
+FAIL("Unexpected character `%c': `</Playlist>' expected.",yytext[0]);
+       YY_BREAK
+case YY_STATE_EOF(E_Playlist):
+FAIL("Premature EOF: `</Playlist>' expected.");
+       YY_BREAK
+
+/* EPILOG: after the root element. */
+
+case 450:
+YY_RULE_SETUP
+FAIL("Unexpected character `%c' after document.", yytext[0]);
+       YY_BREAK
+case YY_STATE_EOF(EPILOG):
+SUCCEED;
+       YY_BREAK
+
+/* CHARACTER DATA. */
+
+/* Non-defined standard entities... */
+case 451:
+YY_RULE_SETUP
+BUFFERPUTC('&');
+       YY_BREAK
+case 452:
+YY_RULE_SETUP
+BUFFERPUTC('<');
+       YY_BREAK
+case 453:
+YY_RULE_SETUP
+BUFFERPUTC('>');
+       YY_BREAK
+case 454:
+YY_RULE_SETUP
+BUFFERPUTC('\'');
+       YY_BREAK
+case 455:
+YY_RULE_SETUP
+BUFFERPUTC('"');
+       YY_BREAK
+/* Character entities. */
+case 456:
+YY_RULE_SETUP
+BUFFERPUTC((unsigned char)atoi(yytext+2));
+       YY_BREAK
+case 457:
+YY_RULE_SETUP
+BUFFERPUTC((unsigned char)strtol(yytext+3,NULL,16));
+       YY_BREAK
+
+
+case 458:
+case 459:
+case 460:
+case 461:
+YY_RULE_SETUP
+BUFFERPUTC('\n');
+       YY_BREAK
+
+
+case 462:
+YY_RULE_SETUP
+ENTER(CDATA);
+       YY_BREAK
+case 463:
+YY_RULE_SETUP
+FAIL("Unexpected `]]>' in character data.");
+       YY_BREAK
+
+
+case 464:
+YY_RULE_SETUP
+BUFFERDONE; LEAVE;
+       YY_BREAK
+case YY_STATE_EOF(VALUE1):
+FAIL("EOF in literal (\"'\" expected).");
+       YY_BREAK
+
+
+case 465:
+YY_RULE_SETUP
+BUFFERDONE; LEAVE;
+       YY_BREAK
+case YY_STATE_EOF(VALUE2):
+FAIL("EOF in literal (`\"' expected).");
+       YY_BREAK
+
+
+case 466:
+YY_RULE_SETUP
+BUFFERPUTC(yytext[0]);
+       YY_BREAK
+case 467:
+YY_RULE_SETUP
+FAIL("Spurious `%c' in character data.",yytext[0]);
+       YY_BREAK
+
+
+case 468:
+YY_RULE_SETUP
+LEAVE;
+       YY_BREAK
+case 469:
+YY_RULE_SETUP
+BUFFERPUTC(yytext[0]); BUFFERPUTC(yytext[1]);
+       YY_BREAK
+case 470:
+YY_RULE_SETUP
+BUFFERPUTC(yytext[0]);
+       YY_BREAK
+case YY_STATE_EOF(CDATA):
+FAIL("EOF in CDATA section.");
+       YY_BREAK
+
+/* Impossible rules to avoid warnings from flex(1). */
+
+case 471:
+YY_RULE_SETUP
+FAIL("The Impossible Happened: INITIAL or IMPOSSIBLE state entered?");
+       YY_BREAK
+
+case 472:
+YY_RULE_SETUP
+YY_FATAL_ERROR( "flex scanner jammed" );
+       YY_BREAK
+case YY_STATE_EOF(INITIAL):
+case YY_STATE_EOF(ROOT_Theme):
+case YY_STATE_EOF(S_Theme):
+case YY_STATE_EOF(S_Theme_2):
+case YY_STATE_EOF(ROOT_Bitmap):
+case YY_STATE_EOF(ROOT_Event):
+case YY_STATE_EOF(ROOT_Font):
+case YY_STATE_EOF(ROOT_ThemeInfo):
+case YY_STATE_EOF(ROOT_Window):
+case YY_STATE_EOF(S_Window):
+case YY_STATE_EOF(S_Window_1):
+case YY_STATE_EOF(ROOT_Layout):
+case YY_STATE_EOF(S_Layout):
+case YY_STATE_EOF(ROOT_Group):
+case YY_STATE_EOF(S_Group):
+case YY_STATE_EOF(S_Group_1):
+case YY_STATE_EOF(ROOT_Anchor):
+case YY_STATE_EOF(ROOT_Image):
+case YY_STATE_EOF(ROOT_Rectangle):
+case YY_STATE_EOF(ROOT_Button):
+case YY_STATE_EOF(ROOT_CheckBox):
+case YY_STATE_EOF(ROOT_Slider):
+case YY_STATE_EOF(ROOT_RadialSlider):
+case YY_STATE_EOF(ROOT_Text):
+case YY_STATE_EOF(ROOT_Playlist):
+case YY_STATE_EOF(S_Playlist):
+case YY_STATE_EOF(IMPOSSIBLE):
+       yyterminate();
+
+       case YY_END_OF_BUFFER:
+               {
+               /* Amount of text matched not including the EOB char. */
+               int yy_amount_of_matched_text = (int) (yy_cp - yytext_ptr) - 1;
+
+               /* Undo the effects of YY_DO_BEFORE_ACTION. */
+               *yy_cp = yy_hold_char;
+               YY_RESTORE_YY_MORE_OFFSET
+
+               if ( yy_current_buffer->yy_buffer_status == YY_BUFFER_NEW )
+                       {
+                       /* We're scanning a new file or input source.  It's
+                        * possible that this happened because the user
+                        * just pointed yyin at a new source and called
+                        * yylex().  If so, then we have to assure
+                        * consistency between yy_current_buffer and our
+                        * globals.  Here is the right place to do so, because
+                        * this is the first action (other than possibly a
+                        * back-up) that will match for the new input source.
+                        */
+                       yy_n_chars = yy_current_buffer->yy_n_chars;
+                       yy_current_buffer->yy_input_file = yyin;
+                       yy_current_buffer->yy_buffer_status = YY_BUFFER_NORMAL;
+                       }
+
+               /* Note that here we test for yy_c_buf_p "<=" to the position
+                * of the first EOB in the buffer, since yy_c_buf_p will
+                * already have been incremented past the NUL character
+                * (since all states make transitions on EOB to the
+                * end-of-buffer state).  Contrast this with the test
+                * in input().
+                */
+               if ( yy_c_buf_p <= &yy_current_buffer->yy_ch_buf[yy_n_chars] )
+                       { /* This was really a NUL. */
+                       yy_state_type yy_next_state;
+
+                       yy_c_buf_p = yytext_ptr + yy_amount_of_matched_text;
+
+                       yy_current_state = yy_get_previous_state();
+
+                       /* Okay, we're now positioned to make the NUL
+                        * transition.  We couldn't have
+                        * yy_get_previous_state() go ahead and do it
+                        * for us because it doesn't know how to deal
+                        * with the possibility of jamming (and we don't
+                        * want to build jamming into it because then it
+                        * will run more slowly).
+                        */
+
+                       yy_next_state = yy_try_NUL_trans( yy_current_state );
+
+                       yy_bp = yytext_ptr + YY_MORE_ADJ;
+
+                       if ( yy_next_state )
+                               {
+                               /* Consume the NUL. */
+                               yy_cp = ++yy_c_buf_p;
+                               yy_current_state = yy_next_state;
+                               goto yy_match;
+                               }
+
+                       else
+                               {
+                               yy_cp = yy_last_accepting_cpos;
+                               yy_current_state = yy_last_accepting_state;
+                               goto yy_find_action;
+                               }
+                       }
+
+               else switch ( yy_get_next_buffer() )
+                       {
+                       case EOB_ACT_END_OF_FILE:
+                               {
+                               yy_did_buffer_switch_on_eof = 0;
+
+                               if ( yywrap() )
+                                       {
+                                       /* Note: because we've taken care in
+                                        * yy_get_next_buffer() to have set up
+                                        * yytext, we can now set up
+                                        * yy_c_buf_p so that if some total
+                                        * hoser (like flex itself) wants to
+                                        * call the scanner after we return the
+                                        * YY_NULL, it'll still work - another
+                                        * YY_NULL will get returned.
+                                        */
+                                       yy_c_buf_p = yytext_ptr + YY_MORE_ADJ;
+
+                                       yy_act = YY_STATE_EOF(YY_START);
+                                       goto do_action;
+                                       }
+
+                               else
+                                       {
+                                       if ( ! yy_did_buffer_switch_on_eof )
+                                               YY_NEW_FILE;
+                                       }
+                               break;
+                               }
+
+                       case EOB_ACT_CONTINUE_SCAN:
+                               yy_c_buf_p =
+                                       yytext_ptr + yy_amount_of_matched_text;
+
+                               yy_current_state = yy_get_previous_state();
+
+                               yy_cp = yy_c_buf_p;
+                               yy_bp = yytext_ptr + YY_MORE_ADJ;
+                               goto yy_match;
+
+                       case EOB_ACT_LAST_MATCH:
+                               yy_c_buf_p =
+                               &yy_current_buffer->yy_ch_buf[yy_n_chars];
+
+                               yy_current_state = yy_get_previous_state();
+
+                               yy_cp = yy_c_buf_p;
+                               yy_bp = yytext_ptr + YY_MORE_ADJ;
+                               goto yy_find_action;
+                       }
+               break;
+               }
+
+       default:
+               YY_FATAL_ERROR(
+                       "fatal flex scanner internal error--no action found" );
+       } /* end of action switch */
+               } /* end of scanning one token */
+       } /* end of yylex */
+
+
+/* yy_get_next_buffer - try to read in a new buffer
+ *
+ * Returns a code representing an action:
+ *     EOB_ACT_LAST_MATCH -
+ *     EOB_ACT_CONTINUE_SCAN - continue scanning from current position
+ *     EOB_ACT_END_OF_FILE - end of file
+ */
+
+static int yy_get_next_buffer()
+       {
+       register char *dest = yy_current_buffer->yy_ch_buf;
+       register char *source = yytext_ptr;
+       register int number_to_move, i;
+       int ret_val;
+
+       if ( yy_c_buf_p > &yy_current_buffer->yy_ch_buf[yy_n_chars + 1] )
+               YY_FATAL_ERROR(
+               "fatal flex scanner internal error--end of buffer missed" );
+
+       if ( yy_current_buffer->yy_fill_buffer == 0 )
+               { /* Don't try to fill the buffer, so this is an EOF. */
+               if ( yy_c_buf_p - yytext_ptr - YY_MORE_ADJ == 1 )
+                       {
+                       /* We matched a single character, the EOB, so
+                        * treat this as a final EOF.
+                        */
+                       return EOB_ACT_END_OF_FILE;
+                       }
+
+               else
+                       {
+                       /* We matched some text prior to the EOB, first
+                        * process it.
+                        */
+                       return EOB_ACT_LAST_MATCH;
+                       }
+               }
+
+       /* Try to read more data. */
+
+       /* First move last chars to start of buffer. */
+       number_to_move = (int) (yy_c_buf_p - yytext_ptr) - 1;
+
+       for ( i = 0; i < number_to_move; ++i )
+               *(dest++) = *(source++);
+
+       if ( yy_current_buffer->yy_buffer_status == YY_BUFFER_EOF_PENDING )
+               /* don't do the read, it's not guaranteed to return an EOF,
+                * just force an EOF
+                */
+               yy_current_buffer->yy_n_chars = yy_n_chars = 0;
+
+       else
+               {
+               int num_to_read =
+                       yy_current_buffer->yy_buf_size - number_to_move - 1;
+
+               while ( num_to_read <= 0 )
+                       { /* Not enough room in the buffer - grow it. */
+#ifdef YY_USES_REJECT
+                       YY_FATAL_ERROR(
+"input buffer overflow, can't enlarge buffer because scanner uses REJECT" );
+#else
+
+                       /* just a shorter name for the current buffer */
+                       YY_BUFFER_STATE b = yy_current_buffer;
+
+                       int yy_c_buf_p_offset =
+                               (int) (yy_c_buf_p - b->yy_ch_buf);
+
+                       if ( b->yy_is_our_buffer )
+                               {
+                               int new_size = b->yy_buf_size * 2;
+
+                               if ( new_size <= 0 )
+                                       b->yy_buf_size += b->yy_buf_size / 8;
+                               else
+                                       b->yy_buf_size *= 2;
+
+                               b->yy_ch_buf = (char *)
+                                       /* Include room in for 2 EOB chars. */
+                                       yy_flex_realloc( (void *) b->yy_ch_buf,
+                                                        b->yy_buf_size + 2 );
+                               }
+                       else
+                               /* Can't grow it, we don't own it. */
+                               b->yy_ch_buf = 0;
+
+                       if ( ! b->yy_ch_buf )
+                               YY_FATAL_ERROR(
+                               "fatal error - scanner input buffer overflow" );
+
+                       yy_c_buf_p = &b->yy_ch_buf[yy_c_buf_p_offset];
+
+                       num_to_read = yy_current_buffer->yy_buf_size -
+                                               number_to_move - 1;
+#endif
+                       }
+
+               if ( num_to_read > YY_READ_BUF_SIZE )
+                       num_to_read = YY_READ_BUF_SIZE;
+
+               /* Read in more data. */
+               YY_INPUT( (&yy_current_buffer->yy_ch_buf[number_to_move]),
+                       yy_n_chars, num_to_read );
+
+               yy_current_buffer->yy_n_chars = yy_n_chars;
+               }
+
+       if ( yy_n_chars == 0 )
+               {
+               if ( number_to_move == YY_MORE_ADJ )
+                       {
+                       ret_val = EOB_ACT_END_OF_FILE;
+                       yyrestart( yyin );
+                       }
+
+               else
+                       {
+                       ret_val = EOB_ACT_LAST_MATCH;
+                       yy_current_buffer->yy_buffer_status =
+                               YY_BUFFER_EOF_PENDING;
+                       }
+               }
+
+       else
+               ret_val = EOB_ACT_CONTINUE_SCAN;
+
+       yy_n_chars += number_to_move;
+       yy_current_buffer->yy_ch_buf[yy_n_chars] = YY_END_OF_BUFFER_CHAR;
+       yy_current_buffer->yy_ch_buf[yy_n_chars + 1] = YY_END_OF_BUFFER_CHAR;
+
+       yytext_ptr = &yy_current_buffer->yy_ch_buf[0];
+
+       return ret_val;
+       }
+
+
+/* yy_get_previous_state - get the state just before the EOB char was reached */
+
+static yy_state_type yy_get_previous_state()
+       {
+       register yy_state_type yy_current_state;
+       register char *yy_cp;
+
+       yy_current_state = yy_start;
+
+       for ( yy_cp = yytext_ptr + YY_MORE_ADJ; yy_cp < yy_c_buf_p; ++yy_cp )
+               {
+               register YY_CHAR yy_c = (*yy_cp ? yy_ec[YY_SC_TO_UI(*yy_cp)] : 1);
+               if ( yy_accept[yy_current_state] )
+                       {
+                       yy_last_accepting_state = yy_current_state;
+                       yy_last_accepting_cpos = yy_cp;
+                       }
+               while ( yy_chk[yy_base[yy_current_state] + yy_c] != yy_current_state )
+                       {
+                       yy_current_state = (int) yy_def[yy_current_state];
+                       if ( yy_current_state >= 2803 )
+                               yy_c = yy_meta[(unsigned int) yy_c];
+                       }
+               yy_current_state = yy_nxt[yy_base[yy_current_state] + (unsigned int) yy_c];
+               }
+
+       return yy_current_state;
+       }
+
+
+/* yy_try_NUL_trans - try to make a transition on the NUL character
+ *
+ * synopsis
+ *     next_state = yy_try_NUL_trans( current_state );
+ */
+
+#ifdef YY_USE_PROTOS
+static yy_state_type yy_try_NUL_trans( yy_state_type yy_current_state )
+#else
+static yy_state_type yy_try_NUL_trans( yy_current_state )
+yy_state_type yy_current_state;
+#endif
+       {
+       register int yy_is_jam;
+       register char *yy_cp = yy_c_buf_p;
+
+       register YY_CHAR yy_c = 1;
+       if ( yy_accept[yy_current_state] )
+               {
+               yy_last_accepting_state = yy_current_state;
+               yy_last_accepting_cpos = yy_cp;
+               }
+       while ( yy_chk[yy_base[yy_current_state] + yy_c] != yy_current_state )
+               {
+               yy_current_state = (int) yy_def[yy_current_state];
+               if ( yy_current_state >= 2803 )
+                       yy_c = yy_meta[(unsigned int) yy_c];
+               }
+       yy_current_state = yy_nxt[yy_base[yy_current_state] + (unsigned int) yy_c];
+       yy_is_jam = (yy_current_state == 2802);
+
+       return yy_is_jam ? 0 : yy_current_state;
+       }
+
+
+#ifndef YY_NO_UNPUT
+#ifdef YY_USE_PROTOS
+static void yyunput( int c, register char *yy_bp )
+#else
+static void yyunput( c, yy_bp )
+int c;
+register char *yy_bp;
+#endif
+       {
+       register char *yy_cp = yy_c_buf_p;
+
+       /* undo effects of setting up yytext */
+       *yy_cp = yy_hold_char;
+
+       if ( yy_cp < yy_current_buffer->yy_ch_buf + 2 )
+               { /* need to shift things up to make room */
+               /* +2 for EOB chars. */
+               register int number_to_move = yy_n_chars + 2;
+               register char *dest = &yy_current_buffer->yy_ch_buf[
+                                       yy_current_buffer->yy_buf_size + 2];
+               register char *source =
+                               &yy_current_buffer->yy_ch_buf[number_to_move];
+
+               while ( source > yy_current_buffer->yy_ch_buf )
+                       *--dest = *--source;
+
+               yy_cp += (int) (dest - source);
+               yy_bp += (int) (dest - source);
+               yy_current_buffer->yy_n_chars =
+                       yy_n_chars = yy_current_buffer->yy_buf_size;
+
+               if ( yy_cp < yy_current_buffer->yy_ch_buf + 2 )
+                       YY_FATAL_ERROR( "flex scanner push-back overflow" );
+               }
+
+       *--yy_cp = (char) c;
+
+
+       yytext_ptr = yy_bp;
+       yy_hold_char = *yy_cp;
+       yy_c_buf_p = yy_cp;
+       }
+#endif /* ifndef YY_NO_UNPUT */
+
+
+#ifdef __cplusplus
+static int yyinput()
+#else
+static int input()
+#endif
+       {
+       int c;
+
+       *yy_c_buf_p = yy_hold_char;
+
+       if ( *yy_c_buf_p == YY_END_OF_BUFFER_CHAR )
+               {
+               /* yy_c_buf_p now points to the character we want to return.
+                * If this occurs *before* the EOB characters, then it's a
+                * valid NUL; if not, then we've hit the end of the buffer.
+                */
+               if ( yy_c_buf_p < &yy_current_buffer->yy_ch_buf[yy_n_chars] )
+                       /* This was really a NUL. */
+                       *yy_c_buf_p = '\0';
+
+               else
+                       { /* need more input */
+                       int offset = yy_c_buf_p - yytext_ptr;
+                       ++yy_c_buf_p;
+
+                       switch ( yy_get_next_buffer() )
+                               {
+                               case EOB_ACT_LAST_MATCH:
+                                       /* This happens because yy_g_n_b()
+                                        * sees that we've accumulated a
+                                        * token and flags that we need to
+                                        * try matching the token before
+                                        * proceeding.  But for input(),
+                                        * there's no matching to consider.
+                                        * So convert the EOB_ACT_LAST_MATCH
+                                        * to EOB_ACT_END_OF_FILE.
+                                        */
+
+                                       /* Reset buffer status. */
+                                       yyrestart( yyin );
+
+                                       /* fall through */
+
+                               case EOB_ACT_END_OF_FILE:
+                                       {
+                                       if ( yywrap() )
+                                               return EOF;
+
+                                       if ( ! yy_did_buffer_switch_on_eof )
+                                               YY_NEW_FILE;
+#ifdef __cplusplus
+                                       return yyinput();
+#else
+                                       return input();
+#endif
+                                       }
+
+                               case EOB_ACT_CONTINUE_SCAN:
+                                       yy_c_buf_p = yytext_ptr + offset;
+                                       break;
+                               }
+                       }
+               }
+
+       c = *(unsigned char *) yy_c_buf_p;      /* cast for 8-bit char's */
+       *yy_c_buf_p = '\0';     /* preserve yytext */
+       yy_hold_char = *++yy_c_buf_p;
+
+
+       return c;
+       }
+
+
+#ifdef YY_USE_PROTOS
+void yyrestart( FILE *input_file )
+#else
+void yyrestart( input_file )
+FILE *input_file;
+#endif
+       {
+       if ( ! yy_current_buffer )
+               yy_current_buffer = yy_create_buffer( yyin, YY_BUF_SIZE );
+
+       yy_init_buffer( yy_current_buffer, input_file );
+       yy_load_buffer_state();
+       }
+
+
+#ifdef YY_USE_PROTOS
+void yy_switch_to_buffer( YY_BUFFER_STATE new_buffer )
+#else
+void yy_switch_to_buffer( new_buffer )
+YY_BUFFER_STATE new_buffer;
+#endif
+       {
+       if ( yy_current_buffer == new_buffer )
+               return;
+
+       if ( yy_current_buffer )
+               {
+               /* Flush out information for old buffer. */
+               *yy_c_buf_p = yy_hold_char;
+               yy_current_buffer->yy_buf_pos = yy_c_buf_p;
+               yy_current_buffer->yy_n_chars = yy_n_chars;
+               }
+
+       yy_current_buffer = new_buffer;
+       yy_load_buffer_state();
+
+       /* We don't actually know whether we did this switch during
+        * EOF (yywrap()) processing, but the only time this flag
+        * is looked at is after yywrap() is called, so it's safe
+        * to go ahead and always set it.
+        */
+       yy_did_buffer_switch_on_eof = 1;
+       }
+
+
+#ifdef YY_USE_PROTOS
+void yy_load_buffer_state( void )
+#else
+void yy_load_buffer_state()
+#endif
+       {
+       yy_n_chars = yy_current_buffer->yy_n_chars;
+       yytext_ptr = yy_c_buf_p = yy_current_buffer->yy_buf_pos;
+       yyin = yy_current_buffer->yy_input_file;
+       yy_hold_char = *yy_c_buf_p;
+       }
+
+
+#ifdef YY_USE_PROTOS
+YY_BUFFER_STATE yy_create_buffer( FILE *file, int size )
+#else
+YY_BUFFER_STATE yy_create_buffer( file, size )
+FILE *file;
+int size;
+#endif
+       {
+       YY_BUFFER_STATE b;
+
+       b = (YY_BUFFER_STATE) yy_flex_alloc( sizeof( struct yy_buffer_state ) );
+       if ( ! b )
+               YY_FATAL_ERROR( "out of dynamic memory in yy_create_buffer()" );
+
+       b->yy_buf_size = size;
+
+       /* yy_ch_buf has to be 2 characters longer than the size given because
+        * we need to put in 2 end-of-buffer characters.
+        */
+       b->yy_ch_buf = (char *) yy_flex_alloc( b->yy_buf_size + 2 );
+       if ( ! b->yy_ch_buf )
+               YY_FATAL_ERROR( "out of dynamic memory in yy_create_buffer()" );
+
+       b->yy_is_our_buffer = 1;
+
+       yy_init_buffer( b, file );
+
+       return b;
+       }
+
+
+#ifdef YY_USE_PROTOS
+void yy_delete_buffer( YY_BUFFER_STATE b )
+#else
+void yy_delete_buffer( b )
+YY_BUFFER_STATE b;
+#endif
+       {
+       if ( ! b )
+               return;
+
+       if ( b == yy_current_buffer )
+               yy_current_buffer = (YY_BUFFER_STATE) 0;
+
+       if ( b->yy_is_our_buffer )
+               yy_flex_free( (void *) b->yy_ch_buf );
+
+       yy_flex_free( (void *) b );
+       }
+
+
+#ifndef _WIN32
+#include <unistd.h>
+#else
+#ifndef YY_ALWAYS_INTERACTIVE
+#ifndef YY_NEVER_INTERACTIVE
+extern int isatty YY_PROTO(( int ));
+#endif
+#endif
+#endif
+
+#ifdef YY_USE_PROTOS
+void yy_init_buffer( YY_BUFFER_STATE b, FILE *file )
+#else
+void yy_init_buffer( b, file )
+YY_BUFFER_STATE b;
+FILE *file;
+#endif
+
+
+       {
+       yy_flush_buffer( b );
+
+       b->yy_input_file = file;
+       b->yy_fill_buffer = 1;
+
+#if YY_ALWAYS_INTERACTIVE
+       b->yy_is_interactive = 1;
+#else
+#if YY_NEVER_INTERACTIVE
+       b->yy_is_interactive = 0;
+#else
+       b->yy_is_interactive = file ? (isatty( fileno(file) ) > 0) : 0;
+#endif
+#endif
+       }
+
+
+#ifdef YY_USE_PROTOS
+void yy_flush_buffer( YY_BUFFER_STATE b )
+#else
+void yy_flush_buffer( b )
+YY_BUFFER_STATE b;
+#endif
+
+       {
+       if ( ! b )
+               return;
+
+       b->yy_n_chars = 0;
+
+       /* We always need two end-of-buffer characters.  The first causes
+        * a transition to the end-of-buffer state.  The second causes
+        * a jam in that state.
+        */
+       b->yy_ch_buf[0] = YY_END_OF_BUFFER_CHAR;
+       b->yy_ch_buf[1] = YY_END_OF_BUFFER_CHAR;
+
+       b->yy_buf_pos = &b->yy_ch_buf[0];
+
+       b->yy_at_bol = 1;
+       b->yy_buffer_status = YY_BUFFER_NEW;
+
+       if ( b == yy_current_buffer )
+               yy_load_buffer_state();
+       }
+
+
+#ifndef YY_NO_SCAN_BUFFER
+#ifdef YY_USE_PROTOS
+YY_BUFFER_STATE yy_scan_buffer( char *base, yy_size_t size )
+#else
+YY_BUFFER_STATE yy_scan_buffer( base, size )
+char *base;
+yy_size_t size;
+#endif
+       {
+       YY_BUFFER_STATE b;
+
+       if ( size < 2 ||
+            base[size-2] != YY_END_OF_BUFFER_CHAR ||
+            base[size-1] != YY_END_OF_BUFFER_CHAR )
+               /* They forgot to leave room for the EOB's. */
+               return 0;
+
+       b = (YY_BUFFER_STATE) yy_flex_alloc( sizeof( struct yy_buffer_state ) );
+       if ( ! b )
+               YY_FATAL_ERROR( "out of dynamic memory in yy_scan_buffer()" );
+
+       b->yy_buf_size = size - 2;      /* "- 2" to take care of EOB's */
+       b->yy_buf_pos = b->yy_ch_buf = base;
+       b->yy_is_our_buffer = 0;
+       b->yy_input_file = 0;
+       b->yy_n_chars = b->yy_buf_size;
+       b->yy_is_interactive = 0;
+       b->yy_at_bol = 1;
+       b->yy_fill_buffer = 0;
+       b->yy_buffer_status = YY_BUFFER_NEW;
+
+       yy_switch_to_buffer( b );
+
+       return b;
+       }
+#endif
+
+
+#ifndef YY_NO_SCAN_STRING
+#ifdef YY_USE_PROTOS
+YY_BUFFER_STATE yy_scan_string( yyconst char *yy_str )
+#else
+YY_BUFFER_STATE yy_scan_string( yy_str )
+yyconst char *yy_str;
+#endif
+       {
+       int len;
+       for ( len = 0; yy_str[len]; ++len )
+               ;
+
+       return yy_scan_bytes( yy_str, len );
+       }
+#endif
+
+
+#ifndef YY_NO_SCAN_BYTES
+#ifdef YY_USE_PROTOS
+YY_BUFFER_STATE yy_scan_bytes( yyconst char *bytes, int len )
+#else
+YY_BUFFER_STATE yy_scan_bytes( bytes, len )
+yyconst char *bytes;
+int len;
+#endif
+       {
+       YY_BUFFER_STATE b;
+       char *buf;
+       yy_size_t n;
+       int i;
+
+       /* Get memory for full buffer, including space for trailing EOB's. */
+       n = len + 2;
+       buf = (char *) yy_flex_alloc( n );
+       if ( ! buf )
+               YY_FATAL_ERROR( "out of dynamic memory in yy_scan_bytes()" );
+
+       for ( i = 0; i < len; ++i )
+               buf[i] = bytes[i];
+
+       buf[len] = buf[len+1] = YY_END_OF_BUFFER_CHAR;
+
+       b = yy_scan_buffer( buf, n );
+       if ( ! b )
+               YY_FATAL_ERROR( "bad buffer in yy_scan_bytes()" );
+
+       /* It's okay to grow etc. this buffer, and we should throw it
+        * away when we're done.
+        */
+       b->yy_is_our_buffer = 1;
+
+       return b;
+       }
+#endif
+
+
+#ifndef YY_NO_PUSH_STATE
+#ifdef YY_USE_PROTOS
+static void yy_push_state( int new_state )
+#else
+static void yy_push_state( new_state )
+int new_state;
+#endif
+       {
+       if ( yy_start_stack_ptr >= yy_start_stack_depth )
+               {
+               yy_size_t new_size;
+
+               yy_start_stack_depth += YY_START_STACK_INCR;
+               new_size = yy_start_stack_depth * sizeof( int );
+
+               if ( ! yy_start_stack )
+                       yy_start_stack = (int *) yy_flex_alloc( new_size );
+
+               else
+                       yy_start_stack = (int *) yy_flex_realloc(
+                                       (void *) yy_start_stack, new_size );
+
+               if ( ! yy_start_stack )
+                       YY_FATAL_ERROR(
+                       "out of memory expanding start-condition stack" );
+               }
+
+       yy_start_stack[yy_start_stack_ptr++] = YY_START;
+
+       BEGIN(new_state);
+       }
+#endif
+
+
+#ifndef YY_NO_POP_STATE
+static void yy_pop_state()
+       {
+       if ( --yy_start_stack_ptr < 0 )
+               YY_FATAL_ERROR( "start-condition stack underflow" );
+
+       BEGIN(yy_start_stack[yy_start_stack_ptr]);
+       }
+#endif
+
+
+#ifndef YY_NO_TOP_STATE
+static int yy_top_state()
+       {
+       return yy_start_stack[yy_start_stack_ptr - 1];
+       }
+#endif
+
+#ifndef YY_EXIT_FAILURE
+#define YY_EXIT_FAILURE 2
+#endif
+
+#ifdef YY_USE_PROTOS
+static void yy_fatal_error( yyconst char msg[] )
+#else
+static void yy_fatal_error( msg )
+char msg[];
+#endif
+       {
+       (void) fprintf( stderr, "%s\n", msg );
+       exit( YY_EXIT_FAILURE );
+       }
+
+
+
+/* Redefine yyless() so it works in section 3 code. */
+
+#undef yyless
+#define yyless(n) \
+       do \
+               { \
+               /* Undo effects of setting up yytext. */ \
+               yytext[yyleng] = yy_hold_char; \
+               yy_c_buf_p = yytext + n; \
+               yy_hold_char = *yy_c_buf_p; \
+               *yy_c_buf_p = '\0'; \
+               yyleng = n; \
+               } \
+       while ( 0 )
+
+
+/* Internal utility routines. */
+
+#ifndef yytext_ptr
+#ifdef YY_USE_PROTOS
+static void yy_flex_strncpy( char *s1, yyconst char *s2, int n )
+#else
+static void yy_flex_strncpy( s1, s2, n )
+char *s1;
+yyconst char *s2;
+int n;
+#endif
+       {
+       register int i;
+       for ( i = 0; i < n; ++i )
+               s1[i] = s2[i];
+       }
+#endif
+
+#ifdef YY_NEED_STRLEN
+#ifdef YY_USE_PROTOS
+static int yy_flex_strlen( yyconst char *s )
+#else
+static int yy_flex_strlen( s )
+yyconst char *s;
+#endif
+       {
+       register int n;
+       for ( n = 0; s[n]; ++n )
+               ;
+
+       return n;
+       }
+#endif
+
+
+#ifdef YY_USE_PROTOS
+static void *yy_flex_alloc( yy_size_t size )
+#else
+static void *yy_flex_alloc( size )
+yy_size_t size;
+#endif
+       {
+       return (void *) malloc( size );
+       }
+
+#ifdef YY_USE_PROTOS
+static void *yy_flex_realloc( void *ptr, yy_size_t size )
+#else
+static void *yy_flex_realloc( ptr, size )
+void *ptr;
+yy_size_t size;
+#endif
+       {
+       /* The cast to (char *) in the following accommodates both
+        * implementations that use char* generic pointers, and those
+        * that use void* generic pointers.  It works with the latter
+        * because both ANSI C and C++ allow castless assignment from
+        * any pointer type to void*, and deal with argument conversions
+        * as though doing an assignment.
+        */
+       return (void *) realloc( (char *) ptr, size );
+       }
+
+#ifdef YY_USE_PROTOS
+static void yy_flex_free( void *ptr )
+#else
+static void yy_flex_free( ptr )
+void *ptr;
+#endif
+       {
+       free( ptr );
+       }
+
+#if YY_MAIN
+int main()
+       {
+       yylex();
+       return 0;
+       }
+#endif
+
+
+/* Element context stack lookup. */
+int element_context(int i)
+{
+  return (0<i && i<yy_start_stack_depth
+         ? yy_start_stack[yy_start_stack_ptr - i]
+         : 0);
+}
+
+#ifdef FLEX_DEBUG
+void print_yy_stack(char* fmt, ...)
+{
+  int i = 0; va_list ap; va_start(ap, fmt);
+  vfprintf(stderr, fmt, ap);
+  for (i=1; i<yy_start_stack_ptr; i++)
+    fprintf(stderr, "%s/", statenames[yy_start_stack[i]]);
+  fprintf(stderr,"%s\n", statenames[YY_START]);
+  va_end(ap);
+}
+
+static void debug_enter(int state, char* statename) {
+  yy_push_state(state);
+  if (yy_flex_debug) print_yy_stack("--ENTER(%s) : ",statename);
+}
+
+static void debug_leave(void) {
+  if (yy_flex_debug) print_yy_stack("--LEAVE : ");
+  yy_pop_state();
+}
+
+static void debug_set(int state, char* statename) {
+  BEGIN(state);
+  if (yy_flex_debug) print_yy_stack("--SET(%s) : ",statename);
+}
+#endif
+
+
+static int fail(const char* fmt, ...)
+{
+  va_list ap; va_start(ap, fmt);
+#ifdef FLEXML_yylineno
+  fprintf(stderr, "Invalid XML (XML input line %d, state %d): ", yylineno, YY_START);
+#else
+  fprintf(stderr, "Invalid XML (state %d): ",YY_START);
+#endif
+  vfprintf(stderr, fmt, ap);
+  fprintf(stderr, "\n");
+  va_end(ap);
+  return 1;
+}
diff --git a/modules/gui/skins2/parser/gen.sh b/modules/gui/skins2/parser/gen.sh
new file mode 100755 (executable)
index 0000000..4d4851d
--- /dev/null
@@ -0,0 +1,11 @@
+flexml -SH -a skin.act skin.dtd
+
+sed -e 's/\([SE]Tag_.*\)(void)/\1(void *pContext)/' \
+    -e 's/int main().*//' skin.c > skin.c.new && mv -f skin.c.new skin.c
+sed -e 's/\([SE]Tag_.*\)(void)/\1(void*)/' \
+    -e 's/extern int yylex(void)/extern int yylex(void*)/' \
+    -e 's/\/\* XML processor entry point. \*\//#define YY_DECL int yylex(void *pContext)/' skin.h > skin.h.new && mv -f skin.h.new skin.h
+
+
+flex -oflex.c -BLs skin.l
+sed -e 's/\([SE]Tag_[^()]*\)()/\1(pContext)/g' flex.c > flex.c.new && mv -f flex.c.new flex.c 
diff --git a/modules/gui/skins2/parser/gen_builder.py b/modules/gui/skins2/parser/gen_builder.py
new file mode 100755 (executable)
index 0000000..98a30db
--- /dev/null
@@ -0,0 +1,100 @@
+#!/usr/bin/python
+
+# Script to generate builder_data.hpp, with the definitions given in
+# builder_data.def
+# Each line of the definition file is in the following format:
+# ClassName param1:type1 param2:type2 ...
+
+import string
+
+deffile = open("builder_data.def")
+hppfile = open("builder_data.hpp","w")
+
+hppfile.write(
+"""/*****************************************************************************
+ * builder_data.hpp
+ *****************************************************************************
+ * Copyright (C) 2003 VideoLAN
+ * $Id: gen_builder.py,v 1.1 2004/01/03 23:31:33 asmax Exp $
+ *
+ * Authors: Cyril Deguet     <asmax@via.ecp.fr>
+ *          Olivier Teulière <ipkiss@via.ecp.fr>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111, USA.
+ *****************************************************************************/
+
+//File generated by gen_builder.py
+//DO NOT EDIT BY HAND !
+
+#ifndef BUILDER_DATA_HPP
+#define BUILDER_DATA_HPP
+
+using namespace std;
+
+#include <vlc/vlc.h>
+#include <list>
+#include <map>
+#include <string>
+
+/// Structure for mapping data from XML file
+struct BuilderData
+{
+
+""")
+
+while 1:
+    line = string.strip(deffile.readline())
+    if line == "":
+        break
+    items = string.split(line, ' ')
+    name = items[0]
+    str = "    /// Type definition\n"
+    str += "    struct " + name + "\n    {\n"
+    str += "        " + name + "( "
+    constructor = ""
+    initlist = ""
+    vars = ""
+    for var in items[1:]:
+        vardef = string.split(var, ':');
+        varname = vardef[0]
+        vartype = vardef[1]
+        if vartype == "string":
+            vartype = "const string &"
+        if constructor != "":
+            constructor += ", "
+        constructor += vartype + " " + varname
+        if initlist != "":
+            initlist += ", "
+        initlist += "m_" + varname + "( " + varname + " )"
+        vartype = vardef[1]
+        if vartype == "string":
+            vartype = "const string"
+        vars += "        " + vartype + " m_" + varname + ";\n"
+    str += constructor + " ):\n" + initlist + " {}\n\n"
+    str += vars + "    };\n"
+    str += "    /// List\n"
+    str += "    list<" + name + "> m_list" + name + ";\n"
+    str += "\n"
+    hppfile.write(str)
+
+hppfile.write(
+"""
+};
+
+#endif
+""")
+
+deffile.close()
+hppfile.close()
diff --git a/modules/gui/skins2/parser/interpreter.cpp b/modules/gui/skins2/parser/interpreter.cpp
new file mode 100644 (file)
index 0000000..a3a7c70
--- /dev/null
@@ -0,0 +1,217 @@
+/*****************************************************************************
+ * interpreter.cpp
+ *****************************************************************************
+ * Copyright (C) 2003 VideoLAN
+ * $Id: interpreter.cpp,v 1.1 2004/01/03 23:31:33 asmax Exp $
+ *
+ * Authors: Cyril Deguet     <asmax@via.ecp.fr>
+ *          Olivier Teulière <ipkiss@via.ecp.fr>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111, USA.
+ *****************************************************************************/
+
+#include "interpreter.hpp"
+#include "../commands/cmd_playlist.hpp"
+#include "../commands/cmd_dialogs.hpp"
+#include "../commands/cmd_dummy.hpp"
+#include "../commands/cmd_layout.hpp"
+#include "../commands/cmd_quit.hpp"
+#include "../commands/cmd_input.hpp"
+#include "../src/theme.hpp"
+#include "../src/vlcproc.hpp"
+#include "../vars/playlist.hpp"
+#include "../vars/vlcvars.hpp"
+#include "../vars/time.hpp"
+#include "../vars/volume.hpp"
+
+
+Interpreter::Interpreter( intf_thread_t *pIntf ): SkinObject( pIntf )
+{
+}
+
+
+CmdGeneric *Interpreter::parseAction( const string &rAction, Theme *pTheme )
+{
+    // XXX should not be so hardcoded!
+    CmdGeneric *pCommand = NULL;
+    if( rAction == "none" )
+    {
+        pCommand = new CmdDummy( getIntf() );
+    }
+    else if( rAction == "dialogs.changeSkin()" )
+    {
+        pCommand = new CmdDlgChangeSkin( getIntf() );
+    }
+    else if( rAction == "dialogs.fileSimple()" )
+    {
+        pCommand = new CmdDlgFileSimple( getIntf() );
+    }
+    else if( rAction == "dialogs.file()" )
+    {
+        pCommand = new CmdDlgFile( getIntf() );
+    }
+    else if( rAction == "dialogs.disc()" )
+    {
+        pCommand = new CmdDlgDisc( getIntf() );
+    }
+    else if( rAction == "dialogs.net()" )
+    {
+        pCommand = new CmdDlgNet( getIntf() );
+    }
+    else if( rAction == "dialogs.messages()" )
+    {
+        pCommand = new CmdDlgMessages( getIntf() );
+    }
+    else if( rAction == "dialogs.prefs()" )
+    {
+        pCommand = new CmdDlgPrefs( getIntf() );
+    }
+    else if( rAction == "dialogs.fileInfo()" )
+    {
+        pCommand = new CmdDlgFileInfo( getIntf() );
+    }
+    else if( rAction == "dialogs.popup()" )
+    {
+        pCommand = new CmdDlgPopupMenu( getIntf() );
+    }
+    else if( rAction == "playlist.add()" )
+    {
+        pCommand = new CmdDlgAdd( getIntf() );
+    }
+    else if( rAction == "playlist.del()" )
+    {
+        VarList &rVar = VlcProc::instance( getIntf() )->getPlaylistVar();
+        pCommand = new CmdPlaylistDel( getIntf(), rVar );
+    }
+    else if( rAction == "playlist.next()" )
+    {
+        pCommand = new CmdPlaylistNext( getIntf() );
+    }
+    else if( rAction == "playlist.previous()" )
+    {
+        pCommand = new CmdPlaylistPrevious( getIntf() );
+    }
+    else if( rAction == "playlist.sort()" )
+    {
+        pCommand = new CmdPlaylistSort( getIntf() );
+    }
+    else if( rAction == "vlc.quit()" )
+    {
+        pCommand = new CmdQuit( getIntf() );
+    }
+    else if( rAction == "vlc.stop()" )
+    {
+        pCommand = new CmdStop( getIntf() );
+    }
+    else if( rAction == "vlc.slower()" )
+    {
+        pCommand = new CmdSlower( getIntf() );
+    }
+    else if( rAction == "vlc.faster()" )
+    {
+        pCommand = new CmdFaster( getIntf() );
+    }
+    else if( rAction.find( ".setLayout(" ) != string::npos )
+    {
+        int leftPos = rAction.find( ".setLayout(" );
+        string windowId = rAction.substr( 0, leftPos );
+        // 11 is the size of ".setLayout("
+        int rightPos = rAction.find( ")", windowId.size() + 11 );
+        string layoutId = rAction.substr( windowId.size() + 11,
+                                          rightPos - (windowId.size() + 11) );
+        // XXX check the IDs (isalpha())
+        pCommand = new CmdLayout( getIntf(), windowId, layoutId );
+    }
+
+    if( pCommand )
+    {
+        // Add the command in the pool
+        pTheme->m_commands.push_back( CmdGenericPtr( pCommand ) );
+    }
+
+    return pCommand;
+}
+
+
+VarBool *Interpreter::getVarBool( const string &rName, Theme *pTheme )
+{
+    VarBool *pVar = NULL;
+
+    if( rName == "vlc.isPlaying" )
+    {
+        pVar = &VlcProc::instance( getIntf() )->getIsPlayingVar();
+    }
+    else if( rName == "vlc.isSeekablePlaying" )
+    {
+        pVar = &VlcProc::instance( getIntf() )->getIsSeekablePlayingVar();
+    }
+    else if( rName == "vlc.isMute" )
+    {
+        pVar = &VlcProc::instance( getIntf() )->getIsMuteVar();
+    }
+    else if( rName.find( ".isVisible" ) != string::npos )
+    {
+        int leftPos = rName.find( ".isVisible" );
+        string windowId = rName.substr( 0, leftPos );
+        // XXX Need to check the IDs (isalpha())?
+        GenericWindow *pWin = pTheme->getWindowById( windowId );
+        if( pWin )
+        {
+            pVar = &pWin->getVisibleVar();
+        }
+        else
+        {
+            msg_Warn( getIntf(), "Unknown window (%s)", windowId.c_str() );
+        }
+    }
+
+    return pVar;
+}
+
+
+VarPercent *Interpreter::getVarPercent( const string &rName, Theme *pTheme )
+{
+    VarPercent *pVar = NULL;
+
+    if( rName == "time" )
+    {
+        pVar = &VlcProc::instance( getIntf() )->getTimeVar();
+    }
+    else if( rName == "volume" )
+    {
+        pVar = &VlcProc::instance( getIntf() )->getVolumeVar();
+    }
+    else if( rName == "playlist.slider" )
+    {
+        pVar = &VlcProc::instance( getIntf() )->
+                getPlaylistVar().getPositionVar();
+    }
+
+    return pVar;
+}
+
+
+VarList *Interpreter::getVarList( const string &rName, Theme *pTheme )
+{
+    VarList *pVar = NULL;
+
+    if( rName == "playlist" )
+    {
+        pVar = &VlcProc::instance( getIntf() )->getPlaylistVar();
+    }
+
+    return pVar;
+}
+
diff --git a/modules/gui/skins2/parser/interpreter.hpp b/modules/gui/skins2/parser/interpreter.hpp
new file mode 100644 (file)
index 0000000..3e247e2
--- /dev/null
@@ -0,0 +1,59 @@
+/*****************************************************************************
+ * interpreter.hpp
+ *****************************************************************************
+ * Copyright (C) 2003 VideoLAN
+ * $Id: interpreter.hpp,v 1.1 2004/01/03 23:31:33 asmax Exp $
+ *
+ * Authors: Cyril Deguet     <asmax@via.ecp.fr>
+ *          Olivier Teulière <ipkiss@via.ecp.fr>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111, USA.
+ *****************************************************************************/
+
+#ifndef INTERPRETER_HPP
+#define INTERPRETER_HPP
+
+#include "../commands/cmd_generic.hpp"
+
+class Theme;
+class VarBool;
+class VarList;
+class VarPercent;
+
+
+/// Command interpreter for scripts in the XML
+class Interpreter: public SkinObject
+{
+    public:
+        Interpreter( intf_thread_t *pIntf );
+        virtual ~Interpreter() {}
+
+        /// Parse an action tag and returns a pointer on a command
+        /// (the intepreter takes care of deleting it, don't do it
+        ///  yourself !)
+        CmdGeneric *parseAction( const string &rAction, Theme *pTheme );
+
+        /// Returns the boolean variable corresponding to the given name
+        VarBool *getVarBool( const string &rName, Theme *pTheme );
+
+
+        /// Returns the percent variable corresponding to the given name
+        VarPercent *getVarPercent( const string &rName, Theme *pTheme );
+
+        /// Returns the list variable corresponding to the given name
+        VarList *getVarList( const string &rName, Theme *pTheme );
+};
+
+#endif
diff --git a/modules/gui/skins2/parser/parser_context.hpp b/modules/gui/skins2/parser/parser_context.hpp
new file mode 100644 (file)
index 0000000..6f2e9e2
--- /dev/null
@@ -0,0 +1,58 @@
+/*****************************************************************************
+ * parser_context.hpp
+ *****************************************************************************
+ * Copyright (C) 2003 VideoLAN
+ * $Id: parser_context.hpp,v 1.1 2004/01/03 23:31:33 asmax Exp $
+ *
+ * Authors: Cyril Deguet     <asmax@via.ecp.fr>
+ *          Olivier Teulière <ipkiss@via.ecp.fr>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111, USA.
+ *****************************************************************************/
+
+#ifndef PARSER_CONTEXT_HPP
+#define PARSER_CONTEXT_HPP
+
+#include <vlc/intf.h>
+#include "builder_data.hpp"
+#include <list>
+
+
+/// Context for the FLEX parser
+class ParserContext
+{
+    public:
+        ParserContext( intf_thread_t *pIntf ):
+            m_pIntf( pIntf ), m_xOffset( 0 ), m_yOffset( 0 ) {}
+
+        intf_thread_t *m_pIntf;
+
+        /// Container for mapping data from the XML
+        BuilderData m_data;
+
+        /// Current IDs
+        string m_curWindowId;
+        string m_curLayoutId;
+        string m_curListId;
+
+        /// Current offset of the controls
+        int m_xOffset, m_yOffset;
+        list<int> m_xOffsetList, m_yOffsetList;
+
+        /// Layer of the current control in the layout
+        int m_curLayer;
+};
+
+#endif
diff --git a/modules/gui/skins2/parser/skin.act b/modules/gui/skins2/parser/skin.act
new file mode 100644 (file)
index 0000000..85056bc
--- /dev/null
@@ -0,0 +1,144 @@
+<!-- vim: set filetype=xml : -->
+
+<!DOCTYPE actions SYSTEM "flexml-act.dtd">
+<actions>
+    <top>
+        <![CDATA[
+            #include <vlc/vlc.h>
+            #include <vlc/intf.h>
+            #include "parser/wrappers.h"
+        ]]>
+    </top>
+    <start tag="Bitmap">
+        <![CDATA[
+            AddBitmap( pContext, {id}, {file}, {alphacolor} );
+        ]]>
+    </start>
+    <start tag="Event">
+        <![CDATA[
+            AddEvent( pContext, {id}, {event}, {key} );
+        ]]>
+    </start>
+    <start tag="Font">
+        <![CDATA[
+            AddFont( pContext, {id}, {font}, {size}, {color},
+                     {italic}, {underline} );
+        ]]>
+    </start>
+    <start tag="ThemeInfo">
+        <![CDATA[
+            AddThemeInfo( pContext, {name}, {author}, {email}, {webpage} );
+        ]]>
+    </start>
+    <start tag="Window">
+        <![CDATA[
+            StartWindow( pContext, {id}, {x}, {y}, {visible}, {dragdrop},
+                         {playondrop} );
+        ]]>
+    </start>
+    <end tag="Window">
+        <![CDATA[
+            EndWindow( pContext );
+        ]]>
+    </end>
+    <start tag="Layout">
+        <![CDATA[
+            StartLayout( pContext, {id}, {width}, {height}, {minwidth},
+                         {maxwidth}, {minheight}, {maxheight} );
+        ]]>
+    </start>
+    <end tag="Layout">
+        <![CDATA[
+            EndLayout( pContext );
+        ]]>
+    </end>
+
+    <start tag="Group">
+        <![CDATA[
+            StartGroup( pContext, {x}, {y} );
+        ]]>
+    </start>
+    <end tag="Group">
+        <![CDATA[
+            EndGroup( pContext );
+        ]]>
+    </end>
+    <start tag="Anchor">
+        <![CDATA[
+            AddAnchor( pContext, {x}, {y}, {range}, {priority} );
+        ]]>
+    </start>
+    <start tag="Image">
+        <![CDATA[
+            AddImage( pContext, {id}, {visible}, {x}, {y}, {lefttop},
+                      {rightbottom}, {image}, {onclick}, {help} );
+        ]]>
+    </start>
+    <start tag="Rectangle">
+        <![CDATA[
+            AddRectangle( pContext, {id}, {visible}, {x}, {y}, {w}, {h},
+                          {color}, {onclick}, {help} );
+        ]]>
+    </start>
+    <start tag="Button">
+        <![CDATA[
+            AddButton( pContext, {id}, {x}, {y}, {lefttop}, {rightbottom},
+                      {up}, {down}, {over}, {action}, {tooltiptext}, {help} );
+        ]]>
+    </start>
+    <start tag="CheckBox">
+        <![CDATA[
+            AddCheckBox( pContext, {id},
+                         {x}, {y}, {lefttop}, {rightbottom},
+                         {up1}, {down1}, {over1}, {up2}, {down2}, {over2},
+                         {state}, {action1}, {action2}, {tooltiptext1},
+                         {tooltiptext2}, {help} );
+        ]]>
+    </start>
+    <start tag="Slider">
+        <![CDATA[
+            AddSlider( pContext, {id}, {visible}, {x}, {y},
+                       {lefttop}, {rightbottom}, {up}, {down},
+                       {over}, {points}, {thickness}, {value}, {tooltiptext},
+                       {help} );
+        ]]>
+    </start>
+    <start tag="RadialSlider">
+        <![CDATA[
+            AddRadialSlider( pContext, {id}, {visible}, {x}, {y},
+                             {lefttop}, {rightbottom}, {sequence}, {nbimages},
+                             {minangle}, {maxangle}, {value}, {tooltiptext},
+                             {help} );
+        ]]>
+    </start>
+    <start tag="Text">
+        <![CDATA[
+            AddText( pContext, {id}, {visible}, {x}, {y}, {text}, {font},
+                     {align}, {width}, {display}, {scroll}, {scrollspace},
+                     {help} );
+        ]]>
+    </start>
+    <start tag="Playlist">
+        <![CDATA[
+            AddPlaylist( pContext, {id}, {visible}, {x}, {y}, {width},
+                        {height}, {lefttop}, {rightbottom}, {font}, {var},
+                        {fgcolor}, {playcolor}, {bgcolor1}, {bgcolor2},
+                        {selcolor}, {help} );
+        ]]>
+    </start>
+    <end tag="Playlist">
+        <![CDATA[
+            AddPlaylistEnd( pContext );
+        ]]>
+    </end>
+    <start tag="Theme">
+        <![CDATA[
+            StartTheme( pContext, {version}, {magnet}, {alpha}, {movealpha}, {fadetime} );
+        ]]>
+    </start>
+    <end tag="Theme">
+        <![CDATA[
+            EndTheme( pContext );
+        ]]>
+    </end>
+</actions>
diff --git a/modules/gui/skins2/parser/skin.dtd b/modules/gui/skins2/parser/skin.dtd
new file mode 100644 (file)
index 0000000..ca9197a
--- /dev/null
@@ -0,0 +1,204 @@
+<!--
+-->
+
+
+<!ELEMENT Theme (ThemeInfo,(Bitmap|Font|Window|Event)*)>
+    <!ATTLIST Theme
+        version     CDATA   "1.0"
+        magnet      CDATA   "15"
+        alpha       CDATA   "255"
+        movealpha   CDATA   "255"
+        fadetime    CDATA   "400"
+    >
+
+<!-- main elements -->
+<!ELEMENT Bitmap EMPTY>
+    <!ATTLIST Bitmap
+        id          CDATA   #REQUIRED
+        file        CDATA   #REQUIRED
+        alphacolor  CDATA   #REQUIRED
+    >
+<!ELEMENT Event EMPTY>
+    <!ATTLIST Event
+        id          CDATA   #REQUIRED
+        event       CDATA   #REQUIRED
+        key         CDATA   "none"
+    >
+<!ELEMENT Font EMPTY>
+    <!ATTLIST Font
+        id          CDATA   #REQUIRED
+        font        CDATA   "arial"
+        size        CDATA   "12"
+        color       CDATA   "#000000"
+        italic      CDATA   "false"
+        underline   CDATA   "false"
+    >
+<!ELEMENT ThemeInfo EMPTY>
+    <!ATTLIST ThemeInfo
+        name        CDATA   #IMPLIED
+        author      CDATA   #IMPLIED
+        email       CDATA   #IMPLIED
+        webpage     CDATA   #IMPLIED
+    >
+<!ELEMENT Window (Layout)+>
+    <!ATTLIST Window
+        id          CDATA   #REQUIRED
+        visible     CDATA   "true"
+        x           CDATA   "\0"
+        y           CDATA   "\0"
+        dragdrop    CDATA   "true"
+        playondrop  CDATA   "true"
+    >
+
+<!ELEMENT Layout (Group)>
+    <!ATTLIST Layout
+        id          CDATA   "none"
+        width       CDATA   #REQUIRED
+        height      CDATA   #REQUIRED
+        minwidth    CDATA   "-1"
+        maxwidth    CDATA   "-1"
+        minheight   CDATA   "-1"
+        maxheight   CDATA   "-1"
+    >
+<!ELEMENT Group (Group|Image|Button|Playlist|Slider|RadialSlider|Text|CheckBox|
+                 Rectangle|Anchor)+>
+    <!ATTLIST Group
+        x           CDATA   "\0"
+        y           CDATA   "\0"
+    >
+
+<!-- Anchors -->
+<!ELEMENT Anchor EMPTY>
+    <!ATTLIST Anchor
+        x           CDATA   "\0"
+        y           CDATA   "\0"
+        priority    CDATA   #REQUIRED
+        range       CDATA   "10"
+    >
+
+<!-- Controls -->
+<!ELEMENT Image EMPTY>
+    <!ATTLIST Image
+        id          CDATA   "none"
+        visible     CDATA   "true"
+        x           CDATA   "\0"
+        y           CDATA   "\0"
+        lefttop     CDATA   "lefttop"
+        rightbottom CDATA   "lefttop"
+        image       CDATA   #REQUIRED
+        onclick     CDATA   "none"
+        help        CDATA   "\0"
+    >
+<!ELEMENT Rectangle EMPTY>
+    <!ATTLIST Rectangle
+        id          CDATA   "none"
+        visible     CDATA   "true"
+        x           CDATA   "\0"
+        y           CDATA   "\0"
+        w           CDATA   "50"
+        h           CDATA   "50"
+        color       CDATA   "#C0C0C0"
+        onclick     CDATA   "none"
+        help        CDATA   "\0"
+    >
+<!ELEMENT Button EMPTY>
+    <!ATTLIST Button
+        id          CDATA   "none"
+        x           CDATA   "\0"
+        y           CDATA   "\0"
+        lefttop     CDATA   "lefttop"
+        rightbottom CDATA   "lefttop"
+        up          CDATA   #REQUIRED
+        down        CDATA   "none"
+        over        CDATA   "none"
+        action      CDATA   "none"
+        tooltiptext CDATA   "\0"
+        help        CDATA   "\0"
+    >
+<!ELEMENT CheckBox EMPTY>
+    <!ATTLIST CheckBox
+        id           CDATA   "none"
+        x            CDATA   "\0"
+        y            CDATA   "\0"
+        lefttop      CDATA   "lefttop"
+        rightbottom  CDATA   "lefttop"
+        up1          CDATA   #REQUIRED
+        down1        CDATA   "none"
+        over1        CDATA   "none"
+        up2          CDATA   #REQUIRED
+        down2        CDATA   "none"
+        over2        CDATA   "none"
+        state        CDATA   #REQUIRED
+        action1      CDATA   "none"
+        action2      CDATA   "none"
+        tooltiptext1 CDATA   "\0"
+        tooltiptext2 CDATA   "\0"
+        help         CDATA   "\0"
+    >
+<!ELEMENT Slider EMPTY>
+    <!ATTLIST Slider
+        id          CDATA   "none"
+        visible     CDATA   "true"
+        x           CDATA   "\0"
+        y           CDATA   "\0"
+        lefttop     CDATA   "lefttop"
+        rightbottom CDATA   "lefttop"
+        up          CDATA   #REQUIRED
+        down        CDATA   "none"
+        over        CDATA   "none"
+        points      CDATA   #REQUIRED
+        thickness   CDATA   "10"
+        value       CDATA   "none"
+        tooltiptext CDATA   "\0"
+        help        CDATA   "\0"
+    >
+<!ELEMENT RadialSlider EMPTY>
+    <!ATTLIST RadialSlider
+        id          CDATA   "none"
+        visible     CDATA   "true"
+        x           CDATA   "\0"
+        y           CDATA   "\0"
+        lefttop     CDATA   "lefttop"
+        rightbottom CDATA   "lefttop"
+        sequence    CDATA   #REQUIRED
+        nbimages    CDATA   #REQUIRED
+        minangle    CDATA   "\0"
+        maxangle    CDATA   "360"
+        value       CDATA   "none"
+        tooltiptext CDATA   "\0"
+        help        CDATA   "\0"
+    >
+<!ELEMENT Text EMPTY>
+    <!ATTLIST Text
+        id          CDATA   "none"
+        visible     CDATA   "true"
+        x           CDATA   "\0"
+        y           CDATA   "\0"
+        text        CDATA   ""
+        font        CDATA   #REQUIRED
+        align       CDATA   "left"
+        width       CDATA   "\0"
+        display     CDATA   "none"
+        scroll      CDATA   "true"
+        scrollspace CDATA   "20"
+        help        CDATA   "\0"
+    >
+<!ELEMENT Playlist Slider>
+    <!ATTLIST Playlist
+        id          CDATA   #REQUIRED
+        visible     CDATA   "true"
+        x           CDATA   "\0"
+        y           CDATA   "\0"
+        width       CDATA   "\0"
+        height      CDATA   "\0"
+        lefttop     CDATA   "lefttop"
+        rightbottom CDATA   "lefttop"
+        font        CDATA   #REQUIRED
+        var         CDATA   "playlist"
+        fgcolor     CDATA   "#000000"
+        playcolor   CDATA   "#FF0000"
+        bgcolor1    CDATA   "#FFFFFF"
+        bgcolor2    CDATA   "#FFFFFF"
+        selcolor    CDATA   "#0000FF"
+        help        CDATA   "\0"
+    >
diff --git a/modules/gui/skins2/parser/skin.h b/modules/gui/skins2/parser/skin.h
new file mode 100644 (file)
index 0000000..998f7ee
--- /dev/null
@@ -0,0 +1,496 @@
+/* XML processor/application API for skin.dtd.
+ * Generated 2004/01/03 15:23:36.
+ *
+ * This program was generated with the FleXML XML processor generator,
+ * (Id: flexml.pl,v 1.24 1999/12/13 16:18:30 krisrose Exp).
+ * Copyright © 1999 Kristoffer Rose.  All rights reserved.
+ *
+ * You can redistribute and/or modify this program provided the following
+ * two conditions hold:
+ *
+ * 1. The program is distributed WITHOUT ANY WARRANTY from the author of
+ *    FleXML; without even the implied warranty of MERCHANTABILITY or
+ *    FITNESS FOR A PARTICULAR PURPOSE.
+ *
+ * 2. The program distribution conditions do not in any way affect the
+ *    distribution conditions of the FleXML system used to generate this
+ *    file or any version of FleXML derived from that system.
+ *
+ * Notice that these are explicit rights granted to you for files
+ * generated by the FleXML system.  For your rights in connection with
+ * the FleXML system itself please consult the GNU General Public License.
+ */
+
+#ifndef _FLEXML_skin_H
+
+/* XML application entry points. */
+extern void STag_Theme(void*);
+extern void ETag_Theme(void*);
+extern void STag_Bitmap(void*);
+extern void ETag_Bitmap(void*);
+extern void STag_Event(void*);
+extern void ETag_Event(void*);
+extern void STag_Font(void*);
+extern void ETag_Font(void*);
+extern void STag_ThemeInfo(void*);
+extern void ETag_ThemeInfo(void*);
+extern void STag_Window(void*);
+extern void ETag_Window(void*);
+extern void STag_Layout(void*);
+extern void ETag_Layout(void*);
+extern void STag_Group(void*);
+extern void ETag_Group(void*);
+extern void STag_Anchor(void*);
+extern void ETag_Anchor(void*);
+extern void STag_Image(void*);
+extern void ETag_Image(void*);
+extern void STag_Rectangle(void*);
+extern void ETag_Rectangle(void*);
+extern void STag_Button(void*);
+extern void ETag_Button(void*);
+extern void STag_CheckBox(void*);
+extern void ETag_CheckBox(void*);
+extern void STag_Slider(void*);
+extern void ETag_Slider(void*);
+extern void STag_RadialSlider(void*);
+extern void ETag_RadialSlider(void*);
+extern void STag_Text(void*);
+extern void ETag_Text(void*);
+extern void STag_Playlist(void*);
+extern void ETag_Playlist(void*);
+
+/* XML application data. */
+typedef char* AT_Text_id;
+#define AU_Text_id NULL
+typedef char* AT_ThemeInfo_author;
+#define AU_ThemeInfo_author NULL
+typedef char* AT_Playlist_fgcolor;
+#define AU_Playlist_fgcolor NULL
+typedef char* AT_CheckBox_down2;
+#define AU_CheckBox_down2 NULL
+typedef char* AT_Image_lefttop;
+#define AU_Image_lefttop NULL
+typedef char* AT_Slider_visible;
+#define AU_Slider_visible NULL
+typedef char* AT_CheckBox_down1;
+#define AU_CheckBox_down1 NULL
+typedef char* AT_Image_rightbottom;
+#define AU_Image_rightbottom NULL
+typedef char* AT_Event_id;
+#define AU_Event_id NULL
+typedef char* AT_Rectangle_h;
+#define AU_Rectangle_h NULL
+typedef char* AT_Slider_lefttop;
+#define AU_Slider_lefttop NULL
+typedef char* AT_Slider_over;
+#define AU_Slider_over NULL
+typedef char* AT_Window_id;
+#define AU_Window_id NULL
+typedef char* AT_Theme_alpha;
+#define AU_Theme_alpha NULL
+typedef char* AT_Text_text;
+#define AU_Text_text NULL
+typedef char* AT_Playlist_rightbottom;
+#define AU_Playlist_rightbottom NULL
+typedef char* AT_Event_event;
+#define AU_Event_event NULL
+typedef char* AT_Slider_value;
+#define AU_Slider_value NULL
+typedef char* AT_Font_underline;
+#define AU_Font_underline NULL
+typedef char* AT_Image_onclick;
+#define AU_Image_onclick NULL
+typedef char* AT_Anchor_priority;
+#define AU_Anchor_priority NULL
+typedef char* AT_Font_italic;
+#define AU_Font_italic NULL
+typedef char* AT_Button_y;
+#define AU_Button_y NULL
+typedef char* AT_RadialSlider_sequence;
+#define AU_RadialSlider_sequence NULL
+typedef char* AT_Playlist_var;
+#define AU_Playlist_var NULL
+typedef char* AT_CheckBox_y;
+#define AU_CheckBox_y NULL
+typedef char* AT_Window_playondrop;
+#define AU_Window_playondrop NULL
+typedef char* AT_RadialSlider_minangle;
+#define AU_RadialSlider_minangle NULL
+typedef char* AT_RadialSlider_visible;
+#define AU_RadialSlider_visible NULL
+typedef char* AT_Playlist_playcolor;
+#define AU_Playlist_playcolor NULL
+typedef char* AT_Anchor_range;
+#define AU_Anchor_range NULL
+typedef char* AT_Theme_fadetime;
+#define AU_Theme_fadetime NULL
+typedef char* AT_CheckBox_x;
+#define AU_CheckBox_x NULL
+typedef char* AT_Bitmap_file;
+#define AU_Bitmap_file NULL
+typedef char* AT_Slider_down;
+#define AU_Slider_down NULL
+typedef char* AT_CheckBox_over2;
+#define AU_CheckBox_over2 NULL
+typedef char* AT_Slider_y;
+#define AU_Slider_y NULL
+typedef char* AT_Slider_id;
+#define AU_Slider_id NULL
+typedef char* AT_Window_dragdrop;
+#define AU_Window_dragdrop NULL
+typedef char* AT_Text_x;
+#define AU_Text_x NULL
+typedef char* AT_Image_y;
+#define AU_Image_y NULL
+typedef char* AT_Font_color;
+#define AU_Font_color NULL
+typedef char* AT_Slider_rightbottom;
+#define AU_Slider_rightbottom NULL
+typedef char* AT_Group_y;
+#define AU_Group_y NULL
+typedef char* AT_Text_font;
+#define AU_Text_font NULL
+typedef char* AT_Button_over;
+#define AU_Button_over NULL
+typedef char* AT_Theme_version;
+#define AU_Theme_version NULL
+typedef char* AT_Image_id;
+#define AU_Image_id NULL
+typedef char* AT_CheckBox_lefttop;
+#define AU_CheckBox_lefttop NULL
+typedef char* AT_Text_scrollspace;
+#define AU_Text_scrollspace NULL
+typedef char* AT_Button_action;
+#define AU_Button_action NULL
+typedef char* AT_Button_lefttop;
+#define AU_Button_lefttop NULL
+typedef char* AT_Button_id;
+#define AU_Button_id NULL
+typedef char* AT_Rectangle_visible;
+#define AU_Rectangle_visible NULL
+typedef char* AT_Rectangle_color;
+#define AU_Rectangle_color NULL
+typedef char* AT_Playlist_width;
+#define AU_Playlist_width NULL
+typedef char* AT_RadialSlider_maxangle;
+#define AU_RadialSlider_maxangle NULL
+typedef char* AT_Window_y;
+#define AU_Window_y NULL
+typedef char* AT_Slider_help;
+#define AU_Slider_help NULL
+typedef char* AT_Text_width;
+#define AU_Text_width NULL
+typedef char* AT_Slider_points;
+#define AU_Slider_points NULL
+typedef char* AT_CheckBox_up1;
+#define AU_CheckBox_up1 NULL
+typedef char* AT_Theme_magnet;
+#define AU_Theme_magnet NULL
+typedef char* AT_Theme_movealpha;
+#define AU_Theme_movealpha NULL
+typedef char* AT_RadialSlider_lefttop;
+#define AU_RadialSlider_lefttop NULL
+typedef char* AT_Button_up;
+#define AU_Button_up NULL
+typedef char* AT_RadialSlider_y;
+#define AU_RadialSlider_y NULL
+typedef char* AT_CheckBox_action1;
+#define AU_CheckBox_action1 NULL
+typedef char* AT_Playlist_id;
+#define AU_Playlist_id NULL
+typedef char* AT_Text_align;
+#define AU_Text_align NULL
+typedef char* AT_CheckBox_tooltiptext1;
+#define AU_CheckBox_tooltiptext1 NULL
+typedef char* AT_Group_x;
+#define AU_Group_x NULL
+typedef char* AT_Text_display;
+#define AU_Text_display NULL
+typedef char* AT_Bitmap_id;
+#define AU_Bitmap_id NULL
+typedef char* AT_Playlist_y;
+#define AU_Playlist_y NULL
+typedef char* AT_Text_scroll;
+#define AU_Text_scroll NULL
+typedef char* AT_Playlist_lefttop;
+#define AU_Playlist_lefttop NULL
+typedef char* AT_Rectangle_x;
+#define AU_Rectangle_x NULL
+typedef char* AT_Layout_minheight;
+#define AU_Layout_minheight NULL
+typedef char* AT_Button_rightbottom;
+#define AU_Button_rightbottom NULL
+typedef char* AT_Slider_thickness;
+#define AU_Slider_thickness NULL
+typedef char* AT_RadialSlider_tooltiptext;
+#define AU_RadialSlider_tooltiptext NULL
+typedef char* AT_RadialSlider_value;
+#define AU_RadialSlider_value NULL
+typedef char* AT_Text_visible;
+#define AU_Text_visible NULL
+typedef char* AT_Slider_tooltiptext;
+#define AU_Slider_tooltiptext NULL
+typedef char* AT_Rectangle_onclick;
+#define AU_Rectangle_onclick NULL
+typedef char* AT_Layout_width;
+#define AU_Layout_width NULL
+typedef char* AT_Rectangle_help;
+#define AU_Rectangle_help NULL
+typedef char* AT_CheckBox_tooltiptext2;
+#define AU_CheckBox_tooltiptext2 NULL
+typedef char* AT_Layout_maxheight;
+#define AU_Layout_maxheight NULL
+typedef char* AT_RadialSlider_help;
+#define AU_RadialSlider_help NULL
+typedef char* AT_Playlist_font;
+#define AU_Playlist_font NULL
+typedef char* AT_Rectangle_id;
+#define AU_Rectangle_id NULL
+typedef char* AT_CheckBox_help;
+#define AU_CheckBox_help NULL
+typedef char* AT_Image_help;
+#define AU_Image_help NULL
+typedef char* AT_Playlist_bgcolor1;
+#define AU_Playlist_bgcolor1 NULL
+typedef char* AT_Bitmap_alphacolor;
+#define AU_Bitmap_alphacolor NULL
+typedef char* AT_Image_image;
+#define AU_Image_image NULL
+typedef char* AT_Font_id;
+#define AU_Font_id NULL
+typedef char* AT_Button_x;
+#define AU_Button_x NULL
+typedef char* AT_CheckBox_id;
+#define AU_CheckBox_id NULL
+typedef char* AT_Layout_id;
+#define AU_Layout_id NULL
+typedef char* AT_Event_key;
+#define AU_Event_key NULL
+typedef char* AT_CheckBox_over1;
+#define AU_CheckBox_over1 NULL
+typedef char* AT_Slider_up;
+#define AU_Slider_up NULL
+typedef char* AT_Layout_minwidth;
+#define AU_Layout_minwidth NULL
+typedef char* AT_CheckBox_rightbottom;
+#define AU_CheckBox_rightbottom NULL
+typedef char* AT_Anchor_x;
+#define AU_Anchor_x NULL
+typedef char* AT_Font_font;
+#define AU_Font_font NULL
+typedef char* AT_Layout_maxwidth;
+#define AU_Layout_maxwidth NULL
+typedef char* AT_Playlist_help;
+#define AU_Playlist_help NULL
+typedef char* AT_Playlist_visible;
+#define AU_Playlist_visible NULL
+typedef char* AT_Slider_x;
+#define AU_Slider_x NULL
+typedef char* AT_CheckBox_up2;
+#define AU_CheckBox_up2 NULL
+typedef char* AT_Text_help;
+#define AU_Text_help NULL
+typedef char* AT_CheckBox_action2;
+#define AU_CheckBox_action2 NULL
+typedef char* AT_CheckBox_state;
+#define AU_CheckBox_state NULL
+typedef char* AT_Font_size;
+#define AU_Font_size NULL
+typedef char* AT_ThemeInfo_webpage;
+#define AU_ThemeInfo_webpage NULL
+typedef char* AT_RadialSlider_x;
+#define AU_RadialSlider_x NULL
+typedef char* AT_Button_tooltiptext;
+#define AU_Button_tooltiptext NULL
+typedef char* AT_Image_visible;
+#define AU_Image_visible NULL
+typedef char* AT_Window_visible;
+#define AU_Window_visible NULL
+typedef char* AT_RadialSlider_id;
+#define AU_RadialSlider_id NULL
+typedef char* AT_Anchor_y;
+#define AU_Anchor_y NULL
+typedef char* AT_RadialSlider_nbimages;
+#define AU_RadialSlider_nbimages NULL
+typedef char* AT_Playlist_bgcolor2;
+#define AU_Playlist_bgcolor2 NULL
+typedef char* AT_Playlist_x;
+#define AU_Playlist_x NULL
+typedef char* AT_ThemeInfo_email;
+#define AU_ThemeInfo_email NULL
+typedef char* AT_Window_x;
+#define AU_Window_x NULL
+typedef char* AT_Button_down;
+#define AU_Button_down NULL
+typedef char* AT_Playlist_height;
+#define AU_Playlist_height NULL
+typedef char* AT_Layout_height;
+#define AU_Layout_height NULL
+typedef char* AT_ThemeInfo_name;
+#define AU_ThemeInfo_name NULL
+typedef char* AT_Button_help;
+#define AU_Button_help NULL
+typedef char* AT_Text_y;
+#define AU_Text_y NULL
+typedef char* AT_Rectangle_w;
+#define AU_Rectangle_w NULL
+typedef char* AT_Image_x;
+#define AU_Image_x NULL
+typedef char* AT_Rectangle_y;
+#define AU_Rectangle_y NULL
+typedef char* AT_Playlist_selcolor;
+#define AU_Playlist_selcolor NULL
+typedef char* AT_RadialSlider_rightbottom;
+#define AU_RadialSlider_rightbottom NULL
+
+/* FleXML-provided data. */
+extern char* pcdata;
+extern AT_Text_id A_Text_id;
+extern AT_ThemeInfo_author A_ThemeInfo_author;
+extern AT_Playlist_fgcolor A_Playlist_fgcolor;
+extern AT_CheckBox_down2 A_CheckBox_down2;
+extern AT_Image_lefttop A_Image_lefttop;
+extern AT_Slider_visible A_Slider_visible;
+extern AT_CheckBox_down1 A_CheckBox_down1;
+extern AT_Image_rightbottom A_Image_rightbottom;
+extern AT_Event_id A_Event_id;
+extern AT_Rectangle_h A_Rectangle_h;
+extern AT_Slider_lefttop A_Slider_lefttop;
+extern AT_Slider_over A_Slider_over;
+extern AT_Window_id A_Window_id;
+extern AT_Theme_alpha A_Theme_alpha;
+extern AT_Text_text A_Text_text;
+extern AT_Playlist_rightbottom A_Playlist_rightbottom;
+extern AT_Event_event A_Event_event;
+extern AT_Slider_value A_Slider_value;
+extern AT_Font_underline A_Font_underline;
+extern AT_Image_onclick A_Image_onclick;
+extern AT_Anchor_priority A_Anchor_priority;
+extern AT_Font_italic A_Font_italic;
+extern AT_Button_y A_Button_y;
+extern AT_RadialSlider_sequence A_RadialSlider_sequence;
+extern AT_Playlist_var A_Playlist_var;
+extern AT_CheckBox_y A_CheckBox_y;
+extern AT_Window_playondrop A_Window_playondrop;
+extern AT_RadialSlider_minangle A_RadialSlider_minangle;
+extern AT_RadialSlider_visible A_RadialSlider_visible;
+extern AT_Playlist_playcolor A_Playlist_playcolor;
+extern AT_Anchor_range A_Anchor_range;
+extern AT_Theme_fadetime A_Theme_fadetime;
+extern AT_CheckBox_x A_CheckBox_x;
+extern AT_Bitmap_file A_Bitmap_file;
+extern AT_Slider_down A_Slider_down;
+extern AT_CheckBox_over2 A_CheckBox_over2;
+extern AT_Slider_y A_Slider_y;
+extern AT_Slider_id A_Slider_id;
+extern AT_Window_dragdrop A_Window_dragdrop;
+extern AT_Text_x A_Text_x;
+extern AT_Image_y A_Image_y;
+extern AT_Font_color A_Font_color;
+extern AT_Slider_rightbottom A_Slider_rightbottom;
+extern AT_Group_y A_Group_y;
+extern AT_Text_font A_Text_font;
+extern AT_Button_over A_Button_over;
+extern AT_Theme_version A_Theme_version;
+extern AT_Image_id A_Image_id;
+extern AT_CheckBox_lefttop A_CheckBox_lefttop;
+extern AT_Text_scrollspace A_Text_scrollspace;
+extern AT_Button_action A_Button_action;
+extern AT_Button_lefttop A_Button_lefttop;
+extern AT_Button_id A_Button_id;
+extern AT_Rectangle_visible A_Rectangle_visible;
+extern AT_Rectangle_color A_Rectangle_color;
+extern AT_Playlist_width A_Playlist_width;
+extern AT_RadialSlider_maxangle A_RadialSlider_maxangle;
+extern AT_Window_y A_Window_y;
+extern AT_Slider_help A_Slider_help;
+extern AT_Text_width A_Text_width;
+extern AT_Slider_points A_Slider_points;
+extern AT_CheckBox_up1 A_CheckBox_up1;
+extern AT_Theme_magnet A_Theme_magnet;
+extern AT_Theme_movealpha A_Theme_movealpha;
+extern AT_RadialSlider_lefttop A_RadialSlider_lefttop;
+extern AT_Button_up A_Button_up;
+extern AT_RadialSlider_y A_RadialSlider_y;
+extern AT_CheckBox_action1 A_CheckBox_action1;
+extern AT_Playlist_id A_Playlist_id;
+extern AT_Text_align A_Text_align;
+extern AT_CheckBox_tooltiptext1 A_CheckBox_tooltiptext1;
+extern AT_Group_x A_Group_x;
+extern AT_Text_display A_Text_display;
+extern AT_Bitmap_id A_Bitmap_id;
+extern AT_Playlist_y A_Playlist_y;
+extern AT_Text_scroll A_Text_scroll;
+extern AT_Playlist_lefttop A_Playlist_lefttop;
+extern AT_Rectangle_x A_Rectangle_x;
+extern AT_Layout_minheight A_Layout_minheight;
+extern AT_Button_rightbottom A_Button_rightbottom;
+extern AT_Slider_thickness A_Slider_thickness;
+extern AT_RadialSlider_tooltiptext A_RadialSlider_tooltiptext;
+extern AT_RadialSlider_value A_RadialSlider_value;
+extern AT_Text_visible A_Text_visible;
+extern AT_Slider_tooltiptext A_Slider_tooltiptext;
+extern AT_Rectangle_onclick A_Rectangle_onclick;
+extern AT_Layout_width A_Layout_width;
+extern AT_Rectangle_help A_Rectangle_help;
+extern AT_CheckBox_tooltiptext2 A_CheckBox_tooltiptext2;
+extern AT_Layout_maxheight A_Layout_maxheight;
+extern AT_RadialSlider_help A_RadialSlider_help;
+extern AT_Playlist_font A_Playlist_font;
+extern AT_Rectangle_id A_Rectangle_id;
+extern AT_CheckBox_help A_CheckBox_help;
+extern AT_Image_help A_Image_help;
+extern AT_Playlist_bgcolor1 A_Playlist_bgcolor1;
+extern AT_Bitmap_alphacolor A_Bitmap_alphacolor;
+extern AT_Image_image A_Image_image;
+extern AT_Font_id A_Font_id;
+extern AT_Button_x A_Button_x;
+extern AT_CheckBox_id A_CheckBox_id;
+extern AT_Layout_id A_Layout_id;
+extern AT_Event_key A_Event_key;
+extern AT_CheckBox_over1 A_CheckBox_over1;
+extern AT_Slider_up A_Slider_up;
+extern AT_Layout_minwidth A_Layout_minwidth;
+extern AT_CheckBox_rightbottom A_CheckBox_rightbottom;
+extern AT_Anchor_x A_Anchor_x;
+extern AT_Font_font A_Font_font;
+extern AT_Layout_maxwidth A_Layout_maxwidth;
+extern AT_Playlist_help A_Playlist_help;
+extern AT_Playlist_visible A_Playlist_visible;
+extern AT_Slider_x A_Slider_x;
+extern AT_CheckBox_up2 A_CheckBox_up2;
+extern AT_Text_help A_Text_help;
+extern AT_CheckBox_action2 A_CheckBox_action2;
+extern AT_CheckBox_state A_CheckBox_state;
+extern AT_Font_size A_Font_size;
+extern AT_ThemeInfo_webpage A_ThemeInfo_webpage;
+extern AT_RadialSlider_x A_RadialSlider_x;
+extern AT_Button_tooltiptext A_Button_tooltiptext;
+extern AT_Image_visible A_Image_visible;
+extern AT_Window_visible A_Window_visible;
+extern AT_RadialSlider_id A_RadialSlider_id;
+extern AT_Anchor_y A_Anchor_y;
+extern AT_RadialSlider_nbimages A_RadialSlider_nbimages;
+extern AT_Playlist_bgcolor2 A_Playlist_bgcolor2;
+extern AT_Playlist_x A_Playlist_x;
+extern AT_ThemeInfo_email A_ThemeInfo_email;
+extern AT_Window_x A_Window_x;
+extern AT_Button_down A_Button_down;
+extern AT_Playlist_height A_Playlist_height;
+extern AT_Layout_height A_Layout_height;
+extern AT_ThemeInfo_name A_ThemeInfo_name;
+extern AT_Button_help A_Button_help;
+extern AT_Text_y A_Text_y;
+extern AT_Rectangle_w A_Rectangle_w;
+extern AT_Image_x A_Image_x;
+extern AT_Rectangle_y A_Rectangle_y;
+extern AT_Playlist_selcolor A_Playlist_selcolor;
+extern AT_RadialSlider_rightbottom A_RadialSlider_rightbottom;
+
+/* XML application utilities. */
+extern int element_context(int);
+
+#define YY_DECL int yylex(void *pContext)
+extern int yylex(void*);
+
+#endif
diff --git a/modules/gui/skins2/parser/skin.l b/modules/gui/skins2/parser/skin.l
new file mode 100644 (file)
index 0000000..9eb494d
--- /dev/null
@@ -0,0 +1,1919 @@
+/* Validating XML processor for skin.dtd.
+ * Generated 2004/01/03 15:23:36.
+ *
+ * This program was generated with the FleXML XML processor generator,
+ * (Id: flexml.pl,v 1.24 1999/12/13 16:18:30 krisrose Exp).
+ * Copyright © 1999 Kristoffer Rose.  All rights reserved.
+ *
+ * You can redistribute and/or modify this program provided the following
+ * two conditions hold:
+ *
+ * 1. The program is distributed WITHOUT ANY WARRANTY from the author of
+ *    FleXML; without even the implied warranty of MERCHANTABILITY or
+ *    FITNESS FOR A PARTICULAR PURPOSE.
+ *
+ * 2. The program distribution conditions do not in any way affect the
+ *    distribution conditions of the FleXML system used to generate this
+ *    file or any version of FleXML derived from that system.
+ *
+ * Notice that these are explicit rights granted to you for files
+ * generated by the FleXML system.  For your rights in connection with
+ * the FleXML system itself please consult the GNU General Public License.
+ */
+
+%{
+
+/* Version strings. */
+const char rcs_flexml_skeleton[] =
+ "$" "Id: skel,v 1.16 1999/12/09 04:01:51 krisrose Exp $";
+const char rcs_flexml[] =
+ "$" "Id: flexml.pl,v 1.24 1999/12/13 16:18:30 krisrose Exp $";
+
+/* ANSI headers. */
+#include <unistd.h>
+#include <stdio.h>
+#include <string.h>
+#include <assert.h>
+#include <stdarg.h>
+#include <ctype.h>
+
+/* Generated definitions. */
+#define FLEXML_BUFFERSTACKSIZE 100000
+
+/* XML processor api. */
+#include "skin.h"
+
+/* FleXML-provided data. */
+char* pcdata;
+AT_Text_id A_Text_id;
+AT_ThemeInfo_author A_ThemeInfo_author;
+AT_Playlist_fgcolor A_Playlist_fgcolor;
+AT_CheckBox_down2 A_CheckBox_down2;
+AT_Image_lefttop A_Image_lefttop;
+AT_Slider_visible A_Slider_visible;
+AT_CheckBox_down1 A_CheckBox_down1;
+AT_Image_rightbottom A_Image_rightbottom;
+AT_Event_id A_Event_id;
+AT_Rectangle_h A_Rectangle_h;
+AT_Slider_lefttop A_Slider_lefttop;
+AT_Slider_over A_Slider_over;
+AT_Window_id A_Window_id;
+AT_Theme_alpha A_Theme_alpha;
+AT_Text_text A_Text_text;
+AT_Playlist_rightbottom A_Playlist_rightbottom;
+AT_Event_event A_Event_event;
+AT_Slider_value A_Slider_value;
+AT_Font_underline A_Font_underline;
+AT_Image_onclick A_Image_onclick;
+AT_Anchor_priority A_Anchor_priority;
+AT_Font_italic A_Font_italic;
+AT_Button_y A_Button_y;
+AT_RadialSlider_sequence A_RadialSlider_sequence;
+AT_Playlist_var A_Playlist_var;
+AT_CheckBox_y A_CheckBox_y;
+AT_Window_playondrop A_Window_playondrop;
+AT_RadialSlider_minangle A_RadialSlider_minangle;
+AT_RadialSlider_visible A_RadialSlider_visible;
+AT_Playlist_playcolor A_Playlist_playcolor;
+AT_Anchor_range A_Anchor_range;
+AT_Theme_fadetime A_Theme_fadetime;
+AT_CheckBox_x A_CheckBox_x;
+AT_Bitmap_file A_Bitmap_file;
+AT_Slider_down A_Slider_down;
+AT_CheckBox_over2 A_CheckBox_over2;
+AT_Slider_y A_Slider_y;
+AT_Slider_id A_Slider_id;
+AT_Window_dragdrop A_Window_dragdrop;
+AT_Text_x A_Text_x;
+AT_Image_y A_Image_y;
+AT_Font_color A_Font_color;
+AT_Slider_rightbottom A_Slider_rightbottom;
+AT_Group_y A_Group_y;
+AT_Text_font A_Text_font;
+AT_Button_over A_Button_over;
+AT_Theme_version A_Theme_version;
+AT_Image_id A_Image_id;
+AT_CheckBox_lefttop A_CheckBox_lefttop;
+AT_Text_scrollspace A_Text_scrollspace;
+AT_Button_action A_Button_action;
+AT_Button_lefttop A_Button_lefttop;
+AT_Button_id A_Button_id;
+AT_Rectangle_visible A_Rectangle_visible;
+AT_Rectangle_color A_Rectangle_color;
+AT_Playlist_width A_Playlist_width;
+AT_RadialSlider_maxangle A_RadialSlider_maxangle;
+AT_Window_y A_Window_y;
+AT_Slider_help A_Slider_help;
+AT_Text_width A_Text_width;
+AT_Slider_points A_Slider_points;
+AT_CheckBox_up1 A_CheckBox_up1;
+AT_Theme_magnet A_Theme_magnet;
+AT_Theme_movealpha A_Theme_movealpha;
+AT_RadialSlider_lefttop A_RadialSlider_lefttop;
+AT_Button_up A_Button_up;
+AT_RadialSlider_y A_RadialSlider_y;
+AT_CheckBox_action1 A_CheckBox_action1;
+AT_Playlist_id A_Playlist_id;
+AT_Text_align A_Text_align;
+AT_CheckBox_tooltiptext1 A_CheckBox_tooltiptext1;
+AT_Group_x A_Group_x;
+AT_Text_display A_Text_display;
+AT_Bitmap_id A_Bitmap_id;
+AT_Playlist_y A_Playlist_y;
+AT_Text_scroll A_Text_scroll;
+AT_Playlist_lefttop A_Playlist_lefttop;
+AT_Rectangle_x A_Rectangle_x;
+AT_Layout_minheight A_Layout_minheight;
+AT_Button_rightbottom A_Button_rightbottom;
+AT_Slider_thickness A_Slider_thickness;
+AT_RadialSlider_tooltiptext A_RadialSlider_tooltiptext;
+AT_RadialSlider_value A_RadialSlider_value;
+AT_Text_visible A_Text_visible;
+AT_Slider_tooltiptext A_Slider_tooltiptext;
+AT_Rectangle_onclick A_Rectangle_onclick;
+AT_Layout_width A_Layout_width;
+AT_Rectangle_help A_Rectangle_help;
+AT_CheckBox_tooltiptext2 A_CheckBox_tooltiptext2;
+AT_Layout_maxheight A_Layout_maxheight;
+AT_RadialSlider_help A_RadialSlider_help;
+AT_Playlist_font A_Playlist_font;
+AT_Rectangle_id A_Rectangle_id;
+AT_CheckBox_help A_CheckBox_help;
+AT_Image_help A_Image_help;
+AT_Playlist_bgcolor1 A_Playlist_bgcolor1;
+AT_Bitmap_alphacolor A_Bitmap_alphacolor;
+AT_Image_image A_Image_image;
+AT_Font_id A_Font_id;
+AT_Button_x A_Button_x;
+AT_CheckBox_id A_CheckBox_id;
+AT_Layout_id A_Layout_id;
+AT_Event_key A_Event_key;
+AT_CheckBox_over1 A_CheckBox_over1;
+AT_Slider_up A_Slider_up;
+AT_Layout_minwidth A_Layout_minwidth;
+AT_CheckBox_rightbottom A_CheckBox_rightbottom;
+AT_Anchor_x A_Anchor_x;
+AT_Font_font A_Font_font;
+AT_Layout_maxwidth A_Layout_maxwidth;
+AT_Playlist_help A_Playlist_help;
+AT_Playlist_visible A_Playlist_visible;
+AT_Slider_x A_Slider_x;
+AT_CheckBox_up2 A_CheckBox_up2;
+AT_Text_help A_Text_help;
+AT_CheckBox_action2 A_CheckBox_action2;
+AT_CheckBox_state A_CheckBox_state;
+AT_Font_size A_Font_size;
+AT_ThemeInfo_webpage A_ThemeInfo_webpage;
+AT_RadialSlider_x A_RadialSlider_x;
+AT_Button_tooltiptext A_Button_tooltiptext;
+AT_Image_visible A_Image_visible;
+AT_Window_visible A_Window_visible;
+AT_RadialSlider_id A_RadialSlider_id;
+AT_Anchor_y A_Anchor_y;
+AT_RadialSlider_nbimages A_RadialSlider_nbimages;
+AT_Playlist_bgcolor2 A_Playlist_bgcolor2;
+AT_Playlist_x A_Playlist_x;
+AT_ThemeInfo_email A_ThemeInfo_email;
+AT_Window_x A_Window_x;
+AT_Button_down A_Button_down;
+AT_Playlist_height A_Playlist_height;
+AT_Layout_height A_Layout_height;
+AT_ThemeInfo_name A_ThemeInfo_name;
+AT_Button_help A_Button_help;
+AT_Text_y A_Text_y;
+AT_Rectangle_w A_Rectangle_w;
+AT_Image_x A_Image_x;
+AT_Rectangle_y A_Rectangle_y;
+AT_Playlist_selcolor A_Playlist_selcolor;
+AT_RadialSlider_rightbottom A_RadialSlider_rightbottom;
+
+/* XML state. */
+#ifdef FLEX_DEBUG
+# define ENTER(state)  debug_enter(state,#state)
+# define LEAVE         debug_leave()
+# define SET(state)    debug_set(state,#state)
+  static void debug_enter(int, char*);
+  static void debug_leave(void);
+  static void debug_set(int, char*);
+#else
+# define ENTER(state)  (yy_push_state(state))
+# define LEAVE         (yy_pop_state())
+# define SET(state)    BEGIN(state)
+#endif
+
+/* Generic actions. */
+#define SKIP   /*skip*/
+#define SUCCEED        return 0
+
+#define FAIL   return fail
+static int fail(const char*, ...);
+
+/* Text buffer stack handling. */
+char bufferstack[FLEXML_BUFFERSTACKSIZE];
+char* limit = bufferstack + FLEXML_BUFFERSTACKSIZE;
+typedef struct BufferLast_s {
+  struct BufferLast_s *old; char* saved; char new[1];
+} BufferLast;
+BufferLast* last = (BufferLast*)0;
+char* next = bufferstack;
+
+#define BUFFERSET(P)  (P = next)
+#define BUFFERPUTC(C) (assert(next<limit), *(next++) = (C))
+#define BUFFERDONE    (BUFFERPUTC('\0'))
+
+#define BUFFERLITERAL(C,P) bufferliteral(C,&(P),yytext)
+static void bufferliteral(char c, char** pp, char* text)
+{
+  char *s = strchr(text,c), *e = strrchr(text,c);
+  assert(s <= e); BUFFERSET(*pp);
+  while (++s<e) {
+    if (isspace(*s)) { BUFFERPUTC(' '); while (isspace(*s)) ++s; }
+    else BUFFERPUTC(*s);
+  } 
+  BUFFERDONE;
+}
+
+#ifdef FLEXML_HasMixed
+static void pushbuffer(char* p)
+{
+  BufferLast* l = (BufferLast*)next;
+  assert(next < limit);
+  l->old = last;
+  l->saved = p;
+  next = l->new;
+  last = l;
+}
+
+static char* popbuffer(void)
+{
+  BufferLast* l = last;
+  assert(last != (BufferLast*)0);
+  last = l->old;
+  next = (char*)l;
+  return l->saved;
+}
+#endif
+
+/* General internal entities are `unput' back onto the input stream... */
+#define ENTITYTEXT(T) \
+  { char *s = (T), *e = s+strlen(s);\
+    while (--e >= s) { unput(*e); }}
+%}
+
+/* Flex standard options. */
+%option stack
+%option noyy_top_state
+%option noinput
+%option noreject
+%option noyymore
+%option noyywrap
+
+/* Flex user-requested options. */
+%option nounput
+
+/* XML character classes (currently restricted to ASCII). */
+
+/* "Common syntactic structures." */
+S              [ \t\n\r\f]+
+s              [ \t\n\r\f]*
+
+/* "Names and Tokens." */
+NameChar       [A-Za-z0-9.:_-]
+Name           [A-Za-z_:]{NameChar}*
+Names          {Name}({S}{Name})*
+Nmtoken                ({NameChar})+
+Nmtokens       {Nmtoken}({S}{Nmtoken})*
+
+/* Miscellaneous. */
+VersionNum     [a-zA-Z0-9_.:-]+
+Eq             {s}"="{s}
+Literal                \'[^'']*\'|\"[^""]*\"
+
+/* Parser states (flex `exclusive start conditions'):
+ *
+ * PROLOG      the XML prolog of the document before <?xml...>
+ * DOCTYPE     the XML prolog of the document after <?xml...>
+ * EPILOG      after the root element
+ * INCOMMENT   inside an XML comment <!--....-->
+ * INPI                inside an XML PI <?...?>
+ * VALUE1      inside a '...'-delimited literal
+ * VALUE2      inside a "..."-delimited literal
+ * CDATA       inside a <![CDATA[...]]> section.
+ * ROOT_<tag>  expect root element <tag>
+ * AL_<tag>    inside the attribute list for <tag>
+ * IN_<tag>    inside a <tag> with element contents (ready for end tag)
+ * IMPOSSIBLE  dummy to permit disabling rules; must be last
+ */
+%x PROLOG DOCTYPE EPILOG INCOMMENT INPI VALUE1 VALUE2 CDATA
+%x ROOT_Theme AL_Theme S_Theme S_Theme_1 S_Theme_2 S_Theme_3 E_Theme
+%x ROOT_Bitmap AL_Bitmap E_Bitmap
+%x ROOT_Event AL_Event E_Event
+%x ROOT_Font AL_Font E_Font
+%x ROOT_ThemeInfo AL_ThemeInfo E_ThemeInfo
+%x ROOT_Window AL_Window S_Window S_Window_1 S_Window_2 E_Window
+%x ROOT_Layout AL_Layout S_Layout E_Layout
+%x ROOT_Group AL_Group S_Group S_Group_1 S_Group_2 E_Group
+%x ROOT_Anchor AL_Anchor E_Anchor
+%x ROOT_Image AL_Image E_Image
+%x ROOT_Rectangle AL_Rectangle E_Rectangle
+%x ROOT_Button AL_Button E_Button
+%x ROOT_CheckBox AL_CheckBox E_CheckBox
+%x ROOT_Slider AL_Slider E_Slider
+%x ROOT_RadialSlider AL_RadialSlider E_RadialSlider
+%x ROOT_Text AL_Text E_Text
+%x ROOT_Playlist AL_Playlist S_Playlist E_Playlist
+%x IMPOSSIBLE
+
+%{
+/* State names. */
+char* statenames[IMPOSSIBLE];
+
+void FleXML_init(void)
+{
+  statenames[PROLOG] = NULL;
+  statenames[DOCTYPE] = NULL;
+  statenames[EPILOG] = NULL;
+  statenames[INCOMMENT] = NULL;
+  statenames[INPI] = NULL;
+  statenames[VALUE1] = NULL;
+  statenames[VALUE2] = NULL;
+  statenames[CDATA] = NULL;
+  statenames[ROOT_Theme] = NULL;
+  statenames[AL_Theme] = NULL;
+  statenames[S_Theme] = "Theme";
+  statenames[S_Theme_1] = "Theme";
+  statenames[S_Theme_2] = "Theme";
+  statenames[S_Theme_3] = "Theme";
+  statenames[E_Theme] = "Theme";
+  statenames[ROOT_Bitmap] = NULL;
+  statenames[AL_Bitmap] = NULL;
+  statenames[E_Bitmap] = "Bitmap";
+  statenames[ROOT_Event] = NULL;
+  statenames[AL_Event] = NULL;
+  statenames[E_Event] = "Event";
+  statenames[ROOT_Font] = NULL;
+  statenames[AL_Font] = NULL;
+  statenames[E_Font] = "Font";
+  statenames[ROOT_ThemeInfo] = NULL;
+  statenames[AL_ThemeInfo] = NULL;
+  statenames[E_ThemeInfo] = "ThemeInfo";
+  statenames[ROOT_Window] = NULL;
+  statenames[AL_Window] = NULL;
+  statenames[S_Window] = "Window";
+  statenames[S_Window_1] = "Window";
+  statenames[S_Window_2] = "Window";
+  statenames[E_Window] = "Window";
+  statenames[ROOT_Layout] = NULL;
+  statenames[AL_Layout] = NULL;
+  statenames[S_Layout] = "Layout";
+  statenames[E_Layout] = "Layout";
+  statenames[ROOT_Group] = NULL;
+  statenames[AL_Group] = NULL;
+  statenames[S_Group] = "Group";
+  statenames[S_Group_1] = "Group";
+  statenames[S_Group_2] = "Group";
+  statenames[E_Group] = "Group";
+  statenames[ROOT_Anchor] = NULL;
+  statenames[AL_Anchor] = NULL;
+  statenames[E_Anchor] = "Anchor";
+  statenames[ROOT_Image] = NULL;
+  statenames[AL_Image] = NULL;
+  statenames[E_Image] = "Image";
+  statenames[ROOT_Rectangle] = NULL;
+  statenames[AL_Rectangle] = NULL;
+  statenames[E_Rectangle] = "Rectangle";
+  statenames[ROOT_Button] = NULL;
+  statenames[AL_Button] = NULL;
+  statenames[E_Button] = "Button";
+  statenames[ROOT_CheckBox] = NULL;
+  statenames[AL_CheckBox] = NULL;
+  statenames[E_CheckBox] = "CheckBox";
+  statenames[ROOT_Slider] = NULL;
+  statenames[AL_Slider] = NULL;
+  statenames[E_Slider] = "Slider";
+  statenames[ROOT_RadialSlider] = NULL;
+  statenames[AL_RadialSlider] = NULL;
+  statenames[E_RadialSlider] = "RadialSlider";
+  statenames[ROOT_Text] = NULL;
+  statenames[AL_Text] = NULL;
+  statenames[E_Text] = "Text";
+  statenames[ROOT_Playlist] = NULL;
+  statenames[AL_Playlist] = NULL;
+  statenames[S_Playlist] = "Playlist";
+  statenames[E_Playlist] = "Playlist";
+}
+%}
+
+%%
+
+ /* Bypass Flex's default INITIAL state and begin by parsing the XML prolog. */
+ SET(PROLOG); FleXML_init();
+
+ /* COMMENTS and PIs: handled uniformly for efficiency. */
+
+<ROOT_Theme,AL_Theme,S_Theme,S_Theme_1,S_Theme_2,S_Theme_3,E_Theme,ROOT_Bitmap,AL_Bitmap,E_Bitmap,ROOT_Event,AL_Event,E_Event,ROOT_Font,AL_Font,E_Font,ROOT_ThemeInfo,AL_ThemeInfo,E_ThemeInfo,ROOT_Window,AL_Window,S_Window,S_Window_1,S_Window_2,E_Window,ROOT_Layout,AL_Layout,S_Layout,E_Layout,ROOT_Group,AL_Group,S_Group,S_Group_1,S_Group_2,E_Group,ROOT_Anchor,AL_Anchor,E_Anchor,ROOT_Image,AL_Image,E_Image,ROOT_Rectangle,AL_Rectangle,E_Rectangle,ROOT_Button,AL_Button,E_Button,ROOT_CheckBox,AL_CheckBox,E_CheckBox,ROOT_Slider,AL_Slider,E_Slider,ROOT_RadialSlider,AL_RadialSlider,E_RadialSlider,ROOT_Text,AL_Text,E_Text,ROOT_Playlist,AL_Playlist,S_Playlist,E_Playlist,PROLOG,DOCTYPE,EPILOG>{
+ "<!--" ENTER(INCOMMENT);
+ "<?" ENTER(INPI);
+}
+<INCOMMENT>{
+ "-->"         LEAVE;
+ "--"          |
+ .             |
+ \n            SKIP;
+ <<EOF>>       FAIL("EOF in comment.");
+}
+<INPI>{
+ "?>"          LEAVE;
+ .             |
+ \n            SKIP;
+ <<EOF>>       FAIL("EOF in PI (processing instruction).");
+}
+
+ /* SPACES: skipped uniformly */
+
+<ROOT_Theme,AL_Theme,S_Theme,S_Theme_1,S_Theme_2,S_Theme_3,E_Theme,ROOT_Bitmap,AL_Bitmap,E_Bitmap,ROOT_Event,AL_Event,E_Event,ROOT_Font,AL_Font,E_Font,ROOT_ThemeInfo,AL_ThemeInfo,E_ThemeInfo,ROOT_Window,AL_Window,S_Window,S_Window_1,S_Window_2,E_Window,ROOT_Layout,AL_Layout,S_Layout,E_Layout,ROOT_Group,AL_Group,S_Group,S_Group_1,S_Group_2,E_Group,ROOT_Anchor,AL_Anchor,E_Anchor,ROOT_Image,AL_Image,E_Image,ROOT_Rectangle,AL_Rectangle,E_Rectangle,ROOT_Button,AL_Button,E_Button,ROOT_CheckBox,AL_CheckBox,E_CheckBox,ROOT_Slider,AL_Slider,E_Slider,ROOT_RadialSlider,AL_RadialSlider,E_RadialSlider,ROOT_Text,AL_Text,E_Text,ROOT_Playlist,AL_Playlist,S_Playlist,E_Playlist,PROLOG,DOCTYPE,EPILOG>{S} SKIP;
+
+ /* PROLOG: determine root element and process it. */
+
+<PROLOG>{
+ "<?xml"({S}version{Eq}(\'{VersionNum}\'|\"{VersionNum}\"))?"?>" SET(DOCTYPE);
+ "<?xml"[^>]*">" FAIL("Bad declaration %s.",yytext);
+}
+
+<PROLOG,DOCTYPE>{
+ "<!DOCTYPE"{S}"Layout"{S}SYSTEM{S}("'skin.dtd'"|"\"skin.dtd\""){s}">" SET(ROOT_Layout);
+ "<!DOCTYPE"{S}"Event"{S}SYSTEM{S}("'skin.dtd'"|"\"skin.dtd\""){s}">" SET(ROOT_Event);
+ "<!DOCTYPE"{S}"Image"{S}SYSTEM{S}("'skin.dtd'"|"\"skin.dtd\""){s}">" SET(ROOT_Image);
+ "<!DOCTYPE"{S}"Playlist"{S}SYSTEM{S}("'skin.dtd'"|"\"skin.dtd\""){s}">" SET(ROOT_Playlist);
+ "<!DOCTYPE"{S}"Text"{S}SYSTEM{S}("'skin.dtd'"|"\"skin.dtd\""){s}">" SET(ROOT_Text);
+ "<!DOCTYPE"{S}"Rectangle"{S}SYSTEM{S}("'skin.dtd'"|"\"skin.dtd\""){s}">" SET(ROOT_Rectangle);
+ "<!DOCTYPE"{S}"Anchor"{S}SYSTEM{S}("'skin.dtd'"|"\"skin.dtd\""){s}">" SET(ROOT_Anchor);
+ "<!DOCTYPE"{S}"Group"{S}SYSTEM{S}("'skin.dtd'"|"\"skin.dtd\""){s}">" SET(ROOT_Group);
+ "<!DOCTYPE"{S}"Theme"{S}SYSTEM{S}("'skin.dtd'"|"\"skin.dtd\""){s}">" SET(ROOT_Theme);
+ "<!DOCTYPE"{S}"Font"{S}SYSTEM{S}("'skin.dtd'"|"\"skin.dtd\""){s}">" SET(ROOT_Font);
+ "<!DOCTYPE"{S}"RadialSlider"{S}SYSTEM{S}("'skin.dtd'"|"\"skin.dtd\""){s}">" SET(ROOT_RadialSlider);
+ "<!DOCTYPE"{S}"ThemeInfo"{S}SYSTEM{S}("'skin.dtd'"|"\"skin.dtd\""){s}">" SET(ROOT_ThemeInfo);
+ "<!DOCTYPE"{S}"Slider"{S}SYSTEM{S}("'skin.dtd'"|"\"skin.dtd\""){s}">" SET(ROOT_Slider);
+ "<!DOCTYPE"{S}"CheckBox"{S}SYSTEM{S}("'skin.dtd'"|"\"skin.dtd\""){s}">" SET(ROOT_CheckBox);
+ "<!DOCTYPE"{S}"Button"{S}SYSTEM{S}("'skin.dtd'"|"\"skin.dtd\""){s}">" SET(ROOT_Button);
+ "<!DOCTYPE"{S}"Bitmap"{S}SYSTEM{S}("'skin.dtd'"|"\"skin.dtd\""){s}">" SET(ROOT_Bitmap);
+ "<!DOCTYPE"{S}"Window"{S}SYSTEM{S}("'skin.dtd'"|"\"skin.dtd\""){s}">" SET(ROOT_Window);
+ "<!"[^>-][^>]*">" FAIL("Bad declaration %s.",yytext);
+ .             FAIL("Unexpected character `%c' in prolog.", yytext[0]);
+ <<EOF>>       FAIL("EOF in prolog.");
+}
+
+ /* RULES DERIVED FROM DTD. */
+
+ /* <!--
+  * -->  */
+
+ /*         version     CDATA   "1.0"
+  *         magnet      CDATA   "15"
+  *         alpha       CDATA   "255"
+  *         movealpha   CDATA   "255"
+  *         fadetime    CDATA   "400"
+  *     >  */
+
+<ROOT_Theme>"<Theme"{s} {
+  A_Theme_version = "1.0";
+  A_Theme_magnet = "15";
+  A_Theme_alpha = "255";
+  A_Theme_movealpha = "255";
+  A_Theme_fadetime = "400";
+  ENTER(AL_Theme);
+}
+
+<AL_Theme>{
+ "version"{Eq}\' ENTER(VALUE1); BUFFERSET(A_Theme_version);
+ "version"{Eq}\" ENTER(VALUE2); BUFFERSET(A_Theme_version);
+
+ "magnet"{Eq}\' ENTER(VALUE1); BUFFERSET(A_Theme_magnet);
+ "magnet"{Eq}\" ENTER(VALUE2); BUFFERSET(A_Theme_magnet);
+
+ "alpha"{Eq}\' ENTER(VALUE1); BUFFERSET(A_Theme_alpha);
+ "alpha"{Eq}\" ENTER(VALUE2); BUFFERSET(A_Theme_alpha);
+
+ "movealpha"{Eq}\' ENTER(VALUE1); BUFFERSET(A_Theme_movealpha);
+ "movealpha"{Eq}\" ENTER(VALUE2); BUFFERSET(A_Theme_movealpha);
+
+ "fadetime"{Eq}\' ENTER(VALUE1); BUFFERSET(A_Theme_fadetime);
+ "fadetime"{Eq}\" ENTER(VALUE2); BUFFERSET(A_Theme_fadetime);
+
+ ">" {
+  LEAVE; STag_Theme(); pcdata = NULL; ENTER(S_Theme);
+ }
+ "/>" FAIL("`Theme' element cannot be empty.");
+ .       FAIL("Unexpected character `%c' in attribute list of Theme element.", yytext[0]);
+ {Name} FAIL("Bad attribute `%s' in `Theme' element start tag.",yytext);
+ <<EOF>> FAIL("EOF in attribute list of `Theme' element.");
+}
+
+<E_Theme,S_Theme_1,S_Theme_3>{
+ "</Theme"{s}">" {
+  LEAVE;
+  ETag_Theme();
+  switch (YY_START) {
+   case ROOT_Theme: SET(EPILOG); break;
+  }
+ }
+ "</"{Name}{s}">" FAIL("Unexpected end-tag `%s': `</Theme>' expected.",yytext);
+ .       FAIL("Unexpected character `%c': `</Theme>' expected.",yytext[0]);
+ <<EOF>> FAIL("Premature EOF: `</Theme>' expected.");
+}
+
+ /* <!-- main elements -->  */
+
+ /*         id          CDATA   #REQUIRED
+  *         file        CDATA   #REQUIRED
+  *         alphacolor  CDATA   #REQUIRED
+  *     >  */
+
+<ROOT_Bitmap,S_Theme_2,S_Theme_1,S_Theme_3>"<Bitmap"{s} {
+  A_Bitmap_id = NULL;
+  A_Bitmap_file = NULL;
+  A_Bitmap_alphacolor = NULL;
+  ENTER(AL_Bitmap);
+}
+
+<AL_Bitmap>{
+ "id"{Eq}\' ENTER(VALUE1); BUFFERSET(A_Bitmap_id);
+ "id"{Eq}\" ENTER(VALUE2); BUFFERSET(A_Bitmap_id);
+
+ "file"{Eq}\' ENTER(VALUE1); BUFFERSET(A_Bitmap_file);
+ "file"{Eq}\" ENTER(VALUE2); BUFFERSET(A_Bitmap_file);
+
+ "alphacolor"{Eq}\' ENTER(VALUE1); BUFFERSET(A_Bitmap_alphacolor);
+ "alphacolor"{Eq}\" ENTER(VALUE2); BUFFERSET(A_Bitmap_alphacolor);
+
+ ">" {
+  if (!A_Bitmap_id) FAIL("Required attribute `id' not set for `Bitmap' element.");
+  if (!A_Bitmap_file) FAIL("Required attribute `file' not set for `Bitmap' element.");
+  if (!A_Bitmap_alphacolor) FAIL("Required attribute `alphacolor' not set for `Bitmap' element.");
+  LEAVE; STag_Bitmap(); pcdata = NULL; ENTER(E_Bitmap);
+ }
+ "/>" {
+  if (!A_Bitmap_id) FAIL("Required attribute `id' not set for `Bitmap' element.");
+  if (!A_Bitmap_file) FAIL("Required attribute `file' not set for `Bitmap' element.");
+  if (!A_Bitmap_alphacolor) FAIL("Required attribute `alphacolor' not set for `Bitmap' element.");
+  LEAVE; STag_Bitmap(); pcdata = NULL; ETag_Bitmap();
+  switch (YY_START) {
+   case S_Theme_2: case S_Theme_1: case S_Theme_3: SET(S_Theme_3); break;
+   case ROOT_Bitmap: SET(EPILOG); break;
+  }
+ }
+ .       FAIL("Unexpected character `%c' in attribute list of Bitmap element.", yytext[0]);
+ {Name} FAIL("Bad attribute `%s' in `Bitmap' element start tag.",yytext);
+ <<EOF>> FAIL("EOF in attribute list of `Bitmap' element.");
+}
+
+<E_Bitmap>{
+ "</Bitmap"{s}">" {
+  LEAVE;
+  ETag_Bitmap();
+  switch (YY_START) {
+   case S_Theme_2: case S_Theme_1: case S_Theme_3: SET(S_Theme_3); break;
+   case ROOT_Bitmap: SET(EPILOG); break;
+  }
+ }
+ "</"{Name}{s}">" FAIL("Unexpected end-tag `%s': `</Bitmap>' expected.",yytext);
+ .       FAIL("Unexpected character `%c': `</Bitmap>' expected.",yytext[0]);
+ <<EOF>> FAIL("Premature EOF: `</Bitmap>' expected.");
+}
+
+ /*         id          CDATA   #REQUIRED
+  *         event       CDATA   #REQUIRED
+  *         key         CDATA   "none"
+  *     >  */
+
+<ROOT_Event,S_Theme_2,S_Theme_1,S_Theme_3>"<Event"{s} {
+  A_Event_id = NULL;
+  A_Event_event = NULL;
+  A_Event_key = "none";
+  ENTER(AL_Event);
+}
+
+<AL_Event>{
+ "id"{Eq}\' ENTER(VALUE1); BUFFERSET(A_Event_id);
+ "id"{Eq}\" ENTER(VALUE2); BUFFERSET(A_Event_id);
+
+ "event"{Eq}\' ENTER(VALUE1); BUFFERSET(A_Event_event);
+ "event"{Eq}\" ENTER(VALUE2); BUFFERSET(A_Event_event);
+
+ "key"{Eq}\' ENTER(VALUE1); BUFFERSET(A_Event_key);
+ "key"{Eq}\" ENTER(VALUE2); BUFFERSET(A_Event_key);
+
+ ">" {
+  if (!A_Event_id) FAIL("Required attribute `id' not set for `Event' element.");
+  if (!A_Event_event) FAIL("Required attribute `event' not set for `Event' element.");
+  LEAVE; STag_Event(); pcdata = NULL; ENTER(E_Event);
+ }
+ "/>" {
+  if (!A_Event_id) FAIL("Required attribute `id' not set for `Event' element.");
+  if (!A_Event_event) FAIL("Required attribute `event' not set for `Event' element.");
+  LEAVE; STag_Event(); pcdata = NULL; ETag_Event();
+  switch (YY_START) {
+   case S_Theme_2: case S_Theme_1: case S_Theme_3: SET(S_Theme_3); break;
+   case ROOT_Event: SET(EPILOG); break;
+  }
+ }
+ .       FAIL("Unexpected character `%c' in attribute list of Event element.", yytext[0]);
+ {Name} FAIL("Bad attribute `%s' in `Event' element start tag.",yytext);
+ <<EOF>> FAIL("EOF in attribute list of `Event' element.");
+}
+
+<E_Event>{
+ "</Event"{s}">" {
+  LEAVE;
+  ETag_Event();
+  switch (YY_START) {
+   case S_Theme_2: case S_Theme_1: case S_Theme_3: SET(S_Theme_3); break;
+   case ROOT_Event: SET(EPILOG); break;
+  }
+ }
+ "</"{Name}{s}">" FAIL("Unexpected end-tag `%s': `</Event>' expected.",yytext);
+ .       FAIL("Unexpected character `%c': `</Event>' expected.",yytext[0]);
+ <<EOF>> FAIL("Premature EOF: `</Event>' expected.");
+}
+
+ /*         id          CDATA   #REQUIRED
+  *         font        CDATA   "arial"
+  *         size        CDATA   "12"
+  *         color       CDATA   "#000000"
+  *         italic      CDATA   "false"
+  *         underline   CDATA   "false"
+  *     >  */
+
+<ROOT_Font,S_Theme_2,S_Theme_1,S_Theme_3>"<Font"{s} {
+  A_Font_id = NULL;
+  A_Font_font = "arial";
+  A_Font_size = "12";
+  A_Font_color = "#000000";
+  A_Font_italic = "false";
+  A_Font_underline = "false";
+  ENTER(AL_Font);
+}
+
+<AL_Font>{
+ "id"{Eq}\' ENTER(VALUE1); BUFFERSET(A_Font_id);
+ "id"{Eq}\" ENTER(VALUE2); BUFFERSET(A_Font_id);
+
+ "font"{Eq}\' ENTER(VALUE1); BUFFERSET(A_Font_font);
+ "font"{Eq}\" ENTER(VALUE2); BUFFERSET(A_Font_font);
+
+ "size"{Eq}\' ENTER(VALUE1); BUFFERSET(A_Font_size);
+ "size"{Eq}\" ENTER(VALUE2); BUFFERSET(A_Font_size);
+
+ "color"{Eq}\' ENTER(VALUE1); BUFFERSET(A_Font_color);
+ "color"{Eq}\" ENTER(VALUE2); BUFFERSET(A_Font_color);
+
+ "italic"{Eq}\' ENTER(VALUE1); BUFFERSET(A_Font_italic);
+ "italic"{Eq}\" ENTER(VALUE2); BUFFERSET(A_Font_italic);
+
+ "underline"{Eq}\' ENTER(VALUE1); BUFFERSET(A_Font_underline);
+ "underline"{Eq}\" ENTER(VALUE2); BUFFERSET(A_Font_underline);
+
+ ">" {
+  if (!A_Font_id) FAIL("Required attribute `id' not set for `Font' element.");
+  LEAVE; STag_Font(); pcdata = NULL; ENTER(E_Font);
+ }
+ "/>" {
+  if (!A_Font_id) FAIL("Required attribute `id' not set for `Font' element.");
+  LEAVE; STag_Font(); pcdata = NULL; ETag_Font();
+  switch (YY_START) {
+   case ROOT_Font: SET(EPILOG); break;
+   case S_Theme_2: case S_Theme_1: case S_Theme_3: SET(S_Theme_3); break;
+  }
+ }
+ .       FAIL("Unexpected character `%c' in attribute list of Font element.", yytext[0]);
+ {Name} FAIL("Bad attribute `%s' in `Font' element start tag.",yytext);
+ <<EOF>> FAIL("EOF in attribute list of `Font' element.");
+}
+
+<E_Font>{
+ "</Font"{s}">" {
+  LEAVE;
+  ETag_Font();
+  switch (YY_START) {
+   case ROOT_Font: SET(EPILOG); break;
+   case S_Theme_2: case S_Theme_1: case S_Theme_3: SET(S_Theme_3); break;
+  }
+ }
+ "</"{Name}{s}">" FAIL("Unexpected end-tag `%s': `</Font>' expected.",yytext);
+ .       FAIL("Unexpected character `%c': `</Font>' expected.",yytext[0]);
+ <<EOF>> FAIL("Premature EOF: `</Font>' expected.");
+}
+
+ /*         name        CDATA   #IMPLIED
+  *         author      CDATA   #IMPLIED
+  *         email       CDATA   #IMPLIED
+  *         webpage     CDATA   #IMPLIED
+  *     >  */
+
+<ROOT_ThemeInfo,S_Theme>"<ThemeInfo"{s} {
+  A_ThemeInfo_name = NULL;
+  A_ThemeInfo_author = NULL;
+  A_ThemeInfo_email = NULL;
+  A_ThemeInfo_webpage = NULL;
+  ENTER(AL_ThemeInfo);
+}
+
+<AL_ThemeInfo>{
+ "name"{Eq}\' ENTER(VALUE1); BUFFERSET(A_ThemeInfo_name);
+ "name"{Eq}\" ENTER(VALUE2); BUFFERSET(A_ThemeInfo_name);
+
+ "author"{Eq}\' ENTER(VALUE1); BUFFERSET(A_ThemeInfo_author);
+ "author"{Eq}\" ENTER(VALUE2); BUFFERSET(A_ThemeInfo_author);
+
+ "email"{Eq}\' ENTER(VALUE1); BUFFERSET(A_ThemeInfo_email);
+ "email"{Eq}\" ENTER(VALUE2); BUFFERSET(A_ThemeInfo_email);
+
+ "webpage"{Eq}\' ENTER(VALUE1); BUFFERSET(A_ThemeInfo_webpage);
+ "webpage"{Eq}\" ENTER(VALUE2); BUFFERSET(A_ThemeInfo_webpage);
+
+ ">" {
+  LEAVE; STag_ThemeInfo(); pcdata = NULL; ENTER(E_ThemeInfo);
+ }
+ "/>" {
+  LEAVE; STag_ThemeInfo(); pcdata = NULL; ETag_ThemeInfo();
+  switch (YY_START) {
+   case S_Theme: SET(S_Theme_1); break;
+   case ROOT_ThemeInfo: SET(EPILOG); break;
+  }
+ }
+ .       FAIL("Unexpected character `%c' in attribute list of ThemeInfo element.", yytext[0]);
+ {Name} FAIL("Bad attribute `%s' in `ThemeInfo' element start tag.",yytext);
+ <<EOF>> FAIL("EOF in attribute list of `ThemeInfo' element.");
+}
+
+<E_ThemeInfo>{
+ "</ThemeInfo"{s}">" {
+  LEAVE;
+  ETag_ThemeInfo();
+  switch (YY_START) {
+   case S_Theme: SET(S_Theme_1); break;
+   case ROOT_ThemeInfo: SET(EPILOG); break;
+  }
+ }
+ "</"{Name}{s}">" FAIL("Unexpected end-tag `%s': `</ThemeInfo>' expected.",yytext);
+ .       FAIL("Unexpected character `%c': `</ThemeInfo>' expected.",yytext[0]);
+ <<EOF>> FAIL("Premature EOF: `</ThemeInfo>' expected.");
+}
+
+ /*         id          CDATA   #REQUIRED
+  *         visible     CDATA   "true"
+  *         x           CDATA   "\0"
+  *         y           CDATA   "\0"
+  *         dragdrop    CDATA   "true"
+  *         playondrop  CDATA   "true"
+  *     >  */
+
+<ROOT_Window,S_Theme_2,S_Theme_1,S_Theme_3>"<Window"{s} {
+  A_Window_id = NULL;
+  A_Window_visible = "true";
+  A_Window_x = "\0";
+  A_Window_y = "\0";
+  A_Window_dragdrop = "true";
+  A_Window_playondrop = "true";
+  ENTER(AL_Window);
+}
+
+<AL_Window>{
+ "id"{Eq}\' ENTER(VALUE1); BUFFERSET(A_Window_id);
+ "id"{Eq}\" ENTER(VALUE2); BUFFERSET(A_Window_id);
+
+ "visible"{Eq}\' ENTER(VALUE1); BUFFERSET(A_Window_visible);
+ "visible"{Eq}\" ENTER(VALUE2); BUFFERSET(A_Window_visible);
+
+ "x"{Eq}\' ENTER(VALUE1); BUFFERSET(A_Window_x);
+ "x"{Eq}\" ENTER(VALUE2); BUFFERSET(A_Window_x);
+
+ "y"{Eq}\' ENTER(VALUE1); BUFFERSET(A_Window_y);
+ "y"{Eq}\" ENTER(VALUE2); BUFFERSET(A_Window_y);
+
+ "dragdrop"{Eq}\' ENTER(VALUE1); BUFFERSET(A_Window_dragdrop);
+ "dragdrop"{Eq}\" ENTER(VALUE2); BUFFERSET(A_Window_dragdrop);
+
+ "playondrop"{Eq}\' ENTER(VALUE1); BUFFERSET(A_Window_playondrop);
+ "playondrop"{Eq}\" ENTER(VALUE2); BUFFERSET(A_Window_playondrop);
+
+ ">" {
+  if (!A_Window_id) FAIL("Required attribute `id' not set for `Window' element.");
+  LEAVE; STag_Window(); pcdata = NULL; ENTER(S_Window);
+ }
+ "/>" FAIL("`Window' element cannot be empty.");
+ .       FAIL("Unexpected character `%c' in attribute list of Window element.", yytext[0]);
+ {Name} FAIL("Bad attribute `%s' in `Window' element start tag.",yytext);
+ <<EOF>> FAIL("EOF in attribute list of `Window' element.");
+}
+
+<S_Window_2,E_Window>{
+ "</Window"{s}">" {
+  LEAVE;
+  ETag_Window();
+  switch (YY_START) {
+   case ROOT_Window: SET(EPILOG); break;
+   case S_Theme_2: case S_Theme_1: case S_Theme_3: SET(S_Theme_3); break;
+  }
+ }
+ "</"{Name}{s}">" FAIL("Unexpected end-tag `%s': `</Window>' expected.",yytext);
+ .       FAIL("Unexpected character `%c': `</Window>' expected.",yytext[0]);
+ <<EOF>> FAIL("Premature EOF: `</Window>' expected.");
+}
+
+ /*         id          CDATA   "none"
+  *         width       CDATA   #REQUIRED
+  *         height      CDATA   #REQUIRED
+  *         minwidth    CDATA   "-1"
+  *         maxwidth    CDATA   "-1"
+  *         minheight   CDATA   "-1"
+  *         maxheight   CDATA   "-1"
+  *     >  */
+
+<ROOT_Layout,S_Window,S_Window_1,S_Window_2>"<Layout"{s} {
+  A_Layout_id = "none";
+  A_Layout_width = NULL;
+  A_Layout_height = NULL;
+  A_Layout_minwidth = "-1";
+  A_Layout_maxwidth = "-1";
+  A_Layout_minheight = "-1";
+  A_Layout_maxheight = "-1";
+  ENTER(AL_Layout);
+}
+
+<AL_Layout>{
+ "id"{Eq}\' ENTER(VALUE1); BUFFERSET(A_Layout_id);
+ "id"{Eq}\" ENTER(VALUE2); BUFFERSET(A_Layout_id);
+
+ "width"{Eq}\' ENTER(VALUE1); BUFFERSET(A_Layout_width);
+ "width"{Eq}\" ENTER(VALUE2); BUFFERSET(A_Layout_width);
+
+ "height"{Eq}\' ENTER(VALUE1); BUFFERSET(A_Layout_height);
+ "height"{Eq}\" ENTER(VALUE2); BUFFERSET(A_Layout_height);
+
+ "minwidth"{Eq}\' ENTER(VALUE1); BUFFERSET(A_Layout_minwidth);
+ "minwidth"{Eq}\" ENTER(VALUE2); BUFFERSET(A_Layout_minwidth);
+
+ "maxwidth"{Eq}\' ENTER(VALUE1); BUFFERSET(A_Layout_maxwidth);
+ "maxwidth"{Eq}\" ENTER(VALUE2); BUFFERSET(A_Layout_maxwidth);
+
+ "minheight"{Eq}\' ENTER(VALUE1); BUFFERSET(A_Layout_minheight);
+ "minheight"{Eq}\" ENTER(VALUE2); BUFFERSET(A_Layout_minheight);
+
+ "maxheight"{Eq}\' ENTER(VALUE1); BUFFERSET(A_Layout_maxheight);
+ "maxheight"{Eq}\" ENTER(VALUE2); BUFFERSET(A_Layout_maxheight);
+
+ ">" {
+  if (!A_Layout_width) FAIL("Required attribute `width' not set for `Layout' element.");
+  if (!A_Layout_height) FAIL("Required attribute `height' not set for `Layout' element.");
+  LEAVE; STag_Layout(); pcdata = NULL; ENTER(S_Layout);
+ }
+ "/>" FAIL("`Layout' element cannot be empty.");
+ .       FAIL("Unexpected character `%c' in attribute list of Layout element.", yytext[0]);
+ {Name} FAIL("Bad attribute `%s' in `Layout' element start tag.",yytext);
+ <<EOF>> FAIL("EOF in attribute list of `Layout' element.");
+}
+
+<E_Layout>{
+ "</Layout"{s}">" {
+  LEAVE;
+  ETag_Layout();
+  switch (YY_START) {
+   case S_Window: case S_Window_1: case S_Window_2: SET(S_Window_2); break;
+   case ROOT_Layout: SET(EPILOG); break;
+  }
+ }
+ "</"{Name}{s}">" FAIL("Unexpected end-tag `%s': `</Layout>' expected.",yytext);
+ .       FAIL("Unexpected character `%c': `</Layout>' expected.",yytext[0]);
+ <<EOF>> FAIL("Premature EOF: `</Layout>' expected.");
+}
+
+ /*                  Rectangle|Anchor)+>  */
+
+ /*         x           CDATA   "\0"
+  *         y           CDATA   "\0"
+  *     >  */
+
+<ROOT_Group,S_Group_2,S_Layout,S_Group_1,S_Group>"<Group"{s} {
+  A_Group_x = "\0";
+  A_Group_y = "\0";
+  ENTER(AL_Group);
+}
+
+<AL_Group>{
+ "x"{Eq}\' ENTER(VALUE1); BUFFERSET(A_Group_x);
+ "x"{Eq}\" ENTER(VALUE2); BUFFERSET(A_Group_x);
+
+ "y"{Eq}\' ENTER(VALUE1); BUFFERSET(A_Group_y);
+ "y"{Eq}\" ENTER(VALUE2); BUFFERSET(A_Group_y);
+
+ ">" {
+  LEAVE; STag_Group(); pcdata = NULL; ENTER(S_Group);
+ }
+ "/>" FAIL("`Group' element cannot be empty.");
+ .       FAIL("Unexpected character `%c' in attribute list of Group element.", yytext[0]);
+ {Name} FAIL("Bad attribute `%s' in `Group' element start tag.",yytext);
+ <<EOF>> FAIL("EOF in attribute list of `Group' element.");
+}
+
+<S_Group_2,E_Group>{
+ "</Group"{s}">" {
+  LEAVE;
+  ETag_Group();
+  switch (YY_START) {
+   case S_Group_2: case S_Group_1: case S_Group: SET(S_Group_2); break;
+   case S_Layout: SET(E_Layout); break;
+   case ROOT_Group: SET(EPILOG); break;
+  }
+ }
+ "</"{Name}{s}">" FAIL("Unexpected end-tag `%s': `</Group>' expected.",yytext);
+ .       FAIL("Unexpected character `%c': `</Group>' expected.",yytext[0]);
+ <<EOF>> FAIL("Premature EOF: `</Group>' expected.");
+}
+
+ /* <!-- Anchors -->  */
+
+ /*         x           CDATA   "\0"
+  *         y           CDATA   "\0"
+  *         priority    CDATA   #REQUIRED
+  *         range       CDATA   "10"
+  *     >  */
+
+<ROOT_Anchor,S_Group_2,S_Group_1,S_Group>"<Anchor"{s} {
+  A_Anchor_x = "\0";
+  A_Anchor_y = "\0";
+  A_Anchor_priority = NULL;
+  A_Anchor_range = "10";
+  ENTER(AL_Anchor);
+}
+
+<AL_Anchor>{
+ "x"{Eq}\' ENTER(VALUE1); BUFFERSET(A_Anchor_x);
+ "x"{Eq}\" ENTER(VALUE2); BUFFERSET(A_Anchor_x);
+
+ "y"{Eq}\' ENTER(VALUE1); BUFFERSET(A_Anchor_y);
+ "y"{Eq}\" ENTER(VALUE2); BUFFERSET(A_Anchor_y);
+
+ "priority"{Eq}\' ENTER(VALUE1); BUFFERSET(A_Anchor_priority);
+ "priority"{Eq}\" ENTER(VALUE2); BUFFERSET(A_Anchor_priority);
+
+ "range"{Eq}\' ENTER(VALUE1); BUFFERSET(A_Anchor_range);
+ "range"{Eq}\" ENTER(VALUE2); BUFFERSET(A_Anchor_range);
+
+ ">" {
+  if (!A_Anchor_priority) FAIL("Required attribute `priority' not set for `Anchor' element.");
+  LEAVE; STag_Anchor(); pcdata = NULL; ENTER(E_Anchor);
+ }
+ "/>" {
+  if (!A_Anchor_priority) FAIL("Required attribute `priority' not set for `Anchor' element.");
+  LEAVE; STag_Anchor(); pcdata = NULL; ETag_Anchor();
+  switch (YY_START) {
+   case S_Group_2: case S_Group_1: case S_Group: SET(S_Group_2); break;
+   case ROOT_Anchor: SET(EPILOG); break;
+  }
+ }
+ .       FAIL("Unexpected character `%c' in attribute list of Anchor element.", yytext[0]);
+ {Name} FAIL("Bad attribute `%s' in `Anchor' element start tag.",yytext);
+ <<EOF>> FAIL("EOF in attribute list of `Anchor' element.");
+}
+
+<E_Anchor>{
+ "</Anchor"{s}">" {
+  LEAVE;
+  ETag_Anchor();
+  switch (YY_START) {
+   case S_Group_2: case S_Group_1: case S_Group: SET(S_Group_2); break;
+   case ROOT_Anchor: SET(EPILOG); break;
+  }
+ }
+ "</"{Name}{s}">" FAIL("Unexpected end-tag `%s': `</Anchor>' expected.",yytext);
+ .       FAIL("Unexpected character `%c': `</Anchor>' expected.",yytext[0]);
+ <<EOF>> FAIL("Premature EOF: `</Anchor>' expected.");
+}
+
+ /* <!-- Controls -->  */
+
+ /*         id          CDATA   "none"
+  *         visible     CDATA   "true"
+  *         x           CDATA   "\0"
+  *         y           CDATA   "\0"
+  *         lefttop     CDATA   "lefttop"
+  *         rightbottom CDATA   "lefttop"
+  *         image       CDATA   #REQUIRED
+  *         onclick     CDATA   "none"
+  *         help        CDATA   "\0"
+  *     >  */
+
+<ROOT_Image,S_Group_2,S_Group_1,S_Group>"<Image"{s} {
+  A_Image_id = "none";
+  A_Image_visible = "true";
+  A_Image_x = "\0";
+  A_Image_y = "\0";
+  A_Image_lefttop = "lefttop";
+  A_Image_rightbottom = "lefttop";
+  A_Image_image = NULL;
+  A_Image_onclick = "none";
+  A_Image_help = "\0";
+  ENTER(AL_Image);
+}
+
+<AL_Image>{
+ "id"{Eq}\' ENTER(VALUE1); BUFFERSET(A_Image_id);
+ "id"{Eq}\" ENTER(VALUE2); BUFFERSET(A_Image_id);
+
+ "visible"{Eq}\' ENTER(VALUE1); BUFFERSET(A_Image_visible);
+ "visible"{Eq}\" ENTER(VALUE2); BUFFERSET(A_Image_visible);
+
+ "x"{Eq}\' ENTER(VALUE1); BUFFERSET(A_Image_x);
+ "x"{Eq}\" ENTER(VALUE2); BUFFERSET(A_Image_x);
+
+ "y"{Eq}\' ENTER(VALUE1); BUFFERSET(A_Image_y);
+ "y"{Eq}\" ENTER(VALUE2); BUFFERSET(A_Image_y);
+
+ "lefttop"{Eq}\' ENTER(VALUE1); BUFFERSET(A_Image_lefttop);
+ "lefttop"{Eq}\" ENTER(VALUE2); BUFFERSET(A_Image_lefttop);
+
+ "rightbottom"{Eq}\' ENTER(VALUE1); BUFFERSET(A_Image_rightbottom);
+ "rightbottom"{Eq}\" ENTER(VALUE2); BUFFERSET(A_Image_rightbottom);
+
+ "image"{Eq}\' ENTER(VALUE1); BUFFERSET(A_Image_image);
+ "image"{Eq}\" ENTER(VALUE2); BUFFERSET(A_Image_image);
+
+ "onclick"{Eq}\' ENTER(VALUE1); BUFFERSET(A_Image_onclick);
+ "onclick"{Eq}\" ENTER(VALUE2); BUFFERSET(A_Image_onclick);
+
+ "help"{Eq}\' ENTER(VALUE1); BUFFERSET(A_Image_help);
+ "help"{Eq}\" ENTER(VALUE2); BUFFERSET(A_Image_help);
+
+ ">" {
+  if (!A_Image_image) FAIL("Required attribute `image' not set for `Image' element.");
+  LEAVE; STag_Image(); pcdata = NULL; ENTER(E_Image);
+ }
+ "/>" {
+  if (!A_Image_image) FAIL("Required attribute `image' not set for `Image' element.");
+  LEAVE; STag_Image(); pcdata = NULL; ETag_Image();
+  switch (YY_START) {
+   case S_Group_2: case S_Group_1: case S_Group: SET(S_Group_2); break;
+   case ROOT_Image: SET(EPILOG); break;
+  }
+ }
+ .       FAIL("Unexpected character `%c' in attribute list of Image element.", yytext[0]);
+ {Name} FAIL("Bad attribute `%s' in `Image' element start tag.",yytext);
+ <<EOF>> FAIL("EOF in attribute list of `Image' element.");
+}
+
+<E_Image>{
+ "</Image"{s}">" {
+  LEAVE;
+  ETag_Image();
+  switch (YY_START) {
+   case S_Group_2: case S_Group_1: case S_Group: SET(S_Group_2); break;
+   case ROOT_Image: SET(EPILOG); break;
+  }
+ }
+ "</"{Name}{s}">" FAIL("Unexpected end-tag `%s': `</Image>' expected.",yytext);
+ .       FAIL("Unexpected character `%c': `</Image>' expected.",yytext[0]);
+ <<EOF>> FAIL("Premature EOF: `</Image>' expected.");
+}
+
+ /*         id          CDATA   "none"
+  *         visible     CDATA   "true"
+  *         x           CDATA   "\0"
+  *         y           CDATA   "\0"
+  *         w           CDATA   "50"
+  *         h           CDATA   "50"
+  *         color       CDATA   "#C0C0C0"
+  *         onclick     CDATA   "none"
+  *         help        CDATA   "\0"
+  *     >  */
+
+<ROOT_Rectangle,S_Group_2,S_Group_1,S_Group>"<Rectangle"{s} {
+  A_Rectangle_id = "none";
+  A_Rectangle_visible = "true";
+  A_Rectangle_x = "\0";
+  A_Rectangle_y = "\0";
+  A_Rectangle_w = "50";
+  A_Rectangle_h = "50";
+  A_Rectangle_color = "#C0C0C0";
+  A_Rectangle_onclick = "none";
+  A_Rectangle_help = "\0";
+  ENTER(AL_Rectangle);
+}
+
+<AL_Rectangle>{
+ "id"{Eq}\' ENTER(VALUE1); BUFFERSET(A_Rectangle_id);
+ "id"{Eq}\" ENTER(VALUE2); BUFFERSET(A_Rectangle_id);
+
+ "visible"{Eq}\' ENTER(VALUE1); BUFFERSET(A_Rectangle_visible);
+ "visible"{Eq}\" ENTER(VALUE2); BUFFERSET(A_Rectangle_visible);
+
+ "x"{Eq}\' ENTER(VALUE1); BUFFERSET(A_Rectangle_x);
+ "x"{Eq}\" ENTER(VALUE2); BUFFERSET(A_Rectangle_x);
+
+ "y"{Eq}\' ENTER(VALUE1); BUFFERSET(A_Rectangle_y);
+ "y"{Eq}\" ENTER(VALUE2); BUFFERSET(A_Rectangle_y);
+
+ "w"{Eq}\' ENTER(VALUE1); BUFFERSET(A_Rectangle_w);
+ "w"{Eq}\" ENTER(VALUE2); BUFFERSET(A_Rectangle_w);
+
+ "h"{Eq}\' ENTER(VALUE1); BUFFERSET(A_Rectangle_h);
+ "h"{Eq}\" ENTER(VALUE2); BUFFERSET(A_Rectangle_h);
+
+ "color"{Eq}\' ENTER(VALUE1); BUFFERSET(A_Rectangle_color);
+ "color"{Eq}\" ENTER(VALUE2); BUFFERSET(A_Rectangle_color);
+
+ "onclick"{Eq}\' ENTER(VALUE1); BUFFERSET(A_Rectangle_onclick);
+ "onclick"{Eq}\" ENTER(VALUE2); BUFFERSET(A_Rectangle_onclick);
+
+ "help"{Eq}\' ENTER(VALUE1); BUFFERSET(A_Rectangle_help);
+ "help"{Eq}\" ENTER(VALUE2); BUFFERSET(A_Rectangle_help);
+
+ ">" {
+  LEAVE; STag_Rectangle(); pcdata = NULL; ENTER(E_Rectangle);
+ }
+ "/>" {
+  LEAVE; STag_Rectangle(); pcdata = NULL; ETag_Rectangle();
+  switch (YY_START) {
+   case S_Group_2: case S_Group_1: case S_Group: SET(S_Group_2); break;
+   case ROOT_Rectangle: SET(EPILOG); break;
+  }
+ }
+ .       FAIL("Unexpected character `%c' in attribute list of Rectangle element.", yytext[0]);
+ {Name} FAIL("Bad attribute `%s' in `Rectangle' element start tag.",yytext);
+ <<EOF>> FAIL("EOF in attribute list of `Rectangle' element.");
+}
+
+<E_Rectangle>{
+ "</Rectangle"{s}">" {
+  LEAVE;
+  ETag_Rectangle();
+  switch (YY_START) {
+   case S_Group_2: case S_Group_1: case S_Group: SET(S_Group_2); break;
+   case ROOT_Rectangle: SET(EPILOG); break;
+  }
+ }
+ "</"{Name}{s}">" FAIL("Unexpected end-tag `%s': `</Rectangle>' expected.",yytext);
+ .       FAIL("Unexpected character `%c': `</Rectangle>' expected.",yytext[0]);
+ <<EOF>> FAIL("Premature EOF: `</Rectangle>' expected.");
+}
+
+ /*         id          CDATA   "none"
+  *         x           CDATA   "\0"
+  *         y           CDATA   "\0"
+  *         lefttop     CDATA   "lefttop"
+  *         rightbottom CDATA   "lefttop"
+  *         up          CDATA   #REQUIRED
+  *         down        CDATA   "none"
+  *         over        CDATA   "none"
+  *         action      CDATA   "none"
+  *         tooltiptext CDATA   "\0"
+  *         help        CDATA   "\0"
+  *     >  */
+
+<ROOT_Button,S_Group_2,S_Group_1,S_Group>"<Button"{s} {
+  A_Button_id = "none";
+  A_Button_x = "\0";
+  A_Button_y = "\0";
+  A_Button_lefttop = "lefttop";
+  A_Button_rightbottom = "lefttop";
+  A_Button_up = NULL;
+  A_Button_down = "none";
+  A_Button_over = "none";
+  A_Button_action = "none";
+  A_Button_tooltiptext = "\0";
+  A_Button_help = "\0";
+  ENTER(AL_Button);
+}
+
+<AL_Button>{
+ "id"{Eq}\' ENTER(VALUE1); BUFFERSET(A_Button_id);
+ "id"{Eq}\" ENTER(VALUE2); BUFFERSET(A_Button_id);
+
+ "x"{Eq}\' ENTER(VALUE1); BUFFERSET(A_Button_x);
+ "x"{Eq}\" ENTER(VALUE2); BUFFERSET(A_Button_x);
+
+ "y"{Eq}\' ENTER(VALUE1); BUFFERSET(A_Button_y);
+ "y"{Eq}\" ENTER(VALUE2); BUFFERSET(A_Button_y);
+
+ "lefttop"{Eq}\' ENTER(VALUE1); BUFFERSET(A_Button_lefttop);
+ "lefttop"{Eq}\" ENTER(VALUE2); BUFFERSET(A_Button_lefttop);
+
+ "rightbottom"{Eq}\' ENTER(VALUE1); BUFFERSET(A_Button_rightbottom);
+ "rightbottom"{Eq}\" ENTER(VALUE2); BUFFERSET(A_Button_rightbottom);
+
+ "up"{Eq}\' ENTER(VALUE1); BUFFERSET(A_Button_up);
+ "up"{Eq}\" ENTER(VALUE2); BUFFERSET(A_Button_up);
+
+ "down"{Eq}\' ENTER(VALUE1); BUFFERSET(A_Button_down);
+ "down"{Eq}\" ENTER(VALUE2); BUFFERSET(A_Button_down);
+
+ "over"{Eq}\' ENTER(VALUE1); BUFFERSET(A_Button_over);
+ "over"{Eq}\" ENTER(VALUE2); BUFFERSET(A_Button_over);
+
+ "action"{Eq}\' ENTER(VALUE1); BUFFERSET(A_Button_action);
+ "action"{Eq}\" ENTER(VALUE2); BUFFERSET(A_Button_action);
+
+ "tooltiptext"{Eq}\' ENTER(VALUE1); BUFFERSET(A_Button_tooltiptext);
+ "tooltiptext"{Eq}\" ENTER(VALUE2); BUFFERSET(A_Button_tooltiptext);
+
+ "help"{Eq}\' ENTER(VALUE1); BUFFERSET(A_Button_help);
+ "help"{Eq}\" ENTER(VALUE2); BUFFERSET(A_Button_help);
+
+ ">" {
+  if (!A_Button_up) FAIL("Required attribute `up' not set for `Button' element.");
+  LEAVE; STag_Button(); pcdata = NULL; ENTER(E_Button);
+ }
+ "/>" {
+  if (!A_Button_up) FAIL("Required attribute `up' not set for `Button' element.");
+  LEAVE; STag_Button(); pcdata = NULL; ETag_Button();
+  switch (YY_START) {
+   case S_Group_2: case S_Group_1: case S_Group: SET(S_Group_2); break;
+   case ROOT_Button: SET(EPILOG); break;
+  }
+ }
+ .       FAIL("Unexpected character `%c' in attribute list of Button element.", yytext[0]);
+ {Name} FAIL("Bad attribute `%s' in `Button' element start tag.",yytext);
+ <<EOF>> FAIL("EOF in attribute list of `Button' element.");
+}
+
+<E_Button>{
+ "</Button"{s}">" {
+  LEAVE;
+  ETag_Button();
+  switch (YY_START) {
+   case S_Group_2: case S_Group_1: case S_Group: SET(S_Group_2); break;
+   case ROOT_Button: SET(EPILOG); break;
+  }
+ }
+ "</"{Name}{s}">" FAIL("Unexpected end-tag `%s': `</Button>' expected.",yytext);
+ .       FAIL("Unexpected character `%c': `</Button>' expected.",yytext[0]);
+ <<EOF>> FAIL("Premature EOF: `</Button>' expected.");
+}
+
+ /*         id           CDATA   "none"
+  *         x            CDATA   "\0"
+  *         y            CDATA   "\0"
+  *         lefttop      CDATA   "lefttop"
+  *         rightbottom  CDATA   "lefttop"
+  *         up1          CDATA   #REQUIRED
+  *         down1        CDATA   "none"
+  *         over1        CDATA   "none"
+  *         up2          CDATA   #REQUIRED
+  *         down2        CDATA   "none"
+  *         over2        CDATA   "none"
+  *         state        CDATA   #REQUIRED
+  *         action1      CDATA   "none"
+  *         action2      CDATA   "none"
+  *         tooltiptext1 CDATA   "\0"
+  *         tooltiptext2 CDATA   "\0"
+  *         help         CDATA   "\0"
+  *     >  */
+
+<ROOT_CheckBox,S_Group_2,S_Group_1,S_Group>"<CheckBox"{s} {
+  A_CheckBox_id = "none";
+  A_CheckBox_x = "\0";
+  A_CheckBox_y = "\0";
+  A_CheckBox_lefttop = "lefttop";
+  A_CheckBox_rightbottom = "lefttop";
+  A_CheckBox_up1 = NULL;
+  A_CheckBox_down1 = "none";
+  A_CheckBox_over1 = "none";
+  A_CheckBox_up2 = NULL;
+  A_CheckBox_down2 = "none";
+  A_CheckBox_over2 = "none";
+  A_CheckBox_state = NULL;
+  A_CheckBox_action1 = "none";
+  A_CheckBox_action2 = "none";
+  A_CheckBox_tooltiptext1 = "\0";
+  A_CheckBox_tooltiptext2 = "\0";
+  A_CheckBox_help = "\0";
+  ENTER(AL_CheckBox);
+}
+
+<AL_CheckBox>{
+ "id"{Eq}\' ENTER(VALUE1); BUFFERSET(A_CheckBox_id);
+ "id"{Eq}\" ENTER(VALUE2); BUFFERSET(A_CheckBox_id);
+
+ "x"{Eq}\' ENTER(VALUE1); BUFFERSET(A_CheckBox_x);
+ "x"{Eq}\" ENTER(VALUE2); BUFFERSET(A_CheckBox_x);
+
+ "y"{Eq}\' ENTER(VALUE1); BUFFERSET(A_CheckBox_y);
+ "y"{Eq}\" ENTER(VALUE2); BUFFERSET(A_CheckBox_y);
+
+ "lefttop"{Eq}\' ENTER(VALUE1); BUFFERSET(A_CheckBox_lefttop);
+ "lefttop"{Eq}\" ENTER(VALUE2); BUFFERSET(A_CheckBox_lefttop);
+
+ "rightbottom"{Eq}\' ENTER(VALUE1); BUFFERSET(A_CheckBox_rightbottom);
+ "rightbottom"{Eq}\" ENTER(VALUE2); BUFFERSET(A_CheckBox_rightbottom);
+
+ "up1"{Eq}\' ENTER(VALUE1); BUFFERSET(A_CheckBox_up1);
+ "up1"{Eq}\" ENTER(VALUE2); BUFFERSET(A_CheckBox_up1);
+
+ "down1"{Eq}\' ENTER(VALUE1); BUFFERSET(A_CheckBox_down1);
+ "down1"{Eq}\" ENTER(VALUE2); BUFFERSET(A_CheckBox_down1);
+
+ "over1"{Eq}\' ENTER(VALUE1); BUFFERSET(A_CheckBox_over1);
+ "over1"{Eq}\" ENTER(VALUE2); BUFFERSET(A_CheckBox_over1);
+
+ "up2"{Eq}\' ENTER(VALUE1); BUFFERSET(A_CheckBox_up2);
+ "up2"{Eq}\" ENTER(VALUE2); BUFFERSET(A_CheckBox_up2);
+
+ "down2"{Eq}\' ENTER(VALUE1); BUFFERSET(A_CheckBox_down2);
+ "down2"{Eq}\" ENTER(VALUE2); BUFFERSET(A_CheckBox_down2);
+
+ "over2"{Eq}\' ENTER(VALUE1); BUFFERSET(A_CheckBox_over2);
+ "over2"{Eq}\" ENTER(VALUE2); BUFFERSET(A_CheckBox_over2);
+
+ "state"{Eq}\' ENTER(VALUE1); BUFFERSET(A_CheckBox_state);
+ "state"{Eq}\" ENTER(VALUE2); BUFFERSET(A_CheckBox_state);
+
+ "action1"{Eq}\' ENTER(VALUE1); BUFFERSET(A_CheckBox_action1);
+ "action1"{Eq}\" ENTER(VALUE2); BUFFERSET(A_CheckBox_action1);
+
+ "action2"{Eq}\' ENTER(VALUE1); BUFFERSET(A_CheckBox_action2);
+ "action2"{Eq}\" ENTER(VALUE2); BUFFERSET(A_CheckBox_action2);
+
+ "tooltiptext1"{Eq}\' ENTER(VALUE1); BUFFERSET(A_CheckBox_tooltiptext1);
+ "tooltiptext1"{Eq}\" ENTER(VALUE2); BUFFERSET(A_CheckBox_tooltiptext1);
+
+ "tooltiptext2"{Eq}\' ENTER(VALUE1); BUFFERSET(A_CheckBox_tooltiptext2);
+ "tooltiptext2"{Eq}\" ENTER(VALUE2); BUFFERSET(A_CheckBox_tooltiptext2);
+
+ "help"{Eq}\' ENTER(VALUE1); BUFFERSET(A_CheckBox_help);
+ "help"{Eq}\" ENTER(VALUE2); BUFFERSET(A_CheckBox_help);
+
+ ">" {
+  if (!A_CheckBox_up1) FAIL("Required attribute `up1' not set for `CheckBox' element.");
+  if (!A_CheckBox_up2) FAIL("Required attribute `up2' not set for `CheckBox' element.");
+  if (!A_CheckBox_state) FAIL("Required attribute `state' not set for `CheckBox' element.");
+  LEAVE; STag_CheckBox(); pcdata = NULL; ENTER(E_CheckBox);
+ }
+ "/>" {
+  if (!A_CheckBox_up1) FAIL("Required attribute `up1' not set for `CheckBox' element.");
+  if (!A_CheckBox_up2) FAIL("Required attribute `up2' not set for `CheckBox' element.");
+  if (!A_CheckBox_state) FAIL("Required attribute `state' not set for `CheckBox' element.");
+  LEAVE; STag_CheckBox(); pcdata = NULL; ETag_CheckBox();
+  switch (YY_START) {
+   case S_Group_2: case S_Group_1: case S_Group: SET(S_Group_2); break;
+   case ROOT_CheckBox: SET(EPILOG); break;
+  }
+ }
+ .       FAIL("Unexpected character `%c' in attribute list of CheckBox element.", yytext[0]);
+ {Name} FAIL("Bad attribute `%s' in `CheckBox' element start tag.",yytext);
+ <<EOF>> FAIL("EOF in attribute list of `CheckBox' element.");
+}
+
+<E_CheckBox>{
+ "</CheckBox"{s}">" {
+  LEAVE;
+  ETag_CheckBox();
+  switch (YY_START) {
+   case S_Group_2: case S_Group_1: case S_Group: SET(S_Group_2); break;
+   case ROOT_CheckBox: SET(EPILOG); break;
+  }
+ }
+ "</"{Name}{s}">" FAIL("Unexpected end-tag `%s': `</CheckBox>' expected.",yytext);
+ .       FAIL("Unexpected character `%c': `</CheckBox>' expected.",yytext[0]);
+ <<EOF>> FAIL("Premature EOF: `</CheckBox>' expected.");
+}
+
+ /*         id          CDATA   "none"
+  *         visible     CDATA   "true"
+  *         x           CDATA   "\0"
+  *         y           CDATA   "\0"
+  *         lefttop     CDATA   "lefttop"
+  *         rightbottom CDATA   "lefttop"
+  *         up          CDATA   #REQUIRED
+  *         down        CDATA   "none"
+  *         over        CDATA   "none"
+  *         points      CDATA   #REQUIRED
+  *         thickness   CDATA   "10"
+  *         value       CDATA   "none"
+  *         tooltiptext CDATA   "\0"
+  *         help        CDATA   "\0"
+  *     >  */
+
+<ROOT_Slider,S_Playlist,S_Group_2,S_Group_1,S_Group>"<Slider"{s} {
+  A_Slider_id = "none";
+  A_Slider_visible = "true";
+  A_Slider_x = "\0";
+  A_Slider_y = "\0";
+  A_Slider_lefttop = "lefttop";
+  A_Slider_rightbottom = "lefttop";
+  A_Slider_up = NULL;
+  A_Slider_down = "none";
+  A_Slider_over = "none";
+  A_Slider_points = NULL;
+  A_Slider_thickness = "10";
+  A_Slider_value = "none";
+  A_Slider_tooltiptext = "\0";
+  A_Slider_help = "\0";
+  ENTER(AL_Slider);
+}
+
+<AL_Slider>{
+ "id"{Eq}\' ENTER(VALUE1); BUFFERSET(A_Slider_id);
+ "id"{Eq}\" ENTER(VALUE2); BUFFERSET(A_Slider_id);
+
+ "visible"{Eq}\' ENTER(VALUE1); BUFFERSET(A_Slider_visible);
+ "visible"{Eq}\" ENTER(VALUE2); BUFFERSET(A_Slider_visible);
+
+ "x"{Eq}\' ENTER(VALUE1); BUFFERSET(A_Slider_x);
+ "x"{Eq}\" ENTER(VALUE2); BUFFERSET(A_Slider_x);
+
+ "y"{Eq}\' ENTER(VALUE1); BUFFERSET(A_Slider_y);
+ "y"{Eq}\" ENTER(VALUE2); BUFFERSET(A_Slider_y);
+
+ "lefttop"{Eq}\' ENTER(VALUE1); BUFFERSET(A_Slider_lefttop);
+ "lefttop"{Eq}\" ENTER(VALUE2); BUFFERSET(A_Slider_lefttop);
+
+ "rightbottom"{Eq}\' ENTER(VALUE1); BUFFERSET(A_Slider_rightbottom);
+ "rightbottom"{Eq}\" ENTER(VALUE2); BUFFERSET(A_Slider_rightbottom);
+
+ "up"{Eq}\' ENTER(VALUE1); BUFFERSET(A_Slider_up);
+ "up"{Eq}\" ENTER(VALUE2); BUFFERSET(A_Slider_up);
+
+ "down"{Eq}\' ENTER(VALUE1); BUFFERSET(A_Slider_down);
+ "down"{Eq}\" ENTER(VALUE2); BUFFERSET(A_Slider_down);
+
+ "over"{Eq}\' ENTER(VALUE1); BUFFERSET(A_Slider_over);
+ "over"{Eq}\" ENTER(VALUE2); BUFFERSET(A_Slider_over);
+
+ "points"{Eq}\' ENTER(VALUE1); BUFFERSET(A_Slider_points);
+ "points"{Eq}\" ENTER(VALUE2); BUFFERSET(A_Slider_points);
+
+ "thickness"{Eq}\' ENTER(VALUE1); BUFFERSET(A_Slider_thickness);
+ "thickness"{Eq}\" ENTER(VALUE2); BUFFERSET(A_Slider_thickness);
+
+ "value"{Eq}\' ENTER(VALUE1); BUFFERSET(A_Slider_value);
+ "value"{Eq}\" ENTER(VALUE2); BUFFERSET(A_Slider_value);
+
+ "tooltiptext"{Eq}\' ENTER(VALUE1); BUFFERSET(A_Slider_tooltiptext);
+ "tooltiptext"{Eq}\" ENTER(VALUE2); BUFFERSET(A_Slider_tooltiptext);
+
+ "help"{Eq}\' ENTER(VALUE1); BUFFERSET(A_Slider_help);
+ "help"{Eq}\" ENTER(VALUE2); BUFFERSET(A_Slider_help);
+
+ ">" {
+  if (!A_Slider_up) FAIL("Required attribute `up' not set for `Slider' element.");
+  if (!A_Slider_points) FAIL("Required attribute `points' not set for `Slider' element.");
+  LEAVE; STag_Slider(); pcdata = NULL; ENTER(E_Slider);
+ }
+ "/>" {
+  if (!A_Slider_up) FAIL("Required attribute `up' not set for `Slider' element.");
+  if (!A_Slider_points) FAIL("Required attribute `points' not set for `Slider' element.");
+  LEAVE; STag_Slider(); pcdata = NULL; ETag_Slider();
+  switch (YY_START) {
+   case S_Playlist: SET(E_Playlist); break;
+   case S_Group_2: case S_Group_1: case S_Group: SET(S_Group_2); break;
+   case ROOT_Slider: SET(EPILOG); break;
+  }
+ }
+ .       FAIL("Unexpected character `%c' in attribute list of Slider element.", yytext[0]);
+ {Name} FAIL("Bad attribute `%s' in `Slider' element start tag.",yytext);
+ <<EOF>> FAIL("EOF in attribute list of `Slider' element.");
+}
+
+<E_Slider>{
+ "</Slider"{s}">" {
+  LEAVE;
+  ETag_Slider();
+  switch (YY_START) {
+   case S_Playlist: SET(E_Playlist); break;
+   case S_Group_2: case S_Group_1: case S_Group: SET(S_Group_2); break;
+   case ROOT_Slider: SET(EPILOG); break;
+  }
+ }
+ "</"{Name}{s}">" FAIL("Unexpected end-tag `%s': `</Slider>' expected.",yytext);
+ .       FAIL("Unexpected character `%c': `</Slider>' expected.",yytext[0]);
+ <<EOF>> FAIL("Premature EOF: `</Slider>' expected.");
+}
+
+ /*         id          CDATA   "none"
+  *         visible     CDATA   "true"
+  *         x           CDATA   "\0"
+  *         y           CDATA   "\0"
+  *         lefttop     CDATA   "lefttop"
+  *         rightbottom CDATA   "lefttop"
+  *         sequence    CDATA   #REQUIRED
+  *         nbimages    CDATA   #REQUIRED
+  *         minangle    CDATA   "\0"
+  *         maxangle    CDATA   "360"
+  *         value       CDATA   "none"
+  *         tooltiptext CDATA   "\0"
+  *         help        CDATA   "\0"
+  *     >  */
+
+<ROOT_RadialSlider,S_Group_2,S_Group_1,S_Group>"<RadialSlider"{s} {
+  A_RadialSlider_id = "none";
+  A_RadialSlider_visible = "true";
+  A_RadialSlider_x = "\0";
+  A_RadialSlider_y = "\0";
+  A_RadialSlider_lefttop = "lefttop";
+  A_RadialSlider_rightbottom = "lefttop";
+  A_RadialSlider_sequence = NULL;
+  A_RadialSlider_nbimages = NULL;
+  A_RadialSlider_minangle = "\0";
+  A_RadialSlider_maxangle = "360";
+  A_RadialSlider_value = "none";
+  A_RadialSlider_tooltiptext = "\0";
+  A_RadialSlider_help = "\0";
+  ENTER(AL_RadialSlider);
+}
+
+<AL_RadialSlider>{
+ "id"{Eq}\' ENTER(VALUE1); BUFFERSET(A_RadialSlider_id);
+ "id"{Eq}\" ENTER(VALUE2); BUFFERSET(A_RadialSlider_id);
+
+ "visible"{Eq}\' ENTER(VALUE1); BUFFERSET(A_RadialSlider_visible);
+ "visible"{Eq}\" ENTER(VALUE2); BUFFERSET(A_RadialSlider_visible);
+
+ "x"{Eq}\' ENTER(VALUE1); BUFFERSET(A_RadialSlider_x);
+ "x"{Eq}\" ENTER(VALUE2); BUFFERSET(A_RadialSlider_x);
+
+ "y"{Eq}\' ENTER(VALUE1); BUFFERSET(A_RadialSlider_y);
+ "y"{Eq}\" ENTER(VALUE2); BUFFERSET(A_RadialSlider_y);
+
+ "lefttop"{Eq}\' ENTER(VALUE1); BUFFERSET(A_RadialSlider_lefttop);
+ "lefttop"{Eq}\" ENTER(VALUE2); BUFFERSET(A_RadialSlider_lefttop);
+
+ "rightbottom"{Eq}\' ENTER(VALUE1); BUFFERSET(A_RadialSlider_rightbottom);
+ "rightbottom"{Eq}\" ENTER(VALUE2); BUFFERSET(A_RadialSlider_rightbottom);
+
+ "sequence"{Eq}\' ENTER(VALUE1); BUFFERSET(A_RadialSlider_sequence);
+ "sequence"{Eq}\" ENTER(VALUE2); BUFFERSET(A_RadialSlider_sequence);
+
+ "nbimages"{Eq}\' ENTER(VALUE1); BUFFERSET(A_RadialSlider_nbimages);
+ "nbimages"{Eq}\" ENTER(VALUE2); BUFFERSET(A_RadialSlider_nbimages);
+
+ "minangle"{Eq}\' ENTER(VALUE1); BUFFERSET(A_RadialSlider_minangle);
+ "minangle"{Eq}\" ENTER(VALUE2); BUFFERSET(A_RadialSlider_minangle);
+
+ "maxangle"{Eq}\' ENTER(VALUE1); BUFFERSET(A_RadialSlider_maxangle);
+ "maxangle"{Eq}\" ENTER(VALUE2); BUFFERSET(A_RadialSlider_maxangle);
+
+ "value"{Eq}\' ENTER(VALUE1); BUFFERSET(A_RadialSlider_value);
+ "value"{Eq}\" ENTER(VALUE2); BUFFERSET(A_RadialSlider_value);
+
+ "tooltiptext"{Eq}\' ENTER(VALUE1); BUFFERSET(A_RadialSlider_tooltiptext);
+ "tooltiptext"{Eq}\" ENTER(VALUE2); BUFFERSET(A_RadialSlider_tooltiptext);
+
+ "help"{Eq}\' ENTER(VALUE1); BUFFERSET(A_RadialSlider_help);
+ "help"{Eq}\" ENTER(VALUE2); BUFFERSET(A_RadialSlider_help);
+
+ ">" {
+  if (!A_RadialSlider_sequence) FAIL("Required attribute `sequence' not set for `RadialSlider' element.");
+  if (!A_RadialSlider_nbimages) FAIL("Required attribute `nbimages' not set for `RadialSlider' element.");
+  LEAVE; STag_RadialSlider(); pcdata = NULL; ENTER(E_RadialSlider);
+ }
+ "/>" {
+  if (!A_RadialSlider_sequence) FAIL("Required attribute `sequence' not set for `RadialSlider' element.");
+  if (!A_RadialSlider_nbimages) FAIL("Required attribute `nbimages' not set for `RadialSlider' element.");
+  LEAVE; STag_RadialSlider(); pcdata = NULL; ETag_RadialSlider();
+  switch (YY_START) {
+   case S_Group_2: case S_Group_1: case S_Group: SET(S_Group_2); break;
+   case ROOT_RadialSlider: SET(EPILOG); break;
+  }
+ }
+ .       FAIL("Unexpected character `%c' in attribute list of RadialSlider element.", yytext[0]);
+ {Name} FAIL("Bad attribute `%s' in `RadialSlider' element start tag.",yytext);
+ <<EOF>> FAIL("EOF in attribute list of `RadialSlider' element.");
+}
+
+<E_RadialSlider>{
+ "</RadialSlider"{s}">" {
+  LEAVE;
+  ETag_RadialSlider();
+  switch (YY_START) {
+   case S_Group_2: case S_Group_1: case S_Group: SET(S_Group_2); break;
+   case ROOT_RadialSlider: SET(EPILOG); break;
+  }
+ }
+ "</"{Name}{s}">" FAIL("Unexpected end-tag `%s': `</RadialSlider>' expected.",yytext);
+ .       FAIL("Unexpected character `%c': `</RadialSlider>' expected.",yytext[0]);
+ <<EOF>> FAIL("Premature EOF: `</RadialSlider>' expected.");
+}
+
+ /*         id          CDATA   "none"
+  *         visible     CDATA   "true"
+  *         x           CDATA   "\0"
+  *         y           CDATA   "\0"
+  *         text        CDATA   ""
+  *         font        CDATA   #REQUIRED
+  *         align       CDATA   "left"
+  *         width       CDATA   "\0"
+  *         display     CDATA   "none"
+  *         scroll      CDATA   "true"
+  *         scrollspace CDATA   "20"
+  *         help        CDATA   "\0"
+  *     >  */
+
+<ROOT_Text,S_Group_2,S_Group_1,S_Group>"<Text"{s} {
+  A_Text_id = "none";
+  A_Text_visible = "true";
+  A_Text_x = "\0";
+  A_Text_y = "\0";
+  A_Text_text = NULL;
+  A_Text_font = NULL;
+  A_Text_align = "left";
+  A_Text_width = "\0";
+  A_Text_display = "none";
+  A_Text_scroll = "true";
+  A_Text_scrollspace = "20";
+  A_Text_help = "\0";
+  ENTER(AL_Text);
+}
+
+<AL_Text>{
+ "id"{Eq}\' ENTER(VALUE1); BUFFERSET(A_Text_id);
+ "id"{Eq}\" ENTER(VALUE2); BUFFERSET(A_Text_id);
+
+ "visible"{Eq}\' ENTER(VALUE1); BUFFERSET(A_Text_visible);
+ "visible"{Eq}\" ENTER(VALUE2); BUFFERSET(A_Text_visible);
+
+ "x"{Eq}\' ENTER(VALUE1); BUFFERSET(A_Text_x);
+ "x"{Eq}\" ENTER(VALUE2); BUFFERSET(A_Text_x);
+
+ "y"{Eq}\' ENTER(VALUE1); BUFFERSET(A_Text_y);
+ "y"{Eq}\" ENTER(VALUE2); BUFFERSET(A_Text_y);
+
+ "text"{Eq}\' ENTER(VALUE1); BUFFERSET(A_Text_text);
+ "text"{Eq}\" ENTER(VALUE2); BUFFERSET(A_Text_text);
+
+ "font"{Eq}\' ENTER(VALUE1); BUFFERSET(A_Text_font);
+ "font"{Eq}\" ENTER(VALUE2); BUFFERSET(A_Text_font);
+
+ "align"{Eq}\' ENTER(VALUE1); BUFFERSET(A_Text_align);
+ "align"{Eq}\" ENTER(VALUE2); BUFFERSET(A_Text_align);
+
+ "width"{Eq}\' ENTER(VALUE1); BUFFERSET(A_Text_width);
+ "width"{Eq}\" ENTER(VALUE2); BUFFERSET(A_Text_width);
+
+ "display"{Eq}\' ENTER(VALUE1); BUFFERSET(A_Text_display);
+ "display"{Eq}\" ENTER(VALUE2); BUFFERSET(A_Text_display);
+
+ "scroll"{Eq}\' ENTER(VALUE1); BUFFERSET(A_Text_scroll);
+ "scroll"{Eq}\" ENTER(VALUE2); BUFFERSET(A_Text_scroll);
+
+ "scrollspace"{Eq}\' ENTER(VALUE1); BUFFERSET(A_Text_scrollspace);
+ "scrollspace"{Eq}\" ENTER(VALUE2); BUFFERSET(A_Text_scrollspace);
+
+ "help"{Eq}\' ENTER(VALUE1); BUFFERSET(A_Text_help);
+ "help"{Eq}\" ENTER(VALUE2); BUFFERSET(A_Text_help);
+
+ ">" {
+  if (!A_Text_font) FAIL("Required attribute `font' not set for `Text' element.");
+  LEAVE; STag_Text(); pcdata = NULL; ENTER(E_Text);
+ }
+ "/>" {
+  if (!A_Text_font) FAIL("Required attribute `font' not set for `Text' element.");
+  LEAVE; STag_Text(); pcdata = NULL; ETag_Text();
+  switch (YY_START) {
+   case S_Group_2: case S_Group_1: case S_Group: SET(S_Group_2); break;
+   case ROOT_Text: SET(EPILOG); break;
+  }
+ }
+ .       FAIL("Unexpected character `%c' in attribute list of Text element.", yytext[0]);
+ {Name} FAIL("Bad attribute `%s' in `Text' element start tag.",yytext);
+ <<EOF>> FAIL("EOF in attribute list of `Text' element.");
+}
+
+<E_Text>{
+ "</Text"{s}">" {
+  LEAVE;
+  ETag_Text();
+  switch (YY_START) {
+   case S_Group_2: case S_Group_1: case S_Group: SET(S_Group_2); break;
+   case ROOT_Text: SET(EPILOG); break;
+  }
+ }
+ "</"{Name}{s}">" FAIL("Unexpected end-tag `%s': `</Text>' expected.",yytext);
+ .       FAIL("Unexpected character `%c': `</Text>' expected.",yytext[0]);
+ <<EOF>> FAIL("Premature EOF: `</Text>' expected.");
+}
+
+ /*         id          CDATA   #REQUIRED
+  *         visible     CDATA   "true"
+  *         x           CDATA   "\0"
+  *         y           CDATA   "\0"
+  *         width       CDATA   "\0"
+  *         height      CDATA   "\0"
+  *         lefttop     CDATA   "lefttop"
+  *         rightbottom CDATA   "lefttop"
+  *         font        CDATA   #REQUIRED
+  *         var         CDATA   "playlist"
+  *         fgcolor     CDATA   "#000000"
+  *         playcolor   CDATA   "#FF0000"
+  *         bgcolor1    CDATA   "#FFFFFF"
+  *         bgcolor2    CDATA   "#FFFFFF"
+  *         selcolor    CDATA   "#0000FF"
+  *         help        CDATA   "\0"
+  *     >  */
+
+<ROOT_Playlist,S_Group_2,S_Group_1,S_Group>"<Playlist"{s} {
+  A_Playlist_id = NULL;
+  A_Playlist_visible = "true";
+  A_Playlist_x = "\0";
+  A_Playlist_y = "\0";
+  A_Playlist_width = "\0";
+  A_Playlist_height = "\0";
+  A_Playlist_lefttop = "lefttop";
+  A_Playlist_rightbottom = "lefttop";
+  A_Playlist_font = NULL;
+  A_Playlist_var = "playlist";
+  A_Playlist_fgcolor = "#000000";
+  A_Playlist_playcolor = "#FF0000";
+  A_Playlist_bgcolor1 = "#FFFFFF";
+  A_Playlist_bgcolor2 = "#FFFFFF";
+  A_Playlist_selcolor = "#0000FF";
+  A_Playlist_help = "\0";
+  ENTER(AL_Playlist);
+}
+
+<AL_Playlist>{
+ "id"{Eq}\' ENTER(VALUE1); BUFFERSET(A_Playlist_id);
+ "id"{Eq}\" ENTER(VALUE2); BUFFERSET(A_Playlist_id);
+
+ "visible"{Eq}\' ENTER(VALUE1); BUFFERSET(A_Playlist_visible);
+ "visible"{Eq}\" ENTER(VALUE2); BUFFERSET(A_Playlist_visible);
+
+ "x"{Eq}\' ENTER(VALUE1); BUFFERSET(A_Playlist_x);
+ "x"{Eq}\" ENTER(VALUE2); BUFFERSET(A_Playlist_x);
+
+ "y"{Eq}\' ENTER(VALUE1); BUFFERSET(A_Playlist_y);
+ "y"{Eq}\" ENTER(VALUE2); BUFFERSET(A_Playlist_y);
+
+ "width"{Eq}\' ENTER(VALUE1); BUFFERSET(A_Playlist_width);
+ "width"{Eq}\" ENTER(VALUE2); BUFFERSET(A_Playlist_width);
+
+ "height"{Eq}\' ENTER(VALUE1); BUFFERSET(A_Playlist_height);
+ "height"{Eq}\" ENTER(VALUE2); BUFFERSET(A_Playlist_height);
+
+ "lefttop"{Eq}\' ENTER(VALUE1); BUFFERSET(A_Playlist_lefttop);
+ "lefttop"{Eq}\" ENTER(VALUE2); BUFFERSET(A_Playlist_lefttop);
+
+ "rightbottom"{Eq}\' ENTER(VALUE1); BUFFERSET(A_Playlist_rightbottom);
+ "rightbottom"{Eq}\" ENTER(VALUE2); BUFFERSET(A_Playlist_rightbottom);
+
+ "font"{Eq}\' ENTER(VALUE1); BUFFERSET(A_Playlist_font);
+ "font"{Eq}\" ENTER(VALUE2); BUFFERSET(A_Playlist_font);
+
+ "var"{Eq}\' ENTER(VALUE1); BUFFERSET(A_Playlist_var);
+ "var"{Eq}\" ENTER(VALUE2); BUFFERSET(A_Playlist_var);
+
+ "fgcolor"{Eq}\' ENTER(VALUE1); BUFFERSET(A_Playlist_fgcolor);
+ "fgcolor"{Eq}\" ENTER(VALUE2); BUFFERSET(A_Playlist_fgcolor);
+
+ "playcolor"{Eq}\' ENTER(VALUE1); BUFFERSET(A_Playlist_playcolor);
+ "playcolor"{Eq}\" ENTER(VALUE2); BUFFERSET(A_Playlist_playcolor);
+
+ "bgcolor1"{Eq}\' ENTER(VALUE1); BUFFERSET(A_Playlist_bgcolor1);
+ "bgcolor1"{Eq}\" ENTER(VALUE2); BUFFERSET(A_Playlist_bgcolor1);
+
+ "bgcolor2"{Eq}\' ENTER(VALUE1); BUFFERSET(A_Playlist_bgcolor2);
+ "bgcolor2"{Eq}\" ENTER(VALUE2); BUFFERSET(A_Playlist_bgcolor2);
+
+ "selcolor"{Eq}\' ENTER(VALUE1); BUFFERSET(A_Playlist_selcolor);
+ "selcolor"{Eq}\" ENTER(VALUE2); BUFFERSET(A_Playlist_selcolor);
+
+ "help"{Eq}\' ENTER(VALUE1); BUFFERSET(A_Playlist_help);
+ "help"{Eq}\" ENTER(VALUE2); BUFFERSET(A_Playlist_help);
+
+ ">" {
+  if (!A_Playlist_id) FAIL("Required attribute `id' not set for `Playlist' element.");
+  if (!A_Playlist_font) FAIL("Required attribute `font' not set for `Playlist' element.");
+  LEAVE; STag_Playlist(); pcdata = NULL; ENTER(S_Playlist);
+ }
+ "/>" FAIL("`Playlist' element cannot be empty.");
+ .       FAIL("Unexpected character `%c' in attribute list of Playlist element.", yytext[0]);
+ {Name} FAIL("Bad attribute `%s' in `Playlist' element start tag.",yytext);
+ <<EOF>> FAIL("EOF in attribute list of `Playlist' element.");
+}
+
+<E_Playlist>{
+ "</Playlist"{s}">" {
+  LEAVE;
+  ETag_Playlist();
+  switch (YY_START) {
+   case S_Group_2: case S_Group_1: case S_Group: SET(S_Group_2); break;
+   case ROOT_Playlist: SET(EPILOG); break;
+  }
+ }
+ "</"{Name}{s}">" FAIL("Unexpected end-tag `%s': `</Playlist>' expected.",yytext);
+ .       FAIL("Unexpected character `%c': `</Playlist>' expected.",yytext[0]);
+ <<EOF>> FAIL("Premature EOF: `</Playlist>' expected.");
+}
+
+ /* EPILOG: after the root element. */
+
+<EPILOG>{
+ .             FAIL("Unexpected character `%c' after document.", yytext[0]);
+ <<EOF>>       SUCCEED;
+}
+
+ /* CHARACTER DATA. */
+
+<IMPOSSIBLE,VALUE1,VALUE2>{
+ /* Non-defined standard entities... */
+"&amp;"  BUFFERPUTC('&');
+"&lt;"   BUFFERPUTC('<');
+"&gt;"   BUFFERPUTC('>');
+"&apos;" BUFFERPUTC('\'');
+"&quot;" BUFFERPUTC('"');
+
+ /* Character entities. */
+ "&#"[[:digit:]]+";"   BUFFERPUTC((unsigned char)atoi(yytext+2));
+ "&#x"[[:xdigit:]]+";" BUFFERPUTC((unsigned char)strtol(yytext+3,NULL,16));
+}
+
+<IMPOSSIBLE,VALUE1,VALUE2,CDATA>{
+ "\n"          |
+ "\r"          |
+ "\r\n"                |
+ "\n\r"                BUFFERPUTC('\n');
+}
+
+<IMPOSSIBLE>{
+ "<![CDATA["   ENTER(CDATA);
+ "]]>"         FAIL("Unexpected `]]>' in character data.");
+}
+
+<VALUE1>{
+ \'            BUFFERDONE; LEAVE;
+ <<EOF>>       FAIL("EOF in literal (\"'\" expected).");
+}
+
+<VALUE2>{
+ \"            BUFFERDONE; LEAVE;
+ <<EOF>>       FAIL("EOF in literal (`\"' expected).");
+}
+
+<IMPOSSIBLE,VALUE1,VALUE2>{
+ [^<&]         BUFFERPUTC(yytext[0]);
+ [<&]          FAIL("Spurious `%c' in character data.",yytext[0]);
+}
+
+<CDATA>{
+ "]]>"         LEAVE;
+ "]]"          BUFFERPUTC(yytext[0]); BUFFERPUTC(yytext[1]);
+ .             BUFFERPUTC(yytext[0]);
+ <<EOF>>       FAIL("EOF in CDATA section.");
+}
+
+ /* Impossible rules to avoid warnings from flex(1). */
+
+<INITIAL,IMPOSSIBLE>{
+ .|[\n] FAIL("The Impossible Happened: INITIAL or IMPOSSIBLE state entered?");
+}
+
+%%
+
+/* Element context stack lookup. */
+int element_context(int i)
+{
+  return (0<i && i<yy_start_stack_depth
+         ? yy_start_stack[yy_start_stack_ptr - i]
+         : 0);
+}
+
+#ifdef FLEX_DEBUG
+void print_yy_stack(char* fmt, ...)
+{
+  int i = 0; va_list ap; va_start(ap, fmt);
+  vfprintf(stderr, fmt, ap);
+  for (i=1; i<yy_start_stack_ptr; i++)
+    fprintf(stderr, "%s/", statenames[yy_start_stack[i]]);
+  fprintf(stderr,"%s\n", statenames[YY_START]);
+  va_end(ap);
+}
+
+static void debug_enter(int state, char* statename) {
+  yy_push_state(state);
+  if (yy_flex_debug) print_yy_stack("--ENTER(%s) : ",statename);
+}
+
+static void debug_leave(void) {
+  if (yy_flex_debug) print_yy_stack("--LEAVE : ");
+  yy_pop_state();
+}
+
+static void debug_set(int state, char* statename) {
+  BEGIN(state);
+  if (yy_flex_debug) print_yy_stack("--SET(%s) : ",statename);
+}
+#endif
+
+
+static int fail(const char* fmt, ...)
+{
+  va_list ap; va_start(ap, fmt);
+#ifdef FLEXML_yylineno
+  fprintf(stderr, "Invalid XML (XML input line %d, state %d): ", yylineno, YY_START);
+#else
+  fprintf(stderr, "Invalid XML (state %d): ",YY_START);
+#endif
+  vfprintf(stderr, fmt, ap);
+  fprintf(stderr, "\n");
+  va_end(ap);
+  return 1;
+}
diff --git a/modules/gui/skins2/parser/wrappers.cpp b/modules/gui/skins2/parser/wrappers.cpp
new file mode 100644 (file)
index 0000000..b6aef88
--- /dev/null
@@ -0,0 +1,304 @@
+/*****************************************************************************
+ * wrappers.cpp
+ *****************************************************************************
+ * Copyright (C) 2003 VideoLAN
+ * $Id: wrappers.cpp,v 1.1 2004/01/03 23:31:33 asmax Exp $
+ *
+ * Authors: Cyril Deguet     <asmax@via.ecp.fr>
+ *          Olivier Teulière <ipkiss@via.ecp.fr>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111, USA.
+ *****************************************************************************/
+
+#include <math.h>
+#include "wrappers.h"
+#include "parser_context.hpp"
+
+// Current DTD version
+#define SKINS_DTD_VERSION "2.0"
+
+// Local functions
+static bool ConvertBoolean( const char *value );
+static int  ConvertColor( const char *transcolor );
+
+// Useful macros
+#define DATA ((ParserContext*)pContext)->m_data
+#define WIN_ID ((ParserContext*)pContext)->m_curWindowId
+#define LAY_ID ((ParserContext*)pContext)->m_curLayoutId
+#define CUR_LIST ((ParserContext*)pContext)->m_curListId
+#define X_OFFSET ((ParserContext*)pContext)->m_xOffset
+#define Y_OFFSET ((ParserContext*)pContext)->m_yOffset
+#define LAYER ((ParserContext*)pContext)->m_curLayer
+
+
+void AddBitmap( void *pContext, char *name, char *file,
+                char *transcolor )
+{
+    const BuilderData::Bitmap bitmap( name, file,
+                                      ConvertColor( transcolor ) );
+    DATA.m_listBitmap.push_back( bitmap );
+}
+
+
+void AddEvent( void *pContext, char *name, char *event, char *key )
+{
+//    const BuilderData:: Command( name, event, key );
+}
+
+
+void AddFont( void *pContext, char *name, char *font, char *size,
+              char *color, char *italic, char *underline )
+{
+    const BuilderData::Font fontData( name, font, atoi( size ) );
+    DATA.m_listFont.push_back( fontData );
+}
+
+
+void AddThemeInfo( void *pContext, char *name, char *author,
+                   char *email, char *webpage )
+{
+    msg_Warn( ((ParserContext*)pContext)->m_pIntf,
+              "skin: %s  author: %s", name, author );
+}
+
+
+void StartWindow( void *pContext, char *name, char *x, char *y,
+                  char *visible, char *dragdrop, char *playOnDrop )
+{
+    const BuilderData::Window window( name, atoi( x ) + X_OFFSET,
+        atoi( y ) + Y_OFFSET, ConvertBoolean( visible ),
+        ConvertBoolean( dragdrop ), ConvertBoolean( playOnDrop ));
+    DATA.m_listWindow.push_back( window );
+    WIN_ID = name;
+}
+
+
+void EndWindow( void *pContext )
+{
+//    ((Builder*)pContext)->endWindow();
+}
+
+
+void StartLayout( void *pContext, char *id, char *width, char *height,
+                  char *minwidth, char *maxwidth, char *minheight,
+                  char *maxheight )
+{
+    const BuilderData::Layout layout( id, atoi( width ), atoi( height ),
+                                      atoi( minwidth ), atoi( maxwidth ),
+                                      atoi( minheight ), atoi( maxheight ),
+                                      WIN_ID );
+    DATA.m_listLayout.push_back( layout );
+    LAY_ID = id;
+    LAYER = 0;
+}
+
+
+void EndLayout( void *pContext )
+{
+//    ((Builder*)pContext)->endLayout();
+}
+
+
+void StartTheme( void *pContext, char *version, char *magnet,
+                 char *alpha, char *movealpha, char *fadetime )
+{
+    // Check the version
+    if( strcmp( version, SKINS_DTD_VERSION ) )
+    {
+        msg_Err( ((ParserContext*)pContext)->m_pIntf, "Bad theme version :"
+                 " %s (you need version %s)", version, SKINS_DTD_VERSION );
+    }
+    const BuilderData::Theme theme( atoi( magnet ),
+        atoi( alpha ), atoi( movealpha ), atoi( fadetime ) );
+    DATA.m_listTheme.push_back( theme );
+}
+
+
+void EndTheme( void *pContext )
+{
+ //   ((Builder*)pContext)->endTheme();
+}
+
+
+void StartGroup( void *pContext, char *x, char *y )
+{
+    X_OFFSET += atoi( x );
+    Y_OFFSET += atoi( y );
+    ((ParserContext*)pContext)->m_xOffsetList.push_back( atoi( x ) );
+    ((ParserContext*)pContext)->m_yOffsetList.push_back( atoi( y ) );
+}
+
+
+void EndGroup( void *pContext )
+{
+    X_OFFSET -= ((ParserContext*)pContext)->m_xOffsetList.back();
+    Y_OFFSET -= ((ParserContext*)pContext)->m_yOffsetList.back();
+    ((ParserContext*)pContext)->m_xOffsetList.pop_back();
+    ((ParserContext*)pContext)->m_yOffsetList.pop_back();
+}
+
+
+void AddAnchor( void *pContext, char *x, char *y, char *len,
+                char *priority )
+{
+    const BuilderData::Anchor anchor( atoi( x ) + X_OFFSET,
+        atoi( y ) + Y_OFFSET, atoi( len ), atoi( priority ), WIN_ID );
+    DATA.m_listAnchor.push_back( anchor );
+}
+
+
+//---------------------------------------------------------------------------
+// CONTROLS
+//---------------------------------------------------------------------------
+void AddImage( void *pContext, char *id, char *visible, char *x,
+               char *y, char *lefttop, char *rightbottom, char *image,
+               char *event, char *help )
+{
+    const BuilderData::Image imageData( id, atoi( x ) + X_OFFSET,
+        atoi( y ) + Y_OFFSET, lefttop, rightbottom, ConvertBoolean( visible ),
+        image, event, help, LAYER, WIN_ID, LAY_ID );
+    LAYER++;
+    DATA.m_listImage.push_back( imageData );
+}
+
+
+void AddRectangle( void *pContext, char *id, char *visible, char *x,
+                   char *y, char *w, char *h, char *color, char *event,
+                   char *help )
+{
+//    msg_Warn( ((Builder*)pContext)->getIntf(), "Do we _really_ need a Rectangle control?" );
+}
+
+
+void AddButton( void *pContext,
+    char *id,
+    char *x, char *y, char *lefttop, char *rightbottom,
+    char *up, char *down, char *over,
+    char *action, char *tooltiptext, char *help )
+{
+    const BuilderData::Button button( id, atoi( x ) + X_OFFSET,
+        atoi( y ) + Y_OFFSET, lefttop, rightbottom, up, down, over, action,
+        tooltiptext, help, LAYER, WIN_ID, LAY_ID );
+    LAYER++;
+    DATA.m_listButton.push_back( button );
+}
+
+
+void AddCheckBox( void *pContext, char *id,
+                  char *x, char *y, char *lefttop, char *rightbottom,
+                  char *up1, char *down1, char *over1, char *up2,
+                  char *down2, char *over2, char *state, char *action1,
+                  char *action2, char *tooltiptext1, char *tooltiptext2,
+                  char *help )
+{
+    const BuilderData::Checkbox checkbox( id, atoi( x ) + X_OFFSET,
+        atoi( y ) + Y_OFFSET, lefttop, rightbottom, up1, down1, over1, up2,
+        down2, over2, state, action1, action2, tooltiptext1, tooltiptext2,
+        help, LAYER, WIN_ID, LAY_ID );
+    LAYER++;
+    DATA.m_listCheckbox.push_back( checkbox );
+}
+
+
+void AddSlider( void *pContext, char *id, char *visible, char *x, char *y,
+                char *lefttop, char *rightbottom,
+                char *up, char *down, char *over, char *points,
+                char *thickness, char *value, char *tooltiptext, char *help )
+{
+    string newValue = value;
+    if( CUR_LIST != "" )
+    {
+        // Slider associated to a list
+        // XXX
+        newValue = "playlist.slider";
+    }
+    const BuilderData::Slider slider( id, visible, atoi( x ) + X_OFFSET,
+        atoi( y ) + Y_OFFSET, lefttop, rightbottom, up, down, over, points,
+        atoi( thickness ), newValue, tooltiptext, help, LAYER, WIN_ID, LAY_ID );
+    LAYER++;
+    DATA.m_listSlider.push_back( slider );
+}
+
+
+void AddRadialSlider( void *pContext, char *id, char *visible, char *x, char *y,
+                      char *lefttop, char *rightbottom, char *sequence,
+                      char *nbImages, char *minAngle, char *maxAngle,
+                      char *value, char *tooltiptext, char *help )
+{
+    const BuilderData::RadialSlider radial( id, visible, atoi( x ) + X_OFFSET,
+        atoi( y ) + Y_OFFSET, lefttop, rightbottom, sequence, atoi( nbImages ),
+        atof( minAngle ) * M_PI / 180, atof( maxAngle ) * M_PI / 180, value,
+        tooltiptext, help, LAYER, WIN_ID, LAY_ID );
+    LAYER++;
+    DATA.m_listRadialSlider.push_back( radial );
+}
+
+
+void AddPlaylist( void *pContext, char *id, char *visible, char *x,
+                  char *y, char *width, char *height, char *lefttop,
+                  char *rightbottom, char *font, char *var, char *fgcolor,
+                  char *playcolor, char *bgcolor1, char *bgcolor2,
+                  char *selcolor, char *help )
+{
+    const BuilderData::List listData( id, atoi( x ) + X_OFFSET,
+        atoi( y ) + Y_OFFSET, atoi( width), atoi( height ), lefttop,
+        rightbottom, font, var, ConvertColor( fgcolor ),
+        ConvertColor( playcolor ), ConvertColor( bgcolor1 ),
+        ConvertColor( bgcolor2 ), ConvertColor( selcolor ), help, LAYER,
+        WIN_ID, LAY_ID );
+    LAYER++;
+    CUR_LIST = id;
+    DATA.m_listList.push_back( listData );
+}
+
+
+void AddPlaylistEnd( void *pContext )
+{
+    CUR_LIST = "";
+}
+
+
+void AddText( void *pContext, char *id, char *visible, char *x,
+              char *y, char *text, char *font, char *align, char *width,
+              char *display, char *scroll, char *scrollspace, char *help )
+{
+    const BuilderData::Text textData( id, atoi( x ) + X_OFFSET,
+        atoi( y ) + Y_OFFSET, font, text, atoi( width ), help, LAYER, WIN_ID,
+        LAY_ID );
+    LAYER++;
+    DATA.m_listText.push_back( textData );
+}
+
+
+
+
+//---------------------------------------------------------------------------
+// Useful functions
+//---------------------------------------------------------------------------
+
+static bool ConvertBoolean( const char *value )
+{
+    return strcmp( value, "true" ) == 0;
+}
+
+
+static int ConvertColor( const char *transcolor )
+{
+    unsigned long iRed, iGreen, iBlue;
+    iRed = iGreen = iBlue = 0;
+    sscanf( transcolor, "#%2lX%2lX%2lX", &iRed, &iGreen, &iBlue );
+    return ( iRed << 16 | iGreen << 8 | iBlue );
+}
+
diff --git a/modules/gui/skins2/parser/wrappers.h b/modules/gui/skins2/parser/wrappers.h
new file mode 100644 (file)
index 0000000..641d481
--- /dev/null
@@ -0,0 +1,91 @@
+#if defined(__cplusplus)
+extern "C" {
+#endif
+
+
+//---------------------------------------------------------------------------
+// Divers
+//---------------------------------------------------------------------------
+void AddAnchor( void *pContext, char *x, char *y, char *len,
+                char *priority );
+void AddBitmap( void *pContext, char *name, char *file,
+                char *transcolor );
+void AddEvent( void *pContext, char *name, char *event, char *key );
+void AddFont( void *pContext, char *name, char *font, char *size,
+              char *color, char *italic, char *underline );
+void StartGroup( void *pContext, char *x, char *y );
+void EndGroup( void *pContext );
+
+//---------------------------------------------------------------------------
+// Theme
+//---------------------------------------------------------------------------
+void AddThemeInfo( void *pContext, char *name, char *author,
+                   char *email, char *webpage );
+void StartTheme( void *pContext, char *version, char *magnet,
+                 char *alpha, char *movealpha, char *fadetime );
+void EndTheme( void *pContext );
+
+//---------------------------------------------------------------------------
+// Window
+//---------------------------------------------------------------------------
+void StartWindow( void *pContext, char *name, char *x, char *y,
+                  char *visible, char *dragdrop, char *playOnDrop );
+void EndWindow( void *pContext );
+
+//---------------------------------------------------------------------------
+// Layout
+//---------------------------------------------------------------------------
+void StartLayout( void *pContext, char *id, char *width, char *height,
+                  char *minwidth, char *maxwidth, char *minheight,
+                  char *maxheight );
+void EndLayout( void *pContext );
+
+//---------------------------------------------------------------------------
+// Control
+//---------------------------------------------------------------------------
+void AddImage( void *pContext, char *id, char *visible, char *x,
+               char *y, char *lefttop, char *rightbottom, char *image,
+               char *event, char *help );
+
+void AddRectangle( void *pContext, char *id, char *visible, char *x,
+                   char *y, char *w, char *h, char *color, char *event,
+                   char *help );
+
+void AddButton( void *pContext, char *id,
+                char *x, char *y, char *lefttop, char *rightbottom,
+                char *up, char *down, char *over,
+                char *action, char *tooltiptext, char *help );
+
+void AddCheckBox( void *pContext, char *id,
+                  char *x, char *y, char *lefttop, char *rightbottom,
+                  char *up1, char *down1, char *over1, char *up2,
+                  char *down2, char *over2, char *state, char *action1,
+                  char *action2, char *tooltiptext1, char *tooltiptext2,
+                  char *help );
+
+void AddSlider( void *pContext, char *id, char *visible, char *x, char *y,
+                char *lefttop, char *rightbottom,
+                char *up, char *down, char *over, char *points,
+                char *thickness, char *value, char *tooltiptext, char *help );
+
+void AddRadialSlider( void *pContext, char *id, char *visible, char *x, char *y,
+                      char *lefttop, char *rightbottom, char *sequence,
+                      char *nbImages, char *minAngle, char *maxAngle,
+                      char *value, char *tooltiptext, char *help );
+
+void AddText( void *pContext, char *id, char *visible, char *x, char *y,
+              char *text, char *font, char *align, char *width, char *display,
+              char *scroll, char *scrollspace, char *help );
+
+void AddPlaylist( void *pContext, char *id, char *visible, char *x,
+              char *y, char *width, char *height, char *lefttop,
+              char *rightbottom, char *font, char *var, char *fgcolor,
+              char *playcolor, char *bgcolor1, char *bgcolor2, char *selcolor,
+              char *help );
+
+void AddPlaylistEnd( void *pContext );
+//---------------------------------------------------------------------------
+
+#if defined(__cplusplus)
+}
+#endif
diff --git a/modules/gui/skins2/src/anchor.cpp b/modules/gui/skins2/src/anchor.cpp
new file mode 100755 (executable)
index 0000000..2585782
--- /dev/null
@@ -0,0 +1,50 @@
+/*****************************************************************************
+ * anchor.cpp
+ *****************************************************************************
+ * Copyright (C) 2003 VideoLAN
+ * $Id: anchor.cpp,v 1.1 2004/01/03 23:31:33 asmax Exp $
+ *
+ * Authors: Cyril Deguet     <asmax@via.ecp.fr>
+ *          Olivier Teulière <ipkiss@via.ecp.fr>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111, USA.
+ *****************************************************************************/
+
+#include "anchor.hpp"
+
+
+bool Anchor::isHanging( const Anchor &rOther ) const
+{
+    return (getXPosAbs() == rOther.getXPosAbs() &&
+            getYPosAbs() == rOther.getYPosAbs() &&
+            m_priority > rOther.m_priority );
+}
+
+
+bool Anchor::canHang( const Anchor &rOther, int &xOffset, int &yOffset ) const
+{
+    int xDist = getXPosAbs() - (rOther.getXPosAbs() + xOffset);
+    int yDist = getYPosAbs() - (rOther.getYPosAbs() + yOffset);
+    if( m_range > 0 && xDist*xDist + yDist*yDist <= m_range*m_range )
+    {
+        xOffset = getXPosAbs() - rOther.getXPosAbs();
+        yOffset = getYPosAbs() - rOther.getYPosAbs();
+        return true;
+    }
+    else
+    {
+        return false;
+    }
+}
diff --git a/modules/gui/skins2/src/anchor.hpp b/modules/gui/skins2/src/anchor.hpp
new file mode 100644 (file)
index 0000000..4eaba98
--- /dev/null
@@ -0,0 +1,78 @@
+/*****************************************************************************
+ * anchor.hpp
+ *****************************************************************************
+ * Copyright (C) 2003 VideoLAN
+ * $Id: anchor.hpp,v 1.1 2004/01/03 23:31:33 asmax Exp $
+ *
+ * Authors: Cyril Deguet     <asmax@via.ecp.fr>
+ *          Olivier Teulière <ipkiss@via.ecp.fr>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111, USA.
+ *****************************************************************************/
+
+#ifndef ANCHOR_HPP
+#define ANCHOR_HPP
+
+#include "skin_common.hpp"
+#include "generic_window.hpp"
+
+
+/// Class for the windows anchors
+class Anchor: public SkinObject
+{
+    public:
+        Anchor( intf_thread_t *pIntf, int xPos, int yPos, int range,
+                int priority, GenericWindow &rWindow ):
+            SkinObject( pIntf ), m_xPos( xPos ), m_yPos( yPos ),
+            m_range( range ), m_priority( priority ), m_rWindow( rWindow ) {}
+        virtual ~Anchor() {}
+
+        /// Return true if the given anchor is hanged by this one
+        /// Two conditions are required:
+        ///  - the other anchor must be in position of anchoring (as defined
+        ///    by canHang())
+        ///  - the priority of the other anchor must be lower than this one's
+        bool isHanging( const Anchor &rOther ) const;
+
+        /// Return true if the other anchor, moved by the (xOffset, yOffset)
+        /// vector, is "hangable" by this one (i.e. if it is in its range of
+        /// action), else return false.
+        /// When the function returns true, the xOffset and yOffset parameters
+        /// are modified to indicate the position that the other anchor would
+        /// take if hanged by this one (this position is calculated to minimize
+        /// the difference with the old xOffset and yOffset, so that the window
+        /// doesn't "jump" in a strange way).
+        bool canHang( const Anchor &rOther, int &xOffset, int &yOffset ) const;
+
+        // Getters
+        int getXPosAbs() const { return (m_xPos + m_rWindow.getLeft()); }
+        int getYPosAbs() const { return (m_yPos + m_rWindow.getTop()); }
+
+    private:
+        /// Coordinates relative to the window
+        int m_xPos, m_yPos;
+
+        /// Range of action
+        int m_range;
+
+        /// Priority
+        int m_priority;
+
+        /// Parent window
+        GenericWindow &m_rWindow;
+};
+
+
+#endif
diff --git a/modules/gui/skins2/src/dialogs.cpp b/modules/gui/skins2/src/dialogs.cpp
new file mode 100644 (file)
index 0000000..04a9b08
--- /dev/null
@@ -0,0 +1,260 @@
+/*****************************************************************************
+ * dialogs.cpp
+ *****************************************************************************
+ * Copyright (C) 2003 VideoLAN
+ * $Id: dialogs.cpp,v 1.1 2004/01/03 23:31:33 asmax Exp $
+ *
+ * Authors: Cyril Deguet     <asmax@via.ecp.fr>
+ *          Olivier Teulière <ipkiss@via.ecp.fr>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111, USA.
+ *****************************************************************************/
+
+#include "dialogs.hpp"
+#include "../commands/async_queue.hpp"
+#include "../commands/cmd_change_skin.hpp"
+#include "../commands/cmd_quit.hpp"
+
+
+/// Callback called when a new skin is chosen
+static void showChangeSkinCB( intf_dialog_args_t *pArg )
+{
+    intf_thread_t *pIntf = (intf_thread_t *)pArg->p_arg;
+
+    if( pArg->i_results )
+    {
+        if( pArg->psz_results[0] )
+        {
+            // Create a change skin command
+            CmdChangeSkin *pCmd = new CmdChangeSkin( pIntf,
+                                                     pArg->psz_results[0] );
+
+            // Push the command in the asynchronous command queue
+            AsyncQueue *pQueue = AsyncQueue::instance( pIntf );
+            pQueue->remove( "resize" );
+            pQueue->push( CmdGenericPtr( pCmd ) );
+        }
+    }
+    else if( !pIntf->p_sys->p_theme )
+    {
+        // If no theme is already loaded, it's time to quit!
+        CmdQuit *pCmd = new CmdQuit( pIntf );
+        AsyncQueue *pQueue = AsyncQueue::instance( pIntf );
+        pQueue->push( CmdGenericPtr( pCmd ) );
+    }
+}
+
+
+/// Callback called when the popup menu is requested
+static int PopupMenuCB( vlc_object_t *p_this, const char *psz_variable,
+                        vlc_value_t old_val, vlc_value_t new_val, void *param )
+{
+    Dialogs *p_dialogs = (Dialogs *)param;
+    p_dialogs->showPopupMenu( new_val.b_bool );
+
+    return VLC_SUCCESS;
+}
+
+
+Dialogs::Dialogs( intf_thread_t *pIntf ):
+    SkinObject( pIntf ), m_pProvider( NULL ), m_pModule( NULL )
+{
+}
+
+
+Dialogs::~Dialogs()
+{
+    if( m_pProvider && m_pModule )
+    {
+        // Detach the dialogs provider from its parent interface
+        vlc_object_detach( m_pProvider );
+
+        module_Unneed( m_pProvider, m_pModule );
+        vlc_object_destroy( m_pProvider );
+    }
+
+    /* Unregister callbacks */
+    var_DelCallback( getIntf()->p_sys->p_playlist, "intf-popupmenu",
+                     PopupMenuCB, this );
+}
+
+
+Dialogs *Dialogs::instance( intf_thread_t *pIntf )
+{
+    if( ! pIntf->p_sys->p_dialogs )
+    {
+        Dialogs *pDialogs = new Dialogs( pIntf );
+        if( pDialogs->init() )
+        {
+            // Initialization succeeded
+            pIntf->p_sys->p_dialogs = pDialogs;
+        }
+        else
+        {
+            // Initialization failed
+            delete pDialogs;
+        }
+    }
+    return pIntf->p_sys->p_dialogs;
+}
+
+
+void Dialogs::destroy( intf_thread_t *pIntf )
+{
+    if( pIntf->p_sys->p_dialogs )
+    {
+        delete pIntf->p_sys->p_dialogs;
+        pIntf->p_sys->p_dialogs = NULL;
+    }
+}
+
+
+bool Dialogs::init()
+{
+    // Allocate descriptor
+    m_pProvider = (intf_thread_t *)vlc_object_create( getIntf(),
+                                                      VLC_OBJECT_INTF );
+    if( m_pProvider == NULL )
+    {
+        msg_Err( getIntf(), "out of memory" );
+        return false;
+    }
+
+    m_pModule = module_Need( m_pProvider, "dialogs provider", NULL );
+    if( m_pModule == NULL )
+    {
+        msg_Err( getIntf(), "No suitable dialogs provider found" );
+        vlc_object_destroy( m_pProvider );
+        m_pProvider = NULL;
+        return false;
+    }
+
+    // Attach the dialogs provider to its parent interface
+    vlc_object_attach( m_pProvider, getIntf() );
+
+    // Initialize dialogs provider
+    // (returns as soon as initialization is done)
+    if( m_pProvider->pf_run )
+    {
+        m_pProvider->pf_run( m_pProvider );
+    }
+
+    /* Register callback for the intf-popupmenu variable */
+    var_AddCallback( getIntf()->p_sys->p_playlist, "intf-popupmenu",
+                     PopupMenuCB, this );
+
+    return true;
+}
+
+
+void Dialogs::showChangeSkin()
+{
+    if( m_pProvider && m_pProvider->pf_show_dialog )
+    {
+        intf_dialog_args_t *p_arg =
+            (intf_dialog_args_t *)malloc( sizeof(intf_dialog_args_t) );
+        memset( p_arg, 0, sizeof(intf_dialog_args_t) );
+
+        p_arg->b_blocking = false;
+
+        p_arg->psz_title = strdup( _("Open a skin file") );
+        p_arg->psz_extensions =
+            strdup( "Skin files (*.vlt)|*.vlt|Skin files (*.xml)|*.xml|" );
+
+        p_arg->p_arg = getIntf();
+        p_arg->pf_callback = showChangeSkinCB;
+
+        m_pProvider->pf_show_dialog( m_pProvider, INTF_DIALOG_FILE_GENERIC,
+                                     0, p_arg );
+    }
+}
+
+
+void Dialogs::showFileSimple( bool play )
+{
+    if( m_pProvider && m_pProvider->pf_show_dialog )
+    {
+        m_pProvider->pf_show_dialog( m_pProvider, INTF_DIALOG_FILE_SIMPLE,
+                                     (int)play, 0 );
+    }
+}
+
+
+void Dialogs::showFile( bool play )
+{
+    if( m_pProvider && m_pProvider->pf_show_dialog )
+    {
+        m_pProvider->pf_show_dialog( m_pProvider, INTF_DIALOG_FILE,
+                                     (int)play, 0 );
+    }
+}
+
+
+void Dialogs::showDisc( bool play )
+{
+    if( m_pProvider && m_pProvider->pf_show_dialog )
+    {
+        m_pProvider->pf_show_dialog( m_pProvider, INTF_DIALOG_DISC,
+                                     (int)play, 0 );
+    }
+}
+
+
+void Dialogs::showNet( bool play )
+{
+    if( m_pProvider && m_pProvider->pf_show_dialog )
+    {
+        m_pProvider->pf_show_dialog( m_pProvider, INTF_DIALOG_NET,
+                                     (int)play, 0 );
+    }
+}
+
+
+void Dialogs::showMessages()
+{
+    if( m_pProvider && m_pProvider->pf_show_dialog )
+    {
+        m_pProvider->pf_show_dialog( m_pProvider, INTF_DIALOG_MESSAGES, 0, 0 );
+    }
+}
+
+
+void Dialogs::showPrefs()
+{
+    if( m_pProvider && m_pProvider->pf_show_dialog )
+    {
+        m_pProvider->pf_show_dialog( m_pProvider, INTF_DIALOG_PREFS, 0, 0 );
+    }
+}
+
+
+void Dialogs::showFileInfo()
+{
+   if( m_pProvider && m_pProvider->pf_show_dialog )
+    {
+       m_pProvider->pf_show_dialog( m_pProvider, INTF_DIALOG_FILEINFO, 0, 0 );
+    }
+}
+
+
+void Dialogs::showPopupMenu( bool bShow )
+{
+    if( m_pProvider && m_pProvider->pf_show_dialog )
+    {
+        m_pProvider->pf_show_dialog( m_pProvider, INTF_DIALOG_POPUPMENU,
+                                     (int)bShow, 0 );
+    }
+}
+
diff --git a/modules/gui/skins2/src/dialogs.hpp b/modules/gui/skins2/src/dialogs.hpp
new file mode 100644 (file)
index 0000000..e8ffcbd
--- /dev/null
@@ -0,0 +1,99 @@
+/*****************************************************************************
+ * dialogs.hpp
+ *****************************************************************************
+ * Copyright (C) 2003 VideoLAN
+ * $Id: dialogs.hpp,v 1.1 2004/01/03 23:31:33 asmax Exp $
+ *
+ * Authors: Cyril Deguet     <asmax@via.ecp.fr>
+ *          Olivier Teulière <ipkiss@via.ecp.fr>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111, USA.
+ *****************************************************************************/
+
+#ifndef DIALOGS_HPP
+#define DIALOGS_HPP
+
+#include "skin_common.hpp"
+#include <string>
+
+
+// Dialogs provider
+class Dialogs: public SkinObject
+{
+    public:
+        /// Get the instance of Dialogs.
+        /// Returns NULL if initialization failed
+        static Dialogs *instance( intf_thread_t *pIntf );
+
+        /// Delete the instance of Dialogs
+        static void destroy( intf_thread_t *pIntf );
+
+        /// Show the Change Skin dialog.
+        void showChangeSkin();
+
+        /// Show the Quick Open File dialog.
+        /// If play is false, just add the item in the playlist
+        void showFileSimple( bool play );
+
+        /// Show the Open File dialog.
+        /// If play is false, just add the item in the playlist
+        void showFile( bool play );
+
+        /// Show the Open Disc dialog
+        /// If play is false, just add the item in the playlist
+        void showDisc( bool play );
+
+        /// Show the Open Network Stream dialog
+        /// If play is false, just add the item in the playlist
+        void showNet( bool play );
+
+        /// Show the Messages dialog
+        void showMessages();
+
+        /// Show the Preferences dialog
+        void showPrefs();
+
+        /// Show the FileInfo dialog
+        void showFileInfo();
+
+        /// Show the popup menu
+        void showPopupMenu( bool bShow );
+
+        // XXX: This is a kludge! In fact, the file name retrieved when
+        // changing the skin should be returned directly to the command, but
+        // the dialog provider mechanism doesn't allow it.
+        /// Store temporarily a file name
+        void setThemeFile( const string &themeFile ) { m_theme = themeFile; }
+        /// Get a previously saved file name
+        const string &getThemeFile() const { return m_theme; }
+
+    private:
+        // Private because it's a singleton
+        Dialogs( intf_thread_t *pIntf );
+        ~Dialogs();
+
+        /// Initialization method
+        bool init();
+
+        /// Dialogs provider module
+        intf_thread_t *m_pProvider;
+        module_t *m_pModule;
+
+        /// Name of a theme file, obtained via the ChangeSkin dialog
+        string m_theme;
+};
+
+
+#endif
diff --git a/modules/gui/skins2/src/ft2_bitmap.cpp b/modules/gui/skins2/src/ft2_bitmap.cpp
new file mode 100644 (file)
index 0000000..ff9d96c
--- /dev/null
@@ -0,0 +1,71 @@
+/*****************************************************************************
+ * ft2_bitmap.cpp
+ *****************************************************************************
+ * Copyright (C) 2003 VideoLAN
+ * $Id: ft2_bitmap.cpp,v 1.1 2004/01/03 23:31:33 asmax Exp $
+ *
+ * Authors: Cyril Deguet     <asmax@via.ecp.fr>
+ *          Olivier Teulière <ipkiss@via.ecp.fr>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111, USA.
+ *****************************************************************************/
+
+#include "ft2_bitmap.hpp"
+
+
+FT2Bitmap::FT2Bitmap( intf_thread_t *pIntf, int width, int height ):
+    GenericBitmap( pIntf ), m_width( width ), m_height( height )
+{
+    // Allocate memory for the buffer
+    m_pData = new uint8_t[m_height * m_width * 4];
+    memset( m_pData, 0, m_height * m_width * 4 );
+}
+
+
+FT2Bitmap::~FT2Bitmap()
+{
+    if( m_pData )
+    {
+        delete[] m_pData;
+    }
+}
+
+
+void FT2Bitmap::draw( const FT_Bitmap &rBitmap, int left, int top,
+                      uint32_t color )
+{
+    uint8_t *pBuf = rBitmap.buffer;
+
+    // Calculate colors
+    uint8_t blue = color & 0xff;
+    uint8_t green = (color >> 8) & 0xff;
+    uint8_t red = (color >> 16) & 0xff;
+
+    for( int y = top; y < top + rBitmap.rows; y++ )
+    {
+        uint8_t *pData = m_pData + 4 * (m_width * y + left);
+        for( int x = left; x < left + rBitmap.width; x++ )
+        {
+            // The buffer in FT_Bitmap contains alpha values
+            uint8_t val = *(pBuf++);
+            *(pData++) = blue;
+            *(pData++) = green;
+            *(pData++) = red;
+            *(pData++) = val;
+        }
+    }
+}
+
+
diff --git a/modules/gui/skins2/src/ft2_bitmap.hpp b/modules/gui/skins2/src/ft2_bitmap.hpp
new file mode 100644 (file)
index 0000000..b925725
--- /dev/null
@@ -0,0 +1,65 @@
+/*****************************************************************************
+ * ft2_bitmap.hpp
+ *****************************************************************************
+ * Copyright (C) 2003 VideoLAN
+ * $Id: ft2_bitmap.hpp,v 1.1 2004/01/03 23:31:33 asmax Exp $
+ *
+ * Authors: Cyril Deguet     <asmax@via.ecp.fr>
+ *          Olivier Teulière <ipkiss@via.ecp.fr>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111, USA.
+ *****************************************************************************/
+
+#ifndef FT2_BITMAP_HPP
+#define FT2_BITMAP_HPP
+
+#include <ft2build.h>
+#include FT_FREETYPE_H
+
+#include "generic_bitmap.hpp"
+
+
+/// Class for rendering freetype glyphs on a bitmap
+class FT2Bitmap: public GenericBitmap
+{
+    public:
+        /// Create an empty bitmap
+        FT2Bitmap( intf_thread_t *pIntf, int width, int height );
+
+        virtual ~FT2Bitmap();
+
+        /// Get the width of the bitmap
+        virtual int getWidth() const { return m_width; }
+
+        /// Get the heighth of the bitmap
+        virtual int getHeight() const { return m_height; }
+
+        /// Get a linear buffer containing the image data.
+        /// Each pixel is stored in 4 bytes in the order B,G,R,A
+        virtual uint8_t *getData() const { return m_pData; }
+
+        /// Render a glyph on the bitmap at the given position
+        void draw( const FT_Bitmap &rBitmap, int left, int top,
+                   uint32_t color );
+
+    private:
+        /// Bitmap size
+        int m_width, m_height;
+        /// Image data buffer
+        uint8_t *m_pData;
+};
+
+
+#endif
diff --git a/modules/gui/skins2/src/ft2_font.cpp b/modules/gui/skins2/src/ft2_font.cpp
new file mode 100644 (file)
index 0000000..ef968e4
--- /dev/null
@@ -0,0 +1,259 @@
+/*****************************************************************************
+ * ft2_font.cpp
+ *****************************************************************************
+ * Copyright (C) 2003 VideoLAN
+ * $Id: ft2_font.cpp,v 1.1 2004/01/03 23:31:33 asmax Exp $
+ *
+ * Authors: Cyril Deguet     <asmax@via.ecp.fr>
+ *          Olivier Teulière <ipkiss@via.ecp.fr>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111, USA.
+ *****************************************************************************/
+
+#include "ft2_font.hpp"
+#include "ft2_bitmap.hpp"
+#include "../utils/ustring.hpp"
+
+
+FT2Font::FT2Font( intf_thread_t *pIntf, const string &rName, int size ):
+    GenericFont( pIntf ), m_name( rName ), m_buffer( NULL ), m_size( size )
+{
+}
+
+
+FT2Font::~FT2Font()
+{
+
+    FT_Done_Glyph( m_dotGlyph );
+    FT_Done_Face( m_face );
+    FT_Done_FreeType( m_lib );
+    if( m_buffer )
+    {
+        free( m_buffer );
+    }
+}
+
+
+bool FT2Font::init()
+{
+    int err;
+
+    // Initalise libfreetype
+    if( FT_Init_FreeType( &m_lib ) )
+    {
+        msg_Err( getIntf(), "Failed to initalize libfreetype" );
+        return false;
+    }
+
+    // Open the font
+    FILE *file = fopen( m_name.c_str(), "rb" );
+    if( !file )
+    {
+        msg_Err( getIntf(), "Unable to open the font %s", m_name.c_str() );
+        return false;
+    }
+    // Get the file size
+    fseek( file, 0, SEEK_END );
+    int size = ftell( file );
+    rewind( file );
+    // Allocate the buffer
+    m_buffer = malloc( size );
+    if( !m_buffer )
+    {
+        msg_Err( getIntf(), "Not enough memory for the font %s",
+                 m_name.c_str() );
+        return false;
+    }
+    // Read the font data
+    fread( m_buffer, size, 1, file );
+    fclose( file );
+
+    // Load the font from the buffer
+    err = FT_New_Memory_Face( m_lib, (const FT_Byte*)m_buffer, size, 0,
+                              &m_face );
+    if ( err == FT_Err_Unknown_File_Format )
+    {
+        msg_Err( getIntf(), "Unsupported font format (%s)", m_name.c_str() );
+        return false;
+    }
+    else if ( err )
+    {
+        msg_Err( getIntf(), "Error opening font (%s)", m_name.c_str() );
+        return false;
+    }
+
+    // Select the charset
+    if( FT_Select_Charmap( m_face, ft_encoding_unicode ) )
+    {
+        msg_Err( getIntf(), "Font has no UNICODE table (%s)", m_name.c_str() );
+        return false;
+    }
+
+    // Set the pixel size
+    if( FT_Set_Pixel_Sizes( m_face, 0, m_size ) )
+    {
+        msg_Warn( getIntf(), "Cannot set a pixel size of %d (%s)", m_size,
+                  m_name.c_str() );
+    }
+
+    // Get the font metrucs
+    m_height = m_face->size->metrics.height >> 6;
+    m_ascender = m_face->size->metrics.ascender >> 6;
+    m_descender = m_face->size->metrics.descender >> 6;
+
+    // Render the '.' symbol and compute its size
+    m_dotIndex = FT_Get_Char_Index( m_face, '.' );
+    FT_Load_Glyph( m_face, m_dotIndex, FT_LOAD_DEFAULT );
+    FT_Get_Glyph( m_face->glyph, &m_dotGlyph );
+    FT_BBox dotSize;
+    FT_Glyph_Get_CBox( m_dotGlyph, ft_glyph_bbox_pixels, &dotSize );
+    m_dotWidth = dotSize.xMax - dotSize.xMin;
+    m_dotAdvance = m_face->glyph->advance.x >> 6;
+    FT_Glyph_To_Bitmap( &m_dotGlyph, ft_render_mode_normal, NULL, 1 );
+
+    return true;
+}
+
+
+GenericBitmap *FT2Font::drawString( const UString &rString, uint32_t color,
+                                    int maxWidth ) const
+{
+    int err;
+    uint32_t code;
+    int n;
+    int penX = 0;
+    int width1 = 0, width2 = 0;
+    int yMin = 0, yMax = 0;
+    uint32_t *pString = (uint32_t*)rString.u_str();
+
+    // Get the length of the string
+    int len = rString.length();
+
+    // Array of glyph bitmaps and position
+    FT_Glyph glyphs[len];
+    int pos[len];
+
+    // Does the font support kerning ?
+    FT_Bool useKerning = FT_HAS_KERNING( m_face );
+    int previous = 0;
+
+    // Index of the last glyph when the text is truncated with trailing ...
+    int maxIndex = 0;
+    // Position of the first trailing dot
+    int firstDotX = 0;
+
+    // First, render all the glyphs
+    for( n = 0; n < len; n++ )
+    {
+        code = *(pString++);
+        // Load the glyph
+        int glyphIndex = FT_Get_Char_Index( m_face, code );
+        err = FT_Load_Glyph( m_face, glyphIndex, FT_LOAD_DEFAULT );
+        err = FT_Get_Glyph( m_face->glyph, &glyphs[n] );
+
+        // Retrieve kerning distance and move pen position
+        if( useKerning && previous && glyphIndex )
+        {
+            FT_Vector delta;
+            FT_Get_Kerning( m_face, previous, glyphIndex,
+                            ft_kerning_default, &delta );
+            penX += delta.x >> 6;
+        }
+
+        // Get the glyph size
+        FT_BBox glyphSize;
+        FT_Glyph_Get_CBox( glyphs[n], ft_glyph_bbox_pixels, &glyphSize );
+
+        // Render the glyph
+        err = FT_Glyph_To_Bitmap( &glyphs[n], ft_render_mode_normal, NULL, 1 );
+
+        pos[n] = penX;
+        width1 = penX + glyphSize.xMax - glyphSize.xMin;
+        yMin = __MIN( yMin, glyphSize.yMin );
+        yMax = __MAX( yMax, glyphSize.yMax );
+
+        // Next position
+        penX += m_face->glyph->advance.x >> 6;
+
+        // Save glyph index
+        previous = glyphIndex;
+
+        if( maxWidth != -1 )
+        {
+            // Check if the truncated text with the '...' fit in the maxWidth
+            int curX = penX;
+            if( useKerning )
+            {
+                FT_Vector delta;
+                FT_Get_Kerning( m_face, glyphIndex, m_dotIndex,
+                                ft_kerning_default, &delta );
+                curX += delta.x >> 6;
+            }
+            if( curX + 2 * m_dotAdvance + m_dotWidth < maxWidth )
+            {
+                width2 = curX + 2 * m_dotAdvance + m_dotWidth;
+                maxIndex++;
+                firstDotX = curX;
+            }
+        }
+        else
+        {
+            // No check
+            width2 = width1;
+            maxIndex++;
+        }
+
+        // Stop here if the text is too large
+        if( maxWidth != -1 && width1 > maxWidth )
+        {
+            break;
+        }
+    }
+
+    // Adjust the size for vertical padding
+    yMax == __MAX( yMax, m_ascender );
+    yMin == __MIN( yMin, m_descender );
+
+    // Create the bitmap
+    FT2Bitmap *pBmp = new FT2Bitmap( getIntf(), __MIN( width1, width2 ),
+                                     yMax - yMin );
+
+    // Draw the glyphs on the bitmap
+    for( n = 0; n < maxIndex; n++ )
+    {
+        FT_BitmapGlyphRec *pBmpGlyph = (FT_BitmapGlyphRec*)glyphs[n];
+        // Draw the glyph on the bitmap
+        pBmp->draw( pBmpGlyph->bitmap, pos[n], yMax - pBmpGlyph->top, color );
+
+        // Free the glyph
+        FT_Done_Glyph( glyphs[n] );
+    }
+    // Draw the trailing dots if the text is truncated
+    if( maxIndex < len )
+    {
+        int penX = firstDotX;
+        FT_BitmapGlyphRec *pBmpGlyph = (FT_BitmapGlyphRec*)m_dotGlyph;
+        for( n = 0; n < 3; n++ )
+        {
+            // Draw the glyph on the bitmap
+            pBmp->draw( pBmpGlyph->bitmap, penX, yMax - pBmpGlyph->top,
+                        color );
+            penX += m_dotAdvance;
+        }
+    }
+
+    return pBmp;
+}
+
diff --git a/modules/gui/skins2/src/ft2_font.hpp b/modules/gui/skins2/src/ft2_font.hpp
new file mode 100644 (file)
index 0000000..b1b32a3
--- /dev/null
@@ -0,0 +1,80 @@
+/*****************************************************************************
+ * ft2_font.hpp
+ *****************************************************************************
+ * Copyright (C) 2003 VideoLAN
+ * $Id: ft2_font.hpp,v 1.1 2004/01/03 23:31:33 asmax Exp $
+ *
+ * Authors: Cyril Deguet     <asmax@via.ecp.fr>
+ *          Olivier Teulière <ipkiss@via.ecp.fr>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111, USA.
+ *****************************************************************************/
+
+#ifndef FT2_FONT_HPP
+#define FT2_FONT_HPP
+
+#include <ft2build.h>
+#include FT_FREETYPE_H
+#include FT_GLYPH_H
+#include <string>
+
+#include "generic_font.hpp"
+
+class UString;
+
+
+/// Freetype2 font
+class FT2Font: public GenericFont
+{
+    public:
+        FT2Font( intf_thread_t *pIntf, const string &rName, int size );
+        virtual ~FT2Font();
+
+        /// Initalize the object. Returns false if it failed
+        virtual bool init();
+
+        /// Render a string on a bitmap.
+        /// If maxWidth != -1, the text is truncated with '...'
+        /// rAscent is filled with the maximum ascent of the glyphs in
+        /// the string (for explanations, see:
+        /// http://www.freetype.org/freetype2/docs/tutorial/step2.html)
+        virtual GenericBitmap *drawString( const UString &rString,
+            uint32_t color, int maxWidth = -1 ) const;
+
+        /// Get the text height
+        virtual int getSize() const { return m_height; }
+
+    private:
+        /// File name
+        const string m_name;
+        /// Buffer to store the font
+        void *m_buffer;
+        /// Pixel size of the font
+        int m_size;
+        /// Handle to FT library
+        FT_Library m_lib;
+        /// Font face
+        FT_Face m_face;
+        /// Font metrics
+        int m_height, m_ascender, m_descender;
+        /// Index, glyph, width and advance of the dot symbol
+        int m_dotIndex;
+        FT_Glyph m_dotGlyph;
+        int m_dotWidth;
+        int m_dotAdvance;
+};
+
+
+#endif
diff --git a/modules/gui/skins2/src/generic_bitmap.hpp b/modules/gui/skins2/src/generic_bitmap.hpp
new file mode 100644 (file)
index 0000000..b88b1ac
--- /dev/null
@@ -0,0 +1,54 @@
+/*****************************************************************************
+ * generic_bitmap.hpp
+ *****************************************************************************
+ * Copyright (C) 2003 VideoLAN
+ * $Id: generic_bitmap.hpp,v 1.1 2004/01/03 23:31:33 asmax Exp $
+ *
+ * Authors: Cyril Deguet     <asmax@via.ecp.fr>
+ *          Olivier Teulière <ipkiss@via.ecp.fr>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111, USA.
+ *****************************************************************************/
+
+#ifndef GENERIC_BITMAP_HPP
+#define GENERIC_BITMAP_HPP
+
+#include "skin_common.hpp"
+#include "../utils/pointer.hpp"
+
+
+/// base class for bitmaps
+class GenericBitmap: public SkinObject
+{
+    public:
+        virtual ~GenericBitmap() {}
+
+        /// Get the width of the bitmap
+        virtual int getWidth() const = 0;
+
+        /// Get the heighth of the bitmap
+        virtual int getHeight() const = 0;
+
+        /// Get a linear buffer containing the image data.
+        /// Each pixel is stored in 4 bytes in the order B,G,R,A
+        virtual uint8_t *getData() const = 0;
+
+    protected:
+        GenericBitmap( intf_thread_t *pIntf ): SkinObject( pIntf ) {}
+};
+
+typedef CountedPtr<GenericBitmap> GenericBitmapPtr;
+
+#endif
diff --git a/modules/gui/skins2/src/generic_font.hpp b/modules/gui/skins2/src/generic_font.hpp
new file mode 100644 (file)
index 0000000..b67faaf
--- /dev/null
@@ -0,0 +1,61 @@
+/*****************************************************************************
+ * generic_font.hpp
+ *****************************************************************************
+ * Copyright (C) 2003 VideoLAN
+ * $Id: generic_font.hpp,v 1.1 2004/01/03 23:31:33 asmax Exp $
+ *
+ * Authors: Cyril Deguet     <asmax@via.ecp.fr>
+ *          Olivier Teulière <ipkiss@via.ecp.fr>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111, USA.
+ *****************************************************************************/
+
+#ifndef GENERIC_FONT_HPP
+#define GENERIC_FONT_HPP
+
+#include "skin_common.hpp"
+#include "../utils/pointer.hpp"
+
+class GenericBitmap;
+class UString;
+
+/// Base class for fonts
+class GenericFont: public SkinObject
+{
+    public:
+        virtual ~GenericFont() {}
+
+        virtual bool init() = 0;
+
+        /// Render a string on a bitmap.
+        /// If maxWidth != -1, the text is truncated with '...'
+        /// rAscent is filled with the maximum ascent of the glyphs in
+        /// the string (for explanations, see:
+        /// http://www.freetype.org/freetype2/docs/tutorial/step2.html)
+        virtual GenericBitmap *drawString( const UString &rString,
+            uint32_t color, int maxWidth = -1 ) const = 0;
+
+
+        /// Get the font size
+        virtual int getSize() const = 0;
+
+    protected:
+        GenericFont( intf_thread_t *pIntf ): SkinObject( pIntf ) {}
+};
+
+typedef CountedPtr<GenericFont> GenericFontPtr;
+
+
+#endif
diff --git a/modules/gui/skins2/src/generic_layout.cpp b/modules/gui/skins2/src/generic_layout.cpp
new file mode 100644 (file)
index 0000000..5e3ac49
--- /dev/null
@@ -0,0 +1,199 @@
+/*****************************************************************************
+ * generic_layout.cpp
+ *****************************************************************************
+ * Copyright (C) 2003 VideoLAN
+ * $Id: generic_layout.cpp,v 1.1 2004/01/03 23:31:33 asmax Exp $
+ *
+ * Authors: Cyril Deguet     <asmax@via.ecp.fr>
+ *          Olivier Teulière <ipkiss@via.ecp.fr>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111, USA.
+ *****************************************************************************/
+
+#include "generic_layout.hpp"
+#include "generic_window.hpp"
+#include "os_factory.hpp"
+#include "os_graphics.hpp"
+#include "../controls/ctrl_generic.hpp"
+
+
+GenericLayout::GenericLayout( intf_thread_t *pIntf, int width, int height,
+                              int minWidth, int maxWidth, int minHeight,
+                              int maxHeight ):
+    SkinObject( pIntf ), m_pWindow( NULL ), m_width( width ),
+    m_height( height ), m_minWidth( minWidth ), m_maxWidth( maxWidth ),
+    m_minHeight( minHeight ), m_maxHeight( maxHeight )
+{
+    // Get the OSFactory
+    OSFactory *pOsFactory = OSFactory::instance( getIntf() );
+    // Create the graphics buffer
+    m_pImage = pOsFactory->createOSGraphics( width, height );
+}
+
+
+GenericLayout::~GenericLayout()
+{
+    if( m_pImage )
+    {
+        delete m_pImage;
+    }
+}
+
+
+void GenericLayout::setWindow( GenericWindow *pWindow )
+{
+    m_pWindow = pWindow;
+}
+
+
+void GenericLayout::onControlCapture( const CtrlGeneric &rCtrl )
+{
+    // Just forward the request to the window
+    GenericWindow *pWindow = getWindow();
+    if( pWindow )
+    {
+        pWindow->onControlCapture( rCtrl );
+    }
+}
+
+
+void GenericLayout::onControlRelease( const CtrlGeneric &rCtrl )
+{
+    // Just forward the request to the window
+    GenericWindow *pWindow = getWindow();
+    if( pWindow )
+    {
+        pWindow->onControlRelease( rCtrl );
+    }
+}
+
+
+void GenericLayout::addControl( CtrlGeneric *pControl,
+                              const Position &rPosition, int layer )
+{
+    if( pControl )
+    {
+        // Associate this layout to the control
+        pControl->setLayout( this, rPosition );
+
+        // Draw the control
+        pControl->draw( *m_pImage, rPosition.getLeft(), rPosition.getTop() );
+
+        // Add the control in the list.
+        // This list must remain sorted by layer order 
+        list<LayeredControl>::iterator it;
+        for( it = m_controlList.begin(); it != m_controlList.end(); it++ )
+        {
+            if( layer < (*it).m_layer )
+            {
+                m_controlList.insert( it, LayeredControl( pControl, layer ) );
+                break;
+            }
+        }
+        // If this control is in front of all the previous ones
+        if( it == m_controlList.end() )
+        {
+            m_controlList.push_back( LayeredControl( pControl, layer ) );
+        }
+    }
+    else
+    {
+        msg_Dbg( getIntf(), "Adding NULL control in the layout" );
+    }
+}
+
+
+const list<LayeredControl> &GenericLayout::getControlList() const
+{
+    return m_controlList;
+}
+
+
+void GenericLayout::onControlUpdate( const CtrlGeneric &rCtrl )
+{
+    refreshAll();
+}
+
+
+void GenericLayout::resize( int width, int height )
+{
+    if( width == m_width && height == m_height )
+    {
+        return;
+    }
+
+    // Update the window size
+    m_width = width;
+    m_height = height;
+
+    // Recreate a new image
+    if( m_pImage )
+    {
+        delete m_pImage;
+        OSFactory *pOsFactory = OSFactory::instance( getIntf() );
+        m_pImage = pOsFactory->createOSGraphics( width, height );
+    }
+
+    // Notify all the controls that the size has changed and redraw them
+    list<LayeredControl>::const_iterator iter;
+    for( iter = m_controlList.begin(); iter != m_controlList.end(); iter++ )
+    {
+        (*iter).m_pControl->onResize();
+        const Position *pPos = (*iter).m_pControl->getPosition();
+        if( pPos )
+        {
+            (*iter).m_pControl->draw( *m_pImage, pPos->getLeft(),
+                                      pPos->getTop() );
+        }
+    }
+
+    // Resize and refresh the associated window
+    GenericWindow *pWindow = getWindow();
+    if( pWindow )
+    {
+        // Resize the window
+        pWindow->refresh( 0, 0, width, height );
+        pWindow->resize( width, height );
+        pWindow->refresh( 0, 0, width, height );
+
+        // Change the shape of the window and redraw it
+        pWindow->updateShape();
+        pWindow->refresh( 0, 0, width, height );
+    }
+}
+
+
+void GenericLayout::refreshAll()
+{
+    // Draw all the controls of the layout
+    list<LayeredControl>::const_iterator iter;
+    for( iter = m_controlList.begin(); iter != m_controlList.end(); iter++ )
+    {
+        const Position *pPos = (*iter).m_pControl->getPosition();
+        if( pPos )
+        {
+            (*iter).m_pControl->draw( *m_pImage, pPos->getLeft(),
+                                      pPos->getTop() );
+        }
+    }
+
+    // Refresh the associated window
+    GenericWindow *pWindow = getWindow();
+    if( pWindow )
+    {
+        pWindow->refresh( 0, 0, m_width, m_height );
+    }
+}
+
diff --git a/modules/gui/skins2/src/generic_layout.hpp b/modules/gui/skins2/src/generic_layout.hpp
new file mode 100644 (file)
index 0000000..6f8b9a1
--- /dev/null
@@ -0,0 +1,122 @@
+/*****************************************************************************
+ * generic_layout.hpp
+ *****************************************************************************
+ * Copyright (C) 2003 VideoLAN
+ * $Id: generic_layout.hpp,v 1.1 2004/01/03 23:31:33 asmax Exp $
+ *
+ * Authors: Cyril Deguet     <asmax@via.ecp.fr>
+ *          Olivier Teulière <ipkiss@via.ecp.fr>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111, USA.
+ *****************************************************************************/
+
+#ifndef GENERIC_LAYOUT_HPP
+#define GENERIC_LAYOUT_HPP
+
+#include "skin_common.hpp"
+#include "../utils/pointer.hpp"
+#include "../utils/position.hpp"
+
+#include <list>
+
+class GenericWindow;
+class OSGraphics;
+class CtrlGeneric;
+
+
+/// Control and its associated layer
+struct LayeredControl
+{
+    LayeredControl( CtrlGeneric *pControl, int layer ):
+        m_pControl( pControl ), m_layer( layer ) {}
+
+    /// Pointer on the control
+    CtrlGeneric *m_pControl;
+    /// Layer number
+    int m_layer;
+};
+
+
+/// Base class for layouts
+class GenericLayout: public SkinObject, public Box
+{
+    public:
+        GenericLayout( intf_thread_t *pIntf, int width, int height,
+                       int minWidth, int maxWidth, int minHeight,
+                       int maxHeight );
+
+        virtual ~GenericLayout();
+
+        /// Attach the layout to a window
+        virtual void setWindow( GenericWindow *pWindow );
+
+        /// Get the associated window, if any
+        virtual GenericWindow *getWindow() const { return m_pWindow; }
+
+        /// Called by a control which wants to capture the mouse
+        virtual void onControlCapture( const CtrlGeneric &rCtrl );
+
+        /// Called by a control which wants to release the mouse
+        virtual void onControlRelease( const CtrlGeneric &rCtrl );
+
+        /// Refresh the window
+        virtual void refreshAll();
+
+        /// Get the image of the layout
+        virtual OSGraphics *getImage() const { return m_pImage; }
+
+        /// Get the size of the layout
+        virtual int getWidth() const { return m_width; }
+        virtual int getHeight() const { return m_height; }
+
+        /// Get the minimum and maximum size of the layout
+        virtual int getMinWidth() const { return m_minWidth; }
+        virtual int getMaxWidth() const { return m_maxWidth; }
+        virtual int getMinHeight() const { return m_minHeight; }
+        virtual int getMaxHeight() const { return m_maxHeight; }
+
+        /// Resize the layout
+        virtual void resize( int width, int height );
+
+        /// Add a control in the layout at the given position, and
+        /// the optional given layer
+        virtual void addControl( CtrlGeneric *pControl,
+                                 const Position &rPosition,
+                                 int layer );
+
+        /// Get the list of the controls in this layout, by layer order
+        virtual const list<LayeredControl> &getControlList() const;
+
+        /// Called by a control when its image has changed
+        virtual void onControlUpdate( const CtrlGeneric &rCtrl );
+
+    private:
+        /// Parent window of the layout
+        GenericWindow *m_pWindow;
+        /// Layout size
+        int m_width, m_height;
+        int m_minWidth, m_maxWidth;
+        int m_minHeight, m_maxHeight;
+        /// Image of the layout
+        OSGraphics *m_pImage;
+        /// List of the controls in the layout
+        list<LayeredControl> m_controlList;
+};
+
+
+typedef CountedPtr<GenericLayout> GenericLayoutPtr;
+
+
+#endif
diff --git a/modules/gui/skins2/src/generic_window.cpp b/modules/gui/skins2/src/generic_window.cpp
new file mode 100644 (file)
index 0000000..8f9b488
--- /dev/null
@@ -0,0 +1,565 @@
+/*****************************************************************************
+ * generic_window.cpp
+ *****************************************************************************
+ * Copyright (C) 2003 VideoLAN
+ * $Id: generic_window.cpp,v 1.1 2004/01/03 23:31:33 asmax Exp $
+ *
+ * Authors: Cyril Deguet     <asmax@via.ecp.fr>
+ *          Olivier Teulière <ipkiss@via.ecp.fr>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111, USA.
+ *****************************************************************************/
+
+#include "generic_window.hpp"
+#include "generic_layout.hpp"
+#include "os_graphics.hpp"
+#include "os_window.hpp"
+#include "os_factory.hpp"
+#include "theme.hpp"
+#include "ft2_font.hpp"
+#include "tooltip.hpp"
+#include "dialogs.hpp"
+#include "var_manager.hpp"
+#include "../commands/cmd_on_top.hpp"
+#include "../controls/ctrl_generic.hpp"
+#include "../events/evt_enter.hpp"
+#include "../events/evt_focus.hpp"
+#include "../events/evt_leave.hpp"
+#include "../events/evt_motion.hpp"
+#include "../events/evt_mouse.hpp"
+#include "../events/evt_key.hpp"
+#include "../events/evt_refresh.hpp"
+#include "../events/evt_special.hpp"
+#include "../events/evt_scroll.hpp"
+#include "../utils/position.hpp"
+#include "../utils/ustring.hpp"
+
+#include <vlc_keys.h>
+
+
+GenericWindow::GenericWindow( intf_thread_t *pIntf, int left, int top,
+                              WindowManager &rWindowManager,
+                              const GenericFont &rTipFont,
+                              bool dragDrop, bool playOnDrop ):
+    SkinObject( pIntf ), m_rWindowManager( rWindowManager ),
+    m_left( left ), m_top( top ), m_width( 0 ), m_height( 0 ),
+    m_pActiveLayout( NULL ), m_pLastHitControl( NULL ),
+    m_pCapturingControl( NULL ), m_pFocusControl( NULL ), m_varVisible( pIntf )
+{
+    // Register as a moving window
+    m_rWindowManager.registerWindow( this );
+
+    // Get the OSFactory
+    OSFactory *pOsFactory = OSFactory::instance( getIntf() );
+
+    // Create an OSWindow to handle OS specific processing
+    m_pOsWindow = pOsFactory->createOSWindow( *this, dragDrop, playOnDrop );
+
+    // Create the tooltip window
+    m_pTooltip = new Tooltip( getIntf(), rTipFont, 500 );
+
+    // Observe the visibility variable
+    m_varVisible.addObserver( this );
+}
+
+
+GenericWindow::~GenericWindow()
+{
+    m_varVisible.delObserver( this );
+    // Unregister from the window manager
+    m_rWindowManager.unregisterWindow( this );
+
+    if( m_pTooltip )
+    {
+        delete m_pTooltip;
+    }
+    if( m_pOsWindow )
+    {
+        delete m_pOsWindow;
+    }
+}
+
+
+void GenericWindow::processEvent( EvtFocus &rEvtFocus )
+{
+//    fprintf(stderr, rEvtFocus.getAsString().c_str()) ;
+}
+
+
+void GenericWindow::processEvent( EvtMotion &rEvtMotion )
+{
+    // New control hit by the mouse
+    CtrlGeneric *pNewHitControl =
+        findHitControl( rEvtMotion.getXPos() - m_left,
+                        rEvtMotion.getYPos() - m_top );
+
+    setLastHit( pNewHitControl );
+
+    /// Update the help text
+    VarManager *pVarManager = VarManager::instance( getIntf() );
+    if( pNewHitControl )
+    {
+        pVarManager->getHelpText().set( pNewHitControl->getHelpText() );
+    }
+
+    // Send a motion event to the hit control, or to the control
+    // that captured the mouse, if any
+    CtrlGeneric *pActiveControl = pNewHitControl;
+    if( m_pCapturingControl )
+    {
+        pActiveControl = m_pCapturingControl;
+    }
+    if( pActiveControl )
+    {
+        // Compute the coordinates relative to the window
+        int xPos = rEvtMotion.getXPos() - m_left;
+        int yPos = rEvtMotion.getYPos() - m_top;
+        // Send a motion event
+        EvtMotion evt( getIntf(), xPos, yPos );
+        pActiveControl->handleEvent( evt );
+    }
+}
+
+
+void GenericWindow::processEvent( EvtLeave &rEvtLeave )
+{
+    // No more hit control
+    setLastHit( NULL );
+
+    if( !m_pCapturingControl )
+    {
+        m_pTooltip->hide();
+    }
+}
+
+
+void GenericWindow::processEvent( EvtMouse &rEvtMouse )
+{
+    // Raise the window and its anchored windows
+    m_rWindowManager.raise( this );
+
+    // Get the control hit by the mouse
+    CtrlGeneric *pNewHitControl = findHitControl( rEvtMouse.getXPos(),
+                                                  rEvtMouse.getYPos() );
+
+    setLastHit( pNewHitControl );
+
+    // Change the focused control
+    if( rEvtMouse.getAction() == EvtMouse::kDown )
+    {
+        if( pNewHitControl && pNewHitControl->isFocusable() )
+        {
+            // If a new control gains the focus, the previous one loses it
+            if( m_pFocusControl && m_pFocusControl != pNewHitControl )
+            {
+                EvtFocus evt( getIntf(), false );
+                m_pFocusControl->handleEvent( evt );
+            }
+            if( pNewHitControl != m_pFocusControl )
+            {
+                m_pFocusControl = pNewHitControl;
+                EvtFocus evt( getIntf(), false );
+                pNewHitControl->handleEvent( evt );
+            }
+        }
+        else if( m_pFocusControl )
+        {
+            // The previous control loses the focus
+            EvtFocus evt( getIntf(), false );
+            m_pFocusControl->handleEvent( evt );
+            m_pFocusControl = NULL;
+        }
+    }
+
+    // Send a mouse event to the hit control, or to the control
+    // that captured the mouse, if any
+    CtrlGeneric *pActiveControl = pNewHitControl;
+    if( m_pCapturingControl )
+    {
+        pActiveControl = m_pCapturingControl;
+    }
+    if( pActiveControl )
+    {
+        pActiveControl->handleEvent( rEvtMouse );
+    }
+}
+
+
+void GenericWindow::processEvent( EvtKey &rEvtKey )
+{
+    // Forward the event to the focused control, if any
+    if( m_pFocusControl )
+    {
+        m_pFocusControl->handleEvent( rEvtKey );
+    }
+
+    // Only do the action when the key is down
+    else if( rEvtKey.getAsString().find( "key:down") != string::npos )
+    {
+        //XXX not to be hardcoded !
+        // Ctrl-S = Change skin
+        if( (rEvtKey.getMod() & EvtInput::kModCtrl) &&
+            rEvtKey.getKey() == 's' )
+        {
+            Dialogs::instance( getIntf() )->showChangeSkin();
+            return;
+        }
+
+        //XXX not to be hardcoded !
+        // Ctrl-T = Toggle on top
+        if( (rEvtKey.getMod() & EvtInput::kModCtrl) &&
+            rEvtKey.getKey() == 't' )
+        {
+            CmdOnTop cmd( getIntf() );
+            cmd.execute();
+            return;
+        }
+
+        vlc_value_t val;
+        // Set the key
+        val.i_int = rEvtKey.getKey();
+        // Set the modifiers
+        if( rEvtKey.getMod() & EvtInput::kModAlt )
+        {
+            val.i_int |= KEY_MODIFIER_ALT;
+        }
+        if( rEvtKey.getMod() & EvtInput::kModCtrl )
+        {
+            val.i_int |= KEY_MODIFIER_CTRL;
+        }
+        if( rEvtKey.getMod() & EvtInput::kModShift )
+        {
+            val.i_int |= KEY_MODIFIER_SHIFT;
+        }
+
+        var_Set( getIntf()->p_vlc, "key-pressed", val );
+    }
+}
+
+
+void GenericWindow::processEvent( EvtRefresh &rEvtRefresh )
+{
+    // Refresh the given area
+    refresh( rEvtRefresh.getXStart(), rEvtRefresh.getYStart(),
+             rEvtRefresh.getWidth(), rEvtRefresh.getHeight() );
+}
+
+
+void GenericWindow::processEvent( EvtScroll &rEvtScroll )
+{
+    // Raise the windows
+    raise();
+
+    // Get the control hit by the mouse
+    CtrlGeneric *pNewHitControl = findHitControl( rEvtScroll.getXPos(),
+                                                  rEvtScroll.getYPos());
+
+    setLastHit( pNewHitControl );
+
+    // Send a mouse event to the hit control, or to the control
+    // that captured the mouse, if any
+    CtrlGeneric *pActiveControl = pNewHitControl;
+
+    if( m_pCapturingControl )
+    {
+        pActiveControl = m_pCapturingControl;
+    }
+    if( pActiveControl )
+    {
+        pActiveControl->handleEvent( rEvtScroll );
+    }
+}
+
+
+void GenericWindow::forwardEvent( EvtGeneric &rEvt, CtrlGeneric &rCtrl )
+{
+    // XXX: We should do some checks here
+    rCtrl.handleEvent( rEvt );
+}
+
+
+void GenericWindow::show()
+{
+    m_varVisible.set( true );
+}
+
+
+void GenericWindow::hide()
+{
+    m_varVisible.set( false );
+}
+
+
+void GenericWindow::refresh( int left, int top, int width, int height )
+{
+    if( m_pActiveLayout )
+    {
+        m_pActiveLayout->getImage()->copyToWindow( *m_pOsWindow, left, top,
+                                                   width, height, left, top );
+    }
+}
+
+
+void GenericWindow::move( int left, int top )
+{
+    // Update the window coordinates
+    m_left = left;
+    m_top = top;
+
+    m_pOsWindow->moveResize( left, top, m_width, m_height );
+}
+
+
+void GenericWindow::resize( int width, int height )
+{
+    // Update the window size
+    m_width = width;
+    m_height = height;
+
+    m_pOsWindow->moveResize( m_left, m_top, width, height );
+}
+
+
+void GenericWindow::raise()
+{
+    m_pOsWindow->raise();
+}
+
+
+void GenericWindow::setOpacity( uint8_t value )
+{
+    m_pOsWindow->setOpacity( value );
+}
+
+
+void GenericWindow::toggleOnTop( bool onTop )
+{
+    m_pOsWindow->toggleOnTop( onTop );
+}
+
+
+void GenericWindow::setActiveLayout( GenericLayout *pLayout )
+{
+    pLayout->setWindow( this );
+    m_pActiveLayout = pLayout;
+    // Get the size of the layout and resize the window
+    m_width = pLayout->getWidth();
+    m_height = pLayout->getHeight();
+    m_pOsWindow->moveResize( m_left, m_top, m_width, m_height );
+    updateShape();
+    pLayout->refreshAll();
+}
+
+
+void GenericWindow::updateShape()
+{
+    // Set the shape of the window
+    if( m_pActiveLayout )
+    {
+        OSGraphics *pImage = m_pActiveLayout->getImage();
+        if( pImage )
+        {
+            pImage->applyMaskToWindow( *m_pOsWindow );
+        }
+    }
+}
+
+
+const list<Anchor*> GenericWindow::getAnchorList() const
+{
+    return m_anchorList;
+}
+
+
+void GenericWindow::addAnchor( Anchor *pAnchor )
+{
+    m_anchorList.push_back( pAnchor );
+}
+
+
+void GenericWindow::onControlCapture( const CtrlGeneric &rCtrl )
+{
+    // Set the capturing control
+    m_pCapturingControl = (CtrlGeneric*) &rCtrl;
+}
+
+
+void GenericWindow::onControlRelease( const CtrlGeneric &rCtrl )
+{
+    // Release the capturing control
+    if( m_pCapturingControl == &rCtrl )
+    {
+        m_pCapturingControl = NULL;
+    }
+    else
+    {
+        msg_Dbg( getIntf(), "Control had not captured the mouse" );
+    }
+
+    // Send an enter event to the control under the mouse, if it doesn't
+    // have received it yet
+    if( m_pLastHitControl && m_pLastHitControl != &rCtrl )
+    {
+        EvtEnter evt( getIntf() );
+        m_pLastHitControl->handleEvent( evt );
+
+        // Show the tooltip
+        m_pTooltip->hide();
+        UString tipText = m_pLastHitControl->getTooltipText();
+        if( tipText.length() > 0 )
+        {
+            // Set the tooltip text variable
+            VarManager *pVarManager = VarManager::instance( getIntf() );
+            pVarManager->getTooltipText().set( tipText );
+            m_pTooltip->show();
+        }
+    }
+}
+
+
+void GenericWindow::onTooltipChange( const CtrlGeneric &rCtrl )
+{
+    // Check that the control is the active one
+    if( m_pLastHitControl && m_pLastHitControl == &rCtrl )
+    {
+        // Set the tooltip text variable
+        VarManager *pVarManager = VarManager::instance( getIntf() );
+        pVarManager->getTooltipText().set( rCtrl.getTooltipText() );
+    }
+}
+
+
+void GenericWindow::onUpdate( Subject<VarBool> &rVariable )
+{
+    if( m_varVisible.get() )
+    {
+        innerShow();
+    }
+    else
+    {
+        innerHide();
+    }
+}
+
+
+void GenericWindow::innerShow()
+{
+    // First, refresh the layout and update the shape of the window
+    if( m_pActiveLayout )
+    {
+        updateShape();
+        m_pActiveLayout->refreshAll();
+    }
+
+    if( m_pOsWindow )
+    {
+        m_pOsWindow->show( m_left, m_top );
+    }
+}
+
+
+void GenericWindow::innerHide()
+{
+    if( m_pOsWindow )
+    {
+        m_pOsWindow->hide();
+    }
+}
+
+
+CtrlGeneric *GenericWindow::findHitControl( int xPos, int yPos )
+{
+    if( m_pActiveLayout == NULL )
+    {
+        return NULL;
+    }
+
+    // Get the controls in the active layout
+    const list<LayeredControl> &ctrlList = m_pActiveLayout->getControlList();
+    list<LayeredControl>::const_reverse_iterator iter;
+
+    // New control hit by the mouse
+    CtrlGeneric *pNewHitControl = NULL;
+
+    // Loop on the control list to find the uppest hit control
+    for( iter = ctrlList.rbegin(); iter != ctrlList.rend(); iter++ )
+    {
+        // Get the position of the control in the layout
+        const Position *pos = (*iter).m_pControl->getPosition();
+        if( pos != NULL )
+        {
+            // Compute the coordinates of the mouse relative to the control
+            int xRel = xPos - pos->getLeft();
+            int yRel = yPos - pos->getTop();
+
+            // Control hit ?
+            if( (*iter).m_pControl->mouseOver( xRel, yRel ) )
+            {
+                pNewHitControl = (*iter).m_pControl;
+                break;
+            }
+        }
+        else
+        {
+            msg_Dbg( getIntf(), "Control at NULL position" );
+        }
+    }
+
+    // If the hit control has just been entered, send it an enter event
+    if( pNewHitControl && (pNewHitControl != m_pLastHitControl) )
+    {
+        // Don't send the event if another control captured the mouse
+        if( !m_pCapturingControl || (m_pCapturingControl == pNewHitControl ) )
+        {
+            EvtEnter evt( getIntf() );
+            pNewHitControl->handleEvent( evt );
+
+            if( !m_pCapturingControl )
+            {
+                // Show the tooltip
+                m_pTooltip->hide();
+                UString tipText = pNewHitControl->getTooltipText();
+                if( tipText.length() > 0 )
+                {
+                    // Set the tooltip text variable
+                    VarManager *pVarManager = VarManager::instance( getIntf() );
+                    pVarManager->getTooltipText().set( tipText );
+                    m_pTooltip->show();
+                }
+            }
+        }
+    }
+
+    return pNewHitControl;
+}
+
+
+
+void GenericWindow::setLastHit( CtrlGeneric *pNewHitControl )
+{
+    // Send a leave event to the left control
+    if( m_pLastHitControl && (pNewHitControl != m_pLastHitControl) )
+    {
+        // Don't send the event if another control captured the mouse
+        if( !m_pCapturingControl || (m_pCapturingControl == m_pLastHitControl))
+        {
+            EvtLeave evt( getIntf() );
+            m_pLastHitControl->handleEvent( evt );
+        }
+    }
+
+    m_pLastHitControl = pNewHitControl;
+}
+
diff --git a/modules/gui/skins2/src/generic_window.hpp b/modules/gui/skins2/src/generic_window.hpp
new file mode 100644 (file)
index 0000000..e4c8877
--- /dev/null
@@ -0,0 +1,172 @@
+/*****************************************************************************
+ * generic_window.hpp
+ *****************************************************************************
+ * Copyright (C) 2003 VideoLAN
+ * $Id: generic_window.hpp,v 1.1 2004/01/03 23:31:33 asmax Exp $
+ *
+ * Authors: Cyril Deguet     <asmax@via.ecp.fr>
+ *          Olivier Teulière <ipkiss@via.ecp.fr>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111, USA.
+ *****************************************************************************/
+
+#ifndef GENERIC_WINDOW_HPP
+#define GENERIC_WINDOW_HPP
+
+#include "skin_common.hpp"
+#include "../utils/pointer.hpp"
+#include "../utils/var_bool.hpp"
+#include <list>
+
+class Anchor;
+class OSWindow;
+class OSGraphics;
+class GenericLayout;
+class Tooltip;
+class CtrlGeneric;
+class EvtGeneric;
+class EvtFocus;
+class EvtLeave;
+class EvtMotion;
+class EvtMouse;
+class EvtKey;
+class EvtRefresh;
+class EvtScroll;
+class GenericFont;
+class WindowManager;
+
+
+/// Generic window class
+class GenericWindow: public SkinObject, public Observer<VarBool>
+{
+    public:
+        GenericWindow( intf_thread_t *pIntf, int xPos, int yPos,
+                       WindowManager &rWindowManager,
+                       const GenericFont &rTipFont,
+                       bool dragDrop, bool playOnDrop );
+        virtual ~GenericWindow();
+
+        /// Methods to process OS events.
+        virtual void processEvent( EvtFocus &rEvtFocus );
+        virtual void processEvent( EvtMotion &rEvtMotion );
+        virtual void processEvent( EvtMouse &rEvtMouse );
+        virtual void processEvent( EvtLeave &rEvtLeave );
+        virtual void processEvent( EvtKey &rEvtKey );
+        virtual void processEvent( EvtRefresh &rEvtRefresh );
+        virtual void processEvent( EvtScroll &rEvtScroll );
+
+        /// Forward an event to a control
+        virtual void forwardEvent( EvtGeneric &rEvt, CtrlGeneric &rCtrl );
+
+        // Show the window
+        virtual void show();
+
+        // Hide the window
+        virtual void hide();
+
+        // Refresh an area of the window
+        virtual void refresh( int left, int top, int width, int height );
+
+        /// Move the window
+        virtual void move( int left, int top );
+
+        /// Resize the window
+        virtual void resize( int width, int height );
+
+        /// Bring the window on top
+        virtual void raise();
+
+        /// Set the opacity of the window (0 = transparent, 255 = opaque)
+        virtual void setOpacity( uint8_t value );
+
+        /// Toggle the window on top
+        virtual void toggleOnTop( bool onTop );
+
+        /// Change the active layout
+        virtual void setActiveLayout( GenericLayout *pLayout );
+
+        /// Update the shape of the window from the active layout
+        virtual void updateShape();
+
+        /// Called by a control that wants to capture the mouse
+        virtual void onControlCapture( const CtrlGeneric &rCtrl );
+
+        /// Called by a control that wants to release the mouse
+        virtual void onControlRelease( const CtrlGeneric &rCtrl );
+
+        /// Called by a control when its tooltip changed
+        virtual void onTooltipChange( const CtrlGeneric &rCtrl );
+
+        /// Get the coordinates of the window
+        virtual int getLeft() const { return m_left; }
+        virtual int getTop() const { return m_top; }
+        virtual int getWidth() const { return m_width; }
+        virtual int getHeight() const { return m_height; }
+
+        /// Give access to the visibility variable
+        VarBool &getVisibleVar() { return m_varVisible; }
+
+        /// Get the list of the anchors of this window
+        virtual const list<Anchor*> getAnchorList() const;
+
+        /// Add an anchor to this window
+        virtual void addAnchor( Anchor *pAnchor );
+
+    private:
+        /// Window manager
+        WindowManager &m_rWindowManager;
+        /// Window position and size
+        int m_left, m_top, m_width, m_height;
+        /// OS specific implementation
+        OSWindow *m_pOsWindow;
+        /// Current active layout of the window
+        GenericLayout *m_pActiveLayout;
+        /// Last control on which the mouse was over
+        CtrlGeneric *m_pLastHitControl;
+        /// Control that has captured the mouse
+        CtrlGeneric *m_pCapturingControl;
+        /// Control that has the focus
+        CtrlGeneric *m_pFocusControl;
+        /// List of the anchors of this window
+        list<Anchor*> m_anchorList;
+        /// Font for the tooltip
+        GenericFont *m_pFont;
+        /// Tooltip
+        Tooltip *m_pTooltip;
+        /// Variable for the visibility of the window
+        VarBool m_varVisible;
+
+        /// Method called when the observed variable is modified
+        virtual void onUpdate( Subject<VarBool> &rVariable );
+
+        // Actually show the window
+        virtual void innerShow();
+
+        // Actually hide the window
+        virtual void innerHide();
+
+        /// Find the uppest control in the layout hit by the mouse, and send
+        /// it an enter event if needed
+        CtrlGeneric *findHitControl( int xPos, int yPos );
+
+        /// Update the lastHitControl pointer and send a leave event to the
+        /// right control
+        void setLastHit( CtrlGeneric *pNewHitControl );
+};
+
+typedef CountedPtr<GenericWindow> GenericWindowPtr;
+
+
+#endif
diff --git a/modules/gui/skins2/src/logger.cpp b/modules/gui/skins2/src/logger.cpp
new file mode 100644 (file)
index 0000000..e6c98a6
--- /dev/null
@@ -0,0 +1,73 @@
+/*****************************************************************************
+ * logger.cpp
+ *****************************************************************************
+ * Copyright (C) 2003 VideoLAN
+ * $Id: logger.cpp,v 1.1 2004/01/03 23:31:33 asmax Exp $
+ *
+ * Authors: Cyril Deguet     <asmax@via.ecp.fr>
+ *          Olivier Teulière <ipkiss@via.ecp.fr>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111, USA.
+ *****************************************************************************/
+
+#include "logger.hpp"
+
+
+Logger::Logger( intf_thread_t *pIntf ): SkinObject( pIntf )
+{
+}
+
+
+Logger::~Logger()
+{
+}
+
+
+Logger *Logger::instance( intf_thread_t *pIntf )
+{
+    if( ! pIntf->p_sys->p_logger )
+    {
+        Logger *pLogger = new Logger( pIntf );
+        if( pLogger )
+        {
+            // Initialization succeeded
+            pIntf->p_sys->p_logger = pLogger;
+        }
+    }
+    return pIntf->p_sys->p_logger;
+}
+
+
+void Logger::destroy( intf_thread_t *pIntf )
+{
+    if( pIntf->p_sys->p_logger )
+    {
+        delete pIntf->p_sys->p_logger;
+        pIntf->p_sys->p_logger = NULL;
+    }
+}
+
+
+void Logger::error( const string &rMsg )
+{
+    msg_Err( getIntf(), rMsg.c_str() );
+}
+
+
+void Logger::warn( const string &rMsg )
+{
+    msg_Warn( getIntf(), rMsg.c_str() );
+}
+
diff --git a/modules/gui/skins2/src/logger.hpp b/modules/gui/skins2/src/logger.hpp
new file mode 100644 (file)
index 0000000..837909b
--- /dev/null
@@ -0,0 +1,61 @@
+/*****************************************************************************
+ * logger.hpp
+ *****************************************************************************
+ * Copyright (C) 2003 VideoLAN
+ * $Id: logger.hpp,v 1.1 2004/01/03 23:31:33 asmax Exp $
+ *
+ * Authors: Cyril Deguet     <asmax@via.ecp.fr>
+ *          Olivier Teulière <ipkiss@via.ecp.fr>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111, USA.
+ *****************************************************************************/
+
+#ifndef LOGGER_HPP
+#define LOGGER_HPP
+
+#include "skin_common.hpp"
+#include <string>
+
+
+// helper macros
+#define MSG_ERR( msg ) Logger::instance( getIntf() )->error( msg )
+#define MSG_WARN( msg ) Logger::instance( getIntf() )->warn( msg )
+
+
+// Logger class
+class Logger: public SkinObject
+{
+    public:
+        /// Get the instance of Logger
+        /// Returns NULL if initialization failed
+        static Logger *instance( intf_thread_t *pIntf );
+
+        /// Delete the instance of Logger
+        static void destroy( intf_thread_t *pIntf );
+
+        /// Print an error message
+        void error( const string &rMsg );
+
+        /// Print a warning
+        void warn( const string &rMsg );
+
+    private:
+        // Private because it's a singleton
+        Logger( intf_thread_t *pIntf );
+        ~Logger();
+};
+
+
+#endif
diff --git a/modules/gui/skins2/src/os_factory.cpp b/modules/gui/skins2/src/os_factory.cpp
new file mode 100644 (file)
index 0000000..deef1a6
--- /dev/null
@@ -0,0 +1,69 @@
+/*****************************************************************************
+ * os_factory.cpp
+ *****************************************************************************
+ * Copyright (C) 2003 VideoLAN
+ * $Id: os_factory.cpp,v 1.1 2004/01/03 23:31:33 asmax Exp $
+ *
+ * Authors: Cyril Deguet     <asmax@via.ecp.fr>
+ *          Olivier Teulière <ipkiss@via.ecp.fr>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111, USA.
+ *****************************************************************************/
+
+#include "os_factory.hpp"
+
+#ifdef X11_SKINS
+#include "../x11/x11_factory.hpp"
+#elif defined WIN32_SKINS
+#include "../win32/win32_factory.hpp"
+#endif
+
+OSFactory *OSFactory::instance( intf_thread_t *pIntf )
+{
+    if( ! pIntf->p_sys->p_osFactory )
+    {
+        OSFactory *pOsFactory;
+#ifdef X11_SKINS
+        pOsFactory = new X11Factory( pIntf );
+#elif defined WIN32_SKINS
+        pOsFactory = new Win32Factory( pIntf );
+#else
+#error "No OSFactory implementation !"
+#endif
+
+        if( pOsFactory->init() )
+        {
+            // Initialization succeeded
+            pIntf->p_sys->p_osFactory = pOsFactory;
+        }
+        else
+        {
+            // Initialization failed
+            delete pOsFactory;
+        }
+    }
+    return pIntf->p_sys->p_osFactory;
+}
+
+
+void OSFactory::destroy( intf_thread_t *pIntf )
+{
+    if( pIntf->p_sys->p_osFactory )
+    {
+        delete pIntf->p_sys->p_osFactory;
+        pIntf->p_sys->p_osFactory = NULL;
+    }
+}
+
diff --git a/modules/gui/skins2/src/os_factory.hpp b/modules/gui/skins2/src/os_factory.hpp
new file mode 100644 (file)
index 0000000..d1c26da
--- /dev/null
@@ -0,0 +1,98 @@
+/*****************************************************************************
+ * os_factory.hpp
+ *****************************************************************************
+ * Copyright (C) 2003 VideoLAN
+ * $Id: os_factory.hpp,v 1.1 2004/01/03 23:31:33 asmax Exp $
+ *
+ * Authors: Cyril Deguet     <asmax@via.ecp.fr>
+ *          Olivier Teulière <ipkiss@via.ecp.fr>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111, USA.
+ *****************************************************************************/
+
+#ifndef OS_FACTORY_HPP
+#define OS_FACTORY_HPP
+
+#include "skin_common.hpp"
+#include "../utils/position.hpp"
+#include <string>
+
+class GenericWindow;
+class OSBitmap;
+class OSGraphics;
+class OSLoop;
+class OSWindow;
+class OSTooltip;
+class OSTimer;
+
+
+/// Abstract factory used to instantiate OS specific objects.
+class OSFactory: public SkinObject
+{
+    public:
+        /// Initialization method overloaded in derived classes.
+        /// It must return false if the init failed.
+        virtual bool init() { return true; }
+
+        /// Get the right instance of OSFactory.
+        /// Returns NULL if initialization of the concrete factory failed.
+        static OSFactory *instance( intf_thread_t *pIntf );
+
+        /// Delete the instance of OSFactory.
+        static void destroy( intf_thread_t *pIntf );
+
+        /// Instantiate an object OSGraphics.
+        virtual OSGraphics *createOSGraphics( int width, int height ) = 0;
+
+        /// Get the instance of the singleton OSLoop.
+        virtual OSLoop *getOSLoop() = 0;
+
+        /// Destroy the instance of OSLoop.
+        virtual void destroyOSLoop() = 0;
+
+        /// Instantiate an OSTimer with the given callback
+        virtual OSTimer *createOSTimer( const Callback &rCallback ) = 0;
+
+        /// Instantiate an object OSWindow.
+        virtual OSWindow *createOSWindow( GenericWindow &rWindow,
+                                          bool dragDrop, bool playOnDrop ) = 0;
+
+        /// Instantiate an object OSTooltip.
+        virtual OSTooltip *createOSTooltip() = 0;
+
+        /// Get the directory separator
+        virtual const string getDirSeparator() const = 0;
+
+        /// Get the screen size
+        virtual int getScreenWidth() const = 0;
+        virtual int getScreenHeight() const = 0;
+
+        /// Get the work area (screen area without taskbars)
+        virtual Rect getWorkArea() const = 0;
+
+        /// Get the position of the mouse
+        virtual void getMousePos( int &rXPos, int &rYPos ) const = 0;
+
+        /// Delete a directory recursively
+        virtual void rmDir( const string &rPath ) = 0;
+
+   protected:
+        // Protected because it's a singleton.
+        OSFactory( intf_thread_t* pIntf ): SkinObject( pIntf ) {}
+        virtual ~OSFactory() {}
+};
+
+
+#endif
diff --git a/modules/gui/skins2/src/os_graphics.hpp b/modules/gui/skins2/src/os_graphics.hpp
new file mode 100644 (file)
index 0000000..8866c09
--- /dev/null
@@ -0,0 +1,84 @@
+/*****************************************************************************
+ * os_graphics.hpp
+ *****************************************************************************
+ * Copyright (C) 2003 VideoLAN
+ * $Id: os_graphics.hpp,v 1.1 2004/01/03 23:31:33 asmax Exp $
+ *
+ * Authors: Cyril Deguet     <asmax@via.ecp.fr>
+ *          Olivier Teulière <ipkiss@via.ecp.fr>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111, USA.
+ *****************************************************************************/
+
+#ifndef OS_GRAPHICS_HPP
+#define OS_GRAPHICS_HPP
+
+#include "skin_common.hpp"
+#include "../utils/pointer.hpp"
+
+class GenericBitmap;
+class OSWindow;
+
+
+/// OS specific graphics class
+class OSGraphics: public SkinObject
+{
+    public:
+        virtual ~OSGraphics() {}
+
+        /// Clear the graphics
+        virtual void clear() = 0;
+
+        /// Draw another graphics on this one
+        virtual void drawGraphics( const OSGraphics &rGraphics, int xSrc = 0,
+                                   int ySrc = 0, int xDest = 0, int yDest = 0,
+                                   int width = -1, int height = -1 ) = 0;
+
+        /// Render a bitmap on this graphics
+        virtual void drawBitmap( const GenericBitmap &rBitmap, int xSrc = 0,
+                                 int ySrc = 0, int xDest = 0, int yDest = 0,
+                                 int width = -1, int height = -1 ) = 0;
+
+        /// Draw a filled rectangle on the grahics (color is #RRGGBB)
+        virtual void fillRect( int left, int top, int width, int height,
+                               uint32_t color ) = 0;
+
+        /// Draw an empty rectangle on the grahics (color is #RRGGBB)
+        virtual void drawRect( int left, int top, int width, int height,
+                               uint32_t color ) = 0;
+
+
+        /// Set the shape of a window with the mask of this graphics.
+        virtual void applyMaskToWindow( OSWindow &rWindow ) = 0;
+
+        /// Copy the graphics on a window
+        virtual void copyToWindow( OSWindow &rWindow, int xSrc,
+                                   int ySrc, int width, int height,
+                                   int xDest, int yDest ) = 0;
+
+        /// Tell whether the pixel at the given position is visible
+        virtual bool hit( int x, int y ) const = 0;
+
+        /// Getters
+        virtual int getWidth() const = 0;
+        virtual int getHeight() const = 0;
+
+    protected:
+        OSGraphics( intf_thread_t *pIntf ): SkinObject( pIntf ) {}
+};
+
+typedef CountedPtr<OSGraphics> OSGraphicsPtr;
+
+#endif
diff --git a/modules/gui/skins2/src/os_loop.hpp b/modules/gui/skins2/src/os_loop.hpp
new file mode 100644 (file)
index 0000000..be1dc8f
--- /dev/null
@@ -0,0 +1,51 @@
+/*****************************************************************************
+ * os_loop.hpp
+ *****************************************************************************
+ * Copyright (C) 2003 VideoLAN
+ * $Id: os_loop.hpp,v 1.1 2004/01/03 23:31:33 asmax Exp $
+ *
+ * Authors: Cyril Deguet     <asmax@via.ecp.fr>
+ *          Olivier Teulière <ipkiss@via.ecp.fr>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111, USA.
+ *****************************************************************************/
+
+#ifndef OS_LOOP_HPP
+#define OS_LOOP_HPP
+
+#include "skin_common.hpp"
+
+
+/// Abstract class for the main event loop
+class OSLoop: public SkinObject
+{
+    public:
+        virtual ~OSLoop() {}
+
+        /// Enter the main loop
+        virtual void run() = 0;
+
+        /// Exit the main loop
+        virtual void exit() = 0;
+
+        /// Flush the event queue
+        virtual void flush() {}
+
+    protected:
+        OSLoop( intf_thread_t *pIntf ): SkinObject( pIntf ) {}
+};
+
+
+#endif
diff --git a/modules/gui/skins2/src/os_timer.hpp b/modules/gui/skins2/src/os_timer.hpp
new file mode 100644 (file)
index 0000000..d9deb21
--- /dev/null
@@ -0,0 +1,49 @@
+/*****************************************************************************
+ * os_timer.hpp
+ *****************************************************************************
+ * Copyright (C) 2003 VideoLAN
+ * $Id: os_timer.hpp,v 1.1 2004/01/03 23:31:33 asmax Exp $
+ *
+ * Authors: Cyril Deguet     <asmax@via.ecp.fr>
+ *          Olivier Teulière <ipkiss@via.ecp.fr>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111, USA.
+ *****************************************************************************/
+
+#ifndef OS_TIMER_HPP
+#define OS_TIMER_HPP
+
+#include "skin_common.hpp"
+
+
+// Base class for OS-specific timers
+class OSTimer: public SkinObject
+{
+    public:
+        virtual ~OSTimer() {}
+
+        /// (Re)start the timer with the given delay (in ms). If oneShot is
+        /// true, stop it after the first execution of the callback.
+        virtual void start( int delay, bool oneShot ) = 0;
+
+        /// Stop the timer
+        virtual void stop() = 0;
+
+    protected:
+        OSTimer( intf_thread_t *pIntf ): SkinObject( pIntf ) {}
+};
+
+
+#endif
diff --git a/modules/gui/skins2/src/os_tooltip.hpp b/modules/gui/skins2/src/os_tooltip.hpp
new file mode 100644 (file)
index 0000000..019ef52
--- /dev/null
@@ -0,0 +1,49 @@
+/*****************************************************************************
+ * os_tooltip.hpp
+ *****************************************************************************
+ * Copyright (C) 2003 VideoLAN
+ * $Id: os_tooltip.hpp,v 1.1 2004/01/03 23:31:33 asmax Exp $
+ *
+ * Authors: Cyril Deguet     <asmax@via.ecp.fr>
+ *          Olivier Teulière <ipkiss@via.ecp.fr>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111, USA.
+ *****************************************************************************/
+
+#ifndef OS_TOOLTIP_HPP
+#define OS_TOOLTIP_HPP
+
+#include "skin_common.hpp"
+
+class OSGraphics;
+
+
+/// Base class for OS specific Tooltip Windows
+class OSTooltip: public SkinObject
+{
+    public:
+        virtual ~OSTooltip() {}
+
+        // Show the tooltip
+        virtual void show( int left, int top, OSGraphics &rText ) = 0;
+
+        // Hide the tooltip
+        virtual void hide() = 0;
+
+    protected:
+        OSTooltip( intf_thread_t *pIntf ): SkinObject( pIntf ) {}
+};
+
+#endif
diff --git a/modules/gui/skins2/src/os_window.hpp b/modules/gui/skins2/src/os_window.hpp
new file mode 100644 (file)
index 0000000..eef00c4
--- /dev/null
@@ -0,0 +1,63 @@
+/*****************************************************************************
+ * os_window.hpp
+ *****************************************************************************
+ * Copyright (C) 2003 VideoLAN
+ * $Id: os_window.hpp,v 1.1 2004/01/03 23:31:33 asmax Exp $
+ *
+ * Authors: Cyril Deguet     <asmax@via.ecp.fr>
+ *          Olivier Teulière <ipkiss@via.ecp.fr>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111, USA.
+ *****************************************************************************/
+
+#ifndef OS_WINDOW_HPP
+#define OS_WINDOW_HPP
+
+#include "skin_common.hpp"
+
+class GenericWindow;
+class OSGraphics;
+
+
+/// OS specific delegate class for GenericWindow
+class OSWindow: public SkinObject
+{
+    public:
+        virtual ~OSWindow() {}
+
+        // Show the window
+        virtual void show( int left, int top ) = 0;
+
+        // Hide the window
+        virtual void hide() = 0;
+
+        /// Move and resize the window
+        virtual void moveResize( int left, int top, int width, int height ) = 0;
+
+        /// Bring the window on top
+        virtual void raise() = 0;
+
+        /// Set the opacity of the window (0 = transparent, 255 = opaque)
+        virtual void setOpacity( uint8_t value ) = 0;
+
+        /// Toggle the window on top
+        virtual void toggleOnTop( bool onTop ) = 0;
+
+    protected:
+        OSWindow( intf_thread_t *pIntf ): SkinObject( pIntf ) {}
+};
+
+
+#endif
diff --git a/modules/gui/skins2/src/png_bitmap.cpp b/modules/gui/skins2/src/png_bitmap.cpp
new file mode 100644 (file)
index 0000000..7da2a9b
--- /dev/null
@@ -0,0 +1,154 @@
+/*****************************************************************************
+ * png_bitmap.cpp
+ *****************************************************************************
+ * Copyright (C) 2003 VideoLAN
+ * $Id: png_bitmap.cpp,v 1.1 2004/01/03 23:31:33 asmax Exp $
+ *
+ * Authors: Cyril Deguet     <asmax@via.ecp.fr>
+ *          Olivier Teulière <ipkiss@via.ecp.fr>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111, USA.
+ *****************************************************************************/
+
+#include <png.h>
+#include "png_bitmap.hpp"
+
+
+PngBitmap::PngBitmap( intf_thread_t *pIntf, string fileName,
+                      uint32_t aColor ):
+    GenericBitmap( pIntf ), m_width( 0 ), m_height( 0 ), m_pData( NULL )
+{
+    // Open the PNG file
+    FILE *pFile = fopen( fileName.c_str(), "rb" );
+    if( pFile == NULL )
+    {
+        msg_Err( getIntf(), "Cannot open bitmap %s", fileName.c_str() );
+        return;
+    }
+
+    // Create the PNG structures
+    png_structp pReadStruct = png_create_read_struct( PNG_LIBPNG_VER_STRING,
+        NULL, NULL, NULL );
+    if ( pReadStruct == NULL )
+    {
+        msg_Err( getIntf(), "Failed to create PNG read struct" );
+        return;
+    }
+    png_infop pInfo = png_create_info_struct( pReadStruct );
+    if( pInfo == NULL )
+    {
+        png_destroy_read_struct( &pReadStruct, NULL, NULL );
+        msg_Err( getIntf(), "Failed to create PNG info struct" );
+        return;
+    }
+    png_infop pEndInfo = png_create_info_struct( pReadStruct );
+    if( pEndInfo == NULL )
+    {
+        png_destroy_read_struct( &pReadStruct, NULL, NULL );
+        msg_Err( getIntf(), "Failed to create PNG end info struct" );
+        return;
+    }
+
+    // Initialize the PNG reader
+    png_init_io( pReadStruct, pFile );
+
+    // Read the image header
+    png_read_info( pReadStruct, pInfo );
+    m_width = png_get_image_width( pReadStruct, pInfo );
+    m_height = png_get_image_height( pReadStruct, pInfo );
+    int depth = png_get_bit_depth( pReadStruct, pInfo );
+    int colorType = png_get_color_type( pReadStruct, pInfo );
+
+    // Convert paletted images to RGB
+    if( colorType == PNG_COLOR_TYPE_PALETTE )
+    {
+        png_set_palette_to_rgb( pReadStruct );
+    }
+    // Strip to 8 bits per channel
+    if( depth == 16 )
+    {
+        png_set_strip_16( pReadStruct );
+    }
+    // 4 bytes per pixel
+    if( !(colorType & PNG_COLOR_MASK_ALPHA ) )
+    {
+        png_set_filler( pReadStruct, 0xff, PNG_FILLER_AFTER );
+    }
+    // Invert colors
+    if( colorType & PNG_COLOR_MASK_COLOR )
+    {
+        png_set_bgr( pReadStruct );
+    }
+    png_read_update_info( pReadStruct, pInfo );
+
+    // Allocate memory for the buffers
+    m_pData = new uint8_t[m_height * m_width * 4];
+    uint8_t** pRows = new uint8_t*[m_height];
+    for( int i = 0; i < m_height; i++ )
+    {
+        pRows[i] = m_pData + (i * m_width * 4);
+    }
+
+    // Read the image
+    png_read_image( pReadStruct, pRows );
+    png_read_end( pReadStruct, pEndInfo );
+
+    // Compute the alpha layer
+    uint8_t *pData = m_pData;
+    for( int y = 0; y < m_height; y++ )
+    {
+        for( int x = 0; x < m_width; x++ )
+        {
+            uint32_t b = (uint32_t)*(pData++);
+            uint32_t g = (uint32_t)*(pData++);
+            uint32_t r = (uint32_t)*(pData++);
+            // Transparent pixel ?
+            if( aColor == (r<<16 | g<<8 | b) )
+            {
+                *(pData++) = 0;
+            }
+            else
+            {
+                *(pData++) = 0xff;
+            }
+        }
+    }
+
+    // Free the structures
+    png_destroy_read_struct( &pReadStruct, &pInfo, &pEndInfo );
+    delete[] pRows;
+
+    // Close the file
+    fclose( pFile );
+}
+
+
+PngBitmap::~PngBitmap()
+{
+    if( m_pData )
+    {
+        delete[] m_pData;
+    }
+}
+
+
+uint8_t *PngBitmap::getData() const
+{
+    if( m_pData == NULL )
+    {
+        msg_Warn( getIntf(), "PngBitmap::getData() returns NULL" );
+    }
+    return m_pData;
+}
diff --git a/modules/gui/skins2/src/png_bitmap.hpp b/modules/gui/skins2/src/png_bitmap.hpp
new file mode 100644 (file)
index 0000000..698b1ef
--- /dev/null
@@ -0,0 +1,61 @@
+/*****************************************************************************
+ * png_bitmap.hpp
+ *****************************************************************************
+ * Copyright (C) 2003 VideoLAN
+ * $Id: png_bitmap.hpp,v 1.1 2004/01/03 23:31:33 asmax Exp $
+ *
+ * Authors: Cyril Deguet     <asmax@via.ecp.fr>
+ *          Olivier Teulière <ipkiss@via.ecp.fr>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111, USA.
+ *****************************************************************************/
+
+#ifndef PNG_BITMAP_HPP
+#define PNG_BITMAP_HPP
+
+#include "generic_bitmap.hpp"
+#include <string>
+
+
+/// Class for PNG bitmaps
+class PngBitmap: public GenericBitmap
+{
+    public:
+        /// Load a PNG bitmap from a file. aColor is the transparency
+        /// color, in the format 0xRRGGBB
+        PngBitmap( intf_thread_t *pIntf, string fileName,
+                   uint32_t aColor );
+
+        virtual ~PngBitmap();
+
+        /// Get the width of the bitmap
+        virtual int getWidth() const { return m_width; }
+
+        /// Get the heighth of the bitmap
+        virtual int getHeight() const { return m_height; }
+
+        /// Get a linear buffer containing the image data.
+        /// Each pixel is stored in 4 bytes in the order B,G,R,A
+        virtual uint8_t *getData() const;
+
+    private:
+        /// Size of the bitmap.
+        int m_width, m_height;
+        /// Buffer containing the image data.
+        uint8_t *m_pData;
+};
+
+
+#endif
diff --git a/modules/gui/skins2/src/scaled_bitmap.cpp b/modules/gui/skins2/src/scaled_bitmap.cpp
new file mode 100644 (file)
index 0000000..5cd583b
--- /dev/null
@@ -0,0 +1,108 @@
+/*****************************************************************************
+ * scaled_bitmap.cpp
+ *****************************************************************************
+ * Copyright (C) 2003 VideoLAN
+ * $Id: scaled_bitmap.cpp,v 1.1 2004/01/03 23:31:34 asmax Exp $
+ *
+ * Authors: Cyril Deguet     <asmax@via.ecp.fr>
+ *          Olivier Teulière <ipkiss@via.ecp.fr>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111, USA.
+ *****************************************************************************/
+
+#include "scaled_bitmap.hpp"
+
+
+ScaledBitmap::ScaledBitmap( intf_thread_t *pIntf, const GenericBitmap &rBitmap,
+                            int width, int height ):
+    GenericBitmap( pIntf ), m_width( width ), m_height( height )
+{
+    // XXX We should check that width and height are positive...
+
+    // Allocate memory for the buffer
+    m_pData = new uint8_t[m_height * m_width * 4];
+
+    int srcWidth = rBitmap.getWidth();
+    int srcHeight = rBitmap.getHeight();
+    uint32_t *pSrcData = (uint32_t*)rBitmap.getData();
+    uint32_t *pDestData = (uint32_t*)m_pData;
+
+    // Algorithm for horizontal enlargement
+    if( width > srcWidth )
+    {
+        // Decision variables for Bresenham alogrithm
+        int incX1 = 2 * srcWidth;
+        int incX2 = incX1 - 2 * width;
+        int dX = incX1 - width;
+
+        for( int y = 0; y < height; y++ )
+        {
+            uint32_t yOffset = ((y * srcHeight) / height) * srcWidth;
+            pSrcData = ((uint32_t*)rBitmap.getData()) + yOffset;
+
+            for( int x = 0; x < width; x++ )
+            {
+                *(pDestData++) = *pSrcData;
+
+                if( dX <= 0 )
+                {
+                    dX += incX1;
+                }
+                else
+                {
+                    dX += incX2;
+                    pSrcData++;
+                }
+            }
+        }
+    }
+    // Algorithm for horizontal reduction
+    else
+    {
+        // Decision variables for Bresenham alogrithm
+        int incX1 = 2 * width;
+        int incX2 = incX1 - 2 * srcWidth;
+        int dX = incX1 - srcWidth;
+
+        for( int y = 0; y < height; y++ )
+        {
+            uint32_t yOffset = ((y * srcHeight) / height) * srcWidth;
+            pSrcData = ((uint32_t*)rBitmap.getData()) + yOffset;
+
+            for( int x = 0; x < width; x++ )
+            {
+                *(pDestData++) = *(pSrcData++);
+
+                while( dX <= 0 )
+                {
+                    dX += incX1;
+                    pSrcData++;
+                }
+                dX += incX2;
+            }
+        }
+
+    }
+}
+
+
+ScaledBitmap::~ScaledBitmap()
+{
+    if( m_pData )
+    {
+        delete[] m_pData;
+    }
+}
+
diff --git a/modules/gui/skins2/src/scaled_bitmap.hpp b/modules/gui/skins2/src/scaled_bitmap.hpp
new file mode 100644 (file)
index 0000000..c10afe3
--- /dev/null
@@ -0,0 +1,59 @@
+/*****************************************************************************
+ * scaled_bitmap.hpp
+ *****************************************************************************
+ * Copyright (C) 2003 VideoLAN
+ * $Id: scaled_bitmap.hpp,v 1.1 2004/01/03 23:31:34 asmax Exp $
+ *
+ * Authors: Cyril Deguet     <asmax@via.ecp.fr>
+ *          Olivier Teulière <ipkiss@via.ecp.fr>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111, USA.
+ *****************************************************************************/
+
+#ifndef SCALED_BITMAP_HPP
+#define SCALED_BITMAP_HPP
+
+#include "generic_bitmap.hpp"
+
+
+/// Class for scaling bitmaps
+class ScaledBitmap: public GenericBitmap
+{
+    public:
+        /// Create a scaled bitmap from the given bitmap and size
+        ScaledBitmap( intf_thread_t *pIntf, const GenericBitmap &rBitmap,
+                      int width, int height );
+
+        virtual ~ScaledBitmap();
+
+        /// Get the width of the bitmap
+        virtual int getWidth() const { return m_width; }
+
+        /// Get the heighth of the bitmap
+        virtual int getHeight() const { return m_height; }
+
+        /// Get a linear buffer containing the image data.
+        /// Each pixel is stored in 4 bytes in the order B,G,R,A
+        virtual uint8_t *getData() const { return m_pData; }
+
+    private:
+        /// Bitmap size
+        int m_width, m_height;
+        /// Image data buffer
+        uint8_t *m_pData;
+};
+
+
+#endif
diff --git a/modules/gui/skins2/src/skin_common.hpp b/modules/gui/skins2/src/skin_common.hpp
new file mode 100644 (file)
index 0000000..968eacd
--- /dev/null
@@ -0,0 +1,129 @@
+/*****************************************************************************
+ * skin_common.hpp
+ *****************************************************************************
+ * Copyright (C) 2003 VideoLAN
+ * $Id: skin_common.hpp,v 1.1 2004/01/03 23:31:34 asmax Exp $
+ *
+ * Authors: Cyril Deguet     <asmax@via.ecp.fr>
+ *          Olivier Teulière <ipkiss@via.ecp.fr>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111, USA.
+ *****************************************************************************/
+
+#ifndef SKIN_COMMON_HPP
+#define SKIN_COMMON_HPP
+
+#include <vlc/vlc.h>
+#include <vlc/intf.h>
+
+using namespace std;
+
+class AsyncQueue;
+class Logger;
+class Dialogs;
+class OSFactory;
+class OSLoop;
+class VarManager;
+class VlcProc;
+class Theme;
+
+
+// Useful macros
+#define SKINS_DELETE( p ) \
+   if( p ) \
+   { \
+       delete p; \
+   } \
+   else \
+   { \
+       msg_Err( getIntf(), "delete NULL pointer in %s at line %d", \
+                __FILE__, __LINE__ ); \
+   }
+
+
+//---------------------------------------------------------------------------
+// intf_sys_t: description and status of skin interface
+//---------------------------------------------------------------------------
+struct intf_sys_t
+{
+    /// The input thread
+    input_thread_t *p_input;
+
+    /// The playlist thread
+    playlist_t *p_playlist;
+
+    /// Message bank subscription
+    msg_subscription_t *p_sub;
+
+    // "Singleton" objects: MUST be initialized to NULL !
+    /// Logger
+    Logger *p_logger;
+    /// Asynchronous command queue
+    AsyncQueue *p_queue;
+    /// Dialog provider
+    Dialogs *p_dialogs;
+    /// Factory for OS specific classes
+    OSFactory *p_osFactory;
+    /// Main OS specific message loop
+    OSLoop *p_osLoop;
+    /// Variable manager
+    VarManager *p_varManager;
+    /// VLC state handler
+    VlcProc *p_vlcProc;
+
+    /// Current theme
+    Theme *p_theme;
+};
+
+
+/// Base class for all skin classes
+class SkinObject
+{
+    public:
+        SkinObject( intf_thread_t *pIntf ): m_pIntf( pIntf ) {}
+        virtual ~SkinObject() {}
+
+        /// Getter (public because it is used in C callbacks in the win32
+        /// interface)
+        intf_thread_t *getIntf() const { return m_pIntf; }
+
+        /// Class for callbacks
+        class Callback {
+            public:
+                /// Type for callback methods
+                typedef void (*CallbackFunc_t)( SkinObject* );
+
+                /// Create a callback with the given object and function
+                Callback( SkinObject *pObj, CallbackFunc_t pFunc ):
+                    m_pObj( pObj ), m_pFunc( pFunc ) {}
+                ~Callback() {}
+
+                /// Getters
+                SkinObject *getObj() const { return m_pObj; }
+                CallbackFunc_t getFunc() const { return m_pFunc; }
+
+            private:
+                /// Pointer on the callback object
+                SkinObject *const m_pObj;
+                /// Pointer on the callback method
+                CallbackFunc_t m_pFunc;
+        };
+
+    private:
+        intf_thread_t *m_pIntf;
+};
+
+
+#endif
diff --git a/modules/gui/skins2/src/skin_main.cpp b/modules/gui/skins2/src/skin_main.cpp
new file mode 100644 (file)
index 0000000..c4ea5e1
--- /dev/null
@@ -0,0 +1,218 @@
+/*****************************************************************************
+ * skin_main.cpp
+ *****************************************************************************
+ * Copyright (C) 2003 VideoLAN
+ * $Id: skin_main.cpp,v 1.1 2004/01/03 23:31:34 asmax Exp $
+ *
+ * Authors: Cyril Deguet     <asmax@via.ecp.fr>
+ *          Olivier Teulière <ipkiss@via.ecp.fr>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111, USA.
+ *****************************************************************************/
+
+#include <stdlib.h>
+#include "generic_window.hpp"
+#include "dialogs.hpp"
+#include "os_factory.hpp"
+#include "os_loop.hpp"
+#include "window_manager.hpp"
+#include "var_manager.hpp"
+#include "vlcproc.hpp"
+#include "theme.hpp"
+#include "theme_loader.hpp"
+#include "../commands/async_queue.hpp"
+
+
+//---------------------------------------------------------------------------
+// Exported interface functions.
+//---------------------------------------------------------------------------
+#ifdef WIN32_SKINS
+extern "C" __declspec( dllexport )
+    int __VLC_SYMBOL( vlc_entry ) ( module_t *p_module );
+#endif
+
+
+//---------------------------------------------------------------------------
+// Local prototypes.
+//---------------------------------------------------------------------------
+static int  Open  ( vlc_object_t * );
+static void Close ( vlc_object_t * );
+static void Run   ( intf_thread_t * );
+
+
+//---------------------------------------------------------------------------
+// Open: initialize interface
+//---------------------------------------------------------------------------
+static int Open( vlc_object_t *p_this )
+{
+    intf_thread_t *p_intf = (intf_thread_t *)p_this;
+
+    // Allocate instance and initialize some members
+    p_intf->p_sys = (intf_sys_t *) malloc( sizeof( intf_sys_t ) );
+    if( p_intf->p_sys == NULL )
+    {
+        msg_Err( p_intf, "out of memory" );
+        return( VLC_ENOMEM );
+    };
+
+    p_intf->pf_run = Run;
+
+    // Suscribe to messages bank
+    p_intf->p_sys->p_sub = msg_Subscribe( p_intf );
+
+    p_intf->p_sys->p_input = NULL;
+    p_intf->p_sys->p_playlist = (playlist_t *)vlc_object_find( p_intf,
+        VLC_OBJECT_PLAYLIST, FIND_ANYWHERE );
+    if( p_intf->p_sys->p_playlist == NULL )
+    {
+        msg_Err( p_intf, "No playlist object found" );
+        return VLC_EGENERIC;
+    }
+
+    // Initialize "singleton" objects
+    p_intf->p_sys->p_logger = NULL;
+    p_intf->p_sys->p_queue = NULL;
+    p_intf->p_sys->p_dialogs = NULL;
+    p_intf->p_sys->p_osFactory = NULL;
+    p_intf->p_sys->p_osLoop = NULL;
+    p_intf->p_sys->p_varManager = NULL;
+    p_intf->p_sys->p_vlcProc = NULL;
+
+    // No theme yet
+    p_intf->p_sys->p_theme = NULL;
+
+    // Initialize singletons
+    if( AsyncQueue::instance( p_intf ) == NULL )
+    {
+        msg_Err( p_intf, "Cannot initialize AsyncQueue" );
+        return VLC_EGENERIC;
+    }
+    if( OSFactory::instance( p_intf ) == NULL )
+    {
+        msg_Err( p_intf, "Cannot initialize OSFactory" );
+        return VLC_EGENERIC;
+    }
+    if( VarManager::instance( p_intf ) == NULL )
+    {
+        msg_Err( p_intf, "Cannot instanciate VarManager" );
+        return VLC_EGENERIC;
+    }
+    if( VlcProc::instance( p_intf ) == NULL )
+    {
+        msg_Err( p_intf, "Cannot initialize VLCProc" );
+        return VLC_EGENERIC;
+    }
+    Dialogs::instance( p_intf );
+
+    return( VLC_SUCCESS );
+}
+
+//---------------------------------------------------------------------------
+// Close: destroy interface
+//---------------------------------------------------------------------------
+static void Close( vlc_object_t *p_this )
+{
+    intf_thread_t *p_intf = (intf_thread_t *)p_this;
+
+    // Destroy "singleton" objects
+    VlcProc::destroy( p_intf );
+    OSFactory::instance( p_intf )->destroyOSLoop();
+    OSFactory::destroy( p_intf );
+    Dialogs::destroy( p_intf );
+    AsyncQueue::destroy( p_intf );
+    VarManager::destroy( p_intf );
+
+    if( p_intf->p_sys->p_input )
+    {
+        vlc_object_release( p_intf->p_sys->p_input );
+    }
+
+    if( p_intf->p_sys->p_playlist )
+    {
+        vlc_object_release( p_intf->p_sys->p_playlist );
+    }
+
+   // Unsuscribe to messages bank
+    msg_Unsubscribe( p_intf, p_intf->p_sys->p_sub );
+
+    // Destroy structure
+    free( p_intf->p_sys );
+}
+
+
+//---------------------------------------------------------------------------
+// Run: main loop
+//---------------------------------------------------------------------------
+static void Run( intf_thread_t *p_intf )
+{
+    // Load a theme
+    ThemeLoader *pLoader = new ThemeLoader( p_intf );
+    char *skin_last = config_GetPsz( p_intf, "skin_last2" );
+
+    if( skin_last == NULL || !pLoader->load( skin_last ) )
+    {
+        // Too bad, it failed. Let's try with the default theme
+#ifdef WIN32_SKINS
+        string default_dir = (string)p_intf->p_libvlc->psz_vlcpath +
+                             "\\skins\\default\\theme.xml";
+        if( !pLoader->load( default_dir ) )
+#else
+        string user_skin = (string)p_intf->p_vlc->psz_homedir +
+                           "/" + CONFIG_DIR + "/skins/default/theme.xml";
+
+        string default_skin = (string)DATA_PATH + "/skins/default/theme.xml";
+        if( !pLoader->load( user_skin ) && !pLoader->load( default_skin ) )
+#endif
+        {
+            // Last chance: the user can select a new theme file (blocking call)
+            Dialogs *pDialogs = Dialogs::instance( p_intf );
+            pDialogs->showChangeSkin();
+        }
+    }
+    delete pLoader;
+
+    if( skin_last )
+    {
+        free( skin_last );
+    }
+
+    // Get the instance of OSLoop
+    OSLoop *loop = OSFactory::instance( p_intf )->getOSLoop();
+    loop->run();
+
+    // Delete the theme
+    if( p_intf->p_sys->p_theme )
+    {
+        delete p_intf->p_sys->p_theme;
+        p_intf->p_sys->p_theme = NULL;
+    }
+}
+
+//---------------------------------------------------------------------------
+// Module descriptor
+//---------------------------------------------------------------------------
+#define DEFAULT_SKIN        N_("Last skin used")
+#define DEFAULT_SKIN_LONG   N_("Select the path to the last skin used")
+
+vlc_module_begin();
+// XXX
+    add_string( "skin_last2", "", NULL, DEFAULT_SKIN, DEFAULT_SKIN_LONG,
+                VLC_TRUE );
+    set_description( _("Skinnable Interface") );
+    set_capability( "interface", 30 );
+    set_callbacks( Open, Close );
+    set_program( "svlc" );
+vlc_module_end();
+
diff --git a/modules/gui/skins2/src/theme.cpp b/modules/gui/skins2/src/theme.cpp
new file mode 100755 (executable)
index 0000000..d12e550
--- /dev/null
@@ -0,0 +1,76 @@
+/*****************************************************************************
+ * theme.cpp
+ *****************************************************************************
+ * Copyright (C) 2003 VideoLAN
+ * $Id: theme.cpp,v 1.1 2004/01/03 23:31:34 asmax Exp $
+ *
+ * Authors: Cyril Deguet     <asmax@via.ecp.fr>
+ *          Olivier Teulière <ipkiss@via.ecp.fr>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111, USA.
+ *****************************************************************************/
+
+#include "theme.hpp"
+
+
+Theme::~Theme()
+{
+    // Be sure things are destroyed in the right order (XXX check)
+    m_layouts.clear();
+    m_controls.clear();
+    m_windows.clear();
+    m_bitmaps.clear();
+    m_fonts.clear();
+    m_commands.clear();
+    m_vars.clear();
+}
+
+
+// Useful macro
+#define FIND_OBJECT( mapData, mapName ) \
+    map<string, mapData>::const_iterator it; \
+    it = mapName.find( id ); \
+    if( it == mapName.end() ) \
+    { \
+        return NULL; \
+    } \
+    return (*it).second.get();
+
+
+GenericBitmap *Theme::getBitmapById( const string &id )
+{
+    FIND_OBJECT( GenericBitmapPtr, m_bitmaps );
+}
+
+GenericFont *Theme::getFontById( const string &id )
+{
+    FIND_OBJECT( GenericFontPtr, m_fonts );
+}
+
+GenericWindow *Theme::getWindowById( const string &id )
+{
+    FIND_OBJECT( GenericWindowPtr, m_windows );
+}
+
+GenericLayout *Theme::getLayoutById( const string &id )
+{
+    FIND_OBJECT( GenericLayoutPtr, m_layouts );
+}
+
+CtrlGeneric *Theme::getControlById( const string &id )
+{
+    FIND_OBJECT( CtrlGenericPtr, m_controls );
+}
+
diff --git a/modules/gui/skins2/src/theme.hpp b/modules/gui/skins2/src/theme.hpp
new file mode 100755 (executable)
index 0000000..ebb11f0
--- /dev/null
@@ -0,0 +1,80 @@
+/*****************************************************************************
+ * theme.hpp
+ *****************************************************************************
+ * Copyright (C) 2003 VideoLAN
+ * $Id: theme.hpp,v 1.1 2004/01/03 23:31:34 asmax Exp $
+ *
+ * Authors: Cyril Deguet     <asmax@via.ecp.fr>
+ *          Olivier Teulière <ipkiss@via.ecp.fr>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111, USA.
+ *****************************************************************************/
+
+#ifndef THEME_HPP
+#define THEME_HPP
+
+#include "../src/generic_bitmap.hpp"
+#include "../src/generic_font.hpp"
+#include "../src/generic_window.hpp"
+#include "../src/generic_layout.hpp"
+#include "../src/window_manager.hpp"
+#include "../commands/cmd_generic.hpp"
+#include "../utils/variable.hpp"
+#include "../controls/ctrl_generic.hpp"
+#include <string>
+#include <list>
+#include <map>
+
+
+/// Class storing the data of the current theme
+class Theme: public SkinObject
+{
+    public:
+        Theme( intf_thread_t *pIntf ): SkinObject( pIntf ),
+            m_windowManager( getIntf() ) {}
+        virtual ~Theme();
+
+        GenericBitmap *getBitmapById( const string &id );
+        GenericFont *getFontById( const string &id );
+        GenericWindow *getWindowById( const string &id );
+        GenericLayout *getLayoutById( const string &id );
+        CtrlGeneric *getControlById( const string &id );
+
+        WindowManager &getWindowManager() { return m_windowManager; }
+
+        // XXX: It would be nicer to put everything private, and have the
+        // builder and interpreter classes as friends of this one
+//     private:
+        /// Store the bitmaps by ID
+        map<string, GenericBitmapPtr> m_bitmaps;
+        /// Store the fonts by ID
+        map<string, GenericFontPtr> m_fonts;
+        /// Store the windows by ID
+        map<string, GenericWindowPtr> m_windows;
+        /// Store the layouts by ID
+        map<string, GenericLayoutPtr> m_layouts;
+        /// Store the controls by ID
+        map<string, CtrlGenericPtr> m_controls;
+        /// Store the commands
+        list<CmdGenericPtr> m_commands;
+        /// Store the variables
+        list<VariablePtr> m_vars;
+
+    private:
+        WindowManager m_windowManager;
+};
+
+
+#endif
diff --git a/modules/gui/skins2/src/theme_loader.cpp b/modules/gui/skins2/src/theme_loader.cpp
new file mode 100755 (executable)
index 0000000..3741faa
--- /dev/null
@@ -0,0 +1,508 @@
+/*****************************************************************************
+ * theme_loader.cpp
+ *****************************************************************************
+ * Copyright (C) 2003 VideoLAN
+ * $Id: theme_loader.cpp,v 1.1 2004/01/03 23:31:34 asmax Exp $
+ *
+ * Authors: Cyril Deguet     <asmax@via.ecp.fr>
+ *          Olivier Teulière <ipkiss@via.ecp.fr>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111, USA.
+ *****************************************************************************/
+
+#include "theme_loader.hpp"
+#include "theme.hpp"
+#include "../parser/builder.hpp"
+#include "../parser/parser_context.hpp"
+#include "../src/os_factory.hpp"
+#include "../src/window_manager.hpp"
+
+#include <fcntl.h>
+#if !defined( WIN32 )
+#   include <unistd.h>
+#else
+#   include <direct.h>
+#endif
+
+
+#if defined( HAVE_ZLIB_H )
+#   include <zlib.h>
+#   include <errno.h>
+int gzopen_frontend( char *pathname, int oflags, int mode );
+#if defined( HAVE_LIBTAR_H )
+#   include <libtar.h>
+#else
+typedef gzFile TAR;
+int tar_open        ( TAR **t, char *pathname, int oflags );
+int tar_extract_all ( TAR *t, char *prefix );
+int tar_close       ( TAR *t );
+#endif
+#endif
+
+#define DEFAULT_XML_FILE "theme.xml"
+
+extern "C"
+{
+    extern FILE *yyin;
+    int yylex( void *pContext );
+}
+
+bool ThemeLoader::load( const string &fileName )
+{
+    // First, we try to un-targz the file, and if it fails we hope it's a XML
+    // file...
+#if defined( HAVE_ZLIB_H )
+    if( ! extract( fileName ) && ! parse( fileName ) )
+        return false;
+#else
+    if( ! parse( fileName ) )
+        return false;
+#endif
+
+#if 0
+    // Check if the skin to load is in the config file, to load its config
+    char *skin_last = config_GetPsz( getIntf(), "skin_last" );
+    if( skin_last != NULL && fileName == (string)skin_last )
+    {
+        getIntf()->p_sys->p_theme->LoadConfig();
+    }
+    else
+    {
+        config_PutPsz( getIntf(), "skin_last", fileName.c_str() );
+        config_SaveConfigFile( getIntf(), "skins" );
+    }
+#endif
+    Theme *pNewTheme = getIntf()->p_sys->p_theme;
+    if( pNewTheme )
+    {
+        // Used to anchor the windows at the beginning
+        pNewTheme->getWindowManager().stopMove();
+        // Show the windows
+        pNewTheme->getWindowManager().showAll();
+    }
+
+    return true;
+}
+
+
+#if defined( HAVE_ZLIB_H )
+bool ThemeLoader::extractTarGz( const string &tarFile, const string &rootDir )
+{
+    TAR *t;
+#if defined( HAVE_LIBTAR_H )
+    tartype_t gztype = { (openfunc_t) gzopen_frontend, (closefunc_t) gzclose,
+        (readfunc_t) gzread, (writefunc_t) gzwrite };
+
+    if( tar_open( &t, (char *)tarFile.c_str(), &gztype, O_RDONLY, 0,
+                  TAR_GNU ) == -1 )
+#else
+    if( tar_open( &t, (char *)tarFile.c_str(), O_RDONLY ) == -1 )
+#endif
+    {
+        return false;
+    }
+
+    if( tar_extract_all( t, (char *)rootDir.c_str() ) != 0 )
+    {
+        tar_close( t );
+        return false;
+    }
+
+    if( tar_close( t ) != 0 )
+    {
+        return false;
+    }
+
+    return true;
+}
+
+
+bool ThemeLoader::extract( const string &fileName )
+{
+    char *tmpdir = tempnam( NULL, "vlt" );
+    string tempPath = tmpdir;
+    free( tmpdir );
+
+    // Extract the file in a temporary directory
+    if( ! extractTarGz( fileName, tempPath ) )
+        return false;
+
+    // Parse the extracted XML file
+    const string &sep = OSFactory::instance( getIntf() )->getDirSeparator();
+    if( ! parse( tempPath + sep + string( DEFAULT_XML_FILE ) ) )
+    {
+        msg_Err( getIntf(), "%s doesn't contain a " DEFAULT_XML_FILE " file",
+                 fileName.c_str() );
+        deleteTempFiles( tempPath );
+        return false;
+    }
+
+    // Clean-up
+    deleteTempFiles( tempPath );
+    return true;
+}
+
+
+void ThemeLoader::deleteTempFiles( const string &path )
+{
+    OSFactory::instance( getIntf() )->rmDir( path );
+}
+#endif // HAVE_ZLIB_H
+
+
+bool ThemeLoader::parse( const string &xmlFile )
+{
+    // Things to do before loading theme
+//     getIntf()->p_sys->p_theme->OnLoadTheme();
+    // Set the file to parse
+    yyin = fopen( xmlFile.c_str(), "r" );
+    if( yyin == NULL )
+    {
+        // Skin cannot be opened
+        msg_Err( getIntf(), "Cannot open the specified skin file: %s",
+                 xmlFile.c_str() );
+        return false;
+    }
+
+    // File loaded
+    msg_Dbg( getIntf(), "Using skin file: %s", xmlFile.c_str() );
+
+    // Save current working directory
+    char *cwd = new char[PATH_MAX];
+    getcwd( cwd, PATH_MAX );
+
+    // Change current working directory to xml file
+    const string &sep = OSFactory::instance( getIntf() )->getDirSeparator();
+    unsigned int p = xmlFile.rfind( sep, xmlFile.size() );
+    if( p != string::npos )
+    {
+        string path = xmlFile.substr( 0, p );
+        chdir( path.c_str() );
+    }
+
+    // Start the parser
+    ParserContext context( getIntf() );
+    int lex = yylex( &context );
+    fclose( yyin );
+
+    if( lex )
+    {
+        // Set old working directory to current
+        chdir( cwd );
+        delete[] cwd;
+
+        msg_Warn( getIntf(), "yylex failed: %i", lex );
+        return false;
+    }
+
+    // Build and store the theme
+    Builder builder( getIntf(), context.m_data );
+    getIntf()->p_sys->p_theme = builder.build();
+
+    // Set old working directory to current.
+    // We need to do that _after_ calling Builder:build(), otherwise the
+    // opening of the files will fail
+    chdir( cwd );
+    delete[] cwd;
+
+    return true;
+}
+
+
+#if !defined( HAVE_LIBTAR_H ) && defined( HAVE_ZLIB_H )
+
+#ifdef WIN32
+#  define mkdir(dirname,mode) _mkdir(dirname)
+#endif
+
+/* Values used in typeflag field */
+#define REGTYPE  '0'            /* regular file */
+#define AREGTYPE '\0'           /* regular file */
+#define DIRTYPE  '5'            /* directory */
+
+#define BLOCKSIZE 512
+
+struct tar_header
+{                               /* byte offset */
+    char name[100];             /*   0 */
+    char mode[8];               /* 100 */
+    char uid[8];                /* 108 */
+    char gid[8];                /* 116 */
+    char size[12];              /* 124 */
+    char mtime[12];             /* 136 */
+    char chksum[8];             /* 148 */
+    char typeflag;              /* 156 */
+    char linkname[100];         /* 157 */
+    char magic[6];              /* 257 */
+    char version[2];            /* 263 */
+    char uname[32];             /* 265 */
+    char gname[32];             /* 297 */
+    char devmajor[8];           /* 329 */
+    char devminor[8];           /* 337 */
+    char prefix[155];           /* 345 */
+                                /* 500 */
+};
+
+
+union tar_buffer {
+    char              buffer[BLOCKSIZE];
+    struct tar_header header;
+};
+
+
+/* helper functions */
+int getoct( char *p, int width );
+int makedir( char *newdir );
+
+int tar_open( TAR **t, char *pathname, int oflags )
+{
+    gzFile f = gzopen( pathname, "rb" );
+    if( f == NULL )
+    {
+        fprintf( stderr, "Couldn't gzopen %s\n", pathname );
+        return -1;
+    }
+
+    *t = (gzFile *)malloc( sizeof(gzFile) );
+    **t = f;
+    return 0;
+}
+
+
+int tar_extract_all( TAR *t, char *prefix )
+{
+    union tar_buffer buffer;
+    int   len, err, getheader = 1, remaining = 0;
+    FILE  *outfile = NULL;
+    char  fname[BLOCKSIZE + PATH_MAX];
+
+    while( 1 )
+    {
+        len = gzread( *t, &buffer, BLOCKSIZE );
+        if( len < 0 )
+        {
+            fprintf( stderr, "%s\n", gzerror(*t, &err) );
+        }
+
+        /*
+         * Always expect complete blocks to process
+         * the tar information.
+         */
+        if( len != 0 && len != BLOCKSIZE )
+        {
+            fprintf( stderr, "gzread: incomplete block read\n" );
+            return -1;
+        }
+
+        /*
+         * If we have to get a tar header
+         */
+        if( getheader == 1 )
+        {
+            /*
+             * If we met the end of the tar
+             * or the end-of-tar block, we are done
+             */
+            if( (len == 0) || (buffer.header.name[0] == 0) )
+            {
+                break;
+            }
+
+            sprintf( fname, "%s/%s", prefix, buffer.header.name );
+
+            /* Check magic value in header */
+            if( strncmp( buffer.header.magic, "GNUtar", 6 ) &&
+                strncmp( buffer.header.magic, "ustar", 5 ) )
+            {
+                //fprintf(stderr, "not a tar file\n");
+                return -1;
+            }
+
+            switch( buffer.header.typeflag )
+            {
+                case DIRTYPE:
+                    makedir( fname );
+                    break;
+                case REGTYPE:
+                case AREGTYPE:
+                    remaining = getoct( buffer.header.size, 12 );
+                    if( remaining )
+                    {
+                        outfile = fopen( fname, "wb" );
+                        if( outfile == NULL )
+                        {
+                            /* try creating directory */
+                            char *p = strrchr( fname, '/' );
+                            if( p != NULL )
+                            {
+                                *p = '\0';
+                                makedir( fname );
+                                *p = '/';
+                                outfile = fopen( fname, "wb" );
+                                if( !outfile )
+                                {
+                                    fprintf( stderr, "tar couldn't create %s\n",
+                                             fname );
+                                }
+                            }
+                        }
+                    }
+                    else outfile = NULL;
+
+                /*
+                 * could have no contents
+                 */
+                getheader = (remaining) ? 0 : 1;
+                break;
+            default:
+                break;
+            }
+        }
+        else
+        {
+            unsigned int bytes = (remaining > BLOCKSIZE)?BLOCKSIZE:remaining;
+
+            if( outfile != NULL )
+            {
+                if( fwrite( &buffer, sizeof(char), bytes, outfile ) != bytes )
+                {
+                    fprintf( stderr, "error writing %s skipping...\n", fname );
+                    fclose( outfile );
+                    unlink( fname );
+                }
+            }
+            remaining -= bytes;
+            if( remaining == 0 )
+            {
+                getheader = 1;
+                if( outfile != NULL )
+                {
+                    fclose(outfile);
+                    outfile = NULL;
+                }
+            }
+        }
+    }
+
+    return 0;
+}
+
+
+int tar_close( TAR *t )
+{
+    if( gzclose( *t ) != Z_OK ) fprintf( stderr, "failed gzclose\n" );
+    free( t );
+    return 0;
+}
+
+
+/* helper functions */
+int getoct( char *p, int width )
+{
+    int result = 0;
+    char c;
+
+    while( width-- )
+    {
+        c = *p++;
+        if( c == ' ' )
+            continue;
+        if( c == 0 )
+            break;
+        result = result * 8 + (c - '0');
+    }
+    return result;
+}
+
+
+/* Recursive make directory
+ * Abort if you get an ENOENT errno somewhere in the middle
+ * e.g. ignore error "mkdir on existing directory"
+ *
+ * return 1 if OK, 0 on error
+ */
+int makedir( char *newdir )
+{
+    char *p, *buffer = strdup( newdir );
+    int  len = strlen( buffer );
+
+    if( len <= 0 )
+    {
+        free( buffer );
+        return 0;
+    }
+
+    if( buffer[len-1] == '/' )
+    {
+        buffer[len-1] = '\0';
+    }
+
+    if( mkdir( buffer, 0775 ) == 0 )
+    {
+        free( buffer );
+        return 1;
+    }
+
+    p = buffer + 1;
+    while( 1 )
+    {
+        char hold;
+
+        while( *p && *p != '\\' && *p != '/' ) p++;
+        hold = *p;
+        *p = 0;
+        if( ( mkdir( buffer, 0775 ) == -1 ) && ( errno == ENOENT ) )
+        {
+            fprintf( stderr, "couldn't create directory %s\n", buffer );
+            free( buffer );
+            return 0;
+        }
+        if( hold == 0 ) break;
+        *p++ = hold;
+    }
+    free( buffer );
+    return 1;
+}
+
+int gzopen_frontend( char *pathname, int oflags, int mode )
+{
+    char *gzflags;
+    gzFile gzf;
+
+    switch( oflags & O_ACCMODE )
+    {
+        case O_WRONLY:
+            gzflags = "wb";
+            break;
+        case O_RDONLY:
+            gzflags = "rb";
+            break;
+        case O_RDWR:
+        default:
+            errno = EINVAL;
+            return -1;
+    }
+
+    gzf = gzopen( pathname, gzflags );
+    if( !gzf )
+    {
+        errno = ENOMEM;
+        return -1;
+    }
+
+    return (int)gzf;
+}
+
+#endif
diff --git a/modules/gui/skins2/src/theme_loader.hpp b/modules/gui/skins2/src/theme_loader.hpp
new file mode 100755 (executable)
index 0000000..73dedf8
--- /dev/null
@@ -0,0 +1,49 @@
+/*****************************************************************************
+ * theme_loader.hpp
+ *****************************************************************************
+ * Copyright (C) 2003 VideoLAN
+ * $Id: theme_loader.hpp,v 1.1 2004/01/03 23:31:34 asmax Exp $
+ *
+ * Authors: Cyril Deguet     <asmax@via.ecp.fr>
+ *          Olivier Teulière <ipkiss@via.ecp.fr>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111, USA.
+ *****************************************************************************/
+
+#ifndef THEME_LOADER_HPP
+#define THEME_LOADER_HPP
+
+#include "skin_common.hpp"
+#include <string>
+
+
+class ThemeLoader: public SkinObject
+{
+    public:
+        ThemeLoader( intf_thread_t *pIntf ): SkinObject( pIntf ) {}
+        virtual ~ThemeLoader() {}
+
+        bool load( const string &fileName );
+
+    private:
+#if defined( HAVE_ZLIB_H )
+        bool extractTarGz( const string &tarFile, const string &rootDir );
+        bool extract( const string &fileName );
+        void deleteTempFiles( const string &path );
+#endif
+        bool parse( const string &xmlFile );
+};
+
+#endif
diff --git a/modules/gui/skins2/src/tooltip.cpp b/modules/gui/skins2/src/tooltip.cpp
new file mode 100644 (file)
index 0000000..8fceafc
--- /dev/null
@@ -0,0 +1,154 @@
+/*****************************************************************************
+ * tooltip.cpp
+ *****************************************************************************
+ * Copyright (C) 2003 VideoLAN
+ * $Id: tooltip.cpp,v 1.1 2004/01/03 23:31:34 asmax Exp $
+ *
+ * Authors: Cyril Deguet     <asmax@via.ecp.fr>
+ *          Olivier Teulière <ipkiss@via.ecp.fr>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111, USA.
+ *****************************************************************************/
+
+#include "tooltip.hpp"
+#include "generic_bitmap.hpp"
+#include "generic_font.hpp"
+#include "os_factory.hpp"
+#include "os_graphics.hpp"
+#include "os_tooltip.hpp"
+#include "os_timer.hpp"
+#include "var_manager.hpp"
+#include "../utils/ustring.hpp"
+
+
+Tooltip::Tooltip( intf_thread_t *pIntf, const GenericFont &rFont, int delay ):
+    SkinObject( pIntf ), m_rFont( rFont ), m_delay( delay ), m_pImage( NULL ),
+    m_xPos( -1 ), m_yPos( -1 )
+{
+    OSFactory *pOsFactory = OSFactory::instance( pIntf );
+    m_pTimer = pOsFactory->createOSTimer( Callback( this, &doShow ) );
+    m_pOsTooltip = pOsFactory->createOSTooltip();
+
+    // Observe the tooltip text variable
+    VarManager::instance( pIntf )->getTooltipText().addObserver( this );
+}
+
+
+Tooltip::~Tooltip()
+{
+    VarManager::instance( getIntf() )->getTooltipText().delObserver( this );
+    SKINS_DELETE( m_pTimer );
+    SKINS_DELETE( m_pOsTooltip );
+    if( m_pImage )
+    {
+        delete m_pImage;
+    }
+}
+
+
+void Tooltip::show()
+{
+    // (Re)start the timer
+    m_pTimer->start( m_delay, true );
+}
+
+
+void Tooltip::hide()
+{
+    m_pTimer->stop();
+    m_pOsTooltip->hide();
+    m_xPos = -1;
+    m_yPos = -1;
+}
+
+
+void Tooltip::onUpdate( Subject<VarText> &rVariable )
+{
+    // Redisplay the tooltip
+    displayText( ((VarText&)rVariable).get() );
+}
+
+
+void Tooltip::displayText( const UString &rText )
+{
+    // Rebuild the image
+    makeImage( rText );
+
+    // Redraw the window if it is already visible
+    if( m_xPos != -1 )
+    {
+        m_pOsTooltip->show( m_xPos, m_yPos, *m_pImage );
+    }
+}
+
+
+void Tooltip::makeImage( const UString &rText )
+{
+    // Render the text on a bitmap
+    GenericBitmap *pBmpTip = m_rFont.drawString( rText, 0 );
+    int w = pBmpTip->getWidth() + 10;
+    int h = m_rFont.getSize() + 8;
+
+    // Create the image of the tooltip
+    if( m_pImage )
+    {
+        delete m_pImage;
+    }
+    m_pImage = OSFactory::instance( getIntf() )->createOSGraphics( w, h );
+    m_pImage->fillRect( 0, 0, w, h, 0xffffd0 );
+    m_pImage->drawRect( 0, 0, w, h, 0x000000 );
+    m_pImage->drawBitmap( *pBmpTip, 0, 0, 5, 5 );
+
+    delete pBmpTip;
+}
+
+
+void Tooltip::doShow( SkinObject *pObj )
+{
+    Tooltip *pThis = (Tooltip*)pObj;
+
+    if( pThis->m_pImage )
+    {
+        if( pThis->m_xPos == -1 )
+        {
+            // Get the mouse coordinates and the image size
+            OSFactory *pOsFactory = OSFactory::instance( pThis->getIntf() );
+            int x, y;
+            pOsFactory->getMousePos( x, y );
+            int scrWidth = pOsFactory->getScreenWidth();
+            int scrHeight = pOsFactory->getScreenHeight();
+            int w = pThis->m_pImage->getWidth();
+            int h = pThis->m_pImage->getHeight();
+
+            // Compute the position of the tooltip
+            x -= (w / 2 + 4);
+            y += (h + 5);
+            if( x + w > scrWidth )
+                x -= (x + w - scrWidth);
+            else if( x < 0 )
+                x = 0;
+            if( y + h > scrHeight )
+                y -= (2 * h + 20);
+
+            pThis->m_xPos = x;
+            pThis->m_yPos = y;
+        }
+
+        // Show the tooltip window
+        pThis->m_pOsTooltip->show( pThis->m_xPos, pThis->m_yPos,
+                                   *(pThis->m_pImage) );
+    }
+}
+
diff --git a/modules/gui/skins2/src/tooltip.hpp b/modules/gui/skins2/src/tooltip.hpp
new file mode 100644 (file)
index 0000000..6084887
--- /dev/null
@@ -0,0 +1,80 @@
+/*****************************************************************************
+ * tooltip.hpp
+ *****************************************************************************
+ * Copyright (C) 2003 VideoLAN
+ * $Id: tooltip.hpp,v 1.1 2004/01/03 23:31:34 asmax Exp $
+ *
+ * Authors: Cyril Deguet     <asmax@via.ecp.fr>
+ *          Olivier Teulière <ipkiss@via.ecp.fr>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111, USA.
+ *****************************************************************************/
+
+#ifndef TOOLTIP_HPP
+#define TOOLTIP_HPP
+
+#include "../utils/var_text.hpp"
+
+class GenericFont;
+class OSTooltip;
+class OSTimer;
+class OSGraphics;
+class UString;
+
+
+class Tooltip: public SkinObject, public Observer<VarText>
+{
+    public:
+        /// Create a tooltip with the given font and delay (in milliseconds)
+        Tooltip( intf_thread_t *pIntf, const GenericFont &rFont, int delay );
+
+        virtual ~Tooltip();
+
+        /// Draw the tooltip and show it after the delay
+        void show();
+
+        /// Hide the tooltip and cancel the timer if a tooltip is waiting for
+        /// display
+        void hide();
+
+    private:
+        /// Font
+        const GenericFont &m_rFont;
+        /// Delay before popping the tooltip
+        int m_delay;
+        /// Timer to wait before showing the tooltip
+        OSTimer *m_pTimer;
+        /// OS specific tooltip window
+        OSTooltip *m_pOsTooltip;
+        /// Image of the tooltip
+        OSGraphics *m_pImage;
+        /// Position of the tooltip
+        int m_xPos, m_yPos;
+
+        /// Method called when the observed variable is modified
+        virtual void onUpdate( Subject<VarText> &rVariable );
+
+        /// Display text of the tooltip
+        void displayText( const UString &rText );
+
+        /// Build m_pImage with the given text
+        void makeImage( const UString &rText );
+
+        /// Show the tooltip window
+        static void doShow( SkinObject *pObj );
+};
+
+
+#endif
diff --git a/modules/gui/skins2/src/var_manager.cpp b/modules/gui/skins2/src/var_manager.cpp
new file mode 100644 (file)
index 0000000..caa61e1
--- /dev/null
@@ -0,0 +1,57 @@
+/*****************************************************************************
+ * var_manager.cpp
+ *****************************************************************************
+ * Copyright (C) 2003 VideoLAN
+ * $Id: var_manager.cpp,v 1.1 2004/01/03 23:31:34 asmax Exp $
+ *
+ * Authors: Cyril Deguet     <asmax@via.ecp.fr>
+ *          Olivier Teulière <ipkiss@via.ecp.fr>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111, USA.
+ *****************************************************************************/
+
+#include "var_manager.hpp"
+
+
+VarManager::VarManager( intf_thread_t *pIntf ): SkinObject( pIntf ),
+    m_tooltip( pIntf ), m_help( pIntf )
+{
+}
+
+
+VarManager *VarManager::instance( intf_thread_t *pIntf )
+{
+    if( ! pIntf->p_sys->p_varManager )
+    {
+        VarManager *pVarManager;
+        pVarManager = new VarManager( pIntf );
+        if( pVarManager )
+        {
+            pIntf->p_sys->p_varManager = pVarManager;
+        }
+    }
+    return pIntf->p_sys->p_varManager;
+}
+
+
+void VarManager::destroy( intf_thread_t *pIntf )
+{
+    if( pIntf->p_sys->p_varManager )
+    {
+        delete pIntf->p_sys->p_varManager;
+        pIntf->p_sys->p_varManager = NULL;
+    }
+}
+
diff --git a/modules/gui/skins2/src/var_manager.hpp b/modules/gui/skins2/src/var_manager.hpp
new file mode 100644 (file)
index 0000000..8dd04ee
--- /dev/null
@@ -0,0 +1,58 @@
+/*****************************************************************************
+ * var_manager.hpp
+ *****************************************************************************
+ * Copyright (C) 2003 VideoLAN
+ * $Id: var_manager.hpp,v 1.1 2004/01/03 23:31:34 asmax Exp $
+ *
+ * Authors: Cyril Deguet     <asmax@via.ecp.fr>
+ *          Olivier Teulière <ipkiss@via.ecp.fr>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111, USA.
+ *****************************************************************************/
+
+#ifndef VAR_MANAGER_HPP
+#define VAR_MANAGER_HPP
+
+#include "../utils/var_text.hpp"
+
+
+class VarManager: public SkinObject
+{
+    public:
+        /// Get the instance of VarManager
+        static VarManager *instance( intf_thread_t *pIntf );
+
+        /// Delete the instance of VarManager
+        static void destroy( intf_thread_t *pIntf );
+
+        /// Get the tooltip text variable
+        VarText &getTooltipText() { return m_tooltip; }
+
+        /// Get the help text variable
+        VarText &getHelpText() { return m_help; }
+
+    private:
+        /// Tooltip text
+        VarText m_tooltip;
+        /// Help text
+        VarText m_help;
+
+        /// Private because it is a singleton
+        VarManager( intf_thread_t *pIntf );
+        virtual ~VarManager() {}
+};
+
+
+#endif
diff --git a/modules/gui/skins2/src/vlcproc.cpp b/modules/gui/skins2/src/vlcproc.cpp
new file mode 100755 (executable)
index 0000000..106aa5d
--- /dev/null
@@ -0,0 +1,178 @@
+/*****************************************************************************
+ * vlcproc.cpp
+ *****************************************************************************
+ * Copyright (C) 2003 VideoLAN
+ * $Id: vlcproc.cpp,v 1.1 2004/01/03 23:31:34 asmax Exp $
+ *
+ * Authors: Cyril Deguet     <asmax@via.ecp.fr>
+ *          Olivier Teulière <ipkiss@via.ecp.fr>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111, USA.
+ *****************************************************************************/
+
+#include <vlc/aout.h>
+
+#include "vlcproc.hpp"
+#include "os_factory.hpp"
+#include "os_timer.hpp"
+#include "../commands/async_queue.hpp"
+#include "../commands/cmd_notify_playlist.hpp"
+#include "../commands/cmd_quit.hpp"
+
+
+
+VlcProc *VlcProc::instance( intf_thread_t *pIntf )
+{
+    if( pIntf->p_sys->p_vlcProc == NULL )
+    {
+        pIntf->p_sys->p_vlcProc = new VlcProc( pIntf );
+    }
+
+    return pIntf->p_sys->p_vlcProc;
+}
+
+
+void VlcProc::destroy( intf_thread_t *pIntf )
+{
+    if( pIntf->p_sys->p_vlcProc )
+    {
+        delete pIntf->p_sys->p_vlcProc;
+        pIntf->p_sys->p_vlcProc = NULL;
+    }
+}
+
+
+VlcProc::VlcProc( intf_thread_t *pIntf ):
+    SkinObject( pIntf ), m_playlist( pIntf), m_varTime( pIntf ),
+    m_varVolume( pIntf ), m_varMute( pIntf ), m_varPlaying( pIntf ),
+    m_varSeekablePlaying( pIntf )
+{
+    // Create a timer to poll the status of the vlc
+    OSFactory *pOsFactory = OSFactory::instance( pIntf );
+    m_pTimer = pOsFactory->createOSTimer( Callback( this, &doManage ) );
+    m_pTimer->start( 100, false );
+
+    // Callbacks for object variables
+    var_AddCallback( pIntf->p_sys-> p_playlist, "intf-change",
+                     onPlaylistChange, this );
+
+    getIntf()->p_sys->p_input = NULL;
+}
+
+
+VlcProc::~VlcProc()
+{
+    m_pTimer->stop();
+    delete( m_pTimer );
+    if( getIntf()->p_sys->p_input )
+    {
+        vlc_object_release( getIntf()->p_sys->p_input );
+    }
+}
+
+
+void VlcProc::manage()
+{
+    // Did the user requested to quit vlc ?
+    if( getIntf()->p_vlc->b_die )
+    {
+        CmdQuit *pCmd = new CmdQuit( getIntf() );
+        AsyncQueue *pQueue = AsyncQueue::instance( getIntf() );
+        pQueue->push( CmdGenericPtr( pCmd ) );
+    }
+
+    // Refresh sound volume
+    audio_volume_t volume;
+    aout_VolumeGet( getIntf(), &volume);
+    m_varVolume.set( (double)volume / AOUT_VOLUME_MAX );
+
+    // Update the input
+    if( getIntf()->p_sys->p_input == NULL )
+    {
+        getIntf()->p_sys->p_input = (input_thread_t *)vlc_object_find(
+            getIntf(), VLC_OBJECT_INPUT, FIND_ANYWHERE );
+    }
+    else if( getIntf()->p_sys->p_input->b_dead )
+    {
+        vlc_object_release( getIntf()->p_sys->p_input );
+        getIntf()->p_sys->p_input = NULL;
+    }
+
+    input_thread_t *pInput = getIntf()->p_sys->p_input;
+
+    if( pInput && !pInput->b_die )
+    {
+        // Refresh time variables
+        if( pInput->stream.b_seekable )
+        {
+            // Refresh position in the stream
+            vlc_value_t pos;
+            var_Get( pInput, "position", &pos );
+            if( pos.f_float >= 0.0 )
+            {
+                m_varTime.set( pos.f_float, false );
+            }
+        }
+        else
+        {
+            m_varTime.set( 0, false );
+        }
+
+        // Get the status of the playlist
+        playlist_status_t status = getIntf()->p_sys->p_playlist->i_status;
+
+        m_varPlaying.set( status == PLAYLIST_RUNNING, false );
+        if( pInput->stream.b_seekable )
+        {
+            m_varSeekablePlaying.set( status != PLAYLIST_STOPPED );
+        }
+        else
+        {
+            m_varSeekablePlaying.set( false );
+        }
+    }
+    else
+    {
+        m_varPlaying.set( false, false );
+        m_varSeekablePlaying.set( false );
+        m_varTime.set( 0, false );
+    }
+}
+
+
+void VlcProc::doManage( SkinObject *pObj )
+{
+    VlcProc *pThis = (VlcProc*)pObj;
+    pThis->manage();
+}
+
+
+int VlcProc::onPlaylistChange( vlc_object_t *pObj, const char *pVariable,
+                               vlc_value_t oldVal, vlc_value_t newVal,
+                               void *pParam )
+{
+    VlcProc *pThis = ( VlcProc* )pParam;
+
+    // Create a playlist notify command
+    CmdNotifyPlaylist *pCmd = new CmdNotifyPlaylist( pThis->getIntf() );
+
+    // Push the command in the asynchronous command queue
+    AsyncQueue *pQueue = AsyncQueue::instance( pThis->getIntf() );
+    pQueue->remove( "notify playlist" );
+    pQueue->push( CmdGenericPtr( pCmd ) );
+
+    return VLC_SUCCESS;
+}
+
diff --git a/modules/gui/skins2/src/vlcproc.hpp b/modules/gui/skins2/src/vlcproc.hpp
new file mode 100755 (executable)
index 0000000..57c8fc7
--- /dev/null
@@ -0,0 +1,104 @@
+/*****************************************************************************
+ * vlcproc.hpp
+ *****************************************************************************
+ * Copyright (C) 2003 VideoLAN
+ * $Id: vlcproc.hpp,v 1.1 2004/01/03 23:31:34 asmax Exp $
+ *
+ * Authors: Cyril Deguet     <asmax@via.ecp.fr>
+ *          Olivier Teulière <ipkiss@via.ecp.fr>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111, USA.
+ *****************************************************************************/
+
+#ifndef VLCPROC_HPP
+#define VLCPROC_HPP
+
+#include "../vars/playlist.hpp"
+#include "../vars/time.hpp"
+#include "../vars/volume.hpp"
+#include "../vars/vlcvars.hpp"
+
+class OSTimer;
+
+
+/// Singleton object handling VLC internal state
+class VlcProc: public SkinObject
+{
+    public:
+        /// Get the instance of VlcProc
+        /// Returns NULL if the initialization of the object failed
+        static VlcProc *instance( intf_thread_t *pIntf );
+
+        /// Delete the instance of VlcProc
+        static void destroy( intf_thread_t *pIntf );
+
+        /// Getter for the playlist variable
+        Playlist &getPlaylistVar() { return m_playlist; }
+
+        /// Getter for the time variable
+        Time &getTimeVar() { return m_varTime; }
+
+        /// Getter for the volume variable
+        Volume &getVolumeVar() { return m_varVolume; }
+
+        /// Getter for the mute variable
+        VlcIsMute &getIsMuteVar() { return m_varMute; }
+
+        /// Getter for the playing variable
+        VlcIsPlaying &getIsPlayingVar() { return m_varPlaying; }
+
+        /// Getter for the seekable/playing variable
+        VlcIsSeekablePlaying &getIsSeekablePlayingVar()
+            { return m_varSeekablePlaying; }
+
+    protected:
+        // Protected because it is a singleton
+        VlcProc( intf_thread_t *pIntf );
+        virtual ~VlcProc();
+
+    private:
+        /// Timer to call manage() regularly (via doManage())
+        OSTimer *m_pTimer;
+        /// Playlist variable
+        Playlist m_playlist;
+        /// Variable for the position in the stream
+        Time m_varTime;
+        /// Variable for audio volume
+        Volume m_varVolume;
+        /// Variable for the "mute" state
+        VlcIsMute m_varMute;
+        /// Variables related to the input
+        VlcIsPlaying m_varPlaying;
+        VlcIsSeekablePlaying m_varSeekablePlaying;
+
+        /// Poll VLC internals to update the status (volume, current time in
+        /// the stream, current filename, play/pause/stop status, ...)
+        /// This function should be called regurlarly, since there is no
+        /// callback mechanism (yet?) to automatically update a variable when
+        /// the internal status changes
+        void manage();
+
+        /// This function directly calls manage(), because it's boring to
+        /// always write "pThis->"
+        static void doManage( SkinObject *pObj );
+
+        /// Callback for the playlist
+        static int onPlaylistChange( vlc_object_t *pObj, const char *pVariable,
+                                     vlc_value_t oldVal, vlc_value_t newVal,
+                                     void *pParam );
+};
+
+
+#endif
diff --git a/modules/gui/skins2/src/window_manager.cpp b/modules/gui/skins2/src/window_manager.cpp
new file mode 100755 (executable)
index 0000000..ac7bd74
--- /dev/null
@@ -0,0 +1,306 @@
+/*****************************************************************************
+ * window_manager.cpp
+ *****************************************************************************
+ * Copyright (C) 2003 VideoLAN
+ * $Id: window_manager.cpp,v 1.1 2004/01/03 23:31:34 asmax Exp $
+ *
+ * Authors: Cyril Deguet     <asmax@via.ecp.fr>
+ *          Olivier Teulière <ipkiss@via.ecp.fr>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111, USA.
+ *****************************************************************************/
+
+#include "window_manager.hpp"
+#include "generic_window.hpp"
+#include "os_factory.hpp"
+#include "anchor.hpp"
+#include "../utils/position.hpp"
+
+
+void WindowManager::registerWindow( GenericWindow *pWindow )
+{
+    if( pWindow == NULL )
+    {
+        msg_Dbg( getIntf(), "WM: registering a NULL window" );
+        return;
+    }
+
+    // Add the window to the set
+    m_allWindows.insert( pWindow );
+}
+
+
+void WindowManager::unregisterWindow( GenericWindow *pWindow )
+{
+    // Erase every possible reference to the window
+    m_allWindows.erase( pWindow );
+    m_movingWindows.erase( pWindow );
+    m_dependencies.erase( pWindow );
+}
+
+
+void WindowManager::startMove( GenericWindow *pWindow )
+{
+    // Rebuild the set of moving windows
+    m_movingWindows.clear();
+    buildDependSet( m_movingWindows, pWindow );
+
+    // Change the opacity of the moving windows
+    WinSet_t::const_iterator it;
+    for( it = m_movingWindows.begin(); it != m_movingWindows.end(); it++ )
+    {
+        (*it)->setOpacity( m_moveAlpha );
+    }
+}
+
+
+void WindowManager::stopMove()
+{
+    WinSet_t::const_iterator itWin1, itWin2;
+    AncList_t::const_iterator itAnc1, itAnc2;
+
+    // Restore the opacity of the moving windows
+    WinSet_t::const_iterator it;
+    for( it = m_movingWindows.begin(); it != m_movingWindows.end(); it++ )
+    {
+        (*it)->setOpacity( m_alpha );
+    }
+
+    // Delete the dependencies
+    m_dependencies.clear();
+
+    // Now we rebuild the dependencies.
+    // Iterate through all the windows
+    for( itWin1 = m_allWindows.begin(); itWin1 != m_allWindows.end(); itWin1++ )
+    {
+        // Get the anchors of the window
+        const AncList_t &ancList1 = (*itWin1)->getAnchorList();
+
+        // Iterate through all the windows, starting with (*itWin1)
+        for( itWin2 = itWin1; itWin2 != m_allWindows.end(); itWin2++ )
+        {
+            // A window can't anchor itself...
+            if( (*itWin2) == (*itWin1) )
+                continue;
+
+            // Now, check for anchoring between the 2 windows
+            const AncList_t &ancList2 = (*itWin2)->getAnchorList();
+            for( itAnc1 = ancList1.begin(); itAnc1 != ancList1.end(); itAnc1++ )
+            {
+                for( itAnc2 = ancList2.begin();
+                     itAnc2 != ancList2.end(); itAnc2++ )
+                {
+                    if( (*itAnc1)->isHanging( **itAnc2 ) )
+                    {
+                        // (*itWin1) anchors (*itWin2)
+                        m_dependencies[*itWin1].insert( *itWin2 );
+                    }
+                    else if( (*itAnc2)->isHanging( **itAnc1 ) )
+                    {
+                        // (*itWin2) anchors (*itWin1)
+                        m_dependencies[*itWin2].insert( *itWin1 );
+                    }
+                }
+            }
+        }
+    }
+}
+
+
+void WindowManager::move( GenericWindow *pWindow, int left, int top ) const
+{
+    // Compute the real move offset
+    int xOffset = left - pWindow->getLeft();
+    int yOffset = top - pWindow->getTop();
+
+    // Check anchoring; this can change the values of xOffset and yOffset
+    checkAnchors( pWindow, xOffset, yOffset );
+
+    // Move all the windows
+    WinSet_t::const_iterator it;
+    for( it = m_movingWindows.begin(); it != m_movingWindows.end(); it++ )
+    {
+        (*it)->move( (*it)->getLeft() + xOffset, (*it)->getTop() + yOffset );
+    }
+}
+
+
+void WindowManager::raise( GenericWindow *pWindow )
+{
+    // Build a set of windows anchored to pWindow
+    WinSet_t winSet;
+    buildDependSet( winSet, pWindow );
+
+    // Raise the windows in the set
+    WinSet_t::const_iterator iter;
+    for( iter = winSet.begin(); iter != winSet.end(); iter++ )
+    {
+        (*iter)->raise();
+    }
+}
+
+
+void WindowManager::showAll() const
+{
+    WinSet_t::const_iterator it;
+    for( it = m_allWindows.begin(); it != m_allWindows.end(); it++ )
+    {
+        (*it)->show();
+        (*it)->setOpacity( m_alpha );
+    }
+}
+
+
+void WindowManager::hideAll() const
+{
+    WinSet_t::const_iterator it;
+    for( it = m_allWindows.begin(); it != m_allWindows.end(); it++ )
+    {
+        (*it)->hide();
+    }
+}
+
+
+void WindowManager::toggleOnTop()
+{
+    m_isOnTop = !m_isOnTop;
+    WinSet_t::const_iterator it;
+    for( it = m_allWindows.begin(); it != m_allWindows.end(); it++ )
+    {
+        (*it)->toggleOnTop( m_isOnTop );
+    }
+}
+
+
+void WindowManager::buildDependSet( WinSet_t &rWinSet,
+                                    GenericWindow *pWindow )
+{
+    // pWindow is in the set
+    rWinSet.insert( pWindow );
+
+    // Iterate through the anchored windows
+    const WinSet_t &anchored = m_dependencies[pWindow];
+    WinSet_t::const_iterator iter;
+    for( iter = anchored.begin(); iter != anchored.end(); iter++ )
+    {
+        // Check that the window isn't already in the set before adding it
+        if( rWinSet.find( *iter ) == rWinSet.end() )
+        {
+            buildDependSet( rWinSet, *iter );
+        }
+    }
+}
+
+
+void WindowManager::checkAnchors( GenericWindow *pWindow,
+                                  int &xOffset, int &yOffset ) const
+{
+    WinSet_t::const_iterator itMov, itSta;
+    AncList_t::const_iterator itAncMov, itAncSta;
+
+    // Check magnetism with screen edges first (actually it is the work area)
+    Rect workArea = OSFactory::instance( getIntf() )->getWorkArea();
+    // Iterate through the moving windows
+    for( itMov = m_movingWindows.begin();
+         itMov != m_movingWindows.end(); itMov++ )
+    {
+        int newLeft = (*itMov)->getLeft() + xOffset;
+        int newTop = (*itMov)->getTop() + yOffset;
+        if( newLeft > workArea.getLeft() - m_magnet &&
+            newLeft < workArea.getLeft() + m_magnet )
+        {
+            xOffset = workArea.getLeft() - (*itMov)->getLeft();
+        }
+        if( newTop > workArea.getTop() - m_magnet &&
+            newTop < workArea.getTop() + m_magnet )
+        {
+            yOffset = workArea.getTop() - (*itMov)->getTop();
+        }
+        if( newLeft + (*itMov)->getWidth() > workArea.getRight() - m_magnet &&
+            newLeft + (*itMov)->getWidth() < workArea.getRight() + m_magnet )
+        {
+            xOffset = workArea.getRight() - (*itMov)->getLeft()
+                      - (*itMov)->getWidth();
+        }
+        if( newTop + (*itMov)->getHeight() > workArea.getBottom() - m_magnet &&
+            newTop + (*itMov)->getHeight() <  workArea.getBottom() + m_magnet )
+        {
+            yOffset =  workArea.getBottom() - (*itMov)->getTop()
+                       - (*itMov)->getHeight();
+        }
+    }
+
+    // Iterate through the moving windows
+    for( itMov = m_movingWindows.begin();
+         itMov != m_movingWindows.end(); itMov++ )
+    {
+        // Get the anchors of this moving window
+        const AncList_t &movAnchors = (*itMov)->getAnchorList();
+
+        // Iterate through the static windows
+        for( itSta = m_allWindows.begin();
+             itSta != m_allWindows.end(); itSta++ )
+        {
+            // Skip the moving windows
+            if( m_movingWindows.find( (*itSta) ) != m_movingWindows.end() )
+            {
+                continue;
+            }
+
+            // Get the anchors of this static window
+            const AncList_t &staAnchors = (*itSta)->getAnchorList();
+
+            // Check if there is an anchoring between one of the movAnchors
+            // and one of the staAnchors
+            for( itAncMov = movAnchors.begin();
+                 itAncMov != movAnchors.end(); itAncMov++ )
+            {
+                for( itAncSta = staAnchors.begin();
+                     itAncSta != staAnchors.end(); itAncSta++ )
+                {
+                    if( (*itAncSta)->canHang( **itAncMov, xOffset, yOffset ) )
+                    {
+                        // We have found an anchoring!
+                        // There is nothing to do here, since xOffset and
+                        // yOffset are automatically modified by canHang()
+
+                        // Don't check the other anchors, one is enough...
+                        return;
+                    }
+                    else
+                    {
+                        // Temporary variables
+                        int xOffsetTemp = -xOffset;
+                        int yOffsetTemp = -yOffset;
+                        if( (*itAncMov)->canHang( **itAncSta, xOffsetTemp,
+                                                  yOffsetTemp ) )
+                        {
+                            // We have found an anchoring!
+                            // xOffsetTemp and yOffsetTemp have been updated,
+                            // we just need to change xOffset and yOffset
+                            xOffset = -xOffsetTemp;
+                            yOffset = -yOffsetTemp;
+
+                            // Don't check the other anchors, one is enough...
+                            return;
+                        }
+                    }
+                }
+            }
+        }
+    }
+}
+
+
diff --git a/modules/gui/skins2/src/window_manager.hpp b/modules/gui/skins2/src/window_manager.hpp
new file mode 100644 (file)
index 0000000..9f8fabd
--- /dev/null
@@ -0,0 +1,127 @@
+/*****************************************************************************
+ * window_manager.hpp
+ *****************************************************************************
+ * Copyright (C) 2003 VideoLAN
+ * $Id: window_manager.hpp,v 1.1 2004/01/03 23:31:34 asmax Exp $
+ *
+ * Authors: Cyril Deguet     <asmax@via.ecp.fr>
+ *          Olivier Teulière <ipkiss@via.ecp.fr>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111, USA.
+ *****************************************************************************/
+
+#ifndef WINDOW_MANAGER_HPP
+#define WINDOW_MANAGER_HPP
+
+#include "skin_common.hpp"
+#include <list>
+#include <map>
+#include <set>
+#include <utility>
+
+
+class GenericWindow;
+class Anchor;
+
+
+/// Window manager for skin windows
+class WindowManager: public SkinObject
+{
+    public:
+        WindowManager( intf_thread_t *pIntf ):
+            SkinObject( pIntf ), m_isOnTop( false ), m_magnet( 0 ) {}
+        virtual ~WindowManager() {}
+
+        /// Add a window to the list of known windows. Necessary if you want
+        /// your window to be movable...
+        void registerWindow( GenericWindow *pWindow );
+
+        /// Remove a previously registered window
+        void unregisterWindow( GenericWindow *pWindow );
+
+        /// Tell the window manager that a move is initiated for pWindow.
+        void startMove( GenericWindow *pWindow );
+
+        /// Tell the window manager that the current move ended.
+        void stopMove();
+
+        /// Move the pWindow window to (left, top), and move all its
+        /// anchored windows.
+        /// If a new anchoring is detected, the windows will move accordingly.
+        void move( GenericWindow *pWindow, int left, int top ) const;
+
+        /// Raise a window and its anchored windows
+        void raise( GenericWindow *pWindow );
+
+        /// Show all the registered windows
+        void showAll() const;
+
+        /// Hide all the registered windows
+        void hideAll() const;
+
+        /// Toggle all the windows on top
+        void toggleOnTop();
+
+        /// Set the magnetism of screen edges
+        void setMagnetValue( int magnet ) { m_magnet = magnet; }
+
+        /// Set the alpha value of the static windows
+        void setAlphaValue( int alpha ) { m_alpha = alpha; }
+
+        /// Set the alpha value of the moving windows
+        void setMoveAlphaValue( int moveAlpha ) { m_moveAlpha = moveAlpha; }
+
+    private:
+        /// Some useful typedefs for lazy people like me
+        typedef set<GenericWindow*> WinSet_t;
+        typedef list<Anchor*> AncList_t;
+
+        /// This map represents the graph of anchored windows: it associates
+        /// to a given window all the windows that are directly anchored by it.
+        /// This is not transitive, i.e. if a is in m_dep[b] and if b is in
+        /// m_dep[c], it doesn't mean that a is in m_dep[c] (in fact, it
+        /// would be extremely rare...)
+        map<GenericWindow*, WinSet_t> m_dependencies;
+
+        /// Store all the windows
+        WinSet_t m_allWindows;
+
+        /// Store the moving windows; this set is updated at every start of
+        /// move.
+        WinSet_t m_movingWindows;
+
+        /// Indicate whether the windows are currently on top
+        bool m_isOnTop;
+
+        /// Magnetism of the screen edges (= scope of action)
+        int m_magnet;
+
+        /// Alpha value of the static windows
+        int m_alpha;
+
+        /// Alpha value of the moving windows
+        int m_moveAlpha;
+
+        /// Recursively build a set of windows anchored to the one given.
+        void buildDependSet( WinSet_t &rWinSet, GenericWindow *pWindow );
+
+        /// Check anchoring: this function updates xOffset and yOffset,
+        /// to take care of a new anchoring (if any)
+        void checkAnchors( GenericWindow *pWindow,
+                           int &xOffset, int &yOffset ) const;
+};
+
+
+#endif
diff --git a/modules/gui/skins2/utils/bezier.cpp b/modules/gui/skins2/utils/bezier.cpp
new file mode 100644 (file)
index 0000000..08e7e72
--- /dev/null
@@ -0,0 +1,191 @@
+/*****************************************************************************
+ * bezier.cpp
+ *****************************************************************************
+ * Copyright (C) 2003 VideoLAN
+ * $Id: bezier.cpp,v 1.1 2004/01/03 23:31:34 asmax Exp $
+ *
+ * Authors: Cyril Deguet     <asmax@via.ecp.fr>
+ *          Olivier Teulière <ipkiss@via.ecp.fr>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111, USA.
+ *****************************************************************************/
+
+#include "bezier.hpp"
+#include <math.h>
+
+
+Bezier::Bezier( intf_thread_t *p_intf, const vector<double> &rAbscissas,
+                const vector<double> &rOrdinates, Flag_t flag )
+    : SkinObject( p_intf )
+{
+    // We expect rAbscissas and rOrdinates to have the same size, of course
+    m_nbCtrlPt = rAbscissas.size();
+
+    // Copy the control points coordinates
+    m_ptx.assign( rAbscissas.begin(), rAbscissas.end() );
+    m_pty.assign( rOrdinates.begin(), rOrdinates.end() );
+
+    // Precalculate the factoriels
+    m_ft.push_back( 1 );
+    for( int i = 1; i < m_nbCtrlPt; i++ )
+    {
+        m_ft.push_back( i * m_ft[i - 1] );
+    }
+
+    // Initialization
+    int cx, cy, oldx, oldy;
+    m_leftVect.reserve( MAX_BEZIER_POINT + 1 );
+    m_topVect.reserve( MAX_BEZIER_POINT + 1 );
+
+    // Calculate the first point
+    getPoint( 0, oldx, oldy );
+    m_leftVect[0] = oldx;
+    m_topVect[0]  = oldy;
+
+    // Compute the number of different points
+    double percentage;
+    for( double j = 1; j <= MAX_BEZIER_POINT; j++ )
+    {
+        percentage = j / MAX_BEZIER_POINT;
+        getPoint( percentage, cx, cy );
+        if( ( flag == kCoordsBoth && ( cx != oldx || cy != oldy ) ) ||
+            ( flag == kCoordsX && cx != oldx ) ||
+            ( flag == kCoordsY && cy != oldy ) )
+        {
+            m_leftVect.push_back( cx );
+            m_topVect.push_back( cy );
+            oldx = cx;
+            oldy = cy;
+        }
+    }
+    m_nbPoints = m_leftVect.size();
+}
+
+
+double Bezier::getNearestPercent( int x, int y ) const
+{
+    int nearest = findNearestPoint( x, y );
+    return (double)nearest / (double)(m_nbPoints - 1);
+}
+
+
+double Bezier::getMinDist( int x, int y ) const
+{
+    // XXX: duplicate code with findNearestPoint
+    int minDist = (m_leftVect[0] - x) * (m_leftVect[0] - x) +
+                  (m_topVect[0] - y) * (m_topVect[0] - y);
+
+    int dist;
+    for( int i = 1; i < m_nbPoints; i++ )
+    {
+        dist = (m_leftVect[i] - x) * (m_leftVect[i] - x) +
+               (m_topVect[i] - y) * (m_topVect[i] - y);
+        if( dist < minDist )
+        {
+            minDist = dist;
+        }
+    }
+    return sqrt( minDist );
+}
+
+
+void Bezier::getPoint( double t, int &x, int &y ) const
+{
+    // See http://astronomy.swin.edu.au/~pbourke/curves/bezier/ for a simple
+    // explanation of the algorithm
+    double xPos = 0;
+    double yPos = 0;
+    double coeff;
+    for( int i = 0; i < m_nbCtrlPt; i++ )
+    {
+        coeff = computeCoeff( i, m_nbCtrlPt - 1, t );
+        xPos += m_ptx[i] * coeff;
+        yPos += m_pty[i] * coeff;
+    }
+
+    // Double cast to avoid strange truncatures
+    // XXX: not very nice...
+    x = (int)(float)xPos;
+    y = (int)(float)yPos;
+}
+
+
+int Bezier::getWidth() const
+{
+    int width = 0;
+    for( int i = 0; i < m_nbPoints; i++ )
+    {
+        if( m_leftVect[i] > width )
+        {
+            width = m_leftVect[i];
+        }
+    }
+    return width;
+}
+
+
+int Bezier::getHeight() const
+{
+    int height = 0;
+    for( int i = 0; i < m_nbPoints; i++ )
+    {
+        if( m_topVect[i] > height )
+        {
+            height = m_topVect[i];
+        }
+    }
+    return height;
+}
+
+
+int Bezier::findNearestPoint( int x, int y ) const
+{
+    // XXX: duplicate code with getMinDist
+    // The distance to the first point is taken as the reference
+    int refPoint = 0;
+    int minDist = (m_leftVect[0] - x) * (m_leftVect[0] - x) +
+                  (m_topVect[0] - y) * (m_topVect[0] - y);
+
+    int dist;
+    for( int i = 1; i < m_nbPoints; i++ )
+    {
+        dist = (m_leftVect[i] - x) * (m_leftVect[i] - x) +
+               (m_topVect[i] - y) * (m_topVect[i] - y);
+        if( dist < minDist )
+        {
+            minDist = dist;
+            refPoint = i;
+        }
+    }
+
+    return refPoint;
+}
+
+
+inline double Bezier::computeCoeff( int i, int n, double t ) const
+{
+    return (power( t, i ) * power( 1 - t, (n - i) ) *
+        (m_ft[n] / m_ft[i] / m_ft[n - i]));
+}
+
+
+inline double Bezier::power( double x, int n ) const
+{
+    if( n > 0 )
+        return x * power( x, n - 1);
+    else
+        return 1;
+}
+
diff --git a/modules/gui/skins2/utils/bezier.hpp b/modules/gui/skins2/utils/bezier.hpp
new file mode 100644 (file)
index 0000000..4b6b809
--- /dev/null
@@ -0,0 +1,96 @@
+/*****************************************************************************
+ * bezier.hpp
+ *****************************************************************************
+ * Copyright (C) 2003 VideoLAN
+ * $Id: bezier.hpp,v 1.1 2004/01/03 23:31:34 asmax Exp $
+ *
+ * Authors: Cyril Deguet     <asmax@via.ecp.fr>
+ *          Olivier Teulière <ipkiss@via.ecp.fr>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111, USA.
+ *****************************************************************************/
+
+#ifndef BEZIER_HPP
+#define BEZIER_HPP
+
+#include "../src/skin_common.hpp"
+#include <vector>
+using namespace std;
+
+#define MAX_BEZIER_POINT 1023
+
+
+/// Class for Bezier curves
+class Bezier: public SkinObject
+{
+    public:
+        /// Values to indicate which coordinate(s) must be checked to consider
+        /// that two points are distinct
+        typedef enum
+        {
+            kCoordsBoth,    // x or y must be different (default)
+            kCoordsX,       // only x is different
+            kCoordsY        // only y is different
+        } Flag_t;
+
+        Bezier( intf_thread_t *p_intf,
+                const vector<double> &pAbscissas,
+                const vector<double> &pOrdinates,
+                Flag_t flag = kCoordsBoth );
+        ~Bezier() {}
+
+        /// Return the percentage (between 0 and 1) of the curve point nearest
+        /// from (x, y)
+
+        double getNearestPercent( int x, int y ) const;
+
+        /// Return the distance of (x, y) to the curve
+        double getMinDist( int x, int y ) const;
+
+        /// Get the coordinates of the point at t precent of
+        /// the curve (t must be between 0 and 1)
+        void getPoint( double t, int &x, int &y ) const;
+
+        /// Get the width (maximum abscissa) of the curve
+        int getWidth() const;
+
+        /// Get the height (maximum ordinate) of the curve
+        int getHeight() const;
+
+    private:
+        /// Number of control points
+        int m_nbCtrlPt;
+        /// vectors containing the coordinates of the control points
+        vector<double> m_ptx;
+        vector<double> m_pty;
+        /// Vector containing precalculated factoriels
+        vector<double> m_ft;
+
+        /// Number of points (=pixels) used by the curve
+        int m_nbPoints;
+        /// Vectors with the coordinates of the different points of the curve
+        vector<int> m_leftVect;
+        vector<int> m_topVect;
+
+        /// Return the index of the curve point that is the nearest from (x, y)
+        int findNearestPoint( int x, int y ) const;
+        /// Helper function to compute a coefficient of the curve
+        inline double computeCoeff( int i, int n, double t ) const;
+        /// x^n
+        inline double power( double x, int n ) const;
+};
+
+
+#endif
diff --git a/modules/gui/skins2/utils/fsm.cpp b/modules/gui/skins2/utils/fsm.cpp
new file mode 100755 (executable)
index 0000000..be1f27e
--- /dev/null
@@ -0,0 +1,108 @@
+/*****************************************************************************
+ * fsm.cpp
+ *****************************************************************************
+ * Copyright (C) 2003 VideoLAN
+ * $Id: fsm.cpp,v 1.1 2004/01/03 23:31:34 asmax Exp $
+ *
+ * Authors: Cyril Deguet     <asmax@via.ecp.fr>
+ *          Olivier Teulière <ipkiss@via.ecp.fr>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111, USA.
+ *****************************************************************************/
+
+#include "fsm.hpp"
+#include "../commands/cmd_generic.hpp"
+
+
+void FSM::addState( const string &state )
+{
+    m_states.insert( state );
+}
+
+
+void FSM::addTransition( const string &state1, const string &event,
+                         const string &state2, Callback *pCmd )
+{
+    // Check that we already know the states
+    if( m_states.find( state1 ) == m_states.end() ||
+        m_states.find( state2 ) == m_states.end() )
+    {
+        msg_Warn( getIntf(),
+                  "FSM: ignoring transition between invalid states" );
+        return;
+    }
+
+    Key_t key( state1, event );
+    Data_t data( state2, pCmd );
+
+    // Check that the transition doesn't already exist
+    if( m_transitions.find( key ) != m_transitions.end() )
+    {
+        msg_Warn( getIntf(), "FSM: transition already exists" );
+        return;
+    }
+
+    m_transitions[key] = data;
+}
+
+
+void FSM::setState( const string &state )
+{
+    if( m_states.find( state ) == m_states.end() )
+    {
+        msg_Warn( getIntf(), "FSM: trying to set an invalid state" );
+        return;
+    }
+    m_currentState = state;
+}
+
+
+void FSM::handleTransition( const string &event )
+{
+    string tmpEvent = event;
+    Key_t key( m_currentState, event );
+    map<Key_t, Data_t>::const_iterator it;
+
+    // Find a transition
+    it = m_transitions.find( key );
+
+    // While the matching fails, try to match a more generic transition
+    // For example, if "key:up:F" isn't a transition, "key:up" or "key" may be
+    while( it == m_transitions.end() &&
+           tmpEvent.rfind( ":", tmpEvent.size() ) != string::npos )
+    {
+        // Cut the last part
+        tmpEvent = tmpEvent.substr( 0, tmpEvent.rfind( ":", tmpEvent.size() ) );
+
+        key.second = tmpEvent;
+        it = m_transitions.find( key );
+    }
+
+    // No transition was found
+    if( it == m_transitions.end() )
+    {
+        return;
+    }
+
+    // Change state
+    m_currentState = (*it).second.first;
+
+    // Call the callback, if any
+    Callback *pCmd = (*it).second.second;
+    if( pCmd != NULL )
+    {
+        (*(pCmd->getFunc()))( pCmd->getObj() );
+    }
+}
diff --git a/modules/gui/skins2/utils/fsm.hpp b/modules/gui/skins2/utils/fsm.hpp
new file mode 100644 (file)
index 0000000..552f8b9
--- /dev/null
@@ -0,0 +1,83 @@
+/*****************************************************************************
+ * fsm.hpp
+ *****************************************************************************
+ * Copyright (C) 2003 VideoLAN
+ * $Id: fsm.hpp,v 1.1 2004/01/03 23:31:34 asmax Exp $
+ *
+ * Authors: Cyril Deguet     <asmax@via.ecp.fr>
+ *          Olivier Teulière <ipkiss@via.ecp.fr>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111, USA.
+ *****************************************************************************/
+
+#ifndef FSM_HPP
+#define FSM_HPP
+
+#include "../src/skin_common.hpp"
+#include <string>
+#include <map>
+#include <set>
+
+class EvtGeneric;
+
+
+/// This class implements a Finite State Machine (FSM)
+class FSM: public SkinObject
+{
+    public:
+        FSM( intf_thread_t *pIntf ): SkinObject( pIntf ) {}
+        virtual ~FSM() {}
+
+        /// Add a state to the machine
+        void addState( const string &state );
+
+        /// Add a transition to the machine
+        void addTransition( const string &state1, const string &event,
+                            const string &state2,
+                            Callback *pCmd = NULL );
+
+        /// Retrieve the current state
+        const string &getState() const { return m_currentState; }
+
+        /// Set the current state, without bothering about transitions
+        void setState( const string &state );
+
+        /// Find a transition from the current state with the input event,
+        /// change the state, and call the associated callback (if any).
+        void handleTransition( const string &event );
+
+    private:
+        /// A Key_t contains the initial state of a transition, and a string
+        /// characterizing an event (for example: "mouse:left:down:ctrl")
+        typedef pair<string, string> Key_t;
+
+        /// A Data_t contains the final state of a transition, and a callback
+        /// to execute when the transition is applied
+        typedef pair<string, Callback*> Data_t;
+
+        /// Current state of the machine
+        string m_currentState;
+
+        /// Set containing the different states
+        set<string> m_states;
+
+        /// Map containing the different transitions between defined types
+        /// It associates a final state (and potentially a callback)
+        /// with a couple of the form: (currentState, triggerEvent)
+        map<Key_t, Data_t> m_transitions;
+};
+
+
+#endif
diff --git a/modules/gui/skins2/utils/observer.hpp b/modules/gui/skins2/utils/observer.hpp
new file mode 100644 (file)
index 0000000..a2e3022
--- /dev/null
@@ -0,0 +1,100 @@
+/*****************************************************************************
+ * observer.hpp
+ *****************************************************************************
+ * Copyright (C) 2003 VideoLAN
+ * $Id: observer.hpp,v 1.1 2004/01/03 23:31:34 asmax Exp $
+ *
+ * Authors: Cyril Deguet     <asmax@via.ecp.fr>
+ *          Olivier Teulière <ipkiss@via.ecp.fr>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111, USA.
+ *****************************************************************************/
+
+#ifndef OBSERVER_HPP
+#define OBSERVER_HPP
+
+#include <set>
+
+// Forward declaration
+template <class S> class Observer;
+
+
+/// Template for subjects in the Observer design pattern
+template <class S> class Subject
+{
+    public:
+        virtual ~Subject() {}
+
+        /// Remove all observers; should only be used for debugging purposes
+        virtual void clearObservers()
+        {
+            m_observers.clear();
+        }
+
+        /// Add an observer to this subject
+        /// Note: adding twice the same observer is not harmful
+        virtual void addObserver( Observer<S>* pObserver )
+        {
+            m_observers.insert( pObserver );
+        }
+
+        /// Remove an observer from this subject
+        /// Note: removing twice the same observer is not harmful
+        virtual void delObserver( Observer<S>* pObserver )
+        {
+            m_observers.erase( pObserver );
+        }
+
+        /// Notify the observers when the status has changed
+        virtual void notify()
+        {
+            // This stupid gcc 3.2 needs "typename"
+            typename set<Observer<S>*>::const_iterator iter;
+            for( iter = m_observers.begin(); iter != m_observers.end();
+                 iter++ )
+            {
+                if( *iter == NULL )
+                {
+                    fprintf( stderr, "iter NULL !\n" );
+                    return;
+                }
+                (*iter)->onUpdate( *this );
+            }
+        }
+
+    protected:
+        Subject() {}
+
+    private:
+        /// Set of observers for this subject
+        set<Observer<S>*> m_observers;
+};
+
+
+/// Template for observers in the Observer design pattern
+template <class S> class Observer
+{
+    public:
+        virtual ~Observer() {}
+
+        /// Method called when the subject is modified
+        virtual void onUpdate( Subject<S> &rSubject ) = 0;
+
+    protected:
+        Observer() {}
+};
+
+
+#endif
diff --git a/modules/gui/skins2/utils/pointer.hpp b/modules/gui/skins2/utils/pointer.hpp
new file mode 100644 (file)
index 0000000..e3721b5
--- /dev/null
@@ -0,0 +1,93 @@
+/*****************************************************************************
+ * pointer.hpp
+ *****************************************************************************
+ * Copyright (C) 2003 VideoLAN
+ * $Id: pointer.hpp,v 1.1 2004/01/03 23:31:34 asmax Exp $
+ *
+ * Authors: Cyril Deguet     <asmax@via.ecp.fr>
+ *          Olivier Teulière <ipkiss@via.ecp.fr>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111, USA.
+ *****************************************************************************/
+
+#ifndef POINTER_HPP
+#define POINTER_HPP
+
+
+/// Reference couting pointer
+template <class T> class CountedPtr
+{
+    public:
+        explicit CountedPtr( T *pPtr = 0 ): m_pCounter( 0 )
+        {
+            if( pPtr ) m_pCounter = new Counter( pPtr );
+        }
+
+        ~CountedPtr() { release(); }
+
+        CountedPtr(const CountedPtr &rPtr ) { acquire( rPtr.m_pCounter ); }
+
+        CountedPtr &operator=( const CountedPtr &rPtr )
+        {
+            if( this != &rPtr )
+            {
+                release();
+                acquire( rPtr.m_pCounter );
+            }
+            return *this;
+        }
+
+        T &operator*() const { return *m_pCounter->m_pPtr; }
+
+        T *operator->() const {return m_pCounter->m_pPtr; }
+
+        T *get() const { return m_pCounter ? m_pCounter->m_pPtr : 0; }
+
+        bool unique() const
+        {
+            return ( m_pCounter ? m_pCounter->m_count == 1 : true );
+        }
+
+    private:
+        struct Counter
+        {
+            Counter( T* pPtr = 0, unsigned int c = 1 ):
+                m_pPtr( pPtr ), m_count( c ) {}
+            T* m_pPtr;
+            unsigned int m_count;
+        } *m_pCounter;
+
+        void acquire( Counter* pCount )
+        {
+            m_pCounter = pCount;
+            if( pCount ) ++pCount->m_count;
+        }
+
+        void release()
+        {
+            if( m_pCounter )
+            {
+                if( --m_pCounter->m_count == 0 )
+                {
+                    delete m_pCounter->m_pPtr;
+                    delete m_pCounter;
+                }
+                m_pCounter = 0;
+            }
+        }
+};
+
+
+#endif
diff --git a/modules/gui/skins2/utils/position.cpp b/modules/gui/skins2/utils/position.cpp
new file mode 100644 (file)
index 0000000..df85122
--- /dev/null
@@ -0,0 +1,125 @@
+/*****************************************************************************
+ * position.cpp
+ *****************************************************************************
+ * Copyright (C) 2003 VideoLAN
+ * $Id: position.cpp,v 1.1 2004/01/03 23:31:34 asmax Exp $
+ *
+ * Authors: Cyril Deguet     <asmax@via.ecp.fr>
+ *          Olivier Teulière <ipkiss@via.ecp.fr>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111, USA.
+ *****************************************************************************/
+
+#include "position.hpp"
+
+
+Rect::Rect( int left, int top, int right, int bottom ):
+    m_left( left ), m_top( top ), m_right( right ), m_bottom( bottom )
+{
+}
+
+
+Position::Position( int left, int top, int right, int bottom, const Box &rBox,
+                    Ref_t refLeftTop, Ref_t refRightBottom ):
+    m_left( left ), m_top( top ), m_right( right ), m_bottom( bottom ),
+    m_rBox( rBox ), m_refLeftTop( refLeftTop ),
+    m_refRighBottom( refRightBottom )
+{
+}
+
+
+int Position::getLeft() const
+{
+    switch( m_refLeftTop )
+    {
+        case kLeftTop:
+        case kLeftBottom:
+            return m_left;
+            break;
+        case kRightTop:
+        case kRightBottom:
+            return m_rBox.getWidth() + m_left - 1;
+            break;
+    }
+    // Avoid a warning
+    return 0;
+}
+
+
+int Position::getTop() const
+{
+    switch( m_refLeftTop )
+    {
+        case kLeftTop:
+        case kRightTop:
+            return m_top;
+            break;
+        case kRightBottom:
+        case kLeftBottom:
+            return m_rBox.getHeight() + m_top - 1;
+            break;
+    }
+    // Avoid a warning
+    return 0;
+}
+
+
+int Position::getRight() const
+{
+    switch( m_refRighBottom )
+    {
+        case kLeftTop:
+        case kLeftBottom:
+            return m_right;
+            break;
+        case kRightTop:
+        case kRightBottom:
+            return m_rBox.getWidth() + m_right - 1;
+            break;
+    }
+    // Avoid a warning
+    return 0;
+}
+
+
+int Position::getBottom() const
+{
+    switch( m_refRighBottom )
+    {
+        case kLeftTop:
+        case kRightTop:
+            return m_bottom;
+            break;
+        case kLeftBottom:
+        case kRightBottom:
+            return m_rBox.getHeight() + m_bottom - 1;
+            break;
+    }
+    // Avoid a warning
+    return 0;
+}
+
+
+int Position::getWidth() const
+{
+    return getRight() - getLeft() + 1;
+}
+
+
+int Position::getHeight() const
+{
+    return getBottom() - getTop() + 1;
+}
+
diff --git a/modules/gui/skins2/utils/position.hpp b/modules/gui/skins2/utils/position.hpp
new file mode 100644 (file)
index 0000000..531c5de
--- /dev/null
@@ -0,0 +1,106 @@
+/*****************************************************************************
+ * position.hpp
+ *****************************************************************************
+ * Copyright (C) 2003 VideoLAN
+ * $Id: position.hpp,v 1.1 2004/01/03 23:31:34 asmax Exp $
+ *
+ * Authors: Cyril Deguet     <asmax@via.ecp.fr>
+ *          Olivier Teulière <ipkiss@via.ecp.fr>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111, USA.
+ *****************************************************************************/
+
+#ifndef POSITION_HPP
+#define POSITION_HPP
+
+
+/// Interface for rectangular objects
+class Box
+{
+    public:
+        /// Get the size of the box
+        virtual int getWidth() const = 0;
+        virtual int getHeight() const = 0;
+};
+
+
+/// Characterization of a rectangle
+class Rect: public Box
+{
+    public:
+        Rect( int left, int top, int right, int bottom );
+
+        virtual int getLeft() const { return m_left; }
+        virtual int getTop() const { return m_top; }
+        virtual int getRight() const { return m_right; }
+        virtual int getBottom() const { return m_bottom; }
+
+        virtual int getWidth() const { return m_right - m_left; }
+        virtual int getHeight() const { return m_bottom - m_top; }
+
+    private:
+        int m_left;
+        int m_top;
+        int m_right;
+        int m_bottom;
+};
+
+
+/// Relative position of a rectangle in a box
+class Position
+{
+    public:
+        /// Type for reference edge/corner
+        typedef enum
+        {
+            /// Coordinates are relative to the upper left corner
+            kLeftTop,
+            /// Coordinates are relative to the upper right corner
+            kRightTop,
+            /// Coordinates are relative to the lower left corner
+            kLeftBottom,
+            /// Coordinates are relative to the lower right corner
+            kRightBottom
+        } Ref_t;
+
+        /// Create a new position relative to the given box
+        Position( int left, int top, int right, int bottom, const Box &rBox,
+                  Ref_t refLeftTop = kLeftTop,
+                  Ref_t refRightBottom = kLeftTop );
+
+        ~Position() {}
+
+        /// Get the position relative to the left top corner of the box
+        int getLeft() const;
+        int getTop() const;
+        int getRight() const;
+        int getBottom() const;
+        /// Get the size of the rectangle
+        int getWidth() const;
+        int getHeight() const;
+
+    private:
+        /// Position and reference edge/corner
+        int m_left;
+        int m_top;
+        int m_right;
+        int m_bottom;
+        const Box &m_rBox;
+        Ref_t m_refLeftTop;
+        Ref_t m_refRighBottom;
+};
+
+
+#endif
diff --git a/modules/gui/skins2/utils/ustring.cpp b/modules/gui/skins2/utils/ustring.cpp
new file mode 100644 (file)
index 0000000..8d73ec8
--- /dev/null
@@ -0,0 +1,330 @@
+/*****************************************************************************
+ * ustring.cpp
+ *****************************************************************************
+ * Copyright (C) 2003 VideoLAN
+ * $Id: ustring.cpp,v 1.1 2004/01/03 23:31:34 asmax Exp $
+ *
+ * Authors: Cyril Deguet     <asmax@via.ecp.fr>
+ *          Olivier Teulière <ipkiss@via.ecp.fr>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111, USA.
+ *****************************************************************************/
+
+#include <string.h>
+#include "ustring.hpp"
+
+
+const uint32_t UString::npos = 0xffffffff;
+
+
+UString::UString( const UString &rOther ): SkinObject( rOther.getIntf() )
+{
+    m_length = rOther.m_length;
+    m_pString = new uint32_t[m_length + 1];
+    memcpy( m_pString, rOther.m_pString, 4 * m_length + 4);
+}
+
+
+UString::UString( intf_thread_t *pIntf, const char *pString ):
+    SkinObject( pIntf )
+{
+    // First we compute the length of the string
+    const char *pCur = pString;
+    for( m_length = 0; pCur && *pCur; m_length++ )
+    {
+        if( (*pCur & 0xfc) == 0xfc )
+        {
+            pCur += 6;
+        }
+        else if ( (*pCur & 0xf8 ) == 0xf8 )
+        {
+            pCur += 5;
+        }
+        else if ( (*pCur & 0xf0 ) == 0xf0 )
+        {
+            pCur += 4;
+        }
+        else if ( (*pCur & 0xe0 ) == 0xe0 )
+        {
+            pCur += 3;
+        }
+        else if ( (*pCur & 0xc0 ) == 0xc0 )
+        {
+            pCur += 2;
+        }
+        else
+        {
+            pCur++;
+        }
+    }
+    if( !pCur || *pCur )
+    {
+        msg_Err( pIntf, "Invalid UTF8 string: %s", pString );
+        m_length = 0;
+        m_pString = NULL;
+        return;
+    }
+
+    m_pString = new uint32_t[m_length + 1];
+
+    // Convert the UTF8 string into UNICODE
+    pCur = pString;
+    uint32_t aChar = 0;  // current unicode character
+    int remaining = 0;   // remaining bytes
+    for( uint32_t i = 0; i <= m_length; i++ )
+    {
+        if( (*pCur & 0xfc) == 0xfc )
+        {
+            aChar = *pCur & 1;
+            remaining = 5;
+        }
+        else if ( (*pCur & 0xf8 ) == 0xf8 )
+        {
+            aChar = *pCur & 3;
+            remaining = 4;
+        }
+        else if ( (*pCur & 0xf0 ) == 0xf0 )
+        {
+            aChar = *pCur & 7;
+            remaining = 3;
+        }
+        else if ( (*pCur & 0xe0 ) == 0xe0 )
+        {
+            aChar = *pCur & 15;
+            remaining = 2;
+        }
+        else if ( (*pCur & 0xc0 ) == 0xc0 )
+        {
+            aChar = *pCur & 31;
+            remaining = 1;
+        }
+        else
+        {
+            aChar = *pCur;
+            remaining = 0;
+        }
+        while( remaining )
+        {
+            pCur++;
+            remaining--;
+            aChar = ( aChar << 6 ) | ( *pCur & 0x3f );
+        }
+        m_pString[i] = aChar;
+        pCur++;
+    }
+    m_pString[m_length] = 0;
+}
+
+
+UString::~UString()
+{
+    if( m_pString )
+    {
+        delete[] m_pString;
+    }
+}
+
+
+bool UString::operator ==( const UString &rOther ) const
+{
+    if( size() != rOther.size() )
+    {
+        return false;
+    }
+
+    for( uint32_t i = 0; i < size(); i++ )
+    {
+        if( m_pString[i] != rOther.m_pString[i] )
+        {
+            return false;
+        }
+    }
+
+    return true;
+}
+
+
+bool UString::operator !=( const UString &rOther ) const
+{
+    return !(*this == rOther);
+}
+
+
+bool UString::operator <( const UString &rOther ) const
+{
+    const uint32_t *pOther = rOther.u_str();
+    uint32_t i;
+    for( i = 0; i < __MIN(m_length, rOther.length()); i++ )
+    {
+        if( m_pString[i] < pOther[i] )
+        {
+            return true;
+        }
+        else if( m_pString[i] > pOther[i] )
+        {
+            return false;
+        }
+    }
+    return( m_pString[i] < pOther[i] );
+}
+
+
+bool UString::operator <=( const UString &rOther ) const
+{
+    return !( rOther < *this );
+}
+
+
+bool UString::operator >( const UString &rOther ) const
+{
+    return ( rOther < *this );
+}
+
+
+bool UString::operator >=( const UString &rOther ) const
+{
+    return !( *this < rOther );
+}
+
+
+void UString::operator =( const UString &rOther )
+{
+    m_length = rOther.m_length;
+    delete[] m_pString;
+    m_pString = new uint32_t[size() + 1];
+    for( uint32_t i = 0; i < size(); i++ )
+    {
+        m_pString[i] = rOther.m_pString[i];
+    }
+}
+
+
+void UString::operator +=( const UString &rOther )
+{
+    int tempLength = this->length() + rOther.length();
+    uint32_t *pTempString = new uint32_t[tempLength + 1];
+    // Copy the first string
+    memcpy( pTempString, this->m_pString, 4 * this->size() );
+    // Append the second string
+//     memcpy( pTempString + 4 * size(), rOther.m_pString,
+//             4 * rOther.size() );
+    for( uint32_t i = 0; i < rOther.size(); i++ )
+    {
+        pTempString[this->size() + i] = rOther.m_pString[i];
+    }
+    pTempString[tempLength] = 0;
+
+    // Set the string internally
+    delete[] m_pString;
+    m_pString = pTempString;
+    m_length = tempLength;
+}
+
+
+const UString UString::operator +( const UString &rOther ) const
+{
+    UString result( *this );
+    result += rOther;
+
+    return result;
+}
+
+
+const UString UString::operator +( const char *pString ) const
+{
+    UString temp( getIntf(), pString );
+    return (*this + temp );
+}
+
+
+void UString::debug() const
+{
+    char *s = new char[size() + 1];
+    for( uint32_t i = 0; i < size(); i++ )
+    {
+        s[i] = (char)m_pString[i];
+    }
+    s[size()] = '\0';
+    msg_Err( getIntf(), "%s", s );
+    delete[] s;
+}
+
+
+uint32_t UString::find( const UString &str, uint32_t position ) const
+{
+    uint32_t pos;
+    for( pos = position; pos + str.size() <= size(); pos++ )
+    {
+        bool match = true;
+        for( uint32_t i = 0; i < str.size(); i++ )
+        {
+            if( m_pString[pos + i] != str.m_pString[i] )
+            {
+                match = false;
+                break;
+            }
+        }
+
+        // Found
+        if( match )
+        {
+            return pos;
+        }
+    }
+
+    // Not found
+    return npos;
+}
+
+
+uint32_t UString::find( const char *pString, uint32_t position ) const
+{
+    UString tmp( getIntf(), pString );
+    return find( tmp, position );
+}
+
+
+void UString::replace( uint32_t position, uint32_t n1, const UString &str )
+{
+    UString start( substr( 0, position ) );
+    UString end( substr( position + n1 ) );
+    *this = start + str + end;
+}
+
+
+void UString::replace( uint32_t position, uint32_t n1, const char *pString )
+{
+    replace( position, n1, UString( getIntf(), pString ) );
+}
+
+
+UString UString::substr( uint32_t position, uint32_t n) const
+{
+    UString tmp( getIntf(), "" );
+    if( position > size() )
+    {
+        msg_Err( getIntf(), "Invalid position in UString::substr()" );
+        return tmp;
+    }
+    tmp.m_length = (n < size() - position) ? n : size() - position;
+    delete[] tmp.m_pString;
+    tmp.m_pString = new uint32_t[tmp.size() + 1];
+    for( uint32_t i = 0; i < tmp.size(); i++ )
+    {
+        tmp.m_pString[i] = m_pString[position + i];
+    }
+
+    return tmp;
+}
diff --git a/modules/gui/skins2/utils/ustring.hpp b/modules/gui/skins2/utils/ustring.hpp
new file mode 100644 (file)
index 0000000..c21c690
--- /dev/null
@@ -0,0 +1,98 @@
+/*****************************************************************************
+ * ustring.hpp
+ *****************************************************************************
+ * Copyright (C) 2003 VideoLAN
+ * $Id: ustring.hpp,v 1.1 2004/01/03 23:31:34 asmax Exp $
+ *
+ * Authors: Cyril Deguet     <asmax@via.ecp.fr>
+ *          Olivier Teulière <ipkiss@via.ecp.fr>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111, USA.
+ *****************************************************************************/
+
+#ifndef USTRING_HPP
+#define USTRING_HPP
+
+#include "../src/skin_common.hpp"
+#include "pointer.hpp"
+
+
+// Class for UNICODE strings handling
+class UString: public SkinObject
+{
+    public:
+        static const uint32_t npos;
+
+        /// Copy constructor
+        UString( const UString &rOther );
+
+        /// Create a new unicode string from an UTF8 string
+        UString( intf_thread_t *pIntf, const char *pString );
+
+        ~UString();
+
+        /// Get the unicode string
+        const uint32_t *u_str() const { return m_pString; }
+
+        /// Get the length of the string
+        uint32_t length() const { return m_length; }
+        uint32_t size() const { return m_length; }
+
+        /// Comparison
+        bool operator ==( const UString &rOther ) const;
+        bool operator !=( const UString &rOther ) const;
+        bool operator <( const UString &rOther ) const;
+        bool operator <=( const UString &rOther ) const;
+        bool operator >( const UString &rOther ) const;
+        bool operator >=( const UString &rOther ) const;
+        /// Assignment
+        void operator =( const UString &rOther );
+        /// Concatenation with assignment
+        void operator +=( const UString &rOther );
+        /// Concatenation
+        const UString operator +( const UString &rOther ) const;
+        const UString operator +( const char *pString ) const;
+
+
+        /// Search for the first occurance of the substring specified by str
+        /// in this string, starting at position. If found, it returns the
+        /// index of the first character of the matching substring. If not
+        /// found, it returns npos
+        uint32_t find( const UString &str, uint32_t position = 0 ) const;
+        uint32_t find( const char *pString, uint32_t position = 0 ) const;
+
+        /// Insert elements of str in place of n1 elements in this string,
+        /// starting at position position
+        void replace( uint32_t position, uint32_t n1, const UString &str );
+        void replace( uint32_t position, uint32_t n1, const char *pString );
+
+        /// Returns a string composed of copies of the lesser of n and size()
+        /// characters in this string starting at index position
+        UString substr( uint32_t position = 0, uint32_t n = npos) const;
+
+        /// XXX: temporary
+        void debug() const;
+
+    private:
+        /// Unicode string
+        uint32_t *m_pString;
+        /// String length
+        uint32_t m_length;
+};
+
+
+typedef CountedPtr<UString> UStringPtr;
+
+#endif
diff --git a/modules/gui/skins2/utils/var_bool.cpp b/modules/gui/skins2/utils/var_bool.cpp
new file mode 100755 (executable)
index 0000000..d9824f6
--- /dev/null
@@ -0,0 +1,42 @@
+/*****************************************************************************
+ * var_bool.cpp
+ *****************************************************************************
+ * Copyright (C) 2003 VideoLAN
+ * $Id: var_bool.cpp,v 1.1 2004/01/03 23:31:34 asmax Exp $
+ *
+ * Authors: Cyril Deguet     <asmax@via.ecp.fr>
+ *          Olivier Teulière <ipkiss@via.ecp.fr>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111, USA.
+ *****************************************************************************/
+
+#include "var_bool.hpp"
+
+
+VarBool::VarBool( intf_thread_t *pIntf ): Variable( pIntf ), m_value( false )
+{
+}
+
+
+void VarBool::set( bool value )
+{
+    if( value != m_value )
+    {
+        m_value = value;
+
+        notify();
+    }
+}
+
diff --git a/modules/gui/skins2/utils/var_bool.hpp b/modules/gui/skins2/utils/var_bool.hpp
new file mode 100755 (executable)
index 0000000..e24361f
--- /dev/null
@@ -0,0 +1,47 @@
+/*****************************************************************************
+ * var_bool.hpp
+ *****************************************************************************
+ * Copyright (C) 2003 VideoLAN
+ * $Id: var_bool.hpp,v 1.1 2004/01/03 23:31:34 asmax Exp $
+ *
+ * Authors: Cyril Deguet     <asmax@via.ecp.fr>
+ *          Olivier Teulière <ipkiss@via.ecp.fr>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111, USA.
+ *****************************************************************************/
+
+#ifndef VAR_BOOL_HPP
+#define VAR_BOOL_HPP
+
+#include "variable.hpp"
+#include "observer.hpp"
+
+
+/// Percentage variable
+class VarBool: public Variable, public Subject<VarBool>
+{
+    public:
+        VarBool( intf_thread_t *pIntf );
+        virtual ~VarBool() {}
+
+        /// Set the internal value
+        virtual void set( bool value );
+        virtual bool get() const { return m_value; }
+
+    private:
+        bool m_value;
+};
+
+#endif
diff --git a/modules/gui/skins2/utils/var_list.cpp b/modules/gui/skins2/utils/var_list.cpp
new file mode 100644 (file)
index 0000000..b1608bc
--- /dev/null
@@ -0,0 +1,107 @@
+/*****************************************************************************
+ * var_list.cpp
+ *****************************************************************************
+ * Copyright (C) 2003 VideoLAN
+ * $Id: var_list.cpp,v 1.1 2004/01/03 23:31:34 asmax Exp $
+ *
+ * Authors: Cyril Deguet     <asmax@via.ecp.fr>
+ *          Olivier Teulière <ipkiss@via.ecp.fr>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111, USA.
+ *****************************************************************************/
+
+#include "var_list.hpp"
+
+
+VarList::VarList( intf_thread_t *pIntf ): Variable( pIntf ),
+    m_position( pIntf )
+{
+    m_position.set( 1.0 );
+}
+
+
+VarList::~VarList()
+{
+}
+
+
+void VarList::add( const UStringPtr &rcString )
+{
+    m_list.push_back( Elem_t( rcString ) );
+    notify();
+}
+
+
+void VarList::delSelected()
+{
+    Iterator it = begin();
+    while( it != end() )
+    {
+        if( (*it).m_selected )
+        {
+            Iterator oldIt = it;
+            it++;
+            m_list.erase( oldIt );
+        }
+        else
+        {
+            it++;
+        }
+    }
+    notify();
+}
+
+
+void VarList::clear()
+{
+    m_list.clear();
+}
+
+
+VarList::Iterator VarList::operator[]( int n )
+{
+    Iterator it = begin();
+    for( int i = 0; i < n; i++ )
+    {
+        if( it != end() )
+        {
+            it++;
+        }
+        else
+        {
+            break;
+        }
+    }
+    return it;
+}
+
+
+VarList::ConstIterator VarList::operator[]( int n ) const
+{
+    ConstIterator it = begin();
+    for( int i = 0; i < n; i++ )
+    {
+        if( it != end() )
+        {
+            it++;
+        }
+        else
+        {
+            break;
+        }
+    }
+    return it;
+}
+
diff --git a/modules/gui/skins2/utils/var_list.hpp b/modules/gui/skins2/utils/var_list.hpp
new file mode 100644 (file)
index 0000000..7ba1c70
--- /dev/null
@@ -0,0 +1,100 @@
+/*****************************************************************************
+ * var_list.hpp
+ *****************************************************************************
+ * Copyright (C) 2003 VideoLAN
+ * $Id: var_list.hpp,v 1.1 2004/01/03 23:31:34 asmax Exp $
+ *
+ * Authors: Cyril Deguet     <asmax@via.ecp.fr>
+ *          Olivier Teulière <ipkiss@via.ecp.fr>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111, USA.
+ *****************************************************************************/
+
+#ifndef VAR_LIST_HPP
+#define VAR_LIST_HPP
+
+#include <list>
+
+#include "variable.hpp"
+#include "observer.hpp"
+#include "ustring.hpp"
+#include "var_percent.hpp"
+
+
+/// List variable
+class VarList: public Variable, public Subject<VarList>
+{
+    public:
+        VarList( intf_thread_t *pIntf );
+        virtual ~VarList();
+
+        /// Add a pointer on a string in the list
+        virtual void add( const UStringPtr &rcString );
+
+        /// Remove the selected elements from the list
+        virtual void delSelected();
+
+        /// Remove all the elements from the list
+        virtual void clear();
+
+        /// Get the number of items in the list
+        int size() const { return m_list.size(); }
+
+        /// Type of an element in the list
+        struct Elem_t
+        {
+            UStringPtr m_cString;
+            bool m_selected;
+            bool m_playing;
+
+            Elem_t( const UStringPtr &rcString, bool selected = false, bool
+                    playing = false ):
+                m_cString( rcString ), m_selected( selected ),
+                m_playing( playing) {}
+        };
+
+        /// Iterators
+        typedef list<Elem_t>::iterator Iterator;
+        typedef list<Elem_t>::const_iterator ConstIterator;
+
+        /// Beginning of the list
+        Iterator begin() { return m_list.begin(); }
+        ConstIterator begin() const { return m_list.begin(); }
+
+        /// End of the list
+        Iterator end() { return m_list.end(); }
+        ConstIterator end() const { return m_list.end(); }
+
+        /// Return an iterator on the n'th element of the list
+        Iterator operator[]( int n );
+        ConstIterator operator[]( int n ) const;
+
+        /// Execute the action associated to this item
+        virtual void action( Elem_t *pItem ) {}
+
+        /// Get the position variable
+        VarPercent &getPositionVar() { return m_position; }
+
+    protected:
+        /// List of elements
+        list<Elem_t> m_list;
+
+    private:
+        /// Position variable
+        VarPercent m_position;
+};
+
+
+#endif
diff --git a/modules/gui/skins2/utils/var_percent.cpp b/modules/gui/skins2/utils/var_percent.cpp
new file mode 100644 (file)
index 0000000..8512a56
--- /dev/null
@@ -0,0 +1,51 @@
+/*****************************************************************************
+ * var_percent.cpp
+ *****************************************************************************
+ * Copyright (C) 2003 VideoLAN
+ * $Id: var_percent.cpp,v 1.1 2004/01/03 23:31:34 asmax Exp $
+ *
+ * Authors: Cyril Deguet     <asmax@via.ecp.fr>
+ *          Olivier Teulière <ipkiss@via.ecp.fr>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111, USA.
+ *****************************************************************************/
+
+#include "var_percent.hpp"
+
+
+VarPercent::VarPercent( intf_thread_t *pIntf ): Variable( pIntf ), m_value( 0 )
+{
+}
+
+
+void VarPercent::set( double percentage )
+{
+    if( percentage < 0 )
+    {
+        percentage = 0;
+    }
+    if( percentage > 1 )
+    {
+        percentage = 1;
+    }
+
+    // If the value has changed, notify the observers
+    if( m_value != percentage )
+    {
+        m_value = percentage;
+        notify();
+    }
+}
+
diff --git a/modules/gui/skins2/utils/var_percent.hpp b/modules/gui/skins2/utils/var_percent.hpp
new file mode 100644 (file)
index 0000000..96d7940
--- /dev/null
@@ -0,0 +1,47 @@
+/*****************************************************************************
+ * var_percent.hpp
+ *****************************************************************************
+ * Copyright (C) 2003 VideoLAN
+ * $Id: var_percent.hpp,v 1.1 2004/01/03 23:31:34 asmax Exp $
+ *
+ * Authors: Cyril Deguet     <asmax@via.ecp.fr>
+ *          Olivier Teulière <ipkiss@via.ecp.fr>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111, USA.
+ *****************************************************************************/
+
+#ifndef VAR_PERCENT_HPP
+#define VAR_PERCENT_HPP
+
+#include "variable.hpp"
+#include "observer.hpp"
+
+
+/// Percentage variable
+class VarPercent: public Variable, public Subject<VarPercent>
+{
+    public:
+        VarPercent( intf_thread_t *pIntf );
+        virtual ~VarPercent() {}
+
+        /// Set the internal value
+        virtual void set( double percentage );
+        virtual double get() const { return m_value; }
+
+    private:
+        double m_value;
+};
+
+#endif
diff --git a/modules/gui/skins2/utils/var_text.cpp b/modules/gui/skins2/utils/var_text.cpp
new file mode 100755 (executable)
index 0000000..f60dc4a
--- /dev/null
@@ -0,0 +1,136 @@
+/*****************************************************************************
+ * var_text.cpp
+ *****************************************************************************
+ * Copyright (C) 2003 VideoLAN
+ * $Id: var_text.cpp,v 1.1 2004/01/03 23:31:34 asmax Exp $
+ *
+ * Authors: Cyril Deguet     <asmax@via.ecp.fr>
+ *          Olivier Teulière <ipkiss@via.ecp.fr>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111, USA.
+ *****************************************************************************/
+
+#include "var_text.hpp"
+#include "../src/vlcproc.hpp"
+#include "../src/var_manager.hpp"
+#include "../vars/time.hpp"
+#include "../vars/volume.hpp"
+
+
+VarText::VarText( intf_thread_t *pIntf ): Variable( pIntf ),
+    m_text( pIntf, "" ), m_lastText( pIntf, "" )
+{
+    m_lastText = get();
+}
+
+
+VarText::~VarText()
+{
+    // Remove the observers
+    VlcProc *pVlcProc = VlcProc::instance( getIntf() );
+    pVlcProc->getTimeVar().delObserver( this );
+    pVlcProc->getVolumeVar().delObserver( this );
+    VarManager *pVarManager = VarManager::instance( getIntf() );
+    pVarManager->getHelpText().delObserver( this );
+}
+
+
+const UString VarText::get() const
+{
+    uint32_t pos;
+    VlcProc *pVlcProc = VlcProc::instance( getIntf() );
+
+    // Fill a temporary UString object, and replace the escape characters
+    // ($H for help, $T for time, $V for volume)
+    UString temp( m_text );
+
+    while( (pos = temp.find( "$H" )) != UString::npos )
+    {
+        VarManager *pVarManager = VarManager::instance( getIntf() );
+        // We use .getRaw() to avoid replacing the $H recursively!
+        temp.replace( pos, 2, pVarManager->getHelpText().getRaw() );
+    }
+    while( (pos = temp.find( "$T" )) != UString::npos )
+    {
+        temp.replace( pos, 2,
+                      pVlcProc->getTimeVar().getAsStringTime().c_str() );
+    }
+    while( (pos = temp.find( "$V" )) != UString::npos )
+    {
+        temp.replace( pos, 2,
+                      pVlcProc->getVolumeVar().getAsStringPercent().c_str() );
+    }
+
+    return temp;
+}
+
+
+void VarText::set( const UString &rText )
+{
+    // Avoid an infinite loop
+    if( rText == m_text )
+    {
+        return;
+    }
+
+    // Stop observing other variables
+    VlcProc *pVlcProc = VlcProc::instance( getIntf() );
+    pVlcProc->getTimeVar().delObserver( this );
+    pVlcProc->getVolumeVar().delObserver( this );
+    VarManager *pVarManager = VarManager::instance( getIntf() );
+    pVarManager->getHelpText().delObserver( this );
+
+    m_text = rText;
+
+    // Observe needed variables
+    if( m_text.find( "$H" ) != UString::npos )
+    {
+        pVarManager->getHelpText().addObserver( this );
+    }
+    if( m_text.find( "$T" ) != UString::npos )
+    {
+        pVlcProc->getTimeVar().addObserver( this );
+    }
+    if( m_text.find( "$V" ) != UString::npos )
+    {
+        pVlcProc->getVolumeVar().addObserver( this );
+    }
+
+    notify();
+}
+
+
+void VarText::onUpdate( Subject<VarPercent> &rVariable )
+{
+    UString newText = get();
+    // If the text has changed, notify the observers
+    if( newText != m_lastText )
+    {
+        m_lastText = newText;
+        notify();
+    }
+}
+
+
+void VarText::onUpdate( Subject<VarText> &rVariable )
+{
+    UString newText = get();
+    // If the text has changed, notify the observers
+    if( newText != m_lastText )
+    {
+        m_lastText = newText;
+        notify();
+    }
+}
diff --git a/modules/gui/skins2/utils/var_text.hpp b/modules/gui/skins2/utils/var_text.hpp
new file mode 100755 (executable)
index 0000000..2d05a4c
--- /dev/null
@@ -0,0 +1,60 @@
+/*****************************************************************************
+ * var_text.hpp
+ *****************************************************************************
+ * Copyright (C) 2003 VideoLAN
+ * $Id: var_text.hpp,v 1.1 2004/01/03 23:31:34 asmax Exp $
+ *
+ * Authors: Cyril Deguet     <asmax@via.ecp.fr>
+ *          Olivier Teulière <ipkiss@via.ecp.fr>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111, USA.
+ *****************************************************************************/
+
+#ifndef VAR_TEXT_HPP
+#define VAR_TEXT_HPP
+
+#include "variable.hpp"
+#include "var_percent.hpp"
+#include "observer.hpp"
+#include "ustring.hpp"
+
+
+/// String variable
+class VarText: public Variable, public Subject<VarText>,
+               public Observer<VarPercent>, public Observer< VarText >
+{
+    public:
+        VarText( intf_thread_t *pIntf );
+        virtual ~VarText();
+
+        /// Set the internal value
+        virtual void set( const UString &rText );
+        virtual const UString get() const;
+
+        /// Methods called when an observed variable is modified
+        virtual void onUpdate( Subject<VarPercent> &rVariable );
+        virtual void onUpdate( Subject<VarText> &rVariable );
+
+    private:
+        /// The text of the variable
+        UString m_text;
+        /// Actual text after having replaced the variables
+        UString m_lastText;
+
+        /// Get the raw text without replacing the $something's
+        const UString &getRaw() const { return m_text; }
+};
+
+#endif
diff --git a/modules/gui/skins2/utils/variable.hpp b/modules/gui/skins2/utils/variable.hpp
new file mode 100644 (file)
index 0000000..bb07f84
--- /dev/null
@@ -0,0 +1,46 @@
+/*****************************************************************************
+ * variable.hpp
+ *****************************************************************************
+ * Copyright (C) 2003 VideoLAN
+ * $Id: variable.hpp,v 1.1 2004/01/03 23:31:34 asmax Exp $
+ *
+ * Authors: Cyril Deguet     <asmax@via.ecp.fr>
+ *          Olivier Teulière <ipkiss@via.ecp.fr>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111, USA.
+ *****************************************************************************/
+
+#ifndef VARIABLE_HPP
+#define VARIABLE_HPP
+
+#include "../src/skin_common.hpp"
+#include "pointer.hpp"
+
+
+/// Base class for variable objects
+class Variable: public SkinObject
+{
+    public:
+        virtual ~Variable() {}
+
+    protected:
+        Variable( intf_thread_t *pIntf ): SkinObject( pIntf ) {}
+};
+
+
+typedef CountedPtr<Variable> VariablePtr;
+
+
+#endif
diff --git a/modules/gui/skins2/vars/playlist.cpp b/modules/gui/skins2/vars/playlist.cpp
new file mode 100644 (file)
index 0000000..60f1668
--- /dev/null
@@ -0,0 +1,178 @@
+/*****************************************************************************
+ * playlist.cpp
+ *****************************************************************************
+ * Copyright (C) 2003 VideoLAN
+ * $Id: playlist.cpp,v 1.1 2004/01/03 23:31:34 asmax Exp $
+ *
+ * Authors: Cyril Deguet     <asmax@via.ecp.fr>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111, USA.
+ *****************************************************************************/
+
+#if defined(HAVE_ICONV)
+#include <iconv.h>
+#include "charset.h"
+#endif
+
+#include "playlist.hpp"
+#include "../utils/ustring.hpp"
+
+
+Playlist::Playlist( intf_thread_t *pIntf ): VarList( pIntf )
+{
+    // Get the playlist VLC object
+    m_pPlaylist = pIntf->p_sys->p_playlist;
+
+#ifdef HAVE_ICONV
+    // Try to guess the current charset
+    char *pCharset = (char*)malloc( 100 );
+    vlc_current_charset( &pCharset );
+    iconvHandle = iconv_open( "UTF-8", pCharset );
+    msg_Dbg( pIntf, "Using character encoding: %s", pCharset );
+    free( pCharset );
+
+    if( iconvHandle == (iconv_t)-1 )
+    {
+        msg_Warn( pIntf, "Unable to do requested conversion" );
+    }
+#else
+    msg_Dbg( p_dec, "No iconv support available" );
+#endif
+
+    buildList();
+}
+
+
+Playlist::~Playlist()
+{
+#ifdef HAVE_ICONV
+    if( iconvHandle != (iconv_t)-1 )
+    {
+        iconv_close( iconvHandle );
+    }
+#endif
+}
+
+
+void Playlist::add( const UStringPtr &rcString )
+{
+    VarList::add( rcString );
+    //XXX
+}
+
+
+void Playlist::delSelected()
+{
+    // Remove the items from the VLC playlist
+    int index = 0;
+    ConstIterator it;
+    for( it = begin(); it != end(); it++ )
+    {
+        if( (*it).m_selected )
+        {
+            playlist_Delete( m_pPlaylist, index );
+        }
+        else
+        {
+            index++;
+        }
+    }
+
+    notify();
+}
+
+
+void Playlist::action( Elem_t *pItem )
+{
+    // Find the index of the item
+    int index = 0;
+    ConstIterator it;
+    for( it = begin(); it != end(); it++ )
+    {
+        if( &*it == pItem ) break;
+        index++;
+    }
+    // Item found ?
+    if( index < size() )
+    {
+        playlist_Goto( m_pPlaylist, index );
+    }
+}
+
+
+void Playlist::onChange()
+{
+    buildList();
+    notify();
+}
+
+
+void Playlist::buildList()
+{
+    clear();
+
+    vlc_mutex_lock( &m_pPlaylist->object_lock );
+    for( int i = 0; i < m_pPlaylist->i_size; i++ )
+    {
+        // Get the name of the playlist item
+        UString *pName = convertName( m_pPlaylist->pp_items[i]->psz_name );
+        // Is it the played stream ?
+        bool playing = (i == m_pPlaylist->i_index );
+        // Add the item in the list
+        m_list.push_back( Elem_t( UStringPtr( pName ), false, playing ) );
+    }
+    vlc_mutex_unlock( &m_pPlaylist->object_lock );
+}
+
+
+UString *Playlist::convertName( const char *pName )
+{
+#ifdef HAVE_ICONV
+    if( iconvHandle == (iconv_t)-1 )
+    {
+        return new UString( getIntf(), pName );
+    }
+
+    char *pNewName, *pBufferOut;
+    const char *pBufferIn;
+    size_t ret, inbytesLeft, outbytesLeft;
+
+    // Try to convert the playlist item into UTF8
+    pNewName = (char*)malloc( 6 * strlen( pName ) );
+    pBufferOut = pNewName;
+    pBufferIn = pName;
+    inbytesLeft = strlen( pName );
+    outbytesLeft = 6 * inbytesLeft;
+    ret = iconv( iconvHandle, (char**)&pBufferIn, &inbytesLeft, &pBufferOut,
+                 &outbytesLeft );
+    *pBufferOut = '\0';
+
+    if( inbytesLeft )
+    {
+        msg_Warn( getIntf(), "Failed to convert the playlist item into UTF8" );
+        free( pNewName );
+        return new UString( getIntf(), pName );
+    }
+    else
+    {
+        UString *pString = new UString( getIntf(), pNewName );
+        free( pNewName );
+        return pString;
+    }
+#else
+    return new UString( getIntf(), pName );
+#endif
+}
+
diff --git a/modules/gui/skins2/vars/playlist.hpp b/modules/gui/skins2/vars/playlist.hpp
new file mode 100644 (file)
index 0000000..2a781e8
--- /dev/null
@@ -0,0 +1,64 @@
+/*****************************************************************************
+ * playlist.hpp
+ *****************************************************************************
+ * Copyright (C) 2003 VideoLAN
+ * $Id: playlist.hpp,v 1.1 2004/01/03 23:31:34 asmax Exp $
+ *
+ * Authors: Cyril Deguet     <asmax@via.ecp.fr>
+ *          Olivier Teulière <ipkiss@via.ecp.fr>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111, USA.
+ *****************************************************************************/
+
+#ifndef PLAYLIST_HPP
+#define PLAYLIST_HPP
+
+#include "../utils/var_list.hpp"
+
+
+/// Variable for VLC playlist
+class Playlist: public VarList
+{
+    public:
+        Playlist( intf_thread_t *pIntf );
+        virtual ~Playlist();
+
+        /// Add a pointer on a string in the list
+        virtual void add( const UStringPtr &rcString );
+
+        /// Remove the selected elements from the list
+        virtual void delSelected();
+
+        /// Execute the action associated to this item
+        virtual void action( Elem_t *pItem );
+
+        /// Function called to notify playlist changes
+        void onChange();
+
+    private:
+        /// VLC playlist object
+        playlist_t *m_pPlaylist;
+        /// Iconv handle
+        iconv_t iconvHandle;
+
+        /// Build the list from the VLC playlist
+        void buildList();
+
+        /// Convert a string to UTF8 from the current encoding
+        UString *convertName( const char *pName );
+};
+
+
+#endif
diff --git a/modules/gui/skins2/vars/time.cpp b/modules/gui/skins2/vars/time.cpp
new file mode 100755 (executable)
index 0000000..436465e
--- /dev/null
@@ -0,0 +1,86 @@
+/*****************************************************************************
+ * time.cpp
+ *****************************************************************************
+ * Copyright (C) 2003 VideoLAN
+ * $Id: time.cpp,v 1.1 2004/01/03 23:31:34 asmax Exp $
+ *
+ * Authors: Cyril Deguet     <asmax@via.ecp.fr>
+ *          Olivier Teulière <ipkiss@via.ecp.fr>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111, USA.
+ *****************************************************************************/
+
+#include <stdio.h>  // snprintf
+
+#include "time.hpp"
+#include <vlc/input.h>
+
+
+void Time::set( double percentage, bool updateVLC )
+{
+    if( getIntf()->p_sys->p_input == NULL )
+    {
+        return;
+    }
+
+    VarPercent::set( percentage );
+
+    // Avoid looping forever...
+    if( updateVLC )
+    {
+        vlc_value_t pos;
+        pos.f_float = percentage;
+
+        var_Set( getIntf()->p_sys->p_input, "position", pos );
+    }
+}
+
+
+string Time::getAsStringPercent() const
+{
+    int value = (int)(100. * get());
+    // 0 <= value <= 100, so we need 4 chars
+    char *str = new char[4];
+    snprintf( str, 4, "%d", value );
+    string ret = str;
+    delete[] str;
+
+    return ret;
+}
+
+
+string Time::getAsStringTime() const
+{
+    if( getIntf()->p_sys->p_input == NULL ||
+        !getIntf()->p_sys->p_input->stream.b_seekable )
+    {
+        return "-:--:--";
+    }
+
+    vlc_value_t time;
+    char *psz_time = new char[MSTRTIME_MAX_SIZE];
+    var_Get( getIntf()->p_sys->p_input, "time", &time );
+
+    int i_seconds = time.i_time / 1000000;
+    snprintf( psz_time, MSTRTIME_MAX_SIZE, "%d:%02d:%02d",
+              (int) (i_seconds / (60 * 60)),
+              (int) (i_seconds / 60 % 60),
+              (int) (i_seconds % 60) );
+
+    string ret = psz_time;
+    delete[] psz_time;
+
+    return ret;
+}
diff --git a/modules/gui/skins2/vars/time.hpp b/modules/gui/skins2/vars/time.hpp
new file mode 100755 (executable)
index 0000000..fe94d1f
--- /dev/null
@@ -0,0 +1,51 @@
+/*****************************************************************************
+ * time.hpp
+ *****************************************************************************
+ * Copyright (C) 2003 VideoLAN
+ * $Id: time.hpp,v 1.1 2004/01/03 23:31:34 asmax Exp $
+ *
+ * Authors: Cyril Deguet     <asmax@via.ecp.fr>
+ *          Olivier Teulière <ipkiss@via.ecp.fr>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111, USA.
+ *****************************************************************************/
+
+#ifndef TIME_HPP
+#define TIME_HPP
+
+
+#include "../utils/var_percent.hpp"
+#include <string>
+
+
+/// Variable for VLC volume
+class Time: public VarPercent
+{
+    public:
+        Time( intf_thread_t *pIntf ): VarPercent( pIntf ) {}
+        virtual ~Time() {}
+
+        virtual void set( double percentage, bool updateVLC );
+
+        virtual void set( double percentage ) { set( percentage, true ); }
+
+        /// Return a string containing a value from 0 to 100
+        virtual string getAsStringPercent() const;
+        /// Return a string formatted as a time display (h:mm:ss)
+        virtual string getAsStringTime() const;
+};
+
+
+#endif
diff --git a/modules/gui/skins2/vars/vlcvars.cpp b/modules/gui/skins2/vars/vlcvars.cpp
new file mode 100644 (file)
index 0000000..37e428d
--- /dev/null
@@ -0,0 +1,66 @@
+/*****************************************************************************
+ * vlcvars.cpp
+ *****************************************************************************
+ * Copyright (C) 2003 VideoLAN
+ * $Id: vlcvars.cpp,v 1.1 2004/01/03 23:31:34 asmax Exp $
+ *
+ * Authors: Cyril Deguet     <asmax@via.ecp.fr>
+ *          Olivier Teulière <ipkiss@via.ecp.fr>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111, USA.
+ *****************************************************************************/
+
+#include "vlcvars.hpp"
+#include <vlc/aout.h>
+
+
+void VlcIsMute::set( bool value )
+{
+    VarBool::set( value );
+
+    aout_VolumeMute( getIntf(), NULL );
+}
+
+
+void VlcIsPlaying::set( bool value, bool updateVLC )
+{
+    VarBool::set( value );
+
+    if( !updateVLC )
+    {
+        return;
+    }
+
+    if( value )
+    {
+        //XXX use a command
+        playlist_t *pPlaylist = getIntf()->p_sys->p_playlist;
+        if( pPlaylist == NULL )
+        {
+            return;
+        }
+        playlist_Play( pPlaylist );
+    }
+    else
+    {
+        //XXX use a command
+        playlist_t *pPlaylist = getIntf()->p_sys->p_playlist;
+        if( pPlaylist == NULL )
+        {
+            return;
+        }
+        playlist_Pause( pPlaylist );
+    }
+}
diff --git a/modules/gui/skins2/vars/vlcvars.hpp b/modules/gui/skins2/vars/vlcvars.hpp
new file mode 100644 (file)
index 0000000..5af0a29
--- /dev/null
@@ -0,0 +1,61 @@
+/*****************************************************************************
+ * vlcvars.hpp
+ *****************************************************************************
+ * Copyright (C) 2003 VideoLAN
+ * $Id: vlcvars.hpp,v 1.1 2004/01/03 23:31:34 asmax Exp $
+ *
+ * Authors: Cyril Deguet     <asmax@via.ecp.fr>
+ *          Olivier Teulière <ipkiss@via.ecp.fr>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111, USA.
+ *****************************************************************************/
+
+#ifndef VLCVARS_HPP
+#define VLCVARS_HPP
+
+#include "../utils/var_bool.hpp"
+
+
+class VlcIsMute: public VarBool
+{
+    public:
+        VlcIsMute( intf_thread_t *pIntf ): VarBool( pIntf ) {}
+        virtual ~VlcIsMute() {}
+
+        virtual void set( bool value );
+};
+
+
+class VlcIsPlaying: public VarBool
+{
+    public:
+        VlcIsPlaying( intf_thread_t *pIntf ): VarBool( pIntf ) {}
+        virtual ~VlcIsPlaying() {}
+
+        virtual void set( bool value, bool updateVLC );
+
+        virtual void set( bool value ) { set( value, true ); }
+};
+
+
+class VlcIsSeekablePlaying: public VarBool
+{
+    public:
+        VlcIsSeekablePlaying( intf_thread_t *pIntf ): VarBool( pIntf ) {}
+        virtual ~VlcIsSeekablePlaying() {}
+};
+
+
+#endif
diff --git a/modules/gui/skins2/vars/volume.cpp b/modules/gui/skins2/vars/volume.cpp
new file mode 100644 (file)
index 0000000..a18321a
--- /dev/null
@@ -0,0 +1,64 @@
+/*****************************************************************************
+ * volume.cpp
+ *****************************************************************************
+ * Copyright (C) 2003 VideoLAN
+ * $Id: volume.cpp,v 1.1 2004/01/03 23:31:34 asmax Exp $
+ *
+ * Authors: Cyril Deguet     <asmax@via.ecp.fr>
+ *          Olivier Teulière <ipkiss@via.ecp.fr>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111, USA.
+ *****************************************************************************/
+
+#include <stdio.h>  // snprintf
+
+#include <vlc/aout.h>
+#include "volume.hpp"
+
+
+Volume::Volume( intf_thread_t *pIntf ): VarPercent( pIntf )
+{
+    // Initial value
+    audio_volume_t val;
+    aout_VolumeGet( getIntf(), &val );
+    VarPercent::set( val / AOUT_VOLUME_MAX );
+}
+
+
+void Volume::set( double percentage )
+{
+    // Avoid looping forever...
+    if( (int)(get() * AOUT_VOLUME_MAX) !=
+        (int)(percentage * AOUT_VOLUME_MAX) )
+    {
+        VarPercent::set( percentage );
+
+        aout_VolumeSet( getIntf(), (int)(get() * AOUT_VOLUME_MAX) );
+    }
+}
+
+
+string Volume::getAsStringPercent() const
+{
+    int value = (int)(100. * VarPercent::get());
+    // 0 <= value <= 100, so we need 4 chars
+    char *str = new char[4];
+    snprintf( str, 4, "%d", value );
+    string ret = str;
+    delete[] str;
+
+    return ret;
+}
+
diff --git a/modules/gui/skins2/vars/volume.hpp b/modules/gui/skins2/vars/volume.hpp
new file mode 100755 (executable)
index 0000000..333645b
--- /dev/null
@@ -0,0 +1,46 @@
+/*****************************************************************************
+ * volume.hpp
+ *****************************************************************************
+ * Copyright (C) 2003 VideoLAN
+ * $Id: volume.hpp,v 1.1 2004/01/03 23:31:34 asmax Exp $
+ *
+ * Authors: Cyril Deguet     <asmax@via.ecp.fr>
+ *          Olivier Teulière <ipkiss@via.ecp.fr>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111, USA.
+ *****************************************************************************/
+
+#ifndef VOLUME_HPP
+#define VOLUME_HPP
+
+
+#include "../utils/var_percent.hpp"
+#include <string>
+
+
+/// Variable for VLC volume
+class Volume: public VarPercent
+{
+    public:
+        Volume( intf_thread_t *pIntf );
+        virtual ~Volume() {}
+
+        virtual void set( double percentage );
+
+        virtual string getAsStringPercent() const;
+};
+
+
+#endif
diff --git a/modules/gui/skins2/win32/win32_dragdrop.cpp b/modules/gui/skins2/win32/win32_dragdrop.cpp
new file mode 100755 (executable)
index 0000000..20af9c1
--- /dev/null
@@ -0,0 +1,171 @@
+/*****************************************************************************
+ * win32_dragdrop.cpp
+ *****************************************************************************
+ * Copyright (C) 2003 VideoLAN
+ * $Id: win32_dragdrop.cpp,v 1.1 2004/01/03 23:31:34 asmax Exp $
+ *
+ * Authors: Cyril Deguet     <asmax@via.ecp.fr>
+ *          Olivier Teulière <ipkiss@via.ecp.fr>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111, USA.
+ *****************************************************************************/
+
+#ifdef WIN32_SKINS
+
+#include <windows.h>
+#include "win32_dragdrop.hpp"
+#include "../commands/cmd_add_item.hpp"
+
+
+Win32DragDrop::Win32DragDrop( intf_thread_t *pIntf, bool playOnDrop ):
+    SkinObject( pIntf ), IDropTarget(), m_references( 1 ),
+    m_playOnDrop( playOnDrop )
+{
+}
+
+
+STDMETHODIMP Win32DragDrop::QueryInterface( REFIID iid, void FAR* FAR* ppv )
+{
+    // Tell other objects about our capabilities
+    if( iid == IID_IUnknown || iid == IID_IDropTarget )
+    {
+        *ppv = this;
+        AddRef();
+        return S_OK;
+    }
+    *ppv = NULL;
+    return ResultFromScode( E_NOINTERFACE );
+}
+
+
+STDMETHODIMP_(ULONG) Win32DragDrop::AddRef()
+{
+    return ++m_references;
+}
+
+
+STDMETHODIMP_(ULONG) Win32DragDrop::Release()
+{
+    if( --m_references == 0 )
+    {
+        delete this;
+        return 0;
+    }
+    return m_references;
+}
+
+
+STDMETHODIMP Win32DragDrop::DragEnter( LPDATAOBJECT pDataObj,
+    DWORD grfKeyState, POINTL pt, DWORD *pdwEffect )
+{
+    FORMATETC fmtetc;
+
+    fmtetc.cfFormat = CF_HDROP;
+    fmtetc.ptd      = NULL;
+    fmtetc.dwAspect = DVASPECT_CONTENT;
+    fmtetc.lindex   = -1;
+    fmtetc.tymed    = TYMED_HGLOBAL;
+
+    // Check that the drag source provides CF_HDROP,
+    // which is the only format we accept
+    if( pDataObj->QueryGetData( &fmtetc ) == S_OK )
+    {
+        *pdwEffect = DROPEFFECT_COPY;
+    }
+    else
+    {
+        *pdwEffect = DROPEFFECT_NONE;
+    }
+
+    return S_OK;
+}
+
+
+STDMETHODIMP Win32DragDrop::DragOver( DWORD grfKeyState, POINTL pt,
+                                      DWORD *pdwEffect )
+{
+    // For visual feedback
+    return S_OK;
+}
+
+
+STDMETHODIMP Win32DragDrop::DragLeave()
+{
+    // Remove visual feedback
+    return S_OK;
+}
+
+
+STDMETHODIMP Win32DragDrop::Drop( LPDATAOBJECT pDataObj, DWORD grfKeyState,
+    POINTL pt, DWORD *pdwEffect )
+{
+    // User has dropped on us -- get the CF_HDROP data from drag source
+    FORMATETC fmtetc;
+    fmtetc.cfFormat = CF_HDROP;
+    fmtetc.ptd      = NULL;
+    fmtetc.dwAspect = DVASPECT_CONTENT;
+    fmtetc.lindex   = -1;
+    fmtetc.tymed    = TYMED_HGLOBAL;
+
+    STGMEDIUM medium;
+    HRESULT hr = pDataObj->GetData( &fmtetc, &medium );
+
+    if( !FAILED(hr) )
+    {
+        // Grab a pointer to the data
+        HGLOBAL HFiles = medium.hGlobal;
+        HDROP HDrop = (HDROP)GlobalLock( HFiles );
+
+        // Notify VLC of the drop
+        HandleDrop( HDrop );
+
+        // Release the pointer to the memory
+        GlobalUnlock( HFiles );
+//        ReleaseStgMedium( &medium );
+    }
+    else
+    {
+        *pdwEffect = DROPEFFECT_NONE;
+        return hr;
+    }
+    return S_OK;
+}
+
+
+void Win32DragDrop::HandleDrop( HDROP HDrop )
+{
+    // Get the number of dropped files
+    int nbFiles = DragQueryFile( HDrop, 0xFFFFFFFF, NULL, 0 );
+
+    // For each dropped file
+    for( int i = 0; i < nbFiles; i++ )
+    {
+        // Get the name of the file
+        int nameLength = DragQueryFile( HDrop, i, NULL, 0 ) + 1;
+        char *psz_fileName = new char[nameLength];
+        DragQueryFile( HDrop, i, psz_fileName, nameLength );
+
+        // Add the file
+        CmdAddItem cmd( getIntf(), psz_fileName, m_playOnDrop );
+        cmd.execute();
+
+        delete[] psz_fileName;
+    }
+
+    DragFinish( HDrop );
+}
+
+
+#endif
diff --git a/modules/gui/skins2/win32/win32_dragdrop.hpp b/modules/gui/skins2/win32/win32_dragdrop.hpp
new file mode 100755 (executable)
index 0000000..3647da3
--- /dev/null
@@ -0,0 +1,64 @@
+/*****************************************************************************
+ * win32_dragdrop.hpp
+ *****************************************************************************
+ * Copyright (C) 2003 VideoLAN
+ * $Id: win32_dragdrop.hpp,v 1.1 2004/01/03 23:31:34 asmax Exp $
+ *
+ * Authors: Cyril Deguet     <asmax@via.ecp.fr>
+ *          Olivier Teulière <ipkiss@via.ecp.fr>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111, USA.
+ *****************************************************************************/
+
+#ifndef WIN32_DRAGDROP_HPP
+#define WIN32_DRAGDROP_HPP
+
+#include <shellapi.h>
+#include <ole2.h>
+#include "../src/skin_common.hpp"
+
+
+class Win32DragDrop: public SkinObject, public IDropTarget
+{
+    public:
+       Win32DragDrop( intf_thread_t *pIntf, bool playOnDrop );
+       virtual ~Win32DragDrop() {}
+
+    protected:
+        // IUnknown methods
+        STDMETHOD(QueryInterface)( REFIID riid, void FAR* FAR* ppvObj );
+        STDMETHOD_(ULONG, AddRef)();
+        STDMETHOD_(ULONG, Release)();
+
+        // IDropTarget methods
+        STDMETHOD(DragEnter)( LPDATAOBJECT pDataObj, DWORD grfKeyState,
+                              POINTL pt, DWORD *pdwEffect );
+        STDMETHOD(DragOver)( DWORD grfKeyState, POINTL pt, DWORD *pdwEffect );
+        STDMETHOD(DragLeave)();
+        STDMETHOD(Drop)( LPDATAOBJECT pDataObj, DWORD grfKeyState,
+                         POINTL pt, DWORD *pdwEffect );
+
+    private:
+        /// Internal reference counter
+        unsigned long m_references;
+        /// Indicates whether the file(s) must be played immediately
+        bool m_playOnDrop;
+
+        /// Helper function
+        void HandleDrop( HDROP HDrop );
+};
+
+
+#endif
diff --git a/modules/gui/skins2/win32/win32_factory.cpp b/modules/gui/skins2/win32/win32_factory.cpp
new file mode 100644 (file)
index 0000000..ea0897b
--- /dev/null
@@ -0,0 +1,304 @@
+/*****************************************************************************
+ * win32_factory.cpp
+ *****************************************************************************
+ * Copyright (C) 2003 VideoLAN
+ * $Id: win32_factory.cpp,v 1.1 2004/01/03 23:31:34 asmax Exp $
+ *
+ * Authors: Cyril Deguet     <asmax@via.ecp.fr>
+ *          Olivier Teulière <ipkiss@via.ecp.fr>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111, USA.
+ *****************************************************************************/
+
+#ifdef WIN32_SKINS
+
+#include "win32_factory.hpp"
+#include "win32_graphics.hpp"
+#include "win32_timer.hpp"
+#include "win32_window.hpp"
+#include "win32_tooltip.hpp"
+#include "win32_loop.hpp"
+
+
+LRESULT CALLBACK Win32Proc( HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam )
+{
+    // Get pointer to thread info: should only work with the parent window
+    intf_thread_t *p_intf = (intf_thread_t *)GetWindowLongPtr( hwnd,
+        GWLP_USERDATA );
+
+    // If doesn't exist, treat windows message normally
+    if( p_intf == NULL || p_intf->p_sys->p_osFactory == NULL )
+    {
+        return DefWindowProc( hwnd, uMsg, wParam, lParam );
+    }
+
+    // Here we know we are getting a message for the parent window, since it is
+    // the only one to store p_intf...
+    // Yes, it is a kludge :)
+
+//Win32Factory *pFactory = (Win32Factory*)Win32Factory::instance( p_intf );
+//msg_Err( p_intf, "Parent window %p %p %u %i\n", pFactory->m_hParentWindow, hwnd, uMsg, wParam );
+    // If Window is parent window
+    // XXX: this test isn't needed, see the kludge above...
+//    if( hwnd == pFactory->m_hParentWindow )
+    {
+        if( uMsg == WM_SYSCOMMAND )
+        {
+            // If closing parent window
+            if( wParam == SC_CLOSE )
+            {
+                Win32Loop *pLoop = (Win32Loop*)Win32Loop::instance( p_intf );
+                pLoop->exit();
+                return 0;
+            }
+            else
+            {
+                msg_Err( p_intf, "WM_SYSCOMMAND %i", wParam );
+            }
+//            if( (Event *)wParam != NULL )
+//                ( (Event *)wParam )->SendEvent();
+//            return 0;
+        }
+    }
+
+    // If hwnd does not match any window or message not processed
+    return DefWindowProc( hwnd, uMsg, wParam, lParam );
+}
+
+
+Win32Factory::Win32Factory( intf_thread_t *pIntf ):
+    OSFactory( pIntf ), TransparentBlt( NULL ),
+    SetLayeredWindowAttributes( NULL )
+{
+    // see init()
+}
+
+
+bool Win32Factory::init()
+{
+    // Get instance handle
+    m_hInst = GetModuleHandle( NULL );
+    if( m_hInst == NULL )
+    {
+        msg_Err( getIntf(), "Cannot get module handle" );
+    }
+
+    // Create window class
+    WNDCLASS skinWindowClass;
+    skinWindowClass.style = CS_VREDRAW | CS_HREDRAW | CS_DBLCLKS;
+    skinWindowClass.lpfnWndProc = (WNDPROC) Win32Proc;
+    skinWindowClass.lpszClassName = "SkinWindowClass";
+    skinWindowClass.lpszMenuName = NULL;
+    skinWindowClass.cbClsExtra = 0;
+    skinWindowClass.cbWndExtra = 0;
+    skinWindowClass.hbrBackground = HBRUSH (COLOR_WINDOW);
+    skinWindowClass.hCursor = LoadCursor( NULL , IDC_ARROW );
+    skinWindowClass.hIcon = LoadIcon( m_hInst, "VLC_ICON" );
+    skinWindowClass.hInstance = m_hInst;
+
+    // Register class and check it
+    if( !RegisterClass( &skinWindowClass ) )
+    {
+        WNDCLASS wndclass;
+
+        // Check why it failed. If it's because the class already exists
+        // then fine, otherwise return with an error.
+        if( !GetClassInfo( m_hInst, "SkinWindowClass", &wndclass ) )
+        {
+            msg_Err( getIntf(), "Cannot register window class" );
+            return false;
+        }
+    }
+
+    // Create Window
+    m_hParentWindow = CreateWindowEx( WS_EX_APPWINDOW, "SkinWindowClass",
+        "VLC Media Player", WS_SYSMENU, 0, 0, 0, 0, 0, 0,
+        m_hInst, NULL );
+    if( m_hParentWindow == NULL )
+    {
+        msg_Err( getIntf(), "Cannot create parent window" );
+        return false;
+    }
+
+    // We do it this way otherwise CreateWindowEx will fail
+    // if WS_EX_LAYERED is not supported
+    SetWindowLongPtr( m_hParentWindow, GWL_EXSTYLE,
+                      GetWindowLong( m_hParentWindow, GWL_EXSTYLE )
+                      | WS_EX_LAYERED );
+
+    // Store with it a pointer to the interface thread
+    SetWindowLongPtr( m_hParentWindow, GWLP_USERDATA, (LONG_PTR)getIntf() );
+    ShowWindow( m_hParentWindow, SW_SHOW );
+
+    // Initialize the OLE library (for drag & drop)
+    OleInitialize( NULL );
+
+    // We dynamically load msimg32.dll to get a pointer to TransparentBlt()
+    m_hMsimg32 = LoadLibrary( "msimg32.dll" );
+    if( !m_hMsimg32 ||
+        !( TransparentBlt =
+            (BOOL (WINAPI*)(HDC, int, int, int, int,
+                            HDC, int, int, int, int, unsigned int))
+            GetProcAddress( m_hMsimg32, "TransparentBlt" ) ) )
+    {
+        TransparentBlt = NULL;
+        msg_Dbg( getIntf(), "Couldn't find TransparentBlt(), "
+                 "falling back to BitBlt()" );
+    }
+
+    // Idem for user32.dll and SetLayeredWindowAttributes()
+    m_hUser32 = LoadLibrary( "user32.dll" );
+    if( !m_hUser32 ||
+        !( SetLayeredWindowAttributes =
+            (BOOL (WINAPI *)(HWND, COLORREF, BYTE, DWORD))
+            GetProcAddress( m_hUser32, "SetLayeredWindowAttributes" ) ) )
+    {
+        SetLayeredWindowAttributes = NULL;
+        msg_Dbg( getIntf(), "Couldn't find SetLayeredWindowAttributes()" );
+    }
+
+    // All went well
+    return true;
+}
+
+
+Win32Factory::~Win32Factory()
+{
+    // Uninitialize the OLE library
+    OleUninitialize();
+
+    // Unload msimg32.dll and user32.dll
+    if( m_hMsimg32 )
+        FreeLibrary( m_hMsimg32 );
+    if( m_hUser32 )
+        FreeLibrary( m_hUser32 );
+}
+
+
+OSGraphics *Win32Factory::createOSGraphics( int width, int height )
+{
+    return new Win32Graphics( getIntf(), width, height );
+}
+
+
+OSLoop *Win32Factory::getOSLoop()
+{
+    return Win32Loop::instance( getIntf() );
+}
+
+
+void Win32Factory::destroyOSLoop()
+{
+    Win32Loop::destroy( getIntf() );
+}
+
+
+OSTimer *Win32Factory::createOSTimer( const Callback &rCallback )
+{
+    return new Win32Timer( getIntf(), rCallback, m_hParentWindow );
+}
+
+
+OSWindow *Win32Factory::createOSWindow( GenericWindow &rWindow, bool dragDrop,
+                                        bool playOnDrop )
+{
+    return new Win32Window( getIntf(), rWindow, m_hInst, m_hParentWindow,
+                            dragDrop, playOnDrop );
+}
+
+
+OSTooltip *Win32Factory::createOSTooltip()
+{
+    return new Win32Tooltip( getIntf(), m_hInst, m_hParentWindow );
+}
+
+
+const string Win32Factory::getDirSeparator() const
+{
+    return "\\";
+}
+
+
+int Win32Factory::getScreenWidth() const
+{
+    return GetSystemMetrics(SM_CXSCREEN);
+
+}
+
+
+int Win32Factory::getScreenHeight() const
+{
+    return GetSystemMetrics(SM_CYSCREEN);
+}
+
+
+Rect Win32Factory::getWorkArea() const
+{
+    RECT r;
+    SystemParametersInfo( SPI_GETWORKAREA, 0, &r, 0 );
+    // Fill a Rect object
+    Rect rect( r.left, r.top, r.right, r.bottom );
+    return rect;
+}
+
+
+void Win32Factory::getMousePos( int &rXPos, int &rYPos ) const
+{
+    POINT mousePos;
+    GetCursorPos( &mousePos );
+    rXPos = mousePos.x;
+    rYPos = mousePos.y;
+}
+
+
+void Win32Factory::rmDir( const string &rPath )
+{
+    WIN32_FIND_DATA find;
+    string file;
+    string findFiles = rPath + "\\*";
+    HANDLE handle    = FindFirstFile( findFiles.c_str(), &find );
+
+    while( handle != INVALID_HANDLE_VALUE )
+    {
+        // If file is neither "." nor ".."
+        if( strcmp( find.cFileName, "." ) && strcmp( find.cFileName, ".." ) )
+        {
+            // Set file name
+            file = rPath + "\\" + (string)find.cFileName;
+
+            // If file is a directory, delete it recursively
+            if( find.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY )
+            {
+                rmDir( file );
+            }
+            // Else, it is a file so simply delete it
+            else
+            {
+                DeleteFile( file.c_str() );
+            }
+        }
+
+        // If no more file in directory, exit while
+        if( !FindNextFile( handle, &find ) )
+            break;
+    }
+
+    // Now directory is empty so can be removed
+    FindClose( handle );
+    RemoveDirectory( rPath.c_str() );
+}
+
+
+#endif
diff --git a/modules/gui/skins2/win32/win32_factory.hpp b/modules/gui/skins2/win32/win32_factory.hpp
new file mode 100644 (file)
index 0000000..0638f1d
--- /dev/null
@@ -0,0 +1,103 @@
+/*****************************************************************************
+ * win32_factory.hpp
+ *****************************************************************************
+ * Copyright (C) 2003 VideoLAN
+ * $Id: win32_factory.hpp,v 1.1 2004/01/03 23:31:34 asmax Exp $
+ *
+ * Authors: Cyril Deguet     <asmax@via.ecp.fr>
+ *          Olivier Teulière <ipkiss@via.ecp.fr>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111, USA.
+ *****************************************************************************/
+
+#ifndef WIN32_FACTORY_HPP
+#define WIN32_FACTORY_HPP
+
+#include <windows.h>
+#include "../src/os_factory.hpp"
+#include <map>
+
+
+/// Class used to instanciate Win32 specific objects
+class Win32Factory: public OSFactory
+{
+    public:
+        Win32Factory( intf_thread_t *pIntf );
+        virtual ~Win32Factory();
+
+        /// Initialization method
+        virtual bool init();
+
+        /// Instantiate an object OSGraphics.
+        virtual OSGraphics *createOSGraphics( int width, int height );
+
+        /// Get the instance of the singleton OSLoop.
+        virtual OSLoop *getOSLoop();
+
+        /// Destroy the instance of OSLoop.
+        virtual void destroyOSLoop();
+
+        /// Instantiate an OSTimer with the given callback
+        virtual OSTimer *createOSTimer( const Callback &rCallback );
+
+        /// Instantiate an OSWindow object
+        virtual OSWindow *createOSWindow( GenericWindow &rWindow,
+                                          bool dragDrop, bool playOnDrop );
+
+        /// Instantiate an object OSTooltip.
+        virtual OSTooltip *createOSTooltip();
+
+        /// Get the directory separator
+        virtual const string getDirSeparator() const;
+
+        /// Get the screen size
+        virtual int getScreenWidth() const;
+        virtual int getScreenHeight() const;
+
+        /// Get the work area (screen area without taskbars)
+        virtual Rect getWorkArea() const;
+
+        /// Get the position of the mouse
+        virtual void getMousePos( int &rXPos, int &rYPos ) const;
+
+        /// Delete a directory recursively
+        virtual void rmDir( const string &rPath );
+
+        /// Map to find the GenericWindow associated with a Win32Window
+        map<HWND, GenericWindow*> m_windowMap;
+
+
+        /// Functions dynamically loaded from the dll, because they don't exist
+        /// on win9x
+        // We dynamically load msimg32.dll to get a pointer to TransparentBlt()
+        BOOL (WINAPI *TransparentBlt)( HDC, int, int, int, int,
+                                       HDC, int, int, int, int, UINT );
+        // Idem for user32.dll and SetLayeredWindowAttributes()
+        BOOL (WINAPI *SetLayeredWindowAttributes)( HWND, COLORREF,
+                                                   BYTE, DWORD );
+
+    private:
+        /// Handle of the instance
+        HINSTANCE m_hInst;
+        /// Handle of the parent window
+        HWND m_hParentWindow;
+        /// Handle on msimg32.dll (for TransparentBlt)
+        HINSTANCE m_hMsimg32;
+        /// Handle on user32.dll (for SetLayeredWindowAttributes)
+        HINSTANCE m_hUser32;
+};
+
+
+#endif
diff --git a/modules/gui/skins2/win32/win32_graphics.cpp b/modules/gui/skins2/win32/win32_graphics.cpp
new file mode 100755 (executable)
index 0000000..e4173c0
--- /dev/null
@@ -0,0 +1,331 @@
+/*****************************************************************************
+ * win32_graphics.cpp
+ *****************************************************************************
+ * Copyright (C) 2003 VideoLAN
+ * $Id: win32_graphics.cpp,v 1.1 2004/01/03 23:31:34 asmax Exp $
+ *
+ * Authors: Cyril Deguet     <asmax@via.ecp.fr>
+ *          Olivier Teulière <ipkiss@via.ecp.fr>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111, USA.
+ *****************************************************************************/
+
+#ifdef WIN32_SKINS
+
+#define WINVER 0x500
+#ifndef AC_SRC_ALPHA
+#define AC_SRC_ALPHA 1
+#endif
+
+#include "win32_graphics.hpp"
+#include "win32_window.hpp"
+#include "../src/generic_bitmap.hpp"
+
+Win32Graphics::Win32Graphics( intf_thread_t *pIntf, int width, int height ):
+    OSGraphics( pIntf ), m_width( width ), m_height( height ), m_hDC( NULL )
+{
+    HBITMAP hBmp;
+    HDC hDC = GetDC( NULL );
+    hBmp = CreateCompatibleBitmap( hDC, m_width, m_height );
+    ReleaseDC( NULL, hDC );
+
+    m_hDC = CreateCompatibleDC( NULL );
+    SelectObject( m_hDC, hBmp );
+    DeleteObject( hBmp );
+
+    // Create the mask
+    m_mask = CreateRectRgn( 0, 0, 0, 0 );
+}
+
+
+Win32Graphics::~Win32Graphics()
+{
+    DeleteDC( m_hDC );
+    DeleteObject( m_mask );
+}
+
+
+void Win32Graphics::clear()
+{
+    // Clear the transparency mask
+    DeleteObject( m_mask );
+    m_mask = CreateRectRgn( 0, 0, 0, 0 );
+}
+
+
+void Win32Graphics::drawBitmap( const GenericBitmap &rBitmap,
+                                int xSrc, int ySrc, int xDest, int yDest,
+                                int width, int height )
+{
+    // Get the bitmap size if necessary
+    if( width == -1 )
+    {
+        width = rBitmap.getWidth();
+    }
+    if( height == -1 )
+    {
+        height = rBitmap.getHeight();
+    }
+
+    if( xDest + width > m_width || yDest + height > m_height )
+    {
+        msg_Err( getIntf(), "Bitmap too large !" );
+        return;
+    }
+
+    // Get a buffer on the image data
+    uint8_t *pBmpData = rBitmap.getData();
+    if( pBmpData == NULL )
+    {
+        // Nothing to draw
+        return;
+    }
+
+    void *pBits;     // pointer to DIB section
+    // Fill a BITMAPINFO structure
+    BITMAPINFO bmpInfo;
+    memset( &bmpInfo, 0, sizeof( bmpInfo ) );
+    bmpInfo.bmiHeader.biSize = sizeof( BITMAPINFOHEADER );
+    bmpInfo.bmiHeader.biWidth = width;
+    bmpInfo.bmiHeader.biHeight = -height;
+    bmpInfo.bmiHeader.biPlanes = 1;
+    bmpInfo.bmiHeader.biBitCount = 32;
+    bmpInfo.bmiHeader.biCompression = BI_RGB;
+    bmpInfo.bmiHeader.biSizeImage = width * height * 4;
+
+    // Create a DIB (Device Independant Bitmap) and associate it with
+    // a temporary DC
+    HDC hDC = CreateCompatibleDC( m_hDC );
+    HBITMAP hBmp = CreateDIBSection( hDC, &bmpInfo, DIB_RGB_COLORS,
+                                     &pBits, NULL, 0 );
+    SelectObject( hDC, hBmp );
+
+    // Mask for transparency
+    HRGN mask = CreateRectRgn( 0, 0, 0, 0 );
+
+    // Skip the first lines of the image
+    pBmpData += 4 * ySrc * rBitmap.getWidth();
+
+    // Copy the bitmap on the image and compute the mask
+    for( int y = 0; y < height; y++ )
+    {
+        // Skip uninteresting bytes at the beginning of the line
+        pBmpData += 4 * xSrc;
+        // Flag to say whether the previous pixel on the line was visible
+        bool wasVisible = false;
+        // Beginning of the current visible segment on the line
+        int visibleSegmentStart = 0;
+        for( int x = 0; x < width; x++ )
+        {
+            uint8_t b = *(pBmpData++);
+            uint8_t g = *(pBmpData++);
+            uint8_t r = *(pBmpData++);
+            uint8_t a = *(pBmpData++);
+
+            // Draw the pixel
+           ((UINT32 *)pBits)[x + y * width] =
+                   (a << 24) | (r << 16) | (g << 8) | b;
+
+            if( a > 0 )
+            {
+                // Pixel is visible
+                if( ! wasVisible )
+                {
+                    // Beginning of a visible segment
+                    visibleSegmentStart = x;
+                }
+                wasVisible = true;
+            }
+            else
+            {
+                // Pixel is transparent
+                if( wasVisible )
+                {
+                    // End of a visible segment: add it to the mask
+                    addSegmentInRegion( mask, visibleSegmentStart, x, y );
+                }
+                wasVisible = false;
+            }
+        }
+        if( wasVisible )
+        {
+            // End of a visible segment: add it to the mask
+            addSegmentInRegion( mask, visibleSegmentStart, width, y );
+        }
+        // Skip uninteresting bytes at the end of the line
+        pBmpData += 4 * (rBitmap.getWidth() - width - xSrc);
+    }
+
+    // Apply the mask to the internal DC
+    OffsetRgn( mask, xDest, yDest );
+    SelectClipRgn( m_hDC, mask );
+
+    BLENDFUNCTION bf;      // structure for alpha blending
+    bf.BlendOp = AC_SRC_OVER;
+    bf.BlendFlags = 0;
+    bf.SourceConstantAlpha = 0xff;  // don't use constant alpha
+    bf.AlphaFormat = AC_SRC_ALPHA;
+
+    // Blend the image onto the internal DC
+    if( !AlphaBlend( m_hDC, xDest, yDest, width, height, hDC, 0, 0,
+                     width, height, bf ) )
+    {
+        msg_Err( getIntf(), "AlphaBlend() failed" );
+    }
+
+    // Copy the image onto the internal DC
+ //   BitBlt( m_hDC, xDest, yDest, width, height, hDC, 0, 0, SRCCOPY );
+
+    // Add the bitmap mask to the global graphics mask
+    CombineRgn( m_mask, m_mask, mask, RGN_OR );
+
+    // Do cleanup
+    DeleteObject( hBmp );
+    DeleteObject( mask );
+    DeleteDC( hDC );
+}
+
+
+void Win32Graphics::drawGraphics( const OSGraphics &rGraphics, int xSrc,
+                                  int ySrc, int xDest, int yDest, int width,
+                                  int height )
+{
+    if( width == -1 )
+    {
+        width = rGraphics.getWidth();
+    }
+    if( height == -1 )
+    {
+        height = rGraphics.getHeight();
+    }
+
+    // Create the mask for transparency
+    HRGN mask = CreateRectRgn( xSrc, ySrc, xSrc + width, ySrc + height );
+    CombineRgn( mask, ((Win32Graphics&)rGraphics).getMask(), mask, RGN_AND );
+    OffsetRgn( mask, xDest - xSrc, yDest - ySrc );
+
+    // Copy the image
+    HDC srcDC = ((Win32Graphics&)rGraphics).getDC();
+    SelectClipRgn( m_hDC, mask );
+    BitBlt( m_hDC, xDest, yDest, width, height, srcDC, xSrc, ySrc, SRCCOPY );
+
+    // Add the source mask to the mask of the graphics
+    CombineRgn( m_mask, mask, m_mask, RGN_OR );
+    DeleteObject( mask );
+}
+
+
+void Win32Graphics::fillRect( int left, int top, int width, int height,
+                              uint32_t color )
+{
+    // Update the mask with the rectangle area
+    HRGN newMask = CreateRectRgn( left, top, left + width, top + height );
+    CombineRgn( m_mask, m_mask, newMask, RGN_OR );
+    SelectClipRgn( m_hDC, m_mask );
+
+    // Create a brush with the color
+    int red = (color & 0xff0000) >> 16;
+    int green = (color & 0xff00) >> 8;
+    int blue = color & 0xff;
+    HBRUSH hBrush = CreateSolidBrush( RGB( red, green, blue ) );
+
+    // Draw the rectangle
+    RECT r;
+    r.left = left;
+    r.top = top;
+    r.right = left + width;
+    r.bottom = top + height;
+    FillRect( m_hDC, &r, hBrush );
+}
+
+
+void Win32Graphics::drawRect( int left, int top, int width, int height,
+                              uint32_t color )
+{
+    // Update the mask with the rectangle
+    HRGN l1 = CreateRectRgn( left, top, left + width, top );
+    HRGN l2 = CreateRectRgn( left + width, top, left + width, top + height );
+    HRGN l3 = CreateRectRgn( left + width, top + height, left, top + height );
+    HRGN l4 = CreateRectRgn( left, top + height, left, top );
+    CombineRgn( m_mask, m_mask, l1, RGN_OR );
+    CombineRgn( m_mask, m_mask, l2, RGN_OR );
+    CombineRgn( m_mask, m_mask, l3, RGN_OR );
+    CombineRgn( m_mask, m_mask, l4, RGN_OR );
+    SelectClipRgn( m_hDC, m_mask );
+
+    // Create a pen with the color
+    int red = (color & 0xff0000) >> 16;
+    int green = (color & 0xff00) >> 8;
+    int blue = color & 0xff;
+    HPEN hPen = CreatePen( PS_SOLID, 0, RGB( red, green, blue ) );
+    SelectObject( m_hDC, hPen );
+
+    // Draw the rectangle
+    MoveToEx( m_hDC, left, top, NULL );
+    LineTo( m_hDC, left + width - 1, top );
+    LineTo( m_hDC, left + width - 1, top + height - 1 );
+    LineTo( m_hDC, left, top + height - 1 );
+    LineTo( m_hDC, left, top );
+
+    // Delete the pen
+    DeleteObject( hPen );
+}
+
+
+void Win32Graphics::applyMaskToWindow( OSWindow &rWindow )
+{
+    // Get window handle
+    HWND hWnd = ((Win32Window&)rWindow).getHandle();
+
+    // Apply the mask
+    // We need to copy the mask, because SetWindowRgn modifies it in our back
+    HRGN mask = CreateRectRgn( 0, 0, 0, 0 );
+    CombineRgn( mask, m_mask, NULL, RGN_COPY );
+    SetWindowRgn( hWnd, mask, TRUE );
+}
+
+
+void Win32Graphics::copyToWindow( OSWindow &rWindow, int xSrc, int ySrc,
+                                  int width, int height, int xDest, int yDest )
+{
+    // Initialize painting
+    HWND hWnd = ((Win32Window&)rWindow).getHandle();
+    HDC wndDC = GetWindowDC( hWnd );
+    HDC srcDC = m_hDC;
+
+    // Draw image on window
+    BitBlt( wndDC, xDest, yDest, width, height, srcDC, xSrc, ySrc, SRCCOPY );
+
+    // Release window device context
+    ReleaseDC( hWnd, wndDC );
+}
+
+
+bool Win32Graphics::hit( int x, int y ) const
+{
+    return PtInRegion( m_mask, x, y );
+}
+
+
+void Win32Graphics::addSegmentInRegion( HRGN &rMask, int start,
+                                        int end, int line )
+{
+    HRGN buffer;
+    buffer = CreateRectRgn( start, line, end, line + 1 );
+    CombineRgn( rMask, buffer, rMask, RGN_OR );
+    DeleteObject( buffer );
+}
+
+#endif
diff --git a/modules/gui/skins2/win32/win32_graphics.hpp b/modules/gui/skins2/win32/win32_graphics.hpp
new file mode 100644 (file)
index 0000000..5928f5b
--- /dev/null
@@ -0,0 +1,99 @@
+/*****************************************************************************
+ * win32_graphics.hpp
+ *****************************************************************************
+ * Copyright (C) 2003 VideoLAN
+ * $Id: win32_graphics.hpp,v 1.1 2004/01/03 23:31:34 asmax Exp $
+ *
+ * Authors: Cyril Deguet     <asmax@via.ecp.fr>
+ *          Olivier Teulière <ipkiss@via.ecp.fr>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111, USA.
+ *****************************************************************************/
+
+#ifndef WIN32_GRAPHICS_HPP
+#define WIN32_GRAPHICS_HPP
+
+#include "../src/os_graphics.hpp"
+#include <windows.h>
+
+
+class GenericBitmap;
+
+/// Win32 implementation of OSGraphics
+class Win32Graphics: public OSGraphics
+{
+    public:
+        Win32Graphics( intf_thread_t *pIntf, int width, int height );
+        virtual ~Win32Graphics();
+
+        /// Clear the graphics
+        virtual void clear();
+
+        /// Render a bitmap on this graphics
+        virtual void drawBitmap( const GenericBitmap &rBitmap, int xSrc = 0,
+                                 int ySrc = 0, int xDest = 0, int yDest = 0,
+                                 int width = -1, int height = -1 );
+
+        /// Draw another graphics on this one
+        virtual void drawGraphics( const OSGraphics &rGraphics, int xSrc = 0,
+                                   int ySrc = 0, int xDest = 0, int yDest = 0,
+                                   int width = -1, int height = -1 );
+
+        /// Draw an empty rectangle on the grahics (color is #RRGGBB)
+        virtual void drawRect( int left, int top, int width, int height,
+                               uint32_t color );
+
+
+        /// Draw a filled rectangle on the grahics (color is #RRGGBB)
+        virtual void fillRect( int left, int top, int width, int height,
+                               uint32_t color );
+
+        /// Set the shape of a window with the mask of this graphics.
+        virtual void applyMaskToWindow( OSWindow &rWindow );
+
+        /// Copy the graphics on a window
+        virtual void copyToWindow( OSWindow &rWindow, int xSrc,
+                                   int ySrc, int width, int height,
+                                   int xDest, int yDest );
+
+        /// Tell whether the pixel at the given position is visible
+        virtual bool hit( int x, int y ) const;
+
+        /// Getters for the size
+        virtual int getWidth() const { return m_width; }
+        virtual int getHeight() const { return m_height; }
+
+        /// Get the device context handler
+        virtual HDC getDC() const { return m_hDC; }
+
+        /// Get the mask
+        virtual HRGN getMask() const { return m_mask; }
+
+    private:
+        /// Size of the image
+        int m_width, m_height;
+
+        /// Device context
+        HDC m_hDC;
+
+        /// Transparency mask
+        HRGN m_mask;
+
+        /// Add a segment in a region
+        void addSegmentInRegion( HRGN &rMask, int start, int end, int line );
+};
+
+
+#endif
diff --git a/modules/gui/skins2/win32/win32_loop.cpp b/modules/gui/skins2/win32/win32_loop.cpp
new file mode 100755 (executable)
index 0000000..f5ae615
--- /dev/null
@@ -0,0 +1,302 @@
+/*****************************************************************************
+ * win32_loop.cpp
+ *****************************************************************************
+ * Copyright (C) 2003 VideoLAN
+ * $Id: win32_loop.cpp,v 1.1 2004/01/03 23:31:34 asmax Exp $
+ *
+ * Authors: Cyril Deguet     <asmax@via.ecp.fr>
+ *          Olivier Teulière <ipkiss@via.ecp.fr>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111, USA.
+ *****************************************************************************/
+
+#ifdef WIN32_SKINS
+
+#include "win32_loop.hpp"
+#include "win32_factory.hpp"
+#include "../src/generic_window.hpp"
+#include "../events/evt_key.hpp"
+#include "../events/evt_leave.hpp"
+#include "../events/evt_motion.hpp"
+#include "../events/evt_mouse.hpp"
+#include "../events/evt_refresh.hpp"
+#include "../events/evt_scroll.hpp"
+#include "vlc_keys.h"
+
+
+// XXX: Cygwin (at least) doesn't define these macros. Too bad...
+#ifndef GET_X_LPARAM
+    #define GET_X_LPARAM(a) ((int16_t)(a))
+    #define GET_Y_LPARAM(a) ((int16_t)((a)>>16))
+#endif
+
+
+Win32Loop::Win32Loop( intf_thread_t *pIntf ): OSLoop( pIntf )
+{
+    // Initialize the map
+    virtKeyToVlcKey[VK_F1] = KEY_F1;
+    virtKeyToVlcKey[VK_F2] = KEY_F2;
+    virtKeyToVlcKey[VK_F3] = KEY_F3;
+    virtKeyToVlcKey[VK_F4] = KEY_F4;
+    virtKeyToVlcKey[VK_F5] = KEY_F5;
+    virtKeyToVlcKey[VK_F6] = KEY_F6;
+    virtKeyToVlcKey[VK_F7] = KEY_F7;
+    virtKeyToVlcKey[VK_F8] = KEY_F8;
+    virtKeyToVlcKey[VK_F9] = KEY_F9;
+    virtKeyToVlcKey[VK_F10] = KEY_F10;
+    virtKeyToVlcKey[VK_F11] = KEY_F11;
+    virtKeyToVlcKey[VK_F12] = KEY_F12;
+    virtKeyToVlcKey[VK_RETURN] = KEY_ENTER;
+    virtKeyToVlcKey[VK_SPACE] = KEY_SPACE;
+    virtKeyToVlcKey[VK_ESCAPE] = KEY_ESC;
+    virtKeyToVlcKey[VK_LEFT] = KEY_LEFT;
+    virtKeyToVlcKey[VK_RIGHT] = KEY_RIGHT;
+    virtKeyToVlcKey[VK_UP] = KEY_UP;
+    virtKeyToVlcKey[VK_DOWN] = KEY_DOWN;
+    virtKeyToVlcKey[VK_HOME] = KEY_HOME;
+    virtKeyToVlcKey[VK_END] = KEY_END;
+    virtKeyToVlcKey[VK_PRIOR] = KEY_PAGEUP;
+    virtKeyToVlcKey[VK_NEXT] = KEY_PAGEDOWN;
+}
+
+
+Win32Loop::~Win32Loop()
+{
+}
+
+
+OSLoop *Win32Loop::instance( intf_thread_t *pIntf )
+{
+    if( pIntf->p_sys->p_osLoop == NULL )
+    {
+        OSLoop *pOsLoop = new Win32Loop( pIntf );
+        pIntf->p_sys->p_osLoop = pOsLoop;
+    }
+    return pIntf->p_sys->p_osLoop;
+}
+
+
+void Win32Loop::destroy( intf_thread_t *pIntf )
+{
+    if( pIntf->p_sys->p_osLoop )
+    {
+        delete pIntf->p_sys->p_osLoop;
+        pIntf->p_sys->p_osLoop = NULL;
+    }
+}
+
+
+void Win32Loop::run()
+{
+    MSG msg;
+
+    // Compute windows message list
+    while( GetMessage( &msg, NULL, 0, 0 ) )
+    {
+        Win32Factory *pFactory =
+            (Win32Factory*)Win32Factory::instance( getIntf() );
+        GenericWindow *pWin = pFactory->m_windowMap[msg.hwnd];
+        if( pWin == NULL )
+        {
+            // We are probably getting a message for a tooltip (which has no
+            // associated GenericWindow), for a timer, or for the parent window
+            DispatchMessage( &msg );
+            continue;
+        }
+
+        GenericWindow &win = *pWin;
+        switch( msg.message )
+        {
+            case WM_PAINT:
+            {
+                PAINTSTRUCT Infos;
+                BeginPaint( msg.hwnd, &Infos );
+                EvtRefresh evt( getIntf(), 0, 0, Infos.rcPaint.right,
+                                Infos.rcPaint.bottom );
+                EndPaint( msg.hwnd, &Infos );
+                win.processEvent( evt );
+                break;
+            }
+            case WM_MOUSEMOVE:
+            {
+                // Needed to generate WM_MOUSELEAVE events
+                TRACKMOUSEEVENT TrackEvent;
+                TrackEvent.cbSize      = sizeof( TRACKMOUSEEVENT );
+                TrackEvent.dwFlags     = TME_LEAVE;
+                TrackEvent.hwndTrack   = msg.hwnd;
+                TrackEvent.dwHoverTime = 1;
+                TrackMouseEvent( &TrackEvent );
+
+                // Compute the absolute position of the mouse
+                int x = GET_X_LPARAM( msg.lParam ) + win.getLeft();
+                int y = GET_Y_LPARAM( msg.lParam ) + win.getTop();
+                EvtMotion evt( getIntf(), x, y );
+                win.processEvent( evt );
+                break;
+            }
+            case WM_MOUSELEAVE:
+            {
+                EvtLeave evt( getIntf() );
+                win.processEvent( evt );
+                break;
+            }
+            case WM_MOUSEWHEEL:
+            {
+                int x = GET_X_LPARAM( msg.lParam ) - win.getLeft();
+                int y = GET_Y_LPARAM( msg.lParam ) - win.getTop();
+                int mod = getMod( msg.wParam );
+                if( GET_WHEEL_DELTA_WPARAM( msg.wParam ) > 0 )
+                {
+                    EvtScroll evt( getIntf(), x, y, EvtScroll::kUp, mod );
+                    win.processEvent( evt );
+                }
+                else
+                {
+                    EvtScroll evt( getIntf(), x, y, EvtScroll::kDown, mod );
+                    win.processEvent( evt );
+                }
+                break;
+            }
+            case WM_LBUTTONDOWN:
+            {
+                SetCapture( msg.hwnd );
+                EvtMouse evt( getIntf(), GET_X_LPARAM( msg.lParam ),
+                              GET_Y_LPARAM( msg.lParam ), EvtMouse::kLeft,
+                              EvtMouse::kDown, getMod( msg.wParam ) );
+                win.processEvent( evt );
+                break;
+            }
+            case WM_RBUTTONDOWN:
+            {
+                SetCapture( msg.hwnd );
+                EvtMouse evt( getIntf(), GET_X_LPARAM( msg.lParam ),
+                              GET_Y_LPARAM( msg.lParam ), EvtMouse::kRight,
+                              EvtMouse::kDown, getMod( msg.wParam ) );
+                win.processEvent( evt );
+                break;
+            }
+            case WM_LBUTTONUP:
+            {
+                ReleaseCapture();
+                EvtMouse evt( getIntf(), GET_X_LPARAM( msg.lParam ),
+                              GET_Y_LPARAM( msg.lParam ), EvtMouse::kLeft,
+                              EvtMouse::kUp, getMod( msg.wParam ) );
+                win.processEvent( evt );
+                break;
+            }
+            case WM_RBUTTONUP:
+            {
+                ReleaseCapture();
+                EvtMouse evt( getIntf(), GET_X_LPARAM( msg.lParam ),
+                              GET_Y_LPARAM( msg.lParam ), EvtMouse::kRight,
+                              EvtMouse::kUp, getMod( msg.wParam ) );
+                win.processEvent( evt );
+                break;
+            }
+            case WM_LBUTTONDBLCLK:
+            {
+                ReleaseCapture();
+                EvtMouse evt( getIntf(), GET_X_LPARAM( msg.lParam ),
+                              GET_Y_LPARAM( msg.lParam ), EvtMouse::kLeft,
+                              EvtMouse::kDblClick, getMod( msg.wParam ) );
+                win.processEvent( evt );
+                break;
+            }
+            case WM_RBUTTONDBLCLK:
+            {
+                ReleaseCapture();
+                EvtMouse evt( getIntf(), GET_X_LPARAM( msg.lParam ),
+                              GET_Y_LPARAM( msg.lParam ), EvtMouse::kRight,
+                              EvtMouse::kDblClick, getMod( msg.wParam ) );
+                win.processEvent( evt );
+                break;
+            }
+            case WM_KEYDOWN:
+            case WM_SYSKEYDOWN:
+            case WM_KEYUP:
+            case WM_SYSKEYUP:
+            {
+                // The key events are first processed here and not translated
+                // into WM_CHAR events because we need to know the status of
+                // the modifier keys.
+
+                // Get VLC key code from the virtual key code
+                int key = virtKeyToVlcKey[msg.wParam];
+                if( !key )
+                {
+                    // This appears to be a "normal" (ascii) key
+                    key = tolower( MapVirtualKey( msg.wParam, 2 ) );
+                }
+
+                if( key )
+                {
+                    // Get the modifier
+                    int mod = 0;
+                    if( GetKeyState( VK_CONTROL ) & 0x8000 )
+                    {
+                        mod |= EvtInput::kModCtrl;
+                    }
+                    if( GetKeyState( VK_SHIFT ) & 0x8000 )
+                    {
+                        mod |= EvtInput::kModShift;
+                    }
+                    if( GetKeyState( VK_MENU ) & 0x8000 )
+                    {
+                        mod |= EvtInput::kModAlt;
+                    }
+
+                    // Get the state
+                    EvtKey::ActionType_t state;
+                    if( msg.message == WM_KEYDOWN ||
+                        msg.message == WM_SYSKEYDOWN )
+                    {
+                        state = EvtKey::kDown;
+                    }
+                    else
+                    {
+                        state = EvtKey::kUp;
+                    }
+
+                    EvtKey evt( getIntf(), key, state, mod );
+                    win.processEvent( evt );
+                }
+                break;
+            }
+            default:
+                TranslateMessage( &msg );
+                DispatchMessage( &msg );
+        }
+    }
+}
+
+
+int Win32Loop::getMod( WPARAM wParam ) const
+{
+    int mod = EvtInput::kModNone;
+    if( wParam & MK_CONTROL )
+        mod |= EvtInput::kModCtrl;
+    if( wParam & MK_SHIFT )
+        mod |= EvtInput::kModShift;
+
+    return mod;
+}
+
+
+void Win32Loop::exit()
+{
+    PostQuitMessage(0);
+}
+
+#endif
diff --git a/modules/gui/skins2/win32/win32_loop.hpp b/modules/gui/skins2/win32/win32_loop.hpp
new file mode 100644 (file)
index 0000000..5ac66fb
--- /dev/null
@@ -0,0 +1,65 @@
+/*****************************************************************************
+ * win32_loop.hpp
+ *****************************************************************************
+ * Copyright (C) 2003 VideoLAN
+ * $Id: win32_loop.hpp,v 1.1 2004/01/03 23:31:34 asmax Exp $
+ *
+ * Authors: Cyril Deguet     <asmax@via.ecp.fr>
+ *          Olivier Teulière <ipkiss@via.ecp.fr>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111, USA.
+ *****************************************************************************/
+
+#ifndef WIN32_LOOP_HPP
+#define WIN32_LOOP_HPP
+
+#include "../events/evt_mouse.hpp"
+#include "../src/os_loop.hpp"
+#include <windows.h>
+#include <map>
+
+
+class GenericWindow;
+
+/// Main event loop for Win32
+class Win32Loop: public OSLoop
+{
+    public:
+        /// Get the instance of Win32Loop
+        static OSLoop *instance( intf_thread_t *pIntf );
+
+        /// Destroy the instance of Win32Loop
+        static void destroy( intf_thread_t *pIntf );
+
+        /// Enter the event loop
+        virtual void run();
+
+        /// Exit the main loop
+        virtual void exit();
+
+    private:
+        // Private because it is a singleton
+        Win32Loop( intf_thread_t *pIntf );
+        virtual ~Win32Loop();
+
+        /// Map associating special (i.e. non ascii) virtual key codes with
+        /// internal vlc key codes
+        map<int, int> virtKeyToVlcKey;
+
+        /// Helper function to find the modifier in a Windows message
+        int getMod( WPARAM wParam ) const;
+};
+
+#endif
diff --git a/modules/gui/skins2/win32/win32_timer.cpp b/modules/gui/skins2/win32/win32_timer.cpp
new file mode 100644 (file)
index 0000000..f3e97a0
--- /dev/null
@@ -0,0 +1,80 @@
+/*****************************************************************************
+ * win32_timer.cpp
+ *****************************************************************************
+ * Copyright (C) 2003 VideoLAN
+ * $Id: win32_timer.cpp,v 1.1 2004/01/03 23:31:34 asmax Exp $
+ *
+ * Authors: Cyril Deguet     <asmax@via.ecp.fr>
+ *          Olivier Teulière <ipkiss@via.ecp.fr>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111, USA.
+ *****************************************************************************/
+
+#ifdef WIN32_SKINS
+
+#include "win32_timer.hpp"
+
+
+void CALLBACK CallbackTimer( HWND hwnd, UINT uMsg,
+                             UINT_PTR idEvent, DWORD dwTime )
+{
+    Win32Timer *pTimer = (Win32Timer*)idEvent;
+    if( pTimer != NULL )
+    {
+        pTimer->execute();
+    }
+}
+
+
+Win32Timer::Win32Timer( intf_thread_t *pIntf, const Callback &rCallback,
+                        HWND hWnd ):
+    OSTimer( pIntf ), m_callback( rCallback ), m_hWnd( hWnd )
+{
+}
+
+
+Win32Timer::~Win32Timer()
+{
+    stop();
+}
+
+
+void Win32Timer::start( int delay, bool oneShot )
+{
+    m_interval = delay;
+    m_oneShot = oneShot;
+    SetTimer( m_hWnd, (UINT_PTR)this, m_interval, (TIMERPROC)CallbackTimer );
+}
+
+
+void Win32Timer::stop()
+{
+    KillTimer( m_hWnd, (UINT_PTR)this );
+}
+
+
+void Win32Timer::execute()
+{
+    // Execute the callback
+    (*(m_callback.getFunc()))( m_callback.getObj() );
+
+    // Restart the timer if needed
+    if( ! m_oneShot )
+    {
+        start( m_interval, m_oneShot );
+    }
+}
+
+#endif
diff --git a/modules/gui/skins2/win32/win32_timer.hpp b/modules/gui/skins2/win32/win32_timer.hpp
new file mode 100644 (file)
index 0000000..45a93d7
--- /dev/null
@@ -0,0 +1,65 @@
+/*****************************************************************************
+ * win32_timer.hpp
+ *****************************************************************************
+ * Copyright (C) 2003 VideoLAN
+ * $Id: win32_timer.hpp,v 1.1 2004/01/03 23:31:34 asmax Exp $
+ *
+ * Authors: Cyril Deguet     <asmax@via.ecp.fr>
+ *          Olivier Teulière <ipkiss@via.ecp.fr>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111, USA.
+ *****************************************************************************/
+
+#ifndef WIN32_TIMER_HPP
+#define WIN32_TIMER_HPP
+
+#include "../src/os_timer.hpp"
+
+
+// Win32 specific timer
+class Win32Timer: public OSTimer
+{
+    public:
+        Win32Timer( intf_thread_t *pIntf, const Callback &rCallback,
+                    HWND hWnd );
+        virtual ~Win32Timer();
+
+        /// (Re)start the timer with the given delay (in ms). If oneShot is
+        /// true, stop it after the first execution of the callback.
+        virtual void start( int delay, bool oneShot );
+
+        /// Stop the timer
+        virtual void stop();
+
+        /// Execute the callback
+        void execute();
+
+    private:
+        /// Callback to execute
+        Callback m_callback;
+
+        /// Delay between two execute
+        mtime_t m_interval;
+
+        /// Flag to tell whether the timer must be stopped after the
+        /// first execution
+        bool m_oneShot;
+
+        /// Handle of the window to which the timer will be attached
+        HWND m_hWnd;
+};
+
+
+#endif
diff --git a/modules/gui/skins2/win32/win32_tooltip.cpp b/modules/gui/skins2/win32/win32_tooltip.cpp
new file mode 100755 (executable)
index 0000000..8e2baec
--- /dev/null
@@ -0,0 +1,80 @@
+/*****************************************************************************
+ * win32_tooltip.cpp
+ *****************************************************************************
+ * Copyright (C) 2003 VideoLAN
+ * $Id: win32_tooltip.cpp,v 1.1 2004/01/03 23:31:34 asmax Exp $
+ *
+ * Authors: Cyril Deguet     <asmax@via.ecp.fr>
+ *          Olivier Teulière <ipkiss@via.ecp.fr>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111, USA.
+ *****************************************************************************/
+
+#ifdef WIN32_SKINS
+
+#include "win32_tooltip.hpp"
+#include "win32_graphics.hpp"
+#include "../src/generic_window.hpp"
+
+Win32Tooltip::Win32Tooltip( intf_thread_t *pIntf, HINSTANCE hInst,
+                            HWND hParentWindow ):
+    OSTooltip( pIntf )
+{
+    // Create the window
+    m_hWnd = CreateWindowEx( WS_EX_TOOLWINDOW,
+        "SkinWindowClass", "default name", WS_POPUP, CW_USEDEFAULT,
+        CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, hParentWindow, 0,
+        hInst, NULL );
+
+    if( !m_hWnd )
+    {
+        msg_Err( getIntf(), "CreateWindow failed" );
+        return;
+    }
+}
+
+
+Win32Tooltip::~Win32Tooltip()
+{
+    if( m_hWnd )
+        DestroyWindow( m_hWnd );
+}
+
+
+void Win32Tooltip::show( int left, int top, OSGraphics &rText )
+{
+    // Source drawable
+    HDC srcDC = ((Win32Graphics&)rText).getDC();
+    int width = rText.getWidth();
+    int height = rText.getHeight();
+
+    // Set the window on top, resize it and show it
+    SetWindowPos( m_hWnd, HWND_TOPMOST, left, top, width, height, 0 );
+    ShowWindow( m_hWnd, SW_SHOW );
+
+    HDC wndDC = GetWindowDC( m_hWnd );
+    BitBlt( wndDC, 0, 0, width, height, srcDC, 0, 0, SRCCOPY );
+    ReleaseDC( m_hWnd, wndDC );
+}
+
+
+void Win32Tooltip::hide()
+{
+    ShowWindow( m_hWnd, SW_HIDE );
+}
+
+
+#endif
+
diff --git a/modules/gui/skins2/win32/win32_tooltip.hpp b/modules/gui/skins2/win32/win32_tooltip.hpp
new file mode 100644 (file)
index 0000000..cebb343
--- /dev/null
@@ -0,0 +1,53 @@
+/*****************************************************************************
+ * win32_tooltip.hpp
+ *****************************************************************************
+ * Copyright (C) 2003 VideoLAN
+ * $Id: win32_tooltip.hpp,v 1.1 2004/01/03 23:31:34 asmax Exp $
+ *
+ * Authors: Cyril Deguet     <asmax@via.ecp.fr>
+ *          Olivier Teulière <ipkiss@via.ecp.fr>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111, USA.
+ *****************************************************************************/
+
+#ifndef WIN32_TOOLTIP_HPP
+#define WIN32_TOOLTIP_HPP
+
+#include "../src/os_tooltip.hpp"
+#include <windows.h>
+
+
+/// Win32 implementation of OSTooltip
+class Win32Tooltip: public OSTooltip
+{
+    public:
+        Win32Tooltip( intf_thread_t *pIntf, HINSTANCE hInst,
+                            HWND hParentWindow );
+
+        virtual ~Win32Tooltip();
+
+        // Show the tooltip
+        virtual void show( int left, int top, OSGraphics &rText );
+
+        // Hide the tooltip
+        virtual void hide();
+
+    private:
+        /// Window ID
+        HWND m_hWnd;
+};
+
+
+#endif
diff --git a/modules/gui/skins2/win32/win32_window.cpp b/modules/gui/skins2/win32/win32_window.cpp
new file mode 100644 (file)
index 0000000..b52c814
--- /dev/null
@@ -0,0 +1,184 @@
+/*****************************************************************************
+ * win32_window.cpp
+ *****************************************************************************
+ * Copyright (C) 2003 VideoLAN
+ * $Id: win32_window.cpp,v 1.1 2004/01/03 23:31:34 asmax Exp $
+ *
+ * Authors: Cyril Deguet     <asmax@via.ecp.fr>
+ *          Olivier Teulière <ipkiss@via.ecp.fr>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111, USA.
+ *****************************************************************************/
+
+#ifdef WIN32_SKINS
+
+#include "../src/generic_window.hpp"
+#include "win32_window.hpp"
+#include "win32_dragdrop.hpp"
+#include "win32_factory.hpp"
+
+
+/// Fading API
+#define LWA_COLORKEY  0x00000001
+#define LWA_ALPHA     0x00000002
+
+
+Win32Window::Win32Window( intf_thread_t *pIntf, GenericWindow &rWindow,
+                          HINSTANCE hInst, HWND hParentWindow,
+                          bool dragDrop, bool playOnDrop ):
+    OSWindow( pIntf ), m_dragDrop( dragDrop ), m_mm( false )
+{
+    // Create the window
+    m_hWnd = CreateWindowEx( WS_EX_TOOLWINDOW,
+        "SkinWindowClass", "default name", WS_POPUP, CW_USEDEFAULT,
+        CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, hParentWindow, 0,
+        hInst, NULL );
+
+    if( !m_hWnd )
+    {
+        msg_Err( getIntf(), "CreateWindow failed" );
+        return;
+    }
+
+    // We do it this way otherwise CreateWindowEx will fail if WS_EX_LAYERED
+    // is not supported
+//    SetWindowLongPtr( m_hWnd, GWL_EXSTYLE,
+//                      GetWindowLong( m_hWnd, GWL_EXSTYLE ) | WS_EX_LAYERED );
+
+    // Store a pointer to the GenericWindow in a map
+    Win32Factory *pFactory = (Win32Factory*)Win32Factory::instance( getIntf() );
+    pFactory->m_windowMap[m_hWnd] = &rWindow;
+
+    // Drag & drop
+    if( m_dragDrop )
+    {
+        m_pDropTarget = (LPDROPTARGET) new Win32DragDrop( getIntf(),
+                                                          playOnDrop );
+        // Register the window as a drop target
+        RegisterDragDrop( m_hWnd, m_pDropTarget );
+    }
+}
+
+
+Win32Window::~Win32Window()
+{
+    Win32Factory *pFactory = (Win32Factory*)Win32Factory::instance( getIntf() );
+    pFactory->m_windowMap[m_hWnd] = NULL;
+
+    if( m_hWnd )
+    {
+        if( m_dragDrop )
+        {
+            // Remove the window from the list of drop targets
+            RevokeDragDrop( m_hWnd );
+            m_pDropTarget->Release();
+        }
+
+        DestroyWindow( m_hWnd );
+    }
+}
+
+
+void Win32Window::show( int left, int top )
+{
+    ShowWindow( m_hWnd, SW_SHOW );
+}
+
+
+void Win32Window::hide()
+{
+    ShowWindow( m_hWnd, SW_HIDE );
+}
+
+
+void Win32Window::moveResize( int left, int top, int width, int height )
+{
+    MoveWindow( m_hWnd, left, top, width, height, true );
+}
+
+
+void Win32Window::raise()
+{
+    SetWindowPos( m_hWnd, HWND_TOP, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE );
+}
+
+
+void Win32Window::setOpacity( uint8_t value )
+{
+    Win32Factory *pFactory = (Win32Factory*)Win32Factory::instance( getIntf() );
+#if 0
+    if( value == 255 )
+    {
+        // If the window is opaque, we remove the WS_EX_LAYERED attribute
+        // which slows resizing for nothing
+        if( m_mm )
+        {
+            SetWindowLongPtr( m_hWnd, GWL_EXSTYLE,
+                GetWindowLong( m_hWnd, GWL_EXSTYLE ) & !WS_EX_LAYERED );
+            SetWindowPos( m_hWnd, HWND_TOP, 0, 0, 0, 0,
+                SWP_NOMOVE | SWP_NOSIZE | SWP_NOZORDER | SWP_FRAMECHANGED );
+            m_mm = false;
+        }
+//    GenericWindow *pWin = pFactory->m_windowMap[m_hWnd];
+//    pWin->refresh( pWin->getLeft(), pWin->getTop(), pWin->getWidth(), pWin->getHeight() );
+
+    }
+    else
+#endif
+    {
+        if( pFactory->SetLayeredWindowAttributes )
+        {
+#if 0
+            // (Re)Add the WS_EX_LAYERED attribute.
+            // Resizing will be very slow, now :)
+            if( !m_mm )
+            {
+                SetWindowLongPtr( m_hWnd, GWL_EXSTYLE,
+                    GetWindowLong( m_hWnd, GWL_EXSTYLE ) | WS_EX_LAYERED );
+                SetWindowPos( m_hWnd, HWND_TOP, 0, 0, 0, 0,
+                    SWP_NOMOVE | SWP_NOSIZE | SWP_NOZORDER | SWP_FRAMECHANGED );
+                m_mm = true;
+            }
+//    GenericWindow *pWin = pFactory->m_windowMap[m_hWnd];
+//    pWin->refresh( pWin->getLeft(), pWin->getTop(), pWin->getWidth(), pWin->getHeight() );
+#endif
+            // Change the opacity
+            pFactory->SetLayeredWindowAttributes(
+                m_hWnd, 0, value, LWA_ALPHA|LWA_COLORKEY );
+        }
+    }
+
+//    UpdateWindow( m_hWnd );
+}
+
+
+void Win32Window::toggleOnTop( bool onTop )
+{
+    if( onTop )
+    {
+        // Set the window on top
+        SetWindowPos( m_hWnd, HWND_TOPMOST, 0, 0, 0, 0,
+                      SWP_NOSIZE | SWP_NOMOVE );
+    }
+    else
+    {
+        // Set the window not on top
+        SetWindowPos( m_hWnd, HWND_NOTOPMOST, 0, 0, 0, 0,
+                      SWP_NOSIZE | SWP_NOMOVE );
+    }
+}
+
+
+#endif
diff --git a/modules/gui/skins2/win32/win32_window.hpp b/modules/gui/skins2/win32/win32_window.hpp
new file mode 100644 (file)
index 0000000..70ed77e
--- /dev/null
@@ -0,0 +1,74 @@
+/*****************************************************************************
+ * win32_window.hpp
+ *****************************************************************************
+ * Copyright (C) 2003 VideoLAN
+ * $Id: win32_window.hpp,v 1.1 2004/01/03 23:31:34 asmax Exp $
+ *
+ * Authors: Cyril Deguet     <asmax@via.ecp.fr>
+ *          Olivier Teulière <ipkiss@via.ecp.fr>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111, USA.
+ *****************************************************************************/
+
+#ifndef WIN32_WINDOW_HPP
+#define WIN32_WINDOW_HPP
+
+#include "../src/os_window.hpp"
+#include <windows.h>
+#include <ole2.h>   // LPDROPTARGET
+
+
+/// Win32 implementation of OSWindow
+class Win32Window: public OSWindow
+{
+    public:
+        Win32Window( intf_thread_t *pIntf, GenericWindow &rWindow,
+                     HINSTANCE hInst, HWND hParentWindow,
+                     bool dragDrop, bool playOnDrop );
+        virtual ~Win32Window();
+
+        // Show the window
+        virtual void show( int left, int top );
+
+        // Hide the window
+        virtual void hide();
+
+        /// Move and resize the window
+        virtual void moveResize( int left, int top, int width, int height );
+
+        /// Bring the window on top
+        virtual void raise();
+
+        /// Set the opacity of the window (0 = transparent, 255 = opaque)
+        virtual void setOpacity( uint8_t value );
+
+        /// Toggle the window on top
+        virtual void toggleOnTop( bool onTop );
+
+        /// Getter for the window handle
+        HWND getHandle() const { return m_hWnd; }
+
+    private:
+        /// Window handle
+        HWND m_hWnd;
+        /// Indicates whether the window handles drag&drop events
+        bool m_dragDrop;
+        /// Drop target
+        LPDROPTARGET m_pDropTarget;
+        bool m_mm;
+};
+
+
+#endif
diff --git a/modules/gui/skins2/x11/x11_display.cpp b/modules/gui/skins2/x11/x11_display.cpp
new file mode 100644 (file)
index 0000000..e1eac7e
--- /dev/null
@@ -0,0 +1,283 @@
+/*****************************************************************************
+ * x11_display.cpp
+ *****************************************************************************
+ * Copyright (C) 2003 VideoLAN
+ * $Id: x11_display.cpp,v 1.1 2004/01/03 23:31:34 asmax Exp $
+ *
+ * Authors: Cyril Deguet     <asmax@via.ecp.fr>
+ *          Olivier Teulière <ipkiss@via.ecp.fr>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111, USA.
+ *****************************************************************************/
+
+#ifdef X11_SKINS
+
+#include <X11/Xutil.h>
+#include <X11/extensions/shape.h>
+
+#include "x11_display.hpp"
+#include "../src/logger.hpp"
+
+
+X11Display::X11Display( intf_thread_t *pIntf ): SkinObject( pIntf ),
+    m_gc( NULL )
+{
+    // Open a connection to the X Server
+    m_pDisplay = XOpenDisplay( NULL );
+    if( m_pDisplay == NULL )
+    {
+        MSG_ERR( "Cannot open display" );
+        return;
+    }
+
+    // Load the XShape extension
+    int event, error;
+    XShapeQueryExtension( m_pDisplay, &event, &error );
+
+    // Get the display parameters
+    int screen = DefaultScreen( m_pDisplay );
+    int depth = DefaultDepth( m_pDisplay, screen );
+    int order = ImageByteOrder( m_pDisplay );
+
+    // Create a graphics context that doesn't generate GraphicsExpose events
+    XGCValues xgcvalues;
+    xgcvalues.graphics_exposures = False;
+    m_gc = XCreateGC( m_pDisplay, DefaultRootWindow( m_pDisplay ),
+                      GCGraphicsExposures, &xgcvalues );
+
+    // Template for looking up the XVisualInfo
+    XVisualInfo xVInfoTemplate;
+    xVInfoTemplate.screen = screen;
+    xVInfoTemplate.depth = depth;
+
+    XVisualInfo *pVInfo = NULL;
+    int vCount = 0;
+
+    switch( depth )
+    {
+        case 16:
+        case 24:
+        case 32:
+            // Get the TrueColor visual
+            xVInfoTemplate.c_class = TrueColor;
+            pVInfo = XGetVisualInfo( m_pDisplay, VisualScreenMask |
+                                     VisualDepthMask | VisualClassMask,
+                                     &xVInfoTemplate, &vCount );
+            if( pVInfo == NULL )
+            {
+                msg_Err( getIntf(), "No TrueColor visual for depth %d",
+                         depth );
+                m_pDisplay = NULL;
+                break;
+            }
+            m_pVisual = pVInfo->visual;
+
+            // Compute the color shifts
+            getShifts( pVInfo->red_mask, m_redLeftShift, m_redRightShift );
+            getShifts( pVInfo->green_mask, m_greenLeftShift,
+                       m_greenRightShift );
+            getShifts( pVInfo->blue_mask, m_blueLeftShift, m_blueRightShift );
+
+            if( depth == 16 )
+            {
+                if( order == MSBFirst )
+                {
+                    makePixelImpl = &X11Display::makePixel16MSB;
+                }
+                else
+                {
+                    makePixelImpl = &X11Display::makePixel16LSB;
+                }
+                m_pixelSize = 2;
+            }
+            else
+            {
+                if( order == MSBFirst )
+                {
+                    makePixelImpl = &X11Display::makePixel32MSB;
+                }
+                else
+                {
+                    makePixelImpl = &X11Display::makePixel32LSB;
+                }
+                m_pixelSize = 4;
+            }
+            break;
+
+        default:
+            msg_Err( getIntf(), "Unsupported depth: %d bpp\n", depth );
+            m_pDisplay = NULL;
+            break;
+    }
+
+    // Free the visual info
+    if( pVInfo )
+    {
+        XFree( pVInfo );
+    }
+}
+
+
+X11Display::~X11Display()
+{
+    if( m_gc )
+    {
+        XFreeGC( m_pDisplay, m_gc );
+    }
+    if( m_pDisplay )
+    {
+        XCloseDisplay( m_pDisplay );
+    }
+}
+
+
+void X11Display::getShifts( uint32_t mask, int &rLeftShift,
+                            int &rRightShift ) const
+{
+    for( rLeftShift = 0; (rLeftShift < 32) && !(mask & 1); rLeftShift++ )
+    {
+        mask >>= 1;
+    }
+    for( rRightShift = 8; (mask & 1) ; rRightShift--)
+    {
+        mask >>= 1;
+    }
+    if( rRightShift < 0 )
+    {
+        rLeftShift -= rRightShift;
+        rRightShift = 0;
+    }
+}
+
+
+void X11Display::makePixel16MSB( uint8_t *pPixel, uint8_t r, uint8_t g,
+                                 uint8_t b, uint8_t a ) const
+{
+    // Get the current pixel value
+    uint16_t value = pPixel[1] | pPixel[0] << 8;
+
+    // Compute the new color values
+    uint16_t temp;
+    temp = ((uint8_t)((value >> m_redLeftShift) << m_redRightShift));
+    uint8_t red = ( temp * (255 - a) + r * a ) / 255;
+    temp = ((uint8_t)((value >> m_greenLeftShift) << m_greenRightShift));
+    uint8_t green = ( temp * (255 - a) + g * a ) / 255;
+    temp = ((uint8_t)((value >> m_blueLeftShift) << m_blueRightShift));
+    uint8_t blue = ( temp * (255 - a) + b * a ) / 255;
+
+    // Set the new pixel value
+    value =
+        ( ((uint16_t)red >> m_redRightShift) << m_redLeftShift ) |
+        ( ((uint16_t)green >> m_greenRightShift) << m_greenLeftShift ) |
+        ( ((uint16_t)blue >> m_blueRightShift) << m_blueLeftShift );
+
+    pPixel[1] = value;
+    value >>= 8;
+    pPixel[0] = value;
+}
+
+
+void X11Display::makePixel16LSB( uint8_t *pPixel, uint8_t r, uint8_t g,
+                                 uint8_t b, uint8_t a ) const
+{
+    // Get the current pixel value
+    uint16_t value = pPixel[0] | pPixel[1] << 8;
+
+    // Compute the new color values
+    uint16_t temp;
+    temp = ((uint8_t)((value >> m_redLeftShift) << m_redRightShift));
+    uint8_t red = ( temp * (255 - a) + r * a ) / 255;
+    temp = ((uint8_t)((value >> m_greenLeftShift) << m_greenRightShift));
+    uint8_t green = ( temp * (255 - a) + g * a ) / 255;
+    temp = ((uint8_t)((value >> m_blueLeftShift) << m_blueRightShift));
+    uint8_t blue = ( temp * (255 - a) + b * a ) / 255;
+
+    // Set the new pixel value
+    value =
+        ( ((uint16_t)red >> m_redRightShift) << m_redLeftShift ) |
+        ( ((uint16_t)green >> m_greenRightShift) << m_greenLeftShift ) |
+        ( ((uint16_t)blue >> m_blueRightShift) << m_blueLeftShift );
+
+    pPixel[0] = value;
+    value >>= 8;
+    pPixel[1] = value;
+}
+
+
+void X11Display::makePixel32MSB( uint8_t *pPixel, uint8_t r, uint8_t g,
+                                 uint8_t b, uint8_t a ) const
+{
+    // Get the current pixel value
+    uint32_t value = pPixel[3] | pPixel[2] << 8 | pPixel[1] << 16 |
+                          pPixel[0] << 24;
+
+    // Compute the new color values
+    uint16_t temp;
+    temp = ((uint8_t)((value >> m_redLeftShift) << m_redRightShift));
+    uint8_t red = ( temp * (255 - a) + r * a ) / 255;
+    temp = ((uint8_t)((value >> m_greenLeftShift) << m_greenRightShift));
+    uint8_t green = ( temp * (255 - a) + g * a ) / 255;
+    temp = ((uint8_t)((value >> m_blueLeftShift) << m_blueRightShift));
+    uint8_t blue = ( temp * (255 - a) + b * a ) / 255;
+
+    // Set the new pixel value
+    value =
+        ( ((uint32_t)red >> m_redRightShift) << m_redLeftShift ) |
+        ( ((uint32_t)green >> m_greenRightShift) << m_greenLeftShift ) |
+        ( ((uint32_t)blue >> m_blueRightShift) << m_blueLeftShift );
+
+    pPixel[3] = value;
+    value >>= 8;
+    pPixel[2] = value;
+    value >>= 8;
+    pPixel[1] = value;
+    value >>= 8;
+    pPixel[0] = value;
+}
+
+
+void X11Display::makePixel32LSB( uint8_t *pPixel, uint8_t r, uint8_t g,
+                                 uint8_t b, uint8_t a ) const
+{
+    // Get the current pixel value
+    uint32_t value = pPixel[0] | pPixel[1] << 8 | pPixel[2] << 16 |
+                          pPixel[3] << 24;
+
+    // Compute the new color values
+    uint16_t temp;
+    temp = ((uint8_t)((value >> m_redLeftShift) << m_redRightShift));
+    uint8_t red = ( temp * (255 - a) + r * a ) / 255;
+    temp = ((uint8_t)((value >> m_greenLeftShift) << m_greenRightShift));
+    uint8_t green = ( temp * (255 - a) + g * a ) / 255;
+    temp = ((uint8_t)((value >> m_blueLeftShift) << m_blueRightShift));
+    uint8_t blue = ( temp * (255 - a) + b * a ) / 255;
+
+    // Set the new pixel value
+    value =
+        ( ((uint32_t)red >> m_redRightShift) << m_redLeftShift ) |
+        ( ((uint32_t)green >> m_greenRightShift) << m_greenLeftShift ) |
+        ( ((uint32_t)blue >> m_blueRightShift) << m_blueLeftShift );
+
+    pPixel[0] = value;
+    value >>= 8;
+    pPixel[1] = value;
+    value >>= 8;
+    pPixel[2] = value;
+    value >>= 8;
+    pPixel[3] = value;
+}
+
+
+#endif
diff --git a/modules/gui/skins2/x11/x11_display.hpp b/modules/gui/skins2/x11/x11_display.hpp
new file mode 100644 (file)
index 0000000..270b931
--- /dev/null
@@ -0,0 +1,100 @@
+/*****************************************************************************
+ * x11_display.hpp
+ *****************************************************************************
+ * Copyright (C) 2003 VideoLAN
+ * $Id: x11_display.hpp,v 1.1 2004/01/03 23:31:34 asmax Exp $
+ *
+ * Authors: Cyril Deguet     <asmax@via.ecp.fr>
+ *          Olivier Teulière <ipkiss@via.ecp.fr>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111, USA.
+ *****************************************************************************/
+
+#ifndef X11_DISPLAY_HPP
+#define X11_DISPLAY_HPP
+
+#include <X11/Xlib.h>
+
+#include "../src/skin_common.hpp"
+
+// Helper macros
+#define XDISPLAY m_rDisplay.getDisplay()
+#define XVISUAL m_rDisplay.getVisual()
+#define XPIXELSIZE m_rDisplay.getPixelSize()
+#define XGC m_rDisplay.getGC()
+
+
+/// Class for encapsulation of a X11 Display
+class X11Display: public SkinObject
+{
+    public:
+        X11Display( intf_thread_t *pIntf );
+        virtual ~X11Display();
+
+        /// Get the display
+        Display *getDisplay() const { return m_pDisplay; }
+
+        /// Get the visual
+        Visual *getVisual() const { return m_pVisual; }
+
+        /// Get the pixel size
+        int getPixelSize() const { return m_pixelSize; }
+
+        /// Get the graphics context
+        GC getGC() const { return m_gc; }
+
+        /// Type of function to convert RGB values into a pixel
+        typedef void (X11Display::*MakePixelFunc_t)( uint8_t *pPixel,
+            uint8_t r, uint8_t g, uint8_t b, uint8_t a ) const;
+
+        /// Get a pointer on the right makePixel implementation
+        MakePixelFunc_t getMakePixel() const { return makePixelImpl; }
+
+    private:
+        /// Display parameters
+        Display *m_pDisplay;
+        Visual *m_pVisual;
+        int m_pixelSize;
+        GC m_gc;
+        int m_redLeftShift, m_redRightShift;
+        int m_greenLeftShift, m_greenRightShift;
+        int m_blueLeftShift, m_blueRightShift;
+
+
+        /// Pointer on the right implementation of getPixel
+        MakePixelFunc_t makePixelImpl;
+
+        /// Calculate shifts from a color mask
+        void getShifts( uint32_t mask, int &rLeftShift,
+                        int &rRightShift ) const;
+
+        /// 16 bpp MSB first version of makePixel
+        void makePixel16MSB( uint8_t *pPixel, uint8_t r, uint8_t g, uint8_t b,
+                             uint8_t a ) const;
+
+        /// 16 bpp LSB first version of makePixel
+        void makePixel16LSB( uint8_t *pPixel, uint8_t r, uint8_t g, uint8_t b,
+                             uint8_t a ) const;
+
+        /// 24/32 bpp MSB first version of makePixel
+        void makePixel32MSB( uint8_t *pPixel, uint8_t r, uint8_t g, uint8_t b,
+                             uint8_t a ) const;
+
+        /// 24/32 bpp LSB first version of makePixel
+        void makePixel32LSB( uint8_t *pPixel, uint8_t r, uint8_t g, uint8_t b,
+                             uint8_t a ) const;
+};
+
+#endif
diff --git a/modules/gui/skins2/x11/x11_dragdrop.cpp b/modules/gui/skins2/x11/x11_dragdrop.cpp
new file mode 100755 (executable)
index 0000000..24113d7
--- /dev/null
@@ -0,0 +1,218 @@
+/*****************************************************************************
+ * x11_dragdrop.cpp
+ *****************************************************************************
+ * Copyright (C) 2003 VideoLAN
+ * $Id: x11_dragdrop.cpp,v 1.1 2004/01/03 23:31:34 asmax Exp $
+ *
+ * Authors: Cyril Deguet     <asmax@via.ecp.fr>
+ *          Olivier Teulière <ipkiss@via.ecp.fr>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111, USA.
+ *****************************************************************************/
+
+#ifdef X11_SKINS
+
+#include <X11/Xlib.h>
+#include <X11/Xatom.h>
+
+#include "x11_dragdrop.hpp"
+#include "x11_display.hpp"
+#include "x11_factory.hpp"
+#include "../commands/cmd_add_item.hpp"
+
+#include <string>
+#include <list>
+
+
+X11DragDrop::X11DragDrop( intf_thread_t *pIntf, X11Display &rDisplay,
+                          Window win, bool playOnDrop ):
+    SkinObject( pIntf ), m_rDisplay( rDisplay ), m_wnd( win ),
+    m_playOnDrop( playOnDrop )
+{
+}
+
+
+void X11DragDrop::dndEnter( ldata_t data )
+{
+    Window src = data[0];
+
+    // Retrieve available data types
+    list<string> dataTypes;
+    if( data[1] & 1 )   // More than 3 data types ?
+    {
+        Atom type;
+        int format;
+        unsigned long nitems, nbytes;
+        Atom *dataList;
+        Atom typeListAtom = XInternAtom( XDISPLAY, "XdndTypeList", 0 );
+        XGetWindowProperty( XDISPLAY, src, typeListAtom, 0, 65536, False,
+                            XA_ATOM, &type, &format, &nitems, &nbytes,
+                            (unsigned char**)&dataList );
+        for( unsigned long i=0; i<nitems; i++ )
+        {
+            string dataType = XGetAtomName( XDISPLAY, dataList[i] );
+            dataTypes.push_back( dataType );
+        }
+        XFree( (void*)dataList );
+    }
+    else
+    {
+        for( int i = 2; i < 5; i++ )
+        {
+            if( data[i] != None )
+            {
+                string dataType = XGetAtomName( XDISPLAY, data[i] );
+                dataTypes.push_back( dataType );
+            }
+        }
+    }
+
+    // Find the right target
+    m_target = None;
+    list<string>::iterator it;
+    for( it = dataTypes.begin(); it != dataTypes.end(); it++ )
+    {
+        if( *it == "text/plain" || *it == "STRING" )
+        {
+            m_target = XInternAtom( XDISPLAY, (*it).c_str(), 0 );
+            break;
+        }
+    }
+}
+
+
+void X11DragDrop::dndPosition( ldata_t data )
+{
+    Window src = data[0];
+    Time time = data[2];
+
+    Atom selectionAtom = XInternAtom( XDISPLAY, "XdndSelection", 0 );
+    Atom targetAtom = XInternAtom( XDISPLAY, "text/plain", 0 );
+    Atom propAtom = XInternAtom( XDISPLAY, "VLC_SELECTION", 0 );
+
+    Atom actionAtom = XInternAtom( XDISPLAY, "XdndActionCopy", 0 );
+    Atom typeAtom = XInternAtom( XDISPLAY, "XdndFinished", 0 );
+
+    // Convert the selection into the given target
+    // NEEDED or it doesn't work!
+    XConvertSelection( XDISPLAY, selectionAtom, targetAtom, propAtom, src,
+                       time );
+
+    actionAtom = XInternAtom( XDISPLAY, "XdndActionCopy", 0 );
+    typeAtom = XInternAtom( XDISPLAY, "XdndStatus", 0 );
+
+    XEvent event;
+    event.type = ClientMessage;
+    event.xclient.window = src;
+    event.xclient.display = XDISPLAY;
+    event.xclient.message_type = typeAtom;
+    event.xclient.format = 32;
+    event.xclient.data.l[0] = m_wnd;
+    if( m_target != None )
+    {
+        // Accept the drop
+        event.xclient.data.l[1] = 1;
+    }
+    else
+    {
+        // Do not accept the drop
+        event.xclient.data.l[1] = 0;
+    }
+    int w = X11Factory::instance( getIntf() )->getScreenWidth();
+    int h = X11Factory::instance( getIntf() )->getScreenHeight();
+    event.xclient.data.l[2] = 0;
+    event.xclient.data.l[3] = (w << 16) | h;
+    event.xclient.data.l[4] = actionAtom;
+
+    // Tell the source whether we accept the drop
+    XSendEvent( XDISPLAY, src, False, 0, &event );
+}
+
+
+void X11DragDrop::dndLeave( ldata_t data )
+{
+}
+
+
+void X11DragDrop::dndDrop( ldata_t data )
+{
+    Window src = data[0];
+    Time time = data[2];
+
+    Atom selectionAtom = XInternAtom( XDISPLAY, "XdndSelection", 0 );
+    Atom targetAtom = XInternAtom( XDISPLAY, "text/plain", 0 );
+    Atom propAtom = XInternAtom( XDISPLAY, "VLC_SELECTION", 0 );
+
+    Atom actionAtom = XInternAtom( XDISPLAY, "XdndActionCopy", 0 );
+    Atom typeAtom = XInternAtom( XDISPLAY, "XdndFinished", 0 );
+
+    // Convert the selection into the given target
+    XConvertSelection( XDISPLAY, selectionAtom, targetAtom, propAtom, src,
+                       time );
+
+    // Read the selection
+    Atom type;
+    int format;
+    unsigned long nitems, nbytes;
+    char *buffer;
+    XGetWindowProperty( XDISPLAY, src, propAtom, 0, 1024, False,
+                        AnyPropertyType, &type, &format, &nitems, &nbytes,
+                        (unsigned char**)&buffer );
+    string selection = "";
+    if( buffer != NULL )
+    {
+        selection = buffer;
+    }
+    XFree( buffer );
+
+    if( selection != "" )
+    {
+        // TODO: multiple files handling
+        string::size_type end = selection.find( "\n", 0 );
+        selection = selection.substr( 0, end - 1 );
+        end = selection.find( "\r", 0 );
+        selection = selection.substr( 0, end - 1 );
+
+        // Find the protocol, if any
+        string::size_type pos = selection.find( ":", 0 );
+        if( selection.find( "///", pos + 1 ) == pos + 1 )
+        {
+            selection.erase( pos + 1, 2 );
+        }
+
+        char *psz_fileName = new char[selection.size() + 1];
+        strncpy( psz_fileName, selection.c_str(), selection.size() + 1 );
+
+        // Add the file
+        CmdAddItem cmd( getIntf(), psz_fileName, m_playOnDrop );
+        cmd.execute();
+
+        delete[] psz_fileName;
+    }
+
+    // Tell the source we accepted the drop
+    XEvent event;
+    event.type = ClientMessage;
+    event.xclient.window = src;
+    event.xclient.display = XDISPLAY;
+    event.xclient.message_type = typeAtom;
+    event.xclient.format = 32;
+    event.xclient.data.l[0] = m_wnd;
+    event.xclient.data.l[1] = 1;            // drop accepted
+    event.xclient.data.l[2] = actionAtom;
+    XSendEvent( XDISPLAY, src, False, 0, &event );
+}
+
+#endif
diff --git a/modules/gui/skins2/x11/x11_dragdrop.hpp b/modules/gui/skins2/x11/x11_dragdrop.hpp
new file mode 100755 (executable)
index 0000000..ae7ad8a
--- /dev/null
@@ -0,0 +1,60 @@
+/*****************************************************************************
+ * x11_dragdrop.hpp
+ *****************************************************************************
+ * Copyright (C) 2003 VideoLAN
+ * $Id: x11_dragdrop.hpp,v 1.1 2004/01/03 23:31:34 asmax Exp $
+ *
+ * Authors: Cyril Deguet     <asmax@via.ecp.fr>
+ *          Olivier Teulière <ipkiss@via.ecp.fr>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111, USA.
+ *****************************************************************************/
+
+#ifndef X11_DRAGDROP_HPP
+#define X11_DRAGDROP_HPP
+
+#include <X11/Xlib.h>
+#include "../src/skin_common.hpp"
+
+class X11Display;
+
+
+class X11DragDrop: public SkinObject
+{
+    public:
+        typedef long ldata_t[5];
+
+        X11DragDrop( intf_thread_t *pIntf, X11Display &rDisplay, Window win,
+                     bool playOnDrop );
+        virtual ~X11DragDrop() {}
+
+        void dndEnter( ldata_t data );
+        void dndPosition( ldata_t data );
+        void dndLeave( ldata_t data );
+        void dndDrop( ldata_t data );
+
+    private:
+        /// X11 display
+        X11Display &m_rDisplay;
+        /// Window ID
+        Window m_wnd;
+        /// Indicates whether the file(s) must be played immediately
+        bool m_playOnDrop;
+        /// Target type
+        Atom m_target;
+};
+
+
+#endif
diff --git a/modules/gui/skins2/x11/x11_factory.cpp b/modules/gui/skins2/x11/x11_factory.cpp
new file mode 100644 (file)
index 0000000..3c65028
--- /dev/null
@@ -0,0 +1,195 @@
+/*****************************************************************************
+ * x11_factory.cpp
+ *****************************************************************************
+ * Copyright (C) 2003 VideoLAN
+ * $Id: x11_factory.cpp,v 1.1 2004/01/03 23:31:34 asmax Exp $
+ *
+ * Authors: Cyril Deguet     <asmax@via.ecp.fr>
+ *          Olivier Teulière <ipkiss@via.ecp.fr>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111, USA.
+ *****************************************************************************/
+
+#ifdef X11_SKINS
+
+#include <unistd.h>
+#include <dirent.h>
+#include <sys/stat.h>
+#include <X11/Xlib.h>
+
+#include "x11_factory.hpp"
+#include "x11_display.hpp"
+#include "x11_graphics.hpp"
+#include "x11_loop.hpp"
+#include "x11_timer.hpp"
+#include "x11_window.hpp"
+#include "x11_tooltip.hpp"
+
+
+X11Factory::X11Factory( intf_thread_t *pIntf ): OSFactory( pIntf )
+{
+    // see init()
+}
+
+
+X11Factory::~X11Factory()
+{
+    delete m_pTimerLoop;
+    delete m_pDisplay;
+}
+
+
+bool X11Factory::init()
+{
+    // Create the X11 display
+    m_pDisplay = new X11Display( getIntf() );
+
+    // Get the display
+    Display *pDisplay = m_pDisplay->getDisplay();
+    if( pDisplay == NULL )
+    {
+        // Initialization failed
+        return false;
+    }
+
+    // Create the timer loop
+    m_pTimerLoop = new X11TimerLoop( getIntf(),
+                                     ConnectionNumber( pDisplay ) );
+
+    return true;
+}
+
+
+OSGraphics *X11Factory::createOSGraphics( int width, int height )
+{
+    return new X11Graphics( getIntf(), *m_pDisplay, width, height );
+}
+
+
+OSLoop *X11Factory::getOSLoop()
+{
+    return X11Loop::instance( getIntf(), *m_pDisplay );
+}
+
+
+void X11Factory::destroyOSLoop()
+{
+    X11Loop::destroy( getIntf() );
+}
+
+
+OSTimer *X11Factory::createOSTimer( const Callback &rCallback )
+{
+    return new X11Timer( getIntf(), rCallback );
+}
+
+
+OSWindow *X11Factory::createOSWindow( GenericWindow &rWindow, bool dragDrop,
+                                      bool playOnDrop )
+{
+    return new X11Window( getIntf(), rWindow, *m_pDisplay, dragDrop,
+                          playOnDrop );
+}
+
+
+OSTooltip *X11Factory::createOSTooltip()
+{
+    return new X11Tooltip( getIntf(), *m_pDisplay );
+}
+
+
+const string X11Factory::getDirSeparator() const
+{
+    return "/";
+}
+
+
+int X11Factory::getScreenWidth() const
+{
+    Display *pDisplay = m_pDisplay->getDisplay();
+    int screen = DefaultScreen( pDisplay );
+    return DisplayWidth( pDisplay, screen );
+}
+
+
+int X11Factory::getScreenHeight() const
+{
+    Display *pDisplay = m_pDisplay->getDisplay();
+    int screen = DefaultScreen( pDisplay );
+    return DisplayHeight( pDisplay, screen );
+}
+
+
+Rect X11Factory::getWorkArea() const
+{
+    // XXX
+    return Rect( 0, 0, getScreenWidth(), getScreenHeight() );
+}
+
+
+void X11Factory::getMousePos( int &rXPos, int &rYPos ) const
+{
+    Window rootReturn, childReturn;
+    int winx, winy;
+    unsigned int xmask;
+
+    Display *pDisplay = m_pDisplay->getDisplay();
+    Window root = DefaultRootWindow( pDisplay );
+    XQueryPointer( pDisplay, root, &rootReturn, &childReturn,
+                   &rXPos, &rYPos, &winx, &winy, &xmask );
+}
+
+
+void X11Factory::rmDir( const string &rPath )
+{
+    struct dirent *file;
+    DIR *dir;
+
+    dir = opendir( rPath.c_str() );
+    if( !dir ) return;
+
+    // Parse the directory and remove everything it contains
+    while( (file = readdir( dir )) )
+    {
+        struct stat statbuf;
+        string filename = file->d_name;
+
+        // Skip "." and ".."
+        if( filename == "." || filename == ".." )
+        {
+            continue;
+        }
+
+        filename = rPath + "/" + filename;
+
+        if( !stat( filename.c_str(), &statbuf ) && statbuf.st_mode & S_IFDIR )
+        {
+            rmDir( filename );
+        }
+        else
+        {
+            unlink( filename.c_str() );
+        }
+    }
+
+    // Close the directory
+    closedir( dir );
+
+    // And delete it
+    rmdir( rPath.c_str() );
+}
+
+
+#endif
diff --git a/modules/gui/skins2/x11/x11_factory.hpp b/modules/gui/skins2/x11/x11_factory.hpp
new file mode 100644 (file)
index 0000000..61e801d
--- /dev/null
@@ -0,0 +1,95 @@
+/*****************************************************************************
+ * x11_factory.hpp
+ *****************************************************************************
+ * Copyright (C) 2003 VideoLAN
+ * $Id: x11_factory.hpp,v 1.1 2004/01/03 23:31:34 asmax Exp $
+ *
+ * Authors: Cyril Deguet     <asmax@via.ecp.fr>
+ *          Olivier Teulière <ipkiss@via.ecp.fr>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111, USA.
+ *****************************************************************************/
+
+#ifndef X11_FACTORY_HPP
+#define X11_FACTORY_HPP
+
+#include <X11/Xlib.h>
+
+#include "../src/os_factory.hpp"
+#include <map>
+
+class X11Display;
+class X11TimerLoop;
+
+
+/// Class used to instanciate X11 specific objects
+class X11Factory: public OSFactory
+{
+    public:
+        X11Factory( intf_thread_t *pIntf );
+        virtual ~X11Factory();
+
+        /// Initialization method
+        virtual bool init();
+
+        /// Instantiate an object OSGraphics.
+        virtual OSGraphics *createOSGraphics( int width, int height );
+
+        /// Get the instance of the singleton OSLoop.
+        virtual OSLoop *getOSLoop();
+
+        /// Destroy the instance of OSLoop.
+        virtual void destroyOSLoop();
+
+        /// Instantiate an OSTimer with the given callback
+        virtual OSTimer *createOSTimer( const Callback &rCallback );
+
+        /// Instantiate an OSWindow object
+        virtual OSWindow *createOSWindow( GenericWindow &rWindow,
+                                          bool dragDrop, bool playOnDrop );
+
+        /// Instantiate an object OSTooltip.
+        virtual OSTooltip *createOSTooltip();
+
+        /// Get the directory separator
+        virtual const string getDirSeparator() const;
+
+        /// Get the screen size
+        virtual int getScreenWidth() const;
+        virtual int getScreenHeight() const;
+
+        /// Get the work area (screen area without taskbars)
+        virtual Rect getWorkArea() const;
+
+        /// Get the position of the mouse
+        virtual void getMousePos( int &rXPos, int &rYPos ) const;
+
+        /// Delete a directory recursively
+        virtual void rmDir( const string &rPath );
+
+        /// Get the timer loop
+        X11TimerLoop *getTimerLoop() const { return m_pTimerLoop; }
+
+        /// Map to find the GenericWindow associated with a X11Window
+        map<Window, GenericWindow*> m_windowMap;
+
+    private:
+        /// X11 display
+        X11Display *m_pDisplay;
+        /// Timer loop
+        X11TimerLoop *m_pTimerLoop;
+};
+
+#endif
diff --git a/modules/gui/skins2/x11/x11_graphics.cpp b/modules/gui/skins2/x11/x11_graphics.cpp
new file mode 100644 (file)
index 0000000..102ccd5
--- /dev/null
@@ -0,0 +1,368 @@
+/*****************************************************************************
+ * x11_graphics.cpp
+ *****************************************************************************
+ * Copyright (C) 2003 VideoLAN
+ * $Id: x11_graphics.cpp,v 1.1 2004/01/03 23:31:34 asmax Exp $
+ *
+ * Authors: Cyril Deguet     <asmax@via.ecp.fr>
+ *          Olivier Teulière <ipkiss@via.ecp.fr>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111, USA.
+ *****************************************************************************/
+
+#ifdef X11_SKINS
+
+#include <stdlib.h>
+#include <X11/extensions/shape.h>
+
+#include "x11_display.hpp"
+#include "x11_graphics.hpp"
+#include "x11_window.hpp"
+#include "../src/generic_bitmap.hpp"
+
+
+X11Graphics::X11Graphics( intf_thread_t *pIntf, X11Display &rDisplay,
+                          int width, int height ):
+    OSGraphics( pIntf ), m_rDisplay( rDisplay ), m_width( width ),
+    m_height( height )
+{
+    // Get the display paramaters
+    int screen = DefaultScreen( XDISPLAY );
+    int depth = DefaultDepth( XDISPLAY, screen );
+
+    // Create a pixmap
+    m_pixmap = XCreatePixmap( XDISPLAY, DefaultRootWindow( XDISPLAY ),
+                              width, height, depth);
+
+    // Create the transparency mask (everything is transparent initially)
+    m_mask = XCreateRegion();
+
+    // Create a Graphics Context that does not generate GraphicsExpose events
+    XGCValues xgcvalues;
+    xgcvalues.graphics_exposures = False;
+    m_gc = XCreateGC( XDISPLAY, m_pixmap, GCGraphicsExposures, &xgcvalues );
+
+}
+
+
+X11Graphics::~X11Graphics()
+{
+    XFreeGC( XDISPLAY, m_gc );
+    XDestroyRegion( m_mask );
+    XFreePixmap( XDISPLAY, m_pixmap );
+}
+
+
+void X11Graphics::clear()
+{
+    // Clear the transparency mask
+    XDestroyRegion( m_mask );
+    m_mask = XCreateRegion();
+}
+
+
+void X11Graphics::drawGraphics( const OSGraphics &rGraphics, int xSrc,
+                                int ySrc, int xDest, int yDest, int width,
+                                int height )
+{
+    if( width == -1 )
+    {
+        width = rGraphics.getWidth();
+    }
+    if( height == -1 )
+    {
+        height = rGraphics.getHeight();
+    }
+
+    // Source drawable
+    Drawable src = ((X11Graphics&)rGraphics).getDrawable();
+
+    // Create the mask for transparency
+    Region voidMask = XCreateRegion();
+    XRectangle rect;
+    rect.x = xSrc;
+    rect.y = ySrc;
+    rect.width = width;
+    rect.height = height;
+    Region clipMask = XCreateRegion();
+    XUnionRectWithRegion( &rect, voidMask, clipMask );
+    Region mask = XCreateRegion();
+    XIntersectRegion( ((X11Graphics&)rGraphics).getMask(), clipMask, mask );
+    XDestroyRegion( clipMask );
+    XDestroyRegion( voidMask );
+    XOffsetRegion( mask, xDest - xSrc, yDest - ySrc );
+
+    // Copy the pixmap
+    XSetRegion( XDISPLAY, m_gc, mask );
+    XCopyArea( XDISPLAY, src, m_pixmap, m_gc, xSrc, ySrc, width, height,
+               xDest, yDest );
+
+    // Add the source mask to the mask of the graphics
+    Region newMask = XCreateRegion();
+    XUnionRegion( m_mask, mask, newMask );
+    XDestroyRegion( mask );
+    XDestroyRegion( m_mask );
+    m_mask = newMask;
+}
+
+
+void X11Graphics::drawBitmap( const GenericBitmap &rBitmap, int xSrc,
+                              int ySrc, int xDest, int yDest, int width,
+                              int height )
+{
+    // Get the bitmap size if necessary
+    if( width == -1 )
+    {
+        width = rBitmap.getWidth();
+    }
+    else if( width > rBitmap.getWidth() )
+    {
+        msg_Dbg( getIntf(), "Bitmap width too small!" );
+        width = rBitmap.getWidth();
+    }
+    if( height == -1 )
+    {
+        height = rBitmap.getHeight();
+    }
+    else if( height > rBitmap.getHeight() )
+    {
+        msg_Dbg( getIntf(), "Bitmap height too small!" );
+        height = rBitmap.getHeight();
+    }
+
+    // Nothing to draw if width or height is null
+    if( width == 0 || height == 0 )
+    {
+        return;
+    }
+
+    // Safety check for debugging purpose
+    if( xDest + width > m_width || yDest + height > m_height )
+    {
+        msg_Dbg( getIntf(), "Bitmap too large !" );
+        return;
+    }
+
+    // Get a buffer on the image data
+    uint8_t *pBmpData = rBitmap.getData();
+    if( pBmpData == NULL )
+    {
+        // Nothing to draw
+        return;
+    }
+
+    // Get the image from the pixmap
+    XImage *pImage = XGetImage( XDISPLAY, m_pixmap, xDest, yDest, width,
+                                height, AllPlanes, ZPixmap );
+    if( pImage == NULL )
+    {
+        msg_Dbg( getIntf(), "XGetImage returned NULL" );
+        return;
+    }
+    char *pData = pImage->data;
+
+    // Get the padding of this image
+    int pad = pImage->bitmap_pad >> 3;
+    int shift = ( pad - ( (width * XPIXELSIZE) % pad ) ) % pad;
+
+    // Mask for transparency
+    Region mask = XCreateRegion();
+
+    // Get a pointer on the right X11Display::makePixel method
+    X11Display::MakePixelFunc_t makePixelFunc = m_rDisplay.getMakePixel();
+
+    // Skip the first lines of the image
+    pBmpData += 4 * ySrc * rBitmap.getWidth();
+
+    // Copy the bitmap on the image and compute the mask
+    for( int y = 0; y < height; y++ )
+    {
+        // Skip uninteresting bytes at the beginning of the line
+        pBmpData += 4 * xSrc;
+        // Flag to say whether the previous pixel on the line was visible
+        bool wasVisible = false;
+        // Beginning of the current visible segment on the line
+        int visibleSegmentStart = 0;
+        for( int x = 0; x < width; x++ )
+        {
+            uint8_t b = *(pBmpData++);
+            uint8_t g = *(pBmpData++);
+            uint8_t r = *(pBmpData++);
+            uint8_t a = *(pBmpData++);
+            // Draw the pixel
+            (m_rDisplay.*makePixelFunc)( (uint8_t*)pData, r, g, b, a );
+            pData += XPIXELSIZE;
+            if( a > 0 )
+            {
+                // Pixel is visible
+                if( ! wasVisible )
+                {
+                    // Beginning of a visible segment
+                    visibleSegmentStart = x;
+                }
+                wasVisible = true;
+            }
+            else
+            {
+                // Pixel is transparent
+                if( wasVisible )
+                {
+                    // End of a visible segment: add it to the mask
+                    addHSegmentInRegion( mask, visibleSegmentStart, x, y );
+                }
+                wasVisible = false;
+            }
+        }
+        if( wasVisible )
+        {
+            // End of a visible segment: add it to the mask
+            addHSegmentInRegion( mask, visibleSegmentStart, width, y );
+        }
+        pData += shift;
+        // Skip uninteresting bytes at the end of the line
+        pBmpData += 4 * (rBitmap.getWidth() - width - xSrc);
+    }
+
+    // Apply the mask to the graphics context
+    XOffsetRegion( mask, xDest, yDest );
+    XSetRegion( XDISPLAY, m_gc, mask );
+    // Copy the image on the pixmap
+    XPutImage( XDISPLAY, m_pixmap, m_gc, pImage, 0, 0, xDest, yDest, width,
+               height);
+    XDestroyImage( pImage );
+
+    // Add the bitmap mask to the global graphics mask
+    Region newMask = XCreateRegion();
+    XUnionRegion( mask, m_mask, newMask );
+    XDestroyRegion( m_mask );
+    m_mask = newMask;
+
+    XDestroyRegion( mask );
+}
+
+
+void X11Graphics::fillRect( int left, int top, int width, int height,
+                            uint32_t color )
+{
+    // Update the mask with the rectangle area
+    Region newMask = XCreateRegion();
+    XRectangle rect;
+    rect.x = left;
+    rect.y = top;
+    rect.width = width;
+    rect.height = height;
+    XUnionRectWithRegion( &rect, m_mask, newMask );
+    XDestroyRegion( m_mask );
+    m_mask = newMask;
+
+    XColor xcolor;
+    xcolor.red = (color & 0xff0000) >> 8;
+    xcolor.green = color & 0xff00;
+    xcolor.blue = (color & 0xff) << 8;
+
+    // Draw the rectangle
+    Colormap cm = DefaultColormap( XDISPLAY, DefaultScreen( XDISPLAY ) );
+    XAllocColor( XDISPLAY, cm, &xcolor );
+    XGCValues gcVal;
+    gcVal.foreground = xcolor.pixel;
+    XChangeGC( XDISPLAY, m_gc, GCForeground,  &gcVal );
+    XSetRegion( XDISPLAY, m_gc, m_mask );
+    XFillRectangle( XDISPLAY, m_pixmap, m_gc, left, top, width, height );
+}
+
+
+void X11Graphics::drawRect( int left, int top, int width, int height,
+                            uint32_t color )
+{
+    // Update the mask with the rectangle
+    addHSegmentInRegion( m_mask, left, left + width, top );
+    addHSegmentInRegion( m_mask, left, left + width, top + height );
+    addVSegmentInRegion( m_mask, top, top + height, left );
+    addVSegmentInRegion( m_mask, top, top + height, left + width );
+
+    XColor xcolor;
+    xcolor.red = (color & 0xff0000) >> 8;
+    xcolor.green = color & 0xff00;
+    xcolor.blue = (color & 0xff) << 8;
+
+    // Draw the rectangle
+    Colormap cm = DefaultColormap( XDISPLAY, DefaultScreen( XDISPLAY ) );
+    XAllocColor( XDISPLAY, cm, &xcolor );
+    XGCValues gcVal;
+    gcVal.foreground = xcolor.pixel;
+    XChangeGC( XDISPLAY, m_gc, GCForeground,  &gcVal );
+    XSetRegion( XDISPLAY, m_gc, m_mask );
+    XDrawRectangle( XDISPLAY, m_pixmap, m_gc, left, top, width - 1, height - 1 );
+}
+
+
+void X11Graphics::applyMaskToWindow( OSWindow &rWindow )
+{
+    // Get the target window
+    Window win = ((X11Window&)rWindow).getDrawable();
+
+    // Change the shape of the window
+    XShapeCombineRegion( XDISPLAY, win, ShapeBounding, 0, 0, m_mask,
+                         ShapeSet );
+}
+
+
+void X11Graphics::copyToWindow( OSWindow &rWindow, int xSrc,  int ySrc,
+                                int width, int height, int xDest, int yDest )
+{
+    // Destination window
+    Drawable dest = ((X11Window&)rWindow).getDrawable();
+
+    XCopyArea( XDISPLAY, m_pixmap, dest, XGC, xSrc, ySrc, width, height,
+               xDest, yDest );
+}
+
+
+bool X11Graphics::hit( int x, int y ) const
+{
+    return XPointInRegion( m_mask, x, y );
+}
+
+
+inline void X11Graphics::addHSegmentInRegion( Region &rMask, int xStart,
+                                              int xEnd, int y )
+{
+    XRectangle rect;
+    rect.x = xStart;
+    rect.y = y;
+    rect.width = xEnd - xStart;
+    rect.height = 1;
+    Region newMask = XCreateRegion();
+    XUnionRectWithRegion( &rect, rMask, newMask );
+    XDestroyRegion( rMask );
+    rMask = newMask;
+}
+
+
+inline void X11Graphics::addVSegmentInRegion( Region &rMask, int yStart,
+                                              int yEnd, int x )
+{
+    XRectangle rect;
+    rect.x = x;
+    rect.y = yStart;
+    rect.width = 1;
+    rect.height = yEnd - yStart;
+    Region newMask = XCreateRegion();
+    XUnionRectWithRegion( &rect, rMask, newMask );
+    XDestroyRegion( rMask );
+    rMask = newMask;
+}
+
+#endif
diff --git a/modules/gui/skins2/x11/x11_graphics.hpp b/modules/gui/skins2/x11/x11_graphics.hpp
new file mode 100644 (file)
index 0000000..4bcfe0a
--- /dev/null
@@ -0,0 +1,108 @@
+/*****************************************************************************
+ * x11_graphics.hpp
+ *****************************************************************************
+ * Copyright (C) 2003 VideoLAN
+ * $Id: x11_graphics.hpp,v 1.1 2004/01/03 23:31:34 asmax Exp $
+ *
+ * Authors: Cyril Deguet     <asmax@via.ecp.fr>
+ *          Olivier Teulière <ipkiss@via.ecp.fr>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111, USA.
+ *****************************************************************************/
+
+#ifndef X11_GRAPHICS_HPP
+#define X11_GRAPHICS_HPP
+
+#include <X11/Xlib.h>
+#include <X11/Xutil.h>
+
+#include "../src/os_graphics.hpp"
+
+class X11Display;
+class GenericWindow;
+class GenericBitmap;
+
+/// X11 implementation of OSGraphics
+class X11Graphics: public OSGraphics
+{
+    public:
+        X11Graphics( intf_thread_t *pIntf, X11Display &rDisplay, int width,
+                     int height);
+
+        virtual ~X11Graphics();
+
+        /// Clear the graphics
+        virtual void clear();
+
+        /// Draw another graphics on this one
+        virtual void drawGraphics( const OSGraphics &rGraphics, int xSrc = 0,
+                                   int ySrc = 0, int xDest = 0, int yDest = 0,
+                                   int width = -1, int height = -1 );
+
+        /// Render a bitmap on this graphics
+        virtual void drawBitmap( const GenericBitmap &rBitmap, int xSrc = 0,
+                                 int ySrc = 0, int xDest = 0, int yDest = 0,
+                                 int width = -1, int height = -1 );
+
+        /// Draw a filled rectangle on the grahics (color is #RRGGBB)
+        virtual void fillRect( int left, int top, int width, int height,
+                               uint32_t color );
+
+        /// Draw an empty rectangle on the grahics (color is #RRGGBB)
+        virtual void drawRect( int left, int top, int width, int height,
+                               uint32_t color );
+
+        /// Set the shape of a window with the mask of this graphics.
+        virtual void applyMaskToWindow( OSWindow &rWindow );
+
+        /// Copy the graphics on a window
+        virtual void copyToWindow( OSWindow &rWindow, int xSrc,
+                                   int ySrc, int width, int height,
+                                   int xDest, int yDest );
+
+        /// Tell whether the pixel at the given position is visible
+        virtual bool hit( int x, int y ) const;
+
+        /// Getters
+        virtual int getWidth() const { return m_width; }
+        virtual int getHeight() const { return m_height; }
+
+        /// Get the pixmap ID
+        Pixmap getDrawable() const { return m_pixmap; }
+        /// Get the transparency mask
+        Region getMask() const { return m_mask; }
+
+    private:
+        /// X11 display
+        X11Display &m_rDisplay;
+        /// Size of the image
+        int m_width, m_height;
+        /// Pixmap
+        Pixmap m_pixmap;
+        /// Transparency mask
+        Region m_mask;
+        /// Graphics context
+        GC m_gc;
+
+        /// Add an horizontal segment in a region
+        void X11Graphics::addHSegmentInRegion( Region &rMask, int xStart,
+                                               int xEnd, int y );
+        /// Add a vertical segment in a region
+        void X11Graphics::addVSegmentInRegion( Region &rMask, int yStart,
+                                               int yEnd, int x );
+};
+
+
+#endif
diff --git a/modules/gui/skins2/x11/x11_loop.cpp b/modules/gui/skins2/x11/x11_loop.cpp
new file mode 100644 (file)
index 0000000..b38f7ae
--- /dev/null
@@ -0,0 +1,408 @@
+/*****************************************************************************
+ * x11_loop.cpp
+ *****************************************************************************
+ * Copyright (C) 2003 VideoLAN
+ * $Id: x11_loop.cpp,v 1.1 2004/01/03 23:31:34 asmax Exp $
+ *
+ * Authors: Cyril Deguet     <asmax@via.ecp.fr>
+ *          Olivier Teulière <ipkiss@via.ecp.fr>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111, USA.
+ *****************************************************************************/
+
+#ifdef X11_SKINS
+
+#include <X11/keysym.h>
+#include "x11_loop.hpp"
+#include "x11_display.hpp"
+#include "x11_dragdrop.hpp"
+#include "x11_factory.hpp"
+#include "x11_timer.hpp"
+#include "../src/generic_window.hpp"
+#include "../events/evt_focus.hpp"
+#include "../events/evt_key.hpp"
+#include "../events/evt_mouse.hpp"
+#include "../events/evt_motion.hpp"
+#include "../events/evt_leave.hpp"
+#include "../events/evt_refresh.hpp"
+#include "../events/evt_scroll.hpp"
+#include "../commands/async_queue.hpp"
+#include "vlc_keys.h"
+
+
+// Maximum interval between clicks for a double-click (in microsec)
+int X11Loop::m_dblClickDelay = 400000;
+
+
+X11Loop::X11Loop( intf_thread_t *pIntf, X11Display &rDisplay ):
+    OSLoop( pIntf ), m_rDisplay( rDisplay ), m_exit( false ),
+    m_lastClickTime( 0 ), m_lastClickPosX( 0 ), m_lastClickPosY( 0 )
+{
+    // Initialize the key map
+    keysymToVlcKey[XK_F1] = KEY_F1;
+    keysymToVlcKey[XK_F2] = KEY_F2;
+    keysymToVlcKey[XK_F3] = KEY_F3;
+    keysymToVlcKey[XK_F4] = KEY_F4;
+    keysymToVlcKey[XK_F5] = KEY_F5;
+    keysymToVlcKey[XK_F6] = KEY_F6;
+    keysymToVlcKey[XK_F7] = KEY_F7;
+    keysymToVlcKey[XK_F8] = KEY_F8;
+    keysymToVlcKey[XK_F9] = KEY_F9;
+    keysymToVlcKey[XK_F10] = KEY_F10;
+    keysymToVlcKey[XK_F11] = KEY_F11;
+    keysymToVlcKey[XK_F12] = KEY_F12;
+    keysymToVlcKey[XK_Return] = KEY_ENTER;
+    keysymToVlcKey[XK_space] = KEY_SPACE;
+    keysymToVlcKey[XK_Escape] = KEY_ESC;
+    keysymToVlcKey[XK_Left] = KEY_LEFT;
+    keysymToVlcKey[XK_Right] = KEY_RIGHT;
+    keysymToVlcKey[XK_Up] = KEY_UP;
+    keysymToVlcKey[XK_Down] = KEY_DOWN;
+    keysymToVlcKey[XK_Home] = KEY_HOME;
+    keysymToVlcKey[XK_End] = KEY_END;
+    keysymToVlcKey[XK_Prior] = KEY_PAGEUP;
+    keysymToVlcKey[XK_Next] = KEY_PAGEDOWN;
+}
+
+
+X11Loop::~X11Loop()
+{
+}
+
+
+OSLoop *X11Loop::instance( intf_thread_t *pIntf, X11Display &rDisplay )
+{
+    if( pIntf->p_sys->p_osLoop == NULL )
+    {
+        OSLoop *pOsLoop = new X11Loop( pIntf, rDisplay );
+        pIntf->p_sys->p_osLoop = pOsLoop;
+    }
+    return pIntf->p_sys->p_osLoop;
+}
+
+
+void X11Loop::destroy( intf_thread_t *pIntf )
+{
+    if( pIntf->p_sys->p_osLoop )
+    {
+        delete pIntf->p_sys->p_osLoop;
+        pIntf->p_sys->p_osLoop = NULL;
+    }
+}
+
+
+void X11Loop::run()
+{
+    OSFactory *pOsFactory = OSFactory::instance( getIntf() );
+    X11TimerLoop *pTimerLoop = ((X11Factory*)pOsFactory)->getTimerLoop();
+
+    // Main event loop
+    while( ! m_exit )
+    {
+        int nPending;
+
+        // Number of pending events in the queue
+        nPending = XPending( XDISPLAY );
+
+        while( ! m_exit && nPending > 0 )
+        {
+            // Handle the next X11 event
+            handleX11Event();
+
+            // Number of pending events in the queue
+            nPending = XPending( XDISPLAY );
+        }
+
+        // Wait for the next timer and execute it
+        // The sleep is interrupted if an X11 event is received
+        pTimerLoop->waitNextTimer();
+    }
+}
+
+
+void X11Loop::exit()
+{
+    m_exit = true;
+}
+
+
+void X11Loop::flush()
+{
+    XFlush( XDISPLAY );
+}
+
+
+void X11Loop::handleX11Event()
+{
+    XEvent event;
+    OSFactory *pOsFactory = OSFactory::instance( getIntf() );
+
+    // Look for the next event in the queue
+    XNextEvent( XDISPLAY, &event );
+
+    // Find the window to which the event is sent
+    X11Factory *pFactory = (X11Factory*)X11Factory::instance( getIntf() );
+    GenericWindow *pWin = pFactory->m_windowMap[event.xany.window];
+
+    if( !pWin )
+    {
+        msg_Dbg( getIntf(), "No associated generic window !!" );
+        return;
+    }
+
+    // Send the right event object to the window
+    switch( event.type )
+    {
+        case Expose:
+        {
+            EvtRefresh evt( getIntf(), event.xexpose.x,
+                            event.xexpose.y, event.xexpose.width,
+                            event.xexpose.height );
+            pWin->processEvent( evt );
+            break;
+        }
+        case FocusIn:
+        {
+            EvtFocus evt( getIntf(), true );
+            pWin->processEvent( evt );
+            break;
+        }
+        case FocusOut:
+        {
+            EvtFocus evt( getIntf(), false );
+            pWin->processEvent( evt );
+            break;
+        }
+
+        case MotionNotify:
+        {
+            // Don't trust the position in the event, it is
+            // out of date. Get the actual current position instead
+            int x, y;
+            pOsFactory->getMousePos( x, y );
+            EvtMotion evt( getIntf(), x, y );
+            pWin->processEvent( evt );
+            break;
+        }
+        case LeaveNotify:
+        {
+            EvtLeave evt( getIntf() );
+            pWin->processEvent( evt );
+            break;
+        }
+        case ButtonPress:
+        case ButtonRelease:
+        {
+            EvtMouse::ActionType_t action = EvtMouse::kDown;
+            switch( event.type )
+            {
+                case ButtonPress:
+                    action = EvtMouse::kDown;
+                    break;
+                case ButtonRelease:
+                    action = EvtMouse::kUp;
+                    break;
+            }
+
+            // Get the modifiers
+            int mod = EvtInput::kModNone;
+            if( event.xbutton.state & Mod1Mask )
+            {
+                mod |= EvtInput::kModAlt;
+            }
+            if( event.xbutton.state & ControlMask )
+            {
+                mod |= EvtInput::kModCtrl;
+            }
+            if( event.xbutton.state & ShiftMask )
+            {
+                mod |= EvtInput::kModShift;
+            }
+
+            // Check for double clicks
+            if( event.type == ButtonPress &&
+                event.xbutton.button == 1 )
+            {
+                mtime_t time = mdate();
+                int x, y;
+                pOsFactory->getMousePos( x, y );
+                if( time - m_lastClickTime < m_dblClickDelay &&
+                    x == m_lastClickPosX && y == m_lastClickPosY )
+                {
+                    m_lastClickTime = 0;
+                    action = EvtMouse::kDblClick;
+                }
+                else
+                {
+                    m_lastClickTime = time;
+                    m_lastClickPosX = x;
+                    m_lastClickPosY = y;
+                }
+            }
+
+            switch( event.xbutton.button )
+            {
+                case 1:
+                {
+                    EvtMouse evt( getIntf(), event.xbutton.x,
+                                  event.xbutton.y, EvtMouse::kLeft,
+                                  action, mod );
+                    pWin->processEvent( evt );
+                    break;
+                }
+                case 2:
+                {
+                    EvtMouse evt( getIntf(), event.xbutton.x,
+                                  event.xbutton.y, EvtMouse::kMiddle,
+                                  action, mod );
+                    pWin->processEvent( evt );
+                    break;
+                }
+                case 3:
+                {
+                    EvtMouse evt( getIntf(), event.xbutton.x,
+                                  event.xbutton.y, EvtMouse::kRight,
+                                  action, mod );
+                    pWin->processEvent( evt );
+                    break;
+                }
+                case 4:
+                {
+                    // Scroll up
+                    EvtScroll evt( getIntf(), event.xbutton.x,
+                                   event.xbutton.y, EvtScroll::kUp,
+                                   mod );
+                    pWin->processEvent( evt );
+                    break;
+                }
+                case 5:
+                {
+                    // Scroll down
+                    EvtScroll evt( getIntf(), event.xbutton.x,
+                                   event.xbutton.y, EvtScroll::kDown,
+                                   mod );
+                    pWin->processEvent( evt );
+                    break;
+                }
+            }
+            break;
+        }
+        case KeyPress:
+        case KeyRelease:
+        {
+            EvtKey::ActionType_t action = EvtKey::kDown;
+            int mod = EvtInput::kModNone;
+            // Get the modifiers
+            if( event.xkey.state & Mod1Mask )
+            {
+                mod |= EvtInput::kModAlt;
+            }
+            if( event.xkey.state & ControlMask )
+            {
+                mod |= EvtInput::kModCtrl;
+            }
+            if( event.xkey.state & ShiftMask )
+            {
+                mod |= EvtInput::kModShift;
+            }
+
+            // Take the first keysym = lower case character
+            KeySym keysym = XLookupKeysym( &event.xkey, 0 );
+
+            // Get VLC key code from the keysym
+            int key = keysymToVlcKey[keysym];
+            if( !key )
+            {
+                // Normal key
+                key = keysym;
+            }
+
+            switch( event.type )
+            {
+                case KeyPress:
+                    action = EvtKey::kDown;
+                    break;
+                case KeyRelease:
+                    action = EvtKey::kUp;
+                    break;
+            }
+            EvtKey evt( getIntf(), key, action, mod );
+            pWin->processEvent( evt );
+            break;
+        }
+
+        case ClientMessage:
+        {
+            // Get the message type
+            string type = XGetAtomName( XDISPLAY, event.xclient.message_type );
+
+            // Find the D&D object for this window
+            X11DragDrop *pDnd = (X11DragDrop*)
+                    retrievePointer( event.xany.window, "DND_OBJECT" );
+            if( !pDnd )
+            {
+                msg_Err( getIntf(), "No associated D&D object !!" );
+                return;
+            }
+
+            if( type == "XdndEnter" )
+            {
+                pDnd->dndEnter( event.xclient.data.l );
+            }
+            else if( type == "XdndPosition" )
+            {
+                pDnd->dndPosition( event.xclient.data.l );
+            }
+            else if( type == "XdndLeave" )
+            {
+                pDnd->dndLeave( event.xclient.data.l );
+            }
+            else if( type == "XdndDrop" )
+            {
+                pDnd->dndDrop( event.xclient.data.l );
+            }
+            break;
+        }
+
+        default:
+            // XXX
+            fprintf(stderr, "unknown event: %d\n", event.type );
+            break;
+    }
+}
+
+
+void *X11Loop::retrievePointer( Window wnd, const char *pName )
+{
+    Atom typeRet;
+    int fmtRet;
+    unsigned long nRet, bRet;
+    unsigned char *propRet;
+    void *ptr;
+
+    // Retrieve the pointer on the generic window, which was
+    // stored as a window property
+    Atom prop = XInternAtom( XDISPLAY, pName, False );
+    Atom type = XInternAtom( XDISPLAY, "POINTER", False );
+    XGetWindowProperty( XDISPLAY, wnd, prop, 0,
+                        ((sizeof(void*)+3)/4), False, type,
+                        &typeRet, &fmtRet, &nRet, &bRet, &propRet );
+    memcpy( &ptr, propRet, sizeof(void*));
+    XFree( propRet );
+
+    return ptr;
+}
+
+#endif
diff --git a/modules/gui/skins2/x11/x11_loop.hpp b/modules/gui/skins2/x11/x11_loop.hpp
new file mode 100644 (file)
index 0000000..c2ab812
--- /dev/null
@@ -0,0 +1,81 @@
+/*****************************************************************************
+ * x11_loop.hpp
+ *****************************************************************************
+ * Copyright (C) 2003 VideoLAN
+ * $Id: x11_loop.hpp,v 1.1 2004/01/03 23:31:34 asmax Exp $
+ *
+ * Authors: Cyril Deguet     <asmax@via.ecp.fr>
+ *          Olivier Teulière <ipkiss@via.ecp.fr>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111, USA.
+ *****************************************************************************/
+
+#ifndef X11_LOOP_HPP
+#define X11_LOOP_HPP
+
+#include <X11/Xlib.h>
+#include "../src/os_loop.hpp"
+
+#include <map>
+
+class X11Display;
+class GenericWindow;
+
+/// Main event loop for X11 (singleton)
+class X11Loop: public OSLoop
+{
+    public:
+        /// Get the instance of X11Loop
+        static OSLoop *instance( intf_thread_t *pIntf, X11Display &rDisplay );
+
+        /// Destroy the instance of X11Loop
+        static void destroy( intf_thread_t *pIntf );
+
+        /// Enter the event loop
+        virtual void run();
+
+        /// Exit the main loop
+        virtual void exit();
+
+        /// Flush the event queue
+        virtual void flush();
+
+    private:
+        /// X11 Display
+        X11Display &m_rDisplay;
+        /// Flag set on exit
+        bool m_exit;
+        /// Date and position of the last left-click
+        mtime_t m_lastClickTime;
+        int m_lastClickPosX, m_lastClickPosY;
+        /// Maximum interval between clicks for a double-click (in microsec)
+        static int m_dblClickDelay;
+        /// Map associating special (i.e. non ascii) virtual key codes with
+        /// internal vlc key codes
+        map<KeySym, int> keysymToVlcKey;
+
+
+        // Private because it's a singleton
+        X11Loop( intf_thread_t *pIntf, X11Display &rDisplay );
+        virtual ~X11Loop();
+
+        /// Handle the next X11 event
+        void handleX11Event();
+
+        /// Retrieve a pointer stored in the window as a property
+        void *retrievePointer( Window wnd, const char *pName );
+};
+
+#endif
diff --git a/modules/gui/skins2/x11/x11_timer.cpp b/modules/gui/skins2/x11/x11_timer.cpp
new file mode 100644 (file)
index 0000000..ce5904c
--- /dev/null
@@ -0,0 +1,165 @@
+/*****************************************************************************
+ * x11_timer.cpp
+ *****************************************************************************
+ * Copyright (C) 2003 VideoLAN
+ * $Id: x11_timer.cpp,v 1.1 2004/01/03 23:31:34 asmax Exp $
+ *
+ * Authors: Cyril Deguet     <asmax@via.ecp.fr>
+ *          Olivier Teulière <ipkiss@via.ecp.fr>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111, USA.
+ *****************************************************************************/
+
+#ifdef X11_SKINS
+
+#include <unistd.h>
+#include <fcntl.h>
+
+#include "x11_timer.hpp"
+#include "x11_factory.hpp"
+
+
+X11Timer::X11Timer( intf_thread_t *pIntf, const Callback &rCallback ):
+    OSTimer( pIntf ), m_callback( rCallback )
+{
+    // Get the instance of timer loop
+    X11Factory *m_pOsFactory = (X11Factory*)(OSFactory::instance( pIntf ) );
+    m_pTimerLoop = m_pOsFactory->getTimerLoop();
+}
+
+
+X11Timer::~X11Timer()
+{
+    stop();
+}
+
+
+void X11Timer::start( int delay, bool oneShot )
+{
+    m_interval = 1000 * delay;
+    m_oneShot = oneShot;
+    m_nextDate = mdate() + m_interval;
+    m_pTimerLoop->addTimer( *this );
+}
+
+
+void X11Timer::stop()
+{
+    m_pTimerLoop->removeTimer( *this );
+}
+
+
+mtime_t X11Timer::getNextDate() const
+{
+    return m_nextDate;
+}
+
+
+bool X11Timer::execute()
+{
+    m_nextDate += m_interval;
+    // Execute the callback
+    (*(m_callback.getFunc()))( m_callback.getObj() );
+
+    return !m_oneShot;
+}
+
+
+X11TimerLoop::X11TimerLoop( intf_thread_t *pIntf, int connectionNumber ):
+    SkinObject( pIntf ), m_connectionNumber( connectionNumber )
+{
+}
+
+
+X11TimerLoop::~X11TimerLoop()
+{
+}
+
+
+void X11TimerLoop::addTimer( X11Timer &rTimer )
+{
+    m_timers.push_back( &rTimer );
+}
+
+
+void X11TimerLoop::removeTimer( X11Timer &rTimer )
+{
+    m_timers.remove( &rTimer );
+}
+
+
+void X11TimerLoop::waitNextTimer()
+{
+    mtime_t curDate = mdate();
+    mtime_t nextDate = LAST_MDATE;
+
+    X11Timer *nextTimer = NULL;
+
+    // Find the next timer to execute
+    list<X11Timer*>::const_iterator timer;
+    for( timer = m_timers.begin(); timer != m_timers.end(); timer++ )
+    {
+        mtime_t timerDate = (*timer)->getNextDate();
+        if( timerDate < nextDate )
+        {
+            nextTimer = *timer;
+            nextDate = timerDate;
+        }
+    }
+
+    if( nextTimer == NULL )
+    {
+        this->sleep( 1000 );
+    }
+    else
+    {
+        if( nextDate > curDate )
+        {
+            if( this->sleep( (nextDate - curDate ) / 1000 ) )
+            {
+                // The sleep has been interrupted: stop here
+                return;
+            }
+        }
+        // Execute the timer callback
+        if( ! nextTimer->execute() )
+        {
+            // Remove the timer if execute() returned false
+            m_timers.remove( nextTimer );
+        }
+    }
+}
+
+
+bool X11TimerLoop::sleep( int delay )
+{
+    // Timeout delay
+    struct timeval tv;
+    tv.tv_sec = delay / 1000;
+    tv.tv_usec = 1000 * (delay % 1000);
+
+    // FD set for select()
+    fd_set rfds;
+    FD_ZERO( &rfds );
+    FD_SET( m_connectionNumber, &rfds );
+
+    // Wait for an X11 event, or timeout
+    int num = select( m_connectionNumber + 1, &rfds, NULL, NULL, &tv );
+
+    return ( num > 0 );
+}
+
+
+#endif
diff --git a/modules/gui/skins2/x11/x11_timer.hpp b/modules/gui/skins2/x11/x11_timer.hpp
new file mode 100644 (file)
index 0000000..84564b6
--- /dev/null
@@ -0,0 +1,100 @@
+/*****************************************************************************
+ * x11_timer.hpp
+ *****************************************************************************
+ * Copyright (C) 2003 VideoLAN
+ * $Id: x11_timer.hpp,v 1.1 2004/01/03 23:31:34 asmax Exp $
+ *
+ * Authors: Cyril Deguet     <asmax@via.ecp.fr>
+ *          Olivier Teulière <ipkiss@via.ecp.fr>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111, USA.
+ *****************************************************************************/
+
+#ifndef X11_TIMER_HPP
+#define X11_TIMER_HPP
+
+#include "../src/os_timer.hpp"
+
+#include <list>
+
+// Forward declaration
+class X11TimerLoop;
+
+
+// X11 specific timer
+class X11Timer: public OSTimer
+{
+    public:
+        X11Timer( intf_thread_t *pIntf, const Callback &rCallback );
+        virtual ~X11Timer();
+
+        /// (Re)start the timer with the given delay (in ms). If oneShot is
+        /// true, stop it after the first execution of the callback.
+        virtual void start( int delay, bool oneShot );
+
+        /// Stop the timer
+        virtual void stop();
+
+        mtime_t getNextDate() const;
+
+        /// Execute the callback.
+        /// Returns false if the timer must be removed after
+        bool execute();
+
+    private:
+        /// Callback to execute
+        Callback m_callback;
+        /// Timer loop
+        X11TimerLoop *m_pTimerLoop;
+        /// Delay between two execute
+        mtime_t m_interval;
+        /// Next date at which the timer must be executed
+        mtime_t m_nextDate;
+        /// Flag to tell if the timer must be stopped after the first execution
+        bool m_oneShot;
+};
+
+
+/// Class to manage a set of timers
+class X11TimerLoop: public SkinObject
+{
+    public:
+        /// Create the timer loop with the communication number of the X11
+        /// display
+        X11TimerLoop( intf_thread_t *pIntf, int connectionNumber );
+        virtual ~X11TimerLoop();
+
+        /// Add a timer in the manager
+        void addTimer( X11Timer &rTimer );
+
+        /// Remove a timer from the manager
+        void removeTimer( X11Timer &rTimer );
+
+        /// Wait for the next timer and execute it
+        void waitNextTimer();
+
+    private:
+        /// Connection number of the X11 display
+        int m_connectionNumber;
+        /// List of timers
+        list<X11Timer*> m_timers;
+
+        /// Sleep for delay milliseconds, unless an X11 event is received
+        /// Returns true if the sleep has been interupted.
+        bool sleep( int delay );
+};
+
+
+#endif
diff --git a/modules/gui/skins2/x11/x11_tooltip.cpp b/modules/gui/skins2/x11/x11_tooltip.cpp
new file mode 100644 (file)
index 0000000..9b7d980
--- /dev/null
@@ -0,0 +1,77 @@
+/*****************************************************************************
+ * x11_tooltip.cpp
+ *****************************************************************************
+ * Copyright (C) 2003 VideoLAN
+ * $Id: x11_tooltip.cpp,v 1.1 2004/01/03 23:31:34 asmax Exp $
+ *
+ * Authors: Cyril Deguet     <asmax@via.ecp.fr>
+ *          Olivier Teulière <ipkiss@via.ecp.fr>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111, USA.
+ *****************************************************************************/
+
+#ifdef X11_SKINS
+
+#include "../src/generic_window.hpp"
+#include "x11_display.hpp"
+#include "x11_graphics.hpp"
+#include "x11_tooltip.hpp"
+
+X11Tooltip::X11Tooltip( intf_thread_t *pIntf,
+                                   X11Display &rDisplay ):
+    OSTooltip( pIntf ), m_rDisplay( rDisplay )
+{
+    Window root = DefaultRootWindow( XDISPLAY );
+    XSetWindowAttributes attr;
+    // Bypass the window manager
+    attr.override_redirect = True;
+
+    // Create the window
+    m_wnd = XCreateWindow( XDISPLAY, root, 0, 0, 1, 1, 0, 0,
+                           InputOutput, CopyFromParent, CWOverrideRedirect,
+                           &attr );
+}
+
+
+X11Tooltip::~X11Tooltip()
+{
+    XDestroyWindow( XDISPLAY, m_wnd );
+}
+
+
+void X11Tooltip::show( int left, int top, OSGraphics &rText )
+{
+    // Source drawable
+    Drawable src = ((X11Graphics&)rText).getDrawable();
+    int width = rText.getWidth();
+    int height = rText.getHeight();
+
+    XMoveResizeWindow( XDISPLAY, m_wnd, left, top, width, height );
+    // Show the window
+    XMapRaised( XDISPLAY, m_wnd );
+    // Move it again if the window manager forgets the position
+    XMoveWindow( XDISPLAY, m_wnd, left, top );
+    XCopyArea( XDISPLAY, src, m_wnd, XGC, 0, 0, width, height, 0, 0 );
+}
+
+
+void X11Tooltip::hide()
+{
+    // Unmap the window
+    XUnmapWindow( XDISPLAY, m_wnd );
+}
+
+
+#endif
diff --git a/modules/gui/skins2/x11/x11_tooltip.hpp b/modules/gui/skins2/x11/x11_tooltip.hpp
new file mode 100644 (file)
index 0000000..4534662
--- /dev/null
@@ -0,0 +1,57 @@
+/*****************************************************************************
+ * x11_tooltip.hpp
+ *****************************************************************************
+ * Copyright (C) 2003 VideoLAN
+ * $Id: x11_tooltip.hpp,v 1.1 2004/01/03 23:31:34 asmax Exp $
+ *
+ * Authors: Cyril Deguet     <asmax@via.ecp.fr>
+ *          Olivier Teulière <ipkiss@via.ecp.fr>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111, USA.
+ *****************************************************************************/
+
+#ifndef X11_TOOLTIP_HPP
+#define X11_TOOLTIP_HPP
+
+#include <X11/Xlib.h>
+
+#include "../src/os_tooltip.hpp"
+
+class X11Display;
+
+
+/// X11 implementation of OSTooltip
+class X11Tooltip: public OSTooltip
+{
+    public:
+        X11Tooltip( intf_thread_t *pIntf, X11Display &rDisplay );
+
+        virtual ~X11Tooltip();
+
+        // Show the tooltip
+        virtual void show( int left, int top, OSGraphics &rText );
+
+        // Hide the tooltip
+        virtual void hide();
+
+    private:
+        /// X11 display
+        X11Display &m_rDisplay;
+        /// Window ID
+        Window m_wnd;
+};
+
+
+#endif
diff --git a/modules/gui/skins2/x11/x11_window.cpp b/modules/gui/skins2/x11/x11_window.cpp
new file mode 100644 (file)
index 0000000..39a99ea
--- /dev/null
@@ -0,0 +1,159 @@
+/*****************************************************************************
+ * x11_window.cpp
+ *****************************************************************************
+ * Copyright (C) 2003 VideoLAN
+ * $Id: x11_window.cpp,v 1.1 2004/01/03 23:31:34 asmax Exp $
+ *
+ * Authors: Cyril Deguet     <asmax@via.ecp.fr>
+ *          Olivier Teulière <ipkiss@via.ecp.fr>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111, USA.
+ *****************************************************************************/
+
+#ifdef X11_SKINS
+
+#include <X11/Xatom.h>
+
+#include "../src/generic_window.hpp"
+#include "x11_window.hpp"
+#include "x11_display.hpp"
+#include "x11_graphics.hpp"
+#include "x11_dragdrop.hpp"
+#include "x11_factory.hpp"
+
+
+X11Window::X11Window( intf_thread_t *pIntf, GenericWindow &rWindow,
+                      X11Display &rDisplay, bool dragDrop, bool playOnDrop ):
+    OSWindow( pIntf ), m_rDisplay( rDisplay ), m_dragDrop( dragDrop )
+{
+    Window root = DefaultRootWindow( XDISPLAY );
+    XSetWindowAttributes attr;
+
+    // Create the window
+    m_wnd = XCreateWindow( XDISPLAY, root, 0, 0, 1, 1, 0, 0,
+                           InputOutput, CopyFromParent, 0, &attr );
+
+    // Select events received by the window
+    XSelectInput( XDISPLAY, m_wnd, ExposureMask|KeyPressMask|PointerMotionMask|
+                  ButtonPressMask|ButtonReleaseMask|LeaveWindowMask|
+                  FocusChangeMask );
+
+    // Store a pointer on the generic window in a map
+    X11Factory *pFactory = (X11Factory*)X11Factory::instance( getIntf() );
+    pFactory->m_windowMap[m_wnd] = &rWindow;
+
+    // Changing decorations
+    struct {
+        unsigned long flags;
+        unsigned long functions;
+        unsigned long decorations;
+        long input_mode;
+        unsigned long status;
+    } motifWmHints;
+    Atom hints_atom = XInternAtom( XDISPLAY, "_MOTIF_WM_HINTS", False );
+    motifWmHints.flags = 2;    // MWM_HINTS_DECORATIONS;
+    motifWmHints.decorations = 0;
+    XChangeProperty( XDISPLAY, m_wnd, hints_atom, hints_atom, 32,
+                     PropModeReplace, (unsigned char *)&motifWmHints,
+                     sizeof( motifWmHints ) / sizeof( long ) );
+
+    // Drag & drop
+    if( m_dragDrop )
+    {
+        // Register the window as a drop target
+        m_pDropTarget = new X11DragDrop( getIntf(), m_rDisplay, m_wnd,
+                                         playOnDrop );
+
+        Atom xdndAtom = XInternAtom( XDISPLAY, "XdndAware", False );
+        char xdndVersion = 4;
+        XChangeProperty( XDISPLAY, m_wnd, xdndAtom, XA_ATOM, 32,
+                         PropModeReplace, (unsigned char *)&xdndVersion, 1 );
+
+        // Store a pointer on the D&D object as a window property.
+        storePointer( "DND_OBJECT", (void*)m_pDropTarget );
+    }
+
+    // Change the window title XXX
+    XStoreName( XDISPLAY, m_wnd, "VLC" );
+}
+
+
+X11Window::~X11Window()
+{
+    X11Factory *pFactory = (X11Factory*)X11Factory::instance( getIntf() );
+    pFactory->m_windowMap[m_wnd] = NULL;
+
+    if( m_dragDrop )
+    {
+        delete m_pDropTarget;
+    }
+    XDestroyWindow( XDISPLAY, m_wnd );
+    XSync( XDISPLAY, False );
+}
+
+
+void X11Window::show( int left, int top )
+{
+    // Map the window
+    XMapRaised( XDISPLAY, m_wnd );
+    XMoveWindow( XDISPLAY, m_wnd, left, top );
+}
+
+
+void X11Window::hide()
+{
+    // Unmap the window
+    XUnmapWindow( XDISPLAY, m_wnd );
+}
+
+
+void X11Window::moveResize( int left, int top, int width, int height )
+{
+    XMoveResizeWindow( XDISPLAY, m_wnd, left, top, width, height );
+}
+
+
+void X11Window::raise()
+{
+    XRaiseWindow( XDISPLAY, m_wnd );
+}
+
+
+void X11Window::setOpacity( uint8_t value )
+{
+    // Sorry, the opacity cannot be changed :)
+}
+
+
+void X11Window::toggleOnTop( bool onTop )
+{
+    // XXX TODO
+}
+
+
+void X11Window::storePointer( const char *pName, void *pPtr )
+{
+    // We don't assume pointers are 32bits, so it's a bit tricky
+    unsigned char data[sizeof(void*)];
+    memcpy( data, &pPtr, sizeof(void*) );
+
+    // Store the pointer on the generic window as a window property.
+    Atom prop = XInternAtom( XDISPLAY, pName, False );
+    Atom type = XInternAtom( XDISPLAY, "POINTER", False );
+    XChangeProperty( XDISPLAY, m_wnd, prop, type, 8, PropModeReplace, data,
+                     sizeof(GenericWindow*) );
+}
+
+#endif
diff --git a/modules/gui/skins2/x11/x11_window.hpp b/modules/gui/skins2/x11/x11_window.hpp
new file mode 100644 (file)
index 0000000..864c989
--- /dev/null
@@ -0,0 +1,81 @@
+/*****************************************************************************
+ * x11_window.hpp
+ *****************************************************************************
+ * Copyright (C) 2003 VideoLAN
+ * $Id: x11_window.hpp,v 1.1 2004/01/03 23:31:34 asmax Exp $
+ *
+ * Authors: Cyril Deguet     <asmax@via.ecp.fr>
+ *          Olivier Teulière <ipkiss@via.ecp.fr>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111, USA.
+ *****************************************************************************/
+
+#ifndef X11_WINDOW_HPP
+#define X11_WINDOW_HPP
+
+#include <X11/Xlib.h>
+
+#include "../src/os_window.hpp"
+
+class X11Display;
+class X11DragDrop;
+
+
+/// X11 implementation of OSWindow
+class X11Window: public OSWindow
+{
+    public:
+        X11Window( intf_thread_t *pIntf, GenericWindow &rWindow,
+                   X11Display &rDisplay, bool dragDrop, bool playOnDrop );
+
+        virtual ~X11Window();
+
+        // Show the window
+        virtual void show( int left, int top );
+
+        // Hide the window
+        virtual void hide();
+
+        /// Move the window
+        virtual void moveResize( int left, int top, int width, int height );
+
+        /// Bring the window on top
+        virtual void raise();
+
+        /// Set the opacity of the window (0 = transparent, 255 = opaque)
+        virtual void setOpacity( uint8_t value );
+
+        /// Toggle the window on top
+        virtual void toggleOnTop( bool onTop );
+
+        /// Get the window ID
+        Window getDrawable() const { return m_wnd; }
+
+    private:
+        /// X11 display
+        X11Display &m_rDisplay;
+        /// Window ID
+        Window m_wnd;
+        /// Indicates whether the window handles drag&drop events
+        bool m_dragDrop;
+        /// Drop target
+        X11DragDrop *m_pDropTarget;
+
+        /// Store a pointer in the window as a property
+        void storePointer( const char *pName, void *pPtr );
+};
+
+
+#endif