changeset 1541:06329cbf186a trunk

[svn] this massive commit does the following: - seriously cleans up dependencies on the WA2-like gui code - moves all of the WA2 stuff into a seperate library (libwidgets.a) - makes things less icky in the player tree
author nenolod
date Wed, 09 Aug 2006 02:47:22 -0700
parents 237bb7c97759
children 66ad5920cee4
files ChangeLog audacious/Makefile audacious/controlsocket.c audacious/eq_graph.c audacious/eq_graph.h audacious/eq_slider.c audacious/eq_slider.h audacious/equalizer.c audacious/equalizer.h audacious/genevent.c audacious/genevent.h audacious/hslider.c audacious/hslider.h audacious/input.c audacious/main.c audacious/main.h audacious/mainwin.c audacious/mainwin.h audacious/menurow.c audacious/menurow.h audacious/monostereo.c audacious/monostereo.h audacious/number.c audacious/number.h audacious/pbutton.c audacious/pbutton.h audacious/playback.c audacious/playlist.c audacious/playlist_list.c audacious/playlist_list.h audacious/playlist_slider.c audacious/playlist_slider.h audacious/playstatus.c audacious/playstatus.h audacious/prefswin.c audacious/sbutton.c audacious/sbutton.h audacious/skin.c audacious/skin.h audacious/skinwin.c audacious/svis.c audacious/svis.h audacious/tbutton.c audacious/tbutton.h audacious/textbox.c audacious/textbox.h audacious/ui_fileinfo.c audacious/ui_playlist.c audacious/ui_playlist.h audacious/vis.c audacious/vis.h audacious/visualization.c audacious/widget.c audacious/widget.h audacious/widgets/Makefile audacious/widgets/eq_graph.c audacious/widgets/eq_graph.h audacious/widgets/eq_slider.c audacious/widgets/eq_slider.h audacious/widgets/hslider.c audacious/widgets/hslider.h audacious/widgets/monostereo.c audacious/widgets/monostereo.h audacious/widgets/number.c audacious/widgets/number.h audacious/widgets/pbutton.c audacious/widgets/pbutton.h audacious/widgets/playlist_list.c audacious/widgets/playlist_list.h audacious/widgets/playlist_slider.c audacious/widgets/playlist_slider.h audacious/widgets/playstatus.c audacious/widgets/playstatus.h audacious/widgets/sbutton.c audacious/widgets/sbutton.h audacious/widgets/skin.c audacious/widgets/skin.h audacious/widgets/svis.c audacious/widgets/svis.h audacious/widgets/tbutton.c audacious/widgets/tbutton.h audacious/widgets/textbox.c audacious/widgets/textbox.h audacious/widgets/vis.c audacious/widgets/vis.h audacious/widgets/widget.c audacious/widgets/widget.h
diffstat 87 files changed, 6089 insertions(+), 6313 deletions(-) [+]
line wrap: on
line diff
--- a/ChangeLog	Wed Aug 09 02:11:01 2006 -0700
+++ b/ChangeLog	Wed Aug 09 02:47:22 2006 -0700
@@ -1,3 +1,12 @@
+2006-08-09 09:11:01 +0000  William Pitcock <nenolod@nenolod.net>
+  revision [1994]
+  - use posix_memalign() instead of memalign().
+  
+
+  Changes:        Modified:
+  +7 -4           trunk/Plugins/Input/wma/libffwma/mem.c  
+
+
 2006-08-09 09:04:02 +0000  William Pitcock <nenolod@nenolod.net>
   revision [1992]
   - switch to stdlib/unistd.h for malloc (all C89/C99 systems have these). fixes bug #539.
--- a/audacious/Makefile	Wed Aug 09 02:11:01 2006 -0700
+++ b/audacious/Makefile	Wed Aug 09 02:47:22 2006 -0700
@@ -1,7 +1,7 @@
 include ../mk/rules.mk
 include ../mk/objective.mk
 
-SUBDIRS = glade images
+SUBDIRS = widgets glade images
 
 beepincludedir = $(includedir)/audacious
 
@@ -14,7 +14,8 @@
 	../sqlite/libsqlite.a	\
 	$(CHARDET_LIBS) \
 	$(GTK_LIBS)      \
-	$(LIBGLADE_LIBS)
+	$(LIBGLADE_LIBS) \
+	./widgets/libwidgets.a
 
 CFLAGS += \
 	$(GTK_CFLAGS)      \
@@ -33,7 +34,6 @@
 SOURCES = \
 	build_stamp.c \
 	genevent.c \
-	skin.c \
 	util.c \
 	output.c \
 	fft.c \
@@ -45,23 +45,7 @@
 	playlist.c \
 	controlsocket.c \
 	dock.c \
-	widget.c \
-	sbutton.c \
-	pbutton.c \
-	tbutton.c \
-	textbox.c \
-	menurow.c \
-	hslider.c \
-	monostereo.c \
-	vis.c \
-	svis.c \
-	number.c \
 	playback.c \
-	playstatus.c \
-	playlist_list.c \
-	playlist_slider.c \
-	eq_graph.c \
-	eq_slider.c \
 	main.c \
 	logger.c \
 	mainwin.c \
--- a/audacious/controlsocket.c	Wed Aug 09 02:11:01 2006 -0700
+++ b/audacious/controlsocket.c	Wed Aug 09 02:47:22 2006 -0700
@@ -42,7 +42,6 @@
 #include "playlist.h"
 #include "ui_playlist.h"
 #include "prefswin.h"
-#include "skin.h"
 #include "libaudacious/beepctrl.h"
 
 
--- a/audacious/eq_graph.c	Wed Aug 09 02:11:01 2006 -0700
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,149 +0,0 @@
-/*  BMP - Cross-platform multimedia player
- *  Copyright (C) 2003-2004  BMP development team.
- *
- *  Based on XMMS:
- *  Copyright (C) 1998-2003  XMMS development team.
- *
- *  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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
- */
-
-#include "eq_graph.h"
-
-#include <glib.h>
-
-#include "main.h"
-#include "skin.h"
-
-void
-init_spline(gfloat * x, gfloat * y, gint n, gfloat * y2)
-{
-    gint i, k;
-    gfloat p, qn, sig, un, *u;
-
-    u = (gfloat *) g_malloc(n * sizeof(gfloat));
-
-    y2[0] = u[0] = 0.0;
-
-    for (i = 1; i < n - 1; i++) {
-        sig = ((gfloat) x[i] - x[i - 1]) / ((gfloat) x[i + 1] - x[i - 1]);
-        p = sig * y2[i - 1] + 2.0;
-        y2[i] = (sig - 1.0) / p;
-        u[i] =
-            (((gfloat) y[i + 1] - y[i]) / (x[i + 1] - x[i])) -
-            (((gfloat) y[i] - y[i - 1]) / (x[i] - x[i - 1]));
-        u[i] = (6.0 * u[i] / (x[i + 1] - x[i - 1]) - sig * u[i - 1]) / p;
-    }
-    qn = un = 0.0;
-
-    y2[n - 1] = (un - qn * u[n - 2]) / (qn * y2[n - 2] + 1.0);
-    for (k = n - 2; k >= 0; k--)
-        y2[k] = y2[k] * y2[k + 1] + u[k];
-    g_free(u);
-}
-
-gfloat
-eval_spline(gfloat xa[], gfloat ya[], gfloat y2a[], gint n, gfloat x)
-{
-    gint klo, khi, k;
-    gfloat h, b, a;
-
-    klo = 0;
-    khi = n - 1;
-    while (khi - klo > 1) {
-        k = (khi + klo) >> 1;
-        if (xa[k] > x)
-            khi = k;
-        else
-            klo = k;
-    }
-    h = xa[khi] - xa[klo];
-    a = (xa[khi] - x) / h;
-    b = (x - xa[klo]) / h;
-    return (a * ya[klo] + b * ya[khi] +
-            ((a * a * a - a) * y2a[klo] +
-             (b * b * b - b) * y2a[khi]) * (h * h) / 6.0);
-}
-
-void
-eqgraph_draw(Widget * w)
-{
-    EqGraph *eg = (EqGraph *) w;
-    GdkPixmap *obj;
-    GdkColor col;
-    guint32 cols[19];
-    gint i, y, ymin, ymax, py = 0;
-    gfloat x[] = { 0, 11, 23, 35, 47, 59, 71, 83, 97, 109 }, yf[10];
-
-    /*
-     * This avoids the init_spline() function to be inlined.
-     * Inlining the function caused troubles when compiling with
-     * `-O' (at least on FreeBSD).
-     */
-    void (*__init_spline) (gfloat *, gfloat *, gint, gfloat *) = init_spline;
-
-    obj = eg->eg_widget.parent;
-    skin_draw_pixmap(bmp_active_skin, obj, eg->eg_widget.gc, SKIN_EQMAIN,
-                     0, 294, eg->eg_widget.x, eg->eg_widget.y,
-                     eg->eg_widget.width, eg->eg_widget.height);
-    skin_draw_pixmap(bmp_active_skin, obj, eg->eg_widget.gc, SKIN_EQMAIN,
-                     0, 314, eg->eg_widget.x,
-                     eg->eg_widget.y + 9 +
-                     ((cfg.equalizer_preamp * 9) / 20),
-                     eg->eg_widget.width, 1);
-
-    skin_get_eq_spline_colors(bmp_active_skin, cols);
-
-    __init_spline(x, cfg.equalizer_bands, 10, yf);
-    for (i = 0; i < 109; i++) {
-        y = 9 -
-            (gint) ((eval_spline(x, cfg.equalizer_bands, yf, 10, i) *
-                     9.0) / 20.0);
-        if (y < 0)
-            y = 0;
-        if (y > 18)
-            y = 18;
-        if (!i)
-            py = y;
-        if (y < py) {
-            ymin = y;
-            ymax = py;
-        }
-        else {
-            ymin = py;
-            ymax = y;
-        }
-        py = y;
-        for (y = ymin; y <= ymax; y++) {
-            col.pixel = cols[y];
-            gdk_gc_set_foreground(eg->eg_widget.gc, &col);
-            gdk_draw_point(obj, eg->eg_widget.gc, eg->eg_widget.x + i + 2,
-                           eg->eg_widget.y + y);
-        }
-    }
-}
-
-EqGraph *
-create_eqgraph(GList ** wlist, GdkPixmap * parent, GdkGC * gc, gint x, gint y)
-{
-    EqGraph *eg;
-
-    eg = g_new0(EqGraph, 1);
-    widget_init(&eg->eg_widget, parent, gc, x, y, 113, 19, TRUE);
-    eg->eg_widget.draw = eqgraph_draw;
-
-    widget_list_add(wlist, WIDGET(eg));
-
-    return eg;
-}
--- a/audacious/eq_graph.h	Wed Aug 09 02:11:01 2006 -0700
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,40 +0,0 @@
-/*  BMP - Cross-platform multimedia player
- *  Copyright (C) 2003-2004  BMP development team.
- *
- *  Based on XMMS:
- *  Copyright (C) 1998-2003  XMMS development team.
- *
- *  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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
- */
-
-#ifndef EQ_GRAPH_H
-#define EQ_GRAPH_H
-
-#include <glib.h>
-#include <gdk/gdk.h>
-
-#include "widget.h"
-
-#define EQ_GRAPH(x)  ((EqGraph *)(x))
-struct _EqGraph {
-    Widget eg_widget;
-};
-
-typedef struct _EqGraph EqGraph;
-
-EqGraph *create_eqgraph(GList ** wlist, GdkPixmap * parent, GdkGC * gc,
-                        gint x, gint y);
-
-#endif
--- a/audacious/eq_slider.c	Wed Aug 09 02:11:01 2006 -0700
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,235 +0,0 @@
-/*  BMP - Cross-platform multimedia player
- *  Copyright (C) 2003-2004  BMP development team.
- *
- *  Based on XMMS:
- *  Copyright (C) 1998-2003  XMMS development team.
- *
- *  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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
- */
-
-#include "eq_slider.h"
-
-#include <glib.h>
-#include <glib/gi18n.h>
-#include <gtk/gtk.h>
-#include <gdk/gdk.h>
-
-#include "equalizer.h"
-#include "mainwin.h"
-#include "skin.h"
-
-void
-eqslider_set_position(EqSlider * es,
-                      gfloat pos)
-{
-    es->es_position = 25 - (gint) ((pos * 25.0) / 20.0);
-
-    if (es->es_position < 0)
-        es->es_position = 0;
-
-    if (es->es_position > 50)
-        es->es_position = 50;
-
-    if (es->es_position >= 24 && es->es_position <= 26)
-        es->es_position = 25;
-
-    widget_draw(WIDGET(es));
-}
-
-gfloat
-eqslider_get_position(EqSlider * es)
-{
-    return 20.0 - (((gfloat) es->es_position * 20.0) / 25.0);
-}
-
-void
-eqslider_draw(Widget * w)
-{
-    EqSlider *es = (EqSlider *) w;
-    GdkPixmap *obj;
-    SkinPixmapId src;
-    gint frame;
-
-    src = SKIN_EQMAIN;
-    obj = es->es_widget.parent;
-
-    frame = 27 - ((es->es_position * 27) / 50);
-    if (frame < 14)
-        skin_draw_pixmap(bmp_active_skin, obj, es->es_widget.gc, src,
-                         (frame * 15) + 13, 164, es->es_widget.x,
-                         es->es_widget.y, es->es_widget.width,
-                         es->es_widget.height);
-    else
-        skin_draw_pixmap(bmp_active_skin, obj, es->es_widget.gc, src,
-                         ((frame - 14) * 15) + 13, 229, es->es_widget.x,
-                         es->es_widget.y, es->es_widget.width,
-                         es->es_widget.height);
-    if (es->es_isdragging)
-        skin_draw_pixmap(bmp_active_skin, obj, es->es_widget.gc, src, 0,
-                         176, es->es_widget.x + 1,
-                         es->es_widget.y + es->es_position, 11, 11);
-    else
-        skin_draw_pixmap(bmp_active_skin, obj, es->es_widget.gc, src, 0,
-                         164, es->es_widget.x + 1,
-                         es->es_widget.y + es->es_position, 11, 11);
-}
-
-void
-eqslider_set_mainwin_text(EqSlider * es)
-{
-    gint band = 0;
-    const gchar *bandname[11] = { N_("PREAMP"), N_("60HZ"), N_("170HZ"),
-        N_("310HZ"), N_("600HZ"), N_("1KHZ"),
-        N_("3KHZ"), N_("6KHZ"), N_("12KHZ"),
-        N_("14KHZ"), N_("16KHZ")
-    };
-    gchar *tmp;
-
-    if (es->es_widget.x > 21)
-        band = ((es->es_widget.x - 78) / 18) + 1;
-
-    tmp =
-        g_strdup_printf("EQ: %s: %+.1f DB", _(bandname[band]),
-                        eqslider_get_position(es));
-    mainwin_lock_info_text(tmp);
-    g_free(tmp);
-}
-
-void
-eqslider_button_press_cb(GtkWidget * w,
-                         GdkEventButton * event,
-                         gpointer data)
-{
-    EqSlider *es = EQ_SLIDER(data);
-    gint y;
-
-    if (widget_contains(&es->es_widget, event->x, event->y)) {
-        if (event->button == 1) {
-            y = event->y - es->es_widget.y;
-            es->es_isdragging = TRUE;
-            if (y >= es->es_position && y < es->es_position + 11)
-                es->es_drag_y = y - es->es_position;
-            else {
-                es->es_position = y - 5;
-                es->es_drag_y = 5;
-                if (es->es_position < 0)
-                    es->es_position = 0;
-                if (es->es_position > 50)
-                    es->es_position = 50;
-                if (es->es_position >= 24 && es->es_position <= 26)
-                    es->es_position = 25;
-                equalizerwin_eq_changed();
-            }
-
-            eqslider_set_mainwin_text(es);
-            widget_draw(WIDGET(es));
-        }
-        if (event->button == 4) {
-            es->es_position -= 2;
-            if (es->es_position < 0)
-                es->es_position = 0;
-            equalizerwin_eq_changed();
-            widget_draw(WIDGET(es));
-        }
-    }
-}
-
-void
-eqslider_mouse_scroll_cb(GtkWidget * w,
-                         GdkEventScroll * event,
-                         gpointer data)
-{
-    EqSlider *es = EQ_SLIDER(data);
-
-    if (!widget_contains(&es->es_widget, event->x, event->y))
-        return;
-
-    if (event->direction == GDK_SCROLL_UP) {
-        es->es_position -= 2;
-
-        if (es->es_position < 0)
-            es->es_position = 0;
-
-        equalizerwin_eq_changed();
-        widget_draw(WIDGET(es));
-    }
-    else {
-        es->es_position += 2;
-
-        if (es->es_position > 50)
-            es->es_position = 50;
-
-        equalizerwin_eq_changed();
-        widget_draw(WIDGET(es));
-    }
-}
-
-void
-eqslider_motion_cb(GtkWidget * w,
-                   GdkEventMotion * event,
-                   gpointer data)
-{
-    EqSlider *es = EQ_SLIDER(data);
-    gint y;
-
-    y = event->y - es->es_widget.y;
-    if (es->es_isdragging) {
-        es->es_position = y - es->es_drag_y;
-        if (es->es_position < 0)
-            es->es_position = 0;
-        if (es->es_position > 50)
-            es->es_position = 50;
-        if (es->es_position >= 24 && es->es_position <= 26)
-            es->es_position = 25;
-        equalizerwin_eq_changed();
-        eqslider_set_mainwin_text(es);
-        widget_draw(WIDGET(es));
-    }
-}
-
-void
-eqslider_button_release_cb(GtkWidget * w,
-                           GdkEventButton * event,
-                           gpointer data)
-{
-    EqSlider *es = EQ_SLIDER(data);
-
-    if (es->es_isdragging) {
-        es->es_isdragging = FALSE;
-        mainwin_release_info_text();
-        widget_draw(WIDGET(es));
-    }
-}
-
-EqSlider *
-create_eqslider(GList ** wlist,
-                GdkPixmap * parent,
-                GdkGC * gc,
-                gint x, gint y)
-{
-    EqSlider *es;
-
-    es = g_new0(EqSlider, 1);
-    widget_init(&es->es_widget, parent, gc, x, y, 14, 63, TRUE);
-    es->es_widget.button_press_cb = eqslider_button_press_cb;
-    es->es_widget.button_release_cb = eqslider_button_release_cb;
-    es->es_widget.motion_cb = eqslider_motion_cb;
-    es->es_widget.draw = eqslider_draw;
-    es->es_widget.mouse_scroll_cb = eqslider_mouse_scroll_cb;
-
-    widget_list_add(wlist, WIDGET(es));
-
-    return es;
-}
--- a/audacious/eq_slider.h	Wed Aug 09 02:11:01 2006 -0700
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,44 +0,0 @@
-/*  BMP - Cross-platform multimedia player
- *  Copyright (C) 2003-2004  BMP development team.
- *
- *  Based on XMMS:
- *  Copyright (C) 1998-2003  XMMS development team.
- *
- *  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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
- */
-#ifndef EQ_SLIDER_H
-#define EQ_SLIDER_H
-
-#include <glib.h>
-#include <gdk/gdk.h>
-
-#include "widget.h"
-
-#define EQ_SLIDER(x)  ((EqSlider *)(x))
-struct _EqSlider {
-    Widget es_widget;
-    gint es_position;
-    gboolean es_isdragging;
-    gint es_drag_y;
-};
-
-typedef struct _EqSlider EqSlider;
-
-EqSlider *create_eqslider(GList ** wlist, GdkPixmap * parent, GdkGC * gc,
-                          gint x, gint y);
-void eqslider_set_position(EqSlider * es, gfloat pos);
-gfloat eqslider_get_position(EqSlider * es);
-
-#endif
--- a/audacious/equalizer.c	Wed Aug 09 02:11:01 2006 -0700
+++ b/audacious/equalizer.c	Wed Aug 09 02:47:22 2006 -0700
@@ -41,17 +41,17 @@
 #include <X11/Xlib.h>
 
 #include "dock.h"
-#include "eq_graph.h"
-#include "eq_slider.h"
+#include "widgets/eq_graph.h"
+#include "widgets/eq_slider.h"
 #include "hints.h"
-#include "hslider.h"
+#include "widgets/hslider.h"
 #include "input.h"
 #include "main.h"
-#include "pbutton.h"
+#include "widgets/pbutton.h"
 #include "playlist.h"
 #include "ui_playlist.h"
-#include "skin.h"
-#include "tbutton.h"
+#include "widgets/skin.h"
+#include "widgets/tbutton.h"
 #include "util.h"
 #include "output.h"
 
--- a/audacious/equalizer.h	Wed Aug 09 02:11:01 2006 -0700
+++ b/audacious/equalizer.h	Wed Aug 09 02:47:22 2006 -0700
@@ -25,7 +25,7 @@
 #include <glib.h>
 #include <gtk/gtk.h>
 
-#include "pbutton.h"
+#include "widgets/pbutton.h"
 
 #define EQUALIZER_HEIGHT         (gint)(cfg.equalizer_shaded ? 14 : 116)
 #define EQUALIZER_WIDTH          (gint)275
--- a/audacious/genevent.c	Wed Aug 09 02:11:01 2006 -0700
+++ b/audacious/genevent.c	Wed Aug 09 02:47:22 2006 -0700
@@ -67,7 +67,6 @@
 #include "ui_playlist.h"
 #include "pluginenum.h"
 #include "prefswin.h"
-#include "skin.h"
 #include "skinwin.h"
 #include "util.h"
 #include "visualization.h"
--- a/audacious/genevent.h	Wed Aug 09 02:11:01 2006 -0700
+++ b/audacious/genevent.h	Wed Aug 09 02:47:22 2006 -0700
@@ -26,8 +26,6 @@
 #define GENEVENT_H
 
 #include "mainwin.h"
-#include "textbox.h"
-#include "vis.h"
 
 extern gboolean ev_waiting;
 
--- a/audacious/hslider.c	Wed Aug 09 02:11:01 2006 -0700
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,203 +0,0 @@
-/*  XMMS - Cross-platform multimedia player
- *  Copyright (C) 1998-2000  Peter Alm, Mikael Alm, Olle Hallnas, Thomas Nilsson and 4Front Technologies
- *
- *  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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
- */
-
-#include "hslider.h"
-
-#include <glib.h>
-#include <gdk/gdk.h>
-#include <gtk/gtk.h>
-
-#include "skin.h"
-
-void
-hslider_set_position(HSlider * hs,
-                     gint pos)
-{
-    if (pos == hs->hs_position || hs->hs_pressed)
-        return;
-
-    hs->hs_position = pos;
-
-    if (hs->hs_frame_cb)
-        hs->hs_frame = hs->hs_frame_cb(hs->hs_position);
-
-    widget_draw(WIDGET(hs));
-}
-
-gint
-hslider_get_position(HSlider * hs)
-{
-    return hs->hs_position;
-}
-
-void
-hslider_draw(Widget * w)
-{
-    HSlider *hs = (HSlider *) w;
-    GdkPixmap *obj;
-
-    obj = hs->hs_widget.parent;
-
-    skin_draw_pixmap(bmp_active_skin, obj, hs->hs_widget.gc,
-                     hs->hs_skin_index, hs->hs_frame_offset,
-                     hs->hs_frame * hs->hs_frame_height, hs->hs_widget.x,
-                     hs->hs_widget.y, hs->hs_widget.width,
-                     hs->hs_widget.height);
-    if (hs->hs_pressed)
-        skin_draw_pixmap(bmp_active_skin, obj, hs->hs_widget.gc,
-                         hs->hs_skin_index, hs->hs_knob_px,
-                         hs->hs_knob_py, hs->hs_widget.x + hs->hs_position,
-                         hs->hs_widget.y +
-                         ((hs->hs_widget.height - hs->hs_knob_height) / 2),
-                         hs->hs_knob_width, hs->hs_knob_height);
-    else
-        skin_draw_pixmap(bmp_active_skin, obj, hs->hs_widget.gc,
-                         hs->hs_skin_index, hs->hs_knob_nx, hs->hs_knob_ny,
-                         hs->hs_widget.x + hs->hs_position,
-                         hs->hs_widget.y +
-                         ((hs->hs_widget.height - hs->hs_knob_height) / 2),
-                         hs->hs_knob_width, hs->hs_knob_height);
-}
-
-void
-hslider_button_press_cb(GtkWidget * w,
-                        GdkEventButton * event,
-                        gpointer data)
-{
-    HSlider *hs = HSLIDER(data);
-    gint x;
-
-    if (event->button != 1)
-        return;
-
-    if (widget_contains(&hs->hs_widget, event->x, event->y)) {
-        x = event->x - hs->hs_widget.x;
-        hs->hs_pressed = TRUE;
-
-        if (x >= hs->hs_position && x < hs->hs_position + hs->hs_knob_width)
-            hs->hs_pressed_x = x - hs->hs_position;
-        else {
-            hs->hs_position = x - (hs->hs_knob_width / 2);
-            hs->hs_pressed_x = hs->hs_knob_width / 2;
-            if (hs->hs_position < hs->hs_min)
-                hs->hs_position = hs->hs_min;
-            if (hs->hs_position > hs->hs_max)
-                hs->hs_position = hs->hs_max;
-            if (hs->hs_frame_cb)
-                hs->hs_frame = hs->hs_frame_cb(hs->hs_position);
-
-        }
-
-        if (hs->hs_motion_cb)
-            hs->hs_motion_cb(hs->hs_position);
-
-        widget_draw(WIDGET(hs));
-    }
-}
-
-void
-hslider_motion_cb(GtkWidget * w, GdkEventMotion * event, gpointer data)
-{
-    HSlider *hs = (HSlider *) data;
-    gint x;
-
-    if (hs->hs_pressed) {
-        if (!hs->hs_widget.visible) {
-            hs->hs_pressed = FALSE;
-            return;
-        }
-
-        x = event->x - hs->hs_widget.x;
-        hs->hs_position = x - hs->hs_pressed_x;
-
-        if (hs->hs_position < hs->hs_min)
-            hs->hs_position = hs->hs_min;
-
-        if (hs->hs_position > hs->hs_max)
-            hs->hs_position = hs->hs_max;
-
-        if (hs->hs_frame_cb)
-            hs->hs_frame = hs->hs_frame_cb(hs->hs_position);
-
-        if (hs->hs_motion_cb)
-            hs->hs_motion_cb(hs->hs_position);
-
-        widget_draw(WIDGET(hs));
-    }
-}
-
-void
-hslider_button_release_cb(GtkWidget * w,
-                          GdkEventButton * event,
-                          gpointer data)
-{
-    HSlider *hs = HSLIDER(data);
-
-    if (hs->hs_pressed) {
-        hs->hs_pressed = FALSE;
-
-        if (hs->hs_release_cb)
-            hs->hs_release_cb(hs->hs_position);
-
-        widget_draw(WIDGET(hs));
-    }
-}
-
-HSlider *
-create_hslider(GList ** wlist, GdkPixmap * parent, GdkGC * gc,
-               gint x, gint y, gint w, gint h, gint knx, gint kny,
-               gint kpx, gint kpy, gint kw, gint kh, gint fh,
-               gint fo, gint min, gint max, gint(*fcb) (gint),
-               void (*mcb) (gint), void (*rcb) (gint), SkinPixmapId si)
-{
-    HSlider *hs;
-
-    hs = g_new0(HSlider, 1);
-    widget_init(&hs->hs_widget, parent, gc, x, y, w, h, 1);
-    hs->hs_widget.button_press_cb =
-        (void (*)(GtkWidget *, GdkEventButton *, gpointer))
-        hslider_button_press_cb;
-    hs->hs_widget.button_release_cb =
-        (void (*)(GtkWidget *, GdkEventButton *, gpointer))
-        hslider_button_release_cb;
-    hs->hs_widget.motion_cb =
-        (void (*)(GtkWidget *, GdkEventMotion *, gpointer))
-        hslider_motion_cb;
-    hs->hs_widget.draw = hslider_draw;
-    hs->hs_knob_nx = knx;
-    hs->hs_knob_ny = kny;
-    hs->hs_knob_px = kpx;
-    hs->hs_knob_py = kpy;
-    hs->hs_knob_width = kw;
-    hs->hs_knob_height = kh;
-    hs->hs_frame_height = fh;
-    hs->hs_frame_offset = fo;
-    hs->hs_min = min;
-    hs->hs_position = min;
-    hs->hs_max = max;
-    hs->hs_frame_cb = fcb;
-    hs->hs_motion_cb = mcb;
-    hs->hs_release_cb = rcb;
-    if (hs->hs_frame_cb)
-        hs->hs_frame = hs->hs_frame_cb(0);
-    hs->hs_skin_index = si;
-
-    widget_list_add(wlist, WIDGET(hs));
-
-    return hs;
-}
--- a/audacious/hslider.h	Wed Aug 09 02:11:01 2006 -0700
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,54 +0,0 @@
-/*  XMMS - Cross-platform multimedia player
- *  Copyright (C) 1998-2000  Peter Alm, Mikael Alm, Olle Hallnas, Thomas Nilsson and 4Front Technologies
- *
- *  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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
- */
-#ifndef HSLIDER_H
-#define HSLIDER_H
-
-#include <glib.h>
-#include <gdk/gdk.h>
-
-#include "skin.h"
-#include "widget.h"
-
-#define HSLIDER(x)  ((HSlider *)(x))
-struct _HSlider {
-    Widget hs_widget;
-    gint hs_frame, hs_frame_offset, hs_frame_height, hs_min, hs_max;
-    gint hs_knob_nx, hs_knob_ny, hs_knob_px, hs_knob_py;
-    gint hs_knob_width, hs_knob_height;
-    gint hs_position;
-    gboolean hs_pressed;
-    gint hs_pressed_x, hs_pressed_y;
-     gint(*hs_frame_cb) (gint);
-    void (*hs_motion_cb) (gint);
-    void (*hs_release_cb) (gint);
-    SkinPixmapId hs_skin_index;
-};
-
-typedef struct _HSlider HSlider;
-
-HSlider *create_hslider(GList ** wlist, GdkPixmap * parent, GdkGC * gc,
-                        gint x, gint y, gint w, gint h, gint knx, gint kny,
-                        gint kpx, gint kpy, gint kw, gint kh, gint fh,
-                        gint fo, gint min, gint max, gint(*fcb) (gint),
-                        void (*mcb) (gint), void (*rcb) (gint),
-                        SkinPixmapId si);
-
-void hslider_set_position(HSlider * hs, gint pos);
-gint hslider_get_position(HSlider * hs);
-
-#endif
--- a/audacious/input.c	Wed Aug 09 02:11:01 2006 -0700
+++ b/audacious/input.c	Wed Aug 09 02:47:22 2006 -0700
@@ -36,7 +36,7 @@
 #include "util.h"
 #include "visualization.h"
 #include "playback.h"
-#include "playstatus.h"
+#include "widgets/playstatus.h"
 #include "pluginenum.h"
 
 #include "libaudacious/titlestring.h"
--- a/audacious/main.c	Wed Aug 09 02:11:01 2006 -0700
+++ b/audacious/main.c	Wed Aug 09 02:47:22 2006 -0700
@@ -68,7 +68,6 @@
 #include "ui_playlist.h"
 #include "pluginenum.h"
 #include "prefswin.h"
-#include "skin.h"
 #include "skinwin.h"
 #include "util.h"
 #include "visualization.h"
--- a/audacious/main.h	Wed Aug 09 02:11:01 2006 -0700
+++ b/audacious/main.h	Wed Aug 09 02:47:22 2006 -0700
@@ -23,8 +23,8 @@
 #define MAIN_H
 
 #include "mainwin.h"
-#include "textbox.h"
-#include "vis.h"
+#include "widgets/textbox.h"
+#include "widgets/vis.h"
 
 #include <sys/types.h>
 #include <sys/stat.h>
--- a/audacious/mainwin.c	Wed Aug 09 02:11:01 2006 -0700
+++ b/audacious/mainwin.c	Wed Aug 09 02:47:22 2006 -0700
@@ -41,7 +41,7 @@
 
 #include <X11/Xlib.h>
 
-#include "textbox.h"
+#include "widgets/textbox.h"
 #include "mainwin.h"
 #include "pixmaps.h"
 
@@ -60,20 +60,20 @@
 #include "prefswin.h"
 #include "skinwin.h"
 #include "genevent.h"
-#include "hslider.h"
-#include "menurow.h"
-#include "monostereo.h"
-#include "pbutton.h"
+#include "widgets/hslider.h"
+#include "widgets/menurow.h"
+#include "widgets/monostereo.h"
+#include "widgets/pbutton.h"
 #include "playback.h"
 #include "playlist.h"
-#include "playlist_list.h"
-#include "playstatus.h"
-#include "sbutton.h"
-#include "svis.h"
-#include "textbox.h"
+#include "widgets/playlist_list.h"
+#include "widgets/playstatus.h"
+#include "widgets/sbutton.h"
+#include "widgets/svis.h"
+#include "widgets/textbox.h"
 #include "urldecode.h"
 #include "util.h"
-#include "vis.h"
+#include "widgets/vis.h"
 #include "visualization.h"
 #include "libaudacious/configdb.h"
 
--- a/audacious/mainwin.h	Wed Aug 09 02:11:01 2006 -0700
+++ b/audacious/mainwin.h	Wed Aug 09 02:47:22 2006 -0700
@@ -24,14 +24,14 @@
 
 #include <gtk/gtk.h>
 
-#include "number.h"
-#include "pbutton.h"
-#include "playstatus.h"
-#include "tbutton.h"
-#include "textbox.h"
-#include "svis.h"
-#include "vis.h"
-#include "hslider.h"
+#include "widgets/number.h"
+#include "widgets/pbutton.h"
+#include "widgets/playstatus.h"
+#include "widgets/tbutton.h"
+#include "widgets/textbox.h"
+#include "widgets/svis.h"
+#include "widgets/vis.h"
+#include "widgets/hslider.h"
 
 /* yes, main window size is fixed */
 #define MAINWIN_WIDTH            (gint)275
--- a/audacious/menurow.c	Wed Aug 09 02:11:01 2006 -0700
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,186 +0,0 @@
-/*  BMP - Cross-platform multimedia player
- *  Copyright (C) 2003-2004  BMP development team.
- *
- *  Based on XMMS:
- *  Copyright (C) 1998-2003  XMMS development team.
- *
- *  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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
- */
-
-#include "menurow.h"
-
-#include <glib.h>
-#include <gdk/gdk.h>
-
-#include "main.h"
-#include "menurow.h"
-#include "widget.h"
-
-void
-menurow_draw(Widget * widget)
-{
-    MenuRow *mr = MENU_ROW(widget);
-
-    GdkPixmap *obj = mr->mr_widget.parent;
-
-    if (mr->mr_selected == MENUROW_NONE) {
-        if (cfg.always_show_cb || mr->mr_bpushed)
-            skin_draw_pixmap(bmp_active_skin, obj,
-                             mr->mr_widget.gc,
-                             mr->mr_skin_index,
-                             mr->mr_nx, mr->mr_ny,
-                             mr->mr_widget.x, mr->mr_widget.y, 8, 43);
-        else
-            skin_draw_pixmap(bmp_active_skin, obj,
-                             mr->mr_widget.gc,
-                             mr->mr_skin_index,
-                             mr->mr_nx + 8, mr->mr_ny,
-                             mr->mr_widget.x, mr->mr_widget.y, 8, 43);
-    }
-    else {
-        skin_draw_pixmap(bmp_active_skin, obj,
-                         mr->mr_widget.gc,
-                         mr->mr_skin_index,
-                         mr->mr_sx + ((mr->mr_selected - 1) * 8),
-                         mr->mr_sy, mr->mr_widget.x, mr->mr_widget.y, 8, 43);
-    }
-    if (cfg.always_show_cb || mr->mr_bpushed) {
-        if (mr->mr_always_selected)
-            skin_draw_pixmap(bmp_active_skin, obj,
-                             mr->mr_widget.gc,
-                             mr->mr_skin_index,
-                             mr->mr_sx + 8, mr->mr_sy + 10,
-                             mr->mr_widget.x, mr->mr_widget.y + 10, 8, 8);
-        if (mr->mr_doublesize_selected)
-            skin_draw_pixmap(bmp_active_skin, obj,
-                             mr->mr_widget.gc,
-                             mr->mr_skin_index,
-                             mr->mr_sx + 24, mr->mr_sy + 26,
-                             mr->mr_widget.x, mr->mr_widget.y + 26, 8, 8);
-    }
-
-}
-
-MenuRowItem
-menurow_find_selected(MenuRow * mr, gint x, gint y)
-{
-    MenuRowItem ret = MENUROW_NONE;
-
-    x -= mr->mr_widget.x;
-    y -= mr->mr_widget.y;
-    if (x > 0 && x < 8) {
-        if (y >= 0 && y <= 10)
-            ret = MENUROW_OPTIONS;
-        if (y >= 10 && y <= 17)
-            ret = MENUROW_ALWAYS;
-        if (y >= 18 && y <= 25)
-            ret = MENUROW_FILEINFOBOX;
-        if (y >= 26 && y <= 33)
-            ret = MENUROW_DOUBLESIZE;
-        if (y >= 34 && y <= 42)
-            ret = MENUROW_VISUALIZATION;
-    }
-    return ret;
-}
-
-void
-menurow_button_press(GtkWidget * widget,
-                     GdkEventButton * event,
-                     gpointer data)
-{
-    MenuRow *mr = MENU_ROW(data);
-
-    if (event->button != 1)
-        return;
-
-    if (widget_contains(&mr->mr_widget, event->x, event->y)) {
-        mr->mr_bpushed = TRUE;
-        mr->mr_selected = menurow_find_selected(mr, event->x, event->y);
-
-        widget_draw(WIDGET(mr));
-
-        if (mr->mr_change_callback)
-            mr->mr_change_callback(mr->mr_selected);
-    }
-}
-
-void
-menurow_motion(GtkWidget * widget,
-               GdkEventMotion * event,
-               gpointer data)
-{
-    MenuRow *mr = MENU_ROW(data);
-
-    if (mr->mr_bpushed) {
-        mr->mr_selected = menurow_find_selected(mr, event->x, event->y);
-
-        widget_draw(WIDGET(mr));
-
-        if (mr->mr_change_callback)
-            mr->mr_change_callback(mr->mr_selected);
-    }
-}
-
-void
-menurow_button_release(GtkWidget * widget,
-                       GdkEventButton * event,
-                       gpointer data)
-{
-    MenuRow *mr = MENU_ROW(data);
-
-    if (mr->mr_bpushed) {
-        mr->mr_bpushed = FALSE;
-
-        if (mr->mr_selected == MENUROW_ALWAYS)
-            mr->mr_always_selected = !mr->mr_always_selected;
-
-        if (mr->mr_selected == MENUROW_DOUBLESIZE)
-            mr->mr_doublesize_selected = !mr->mr_doublesize_selected;
-
-        if ((int)(mr->mr_selected) != -1 && mr->mr_release_callback)
-            mr->mr_release_callback(mr->mr_selected);
-
-        mr->mr_selected = MENUROW_NONE;
-
-        widget_draw(WIDGET(mr));
-    }
-}
-
-MenuRow *
-create_menurow(GList ** wlist, GdkPixmap * parent, GdkGC * gc,
-               gint x, gint y, gint nx, gint ny, gint sx, gint sy,
-               void (*ccb) (MenuRowItem),
-               void (*rcb) (MenuRowItem), SkinPixmapId si)
-{
-    MenuRow *mr;
-
-    mr = g_new0(MenuRow, 1);
-    widget_init(&mr->mr_widget, parent, gc, x, y, 8, 43, 1);
-    mr->mr_widget.draw = menurow_draw;
-    mr->mr_widget.button_press_cb = menurow_button_press;
-    mr->mr_widget.motion_cb = menurow_motion;
-    mr->mr_widget.button_release_cb = menurow_button_release;
-    mr->mr_nx = nx;
-    mr->mr_ny = ny;
-    mr->mr_sx = sx;
-    mr->mr_sy = sy;
-    mr->mr_selected = MENUROW_NONE;
-    mr->mr_change_callback = ccb;
-    mr->mr_release_callback = rcb;
-    mr->mr_skin_index = si;
-
-    widget_list_add(wlist, WIDGET(mr));
-    return mr;
-}
--- a/audacious/menurow.h	Wed Aug 09 02:11:01 2006 -0700
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,56 +0,0 @@
-/*  BMP - Cross-platform multimedia player
- *  Copyright (C) 2003-2004  BMP development team.
- *
- *  Based on XMMS:
- *  Copyright (C) 1998-2003  XMMS development team.
- *
- *  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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
- */
-#ifndef MENUROW_H
-#define	MENUROW_H
-
-#include <glib.h>
-#include <gdk/gdk.h>
-
-#include "skin.h"
-#include "widget.h"
-
-typedef enum {
-    MENUROW_NONE, MENUROW_OPTIONS, MENUROW_ALWAYS, MENUROW_FILEINFOBOX,
-    MENUROW_DOUBLESIZE, MENUROW_VISUALIZATION
-} MenuRowItem;
-
-#define MENU_ROW(x)  ((MenuRow *)(x))
-struct _MenuRow {
-    Widget mr_widget;
-    gint mr_nx, mr_ny;
-    gint mr_sx, mr_sy;
-    MenuRowItem mr_selected;
-    gboolean mr_bpushed;
-    gboolean mr_always_selected;
-    gboolean mr_doublesize_selected;
-    void (*mr_change_callback) (MenuRowItem);
-    void (*mr_release_callback) (MenuRowItem);
-    SkinPixmapId mr_skin_index;
-};
-
-typedef struct _MenuRow MenuRow;
-
-MenuRow *create_menurow(GList ** wlist, GdkPixmap * parent, GdkGC * gc,
-                        gint x, gint y, gint nx, gint ny, gint sx, gint sy,
-                        void (*ccb) (MenuRowItem),
-                        void (*rcb) (MenuRowItem), SkinPixmapId si);
-
-#endif
--- a/audacious/monostereo.c	Wed Aug 09 02:11:01 2006 -0700
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,93 +0,0 @@
-/*  BMP - Cross-platform multimedia player
- *  Copyright (C) 2003-2004  BMP development team.
- *
- *  Based on XMMS:
- *  Copyright (C) 1998-2003  XMMS development team.
- *
- *  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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
- */
-
-#include "monostereo.h"
-
-#include <glib.h>
-#include <gdk/gdk.h>
-
-#include "skin.h"
-#include "widget.h"
-
-void
-monostereo_draw(Widget * widget)
-{
-    MonoStereo *ms = (MonoStereo *) widget;
-    GdkPixmap *obj;
-
-    obj = ms->ms_widget.parent;
-
-    switch (ms->ms_num_channels) {
-    case 0:
-        skin_draw_pixmap(bmp_active_skin, obj, ms->ms_widget.gc,
-                         ms->ms_skin_index, 29, 12,
-                         ms->ms_widget.x, ms->ms_widget.y, 27, 12);
-        skin_draw_pixmap(bmp_active_skin, obj, ms->ms_widget.gc,
-                         ms->ms_skin_index, 0, 12,
-                         ms->ms_widget.x + 27, ms->ms_widget.y, 29, 12);
-        break;
-    case 1:
-        skin_draw_pixmap(bmp_active_skin, obj, ms->ms_widget.gc,
-                         ms->ms_skin_index, 29, 0,
-                         ms->ms_widget.x, ms->ms_widget.y, 27, 12);
-        skin_draw_pixmap(bmp_active_skin, obj, ms->ms_widget.gc,
-                         ms->ms_skin_index, 0, 12,
-                         ms->ms_widget.x + 27, ms->ms_widget.y, 29, 12);
-        break;
-    case 2:
-        skin_draw_pixmap(bmp_active_skin, obj, ms->ms_widget.gc,
-                         ms->ms_skin_index, 29, 12,
-                         ms->ms_widget.x, ms->ms_widget.y, 27, 12);
-        skin_draw_pixmap(bmp_active_skin, obj, ms->ms_widget.gc,
-                         ms->ms_skin_index, 0, 0,
-                         ms->ms_widget.x + 27, ms->ms_widget.y, 29, 12);
-        break;
-    }
-}
-
-void
-monostereo_set_num_channels(MonoStereo * ms,
-                            gint nch)
-{
-    if (!ms)
-        return;
-
-    ms->ms_num_channels = nch;
-    widget_draw(WIDGET(ms));
-}
-
-MonoStereo *
-create_monostereo(GList ** wlist,
-                  GdkPixmap * parent,
-                  GdkGC * gc,
-                  gint x, gint y, 
-                  SkinPixmapId si)
-{
-    MonoStereo *ms;
-
-    ms = g_new0(MonoStereo, 1);
-    widget_init(&ms->ms_widget, parent, gc, x, y, 56, 12, 1);
-    ms->ms_widget.draw = monostereo_draw;
-    ms->ms_skin_index = si;
-
-    widget_list_add(wlist, WIDGET(ms));
-    return ms;
-}
--- a/audacious/monostereo.h	Wed Aug 09 02:11:01 2006 -0700
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,43 +0,0 @@
-/*  BMP - Cross-platform multimedia player
- *  Copyright (C) 2003-2004  BMP development team.
- *
- *  Based on XMMS:
- *  Copyright (C) 1998-2003  XMMS development team.
- *
- *  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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
- */
-#ifndef MONOSTEREO_H
-#define MONOSTEREO_H
-
-#include <glib.h>
-#include <gdk/gdk.h>
-
-#include "skin.h"
-#include "widget.h"
-
-#define MONO_STEREO(x)  ((MonoStereo *)(x))
-struct _MonoStereo {
-    Widget ms_widget;
-    gint ms_num_channels;
-    SkinPixmapId ms_skin_index;
-};
-
-typedef struct _MonoStereo MonoStereo;
-
-MonoStereo *create_monostereo(GList ** wlist, GdkPixmap * parent,
-                              GdkGC * gc, gint x, gint y, SkinPixmapId si);
-void monostereo_set_num_channels(MonoStereo * ms, gint nch);
-
-#endif
--- a/audacious/number.c	Wed Aug 09 02:11:01 2006 -0700
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,75 +0,0 @@
-/*  BMP - Cross-platform multimedia player
- *  Copyright (C) 2003-2004  BMP development team.
- *
- *  Based on XMMS:
- *  Copyright (C) 1998-2003  XMMS development team.
- *
- *  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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
- */
-
-#include "number.h"
-
-#include <glib.h>
-#include <gdk/gdk.h>
-
-#include "skin.h"
-
-void
-number_set_number(Number * nu,
-                  gint number)
-{
-    if (number == nu->nu_number)
-        return;
-
-    nu->nu_number = number;
-    widget_draw(WIDGET(nu));
-}
-
-void
-number_draw(Widget * w)
-{
-    Number *nu = NUMBER(w);
-    GdkPixmap *obj;
-
-    obj = nu->nu_widget.parent;
-
-    if (nu->nu_number <= 11)
-        skin_draw_pixmap(bmp_active_skin, obj, nu->nu_widget.gc,
-                         nu->nu_skin_index, nu->nu_number * 9, 0,
-                         nu->nu_widget.x, nu->nu_widget.y, 9, 13);
-    else
-        skin_draw_pixmap(bmp_active_skin, obj, nu->nu_widget.gc,
-                         nu->nu_skin_index, 90, 0, nu->nu_widget.x,
-                         nu->nu_widget.y, 9, 13);
-}
-
-Number *
-create_number(GList ** wlist,
-              GdkPixmap * parent,
-              GdkGC * gc,
-              gint x, gint y,
-              SkinPixmapId si)
-{
-    Number *nu;
-
-    nu = g_new0(Number, 1);
-    widget_init(&nu->nu_widget, parent, gc, x, y, 9, 13, 1);
-    nu->nu_widget.draw = number_draw;
-    nu->nu_number = 10;
-    nu->nu_skin_index = si;
-
-    widget_list_add(wlist, WIDGET(nu));
-    return nu;
-}
--- a/audacious/number.h	Wed Aug 09 02:11:01 2006 -0700
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,43 +0,0 @@
-/*  BMP - Cross-platform multimedia player
- *  Copyright (C) 2003-2004  BMP development team.
- *
- *  Based on XMMS:
- *  Copyright (C) 1998-2003  XMMS development team.
- *
- *  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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
- */
-#ifndef NUMBER_H
-#define NUMBER_H
-
-#include <glib.h>
-#include <gdk/gdk.h>
-
-#include "widget.h"
-#include "skin.h"
-
-#define NUMBER(x) ((Number *)(x))
-struct _Number {
-    Widget nu_widget;
-    gint nu_number;
-    SkinPixmapId nu_skin_index;
-};
-
-typedef struct _Number Number;
-
-void number_set_number(Number * nu, gint number);
-Number *create_number(GList ** wlist, GdkPixmap * parent, GdkGC * gc,
-                      gint x, gint y, SkinPixmapId si);
-
-#endif
--- a/audacious/pbutton.c	Wed Aug 09 02:11:01 2006 -0700
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,194 +0,0 @@
-/*  BMP - Cross-platform multimedia player
- *  Copyright (C) 2003-2004  BMP development team.
- *
- *  Based on XMMS:
- *  Copyright (C) 1998-2003  XMMS development team.
- *
- *  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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
- */
-
-#include "pbutton.h"
-
-#include <glib.h>
-#include <gtk/gtk.h>
-#include <gdk/gdk.h>
-
-#include "skin.h"
-#include "widget.h"
-
-void
-pbutton_draw(PButton * button)
-{
-    GdkPixmap *obj;
-
-    if (button->pb_allow_draw) {
-        obj = button->pb_widget.parent;
-
-        if (button->pb_pressed && button->pb_inside) {
-            skin_draw_pixmap(bmp_active_skin, obj,
-                             button->pb_widget.gc,
-                             button->pb_skin_index2, button->pb_px,
-                             button->pb_py, button->pb_widget.x,
-                             button->pb_widget.y,
-                             button->pb_widget.width,
-                             button->pb_widget.height);
-        }
-        else {
-            skin_draw_pixmap(bmp_active_skin, obj,
-                             button->pb_widget.gc,
-                             button->pb_skin_index1,
-                             button->pb_nx, button->pb_ny,
-                             button->pb_widget.x, button->pb_widget.y,
-                             button->pb_widget.width,
-                             button->pb_widget.height);
-        }
-    }
-}
-
-void
-pbutton_button_press_cb(GtkWidget * widget,
-                        GdkEventButton * event,
-                        PButton * button)
-{
-    if (event->button != 1)
-        return;
-
-    if (widget_contains(&button->pb_widget, event->x, event->y)) {
-        button->pb_pressed = 1;
-        button->pb_inside = 1;
-        widget_draw(WIDGET(button));
-        if (button->pb_push_cb)
-            button->pb_push_cb();
-    }
-}
-
-void
-pbutton_button_release_cb(GtkWidget * widget,
-                          GdkEventButton * event,
-                          PButton * button)
-{
-    if (event->button != 1)
-        return;
-    if (button->pb_inside && button->pb_pressed) {
-        button->pb_inside = 0;
-        widget_draw(WIDGET(button));
-	if (button->pb_release_cb)
-	    button->pb_release_cb();
-    }
-    if (button->pb_pressed)
-        button->pb_pressed = 0;
-}
-
-void
-pbutton_motion_cb(GtkWidget * widget, GdkEventMotion * event,
-                  PButton * button)
-{
-    gint inside;
-
-    if (!button->pb_pressed)
-        return;
-
-    inside = widget_contains(&button->pb_widget, event->x, event->y);
-
-    if (inside != button->pb_inside) {
-        button->pb_inside = inside;
-        widget_draw(WIDGET(button));
-    }
-}
-
-void
-pbutton_set_skin_index(PButton * b, SkinPixmapId si)
-{
-    b->pb_skin_index1 = b->pb_skin_index2 = si;
-}
-
-void
-pbutton_set_skin_index1(PButton * b, SkinPixmapId si)
-{
-    b->pb_skin_index1 = si;
-}
-
-void
-pbutton_set_skin_index2(PButton * b, SkinPixmapId si)
-{
-    b->pb_skin_index2 = si;
-}
-
-void
-pbutton_set_button_data(PButton * b, gint nx, gint ny, gint px, gint py)
-{
-    if (nx > -1)
-        b->pb_nx = nx;
-    if (ny > -1)
-        b->pb_ny = ny;
-    if (px > -1)
-        b->pb_px = px;
-    if (py > -1)
-        b->pb_py = py;
-}
-
-
-PButton *
-create_pbutton_ex(GList ** wlist, GdkPixmap * parent, GdkGC * gc,
-                  gint x, gint y, gint w, gint h, gint nx,
-                  gint ny, gint px, gint py, void (*push_cb) (void),
-		  void (*release_cb) (void),
-                  SkinPixmapId si1, SkinPixmapId si2)
-{
-    PButton *b;
-
-    b = g_new0(PButton, 1);
-    widget_init(&b->pb_widget, parent, gc, x, y, w, h, 1);
-    b->pb_widget.button_press_cb =
-        (void (*)(GtkWidget *, GdkEventButton *, gpointer))
-        pbutton_button_press_cb;
-    b->pb_widget.button_release_cb =
-        (void (*)(GtkWidget *, GdkEventButton *, gpointer))
-        pbutton_button_release_cb;
-    b->pb_widget.motion_cb =
-        (void (*)(GtkWidget *, GdkEventMotion *, gpointer))
-        pbutton_motion_cb;
-
-    b->pb_widget.draw = (void (*)(Widget *)) pbutton_draw;
-    b->pb_nx = nx;
-    b->pb_ny = ny;
-    b->pb_px = px;
-    b->pb_py = py;
-    b->pb_push_cb = push_cb;
-    b->pb_release_cb = release_cb;
-    b->pb_skin_index1 = si1;
-    b->pb_skin_index2 = si2;
-    b->pb_allow_draw = TRUE;
-    b->pb_inside = 0;
-    b->pb_pressed = 0;
-    widget_list_add(wlist, WIDGET(b));
-
-    return b;
-}
-
-PButton *
-create_pbutton(GList ** wlist, GdkPixmap * parent, GdkGC * gc,
-               gint x, gint y, gint w, gint h, gint nx, gint ny,
-               gint px, gint py, void (*cb) (void), SkinPixmapId si)
-{
-    return create_pbutton_ex(wlist, parent, gc, x, y, w, h, nx, ny, px, py,
-                             NULL, cb, si, si);
-}
-
-void
-free_pbutton(PButton * b)
-{
-    g_free(b);
-}
--- a/audacious/pbutton.h	Wed Aug 09 02:11:01 2006 -0700
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,59 +0,0 @@
-/*  BMP - Cross-platform multimedia player
- *  Copyright (C) 2003-2004  BMP development team.
- *
- *  Based on XMMS:
- *  Copyright (C) 1998-2003  XMMS development team.
- *
- *  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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
- */
-#ifndef PBUTTON_H
-#define PBUTTON_H
-
-#include <glib.h>
-#include <gdk/gdk.h>
-
-#include "widget.h"
-#include "skin.h"
-
-#define PBUTTON(x)  ((PButton *)(x))
-struct _PButton {
-    Widget pb_widget;
-    gint pb_nx, pb_ny;
-    gint pb_px, pb_py;
-    gboolean pb_pressed;
-    gboolean pb_inside;
-    gboolean pb_allow_draw;
-    void (*pb_push_cb) (void);
-    void (*pb_release_cb) (void);
-    SkinPixmapId pb_skin_index1, pb_skin_index2;
-};
-
-typedef struct _PButton PButton;
-
-PButton *create_pbutton(GList ** wlist, GdkPixmap * parent, GdkGC * gc,
-                        gint x, gint y, gint w, gint h, gint nx, gint ny,
-                        gint px, gint py, void (*push_cb) (void), SkinPixmapId si);
-PButton *create_pbutton_ex(GList ** wlist, GdkPixmap * parent, GdkGC * gc,
-                           gint x, gint y, gint w, gint h, gint nx,
-                           gint ny, gint px, gint py, void (*push_cb) (void),
-			   void (*release_cb) (void), SkinPixmapId si1,
-			   SkinPixmapId si2);
-void free_pbutton(PButton * b);
-void pbutton_set_skin_index(PButton * b, SkinPixmapId si);
-void pbutton_set_skin_index1(PButton * b, SkinPixmapId si);
-void pbutton_set_skin_index2(PButton * b, SkinPixmapId si);
-void pbutton_set_button_data(PButton * b, gint nx, gint ny, gint px, gint py);
-
-#endif
--- a/audacious/playback.c	Wed Aug 09 02:11:01 2006 -0700
+++ b/audacious/playback.c	Wed Aug 09 02:47:22 2006 -0700
@@ -45,8 +45,6 @@
 #include "output.h"
 #include "playlist.h"
 #include "ui_playlist.h"
-#include "playlist_list.h"
-#include "skin.h"
 #include "skinwin.h"
 #include "urldecode.h"
 #include "util.h"
--- a/audacious/playlist.c	Wed Aug 09 02:11:01 2006 -0700
+++ b/audacious/playlist.c	Wed Aug 09 02:47:22 2006 -0700
@@ -50,8 +50,6 @@
 #include "playback.h"
 #include "playlist.h"
 #include "ui_playlist.h"
-#include "playlist_list.h"
-#include "skin.h"
 #include "urldecode.h"
 #include "util.h"
 #include "ui_fileinfo.h"
--- a/audacious/playlist_list.c	Wed Aug 09 02:11:01 2006 -0700
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,954 +0,0 @@
-/*  Audacious - Cross-platform multimedia player
- *  Copyright (C) 2005-2006  Audacious development team.
- *
- *  BMP - Cross-platform multimedia player
- *  Copyright (C) 2003-2004  BMP development team.
- *
- *  Based on XMMS:
- *  Copyright (C) 1998-2003  XMMS development team.
- *
- *  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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
- */
-
-/*
- *  A note about Pango and some funky spacey fonts: Weirdly baselined
- *  fonts, or fonts with weird ascents or descents _will_ display a
- *  little bit weird in the playlist widget, but the display engine
- *  won't make it look too bad, just a little deranged.  I honestly
- *  don't think it's worth fixing (around...), it doesn't have to be
- *  perfectly fitting, just the general look has to be ok, which it
- *  IMHO is.
- *
- *  A second note: The numbers aren't perfectly aligned, but in the
- *  end it looks better when using a single Pango layout for each
- *  number.
- */
-
-#include "playlist_list.h"
-
-#include <stdlib.h>
-#include <string.h>
-
-#include "main.h"
-#include "input.h"
-#include "playback.h"
-#include "playlist.h"
-#include "ui_playlist.h"
-#include "util.h"
-
-#include "debug.h"
-
-static PangoFontDescription *playlist_list_font = NULL;
-static gint ascent, descent, width_delta_digit_one;
-static gboolean has_slant;
-static guint padding;
-
-/* FIXME: the following globals should not be needed. */
-static gint width_approx_letters;
-static gint width_colon, width_colon_third;
-static gint width_approx_digits, width_approx_digits_half;
-
-GdkPixmap *rootpix;
-
-void playlist_list_draw(Widget * w);
-
-/* Sort of stolen from XChat, but not really, as theres uses Xlib */
-static void
-shade_gdkimage_generic (GdkVisual *visual, GdkImage *ximg, int bpl, int w, int h, int rm, int gm, int bm, int bg)
-{
-	int x, y;
-	int bgr = (256 - rm) * (bg & visual->red_mask);
-	int bgg = (256 - gm) * (bg & visual->green_mask);
-	int bgb = (256 - bm) * (bg & visual->blue_mask);
-
-	for (x = 0; x < w; x++)
-	{
-		for (y = 0; y < h; y++)
-		{
-			unsigned long pixel = gdk_image_get_pixel (ximg, x, y);
-			int r, g, b;
-
-			r = rm * (pixel & visual->red_mask) + bgr;
-			g = gm * (pixel & visual->green_mask) + bgg;
-			b = bm * (pixel & visual->blue_mask) + bgb;
-
-			gdk_image_put_pixel (ximg, x, y,
-				((r >> 8) & visual->red_mask) |
-				((g >> 8) & visual->green_mask) |
-				((b >> 8) & visual->blue_mask));
-		}
-	}
-}
-
-/* and this is definately mine... -nenolod */
-GdkPixmap *
-shade_pixmap(GdkPixmap *in, gint x, gint y, gint x_offset, gint y_offset, gint w, gint h, GdkColor *shade_color)
-{
-	GdkImage *ximg;
-	GdkPixmap *p = gdk_pixmap_new(in, w, h, -1);
-	GdkGC *gc = gdk_gc_new(p);
-
-        gdk_draw_pixmap(p, gc, in, x, y, 0, 0, w, h);
-
-	gdk_error_trap_push();
-
-	ximg = gdk_drawable_copy_to_image(in, NULL, x, y, 0, 0, w, h);	/* copy */
-
-	gdk_error_trap_pop();
-
-	shade_gdkimage_generic(gdk_drawable_get_visual(GDK_WINDOW(playlistwin->window)),
-		ximg, ximg->bpl, w, h, 60, 60, 60, shade_color->pixel);
-
-	gdk_draw_image(p, gc, ximg, 0, 0, x, y, w, h);
-
-	g_object_unref(gc);
-
-	return p;
-}
-
-#ifdef GDK_WINDOWING_X11
-
-#include <gdk/gdkx.h>
-#include <X11/Xlib.h>
-#include <X11/Xatom.h>
-
-GdkDrawable *get_transparency_pixmap(void)
-{
-	GdkDrawable *root;
-	XID *pixmaps;
-	GdkAtom prop_type;
-	gint prop_size;
-	GdkPixmap *pixmap;
-	gboolean ret;
-
-	root = gdk_get_default_root_window();
-
-	pixmap = NULL;
-	pixmaps = NULL;
-
-	gdk_error_trap_push();
-
-	ret = gdk_property_get(root, gdk_atom_intern("_XROOTPMAP_ID", TRUE),
-			0, 0, INT_MAX - 3,
-			FALSE,
-			&prop_type, NULL, &prop_size,
-			(guchar **) &pixmaps);
-
-	gdk_error_trap_pop();
-
-	if ((ret == TRUE) && (prop_type == GDK_TARGET_PIXMAP) && (prop_size >= sizeof(XID)) && (pixmaps != NULL))
-	{
-		pixmap = gdk_pixmap_foreign_new_for_display(gdk_drawable_get_display(root),
-			pixmaps[0]);
-
-		if (pixmaps != NULL)
-			g_free(pixmaps);
-	}
-
-	return GDK_DRAWABLE(pixmap);
-}
-
-static GdkFilterReturn
-root_event_cb (GdkXEvent *xev, GdkEventProperty *event, gpointer data)
-{
-        static Atom at = None;
-        XEvent *xevent = (XEvent *)xev;
-
-        if (xevent->type == PropertyNotify)
-        {
-                if (at == None)
-                        at = XInternAtom (xevent->xproperty.display, "_XROOTPMAP_ID", True);
-
-                if (at == xevent->xproperty.atom)
-		{
-                        rootpix = shade_pixmap(get_transparency_pixmap(), 0, 0, 0, 0, gdk_screen_width(), gdk_screen_height(),
-                            skin_get_color(bmp_active_skin, SKIN_PLEDIT_NORMALBG));
-
-			if (cfg.playlist_transparent)
-			{
-				playlistwin_update_list();
-				draw_playlist_window(TRUE);
-			}
-		}
-        }
-
-        return GDK_FILTER_CONTINUE;
-}
-
-#else
-
-GdkPixmap *get_transparency_pixmap(void)
-{
-    return NULL;
-}
-
-#endif
-
-static gboolean
-playlist_list_auto_drag_down_func(gpointer data)
-{
-    PlayList_List *pl = data;
-
-    if (pl->pl_auto_drag_down) {
-        playlist_list_move_down(pl);
-        pl->pl_first++;
-        playlistwin_update_list();
-        return TRUE;
-    }
-    return FALSE;
-}
-
-static gboolean
-playlist_list_auto_drag_up_func(gpointer data)
-{
-    PlayList_List *pl = data;
-
-    if (pl->pl_auto_drag_up) {
-        playlist_list_move_up(pl);
-        pl->pl_first--;
-        playlistwin_update_list();
-        return TRUE;
-
-    }
-    return FALSE;
-}
-
-void
-playlist_list_move_up(PlayList_List * pl)
-{
-    GList *list;
-
-    PLAYLIST_LOCK();
-    if ((list = playlist_get()) == NULL) {
-        PLAYLIST_UNLOCK();
-        return;
-    }
-    if (PLAYLIST_ENTRY(list->data)->selected) {
-        /* We are at the top */
-        PLAYLIST_UNLOCK();
-        return;
-    }
-    while (list) {
-        if (PLAYLIST_ENTRY(list->data)->selected)
-            glist_moveup(list);
-        list = g_list_next(list);
-    }
-    PLAYLIST_UNLOCK();
-    if (pl->pl_prev_selected != -1)
-        pl->pl_prev_selected--;
-    if (pl->pl_prev_min != -1)
-        pl->pl_prev_min--;
-    if (pl->pl_prev_max != -1)
-        pl->pl_prev_max--;
-}
-
-void
-playlist_list_move_down(PlayList_List * pl)
-{
-    GList *list;
-
-    PLAYLIST_LOCK();
-
-    if (!(list = g_list_last(playlist_get()))) {
-        PLAYLIST_UNLOCK();
-        return;
-    }
-
-    if (PLAYLIST_ENTRY(list->data)->selected) {
-        /* We are at the bottom */
-        PLAYLIST_UNLOCK();
-        return;
-    }
-
-    while (list) {
-        if (PLAYLIST_ENTRY(list->data)->selected)
-            glist_movedown(list);
-        list = g_list_previous(list);
-    }
-
-    PLAYLIST_UNLOCK();
-
-    if (pl->pl_prev_selected != -1)
-        pl->pl_prev_selected++;
-    if (pl->pl_prev_min != -1)
-        pl->pl_prev_min++;
-    if (pl->pl_prev_max != -1)
-        pl->pl_prev_max++;
-}
-
-static void
-playlist_list_button_press_cb(GtkWidget * widget,
-                              GdkEventButton * event,
-                              PlayList_List * pl)
-{
-    gint nr, y;
-
-    if (event->button == 1 && pl->pl_fheight &&
-        widget_contains(&pl->pl_widget, event->x, event->y)) {
-
-        y = event->y - pl->pl_widget.y;
-        nr = (y / pl->pl_fheight) + pl->pl_first;
-
-        if (nr >= playlist_get_length())
-            nr = playlist_get_length() - 1;
-
-        if (!(event->state & GDK_CONTROL_MASK))
-            playlist_select_all(FALSE);
-
-        if (event->state & GDK_SHIFT_MASK && pl->pl_prev_selected != -1) {
-            playlist_select_range(pl->pl_prev_selected, nr, TRUE);
-            pl->pl_prev_min = pl->pl_prev_selected;
-            pl->pl_prev_max = nr;
-            pl->pl_drag_pos = nr - pl->pl_first;
-        }
-        else {
-            if (playlist_select_invert(nr)) {
-                if (event->state & GDK_CONTROL_MASK) {
-                    if (pl->pl_prev_min == -1) {
-                        pl->pl_prev_min = pl->pl_prev_selected;
-                        pl->pl_prev_max = pl->pl_prev_selected;
-                    }
-                    if (nr < pl->pl_prev_min)
-                        pl->pl_prev_min = nr;
-                    else if (nr > pl->pl_prev_max)
-                        pl->pl_prev_max = nr;
-                }
-                else
-                    pl->pl_prev_min = -1;
-                pl->pl_prev_selected = nr;
-                pl->pl_drag_pos = nr - pl->pl_first;
-            }
-        }
-        if (event->type == GDK_2BUTTON_PRESS) {
-            /*
-             * Ungrab the pointer to prevent us from
-             * hanging on to it during the sometimes slow
-             * bmp_playback_initiate().
-             */
-            gdk_pointer_ungrab(GDK_CURRENT_TIME);
-            gdk_flush();
-            playlist_set_position(nr);
-            if (!bmp_playback_get_playing())
-                bmp_playback_initiate();
-        }
-
-        pl->pl_dragging = TRUE;
-        playlistwin_update_list();
-    }
-}
-
-gint
-playlist_list_get_playlist_position(PlayList_List * pl,
-                                    gint x,
-                                    gint y)
-{
-    gint iy, length;
-
-    if (!widget_contains(WIDGET(pl), x, y) || !pl->pl_fheight)
-        return -1;
-
-    if ((length = playlist_get_length()) == 0)
-        return -1;
-    iy = y - pl->pl_widget.y;
-
-    return (MIN((iy / pl->pl_fheight) + pl->pl_first, length - 1));
-}
-
-static void
-playlist_list_motion_cb(GtkWidget * widget,
-                        GdkEventMotion * event,
-                        PlayList_List * pl)
-{
-    gint nr, y, off, i;
-
-    if (pl->pl_dragging) {
-        y = event->y - pl->pl_widget.y;
-        nr = (y / pl->pl_fheight);
-        if (nr < 0) {
-            nr = 0;
-            if (!pl->pl_auto_drag_up) {
-                pl->pl_auto_drag_up = TRUE;
-                pl->pl_auto_drag_up_tag =
-                    gtk_timeout_add(100, playlist_list_auto_drag_up_func, pl);
-            }
-        }
-        else if (pl->pl_auto_drag_up)
-            pl->pl_auto_drag_up = FALSE;
-
-        if (nr >= pl->pl_num_visible) {
-            nr = pl->pl_num_visible - 1;
-            if (!pl->pl_auto_drag_down) {
-                pl->pl_auto_drag_down = TRUE;
-                pl->pl_auto_drag_down_tag =
-                    gtk_timeout_add(100, playlist_list_auto_drag_down_func,
-                                    pl);
-            }
-        }
-        else if (pl->pl_auto_drag_down)
-            pl->pl_auto_drag_down = FALSE;
-
-        off = nr - pl->pl_drag_pos;
-        if (off) {
-            for (i = 0; i < abs(off); i++) {
-                if (off < 0)
-                    playlist_list_move_up(pl);
-                else
-                    playlist_list_move_down(pl);
-
-            }
-            playlistwin_update_list();
-        }
-        pl->pl_drag_pos = nr;
-    }
-}
-
-static void
-playlist_list_button_release_cb(GtkWidget * widget,
-                                GdkEventButton * event,
-                                PlayList_List * pl)
-{
-    pl->pl_dragging = FALSE;
-    pl->pl_auto_drag_down = FALSE;
-    pl->pl_auto_drag_up = FALSE;
-}
-
-static void
-playlist_list_draw_string(PlayList_List * pl,
-                          PangoFontDescription * font,
-                          gint line,
-                          gint width,
-                          const gchar * text,
-                          guint ppos)
-{
-    guint plist_length_int;
-
-    PangoLayout *layout;
-
-    REQUIRE_STATIC_LOCK(playlist);
-
-    if (cfg.show_numbers_in_pl) {
-        gchar *pos_string = g_strdup_printf(cfg.show_separator_in_pl == TRUE ? "%d" : "%d.", ppos);
-        plist_length_int =
-            gint_count_digits(playlist_get_length_nolock()) + !cfg.show_separator_in_pl + 1; /* cf.show_separator_in_pl will be 0 if false */
-
-        padding = plist_length_int;
-        padding = ((padding + 1) * width_approx_digits);
-
-        layout = gtk_widget_create_pango_layout(playlistwin, pos_string);
-        pango_layout_set_font_description(layout, playlist_list_font);
-        pango_layout_set_width(layout, plist_length_int * 100);
-
-        pango_layout_set_alignment(layout, PANGO_ALIGN_LEFT);
-        gdk_draw_layout(pl->pl_widget.parent, pl->pl_widget.gc,
-                        pl->pl_widget.x +
-                        (width_approx_digits *
-                         (-1 + plist_length_int - strlen(pos_string))) +
-                        (width_approx_digits / 4),
-                        pl->pl_widget.y + (line - 1) * pl->pl_fheight +
-                        ascent + abs(descent), layout);
-        g_free(pos_string);
-        g_object_unref(layout);
-
-        if (!cfg.show_separator_in_pl)
-            padding -= (width_approx_digits * 1.5);
-    }
-    else {
-        padding = 3;
-    }
-
-    width -= padding;
-
-    layout = gtk_widget_create_pango_layout(playlistwin, text);
-
-    pango_layout_set_font_description(layout, playlist_list_font);
-    pango_layout_set_width(layout, width * PANGO_SCALE);
-    pango_layout_set_single_paragraph_mode(layout, TRUE);
-    pango_layout_set_ellipsize(layout, PANGO_ELLIPSIZE_END);
-    gdk_draw_layout(pl->pl_widget.parent, pl->pl_widget.gc,
-                    pl->pl_widget.x + padding + (width_approx_letters / 4),
-                    pl->pl_widget.y + (line - 1) * pl->pl_fheight +
-                    ascent + abs(descent), layout);
-
-    g_object_unref(layout);
-}
-
-void
-playlist_list_draw(Widget * w)
-{
-    PlayList_List *pl = PLAYLIST_LIST(w);
-    GList *list;
-    GdkGC *gc;
-    GdkPixmap *obj;
-    PangoLayout *layout;
-    gchar *title;
-    gint width, height;
-    gint i, max_first;
-    guint padding, padding_dwidth, padding_plength;
-    guint max_time_len = 0;
-    gfloat queue_tailpadding = 0;
-    gint tpadding; 
-    gsize tpadding_dwidth = 0;
-    gint x, y;
-    guint tail_width;
-    guint tail_len;
-
-    gchar tail[100];
-    gchar queuepos[255];
-    gchar length[40];
-
-    gchar **frags;
-    gchar *frag0;
-
-    gint plw_w, plw_h;
-
-    GdkRectangle *playlist_rect;
-
-    gc = pl->pl_widget.gc;
-
-    width = pl->pl_widget.width;
-    height = pl->pl_widget.height;
-
-    obj = pl->pl_widget.parent;
-
-    gtk_window_get_size(GTK_WINDOW(playlistwin), &plw_w, &plw_h);
-
-    playlist_rect = g_new0(GdkRectangle, 1);
-
-    playlist_rect->x = 0;
-    playlist_rect->y = 0;
-    playlist_rect->width = plw_w - 17;
-    playlist_rect->height = plw_h - 36;
-
-    gdk_gc_set_clip_origin(gc, 31, 58);
-    gdk_gc_set_clip_rectangle(gc, playlist_rect);
-
-    if (cfg.playlist_transparent == FALSE)
-    {
-        gdk_gc_set_foreground(gc,
-                              skin_get_color(bmp_active_skin,
-                                             SKIN_PLEDIT_NORMALBG));
-        gdk_draw_rectangle(obj, gc, TRUE, pl->pl_widget.x, pl->pl_widget.y,
-                              width, height);
-    }
-    else
-    {
-	if (!rootpix)
-           rootpix = shade_pixmap(get_transparency_pixmap(), 0, 0, 0, 0, gdk_screen_width(), gdk_screen_height(), 
-    			    skin_get_color(bmp_active_skin, SKIN_PLEDIT_NORMALBG));
-        gdk_draw_pixmap(obj, gc, rootpix, cfg.playlist_x + pl->pl_widget.x,
-                    cfg.playlist_y + pl->pl_widget.y, pl->pl_widget.x, pl->pl_widget.y,
-                    width, height);
-    }
-
-    if (!playlist_list_font) {
-        g_critical("Couldn't open playlist font");
-        return;
-    }
-
-    pl->pl_fheight = (ascent + abs(descent));
-    pl->pl_num_visible = height / pl->pl_fheight;
-
-    max_first = playlist_get_length() - pl->pl_num_visible;
-    max_first = MAX(max_first, 0);
-
-    pl->pl_first = CLAMP(pl->pl_first, 0, max_first);
-
-    PLAYLIST_LOCK();
-    list = playlist_get();
-    list = g_list_nth(list, pl->pl_first);
-
-    /* It sucks having to run the iteration twice but this is the only
-       way you can reliably get the maximum width so we can get our
-       playlist nice and aligned... -- plasmaroo */
-
-    for (i = pl->pl_first;
-         list && i < pl->pl_first + pl->pl_num_visible;
-         list = g_list_next(list), i++) {
-        PlaylistEntry *entry = list->data;
-
-        if (entry->length != -1)
-        {
-            g_snprintf(length, sizeof(length), "%d:%-2.2d",
-                       entry->length / 60000, (entry->length / 1000) % 60);
-            tpadding_dwidth = MAX(tpadding_dwidth, strlen(length));
-        }
-    }
-
-    /* Reset */
-    list = playlist_get();
-    list = g_list_nth(list, pl->pl_first);
-
-    for (i = pl->pl_first;
-         list && i < pl->pl_first + pl->pl_num_visible;
-         list = g_list_next(list), i++) {
-        gint pos;
-        PlaylistEntry *entry = list->data;
-
-        if (entry->selected) {
-            gdk_gc_set_foreground(gc,
-                                  skin_get_color(bmp_active_skin,
-                                                 SKIN_PLEDIT_SELECTEDBG));
-            gdk_draw_rectangle(obj, gc, TRUE, pl->pl_widget.x,
-                               pl->pl_widget.y +
-                               ((i - pl->pl_first) * pl->pl_fheight),
-                               width, pl->pl_fheight);
-        }
-
-        /* FIXME: entry->title should NEVER be NULL, and there should
-           NEVER be a need to do a UTF-8 conversion. Playlist title
-           strings should be kept properly. */
-
-        if (!entry->title) {
-            gchar *basename = g_path_get_basename(entry->filename);
-            title = filename_to_utf8(basename);
-            g_free(basename);
-        }
-        else
-            title = str_to_utf8(entry->title);
-
-        pos = playlist_get_queue_position(entry);
-
-        tail[0] = 0;
-        queuepos[0] = 0;
-        length[0] = 0;
-
-        if (pos != -1)
-            g_snprintf(queuepos, sizeof(queuepos), "%d", pos + 1);
-
-        if (entry->length != -1)
-        {
-            g_snprintf(length, sizeof(length), "%d:%-2.2d",
-                       entry->length / 60000, (entry->length / 1000) % 60);
-        }
-
-        strncat(tail, length, sizeof(tail));
-        tail_len = strlen(tail);
-
-        max_time_len = MAX(max_time_len, tail_len);
-
-        if (pos != -1 && tpadding_dwidth <= 0)
-            tail_width = width - (width_approx_digits * (strlen(queuepos) + 2.25));
-        else if (pos != -1)
-            tail_width = width - (width_approx_digits * (tpadding_dwidth + strlen(queuepos) + 4));
-        else if (tpadding_dwidth > 0)
-            tail_width = width - (width_approx_digits * (tpadding_dwidth + 2.5));
-        else
-            tail_width = width;
-
-        if (i == playlist_get_position_nolock())
-            gdk_gc_set_foreground(gc,
-                                  skin_get_color(bmp_active_skin,
-                                                 SKIN_PLEDIT_CURRENT));
-        else
-            gdk_gc_set_foreground(gc,
-                                  skin_get_color(bmp_active_skin,
-                                                 SKIN_PLEDIT_NORMAL));
-        playlist_list_draw_string(pl, playlist_list_font,
-                                  i - pl->pl_first, tail_width, title,
-                                  i + 1);
-
-        x = pl->pl_widget.x + width - width_approx_digits * 2;
-        y = pl->pl_widget.y + ((i - pl->pl_first) -
-                               1) * pl->pl_fheight + ascent;
-
-        frags = NULL;
-        frag0 = NULL;
-
-        if ((strlen(tail) > 0) && (tail != NULL)) {
-            frags = g_strsplit(tail, ":", 0);
-            frag0 = g_strconcat(frags[0], ":", NULL);
-
-            layout = gtk_widget_create_pango_layout(playlistwin, frags[1]);
-            pango_layout_set_font_description(layout, playlist_list_font);
-            pango_layout_set_width(layout, tail_len * 100);
-            pango_layout_set_alignment(layout, PANGO_ALIGN_LEFT);
-            gdk_draw_layout(obj, gc, x - (0.5 * width_approx_digits),
-                            y + abs(descent), layout);
-            g_object_unref(layout);
-
-            layout = gtk_widget_create_pango_layout(playlistwin, frag0);
-            pango_layout_set_font_description(layout, playlist_list_font);
-            pango_layout_set_width(layout, tail_len * 100);
-            pango_layout_set_alignment(layout, PANGO_ALIGN_RIGHT);
-            gdk_draw_layout(obj, gc, x - (0.75 * width_approx_digits),
-                            y + abs(descent), layout);
-            g_object_unref(layout);
-
-            g_free(frag0);
-            g_strfreev(frags);
-        }
-
-        if (pos != -1) {
-
-            /* DON'T remove the commented code yet please     -- Milosz */
-
-            if (tpadding_dwidth > 0)
-                queue_tailpadding = tpadding_dwidth + 1;
-            else
-                queue_tailpadding = -0.75;
-
-            gdk_draw_rectangle(obj, gc, FALSE,
-                               x -
-                               (((queue_tailpadding +
-                                  strlen(queuepos)) *
-                                 width_approx_digits) +
-                                (width_approx_digits / 4)),
-                               y + abs(descent),
-                               (strlen(queuepos)) *
-                               width_approx_digits +
-                               (width_approx_digits / 2),
-                               pl->pl_fheight - 2);
-
-            layout =
-                gtk_widget_create_pango_layout(playlistwin, queuepos);
-            pango_layout_set_font_description(layout, playlist_list_font);
-            pango_layout_set_alignment(layout, PANGO_ALIGN_CENTER);
-
-            gdk_draw_layout(obj, gc,
-                            x -
-                            ((queue_tailpadding +
-                              strlen(queuepos)) * width_approx_digits) +
-                            (width_approx_digits / 4),
-                            y + abs(descent), layout);
-            g_object_unref(layout);
-        }
-
-        g_free(title);
-    }
-
-
-    /*
-     * Drop target hovering over the playlist, so draw some hint where the
-     * drop will occur.
-     *
-     * This is (currently? unfixably?) broken when dragging files from Qt/KDE apps,
-     * probably due to DnD signaling problems (actually i have no clue).
-     *
-     */
-
-    if (pl->pl_drag_motion) {
-        guint pos, plength, lpadding;
-	gint x, y, plx, ply;
-
-        if (cfg.show_numbers_in_pl) {
-            lpadding = gint_count_digits(playlist_get_length_nolock()) + 1;
-            lpadding = ((lpadding + 1) * width_approx_digits);
-        }
-        else {
-            lpadding = 3;
-        };
-
-        /* We already hold the mutex and have the playlist locked, so call
-           the non-locking function. */
-        plength = playlist_get_length_nolock();
-
-        x = pl->drag_motion_x;
-        y = pl->drag_motion_y;
-
-        plx = pl->pl_widget.x;
-        ply = pl->pl_widget.y;
-
-        if ((x > pl->pl_widget.x) && !(x > pl->pl_widget.width)) {
-
-            if ((y > pl->pl_widget.y)
-                && !(y > (pl->pl_widget.height + ply))) {
-
-                pos = ((y - ((Widget *) pl)->y) / pl->pl_fheight) +
-                    pl->pl_first;
-
-                if (pos > (plength)) {
-                    pos = plength;
-                }
-
-                gdk_gc_set_foreground(gc,
-                                      skin_get_color(bmp_active_skin,
-                                                     SKIN_PLEDIT_CURRENT));
-
-                gdk_draw_line(obj, gc, pl->pl_widget.x,
-			      pl->pl_widget.y + ((pos - pl->pl_first) * pl->pl_fheight),
-                              pl->pl_widget.width + pl->pl_widget.x - 1,
-                              pl->pl_widget.y +
-                              ((pos - pl->pl_first) * pl->pl_fheight));
-            }
-
-        }
-
-        /* When dropping on the borders of the playlist, outside the text area,
-         * files get appended at the end of the list. Show that too.
-         */
-
-        if ((y < ply) || (y > pl->pl_widget.height + ply)) {
-            if ((y >= 0) || (y <= (pl->pl_widget.height + ply))) {
-                pos = plength;
-                gdk_gc_set_foreground(gc,
-                                      skin_get_color(bmp_active_skin,
-                                                     SKIN_PLEDIT_CURRENT));
-
-                gdk_draw_line(obj, gc, pl->pl_widget.x,
-                              pl->pl_widget.y +
-                              ((pos - pl->pl_first) * pl->pl_fheight),
-                              pl->pl_widget.width + pl->pl_widget.x - 1,
-                              pl->pl_widget.y +
-                              ((pos - pl->pl_first) * pl->pl_fheight));
-
-            }
-        }
-    }
-
-    gdk_gc_set_foreground(gc,
-                          skin_get_color(bmp_active_skin,
-                                         SKIN_PLEDIT_NORMAL));
-
-    if (cfg.show_numbers_in_pl) {
-
-        padding_plength = playlist_get_length_nolock();
-
-        if (padding_plength == 0) {
-            padding_dwidth = 0;
-        }
-        else {
-            padding_dwidth = gint_count_digits(playlist_get_length_nolock());
-        }
-
-        padding =
-            (padding_dwidth *
-             width_approx_digits) + width_approx_digits;
-
-
-        /* For italic or oblique fonts we add another half of the
-         * approximate width */
-        if (has_slant)
-            padding += width_approx_digits_half;
-
-        if (cfg.show_separator_in_pl) {
-            gdk_draw_line(obj, gc,
-                          pl->pl_widget.x + padding,
-                          pl->pl_widget.y,
-                          pl->pl_widget.x + padding,
-                          pl->pl_widget.y + pl->pl_widget.height - 1);
-        }
-    }
-
-    if (tpadding_dwidth != 0)
-    {
-        tpadding = (tpadding_dwidth * width_approx_digits) + (width_approx_digits * 1.5);
-
-        if (has_slant)
-            tpadding += width_approx_digits_half;
-
-        if (cfg.show_separator_in_pl) {
-            gdk_draw_line(obj, gc,
-                          pl->pl_widget.x + pl->pl_widget.width - tpadding,
-                          pl->pl_widget.y,
-                          pl->pl_widget.x + pl->pl_widget.width - tpadding,
-                          pl->pl_widget.y + pl->pl_widget.height - 1);
-        }
-    }
-
-    gdk_gc_set_clip_origin(gc, 0, 0);
-    gdk_gc_set_clip_rectangle(gc, NULL);
-
-    PLAYLIST_UNLOCK();
-
-    gdk_flush();
-
-    g_free(playlist_rect);
-}
-
-
-PlayList_List *
-create_playlist_list(GList ** wlist,
-                     GdkPixmap * parent,
-                     GdkGC * gc,
-                     gint x, gint y,
-                     gint w, gint h)
-{
-    PlayList_List *pl;
-
-    pl = g_new0(PlayList_List, 1);
-    widget_init(&pl->pl_widget, parent, gc, x, y, w, h, TRUE);
-
-    pl->pl_widget.button_press_cb =
-        (WidgetButtonPressFunc) playlist_list_button_press_cb;
-    pl->pl_widget.button_release_cb =
-        (WidgetButtonReleaseFunc) playlist_list_button_release_cb;
-    pl->pl_widget.motion_cb = (WidgetMotionFunc) playlist_list_motion_cb;
-    pl->pl_widget.draw = playlist_list_draw;
-
-    pl->pl_prev_selected = -1;
-    pl->pl_prev_min = -1;
-    pl->pl_prev_max = -1;
-
-    widget_list_add(wlist, WIDGET(pl));
-
-#ifdef GDK_WINDOWING_X11
-    gdk_window_set_events (gdk_get_default_root_window(), GDK_PROPERTY_CHANGE_MASK);
-    gdk_window_add_filter (gdk_get_default_root_window(), (GdkFilterFunc)root_event_cb, pl);
-#endif
-
-    return pl;
-}
-
-void
-playlist_list_set_font(const gchar * font)
-{
-
-    /* Welcome to bad hack central 2k3 */
-
-    gchar *font_lower;
-    gint width_temp;
-    gint width_temp_0;
-
-    playlist_list_font = pango_font_description_from_string(font);
-
-    text_get_extents(font,
-                     "AaBbCcDdEeFfGgHhIiJjKkLlMmNnOoPpQqRrSsTtUuVvWwXxYyZz ",
-                     &width_approx_letters, NULL, &ascent, &descent);
-
-    width_approx_letters = (width_approx_letters / 53);
-
-    /* Experimental: We don't weigh the 1 into total because it's width is almost always
-     * very different from the rest
-     */
-    text_get_extents(font, "023456789", &width_approx_digits, NULL, NULL,
-                     NULL);
-    width_approx_digits = (width_approx_digits / 9);
-
-    /* Precache some often used calculations */
-    width_approx_digits_half = width_approx_digits / 2;
-
-    /* FIXME: We assume that any other number is broader than the "1" */
-    text_get_extents(font, "1", &width_temp, NULL, NULL, NULL);
-    text_get_extents(font, "2", &width_temp_0, NULL, NULL, NULL);
-
-    if (abs(width_temp_0 - width_temp) < 2) {
-        width_delta_digit_one = 0;
-    }
-    else {
-        width_delta_digit_one = ((width_temp_0 - width_temp) / 2) + 2;
-    }
-
-    text_get_extents(font, ":", &width_colon, NULL, NULL, NULL);
-    width_colon_third = width_colon / 4;
-
-    font_lower = g_utf8_strdown(font, strlen(font));
-    /* This doesn't take any i18n into account, but i think there is none with TTF fonts
-     * FIXME: This can probably be retrieved trough Pango too
-     */
-    has_slant = g_strstr_len(font_lower, strlen(font_lower), "oblique")
-        || g_strstr_len(font_lower, strlen(font_lower), "italic");
-
-    g_free(font_lower);
-}
--- a/audacious/playlist_list.h	Wed Aug 09 02:11:01 2006 -0700
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,56 +0,0 @@
-/*  BMP - Cross-platform multimedia player
- *  Copyright (C) 2003-2004  BMP development team.
- *
- *  Based on XMMS:
- *  Copyright (C) 1998-2003  XMMS development team.
- *
- *  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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
- */
-
-#ifndef PLAYLIST_LIST_H
-#define PLAYLIST_LIST_H
-
-#include <glib.h>
-#include <gtk/gtk.h>
-#include <gdk/gdk.h>
-
-#include "widget.h"
-
-#define PLAYLIST_LIST(x)    ((PlayList_List *)(x))
-struct _PlayList_List {
-    Widget pl_widget;
-    gint pl_first, pl_fheight, pl_prev_selected, pl_prev_min, pl_prev_max;
-    gint pl_num_visible, pl_drag_pos;
-    gboolean pl_dragging, pl_auto_drag_down, pl_auto_drag_up;
-    gint pl_auto_drag_up_tag, pl_auto_drag_down_tag;
-    gboolean pl_drag_motion;
-    gint drag_motion_x, drag_motion_y;
-    gboolean pl_tooltips;
-};
-
-typedef struct _PlayList_List PlayList_List;
-
-PlayList_List *create_playlist_list(GList ** wlist, GdkPixmap * parent,
-                                    GdkGC * gc, gint x, gint y, gint w,
-                                    gint h);
-void playlist_list_move_up(PlayList_List * pl);
-void playlist_list_move_down(PlayList_List * pl);
-int playlist_list_get_playlist_position(PlayList_List * pl, gint x, gint y);
-void playlist_list_set_font(const gchar * font);
-GdkPixmap *rootpix;
-GdkPixmap *shade_pixmap(GdkDrawable *in, gint x, gint y, gint x_offset, gint y_offset, gint w, gint h, GdkColor *shade_color);
-GdkDrawable *get_transparency_pixmap(void);
-
-#endif
--- a/audacious/playlist_slider.c	Wed Aug 09 02:11:01 2006 -0700
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,168 +0,0 @@
-/*  BMP - Cross-platform multimedia player
- *  Copyright (C) 2003-2004  BMP development team.
- *
- *  Based on XMMS:
- *  Copyright (C) 1998-2003  XMMS development team.
- *
- *  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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
- */
-
-#include "playlist_slider.h"
-
-#include <glib.h>
-
-#include "playlist.h"
-#include "ui_playlist.h"
-#include "skin.h"
-#include "widget.h"
-
-void
-playlistslider_draw(Widget * w)
-{
-    PlaylistSlider *ps = (PlaylistSlider *) w;
-    GdkPixmap *obj;
-    gint y, skinx;
-
-    g_return_if_fail(ps != NULL);
-    g_return_if_fail(ps->ps_list != NULL);
-
-    if (playlist_get_length() > ps->ps_list->pl_num_visible)
-        y = (ps->ps_list->pl_first * (ps->ps_widget.height - 19)) /
-            (playlist_get_length() - ps->ps_list->pl_num_visible);
-    else
-        y = 0;
-
-    obj = ps->ps_widget.parent;
-
-    if (ps->ps_back_image) {
-        if (skin_get_id() != ps->ps_skin_id)
-            ps->ps_skin_id = skin_get_id();
-        else if (ps->ps_widget.height == ps->ps_prev_height)
-            gdk_draw_image(obj, ps->ps_widget.gc,
-                           ps->ps_back_image, 0, 0,
-                           ps->ps_widget.x,
-                           ps->ps_widget.y + ps->ps_prev_y, 8, 18);
-        gdk_image_destroy(ps->ps_back_image);
-    }
-
-    ps->ps_prev_y = y;
-    ps->ps_prev_height = ps->ps_widget.height;
-    ps->ps_back_image = gdk_drawable_get_image(obj, ps->ps_widget.x,
-                                               ps->ps_widget.y + y, 8, 18);
-    if (ps->ps_is_draging)
-        skinx = 61;
-    else
-        skinx = 52;
-
-    skin_draw_pixmap(bmp_active_skin, obj, ps->ps_widget.gc, SKIN_PLEDIT,
-                     skinx, 53, ps->ps_widget.x, ps->ps_widget.y + y, 8, 18);
-}
-
-static void
-playlistslider_set_pos(PlaylistSlider * ps, gint y)
-{
-    gint pos;
-
-    y = CLAMP(y, 0, ps->ps_widget.height - 19);
-
-    pos = (y * (playlist_get_length() - ps->ps_list->pl_num_visible)) /
-        (ps->ps_widget.height - 19);
-    playlistwin_set_toprow(pos);
-}
-
-
-void
-playlistslider_button_press_cb(GtkWidget * widget,
-                               GdkEventButton * event, PlaylistSlider * ps)
-{
-    gint y = event->y - ps->ps_widget.y;
-
-    if (!widget_contains(&ps->ps_widget, event->x, event->y))
-        return;
-
-    if (event->button != 1 && event->button != 2)
-        return;
-
-    if ((y >= ps->ps_prev_y && y < ps->ps_prev_y + 18)) {
-        ps->ps_is_draging |= event->button;
-        ps->ps_drag_y = y - ps->ps_prev_y;
-        widget_draw(WIDGET(ps));
-    }
-    else if (event->button == 2) {
-        playlistslider_set_pos(ps, y);
-        ps->ps_is_draging |= event->button;
-        ps->ps_drag_y = 0;
-        widget_draw(WIDGET(ps));
-    }
-    else {
-        gint n = ps->ps_list->pl_num_visible / 2;
-        if (y < ps->ps_prev_y)
-            n *= -1;
-        playlistwin_scroll(n);
-    }
-}
-
-void
-playlistslider_button_release_cb(GtkWidget * widget,
-                                 GdkEventButton * event,
-                                 PlaylistSlider * ps)
-{
-    if (ps->ps_is_draging) {
-        ps->ps_is_draging &= ~event->button;
-        widget_draw(WIDGET(ps));
-    }
-}
-
-void
-playlistslider_motion_cb(GtkWidget * widget, GdkEventMotion * event,
-                         PlaylistSlider * ps)
-{
-    gint y;
-
-    if (!ps->ps_is_draging)
-        return;
-
-    y = event->y - ps->ps_widget.y - ps->ps_drag_y;
-    playlistslider_set_pos(ps, y);
-}
-
-PlaylistSlider *
-create_playlistslider(GList ** wlist, GdkPixmap * parent,
-                      GdkGC * gc, gint x, gint y, gint h,
-                      PlayList_List * list)
-{
-    PlaylistSlider *ps;
-
-    ps = g_new0(PlaylistSlider, 1);
-    widget_init(&ps->ps_widget, parent, gc, x, y, 8, h, 1);
-
-    ps->ps_widget.button_press_cb =
-        (void (*)(GtkWidget *, GdkEventButton *, gpointer))
-        playlistslider_button_press_cb;
-
-    ps->ps_widget.button_release_cb =
-        (void (*)(GtkWidget *, GdkEventButton *, gpointer))
-        playlistslider_button_release_cb;
-
-    ps->ps_widget.motion_cb =
-        (void (*)(GtkWidget *, GdkEventMotion *, gpointer))
-        playlistslider_motion_cb;
-
-    ps->ps_widget.draw = playlistslider_draw;
-    ps->ps_list = list;
-
-    widget_list_add(wlist, WIDGET(ps));
-    return ps;
-}
--- a/audacious/playlist_slider.h	Wed Aug 09 02:11:01 2006 -0700
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,47 +0,0 @@
-/*  BMP - Cross-platform multimedia player
- *  Copyright (C) 2003-2004  BMP development team.
- *
- *  Based on XMMS:
- *  Copyright (C) 1998-2003  XMMS development team.
- *
- *  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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
- */
-
-#ifndef PLAYLIST_SLIDER_H
-#define PLAYLIST_SLIDER_H
-
-#include <glib.h>
-#include <gdk/gdk.h>
-
-#include "playlist_list.h"
-#include "widget.h"
-
-#define PLAYLIST_SLIDER(x)  ((PlayerlistSlider *)(x))
-struct _PlaylistSlider {
-    Widget ps_widget;
-    PlayList_List *ps_list;
-    gboolean ps_is_draging;
-    gint ps_drag_y, ps_prev_y, ps_prev_height;
-    GdkImage *ps_back_image;
-    gint ps_skin_id;
-};
-
-typedef struct _PlaylistSlider PlaylistSlider;
-
-PlaylistSlider *create_playlistslider(GList ** wlist, GdkPixmap * parent,
-                                      GdkGC * gc, gint x, gint y, gint h,
-                                      PlayList_List * list);
-
-#endif
--- a/audacious/playstatus.c	Wed Aug 09 02:11:01 2006 -0700
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,102 +0,0 @@
-/*  XMMS - Cross-platform multimedia player
- *  Copyright (C) 1998-2000  Peter Alm, Mikael Alm, Olle Hallnas, Thomas Nilsson and 4Front Technologies
- *
- *  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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
- */
-
-#include "playstatus.h"
-
-#include <glib.h>
-#include <gdk/gdk.h>
-
-#include "skin.h"
-#include "widget.h"
-
-void
-playstatus_draw(Widget * w)
-{
-    PlayStatus *ps = PLAY_STATUS(w);
-    GdkPixmap *obj;
-
-    if (!w)
-        return;
-
-    obj = ps->ps_widget.parent;
-    if (ps->ps_status == STATUS_STOP && ps->ps_status_buffering == TRUE)
-        ps->ps_status_buffering = FALSE;
-    if (ps->ps_status == STATUS_PLAY && ps->ps_status_buffering == TRUE)
-        skin_draw_pixmap(bmp_active_skin, obj, ps->ps_widget.gc,
-                         SKIN_PLAYPAUSE, 39, 0, ps->ps_widget.x,
-                         ps->ps_widget.y, 3, 9);
-    else if (ps->ps_status == STATUS_PLAY)
-        skin_draw_pixmap(bmp_active_skin, obj, ps->ps_widget.gc,
-                         SKIN_PLAYPAUSE, 36, 0, ps->ps_widget.x,
-                         ps->ps_widget.y, 3, 9);
-    else
-        skin_draw_pixmap(bmp_active_skin, obj, ps->ps_widget.gc,
-                         SKIN_PLAYPAUSE, 27, 0, ps->ps_widget.x,
-                         ps->ps_widget.y, 2, 9);
-    switch (ps->ps_status) {
-    case STATUS_STOP:
-        skin_draw_pixmap(bmp_active_skin, obj, ps->ps_widget.gc,
-                         SKIN_PLAYPAUSE, 18, 0,
-                         ps->ps_widget.x + 2, ps->ps_widget.y, 9, 9);
-        break;
-    case STATUS_PAUSE:
-        skin_draw_pixmap(bmp_active_skin, obj, ps->ps_widget.gc,
-                         SKIN_PLAYPAUSE, 9, 0,
-                         ps->ps_widget.x + 2, ps->ps_widget.y, 9, 9);
-        break;
-    case STATUS_PLAY:
-        skin_draw_pixmap(bmp_active_skin, obj, ps->ps_widget.gc,
-                         SKIN_PLAYPAUSE, 1, 0,
-                         ps->ps_widget.x + 3, ps->ps_widget.y, 8, 9);
-        break;
-    }
-}
-
-void
-playstatus_set_status(PlayStatus * ps, PStatus status)
-{
-    if (!ps)
-        return;
-
-    ps->ps_status = status;
-    widget_draw(WIDGET(ps));
-}
-
-void
-playstatus_set_status_buffering(PlayStatus * ps, gboolean status)
-{
-    if (!ps)
-        return;
-
-    ps->ps_status_buffering = status;
-    widget_draw(WIDGET(ps));
-}
-
-PlayStatus *
-create_playstatus(GList ** wlist, GdkPixmap * parent,
-                  GdkGC * gc, gint x, gint y)
-{
-    PlayStatus *ps;
-
-    ps = g_new0(PlayStatus, 1);
-    widget_init(&ps->ps_widget, parent, gc, x, y, 11, 9, TRUE);
-    ps->ps_widget.draw = playstatus_draw;
-
-    widget_list_add(wlist, WIDGET(ps));
-    return ps;
-}
--- a/audacious/playstatus.h	Wed Aug 09 02:11:01 2006 -0700
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,41 +0,0 @@
-/*  XMMS - Cross-platform multimedia player
- *  Copyright (C) 1998-2000  Peter Alm, Mikael Alm, Olle Hallnas, Thomas Nilsson and 4Front Technologies
- *
- *  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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
- */
-#ifndef PLAYSTATUS_H
-#define PLAYSTATUS_H
-
-#include "widget.h"
-
-typedef enum {
-    STATUS_STOP, STATUS_PAUSE, STATUS_PLAY
-} PStatus;
-
-#define PLAY_STATUS(x)  ((PlayStatus *)(x))
-struct _PlayStatus {
-    Widget ps_widget;
-    PStatus ps_status;
-    gboolean ps_status_buffering;
-};
-
-typedef struct _PlayStatus PlayStatus;
-
-void playstatus_set_status(PlayStatus * ps, PStatus status);
-void playstatus_set_status_buffering(PlayStatus * ps, gboolean status);
-PlayStatus *create_playstatus(GList ** wlist, GdkPixmap * parent,
-                              GdkGC * gc, gint x, gint y);
-
-#endif
--- a/audacious/prefswin.c	Wed Aug 09 02:11:01 2006 -0700
+++ b/audacious/prefswin.c	Wed Aug 09 02:47:22 2006 -0700
@@ -48,7 +48,7 @@
 #include "visualization.h"
 
 #include "main.h"
-#include "skin.h"
+#include "widgets/skin.h"
 #include "urldecode.h"
 #include "util.h"
 #include "dnd.h"
@@ -57,7 +57,6 @@
 #include "mainwin.h"
 #include "ui_playlist.h"
 #include "skinwin.h"
-#include "playlist_list.h"
 #include "build_stamp.h"
 #include "prefswin.h"
 
--- a/audacious/sbutton.c	Wed Aug 09 02:11:01 2006 -0700
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,99 +0,0 @@
-/*  BMP - Cross-platform multimedia player
- *  Copyright (C) 2003-2004  BMP development team.
- *
- *  Based on XMMS:
- *  Copyright (C) 1998-2003  XMMS development team.
- *
- *  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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
- */
-
-#include "sbutton.h"
-
-#include <glib.h>
-#include <gtk/gtk.h>
-#include <gdk/gdk.h>
-
-void
-sbutton_button_press_cb(GtkWidget * widget,
-                        GdkEventButton * event,
-                        SButton * button)
-{
-    if (event->button != 1)
-        return;
-
-    if (widget_contains(&button->sb_widget, event->x, event->y)) {
-        button->sb_pressed = 1;
-        button->sb_inside = 1;
-    }
-}
-
-void
-sbutton_button_release_cb(GtkWidget * widget, GdkEventButton * event,
-                          SButton * button)
-{
-    if (event->button != 1)
-        return;
-    if (button->sb_inside && button->sb_pressed) {
-        button->sb_inside = 0;
-        if (button->sb_push_cb)
-            button->sb_push_cb();
-    }
-    if (button->sb_pressed)
-        button->sb_pressed = 0;
-}
-
-void
-sbutton_motion_cb(GtkWidget * widget, GdkEventMotion * event,
-                  SButton * button)
-{
-    int inside;
-
-    if (!button->sb_pressed)
-        return;
-
-    inside = widget_contains(&button->sb_widget, event->x, event->y);
-
-    if (inside != button->sb_inside)
-        button->sb_inside = inside;
-}
-
-SButton *
-create_sbutton(GList ** wlist, GdkPixmap * parent, GdkGC * gc,
-               gint x, gint y, gint w, gint h, void (*cb) (void))
-{
-    SButton *b;
-
-    b = g_new0(SButton, 1);
-    widget_init(&b->sb_widget, parent, gc, x, y, w, h, 1);
-    b->sb_widget.button_press_cb =
-        (void (*)(GtkWidget *, GdkEventButton *, gpointer))
-        sbutton_button_press_cb;
-    b->sb_widget.button_release_cb =
-        (void (*)(GtkWidget *, GdkEventButton *, gpointer))
-        sbutton_button_release_cb;
-    b->sb_widget.motion_cb =
-        (void (*)(GtkWidget *, GdkEventMotion *, gpointer))
-        sbutton_motion_cb;
-    b->sb_push_cb = cb;
-
-    widget_list_add(wlist, WIDGET(b));
-    return b;
-}
-
-void
-free_sbutton(SButton * b)
-{
-    g_free(b);
-}
--- a/audacious/sbutton.h	Wed Aug 09 02:11:01 2006 -0700
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,43 +0,0 @@
-/*  BMP - Cross-platform multimedia player
- *  Copyright (C) 2003-2004  BMP development team.
- *
- *  Based on XMMS:
- *  Copyright (C) 1998-2003  XMMS development team.
- *
- *  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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
- */
-
-#ifndef SBUTTON_H
-#define SBUTTON_H
-
-#include <glib.h>
-#include <gdk/gdk.h>
-
-#include "widget.h"
-
-#define SBUTTON(x)  ((SButton *)(x))
-struct _SButton {
-    Widget sb_widget;
-    gint sb_pressed, sb_inside;
-    void (*sb_push_cb) (void);
-};
-
-typedef struct _SButton SButton;
-
-SButton *create_sbutton(GList ** wlist, GdkPixmap * parent, GdkGC * gc,
-                        gint x, gint y, gint w, gint h, void (*cb) (void));
-void free_sbutton(SButton * b);
-
-#endif
--- a/audacious/skin.c	Wed Aug 09 02:11:01 2006 -0700
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,1260 +0,0 @@
-/*  BMP - Cross-platform multimedia player
- *  Copyright (C) 2003-2004  BMP development team.
- *
- *  Based on XMMS:
- *  Copyright (C) 1998-2003  XMMS development team.
- *
- *  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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
- */
-
-#ifdef HAVE_CONFIG_H
-#  include "config.h"
-#endif
-
-/* TODO: enforce default sizes! */
-
-#include <glib.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <ctype.h>
-
-#include "equalizer.h"
-#include "main.h"
-#include "ui_playlist.h"
-#include "skin.h"
-#include "skinwin.h"
-#include "util.h"
-
-#include "debug.h"
-
-#include <gdk/gdkx.h>
-#include <X11/Xlib.h>
-
-#define EXTENSION_TARGETS 7
-
-static gchar *ext_targets[EXTENSION_TARGETS] = { "bmp", "xpm", "png", "svg", 
-	"gif", "jpg", "jpeg" };
-
-struct _SkinPixmapIdMapping {
-    SkinPixmapId id;
-    const gchar *name;
-    const gchar *alt_name;
-    gint width, height;
-};
-
-struct _SkinMaskInfo {
-    gint width, height;
-    gchar *inistr;
-};
-
-typedef struct _SkinPixmapIdMapping SkinPixmapIdMapping;
-typedef struct _SkinMaskInfo SkinMaskInfo;
-
-
-Skin *bmp_active_skin = NULL;
-
-static gint skin_current_num;
-
-static SkinMaskInfo skin_mask_info[] = {
-    {275, 116, "Normal"},
-    {275, 16,  "WindowShade"},
-    {275, 116, "Equalizer"},
-    {275, 16,  "EqualizerWS"}
-};
-
-static SkinPixmapIdMapping skin_pixmap_id_map[] = {
-    {SKIN_MAIN, "main", NULL, 0, 0},
-    {SKIN_CBUTTONS, "cbuttons", NULL, 0, 0},
-    {SKIN_SHUFREP, "shufrep", NULL, 0, 0},
-    {SKIN_TEXT, "text", NULL, 0, 0},
-    {SKIN_TITLEBAR, "titlebar", NULL, 0, 0},
-    {SKIN_VOLUME, "volume", NULL, 0, 0},
-    {SKIN_BALANCE, "balance", "volume", 0, 0},
-    {SKIN_MONOSTEREO, "monoster", NULL, 0, 0},
-    {SKIN_PLAYPAUSE, "playpaus", NULL, 0, 0},
-    {SKIN_NUMBERS, "nums_ex", "numbers", 0, 0},
-    {SKIN_POSBAR, "posbar", NULL, 0, 0},
-    {SKIN_EQMAIN, "eqmain", NULL, 0, 0},
-    {SKIN_PLEDIT, "pledit", NULL, 0, 0},
-    {SKIN_EQ_EX, "eq_ex", NULL, 0, 0}
-};
-
-static guint skin_pixmap_id_map_size = G_N_ELEMENTS(skin_pixmap_id_map);
-
-static const guchar skin_default_viscolor[24][3] = {
-    {9, 34, 53},
-    {10, 18, 26},
-    {0, 54, 108},
-    {0, 58, 116},
-    {0, 62, 124},
-    {0, 66, 132},
-    {0, 70, 140},
-    {0, 74, 148},
-    {0, 78, 156},
-    {0, 82, 164},
-    {0, 86, 172},
-    {0, 92, 184},
-    {0, 98, 196},
-    {0, 104, 208},
-    {0, 110, 220},
-    {0, 116, 232},
-    {0, 122, 244},
-    {0, 128, 255},
-    {0, 128, 255},
-    {0, 104, 208},
-    {0, 80, 160},
-    {0, 56, 112},
-    {0, 32, 64},
-    {200, 200, 200}
-};
-
-static GdkBitmap *
-skin_create_transparent_mask(const gchar *,
-                             const gchar *,
-                             const gchar *,
-                             GdkWindow *,
-                             gint, gint);
-
-static void
-skin_setup_masks(Skin * skin);
-
-static void
-skin_set_default_vis_color(Skin * skin);
-
-
-void
-skin_lock(Skin * skin)
-{
-    g_mutex_lock(skin->lock);
-}
-
-void
-skin_unlock(Skin * skin)
-{
-    g_mutex_unlock(skin->lock);
-}
-
-gboolean
-bmp_active_skin_reload(void) 
-{
-    return bmp_active_skin_load(bmp_active_skin->path);	
-}
-
-gboolean
-bmp_active_skin_load(const gchar * path)
-{
-    g_return_val_if_fail(bmp_active_skin != NULL, FALSE);
-
-    memset(&bmp_active_skin->properties, 0, sizeof(SkinProperties));
-
-    if (!skin_load(bmp_active_skin, path))
-        return FALSE;
-
-    skin_setup_masks(bmp_active_skin);
-
-    if (cfg.playlist_transparent)
-    {
-        if (rootpix != NULL)
-            g_object_unref(rootpix);
-
-        rootpix = shade_pixmap(get_transparency_pixmap(), 0, 0, 0, 0, gdk_screen_width(), gdk_screen_height(),
-                               skin_get_color(bmp_active_skin, SKIN_PLEDIT_NORMALBG));
-    }
-
-    draw_main_window(TRUE);
-    draw_playlist_window(TRUE);
-    draw_equalizer_window(TRUE);
-
-    vis_set_window(mainwin_vis, mainwin->window);
-    playlistwin_update_list();
-
-    return TRUE;
-}
-
-void
-skin_pixmap_free(SkinPixmap * p)
-{
-    g_return_if_fail(p != NULL);
-    g_return_if_fail(p->pixmap != NULL);
-
-    g_object_unref(p->pixmap);
-    p->pixmap = NULL;
-}
-
-Skin *
-skin_new(void)
-{
-    Skin *skin;
-    skin = g_new0(Skin, 1);
-    skin->lock = g_mutex_new();
-    return skin;
-}
-
-void
-skin_free(Skin * skin)
-{
-    gint i;
-
-    g_return_if_fail(skin != NULL);
-
-    skin_lock(skin);
-
-    for (i = 0; i < SKIN_PIXMAP_COUNT; i++)
-        skin_pixmap_free(&skin->pixmaps[i]);
-
-    for (i = 0; i < SKIN_PIXMAP_COUNT; i++) {
-        if (skin->masks[i])
-            g_object_unref(skin->masks[i]);
-
-        skin->masks[i] = NULL;
-    }
-
-    skin_set_default_vis_color(skin);
-    skin_unlock(skin);
-}
-
-void
-skin_destroy(Skin * skin)
-{
-    g_return_if_fail(skin != NULL);
-    skin_free(skin);
-    g_mutex_free(skin->lock);
-    g_free(skin);
-}
-
-const SkinPixmapIdMapping *
-skin_pixmap_id_lookup(guint id)
-{
-    guint i;
-
-    for (i = 0; i < skin_pixmap_id_map_size; i++) {
-        if (id == skin_pixmap_id_map[i].id) {
-            return &skin_pixmap_id_map[i];
-        }
-    }
-
-    return NULL;
-}
-
-const gchar *
-skin_pixmap_id_to_name(SkinPixmapId id)
-{
-    guint i;
-
-    for (i = 0; i < skin_pixmap_id_map_size; i++) {
-        if (id == skin_pixmap_id_map[i].id)
-            return skin_pixmap_id_map[i].name;
-    }
-    return NULL;
-}
-
-static void
-skin_set_default_vis_color(Skin * skin)
-{
-    memcpy(skin->vis_color, skin_default_viscolor,
-           sizeof(skin_default_viscolor));
-}
-
-/*
- * I have rewritten this to take an array of possible targets,
- * once we find a matching target we now return, instead of loop
- * recursively. This allows for us to support many possible format
- * targets for our skinning engine than just the original winamp 
- * formats.
- *
- *    -- nenolod, 16 January 2006
- */
-gchar *
-skin_pixmap_locate(const gchar * dirname, gchar ** basenames)
-{
-    gchar *filename;
-    gint i;
-
-    for (i = 0; basenames[i]; i++)
-	if (!(filename = find_file_recursively(dirname, basenames[i]))) 
-            g_free(filename);
-        else
-            return filename;
-
-    /* can't find any targets -- sorry */
-    return NULL;
-}
-
-/* FIXME: this function is temporary. It will be removed when the skinning system
-   uses GdkPixbuf in place of GdkPixmap */
-
-static GdkPixmap *
-pixmap_new_from_file(const gchar * filename)
-{
-    GdkPixbuf *pixbuf;
-    GdkPixmap *pixmap;
-    gint width, height;
-
-    if (!(pixbuf = gdk_pixbuf_new_from_file(filename, NULL)))
-        return NULL;
-
-    width = gdk_pixbuf_get_width(pixbuf);
-    height = gdk_pixbuf_get_height(pixbuf);
-
-    if (!(pixmap = gdk_pixmap_new(mainwin->window, width, height,
-                                  gdk_rgb_get_visual()->depth))) {
-        g_object_unref(pixbuf);
-        return NULL;
-    }
-
-    gdk_pixbuf_render_to_drawable(pixbuf, pixmap, mainwin_gc, 0, 0, 0, 0,
-                                  width, height, GDK_RGB_DITHER_MAX, 0, 0);
-    g_object_unref(pixbuf);
-
-    return pixmap;
-}
-
-static gboolean
-skin_load_pixmap_id(Skin * skin, SkinPixmapId id, const gchar * path_p)
-{
-    const gchar *path;
-    gchar *filename;
-    gint width, height;
-    const SkinPixmapIdMapping *pixmap_id_mapping;
-    GdkPixmap *gpm;
-    SkinPixmap *pm = NULL;
-    gchar *basenames[EXTENSION_TARGETS * 2 + 1]; /* alternate basenames */
-    gint i, y;
-
-    g_return_val_if_fail(skin != NULL, FALSE);
-    g_return_val_if_fail(id < SKIN_PIXMAP_COUNT, FALSE);
-
-    pixmap_id_mapping = skin_pixmap_id_lookup(id);
-    g_return_val_if_fail(pixmap_id_mapping != NULL, FALSE);
-
-    memset(&basenames, 0, sizeof(basenames));
-
-    for (i = 0, y = 0; i < EXTENSION_TARGETS; i++, y++)
-    {
-        basenames[y] = g_strdup_printf("%s.%s", pixmap_id_mapping->name,
-			ext_targets[i]);
-
-        if (pixmap_id_mapping->alt_name)
-            basenames[++y] = g_strdup_printf("%s.%s", 
-			pixmap_id_mapping->alt_name, ext_targets[i]);
-    }
-
-    path = path_p ? path_p : skin->path;
-    filename = skin_pixmap_locate(path, basenames);
-
-    for (i = 0; basenames[i] != NULL; i++)
-    {
-         g_free(basenames[i]);
-         basenames[i] = NULL;
-    }
-
-    if (!(gpm = pixmap_new_from_file(filename))) {
-        g_warning("loading of %s failed", filename);
-        g_free(filename);
-        return FALSE;
-    }
-
-    g_free(filename);
-
-    gdk_window_get_size(gpm, &width, &height);
-    pm = &skin->pixmaps[id];
-    pm->pixmap = gpm;
-    pm->width = width;
-    pm->height = height;
-    pm->current_width = width;
-    pm->current_height = height;
-
-    return TRUE;
-}
-
-void
-skin_mask_create(Skin * skin,
-                 const gchar * path,
-                 gint id,
-                 GdkWindow * window)
-{
-    skin->masks[id] =
-        skin_create_transparent_mask(path, "region.txt",
-                                     skin_mask_info[id].inistr, window,
-                                     skin_mask_info[id].width,
-                                     skin_mask_info[id].height);
-}
-
-static void
-skin_setup_masks(Skin * skin)
-{
-    GdkBitmap *mask;
-
-    if (cfg.show_wm_decorations)
-        return;
-
-    if (cfg.player_visible) {
-        mask = skin_get_mask(skin, SKIN_MASK_MAIN + cfg.player_shaded);
-        gtk_widget_shape_combine_mask(mainwin, mask, 0, 0);
-    }
-
-    mask = skin_get_mask(skin, SKIN_MASK_EQ + cfg.equalizer_shaded);
-    gtk_widget_shape_combine_mask(equalizerwin, mask, 0, 0);
-}
-
-static GdkBitmap *
-create_default_mask(GdkWindow * parent, gint w, gint h)
-{
-    GdkBitmap *ret;
-    GdkGC *gc;
-    GdkColor pattern;
-
-    ret = gdk_pixmap_new(parent, w, h, 1);
-    gc = gdk_gc_new(ret);
-    pattern.pixel = 1;
-    gdk_gc_set_foreground(gc, &pattern);
-    gdk_draw_rectangle(ret, gc, TRUE, 0, 0, w, h);
-    gdk_gc_destroy(gc);
-
-    return ret;
-}
-
-static void
-skin_query_color(GdkColormap * cm, GdkColor * c)
-{
-    XColor xc = { 0,0,0,0,0,0 };
-
-    xc.pixel = c->pixel;
-    XQueryColor(GDK_COLORMAP_XDISPLAY(cm), GDK_COLORMAP_XCOLORMAP(cm), &xc);
-    c->red = xc.red;
-    c->green = xc.green;
-    c->blue = xc.blue;
-}
-
-static glong
-skin_calc_luminance(GdkColor * c)
-{
-    return (0.212671 * c->red + 0.715160 * c->green + 0.072169 * c->blue);
-}
-
-static void
-skin_get_textcolors(GdkPixmap * text, GdkColor * bgc, GdkColor * fgc)
-{
-    /*
-     * Try to extract reasonable background and foreground colors
-     * from the font pixmap
-     */
-
-    GdkImage *gi;
-    GdkColormap *cm;
-    gint i;
-
-    g_return_if_fail(text != NULL);
-
-    /* Get the first line of text */
-    gi = gdk_drawable_get_image(text, 0, 0, 152, 6);
-    cm = gdk_window_get_colormap(playlistwin->window);
-    g_return_if_fail(GDK_IS_WINDOW(playlistwin->window));
-
-    for (i = 0; i < 6; i++) {
-        GdkColor c;
-        gint x;
-        glong d, max_d;
-
-        /* Get a pixel from the middle of the space character */
-        bgc[i].pixel = gdk_image_get_pixel(gi, 151, i);
-        skin_query_color(cm, &bgc[i]);
-
-        max_d = 0;
-        for (x = 1; x < 150; x++) {
-            c.pixel = gdk_image_get_pixel(gi, x, i);
-            skin_query_color(cm, &c);
-
-            d = labs(skin_calc_luminance(&c) - skin_calc_luminance(&bgc[i]));
-            if (d > max_d) {
-                memcpy(&fgc[i], &c, sizeof(GdkColor));
-                max_d = d;
-            }
-        }
-    }
-    gdk_image_destroy(gi);
-}
-
-gboolean
-init_skins(const gchar * path)
-{
-    bmp_active_skin = skin_new();
-
-    if (!bmp_active_skin_load(path)) {
-        /* FIXME: Oddly, g_message() causes a crash if path is NULL on
-         * Solaris (see bug #165) */
-        if (path) 
-            g_message("Unable to load skin (%s), trying default...", path);
-
-        /* can't load configured skin, retry with default */
-        if (!bmp_active_skin_load(BMP_DEFAULT_SKIN_PATH)) {
-            g_message("Unable to load default skin (%s)! Giving up.",
-                      BMP_DEFAULT_SKIN_PATH);
-            return FALSE;
-        }
-    }
-
-    if (cfg.random_skin_on_play)
-        skinlist_update();
-
-    return TRUE;
-}
-
-/*
- * Opens and parses a skin's hints file.
- * Hints files are somewhat like "scripts" in Winamp3/5.
- * We'll probably add scripts to it next.
- */
-void
-skin_parse_hints(Skin * skin, gchar *path_p)
-{
-    gchar *filename, *tmp;
-
-    path_p = path_p ? path_p : skin->path;
-
-    filename = find_file_recursively(path_p, "skin.hints");
-
-    if (filename == NULL)
-        return;
-
-#if 0
-    skin->description = read_ini_string(filename, "skin", "skinDescription");
-#endif
-
-    tmp = read_ini_string(filename, "skin", "mainwinOthertext");
-
-    if (tmp != NULL)
-        skin->properties.mainwin_othertext = atoi(tmp);
-}
-
-static guint
-hex_chars_to_int(gchar hi, gchar lo)
-{
-    /*
-     * Converts a value in the range 0x00-0xFF
-     * to a integer in the range 0-65535
-     */
-    gchar str[3];
-
-    str[0] = hi;
-    str[1] = lo;
-    str[2] = 0;
-
-    return (CLAMP(strtol(str, NULL, 16), 0, 0xFF) << 8);
-}
-
-GdkColor *
-skin_load_color(const gchar * path, const gchar * file,
-                const gchar * section, const gchar * key,
-                gchar * default_hex)
-{
-    gchar *filename, *value;
-    GdkColor *color = NULL;
-
-    filename = find_file_recursively(path, file);
-    if (filename || default_hex) {
-        if (filename) {
-            value = read_ini_string(filename, section, key);
-            if (value == NULL) {
-                value = g_strdup(default_hex);
-            }
-        } else {
-            value = g_strdup(default_hex);
-        }
-        if (value) {
-            gchar *ptr = value;
-            gint len;
-
-            color = g_new0(GdkColor, 1);
-            g_strstrip(value);
-
-            if (value[0] == '#')
-                ptr++;
-            len = strlen(ptr);
-            /*
-             * The handling of incomplete values is done this way
-             * to maximize winamp compatibility
-             */
-            if (len >= 6) {
-                color->red = hex_chars_to_int(*ptr, *(ptr + 1));
-                ptr += 2;
-            }
-            if (len >= 4) {
-                color->green = hex_chars_to_int(*ptr, *(ptr + 1));
-                ptr += 2;
-            }
-            if (len >= 2)
-                color->blue = hex_chars_to_int(*ptr, *(ptr + 1));
-
-            gdk_color_alloc(gdk_window_get_colormap(playlistwin->window),
-                            color);
-            g_free(value);
-        }
-        if (filename)
-            g_free(filename);
-    }
-    return color;
-}
-
-
-
-GdkBitmap *
-skin_create_transparent_mask(const gchar * path,
-                             const gchar * file,
-                             const gchar * section,
-                             GdkWindow * window,
-                             gint width,
-                             gint height)
-{
-    GdkBitmap *mask = NULL;
-    GdkGC *gc = NULL;
-    GdkColor pattern;
-    GdkPoint *gpoints;
-
-    gchar *filename = NULL;
-    gboolean created_mask = FALSE;
-    GArray *num, *point;
-    guint i, j;
-    gint k;
-
-    if (path)
-        filename = find_file_recursively(path, file);
-
-    /* filename will be null if path wasn't set */
-    if (!filename) {
-        return create_default_mask(window, width, height);
-    }
-
-    if ((num = read_ini_array(filename, section, "NumPoints")) == NULL) {
-        g_free(filename);
-        return NULL;
-    }
-
-    if ((point = read_ini_array(filename, section, "PointList")) == NULL) {
-        g_array_free(num, TRUE);
-        g_free(filename);
-        return NULL;
-    }
-
-    mask = gdk_pixmap_new(window, width, height, 1);
-    gc = gdk_gc_new(mask);
-
-    pattern.pixel = 0;
-    gdk_gc_set_foreground(gc, &pattern);
-    gdk_draw_rectangle(mask, gc, TRUE, 0, 0, width, height);
-    pattern.pixel = 1;
-    gdk_gc_set_foreground(gc, &pattern);
-
-    j = 0;
-    for (i = 0; i < num->len; i++) {
-        if ((int)(point->len - j) >= (g_array_index(num, gint, i) * 2)) {
-            created_mask = TRUE;
-            gpoints = g_new(GdkPoint, g_array_index(num, gint, i));
-            for (k = 0; k < g_array_index(num, gint, i); k++) {
-                gpoints[k].x = g_array_index(point, gint, j + k * 2);
-                gpoints[k].y = g_array_index(point, gint, j + k * 2 + 1);
-            }
-            j += k * 2;
-            gdk_draw_polygon(mask, gc, TRUE, gpoints,
-                             g_array_index(num, gint, i));
-            g_free(gpoints);
-        }
-    }
-    g_array_free(num, TRUE);
-    g_array_free(point, TRUE);
-    g_free(filename);
-
-    if (!created_mask)
-        gdk_draw_rectangle(mask, gc, TRUE, 0, 0, width, height);
-
-    gdk_gc_destroy(gc);
-
-    return mask;
-}
-
-void
-skin_load_viscolor(Skin * skin, const gchar * path, const gchar * basename)
-{
-    FILE *file;
-    gint i, c;
-    gchar line[256], *filename;
-    GArray *a;
-
-    g_return_if_fail(skin != NULL);
-    g_return_if_fail(path != NULL);
-    g_return_if_fail(basename != NULL);
-
-    skin_set_default_vis_color(skin);
-
-    filename = find_file_recursively(path, basename);
-    if (!filename)
-        return;
-
-    if (!(file = fopen(filename, "r"))) {
-        g_free(filename);
-        return;
-    }
-
-    g_free(filename);
-
-    for (i = 0; i < 24; i++) {
-        if (fgets(line, 255, file)) {
-            a = string_to_garray(line);
-            if (a->len > 2) {
-                for (c = 0; c < 3; c++)
-                    skin->vis_color[i][c] = g_array_index(a, gint, c);
-            }
-            g_array_free(a, TRUE);
-        }
-        else
-            break;
-    }
-
-    fclose(file);
-}
-
-#if 0
-static void
-skin_numbers_generate_dash(Skin * skin)
-{
-    GdkGC *gc;
-    GdkPixmap *pixmap;
-    SkinPixmap *numbers;
-
-    g_return_if_fail(skin != NULL);
-
-    numbers = &skin->pixmaps[SKIN_NUMBERS];
-    if (!numbers->pixmap || numbers->current_width < 99)
-        return;
-
-    gc = gdk_gc_new(numbers->pixmap);
-    pixmap = gdk_pixmap_new(mainwin->window, 108,
-                            numbers->current_height,
-                            -1);
-
-    skin_draw_pixmap(skin, pixmap, gc, SKIN_NUMBERS, 0, 0, 0, 0, 99, 13);
-    skin_draw_pixmap(skin, pixmap, gc, SKIN_NUMBERS, 90, 0, 99, 0, 9, 13);
-    skin_draw_pixmap(skin, pixmap, gc, SKIN_NUMBERS, 20, 6, 101, 6, 5, 1);
-
-    g_object_unref(numbers->pixmap);
-    g_object_unref(gc);
-
-    numbers->pixmap = pixmap;
-    numbers->current_width = 108;
-}
-#endif
-
-static void
-skin_load_cursor(Skin * skin, const gchar * dirname)
-{
-    const gchar * basename = "normal.cur";
-    gchar * filename = NULL;
-    GdkPixbuf * cursor_pixbuf = NULL;
-    GdkPixbufAnimation * cursor_animated = NULL;
-    GdkCursor * cursor_gdk = NULL;
-    GError * error = NULL;
- 
-    filename = find_file_recursively(dirname, basename);
-
-    if (filename && cfg.custom_cursors)	{
-    	cursor_animated = gdk_pixbuf_animation_new_from_file(filename, &error);
-        cursor_pixbuf = gdk_pixbuf_animation_get_static_image(cursor_animated);
-        cursor_gdk = gdk_cursor_new_from_pixbuf(gdk_display_get_default(),
-                                                cursor_pixbuf, 0, 0);
-    } else {
-        cursor_gdk = gdk_cursor_new(GDK_LEFT_PTR);
-    }
-
-    gdk_window_set_cursor(mainwin->window, cursor_gdk);
-    gdk_window_set_cursor(playlistwin->window, cursor_gdk);
-    gdk_window_set_cursor(equalizerwin->window, cursor_gdk);
-    gdk_cursor_unref(cursor_gdk);
-}
-
-static void
-skin_load_pixmaps(Skin * skin, const gchar * path)
-{
-    GdkPixmap *text_pm;
-    guint i;
-
-    for (i = 0; i < SKIN_PIXMAP_COUNT; i++)
-        skin_load_pixmap_id(skin, i, path);
-
-    text_pm = skin->pixmaps[SKIN_TEXT].pixmap;
-
-    if (text_pm)
-        skin_get_textcolors(text_pm, skin->textbg, skin->textfg);
-
-#if 0
-    if (skin->pixmaps[SKIN_NUMBERS].pixmap)
-        skin_numbers_generate_dash(skin);
-#endif
-
-    skin->colors[SKIN_PLEDIT_NORMAL] =
-        skin_load_color(path, "pledit.txt", "text", "normal", "#2499ff");
-    skin->colors[SKIN_PLEDIT_CURRENT] =
-        skin_load_color(path, "pledit.txt", "text", "current", "#ffeeff");
-    skin->colors[SKIN_PLEDIT_NORMALBG] =
-        skin_load_color(path, "pledit.txt", "text", "normalbg", "#0a120a");
-    skin->colors[SKIN_PLEDIT_SELECTEDBG] =
-        skin_load_color(path, "pledit.txt", "text", "selectedbg", "#0a124a");
-
-    skin_mask_create(skin, path, SKIN_MASK_MAIN, mainwin->window);
-    skin_mask_create(skin, path, SKIN_MASK_MAIN_SHADE, mainwin->window);
-
-    skin_mask_create(skin, path, SKIN_MASK_EQ, equalizerwin->window);
-    skin_mask_create(skin, path, SKIN_MASK_EQ_SHADE, equalizerwin->window);
-
-    skin_load_viscolor(skin, path, "viscolor.txt");
-}
-
-static gboolean
-skin_load_nolock(Skin * skin, const gchar * path, gboolean force)
-{
-    gchar *cpath;
-
-    g_return_val_if_fail(skin != NULL, FALSE);
-    g_return_val_if_fail(path != NULL, FALSE);
-    REQUIRE_LOCK(skin->lock);
-
-    if (!g_file_test(path, G_FILE_TEST_IS_REGULAR | G_FILE_TEST_IS_DIR))
-	return FALSE;
-   
-    if (!force) {
-        if (skin->path)
-            if (!strcmp(skin->path, path))
-                return FALSE;
-    }
-      
-    skin_current_num++;
-
-    skin->path = g_strdup(path);
-
-    if (!file_is_archive(path)) {
-        skin_load_pixmaps(skin, path);
-        skin_load_cursor(skin, path);
-
-        /* Parse the hints for this skin. */
-        skin_parse_hints(skin, NULL);
-
-        return TRUE;
-    }
-
-    if (!(cpath = archive_decompress(path))) {
-        g_message("Unable to extract skin archive (%s)", path);
-        return FALSE;
-    }
-
-    skin_load_pixmaps(skin, cpath);
-    skin_load_cursor(skin, cpath);
-
-    /* Parse the hints for this skin. */
-    skin_parse_hints(skin, cpath);
-
-    del_directory(cpath);
-    g_free(cpath);
-
-    return TRUE;
-}
-
-void
-skin_install_skin(const gchar * path)
-{
-    gchar *command;
-
-    g_return_if_fail(path != NULL);
-
-    command = g_strdup_printf("cp %s %s", path, bmp_paths[BMP_PATH_USER_SKIN_DIR]);
-    if (system(command)) {
-        g_message("Unable to install skin (%s) into user directory (%s)",
-                  path, bmp_paths[BMP_PATH_USER_SKIN_DIR]);
-    }
-    g_free(command);
-}
-
-
-gboolean
-skin_load(Skin * skin, const gchar * path)
-{
-    gboolean error;
-
-    g_return_val_if_fail(skin != NULL, FALSE);
-
-    if (!path)
-        return FALSE;
-
-    skin_lock(skin);
-    error = skin_load_nolock(skin, path, FALSE);
-    skin_unlock(skin);
-    
-    return error;
-}
-
-gboolean
-skin_reload_forced(void) 
-{
-   gboolean error;
-
-   skin_lock(bmp_active_skin);
-   error = skin_load_nolock(bmp_active_skin, bmp_active_skin->path, TRUE);
-   skin_unlock(bmp_active_skin);
-
-   return error;
-}
-
-void
-skin_reload(Skin * skin)
-{
-    g_return_if_fail(skin != NULL);
-    skin_load_nolock(skin, skin->path, TRUE);
-}
-
-
-static SkinPixmap *
-skin_get_pixmap(Skin * skin, SkinPixmapId map_id)
-{
-    g_return_val_if_fail(skin != NULL, NULL);
-    g_return_val_if_fail(map_id < SKIN_PIXMAP_COUNT, NULL);
-
-    return &skin->pixmaps[map_id];
-}
-
-GdkBitmap *
-skin_get_mask(Skin * skin, SkinMaskId mi)
-{
-    g_return_val_if_fail(skin != NULL, NULL);
-    g_return_val_if_fail(mi < SKIN_PIXMAP_COUNT, NULL);
-
-    return skin->masks[mi];
-}
-
-GdkColor *
-skin_get_color(Skin * skin, SkinColorId color_id)
-{
-    GdkColor *ret = NULL;
-
-    g_return_val_if_fail(skin != NULL, NULL);
-
-    switch (color_id) {
-    case SKIN_TEXTBG:
-        if (skin->pixmaps[SKIN_TEXT].pixmap)
-            ret = skin->textbg;
-        else
-            ret = skin->def_textbg;
-        break;
-    case SKIN_TEXTFG:
-        if (skin->pixmaps[SKIN_TEXT].pixmap)
-            ret = skin->textfg;
-        else
-            ret = skin->def_textfg;
-        break;
-    default:
-        if (color_id < SKIN_COLOR_COUNT)
-            ret = skin->colors[color_id];
-        break;
-    }
-    return ret;
-}
-
-void
-skin_get_viscolor(Skin * skin, guchar vis_color[24][3])
-{
-    gint i;
-
-    g_return_if_fail(skin != NULL);
-
-    for (i = 0; i < 24; i++) {
-        vis_color[i][0] = skin->vis_color[i][0];
-        vis_color[i][1] = skin->vis_color[i][1];
-        vis_color[i][2] = skin->vis_color[i][2];
-    }
-}
-
-gint
-skin_get_id(void)
-{
-    return skin_current_num;
-}
-
-void
-skin_draw_pixmap(Skin * skin, GdkDrawable * drawable, GdkGC * gc,
-                 SkinPixmapId pixmap_id,
-                 gint xsrc, gint ysrc, gint xdest, gint ydest,
-                 gint width, gint height)
-{
-    SkinPixmap *pixmap;
-
-    g_return_if_fail(skin != NULL);
-
-    pixmap = skin_get_pixmap(skin, pixmap_id);
-    g_return_if_fail(pixmap != NULL);
-    g_return_if_fail(pixmap->pixmap != NULL);
-
-    if (xsrc > pixmap->width || ysrc > pixmap->height)
-        return;
-
-    width = MIN(width, pixmap->width - xsrc);
-    height = MIN(height, pixmap->height - ysrc);
-    gdk_draw_pixmap(drawable, gc, pixmap->pixmap, xsrc, ysrc,
-                    xdest, ydest, width, height);
-}
-
-void
-skin_get_eq_spline_colors(Skin * skin, guint32 colors[19])
-{
-    gint i;
-    GdkPixmap *pixmap;
-    GdkImage *img;
-    SkinPixmap *eqmainpm;
-
-    g_return_if_fail(skin != NULL);
-
-    eqmainpm = &skin->pixmaps[SKIN_EQMAIN];
-    if (eqmainpm->pixmap &&
-        eqmainpm->current_width >= 116 && eqmainpm->current_height >= 313)
-        pixmap = eqmainpm->pixmap;
-    else
-        return;
-
-    if (!GDK_IS_DRAWABLE(pixmap))
-        return;
-
-    if (!(img = gdk_drawable_get_image(pixmap, 115, 294, 1, 19)))
-        return;
-
-    for (i = 0; i < 19; i++)
-        colors[i] = gdk_image_get_pixel(img, 0, i);
-
-    gdk_image_destroy(img);
-}
-
-
-static void
-skin_draw_playlistwin_frame_top(Skin * skin,
-                                GdkDrawable * drawable,
-                                GdkGC * gc,
-                                gint width, gint height, gboolean focus)
-{
-    /* The title bar skin consists of 2 sets of 4 images, 1 set
-     * for focused state and the other for unfocused. The 4 images
-     * are: 
-     *
-     * a. right corner (25,20)
-     * b. left corner  (25,20)
-     * c. tiler        (25,20)
-     * d. title        (100,20)
-     * 
-     * min allowed width = 100+25+25 = 150
-     */
-
-    gint i, y, c;
-
-    /* get y offset of the pixmap set to use */
-    if (focus)
-        y = 0;
-    else
-        y = 21;
-
-    /* left corner */
-    skin_draw_pixmap(skin, drawable, gc, SKIN_PLEDIT, 0, y, 0, 0, 25, 20);
-
-    /* titlebar title */
-    skin_draw_pixmap(skin, drawable, gc, SKIN_PLEDIT, 26, y,
-                     (width - 100) / 2, 0, 100, 20);
-
-    /* titlebar right corner  */
-    skin_draw_pixmap(skin, drawable, gc, SKIN_PLEDIT, 153, y,
-                     width - 25, 0, 25, 20);
-
-    /* tile draw the remaining frame */
-
-    /* compute tile count */
-    c = (width - (100 + 25 + 25)) / 25;
-
-    for (i = 0; i < c / 2; i++) {
-        /* left of title */
-        skin_draw_pixmap(skin, drawable, gc, SKIN_PLEDIT, 127, y,
-                         25 + i * 25, 0, 25, 20);
-
-        /* right of title */
-        skin_draw_pixmap(skin, drawable, gc, SKIN_PLEDIT, 127, y,
-                         (width + 100) / 2 + i * 25, 0, 25, 20);
-    }
-
-    if (c & 1) {
-        /* Odd tile count, so one remaining to draw. Here we split
-         * it into two and draw half on either side of the title */
-        skin_draw_pixmap(skin, drawable, gc, SKIN_PLEDIT, 127, y,
-                         ((c / 2) * 25) + 25, 0, 12, 20);
-        skin_draw_pixmap(skin, drawable, gc, SKIN_PLEDIT, 127, y,
-                         (width / 2) + ((c / 2) * 25) + 50, 0, 13, 20);
-    }
-}
-
-static void
-skin_draw_playlistwin_frame_bottom(Skin * skin,
-                                   GdkDrawable * drawable,
-                                   GdkGC * gc,
-                                   gint width, gint height, gboolean focus)
-{
-    /* The bottom frame skin consists of 1 set of 4 images. The 4
-     * images are:
-     *
-     * a. left corner with menu buttons (125,38)
-     * b. visualization window (75,38)
-     * c. right corner with play buttons (150,38)
-     * d. frame tile (25,38)
-     * 
-     * (min allowed width = 125+150+25=300
-     */
-
-    gint i, c;
-
-    /* bottom left corner (menu buttons) */
-    skin_draw_pixmap(skin, drawable, gc, SKIN_PLEDIT, 0, 72,
-                     0, height - 38, 125, 38);
-
-    c = (width - 275) / 25;
-
-    /* draw visualization window, if width allows */
-    if (c >= 3) {
-        c -= 3;
-        skin_draw_pixmap(skin, drawable, gc, SKIN_PLEDIT, 205, 0,
-                         width - (150 + 75), height - 38, 75, 38);
-    }
-
-    /* Bottom right corner (playbuttons etc) */
-    skin_draw_pixmap(skin, drawable, gc, SKIN_PLEDIT,
-                     126, 72, width - 150, height - 38, 150, 38);
-
-    /* Tile draw the remaining undrawn portions */
-    for (i = 0; i < c; i++)
-        skin_draw_pixmap(skin, drawable, gc, SKIN_PLEDIT, 179, 0,
-                         125 + i * 25, height - 38, 25, 38);
-}
-
-static void
-skin_draw_playlistwin_frame_sides(Skin * skin,
-                                  GdkDrawable * drawable,
-                                  GdkGC * gc,
-                                  gint width, gint height, gboolean focus)
-{
-    /* The side frames consist of 2 tile images. 1 for the left, 1 for
-     * the right. 
-     * a. left  (12,29)
-     * b. right (19,29)
-     */
-
-    gint i;
-
-    /* frame sides */
-    for (i = 0; i < (height - (20 + 38)) / 29; i++) {
-        /* left */
-        skin_draw_pixmap(skin, drawable, gc, SKIN_PLEDIT, 0, 42,
-                         0, 20 + i * 29, 12, 29);
-
-        /* right */
-        skin_draw_pixmap(skin, drawable, gc, SKIN_PLEDIT, 32, 42,
-                         width - 19, 20 + i * 29, 19, 29);
-    }
-}
-
-
-void
-skin_draw_playlistwin_frame(Skin * skin,
-                            GdkDrawable * drawable, GdkGC * gc,
-                            gint width, gint height, gboolean focus)
-{
-    skin_draw_playlistwin_frame_top(skin, drawable, gc, width, height, focus);
-    skin_draw_playlistwin_frame_bottom(skin, drawable, gc, width, height,
-                                       focus);
-    skin_draw_playlistwin_frame_sides(skin, drawable, gc, width, height,
-                                      focus);
-}
-
-
-void
-skin_draw_playlistwin_shaded(Skin * skin,
-                             GdkDrawable * drawable, GdkGC * gc,
-                             gint width, gboolean focus)
-{
-    /* The shade mode titlebar skin consists of 4 images:
-     * a) left corner               offset (72,42) size (25,14)
-     * b) right corner, focused     offset (99,57) size (50,14)
-     * c) right corner, unfocused   offset (99,42) size (50,14)
-     * d) bar tile                  offset (72,57) size (25,14)
-     */
-
-    gint i;
-
-    /* left corner */
-    skin_draw_pixmap(skin, drawable, gc, SKIN_PLEDIT, 72, 42, 0, 0, 25, 14);
-
-    /* bar tile */
-    for (i = 0; i < (width - 75) / 25; i++)
-        skin_draw_pixmap(skin, drawable, gc, SKIN_PLEDIT, 72, 57,
-                         (i * 25) + 25, 0, 25, 14);
-
-    /* right corner */
-    skin_draw_pixmap(skin, drawable, gc, SKIN_PLEDIT, 99, focus ? 57 : 42,
-                     width - 50, 0, 50, 14);
-}
-
-
-void
-skin_draw_mainwin_titlebar(Skin * skin,
-                           GdkDrawable * drawable, GdkGC * gc,
-                           gboolean shaded, gboolean focus)
-{
-    /* The titlebar skin consists of 2 sets of 2 images, one for for
-     * shaded and the other for unshaded mode, giving a total of 4.
-     * The images are exactly 275x14 pixels, aligned and arranged
-     * vertically on each other in the pixmap in the following order:
-     * 
-     * a) unshaded, focused      offset (27, 0)
-     * b) unshaded, unfocused    offset (27, 15)
-     * c) shaded, focused        offset (27, 29)
-     * d) shaded, unfocused      offset (27, 42)
-     */
-
-    gint y_offset;
-
-    if (shaded) {
-        if (focus)
-            y_offset = 29;
-        else
-            y_offset = 42;
-    }
-    else {
-        if (focus)
-            y_offset = 0;
-        else
-            y_offset = 15;
-    }
-
-    skin_draw_pixmap(skin, drawable, gc, SKIN_TITLEBAR, 27, y_offset,
-                     0, 0, MAINWIN_WIDTH, MAINWIN_TITLEBAR_HEIGHT);
-}
-
-#if 0
-void
-skin_draw_mainwin(Skin * skin,
-                  GdkDrawable * drawable, GdkGC gc,
-                  gboolean doublesize, gboolean shaded, gboolean focus)
-{
-
-}
-#endif
--- a/audacious/skin.h	Wed Aug 09 02:11:01 2006 -0700
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,145 +0,0 @@
-/*  BMP - Cross-platform multimedia player
- *  Copyright (C) 2003-2004  BMP development team.
- *
- *  Based on XMMS:
- *  Copyright (C) 1998-2003  XMMS development team.
- *
- *  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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
- */
-
-#ifndef SKIN_H
-#define SKIN_H
-
-
-#include <glib.h>
-#include <gdk/gdk.h>
-
-
-#define BMP_DEFAULT_SKIN_PATH \
-  DATA_DIR G_DIR_SEPARATOR_S "Skins" G_DIR_SEPARATOR_S "Default"
-
-
-typedef enum {
-    SKIN_MAIN = 0,
-    SKIN_CBUTTONS,
-    SKIN_TITLEBAR,
-    SKIN_SHUFREP,
-    SKIN_TEXT,
-    SKIN_VOLUME,
-    SKIN_BALANCE,
-    SKIN_MONOSTEREO,
-    SKIN_PLAYPAUSE,
-    SKIN_NUMBERS,
-    SKIN_POSBAR,
-    SKIN_PLEDIT,
-    SKIN_EQMAIN,
-    SKIN_EQ_EX,
-    SKIN_PIXMAP_COUNT
-} SkinPixmapId;
-
-typedef enum {
-    SKIN_MASK_MAIN = 0,
-    SKIN_MASK_MAIN_SHADE,
-    SKIN_MASK_EQ,
-    SKIN_MASK_EQ_SHADE,
-    SKIN_MASK_COUNT
-} SkinMaskId;
-
-typedef enum {
-    SKIN_PLEDIT_NORMAL = 0,
-    SKIN_PLEDIT_CURRENT,
-    SKIN_PLEDIT_NORMALBG,
-    SKIN_PLEDIT_SELECTEDBG,
-    SKIN_TEXTBG,
-    SKIN_TEXTFG,
-    SKIN_COLOR_COUNT
-} SkinColorId;
-
-typedef struct _SkinProperties {
-	gboolean mainwin_othertext;
-} SkinProperties;
-
-#define SKIN_PIXMAP(x)  ((SkinPixmap *)(x))
-typedef struct _SkinPixmap {
-    GdkPixmap *pixmap;
-    /* GdkPixmap *def_pixmap; */
-
-    /* The real size of the pixmap */
-    gint width, height;
-
-    /* The size of the pixmap from the current skin,
-       which might be smaller */
-    gint current_width, current_height;
-} SkinPixmap;
-
-
-#define SKIN(x)  ((Skin *)(x))
-typedef struct _Skin {
-    GMutex *lock;
-    gchar *path;
-    gchar *def_path;
-    SkinPixmap pixmaps[SKIN_PIXMAP_COUNT];
-    GdkColor textbg[6], def_textbg[6];
-    GdkColor textfg[6], def_textfg[6];
-    GdkColor *colors[SKIN_COLOR_COUNT];
-    guchar vis_color[24][3];
-    GdkBitmap *masks[SKIN_MASK_COUNT];
-    SkinProperties properties;
-} Skin;
-
-extern Skin *bmp_active_skin;
-
-gboolean init_skins(const gchar * path);
-void cleanup_skins(void);
-
-gboolean bmp_active_skin_load(const gchar * path);
-gboolean bmp_active_skin_reload(void);
-
-Skin *skin_new(void);
-gboolean skin_load(Skin * skin, const gchar * path);
-void skin_reload(Skin * skin);
-void skin_free(Skin * skin);
-
-GdkBitmap *skin_get_mask(Skin * skin, SkinMaskId mi);
-GdkColor *skin_get_color(Skin * skin, SkinColorId color_id);
-
-void skin_get_viscolor(Skin * skin, guchar vis_color[24][3]);
-gint skin_get_id(void);
-void skin_draw_pixmap(Skin * skin, GdkDrawable * drawable, GdkGC * gc,
-                      SkinPixmapId pixmap_id,
-                      gint xsrc, gint ysrc, gint xdest, gint ydest,
-                      gint width, gint height);
-void skin_get_eq_spline_colors(Skin * skin, guint32 colors[19]);
-void skin_install_skin(const gchar * path);
-
-void skin_draw_playlistwin_shaded(Skin * skin,
-                                  GdkDrawable * drawable, GdkGC * gc,
-                                  gint width, gboolean focus);
-void skin_draw_playlistwin_frame(Skin * skin,
-                                 GdkDrawable * drawable, GdkGC * gc,
-                                 gint width, gint height, gboolean focus);
-
-void skin_draw_mainwin_titlebar(Skin * skin,
-                                GdkDrawable * drawable, GdkGC * gc,
-                                gboolean shaded, gboolean focus);
-
-
-void skin_parse_hints(Skin * skin, gchar *path_p);
-
-
-gboolean
-skin_reload_forced(void);
-
-#endif
--- a/audacious/skinwin.c	Wed Aug 09 02:11:01 2006 -0700
+++ b/audacious/skinwin.c	Wed Aug 09 02:47:22 2006 -0700
@@ -34,7 +34,7 @@
 #include <string.h>
 
 #include "main.h"
-#include "skin.h"
+#include "widgets/skin.h"
 #include "util.h"
 
 #include <gdk/gdkx.h>
--- a/audacious/svis.c	Wed Aug 09 02:11:01 2006 -0700
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,204 +0,0 @@
-/*  BMP - Cross-platform multimedia player
- *  Copyright (C) 2003-2004  BMP development team.
- *
- *  Based on XMMS:
- *  Copyright (C) 1998-2003  XMMS development team.
- *
- *  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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
- */
-
-#include "svis.h"
-
-#include <glib.h>
-#include <gdk/gdk.h>
-#include <string.h>
-
-#include "main.h"
-#include "mainwin.h"
-#include "plugin.h"
-#include "widget.h"
-#include "vis.h"
-
-static gint svis_redraw_delays[] = { 1, 2, 4, 8 };
-
-/* FIXME: Are the svis_scope_colors correct? */
-static guint8 svis_scope_colors[] = { 20, 19, 18, 19, 20 };
-static guint8 svis_vu_normal_colors[] = { 17, 17, 17, 12, 12, 12, 2, 2 };
-
-#define DRAW_DS_PIXEL(ptr,value) \
-	*(ptr) = (value); \
-	*((ptr) + 1) = (value); \
-	*((ptr) + 76) = (value); \
-	*((ptr) + 77) = (value);
-
-#define SVIS_HEIGHT 5
-#define SVIS_WIDTH 38
-
-void
-svis_timeout_func(SVis * svis, guchar * data)
-{
-    static GTimer *timer = NULL;
-    gulong micros = 9999999;
-    gboolean falloff = FALSE;
-    gint i;
-
-    if (!timer) {
-        timer = g_timer_new();
-        g_timer_start(timer);
-    }
-    else {
-        g_timer_elapsed(timer, &micros);
-        if (micros > 14000)
-            g_timer_reset(timer);
-
-    }
-
-    if (cfg.vis_type == INPUT_VIS_ANALYZER) {
-        if (micros > 14000)
-            falloff = TRUE;
-
-        for (i = 0; i < 2; i++) {
-            if (falloff || data) {
-                if (data && data[i] > svis->vs_data[i])
-                    svis->vs_data[i] = data[i];
-                else if (falloff) {
-                    if (svis->vs_data[i] >= 2)
-                        svis->vs_data[i] -= 2;
-                    else
-                        svis->vs_data[i] = 0;
-                }
-            }
-
-        }
-    }
-    else if (data) {
-        for (i = 0; i < 75; i++)
-            svis->vs_data[i] = data[i];
-    }
-
-    if (micros > 14000) {
-        if (!svis->vs_refresh_delay) {
-            svis_draw((Widget *) svis);
-            svis->vs_refresh_delay = svis_redraw_delays[cfg.vis_refresh];
-
-        }
-        svis->vs_refresh_delay--;
-    }
-}
-
-void
-svis_draw(Widget * w)
-{
-    SVis *svis = (SVis *) w;
-    gint x, y, h;
-    guchar svis_color[24][3];
-    guchar rgb_data[SVIS_WIDTH * 2 * SVIS_HEIGHT * 2], *ptr, c;
-    guint32 colors[24];
-    GdkRgbCmap *cmap;
-
-    GDK_THREADS_ENTER();
-
-    skin_get_viscolor(bmp_active_skin, svis_color);
-    for (y = 0; y < 24; y++) {
-        colors[y] =
-            svis_color[y][0] << 16 | svis_color[y][1] << 8 | svis_color[y][2];
-    }
-    cmap = gdk_rgb_cmap_new(colors, 24);
-
-    memset(rgb_data, 0, SVIS_WIDTH * SVIS_HEIGHT);
-    if (cfg.vis_type == VIS_ANALYZER) {
-        switch (cfg.vu_mode) {
-        case VU_NORMAL:
-            for (y = 0; y < 2; y++) {
-                ptr = rgb_data + ((y * 3) * 38);
-                h = (svis->vs_data[y] * 7) / 37;
-                for (x = 0; x < h; x++, ptr += 5) {
-                    c = svis_vu_normal_colors[x];
-                    *(ptr) = c;
-                    *(ptr + 1) = c;
-                    *(ptr + 2) = c;
-                    *(ptr + 38) = c;
-                    *(ptr + 39) = c;
-                    *(ptr + 40) = c;
-                }
-            }
-            break;
-        case VU_SMOOTH:
-            for (y = 0; y < 2; y++) {
-                ptr = rgb_data + ((y * 3) * SVIS_WIDTH);
-                for (x = 0; x < svis->vs_data[y]; x++, ptr++) {
-                    c = 17 - ((x * 15) / 37);
-                    *(ptr) = c;
-                    *(ptr + 38) = c;
-                }
-            }
-            break;
-        }
-    }
-    else if (cfg.vis_type == VIS_SCOPE) {
-        for (x = 0; x < 38; x++) {
-            h = svis->vs_data[x << 1] / 3;
-            ptr = rgb_data + ((4 - h) * 38) + x;
-            *ptr = svis_scope_colors[h];
-        }
-    }
-
-    gdk_draw_indexed_image(mainwin->window, mainwin_gc,
-                           svis->vs_widget.x, svis->vs_widget.y,
-                           svis->vs_widget.width,
-                           svis->vs_widget.height,
-                           GDK_RGB_DITHER_NORMAL, (guchar *) rgb_data,
-                           38, cmap);
-
-    gdk_rgb_cmap_free(cmap);
-    GDK_THREADS_LEAVE();
-}
-
-void
-svis_clear_data(SVis * svis)
-{
-    gint i;
-
-    if (!svis)
-        return;
-
-    for (i = 0; i < 75; i++) {
-        svis->vs_data[i] = (cfg.vis_type == VIS_SCOPE) ? 6 : 0;
-    }
-}
-
-void
-svis_clear(SVis * svis)
-{
-    gdk_window_clear_area(mainwin->window, svis->vs_widget.x,
-                          svis->vs_widget.y, svis->vs_widget.width,
-                          svis->vs_widget.height);
-}
-
-SVis *
-create_svis(GList ** wlist,
-            GdkPixmap * parent, 
-            GdkGC * gc,
-            gint x, gint y)
-{
-    SVis *svis;
-
-    svis = g_new0(SVis, 1);
-    widget_init(&svis->vs_widget, parent, gc, x, y, SVIS_WIDTH, SVIS_HEIGHT,
-                1);
-
-    widget_list_add(wlist, WIDGET(svis));
-    return svis;
-}
--- a/audacious/svis.h	Wed Aug 09 02:11:01 2006 -0700
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,47 +0,0 @@
-/*  BMP - Cross-platform multimedia player
- *  Copyright (C) 2003-2004  BMP development team.
- *
- *  Based on XMMS:
- *  Copyright (C) 1998-2003  XMMS development team.
- *
- *  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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
- */
-#ifndef SVIS_H
-#define SVIS_H
-
-#include <glib.h>
-#include <gdk/gdk.h>
-
-#include "svis.h"
-#include "widget.h"
-
-#define SVIS(x)  ((SVis *)(x))
-struct _SVis {
-    Widget vs_widget;
-    gint vs_data[75];
-    gint vs_refresh_delay;
-};
-
-typedef struct _SVis SVis;
-
-void svis_draw(Widget * w);
-void svis_timeout_func(SVis * svis, guchar * data);
-SVis *create_svis(GList ** wlist, GdkPixmap * parent, GdkGC * gc, gint x,
-                  gint y);
-void svis_set_data(SVis * vis, guchar * data);
-void svis_clear_data(SVis * vis);
-void svis_clear(SVis * vis);
-
-#endif
--- a/audacious/tbutton.c	Wed Aug 09 02:11:01 2006 -0700
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,176 +0,0 @@
-/*  BMP - Cross-platform multimedia player
- *  Copyright (C) 2003-2004  BMP development team.
- *
- *  Based on XMMS:
- *  Copyright (C) 1998-2003  XMMS development team.
- *
- *  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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
- */
-
-#include "tbutton.h"
-
-#include <glib.h>
-#include <gdk/gdk.h>
-
-#include "widget.h"
-
-void
-tbutton_draw(Widget * w)
-{
-    TButton *button = TBUTTON(w);
-    GdkPixmap *obj;
-
-    obj = button->tb_widget.parent;
-
-    if (button->tb_pressed && button->tb_inside) {
-        if (button->tb_selected) {
-            skin_draw_pixmap(bmp_active_skin, obj,
-                             button->tb_widget.gc,
-                             button->tb_skin_index,
-                             button->tb_psx, button->tb_psy,
-                             button->tb_widget.x, button->tb_widget.y,
-                             button->tb_widget.width,
-                             button->tb_widget.height);
-        }
-        else {
-            skin_draw_pixmap(bmp_active_skin, obj,
-                             button->tb_widget.gc,
-                             button->tb_skin_index,
-                             button->tb_pux, button->tb_puy,
-                             button->tb_widget.x, button->tb_widget.y,
-                             button->tb_widget.width,
-                             button->tb_widget.height);
-        }
-    }
-    else {
-        if (button->tb_selected) {
-            skin_draw_pixmap(bmp_active_skin, obj,
-                             button->tb_widget.gc,
-                             button->tb_skin_index,
-                             button->tb_nsx, button->tb_nsy,
-                             button->tb_widget.x, button->tb_widget.y,
-                             button->tb_widget.width,
-                             button->tb_widget.height);
-        }
-        else {
-            skin_draw_pixmap(bmp_active_skin, obj,
-                             button->tb_widget.gc,
-                             button->tb_skin_index,
-                             button->tb_nux, button->tb_nuy,
-                             button->tb_widget.x, button->tb_widget.y,
-                             button->tb_widget.width,
-                             button->tb_widget.height);
-
-        }
-    }
-}
-
-void
-tbutton_button_press_cb(GtkWidget * widget, GdkEventButton * event,
-                        TButton * button)
-{
-    if (event->button != 1)
-        return;
-
-    if (widget_contains(&button->tb_widget, event->x, event->y)) {
-        button->tb_pressed = 1;
-        button->tb_inside = 1;
-        widget_draw(WIDGET(button));
-    }
-}
-
-void
-tbutton_button_release_cb(GtkWidget * widget, GdkEventButton * event,
-                          TButton * button)
-{
-    if (event->button != 1)
-        return;
-
-    if (button->tb_inside && button->tb_pressed) {
-        button->tb_inside = 0;
-        button->tb_selected = !button->tb_selected;
-
-        widget_draw(WIDGET(button));
-
-        if (button->tb_push_cb)
-            button->tb_push_cb(button->tb_selected);
-    }
-
-    if (button->tb_pressed)
-        button->tb_pressed = 0;
-}
-
-void
-tbutton_motion_cb(GtkWidget * widget, GdkEventMotion * event,
-                  TButton * button)
-{
-    gint inside;
-
-    if (!button->tb_pressed)
-        return;
-    inside = widget_contains(&button->tb_widget, event->x, event->y);
-    if (inside != button->tb_inside) {
-        button->tb_inside = inside;
-        widget_draw(WIDGET(button));
-    }
-}
-
-TButton *
-create_tbutton(GList ** wlist, GdkPixmap * parent, GdkGC * gc,
-               gint x, gint y, gint w, gint h, gint nux, gint nuy,
-               gint pux, gint puy, gint nsx, gint nsy, gint psx,
-               gint psy, void (*cb) (gboolean), SkinPixmapId si)
-{
-    TButton *b;
-
-    b = g_new0(TButton, 1);
-    widget_init(&b->tb_widget, parent, gc, x, y, w, h, 1);
-    b->tb_widget.button_press_cb =
-        (void (*)(GtkWidget *, GdkEventButton *, gpointer))
-        tbutton_button_press_cb;
-    b->tb_widget.button_release_cb =
-        (void (*)(GtkWidget *, GdkEventButton *, gpointer))
-        tbutton_button_release_cb;
-    b->tb_widget.motion_cb =
-        (void (*)(GtkWidget *, GdkEventMotion *, gpointer))
-        tbutton_motion_cb;
-    b->tb_widget.draw = tbutton_draw;
-    b->tb_nux = nux;
-    b->tb_nuy = nuy;
-    b->tb_pux = pux;
-    b->tb_puy = puy;
-    b->tb_nsx = nsx;
-    b->tb_nsy = nsy;
-    b->tb_psx = psx;
-    b->tb_psy = psy;
-    b->tb_push_cb = cb;
-    b->tb_skin_index = si;
-
-    widget_list_add(wlist, WIDGET(b));
-    return b;
-}
-
-void
-tbutton_set_toggled(TButton * tb, gboolean toggled)
-{
-    tb->tb_selected = toggled;
-    widget_draw(WIDGET(tb));
-}
-
-void
-free_tbutton(TButton * b)
-{
-    g_free(b);
-}
--- a/audacious/tbutton.h	Wed Aug 09 02:11:01 2006 -0700
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,48 +0,0 @@
-/*  BMP - Cross-platform multimedia player
- *  Copyright (C) 2003-2004  BMP development team.
- *
- *  Based on XMMS:
- *  Copyright (C) 1998-2003  XMMS development team.
- *
- *  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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
- */
-
-#ifndef TBUTTON_H
-#define TBUTTON_H
-
-#include <glib.h>
-
-#include "skin.h"
-#include "widget.h"
-
-#define TBUTTON(x) ((TButton *)(x))
-struct _TButton {
-    Widget tb_widget;
-    gint tb_nux, tb_nuy, tb_pux, tb_puy, tb_nsx, tb_nsy, tb_psx, tb_psy;
-    gint tb_pressed, tb_inside, tb_selected;
-    void (*tb_push_cb) (gboolean);
-    SkinPixmapId tb_skin_index;
-};
-
-typedef struct _TButton TButton;
-
-TButton *create_tbutton(GList ** wlist, GdkPixmap * parent, GdkGC * gc,
-                        gint x, gint y, gint w, gint h, gint nux, gint nuy,
-                        gint pux, gint puy, gint nsx, gint nsy, gint psx,
-                        gint psy, void (*cb) (gboolean), SkinPixmapId si);
-void tbutton_set_toggled(TButton * tb, gboolean toggled);
-void free_tbutton(TButton * b);
-
-#endif
--- a/audacious/textbox.c	Wed Aug 09 02:11:01 2006 -0700
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,579 +0,0 @@
-/*  BMP - Cross-platform multimedia player
- *  Copyright (C) 2003-2004  BMP development team.
- *
- *  Based on XMMS:
- *  Copyright (C) 1998-2003  XMMS development team.
- *
- *  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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
- */
-
-#include "textbox.h"
-
-#include <glib.h>
-#include <gtk/gtk.h>
-#include <gdk/gdk.h>
-#include <gdk/gdkprivate.h>
-#include <string.h>
-#include <ctype.h>
-
-#include "main.h"
-#include "util.h"
-
-static void textbox_generate_pixmap(TextBox * tb);
-
-static void
-textbox_draw(Widget * w)
-{
-    TextBox *tb = TEXT_BOX(w);
-    gint cw;
-    GdkPixmap *obj;
-    GdkPixmap *src;
-
-    g_return_if_fail(tb != NULL);
-
-    if (tb->tb_text &&
-        (!tb->tb_pixmap_text || strcmp(tb->tb_text, tb->tb_pixmap_text)))
-        textbox_generate_pixmap(tb);
-
-    if (tb->tb_pixmap) {
-        if (skin_get_id() != tb->tb_skin_id) {
-            tb->tb_skin_id = skin_get_id();
-            textbox_generate_pixmap(tb);
-        }
-        obj = tb->tb_widget.parent;
-        src = tb->tb_pixmap;
-
-        cw = tb->tb_pixmap_width - tb->tb_offset;
-        if (cw > tb->tb_widget.width)
-            cw = tb->tb_widget.width;
-        gdk_draw_pixmap(obj, tb->tb_widget.gc, src, tb->tb_offset, 0,
-                        tb->tb_widget.x, tb->tb_widget.y, cw,
-                        tb->tb_widget.height);
-        if (cw < tb->tb_widget.width)
-            gdk_draw_pixmap(obj, tb->tb_widget.gc, src, 0, 0,
-                            tb->tb_widget.x + cw, tb->tb_widget.y,
-                            tb->tb_widget.width - cw, tb->tb_widget.height);
-    }
-}
-
-static gboolean
-textbox_scroll(gpointer data)
-{
-    TextBox *tb = TEXT_BOX(data);
-
-    if (!tb->tb_is_dragging) {
-        tb->tb_offset += 1;
-        if (tb->tb_offset >= tb->tb_pixmap_width)
-            tb->tb_offset -= tb->tb_pixmap_width;
-        widget_draw(WIDGET(tb));
-    }
-
-    return TRUE;
-}
-
-static void
-textbox_button_press(GtkWidget * w, GdkEventButton * event, gpointer data)
-{
-    TextBox *tb = TEXT_BOX(data);
-
-    if (event->button != 1)
-        return;
-    if (widget_contains(&tb->tb_widget, event->x, event->y) &&
-        tb->tb_scroll_allowed &&
-        tb->tb_pixmap_width > tb->tb_widget.width && tb->tb_is_scrollable) {
-        tb->tb_is_dragging = TRUE;
-        tb->tb_drag_off = tb->tb_offset;
-        tb->tb_drag_x = event->x;
-    }
-}
-
-static void
-textbox_motion(GtkWidget * w, GdkEventMotion * event, gpointer data)
-{
-    TextBox *tb = TEXT_BOX(data);
-
-    if (tb->tb_is_dragging) {
-        if (tb->tb_scroll_allowed &&
-            tb->tb_pixmap_width > tb->tb_widget.width) {
-            tb->tb_offset = tb->tb_drag_off - (event->x - tb->tb_drag_x);
-
-            while (tb->tb_offset < 0)
-                tb->tb_offset += tb->tb_pixmap_width;
-
-            while (tb->tb_offset > tb->tb_pixmap_width)
-                tb->tb_offset -= tb->tb_pixmap_width;
-
-            widget_draw(WIDGET(tb));
-        }
-    }
-}
-
-static void
-textbox_button_release(GtkWidget * w, GdkEventButton * event, gpointer data)
-{
-    TextBox *tb = TEXT_BOX(data);
-
-    if (event->button == 1)
-        tb->tb_is_dragging = FALSE;
-}
-
-static gboolean
-textbox_should_scroll(TextBox * tb)
-{
-    g_return_val_if_fail(tb != NULL, FALSE);
-
-    if (!tb->tb_scroll_allowed)
-        return FALSE;
-
-    if (tb->tb_font) {
-        gint width;
-
-        text_get_extents(tb->tb_fontname, tb->tb_text, &width, NULL, NULL,
-                         NULL);
-
-        if (width <= tb->tb_widget.width)
-            return FALSE;
-        else
-            return TRUE;
-    }
-
-    if (g_utf8_strlen(tb->tb_text, -1) * 5 > tb->tb_widget.width)
-        return TRUE;
-
-    return FALSE;
-}
-
-void
-textbox_set_text(TextBox * tb, const gchar * text)
-{
-    g_return_if_fail(tb != NULL);
-    g_return_if_fail(text != NULL);
-
-    widget_lock(WIDGET(tb));
-
-    if (tb->tb_text) {
-        if (!strcmp(text, tb->tb_text)) {
-            widget_unlock(WIDGET(tb));
-            return;
-        }
-        g_free(tb->tb_text);
-    }
-
-    tb->tb_text = str_to_utf8(text);
-
-    widget_unlock(WIDGET(tb));
-    widget_draw(WIDGET(tb));
-}
-
-static void
-textbox_generate_xfont_pixmap(TextBox * tb, const gchar * pixmaptext)
-{
-    gint length, i;
-    GdkGC *gc, *maskgc;
-    GdkColor *c, pattern;
-    GdkBitmap *mask;
-    PangoLayout *layout;
-    gint width;
-
-    g_return_if_fail(tb != NULL);
-    g_return_if_fail(pixmaptext != NULL);
-
-    length = g_utf8_strlen(pixmaptext, -1);
-
-    text_get_extents(tb->tb_fontname, pixmaptext, &width, NULL, NULL, NULL);
-
-    tb->tb_pixmap_width = MAX(width, tb->tb_widget.width);
-    tb->tb_pixmap = gdk_pixmap_new(mainwin->window, tb->tb_pixmap_width,
-                                   tb->tb_widget.height,
-                                   gdk_rgb_get_visual()->depth);
-    gc = tb->tb_widget.gc;
-    c = skin_get_color(bmp_active_skin, SKIN_TEXTBG);
-    for (i = 0; i < tb->tb_widget.height; i++) {
-        gdk_gc_set_foreground(gc, &c[6 * i / tb->tb_widget.height]);
-        gdk_draw_line(tb->tb_pixmap, gc, 0, i, tb->tb_pixmap_width, i);
-    }
-
-    mask = gdk_pixmap_new(mainwin->window, tb->tb_pixmap_width,
-                          tb->tb_widget.height, 1);
-    maskgc = gdk_gc_new(mask);
-    pattern.pixel = 0;
-    gdk_gc_set_foreground(maskgc, &pattern);
-
-    gdk_draw_rectangle(mask, maskgc, TRUE, 0, 0,
-                       tb->tb_pixmap_width, tb->tb_widget.height);
-    pattern.pixel = 1;
-    gdk_gc_set_foreground(maskgc, &pattern);
-
-    gdk_gc_set_foreground(gc, skin_get_color(bmp_active_skin, SKIN_TEXTFG));
-
-    layout = gtk_widget_create_pango_layout(mainwin, pixmaptext);
-    pango_layout_set_font_description(layout, tb->tb_font);
-
-    gdk_draw_layout(tb->tb_pixmap, gc, 0, (tb->tb_font_descent / 2), layout);
-    g_object_unref(layout);
-
-    g_object_unref(maskgc);
-
-    gdk_gc_set_clip_mask(gc, mask);
-    c = skin_get_color(bmp_active_skin, SKIN_TEXTFG);
-    for (i = 0; i < tb->tb_widget.height; i++) {
-        gdk_gc_set_foreground(gc, &c[6 * i / tb->tb_widget.height]);
-        gdk_draw_line(tb->tb_pixmap, gc, 0, i, tb->tb_pixmap_width, i);
-    }
-    g_object_unref(mask);
-    gdk_gc_set_clip_mask(gc, NULL);
-}
-
-static void
-textbox_handle_special_char(gchar c, gint * x, gint * y)
-{
-    switch (c) {
-    case '"':
-        *x = 130;
-        *y = 0;
-        break;
-    case '\r':
-        *x = 50;
-        *y = 6;
-        break;
-    case ':':
-    case ';':
-        *x = 60;
-        *y = 6;
-        break;
-    case '(':
-        *x = 65;
-        *y = 6;
-        break;
-    case ')':
-        *x = 70;
-        *y = 6;
-        break;
-    case '-':
-        *x = 75;
-        *y = 6;
-        break;
-    case '`':
-    case '\'':
-        *x = 80;
-        *y = 6;
-        break;
-    case '!':
-        *x = 85;
-        *y = 6;
-        break;
-    case '_':
-        *x = 90;
-        *y = 6;
-        break;
-    case '+':
-        *x = 95;
-        *y = 6;
-        break;
-    case '\\':
-        *x = 100;
-        *y = 6;
-        break;
-    case '/':
-        *x = 105;
-        *y = 6;
-        break;
-    case '[':
-        *x = 110;
-        *y = 6;
-        break;
-    case ']':
-        *x = 115;
-        *y = 6;
-        break;
-    case '^':
-        *x = 120;
-        *y = 6;
-        break;
-    case '&':
-        *x = 125;
-        *y = 6;
-        break;
-    case '%':
-        *x = 130;
-        *y = 6;
-        break;
-    case '.':
-    case ',':
-        *x = 135;
-        *y = 6;
-        break;
-    case '=':
-        *x = 140;
-        *y = 6;
-        break;
-    case '$':
-        *x = 145;
-        *y = 6;
-        break;
-    case '#':
-        *x = 150;
-        *y = 6;
-        break;
-    case 'å':
-    case 'Å':
-        *x = 0;
-        *y = 12;
-        break;
-    case 'ö':
-    case 'Ö':
-        *x = 5;
-        *y = 12;
-        break;
-    case 'ä':
-    case 'Ä':
-        *x = 10;
-        *y = 12;
-        break;
-    case 'ü':
-    case 'Ü':
-        *x = 100;
-        *y = 0;
-        break;
-    case '?':
-        *x = 15;
-        *y = 12;
-        break;
-    case '*':
-        *x = 20;
-        *y = 12;
-        break;
-    default:
-        *x = 145;
-        *y = 0;
-        break;
-    }
-}
-
-static void
-textbox_generate_pixmap(TextBox * tb)
-{
-    gint length, i, x, y, wl;
-    gchar *pixmaptext;
-    GdkGC *gc;
-
-    g_return_if_fail(tb != NULL);
-
-    if (tb->tb_pixmap) {
-        g_object_unref(tb->tb_pixmap);
-        tb->tb_pixmap = NULL;
-    }
-
-    /*
-     * Don't reset the offset if only text after the last '(' has
-     * changed.  This is a hack to avoid visual noice on vbr files
-     * where we guess the length.
-     */
-    if (!(tb->tb_pixmap_text && strrchr(tb->tb_text, '(') &&
-          !strncmp(tb->tb_pixmap_text, tb->tb_text,
-                   strrchr(tb->tb_text, '(') - tb->tb_text)))
-        tb->tb_offset = 0;
-
-    g_free(tb->tb_pixmap_text);
-    tb->tb_pixmap_text = g_strdup(tb->tb_text);
-
-    /*
-     * wl is the number of (partial) letters visible. Only makes
-     * sense when using skinned font.
-     */
-
-    wl = tb->tb_widget.width / 5;
-    if (wl * 5 != tb->tb_widget.width)
-        wl++;
-
-    length = g_utf8_strlen(tb->tb_text, -1);
-
-    tb->tb_is_scrollable = FALSE;
-
-    if (textbox_should_scroll(tb)) {
-        tb->tb_is_scrollable = TRUE;
-        pixmaptext = g_strconcat(tb->tb_pixmap_text, "  ***  ", NULL);
-        length += 7;
-    }
-    else if (!tb->tb_font && length <= wl) {
-        gint pad = wl - length;
-        gchar *padchars = g_strnfill(pad, ' ');
-
-        pixmaptext = g_strconcat(tb->tb_pixmap_text, padchars, NULL);
-        g_free(padchars);
-        length += pad;
-    }
-    else
-        pixmaptext = g_strdup(tb->tb_pixmap_text);
-
-
-    if (tb->tb_is_scrollable) {
-        if (tb->tb_scroll_enabled && !tb->tb_timeout_tag) {
-            gint tag;
-            tag = TEXTBOX_SCROLL_SMOOTH_TIMEOUT;
-            tb->tb_timeout_tag = gtk_timeout_add(tag, textbox_scroll, tb);
-        }
-    }
-    else {
-        if (tb->tb_timeout_tag) {
-            gtk_timeout_remove(tb->tb_timeout_tag);
-            tb->tb_timeout_tag = 0;
-        }
-        tb->tb_offset = 0;
-    }
-
-    if (tb->tb_font) {
-        textbox_generate_xfont_pixmap(tb, pixmaptext);
-        g_free(pixmaptext);
-        return;
-    }
-
-    tb->tb_pixmap_width = length * 5;
-    tb->tb_pixmap = gdk_pixmap_new(mainwin->window,
-                                   tb->tb_pixmap_width, 6,
-                                   gdk_rgb_get_visual()->depth);
-    gc = tb->tb_widget.gc;
-
-    for (i = 0; i < length; i++) {
-        gchar c;
-        x = y = -1;
-        c = toupper(pixmaptext[i]);
-        if (c >= 'A' && c <= 'Z') {
-            x = 5 * (c - 'A');
-            y = 0;
-        }
-        else if (c >= '0' && c <= '9') {
-            x = 5 * (c - '0');
-            y = 6;
-        }
-        else
-            textbox_handle_special_char(c, &x, &y);
-
-        skin_draw_pixmap(bmp_active_skin,
-                         tb->tb_pixmap, gc, tb->tb_skin_index,
-                         x, y, i * 5, 0, 5, 6);
-    }
-    g_free(pixmaptext);
-}
-
-void
-textbox_set_scroll(TextBox * tb, gboolean s)
-{
-    g_return_if_fail(tb != NULL);
-
-    tb->tb_scroll_enabled = s;
-    if (tb->tb_scroll_enabled && tb->tb_is_scrollable
-        && tb->tb_scroll_allowed) {
-        gint tag;
-        tag = TEXTBOX_SCROLL_SMOOTH_TIMEOUT;
-
-	if (tb->tb_timeout_tag)
-        {
-	    gtk_timeout_remove(tb->tb_timeout_tag);
-            tb->tb_timeout_tag = 0;
-	}
-
-        tb->tb_timeout_tag = gtk_timeout_add(tag, textbox_scroll, tb);
-    }
-    else
-    {
-        if (tb->tb_timeout_tag)
-        {
-            gtk_timeout_remove(tb->tb_timeout_tag);
-            tb->tb_timeout_tag = 0;
-        }
-
-        tb->tb_offset = 0;
-        widget_draw(WIDGET(tb));
-    }
-
-}
-
-void
-textbox_set_xfont(TextBox * tb, gboolean use_xfont, const gchar * fontname)
-{
-    gint ascent, descent;
-
-    g_return_if_fail(tb != NULL);
-
-    if (tb->tb_font) {
-        pango_font_description_free(tb->tb_font);
-        tb->tb_font = NULL;
-    }
-
-    tb->tb_widget.y = tb->tb_nominal_y;
-    tb->tb_widget.height = tb->tb_nominal_height;
-
-    /* Make sure the pixmap is regenerated */
-    if (tb->tb_pixmap_text) {
-        g_free(tb->tb_pixmap_text);
-        tb->tb_pixmap_text = NULL;
-    }
-
-    if (!use_xfont || strlen(fontname) == 0)
-        return;
-
-    tb->tb_font = pango_font_description_from_string(fontname);
-    tb->tb_fontname = g_strdup(fontname);
-
-    text_get_extents(fontname,
-                     "AaBbCcDdEeFfGgHhIiJjKkLlMmNnOoPpQqRrSsTtUuVvWwXxYyZz ",
-                     NULL, NULL, &ascent, &descent);
-    tb->tb_font_ascent = ascent;
-    tb->tb_font_descent = descent;
-
-
-    if (tb->tb_font == NULL)
-        return;
-
-    tb->tb_widget.height = tb->tb_font_ascent;
-    if (tb->tb_widget.height > tb->tb_nominal_height)
-        tb->tb_widget.y -= (tb->tb_widget.height - tb->tb_nominal_height) / 2;
-    else
-        tb->tb_widget.height = tb->tb_nominal_height;
-}
-
-TextBox *
-create_textbox(GList ** wlist, GdkPixmap * parent, GdkGC * gc,
-               gint x, gint y, gint w, gboolean allow_scroll, SkinPixmapId si)
-{
-    TextBox *tb;
-
-    tb = g_new0(TextBox, 1);
-    widget_init(&tb->tb_widget, parent, gc, x, y, w, 6, 1);
-    tb->tb_widget.button_press_cb = textbox_button_press;
-    tb->tb_widget.button_release_cb = textbox_button_release;
-    tb->tb_widget.motion_cb = textbox_motion;
-    tb->tb_widget.draw = textbox_draw;
-    tb->tb_scroll_allowed = allow_scroll;
-    tb->tb_scroll_enabled = TRUE;
-    tb->tb_skin_index = si;
-    tb->tb_nominal_y = y;
-    tb->tb_nominal_height = tb->tb_widget.height;
-    widget_list_add(wlist, WIDGET(tb));
-    tb->tb_timeout_tag = 0;
-    return tb;
-}
-
-void
-textbox_free(TextBox * tb)
-{
-    g_return_if_fail(tb != NULL);
-
-    if (tb->tb_pixmap)
-        g_object_unref(tb->tb_pixmap);
-    g_free(tb->tb_text);
-    g_free(tb);
-}
--- a/audacious/textbox.h	Wed Aug 09 02:11:01 2006 -0700
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,64 +0,0 @@
-/*  BMP - Cross-platform multimedia player
- *  Copyright (C) 2003-2004  BMP development team.
- *
- *  Based on XMMS:
- *  Copyright (C) 1998-2003  XMMS development team.
- *
- *  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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
- */
-
-#ifndef TEXTBOX_H
-#define	TEXTBOX_H
-
-#include <glib.h>
-#include <gdk/gdk.h>
-#include <pango/pango.h>
-
-#include "skin.h"
-#include "widget.h"
-
-#define	TEXTBOX_SCROLL_TIMEOUT	       200
-#define TEXTBOX_SCROLL_SMOOTH_TIMEOUT  30
-
-#define TEXT_BOX(x)  ((TextBox *)(x))
-struct _TextBox {
-    Widget tb_widget;
-    GdkPixmap *tb_pixmap;
-    gchar *tb_text, *tb_pixmap_text;
-    gint tb_pixmap_width;
-    gint tb_offset;
-    gboolean tb_scroll_allowed, tb_scroll_enabled;
-    gboolean tb_is_scrollable, tb_is_dragging;
-    gint tb_timeout_tag, tb_drag_x, tb_drag_off;
-    gint tb_nominal_y, tb_nominal_height;
-    gint tb_skin_id;
-    SkinPixmapId tb_skin_index;
-    PangoFontDescription *tb_font;
-    gint tb_font_ascent, tb_font_descent;
-    gchar *tb_fontname;
-};
-
-typedef struct _TextBox TextBox;
-
-void textbox_set_text(TextBox * tb, const gchar * text);
-void textbox_set_scroll(TextBox * tb, gboolean s);
-TextBox *create_textbox(GList ** wlist, GdkPixmap * parent, GdkGC * gc,
-                        gint x, gint y, gint w, gboolean allow_scroll,
-                        SkinPixmapId si);
-void textbox_set_xfont(TextBox * tb, gboolean use_xfont,
-                       const gchar * fontname);
-void textbox_free(TextBox * tb);
-
-#endif
--- a/audacious/ui_fileinfo.c	Wed Aug 09 02:11:01 2006 -0700
+++ b/audacious/ui_fileinfo.c	Wed Aug 09 02:47:22 2006 -0700
@@ -47,7 +47,6 @@
 #include "visualization.h"
 
 #include "main.h"
-#include "skin.h"
 #include "urldecode.h"
 #include "util.h"
 #include "dnd.h"
@@ -59,7 +58,6 @@
 #include "mainwin.h"
 #include "ui_playlist.h"
 #include "skinwin.h"
-#include "playlist_list.h"
 #include "build_stamp.h"
 #include "ui_fileinfo.h"
 #include "ui_playlist.h"
--- a/audacious/ui_playlist.c	Wed Aug 09 02:11:01 2006 -0700
+++ b/audacious/ui_playlist.c	Wed Aug 09 02:47:22 2006 -0700
@@ -48,12 +48,12 @@
 #include "mainwin.h"
 #include "playback.h"
 #include "playlist.h"
-#include "playlist_list.h"
-#include "playlist_slider.h"
-#include "pbutton.h"
-#include "sbutton.h"
-#include "skin.h"
-#include "textbox.h"
+#include "widgets/playlist_list.h"
+#include "widgets/playlist_slider.h"
+#include "widgets/pbutton.h"
+#include "widgets/sbutton.h"
+#include "widgets/skin.h"
+#include "widgets/textbox.h"
 #include "util.h"
 
 #include "pixmaps.h"
--- a/audacious/ui_playlist.h	Wed Aug 09 02:11:01 2006 -0700
+++ b/audacious/ui_playlist.h	Wed Aug 09 02:47:22 2006 -0700
@@ -25,8 +25,8 @@
 #include <glib.h>
 
 #include "mainwin.h"
-#include "pbutton.h"
-#include "playlist_list.h"
+#include "widgets/pbutton.h"
+#include "widgets/playlist_list.h"
 
 
 #define PLAYLISTWIN_FRAME_TOP_HEIGHT    20
--- a/audacious/vis.c	Wed Aug 09 02:11:01 2006 -0700
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,291 +0,0 @@
-/*  BMP - Cross-platform multimedia player
- *  Copyright (C) 2003-2004  BMP development team.
- *
- *  Based on XMMS:
- *  Copyright (C) 1998-2003  XMMS development team.
- *
- *  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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
- */
-
-#include "vis.h"
-
-#include <glib.h>
-#include <gdk/gdk.h>
-#include <string.h>
-
-#include "main.h"
-#include "skin.h"
-#include "widget.h"
-
-static const gfloat vis_afalloff_speeds[] = { 0.34, 0.5, 1.0, 1.3, 1.6 };
-static const gfloat vis_pfalloff_speeds[] = { 1.2, 1.3, 1.4, 1.5, 1.6 };
-static const gint vis_redraw_delays[] = { 1, 2, 4, 8 };
-static const guint8 vis_scope_colors[] =
-    { 21, 21, 20, 20, 19, 19, 18, 19, 19, 20, 20, 21, 21 };
-
-void
-vis_timeout_func(Vis * vis, guchar * data)
-{
-    static GTimer *timer = NULL;
-    gulong micros = 9999999;
-    gboolean falloff = FALSE;
-    gint i;
-
-    if (!timer) {
-        timer = g_timer_new();
-        g_timer_start(timer);
-    }
-    else {
-        g_timer_elapsed(timer, &micros);
-        if (micros > 14000)
-            g_timer_reset(timer);
-
-    }
-
-    if (cfg.vis_type == VIS_ANALYZER) {
-        if (micros > 14000)
-            falloff = TRUE;
-        if (data || falloff) {
-            for (i = 0; i < 75; i++) {
-                if (data && data[i] > vis->vs_data[i]) {
-                    vis->vs_data[i] = data[i];
-                    if (vis->vs_data[i] > vis->vs_peak[i]) {
-                        vis->vs_peak[i] = vis->vs_data[i];
-                        vis->vs_peak_speed[i] = 0.01;
-
-                    }
-                    else if (vis->vs_peak[i] > 0.0) {
-                        vis->vs_peak[i] -= vis->vs_peak_speed[i];
-                        vis->vs_peak_speed[i] *=
-                            vis_pfalloff_speeds[cfg.peaks_falloff];
-                        if (vis->vs_peak[i] < vis->vs_data[i])
-                            vis->vs_peak[i] = vis->vs_data[i];
-                        if (vis->vs_peak[i] < 0.0)
-                            vis->vs_peak[i] = 0.0;
-                    }
-                }
-                else if (falloff) {
-                    if (vis->vs_data[i] > 0.0) {
-                        vis->vs_data[i] -=
-                            vis_afalloff_speeds[cfg.analyzer_falloff];
-                        if (vis->vs_data[i] < 0.0)
-                            vis->vs_data[i] = 0.0;
-                    }
-                    if (vis->vs_peak[i] > 0.0) {
-                        vis->vs_peak[i] -= vis->vs_peak_speed[i];
-                        vis->vs_peak_speed[i] *=
-                            vis_pfalloff_speeds[cfg.peaks_falloff];
-                        if (vis->vs_peak[i] < vis->vs_data[i])
-                            vis->vs_peak[i] = vis->vs_data[i];
-                        if (vis->vs_peak[i] < 0.0)
-                            vis->vs_peak[i] = 0.0;
-                    }
-                }
-            }
-        }
-    }
-    else if (data) {
-        for (i = 0; i < 75; i++)
-            vis->vs_data[i] = data[i];
-    }
-
-    if (micros > 14000) {
-        if (!vis->vs_refresh_delay) {
-            vis_draw((Widget *) vis);
-            vis->vs_refresh_delay = vis_redraw_delays[cfg.vis_refresh];
-
-        }
-        vis->vs_refresh_delay--;
-    }
-}
-
-void
-vis_draw(Widget * w)
-{
-    Vis *vis = (Vis *) w;
-    gint x, y, h = 0, h2;
-    guchar vis_color[24][3];
-    guchar rgb_data[152 * 32], *ptr, c;
-    guint32 colors[24];
-    GdkRgbCmap *cmap;
-
-    if (!vis->vs_widget.visible)
-        return;
-
-    skin_get_viscolor(bmp_active_skin, vis_color);
-    for (y = 0; y < 24; y++) {
-        colors[y] =
-            vis_color[y][0] << 16 | vis_color[y][1] << 8 | vis_color[y][2];
-    }
-    cmap = gdk_rgb_cmap_new(colors, 24);
-
-    memset(rgb_data, 0, 76 * 16);
-    for (y = 1; y < 16; y += 2) {
-        ptr = rgb_data + (y * 76);
-        for (x = 0; x < 76; x += 2, ptr += 2)
-            *ptr = 1;
-    }
-    if (cfg.vis_type == VIS_ANALYZER) {
-        for (x = 0; x < 75; x++) {
-            if (cfg.analyzer_type == ANALYZER_BARS && (x % 4) == 0)
-                h = vis->vs_data[x >> 2];
-            else if (cfg.analyzer_type == ANALYZER_LINES)
-                h = vis->vs_data[x];
-            if (h && (cfg.analyzer_type == ANALYZER_LINES ||
-                      (x % 4) != 3)) {
-                ptr = rgb_data + ((16 - h) * 76) + x;
-                switch (cfg.analyzer_mode) {
-                case ANALYZER_NORMAL:
-                    for (y = 0; y < h; y++, ptr += 76)
-                        *ptr = 18 - h + y;
-                    break;
-                case ANALYZER_FIRE:
-                    for (y = 0; y < h; y++, ptr += 76)
-                        *ptr = y + 2;
-                    break;
-                case ANALYZER_VLINES:
-                    for (y = 0; y < h; y++, ptr += 76)
-                        *ptr = 18 - h;
-                    break;
-                }
-            }
-        }
-        if (cfg.analyzer_peaks) {
-            for (x = 0; x < 75; x++) {
-                if (cfg.analyzer_type == ANALYZER_BARS && (x % 4) == 0)
-                    h = vis->vs_peak[x >> 2];
-                else if (cfg.analyzer_type == ANALYZER_LINES)
-                    h = vis->vs_peak[x];
-                if (h
-                    && (cfg.analyzer_type == ANALYZER_LINES
-                        || (x % 4) != 3))
-                    rgb_data[(16 - h) * 76 + x] = 23;
-            }
-        }
-    }
-    else if (cfg.vis_type == VIS_SCOPE) {
-        for (x = 0; x < 75; x++) {
-            switch (cfg.scope_mode) {
-            case SCOPE_DOT:
-                h = vis->vs_data[x];
-                ptr = rgb_data + ((15 - h) * 76) + x;
-                *ptr = vis_scope_colors[h];
-                break;
-            case SCOPE_LINE:
-                if (x != 74) {
-                    h = 15 - vis->vs_data[x];
-                    h2 = 15 - vis->vs_data[x + 1];
-                    if (h > h2) {
-                        y = h;
-                        h = h2;
-                        h2 = y;
-                    }
-                    ptr = rgb_data + (h * 76) + x;
-                    for (y = h; y <= h2; y++, ptr += 76)
-                        *ptr = vis_scope_colors[y - 3];
-
-                }
-                else {
-                    h = 15 - vis->vs_data[x];
-                    ptr = rgb_data + (h * 76) + x;
-                    *ptr = vis_scope_colors[h];
-                }
-                break;
-            case SCOPE_SOLID:
-                h = 15 - vis->vs_data[x];
-                h2 = 9;
-                c = vis_scope_colors[(gint) vis->vs_data[x]];
-                if (h > h2) {
-                    y = h;
-                    h = h2;
-                    h2 = y;
-                }
-                ptr = rgb_data + (h * 76) + x;
-                for (y = h; y <= h2; y++, ptr += 76)
-                    *ptr = c;
-                break;
-            }
-        }
-    }
-
-    /* FIXME: The check "shouldn't" be neccessary? */
-    /*	if (GTK_IS_WINDOW(vis->vs_window)) { */
-    GDK_THREADS_ENTER();
-    gdk_draw_indexed_image(vis->vs_window, vis->vs_widget.gc,
-                           vis->vs_widget.x, vis->vs_widget.y,
-                           vis->vs_widget.width, vis->vs_widget.height,
-                           GDK_RGB_DITHER_NORMAL, (guchar *) rgb_data,
-                           76, cmap);
-    GDK_THREADS_LEAVE();
-    /*	} else {
-        vis->vs_window = mainwin->window;
-        GDK_THREADS_ENTER();
-        gdk_draw_indexed_image(vis->vs_window, vis->vs_widget.gc,
-        vis->vs_widget.x, vis->vs_widget.y,
-        vis->vs_widget.width, vis->vs_widget.height,
-        GDK_RGB_DITHER_NORMAL, (guchar *) rgb_data,
-        76, cmap);
-        GDK_THREADS_LEAVE();
-        }
-    */
-
-    gdk_rgb_cmap_free(cmap);
-}
-
-void
-vis_clear_data(Vis * vis)
-{
-    gint i;
-
-    if (!vis)
-        return;
-
-    for (i = 0; i < 75; i++) {
-        vis->vs_data[i] = (cfg.vis_type == VIS_SCOPE) ? 6 : 0;
-        vis->vs_peak[i] = 0;
-    }
-}
-
-void
-vis_clear(Vis * vis)
-{
-    gdk_window_clear_area(vis->vs_window, vis->vs_widget.x,
-                          vis->vs_widget.y, vis->vs_widget.width,
-                          vis->vs_widget.height);
-}
-
-void
-vis_set_window(Vis * vis, GdkWindow * window)
-{
-    vis->vs_window = window;
-}
-
-Vis *
-create_vis(GList ** wlist,
-           GdkPixmap * parent,
-           GdkWindow * window,
-           GdkGC * gc,
-           gint x, gint y,
-           gint width)
-{
-    Vis *vis;
-
-    vis = g_new0(Vis, 1);
-
-    widget_init(&vis->vs_widget, parent, gc, x, y, width, 16, 1);
-    widget_list_add(wlist, WIDGET(vis));
-
-    return vis;
-}
--- a/audacious/vis.h	Wed Aug 09 02:11:01 2006 -0700
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,77 +0,0 @@
-/*  BMP - Cross-platform multimedia player
- *  Copyright (C) 2003-2004  BMP development team.
- *
- *  Based on XMMS:
- *  Copyright (C) 1998-2003  XMMS development team.
- *
- *  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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
- */
-#ifndef VIS_H
-#define VIS_H
-
-#include <glib.h>
-#include <gdk/gdk.h>
-
-#include "widget.h"
-
-typedef enum {
-    VIS_ANALYZER, VIS_SCOPE, VIS_OFF
-} VisType;
-
-typedef enum {
-    ANALYZER_NORMAL, ANALYZER_FIRE, ANALYZER_VLINES
-} AnalyzerMode;
-
-typedef enum {
-    ANALYZER_LINES, ANALYZER_BARS
-} AnalyzerType;
-
-typedef enum {
-    SCOPE_DOT, SCOPE_LINE, SCOPE_SOLID
-} ScopeMode;
-
-typedef enum {
-    VU_NORMAL, VU_SMOOTH
-} VUMode;
-
-typedef enum {
-    REFRESH_FULL, REFRESH_HALF, REFRESH_QUARTER, REFRESH_EIGTH
-} RefreshRate;
-
-typedef enum {
-    FALLOFF_SLOWEST, FALLOFF_SLOW, FALLOFF_MEDIUM, FALLOFF_FAST,
-    FALLOFF_FASTEST
-} FalloffSpeed;
-
-#define VIS(x)  ((Vis *)(x))
-struct _Vis {
-    Widget vs_widget;
-    GdkWindow *vs_window;
-    gfloat vs_data[75], vs_peak[75], vs_peak_speed[75];
-    gint vs_refresh_delay;
-};
-
-typedef struct _Vis Vis;
-
-void vis_draw(Widget * w);
-
-Vis *create_vis(GList ** wlist, GdkPixmap * parent, GdkWindow * window,
-                GdkGC * gc, gint x, gint y, gint width);
-void vis_timeout_func(Vis * vis, guchar * data);
-void vis_clear_data(Vis * vis);
-void vis_clear(Vis * vis);
-void vis_set_window(Vis * vis, GdkWindow * window);
-
-#endif
--- a/audacious/visualization.c	Wed Aug 09 02:11:01 2006 -0700
+++ b/audacious/visualization.c	Wed Aug 09 02:47:22 2006 -0700
@@ -32,9 +32,9 @@
 #include "playback.h"
 #include "plugin.h"
 #include "prefswin.h"
-#include "svis.h"
-#include "vis.h"
-#include "widget.h"
+#include "widgets/svis.h"
+#include "widgets/vis.h"
+#include "widgets/widget.h"
 
 VisPluginData vp_data = {
     NULL,
--- a/audacious/widget.c	Wed Aug 09 02:11:01 2006 -0700
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,263 +0,0 @@
-/*  BMP - Cross-platform multimedia player
- *  Copyright (C) 2003-2004  BMP development team.
- *
- *  Based on XMMS:
- *  Copyright (C) 1998-2003  XMMS development team.
- *
- *  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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
- */
-
-#include "widget.h"
-
-#include <glib.h>
-#include <gdk/gdk.h>
-
-#include "debug.h"
-
-
-void
-widget_init(Widget * widget, GdkPixmap * parent, GdkGC * gc,
-            gint x, gint y, gint width, gint height, gint visible)
-{
-    widget->parent = parent;
-    widget->gc = gc;
-    widget_set_position(widget, x, y);
-    widget_set_size(widget, width, height);
-    widget->visible = visible;
-    widget->redraw = TRUE;
-    widget->mutex = g_mutex_new();
-}
-
-void
-widget_set_position(Widget * widget, gint x, gint y)
-{
-    widget->x = x;
-    widget->y = y;
-    widget_queue_redraw(widget);
-}
-
-void
-widget_set_size(Widget * widget, gint width, gint height)
-{
-    widget->width = width;
-    widget->height = height;
-    widget_queue_redraw(widget);
-}
-
-void
-widget_queue_redraw(Widget * widget)
-{
-    widget->redraw = TRUE;
-}
-
-gboolean
-widget_contains(Widget * widget, gint x, gint y)
-{
-    return (widget->visible &&
-            x >= widget->x && 
-            y >= widget->y && 
-            x <  widget->x + widget->width && 
-            y <  widget->y + widget->height);
-}
-
-void
-widget_show(Widget * widget)
-{
-    if (!widget)
-        return;
-
-    widget->visible = TRUE;
-    widget_draw(widget);
-}
-
-void
-widget_hide(Widget * widget)
-{
-    if (!widget)
-        return;
-
-    widget->visible = FALSE;
-}
-
-gboolean
-widget_is_visible(Widget * widget)
-{
-    if (!widget)
-        return FALSE;
-
-    return widget->visible;
-}
-
-void
-widget_resize(Widget * widget, gint width, gint height)
-{
-    widget_set_size(widget, width, height);
-}
-
-void
-widget_move(Widget * widget, gint x, gint y)
-{
-    widget_lock(widget);
-    widget_set_position(widget, x, y);
-    widget_unlock(widget);
-}
-
-void
-widget_draw(Widget * widget)
-{
-    widget_lock(widget);
-    WIDGET(widget)->redraw = TRUE;
-    widget_unlock(widget);
-}
-
-void
-widget_draw_quick(Widget * widget)
-{
-    widget_lock(widget);
-    if (WIDGET(widget)->draw != NULL)
-    {
-	WIDGET(widget)->draw(widget);
-        gdk_flush();
-    }
-    widget_unlock(widget);
-}
-
-void
-widget_list_add(GList ** list, Widget * widget)
-{
-    (*list) = g_list_append(*list, widget);
-}
-
-void
-handle_press_cb(GList * widget_list, GtkWidget * widget,
-                GdkEventButton * event)
-{
-    GList *wl;
-
-    for (wl = widget_list; wl; wl = g_list_next(wl)) {
-        if (WIDGET(wl->data)->button_press_cb)
-            WIDGET(wl->data)->button_press_cb(widget, event, wl->data);
-    }
-}
-
-void
-handle_release_cb(GList * widget_list, GtkWidget * widget,
-                  GdkEventButton * event)
-{
-    GList *wl;
-
-    for (wl = widget_list; wl; wl = g_list_next(wl)) {
-        if (WIDGET(wl->data)->button_release_cb)
-            WIDGET(wl->data)->button_release_cb(widget, event, wl->data);
-    }
-}
-
-void
-handle_motion_cb(GList * widget_list, GtkWidget * widget,
-                 GdkEventMotion * event)
-{
-    GList *wl;
-
-    for (wl = widget_list; wl; wl = g_list_next(wl)) {
-        if (WIDGET(wl->data)->motion_cb)
-            WIDGET(wl->data)->motion_cb(widget, event, wl->data);
-    }
-}
-
-void
-handle_scroll_cb(GList * wlist, GtkWidget * widget, GdkEventScroll * event)
-{
-    GList *wl;
-
-    for (wl = wlist; wl; wl = g_list_next(wl)) {
-        if (WIDGET(wl->data)->mouse_scroll_cb)
-            WIDGET(wl->data)->mouse_scroll_cb(widget, event, wl->data);
-    }
-}
-
-void
-widget_list_draw(GList * widget_list, gboolean * redraw, gboolean force)
-{
-    GList *wl;
-    Widget *w;
-
-    *redraw = FALSE;
-    wl = widget_list;
-
-    for (wl = widget_list; wl; wl = g_list_next(wl)) {
-        w = WIDGET(wl->data);
-
-        REQUIRE_LOCK(w->mutex);
-
-        if (!w->draw)
-            continue;
-
-        if (!w->visible)
-            continue;
-
-        if (w->redraw || force) {
-            w->draw(w);
-/*             w->redraw = FALSE; */
-            *redraw = TRUE;
-        }
-    }
-}
-
-void
-widget_list_change_pixmap(GList * widget_list, GdkPixmap * pixmap)
-{
-    GList *wl;
-
-    for (wl = widget_list; wl; wl = g_list_next(wl)) {
-        Widget *widget = wl->data;
-        widget->parent = pixmap;
-        widget_queue_redraw(widget);
-    }
-}
-
-void
-widget_list_clear_redraw(GList * widget_list)
-{
-    GList *wl;
-
-    for (wl = widget_list; wl; wl = g_list_next(wl)) {
-        REQUIRE_LOCK(WIDGET(wl->data)->mutex);
-        WIDGET(wl->data)->redraw = FALSE;
-    }
-}
-
-void
-widget_lock(Widget * widget)
-{
-    g_mutex_lock(WIDGET(widget)->mutex);
-}
-
-void
-widget_unlock(Widget * widget)
-{
-    g_mutex_unlock(WIDGET(widget)->mutex);
-}
-
-void
-widget_list_lock(GList * widget_list)
-{
-    g_list_foreach(widget_list, (GFunc) widget_lock, NULL);
-}
-
-void
-widget_list_unlock(GList * widget_list)
-{
-    g_list_foreach(widget_list, (GFunc) widget_unlock, NULL);
-}
--- a/audacious/widget.h	Wed Aug 09 02:11:01 2006 -0700
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,102 +0,0 @@
-/*  BMP - Cross-platform multimedia player
- *  Copyright (C) 2003-2004  BMP development team.
- *
- *  Based on XMMS:
- *  Copyright (C) 1998-2003  XMMS development team.
- *
- *  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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
- */
-#ifndef WIDGET_H
-#define WIDGET_H
-
-
-#include <glib.h>
-#include <gdk/gdk.h>
-#include <gtk/gtk.h>
-
-
-typedef struct _Widget Widget;
-
-
-typedef void (*WidgetButtonPressFunc) (GtkWidget *, GdkEventButton *,
-                                       gpointer);
-typedef void (*WidgetButtonReleaseFunc) (GtkWidget *, GdkEventButton *,
-                                         gpointer);
-typedef void (*WidgetMotionFunc) (GtkWidget *, GdkEventMotion *, gpointer);
-typedef void (*WidgetDrawFunc) (Widget *);
-typedef void (*WidgetScrollFunc) (GtkWidget *, GdkEventScroll *, gpointer);
-
-
-#define WIDGET(x)  ((Widget *)(x))
-struct _Widget {
-    GdkPixmap *parent;
-    GdkGC *gc;
-
-    gint x, y;
-    gint width, height;
-
-    gint visible;
-    gboolean redraw;
-
-    GMutex *mutex;
-
-    WidgetButtonPressFunc button_press_cb;
-    WidgetButtonReleaseFunc button_release_cb;
-    WidgetMotionFunc motion_cb;
-    WidgetDrawFunc draw;
-    WidgetScrollFunc mouse_scroll_cb;
-};
-
-
-void widget_init(Widget * widget, GdkPixmap * parent, GdkGC * gc,
-                 gint x, gint y, gint width, gint height, gint visible);
-
-void widget_set_position(Widget * widget, gint x, gint y);
-void widget_set_size(Widget * widget, gint width, gint height);
-void widget_queue_redraw(Widget * widget);
-
-void widget_lock(Widget * widget);
-void widget_unlock(Widget * widget);
-
-gboolean widget_contains(Widget * widget, gint x, gint y);
-
-void widget_show(Widget * widget);
-void widget_hide(Widget * widget);
-gboolean widget_is_visible(Widget * widget);
-
-void widget_resize(Widget * widget, gint width, gint height);
-void widget_move(Widget * widget, gint x, gint y);
-void widget_draw(Widget * widget);
-void widget_draw_quick(Widget * widget);
-
-void handle_press_cb(GList * wlist, GtkWidget * widget,
-                     GdkEventButton * event);
-void handle_release_cb(GList * wlist, GtkWidget * widget,
-                       GdkEventButton * event);
-void handle_motion_cb(GList * wlist, GtkWidget * widget,
-                      GdkEventMotion * event);
-void handle_scroll_cb(GList * wlist, GtkWidget * widget,
-                      GdkEventScroll * event);
-
-void widget_list_add(GList ** list, Widget * widget);
-void widget_list_draw(GList * list, gboolean * redraw, gboolean force);
-void widget_list_change_pixmap(GList * list, GdkPixmap * pixmap);
-void widget_list_clear_redraw(GList * list);
-void widget_list_lock(GList * list);
-void widget_list_unlock(GList * list);
-
-
-
-#endif
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/audacious/widgets/Makefile	Wed Aug 09 02:47:22 2006 -0700
@@ -0,0 +1,37 @@
+include ../../mk/rules.mk
+include ../../mk/objective.mk
+
+OBJECTIVE_LIBS_NOINST = libwidgets.a
+
+LDFLAGS += -Wl,-export-dynamic
+
+CFLAGS += \
+	$(GTK_CFLAGS)      \
+	$(LIBGLADE_CFLAGS) \
+	$(BEEP_DEFINES)    \
+	$(ARCH_DEFINES)    \
+	-I../..    \
+	-I..	   \
+	-I../../intl
+
+SOURCES = \
+	widget.c \
+	sbutton.c \
+	pbutton.c \
+	tbutton.c \
+	textbox.c \
+	hslider.c \
+	menurow.c \
+	monostereo.c \
+	vis.c \
+	svis.c \
+	number.c \
+	playstatus.c \
+	playlist_list.c \
+	playlist_slider.c \
+	eq_graph.c \
+	eq_slider.c \
+	skin.c
+
+OBJECTS = ${SOURCES:.c=.o}
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/audacious/widgets/eq_graph.c	Wed Aug 09 02:47:22 2006 -0700
@@ -0,0 +1,149 @@
+/*  BMP - Cross-platform multimedia player
+ *  Copyright (C) 2003-2004  BMP development team.
+ *
+ *  Based on XMMS:
+ *  Copyright (C) 1998-2003  XMMS development team.
+ *
+ *  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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+
+#include "eq_graph.h"
+
+#include <glib.h>
+
+#include "main.h"
+#include "skin.h"
+
+void
+init_spline(gfloat * x, gfloat * y, gint n, gfloat * y2)
+{
+    gint i, k;
+    gfloat p, qn, sig, un, *u;
+
+    u = (gfloat *) g_malloc(n * sizeof(gfloat));
+
+    y2[0] = u[0] = 0.0;
+
+    for (i = 1; i < n - 1; i++) {
+        sig = ((gfloat) x[i] - x[i - 1]) / ((gfloat) x[i + 1] - x[i - 1]);
+        p = sig * y2[i - 1] + 2.0;
+        y2[i] = (sig - 1.0) / p;
+        u[i] =
+            (((gfloat) y[i + 1] - y[i]) / (x[i + 1] - x[i])) -
+            (((gfloat) y[i] - y[i - 1]) / (x[i] - x[i - 1]));
+        u[i] = (6.0 * u[i] / (x[i + 1] - x[i - 1]) - sig * u[i - 1]) / p;
+    }
+    qn = un = 0.0;
+
+    y2[n - 1] = (un - qn * u[n - 2]) / (qn * y2[n - 2] + 1.0);
+    for (k = n - 2; k >= 0; k--)
+        y2[k] = y2[k] * y2[k + 1] + u[k];
+    g_free(u);
+}
+
+gfloat
+eval_spline(gfloat xa[], gfloat ya[], gfloat y2a[], gint n, gfloat x)
+{
+    gint klo, khi, k;
+    gfloat h, b, a;
+
+    klo = 0;
+    khi = n - 1;
+    while (khi - klo > 1) {
+        k = (khi + klo) >> 1;
+        if (xa[k] > x)
+            khi = k;
+        else
+            klo = k;
+    }
+    h = xa[khi] - xa[klo];
+    a = (xa[khi] - x) / h;
+    b = (x - xa[klo]) / h;
+    return (a * ya[klo] + b * ya[khi] +
+            ((a * a * a - a) * y2a[klo] +
+             (b * b * b - b) * y2a[khi]) * (h * h) / 6.0);
+}
+
+void
+eqgraph_draw(Widget * w)
+{
+    EqGraph *eg = (EqGraph *) w;
+    GdkPixmap *obj;
+    GdkColor col;
+    guint32 cols[19];
+    gint i, y, ymin, ymax, py = 0;
+    gfloat x[] = { 0, 11, 23, 35, 47, 59, 71, 83, 97, 109 }, yf[10];
+
+    /*
+     * This avoids the init_spline() function to be inlined.
+     * Inlining the function caused troubles when compiling with
+     * `-O' (at least on FreeBSD).
+     */
+    void (*__init_spline) (gfloat *, gfloat *, gint, gfloat *) = init_spline;
+
+    obj = eg->eg_widget.parent;
+    skin_draw_pixmap(bmp_active_skin, obj, eg->eg_widget.gc, SKIN_EQMAIN,
+                     0, 294, eg->eg_widget.x, eg->eg_widget.y,
+                     eg->eg_widget.width, eg->eg_widget.height);
+    skin_draw_pixmap(bmp_active_skin, obj, eg->eg_widget.gc, SKIN_EQMAIN,
+                     0, 314, eg->eg_widget.x,
+                     eg->eg_widget.y + 9 +
+                     ((cfg.equalizer_preamp * 9) / 20),
+                     eg->eg_widget.width, 1);
+
+    skin_get_eq_spline_colors(bmp_active_skin, cols);
+
+    __init_spline(x, cfg.equalizer_bands, 10, yf);
+    for (i = 0; i < 109; i++) {
+        y = 9 -
+            (gint) ((eval_spline(x, cfg.equalizer_bands, yf, 10, i) *
+                     9.0) / 20.0);
+        if (y < 0)
+            y = 0;
+        if (y > 18)
+            y = 18;
+        if (!i)
+            py = y;
+        if (y < py) {
+            ymin = y;
+            ymax = py;
+        }
+        else {
+            ymin = py;
+            ymax = y;
+        }
+        py = y;
+        for (y = ymin; y <= ymax; y++) {
+            col.pixel = cols[y];
+            gdk_gc_set_foreground(eg->eg_widget.gc, &col);
+            gdk_draw_point(obj, eg->eg_widget.gc, eg->eg_widget.x + i + 2,
+                           eg->eg_widget.y + y);
+        }
+    }
+}
+
+EqGraph *
+create_eqgraph(GList ** wlist, GdkPixmap * parent, GdkGC * gc, gint x, gint y)
+{
+    EqGraph *eg;
+
+    eg = g_new0(EqGraph, 1);
+    widget_init(&eg->eg_widget, parent, gc, x, y, 113, 19, TRUE);
+    eg->eg_widget.draw = eqgraph_draw;
+
+    widget_list_add(wlist, WIDGET(eg));
+
+    return eg;
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/audacious/widgets/eq_graph.h	Wed Aug 09 02:47:22 2006 -0700
@@ -0,0 +1,40 @@
+/*  BMP - Cross-platform multimedia player
+ *  Copyright (C) 2003-2004  BMP development team.
+ *
+ *  Based on XMMS:
+ *  Copyright (C) 1998-2003  XMMS development team.
+ *
+ *  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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+
+#ifndef EQ_GRAPH_H
+#define EQ_GRAPH_H
+
+#include <glib.h>
+#include <gdk/gdk.h>
+
+#include "widget.h"
+
+#define EQ_GRAPH(x)  ((EqGraph *)(x))
+struct _EqGraph {
+    Widget eg_widget;
+};
+
+typedef struct _EqGraph EqGraph;
+
+EqGraph *create_eqgraph(GList ** wlist, GdkPixmap * parent, GdkGC * gc,
+                        gint x, gint y);
+
+#endif
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/audacious/widgets/eq_slider.c	Wed Aug 09 02:47:22 2006 -0700
@@ -0,0 +1,235 @@
+/*  BMP - Cross-platform multimedia player
+ *  Copyright (C) 2003-2004  BMP development team.
+ *
+ *  Based on XMMS:
+ *  Copyright (C) 1998-2003  XMMS development team.
+ *
+ *  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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+
+#include "eq_slider.h"
+
+#include <glib.h>
+#include <glib/gi18n.h>
+#include <gtk/gtk.h>
+#include <gdk/gdk.h>
+
+#include "equalizer.h"
+#include "mainwin.h"
+#include "skin.h"
+
+void
+eqslider_set_position(EqSlider * es,
+                      gfloat pos)
+{
+    es->es_position = 25 - (gint) ((pos * 25.0) / 20.0);
+
+    if (es->es_position < 0)
+        es->es_position = 0;
+
+    if (es->es_position > 50)
+        es->es_position = 50;
+
+    if (es->es_position >= 24 && es->es_position <= 26)
+        es->es_position = 25;
+
+    widget_draw(WIDGET(es));
+}
+
+gfloat
+eqslider_get_position(EqSlider * es)
+{
+    return 20.0 - (((gfloat) es->es_position * 20.0) / 25.0);
+}
+
+void
+eqslider_draw(Widget * w)
+{
+    EqSlider *es = (EqSlider *) w;
+    GdkPixmap *obj;
+    SkinPixmapId src;
+    gint frame;
+
+    src = SKIN_EQMAIN;
+    obj = es->es_widget.parent;
+
+    frame = 27 - ((es->es_position * 27) / 50);
+    if (frame < 14)
+        skin_draw_pixmap(bmp_active_skin, obj, es->es_widget.gc, src,
+                         (frame * 15) + 13, 164, es->es_widget.x,
+                         es->es_widget.y, es->es_widget.width,
+                         es->es_widget.height);
+    else
+        skin_draw_pixmap(bmp_active_skin, obj, es->es_widget.gc, src,
+                         ((frame - 14) * 15) + 13, 229, es->es_widget.x,
+                         es->es_widget.y, es->es_widget.width,
+                         es->es_widget.height);
+    if (es->es_isdragging)
+        skin_draw_pixmap(bmp_active_skin, obj, es->es_widget.gc, src, 0,
+                         176, es->es_widget.x + 1,
+                         es->es_widget.y + es->es_position, 11, 11);
+    else
+        skin_draw_pixmap(bmp_active_skin, obj, es->es_widget.gc, src, 0,
+                         164, es->es_widget.x + 1,
+                         es->es_widget.y + es->es_position, 11, 11);
+}
+
+void
+eqslider_set_mainwin_text(EqSlider * es)
+{
+    gint band = 0;
+    const gchar *bandname[11] = { N_("PREAMP"), N_("60HZ"), N_("170HZ"),
+        N_("310HZ"), N_("600HZ"), N_("1KHZ"),
+        N_("3KHZ"), N_("6KHZ"), N_("12KHZ"),
+        N_("14KHZ"), N_("16KHZ")
+    };
+    gchar *tmp;
+
+    if (es->es_widget.x > 21)
+        band = ((es->es_widget.x - 78) / 18) + 1;
+
+    tmp =
+        g_strdup_printf("EQ: %s: %+.1f DB", _(bandname[band]),
+                        eqslider_get_position(es));
+    mainwin_lock_info_text(tmp);
+    g_free(tmp);
+}
+
+void
+eqslider_button_press_cb(GtkWidget * w,
+                         GdkEventButton * event,
+                         gpointer data)
+{
+    EqSlider *es = EQ_SLIDER(data);
+    gint y;
+
+    if (widget_contains(&es->es_widget, event->x, event->y)) {
+        if (event->button == 1) {
+            y = event->y - es->es_widget.y;
+            es->es_isdragging = TRUE;
+            if (y >= es->es_position && y < es->es_position + 11)
+                es->es_drag_y = y - es->es_position;
+            else {
+                es->es_position = y - 5;
+                es->es_drag_y = 5;
+                if (es->es_position < 0)
+                    es->es_position = 0;
+                if (es->es_position > 50)
+                    es->es_position = 50;
+                if (es->es_position >= 24 && es->es_position <= 26)
+                    es->es_position = 25;
+                equalizerwin_eq_changed();
+            }
+
+            eqslider_set_mainwin_text(es);
+            widget_draw(WIDGET(es));
+        }
+        if (event->button == 4) {
+            es->es_position -= 2;
+            if (es->es_position < 0)
+                es->es_position = 0;
+            equalizerwin_eq_changed();
+            widget_draw(WIDGET(es));
+        }
+    }
+}
+
+void
+eqslider_mouse_scroll_cb(GtkWidget * w,
+                         GdkEventScroll * event,
+                         gpointer data)
+{
+    EqSlider *es = EQ_SLIDER(data);
+
+    if (!widget_contains(&es->es_widget, event->x, event->y))
+        return;
+
+    if (event->direction == GDK_SCROLL_UP) {
+        es->es_position -= 2;
+
+        if (es->es_position < 0)
+            es->es_position = 0;
+
+        equalizerwin_eq_changed();
+        widget_draw(WIDGET(es));
+    }
+    else {
+        es->es_position += 2;
+
+        if (es->es_position > 50)
+            es->es_position = 50;
+
+        equalizerwin_eq_changed();
+        widget_draw(WIDGET(es));
+    }
+}
+
+void
+eqslider_motion_cb(GtkWidget * w,
+                   GdkEventMotion * event,
+                   gpointer data)
+{
+    EqSlider *es = EQ_SLIDER(data);
+    gint y;
+
+    y = event->y - es->es_widget.y;
+    if (es->es_isdragging) {
+        es->es_position = y - es->es_drag_y;
+        if (es->es_position < 0)
+            es->es_position = 0;
+        if (es->es_position > 50)
+            es->es_position = 50;
+        if (es->es_position >= 24 && es->es_position <= 26)
+            es->es_position = 25;
+        equalizerwin_eq_changed();
+        eqslider_set_mainwin_text(es);
+        widget_draw(WIDGET(es));
+    }
+}
+
+void
+eqslider_button_release_cb(GtkWidget * w,
+                           GdkEventButton * event,
+                           gpointer data)
+{
+    EqSlider *es = EQ_SLIDER(data);
+
+    if (es->es_isdragging) {
+        es->es_isdragging = FALSE;
+        mainwin_release_info_text();
+        widget_draw(WIDGET(es));
+    }
+}
+
+EqSlider *
+create_eqslider(GList ** wlist,
+                GdkPixmap * parent,
+                GdkGC * gc,
+                gint x, gint y)
+{
+    EqSlider *es;
+
+    es = g_new0(EqSlider, 1);
+    widget_init(&es->es_widget, parent, gc, x, y, 14, 63, TRUE);
+    es->es_widget.button_press_cb = eqslider_button_press_cb;
+    es->es_widget.button_release_cb = eqslider_button_release_cb;
+    es->es_widget.motion_cb = eqslider_motion_cb;
+    es->es_widget.draw = eqslider_draw;
+    es->es_widget.mouse_scroll_cb = eqslider_mouse_scroll_cb;
+
+    widget_list_add(wlist, WIDGET(es));
+
+    return es;
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/audacious/widgets/eq_slider.h	Wed Aug 09 02:47:22 2006 -0700
@@ -0,0 +1,44 @@
+/*  BMP - Cross-platform multimedia player
+ *  Copyright (C) 2003-2004  BMP development team.
+ *
+ *  Based on XMMS:
+ *  Copyright (C) 1998-2003  XMMS development team.
+ *
+ *  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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+#ifndef EQ_SLIDER_H
+#define EQ_SLIDER_H
+
+#include <glib.h>
+#include <gdk/gdk.h>
+
+#include "widget.h"
+
+#define EQ_SLIDER(x)  ((EqSlider *)(x))
+struct _EqSlider {
+    Widget es_widget;
+    gint es_position;
+    gboolean es_isdragging;
+    gint es_drag_y;
+};
+
+typedef struct _EqSlider EqSlider;
+
+EqSlider *create_eqslider(GList ** wlist, GdkPixmap * parent, GdkGC * gc,
+                          gint x, gint y);
+void eqslider_set_position(EqSlider * es, gfloat pos);
+gfloat eqslider_get_position(EqSlider * es);
+
+#endif
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/audacious/widgets/hslider.c	Wed Aug 09 02:47:22 2006 -0700
@@ -0,0 +1,203 @@
+/*  XMMS - Cross-platform multimedia player
+ *  Copyright (C) 1998-2000  Peter Alm, Mikael Alm, Olle Hallnas, Thomas Nilsson and 4Front Technologies
+ *
+ *  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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+
+#include "hslider.h"
+
+#include <glib.h>
+#include <gdk/gdk.h>
+#include <gtk/gtk.h>
+
+#include "skin.h"
+
+void
+hslider_set_position(HSlider * hs,
+                     gint pos)
+{
+    if (pos == hs->hs_position || hs->hs_pressed)
+        return;
+
+    hs->hs_position = pos;
+
+    if (hs->hs_frame_cb)
+        hs->hs_frame = hs->hs_frame_cb(hs->hs_position);
+
+    widget_draw(WIDGET(hs));
+}
+
+gint
+hslider_get_position(HSlider * hs)
+{
+    return hs->hs_position;
+}
+
+void
+hslider_draw(Widget * w)
+{
+    HSlider *hs = (HSlider *) w;
+    GdkPixmap *obj;
+
+    obj = hs->hs_widget.parent;
+
+    skin_draw_pixmap(bmp_active_skin, obj, hs->hs_widget.gc,
+                     hs->hs_skin_index, hs->hs_frame_offset,
+                     hs->hs_frame * hs->hs_frame_height, hs->hs_widget.x,
+                     hs->hs_widget.y, hs->hs_widget.width,
+                     hs->hs_widget.height);
+    if (hs->hs_pressed)
+        skin_draw_pixmap(bmp_active_skin, obj, hs->hs_widget.gc,
+                         hs->hs_skin_index, hs->hs_knob_px,
+                         hs->hs_knob_py, hs->hs_widget.x + hs->hs_position,
+                         hs->hs_widget.y +
+                         ((hs->hs_widget.height - hs->hs_knob_height) / 2),
+                         hs->hs_knob_width, hs->hs_knob_height);
+    else
+        skin_draw_pixmap(bmp_active_skin, obj, hs->hs_widget.gc,
+                         hs->hs_skin_index, hs->hs_knob_nx, hs->hs_knob_ny,
+                         hs->hs_widget.x + hs->hs_position,
+                         hs->hs_widget.y +
+                         ((hs->hs_widget.height - hs->hs_knob_height) / 2),
+                         hs->hs_knob_width, hs->hs_knob_height);
+}
+
+void
+hslider_button_press_cb(GtkWidget * w,
+                        GdkEventButton * event,
+                        gpointer data)
+{
+    HSlider *hs = HSLIDER(data);
+    gint x;
+
+    if (event->button != 1)
+        return;
+
+    if (widget_contains(&hs->hs_widget, event->x, event->y)) {
+        x = event->x - hs->hs_widget.x;
+        hs->hs_pressed = TRUE;
+
+        if (x >= hs->hs_position && x < hs->hs_position + hs->hs_knob_width)
+            hs->hs_pressed_x = x - hs->hs_position;
+        else {
+            hs->hs_position = x - (hs->hs_knob_width / 2);
+            hs->hs_pressed_x = hs->hs_knob_width / 2;
+            if (hs->hs_position < hs->hs_min)
+                hs->hs_position = hs->hs_min;
+            if (hs->hs_position > hs->hs_max)
+                hs->hs_position = hs->hs_max;
+            if (hs->hs_frame_cb)
+                hs->hs_frame = hs->hs_frame_cb(hs->hs_position);
+
+        }
+
+        if (hs->hs_motion_cb)
+            hs->hs_motion_cb(hs->hs_position);
+
+        widget_draw(WIDGET(hs));
+    }
+}
+
+void
+hslider_motion_cb(GtkWidget * w, GdkEventMotion * event, gpointer data)
+{
+    HSlider *hs = (HSlider *) data;
+    gint x;
+
+    if (hs->hs_pressed) {
+        if (!hs->hs_widget.visible) {
+            hs->hs_pressed = FALSE;
+            return;
+        }
+
+        x = event->x - hs->hs_widget.x;
+        hs->hs_position = x - hs->hs_pressed_x;
+
+        if (hs->hs_position < hs->hs_min)
+            hs->hs_position = hs->hs_min;
+
+        if (hs->hs_position > hs->hs_max)
+            hs->hs_position = hs->hs_max;
+
+        if (hs->hs_frame_cb)
+            hs->hs_frame = hs->hs_frame_cb(hs->hs_position);
+
+        if (hs->hs_motion_cb)
+            hs->hs_motion_cb(hs->hs_position);
+
+        widget_draw(WIDGET(hs));
+    }
+}
+
+void
+hslider_button_release_cb(GtkWidget * w,
+                          GdkEventButton * event,
+                          gpointer data)
+{
+    HSlider *hs = HSLIDER(data);
+
+    if (hs->hs_pressed) {
+        hs->hs_pressed = FALSE;
+
+        if (hs->hs_release_cb)
+            hs->hs_release_cb(hs->hs_position);
+
+        widget_draw(WIDGET(hs));
+    }
+}
+
+HSlider *
+create_hslider(GList ** wlist, GdkPixmap * parent, GdkGC * gc,
+               gint x, gint y, gint w, gint h, gint knx, gint kny,
+               gint kpx, gint kpy, gint kw, gint kh, gint fh,
+               gint fo, gint min, gint max, gint(*fcb) (gint),
+               void (*mcb) (gint), void (*rcb) (gint), SkinPixmapId si)
+{
+    HSlider *hs;
+
+    hs = g_new0(HSlider, 1);
+    widget_init(&hs->hs_widget, parent, gc, x, y, w, h, 1);
+    hs->hs_widget.button_press_cb =
+        (void (*)(GtkWidget *, GdkEventButton *, gpointer))
+        hslider_button_press_cb;
+    hs->hs_widget.button_release_cb =
+        (void (*)(GtkWidget *, GdkEventButton *, gpointer))
+        hslider_button_release_cb;
+    hs->hs_widget.motion_cb =
+        (void (*)(GtkWidget *, GdkEventMotion *, gpointer))
+        hslider_motion_cb;
+    hs->hs_widget.draw = hslider_draw;
+    hs->hs_knob_nx = knx;
+    hs->hs_knob_ny = kny;
+    hs->hs_knob_px = kpx;
+    hs->hs_knob_py = kpy;
+    hs->hs_knob_width = kw;
+    hs->hs_knob_height = kh;
+    hs->hs_frame_height = fh;
+    hs->hs_frame_offset = fo;
+    hs->hs_min = min;
+    hs->hs_position = min;
+    hs->hs_max = max;
+    hs->hs_frame_cb = fcb;
+    hs->hs_motion_cb = mcb;
+    hs->hs_release_cb = rcb;
+    if (hs->hs_frame_cb)
+        hs->hs_frame = hs->hs_frame_cb(0);
+    hs->hs_skin_index = si;
+
+    widget_list_add(wlist, WIDGET(hs));
+
+    return hs;
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/audacious/widgets/hslider.h	Wed Aug 09 02:47:22 2006 -0700
@@ -0,0 +1,54 @@
+/*  XMMS - Cross-platform multimedia player
+ *  Copyright (C) 1998-2000  Peter Alm, Mikael Alm, Olle Hallnas, Thomas Nilsson and 4Front Technologies
+ *
+ *  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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+#ifndef HSLIDER_H
+#define HSLIDER_H
+
+#include <glib.h>
+#include <gdk/gdk.h>
+
+#include "skin.h"
+#include "widget.h"
+
+#define HSLIDER(x)  ((HSlider *)(x))
+struct _HSlider {
+    Widget hs_widget;
+    gint hs_frame, hs_frame_offset, hs_frame_height, hs_min, hs_max;
+    gint hs_knob_nx, hs_knob_ny, hs_knob_px, hs_knob_py;
+    gint hs_knob_width, hs_knob_height;
+    gint hs_position;
+    gboolean hs_pressed;
+    gint hs_pressed_x, hs_pressed_y;
+     gint(*hs_frame_cb) (gint);
+    void (*hs_motion_cb) (gint);
+    void (*hs_release_cb) (gint);
+    SkinPixmapId hs_skin_index;
+};
+
+typedef struct _HSlider HSlider;
+
+HSlider *create_hslider(GList ** wlist, GdkPixmap * parent, GdkGC * gc,
+                        gint x, gint y, gint w, gint h, gint knx, gint kny,
+                        gint kpx, gint kpy, gint kw, gint kh, gint fh,
+                        gint fo, gint min, gint max, gint(*fcb) (gint),
+                        void (*mcb) (gint), void (*rcb) (gint),
+                        SkinPixmapId si);
+
+void hslider_set_position(HSlider * hs, gint pos);
+gint hslider_get_position(HSlider * hs);
+
+#endif
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/audacious/widgets/monostereo.c	Wed Aug 09 02:47:22 2006 -0700
@@ -0,0 +1,93 @@
+/*  BMP - Cross-platform multimedia player
+ *  Copyright (C) 2003-2004  BMP development team.
+ *
+ *  Based on XMMS:
+ *  Copyright (C) 1998-2003  XMMS development team.
+ *
+ *  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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+
+#include "monostereo.h"
+
+#include <glib.h>
+#include <gdk/gdk.h>
+
+#include "skin.h"
+#include "widget.h"
+
+void
+monostereo_draw(Widget * widget)
+{
+    MonoStereo *ms = (MonoStereo *) widget;
+    GdkPixmap *obj;
+
+    obj = ms->ms_widget.parent;
+
+    switch (ms->ms_num_channels) {
+    case 0:
+        skin_draw_pixmap(bmp_active_skin, obj, ms->ms_widget.gc,
+                         ms->ms_skin_index, 29, 12,
+                         ms->ms_widget.x, ms->ms_widget.y, 27, 12);
+        skin_draw_pixmap(bmp_active_skin, obj, ms->ms_widget.gc,
+                         ms->ms_skin_index, 0, 12,
+                         ms->ms_widget.x + 27, ms->ms_widget.y, 29, 12);
+        break;
+    case 1:
+        skin_draw_pixmap(bmp_active_skin, obj, ms->ms_widget.gc,
+                         ms->ms_skin_index, 29, 0,
+                         ms->ms_widget.x, ms->ms_widget.y, 27, 12);
+        skin_draw_pixmap(bmp_active_skin, obj, ms->ms_widget.gc,
+                         ms->ms_skin_index, 0, 12,
+                         ms->ms_widget.x + 27, ms->ms_widget.y, 29, 12);
+        break;
+    case 2:
+        skin_draw_pixmap(bmp_active_skin, obj, ms->ms_widget.gc,
+                         ms->ms_skin_index, 29, 12,
+                         ms->ms_widget.x, ms->ms_widget.y, 27, 12);
+        skin_draw_pixmap(bmp_active_skin, obj, ms->ms_widget.gc,
+                         ms->ms_skin_index, 0, 0,
+                         ms->ms_widget.x + 27, ms->ms_widget.y, 29, 12);
+        break;
+    }
+}
+
+void
+monostereo_set_num_channels(MonoStereo * ms,
+                            gint nch)
+{
+    if (!ms)
+        return;
+
+    ms->ms_num_channels = nch;
+    widget_draw(WIDGET(ms));
+}
+
+MonoStereo *
+create_monostereo(GList ** wlist,
+                  GdkPixmap * parent,
+                  GdkGC * gc,
+                  gint x, gint y, 
+                  SkinPixmapId si)
+{
+    MonoStereo *ms;
+
+    ms = g_new0(MonoStereo, 1);
+    widget_init(&ms->ms_widget, parent, gc, x, y, 56, 12, 1);
+    ms->ms_widget.draw = monostereo_draw;
+    ms->ms_skin_index = si;
+
+    widget_list_add(wlist, WIDGET(ms));
+    return ms;
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/audacious/widgets/monostereo.h	Wed Aug 09 02:47:22 2006 -0700
@@ -0,0 +1,43 @@
+/*  BMP - Cross-platform multimedia player
+ *  Copyright (C) 2003-2004  BMP development team.
+ *
+ *  Based on XMMS:
+ *  Copyright (C) 1998-2003  XMMS development team.
+ *
+ *  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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+#ifndef MONOSTEREO_H
+#define MONOSTEREO_H
+
+#include <glib.h>
+#include <gdk/gdk.h>
+
+#include "skin.h"
+#include "widget.h"
+
+#define MONO_STEREO(x)  ((MonoStereo *)(x))
+struct _MonoStereo {
+    Widget ms_widget;
+    gint ms_num_channels;
+    SkinPixmapId ms_skin_index;
+};
+
+typedef struct _MonoStereo MonoStereo;
+
+MonoStereo *create_monostereo(GList ** wlist, GdkPixmap * parent,
+                              GdkGC * gc, gint x, gint y, SkinPixmapId si);
+void monostereo_set_num_channels(MonoStereo * ms, gint nch);
+
+#endif
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/audacious/widgets/number.c	Wed Aug 09 02:47:22 2006 -0700
@@ -0,0 +1,75 @@
+/*  BMP - Cross-platform multimedia player
+ *  Copyright (C) 2003-2004  BMP development team.
+ *
+ *  Based on XMMS:
+ *  Copyright (C) 1998-2003  XMMS development team.
+ *
+ *  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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+
+#include "number.h"
+
+#include <glib.h>
+#include <gdk/gdk.h>
+
+#include "skin.h"
+
+void
+number_set_number(Number * nu,
+                  gint number)
+{
+    if (number == nu->nu_number)
+        return;
+
+    nu->nu_number = number;
+    widget_draw(WIDGET(nu));
+}
+
+void
+number_draw(Widget * w)
+{
+    Number *nu = NUMBER(w);
+    GdkPixmap *obj;
+
+    obj = nu->nu_widget.parent;
+
+    if (nu->nu_number <= 11)
+        skin_draw_pixmap(bmp_active_skin, obj, nu->nu_widget.gc,
+                         nu->nu_skin_index, nu->nu_number * 9, 0,
+                         nu->nu_widget.x, nu->nu_widget.y, 9, 13);
+    else
+        skin_draw_pixmap(bmp_active_skin, obj, nu->nu_widget.gc,
+                         nu->nu_skin_index, 90, 0, nu->nu_widget.x,
+                         nu->nu_widget.y, 9, 13);
+}
+
+Number *
+create_number(GList ** wlist,
+              GdkPixmap * parent,
+              GdkGC * gc,
+              gint x, gint y,
+              SkinPixmapId si)
+{
+    Number *nu;
+
+    nu = g_new0(Number, 1);
+    widget_init(&nu->nu_widget, parent, gc, x, y, 9, 13, 1);
+    nu->nu_widget.draw = number_draw;
+    nu->nu_number = 10;
+    nu->nu_skin_index = si;
+
+    widget_list_add(wlist, WIDGET(nu));
+    return nu;
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/audacious/widgets/number.h	Wed Aug 09 02:47:22 2006 -0700
@@ -0,0 +1,43 @@
+/*  BMP - Cross-platform multimedia player
+ *  Copyright (C) 2003-2004  BMP development team.
+ *
+ *  Based on XMMS:
+ *  Copyright (C) 1998-2003  XMMS development team.
+ *
+ *  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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+#ifndef NUMBER_H
+#define NUMBER_H
+
+#include <glib.h>
+#include <gdk/gdk.h>
+
+#include "widget.h"
+#include "skin.h"
+
+#define NUMBER(x) ((Number *)(x))
+struct _Number {
+    Widget nu_widget;
+    gint nu_number;
+    SkinPixmapId nu_skin_index;
+};
+
+typedef struct _Number Number;
+
+void number_set_number(Number * nu, gint number);
+Number *create_number(GList ** wlist, GdkPixmap * parent, GdkGC * gc,
+                      gint x, gint y, SkinPixmapId si);
+
+#endif
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/audacious/widgets/pbutton.c	Wed Aug 09 02:47:22 2006 -0700
@@ -0,0 +1,194 @@
+/*  BMP - Cross-platform multimedia player
+ *  Copyright (C) 2003-2004  BMP development team.
+ *
+ *  Based on XMMS:
+ *  Copyright (C) 1998-2003  XMMS development team.
+ *
+ *  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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+
+#include "pbutton.h"
+
+#include <glib.h>
+#include <gtk/gtk.h>
+#include <gdk/gdk.h>
+
+#include "skin.h"
+#include "widget.h"
+
+void
+pbutton_draw(PButton * button)
+{
+    GdkPixmap *obj;
+
+    if (button->pb_allow_draw) {
+        obj = button->pb_widget.parent;
+
+        if (button->pb_pressed && button->pb_inside) {
+            skin_draw_pixmap(bmp_active_skin, obj,
+                             button->pb_widget.gc,
+                             button->pb_skin_index2, button->pb_px,
+                             button->pb_py, button->pb_widget.x,
+                             button->pb_widget.y,
+                             button->pb_widget.width,
+                             button->pb_widget.height);
+        }
+        else {
+            skin_draw_pixmap(bmp_active_skin, obj,
+                             button->pb_widget.gc,
+                             button->pb_skin_index1,
+                             button->pb_nx, button->pb_ny,
+                             button->pb_widget.x, button->pb_widget.y,
+                             button->pb_widget.width,
+                             button->pb_widget.height);
+        }
+    }
+}
+
+void
+pbutton_button_press_cb(GtkWidget * widget,
+                        GdkEventButton * event,
+                        PButton * button)
+{
+    if (event->button != 1)
+        return;
+
+    if (widget_contains(&button->pb_widget, event->x, event->y)) {
+        button->pb_pressed = 1;
+        button->pb_inside = 1;
+        widget_draw(WIDGET(button));
+        if (button->pb_push_cb)
+            button->pb_push_cb();
+    }
+}
+
+void
+pbutton_button_release_cb(GtkWidget * widget,
+                          GdkEventButton * event,
+                          PButton * button)
+{
+    if (event->button != 1)
+        return;
+    if (button->pb_inside && button->pb_pressed) {
+        button->pb_inside = 0;
+        widget_draw(WIDGET(button));
+	if (button->pb_release_cb)
+	    button->pb_release_cb();
+    }
+    if (button->pb_pressed)
+        button->pb_pressed = 0;
+}
+
+void
+pbutton_motion_cb(GtkWidget * widget, GdkEventMotion * event,
+                  PButton * button)
+{
+    gint inside;
+
+    if (!button->pb_pressed)
+        return;
+
+    inside = widget_contains(&button->pb_widget, event->x, event->y);
+
+    if (inside != button->pb_inside) {
+        button->pb_inside = inside;
+        widget_draw(WIDGET(button));
+    }
+}
+
+void
+pbutton_set_skin_index(PButton * b, SkinPixmapId si)
+{
+    b->pb_skin_index1 = b->pb_skin_index2 = si;
+}
+
+void
+pbutton_set_skin_index1(PButton * b, SkinPixmapId si)
+{
+    b->pb_skin_index1 = si;
+}
+
+void
+pbutton_set_skin_index2(PButton * b, SkinPixmapId si)
+{
+    b->pb_skin_index2 = si;
+}
+
+void
+pbutton_set_button_data(PButton * b, gint nx, gint ny, gint px, gint py)
+{
+    if (nx > -1)
+        b->pb_nx = nx;
+    if (ny > -1)
+        b->pb_ny = ny;
+    if (px > -1)
+        b->pb_px = px;
+    if (py > -1)
+        b->pb_py = py;
+}
+
+
+PButton *
+create_pbutton_ex(GList ** wlist, GdkPixmap * parent, GdkGC * gc,
+                  gint x, gint y, gint w, gint h, gint nx,
+                  gint ny, gint px, gint py, void (*push_cb) (void),
+		  void (*release_cb) (void),
+                  SkinPixmapId si1, SkinPixmapId si2)
+{
+    PButton *b;
+
+    b = g_new0(PButton, 1);
+    widget_init(&b->pb_widget, parent, gc, x, y, w, h, 1);
+    b->pb_widget.button_press_cb =
+        (void (*)(GtkWidget *, GdkEventButton *, gpointer))
+        pbutton_button_press_cb;
+    b->pb_widget.button_release_cb =
+        (void (*)(GtkWidget *, GdkEventButton *, gpointer))
+        pbutton_button_release_cb;
+    b->pb_widget.motion_cb =
+        (void (*)(GtkWidget *, GdkEventMotion *, gpointer))
+        pbutton_motion_cb;
+
+    b->pb_widget.draw = (void (*)(Widget *)) pbutton_draw;
+    b->pb_nx = nx;
+    b->pb_ny = ny;
+    b->pb_px = px;
+    b->pb_py = py;
+    b->pb_push_cb = push_cb;
+    b->pb_release_cb = release_cb;
+    b->pb_skin_index1 = si1;
+    b->pb_skin_index2 = si2;
+    b->pb_allow_draw = TRUE;
+    b->pb_inside = 0;
+    b->pb_pressed = 0;
+    widget_list_add(wlist, WIDGET(b));
+
+    return b;
+}
+
+PButton *
+create_pbutton(GList ** wlist, GdkPixmap * parent, GdkGC * gc,
+               gint x, gint y, gint w, gint h, gint nx, gint ny,
+               gint px, gint py, void (*cb) (void), SkinPixmapId si)
+{
+    return create_pbutton_ex(wlist, parent, gc, x, y, w, h, nx, ny, px, py,
+                             NULL, cb, si, si);
+}
+
+void
+free_pbutton(PButton * b)
+{
+    g_free(b);
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/audacious/widgets/pbutton.h	Wed Aug 09 02:47:22 2006 -0700
@@ -0,0 +1,59 @@
+/*  BMP - Cross-platform multimedia player
+ *  Copyright (C) 2003-2004  BMP development team.
+ *
+ *  Based on XMMS:
+ *  Copyright (C) 1998-2003  XMMS development team.
+ *
+ *  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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+#ifndef PBUTTON_H
+#define PBUTTON_H
+
+#include <glib.h>
+#include <gdk/gdk.h>
+
+#include "widget.h"
+#include "skin.h"
+
+#define PBUTTON(x)  ((PButton *)(x))
+struct _PButton {
+    Widget pb_widget;
+    gint pb_nx, pb_ny;
+    gint pb_px, pb_py;
+    gboolean pb_pressed;
+    gboolean pb_inside;
+    gboolean pb_allow_draw;
+    void (*pb_push_cb) (void);
+    void (*pb_release_cb) (void);
+    SkinPixmapId pb_skin_index1, pb_skin_index2;
+};
+
+typedef struct _PButton PButton;
+
+PButton *create_pbutton(GList ** wlist, GdkPixmap * parent, GdkGC * gc,
+                        gint x, gint y, gint w, gint h, gint nx, gint ny,
+                        gint px, gint py, void (*push_cb) (void), SkinPixmapId si);
+PButton *create_pbutton_ex(GList ** wlist, GdkPixmap * parent, GdkGC * gc,
+                           gint x, gint y, gint w, gint h, gint nx,
+                           gint ny, gint px, gint py, void (*push_cb) (void),
+			   void (*release_cb) (void), SkinPixmapId si1,
+			   SkinPixmapId si2);
+void free_pbutton(PButton * b);
+void pbutton_set_skin_index(PButton * b, SkinPixmapId si);
+void pbutton_set_skin_index1(PButton * b, SkinPixmapId si);
+void pbutton_set_skin_index2(PButton * b, SkinPixmapId si);
+void pbutton_set_button_data(PButton * b, gint nx, gint ny, gint px, gint py);
+
+#endif
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/audacious/widgets/playlist_list.c	Wed Aug 09 02:47:22 2006 -0700
@@ -0,0 +1,954 @@
+/*  Audacious - Cross-platform multimedia player
+ *  Copyright (C) 2005-2006  Audacious development team.
+ *
+ *  BMP - Cross-platform multimedia player
+ *  Copyright (C) 2003-2004  BMP development team.
+ *
+ *  Based on XMMS:
+ *  Copyright (C) 1998-2003  XMMS development team.
+ *
+ *  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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+
+/*
+ *  A note about Pango and some funky spacey fonts: Weirdly baselined
+ *  fonts, or fonts with weird ascents or descents _will_ display a
+ *  little bit weird in the playlist widget, but the display engine
+ *  won't make it look too bad, just a little deranged.  I honestly
+ *  don't think it's worth fixing (around...), it doesn't have to be
+ *  perfectly fitting, just the general look has to be ok, which it
+ *  IMHO is.
+ *
+ *  A second note: The numbers aren't perfectly aligned, but in the
+ *  end it looks better when using a single Pango layout for each
+ *  number.
+ */
+
+#include "playlist_list.h"
+
+#include <stdlib.h>
+#include <string.h>
+
+#include "main.h"
+#include "input.h"
+#include "playback.h"
+#include "playlist.h"
+#include "ui_playlist.h"
+#include "util.h"
+
+#include "debug.h"
+
+static PangoFontDescription *playlist_list_font = NULL;
+static gint ascent, descent, width_delta_digit_one;
+static gboolean has_slant;
+static guint padding;
+
+/* FIXME: the following globals should not be needed. */
+static gint width_approx_letters;
+static gint width_colon, width_colon_third;
+static gint width_approx_digits, width_approx_digits_half;
+
+GdkPixmap *rootpix;
+
+void playlist_list_draw(Widget * w);
+
+/* Sort of stolen from XChat, but not really, as theres uses Xlib */
+static void
+shade_gdkimage_generic (GdkVisual *visual, GdkImage *ximg, int bpl, int w, int h, int rm, int gm, int bm, int bg)
+{
+	int x, y;
+	int bgr = (256 - rm) * (bg & visual->red_mask);
+	int bgg = (256 - gm) * (bg & visual->green_mask);
+	int bgb = (256 - bm) * (bg & visual->blue_mask);
+
+	for (x = 0; x < w; x++)
+	{
+		for (y = 0; y < h; y++)
+		{
+			unsigned long pixel = gdk_image_get_pixel (ximg, x, y);
+			int r, g, b;
+
+			r = rm * (pixel & visual->red_mask) + bgr;
+			g = gm * (pixel & visual->green_mask) + bgg;
+			b = bm * (pixel & visual->blue_mask) + bgb;
+
+			gdk_image_put_pixel (ximg, x, y,
+				((r >> 8) & visual->red_mask) |
+				((g >> 8) & visual->green_mask) |
+				((b >> 8) & visual->blue_mask));
+		}
+	}
+}
+
+/* and this is definately mine... -nenolod */
+GdkPixmap *
+shade_pixmap(GdkPixmap *in, gint x, gint y, gint x_offset, gint y_offset, gint w, gint h, GdkColor *shade_color)
+{
+	GdkImage *ximg;
+	GdkPixmap *p = gdk_pixmap_new(in, w, h, -1);
+	GdkGC *gc = gdk_gc_new(p);
+
+        gdk_draw_pixmap(p, gc, in, x, y, 0, 0, w, h);
+
+	gdk_error_trap_push();
+
+	ximg = gdk_drawable_copy_to_image(in, NULL, x, y, 0, 0, w, h);	/* copy */
+
+	gdk_error_trap_pop();
+
+	shade_gdkimage_generic(gdk_drawable_get_visual(GDK_WINDOW(playlistwin->window)),
+		ximg, ximg->bpl, w, h, 60, 60, 60, shade_color->pixel);
+
+	gdk_draw_image(p, gc, ximg, 0, 0, x, y, w, h);
+
+	g_object_unref(gc);
+
+	return p;
+}
+
+#ifdef GDK_WINDOWING_X11
+
+#include <gdk/gdkx.h>
+#include <X11/Xlib.h>
+#include <X11/Xatom.h>
+
+GdkDrawable *get_transparency_pixmap(void)
+{
+	GdkDrawable *root;
+	XID *pixmaps;
+	GdkAtom prop_type;
+	gint prop_size;
+	GdkPixmap *pixmap;
+	gboolean ret;
+
+	root = gdk_get_default_root_window();
+
+	pixmap = NULL;
+	pixmaps = NULL;
+
+	gdk_error_trap_push();
+
+	ret = gdk_property_get(root, gdk_atom_intern("_XROOTPMAP_ID", TRUE),
+			0, 0, INT_MAX - 3,
+			FALSE,
+			&prop_type, NULL, &prop_size,
+			(guchar **) &pixmaps);
+
+	gdk_error_trap_pop();
+
+	if ((ret == TRUE) && (prop_type == GDK_TARGET_PIXMAP) && (prop_size >= sizeof(XID)) && (pixmaps != NULL))
+	{
+		pixmap = gdk_pixmap_foreign_new_for_display(gdk_drawable_get_display(root),
+			pixmaps[0]);
+
+		if (pixmaps != NULL)
+			g_free(pixmaps);
+	}
+
+	return GDK_DRAWABLE(pixmap);
+}
+
+static GdkFilterReturn
+root_event_cb (GdkXEvent *xev, GdkEventProperty *event, gpointer data)
+{
+        static Atom at = None;
+        XEvent *xevent = (XEvent *)xev;
+
+        if (xevent->type == PropertyNotify)
+        {
+                if (at == None)
+                        at = XInternAtom (xevent->xproperty.display, "_XROOTPMAP_ID", True);
+
+                if (at == xevent->xproperty.atom)
+		{
+                        rootpix = shade_pixmap(get_transparency_pixmap(), 0, 0, 0, 0, gdk_screen_width(), gdk_screen_height(),
+                            skin_get_color(bmp_active_skin, SKIN_PLEDIT_NORMALBG));
+
+			if (cfg.playlist_transparent)
+			{
+				playlistwin_update_list();
+				draw_playlist_window(TRUE);
+			}
+		}
+        }
+
+        return GDK_FILTER_CONTINUE;
+}
+
+#else
+
+GdkPixmap *get_transparency_pixmap(void)
+{
+    return NULL;
+}
+
+#endif
+
+static gboolean
+playlist_list_auto_drag_down_func(gpointer data)
+{
+    PlayList_List *pl = data;
+
+    if (pl->pl_auto_drag_down) {
+        playlist_list_move_down(pl);
+        pl->pl_first++;
+        playlistwin_update_list();
+        return TRUE;
+    }
+    return FALSE;
+}
+
+static gboolean
+playlist_list_auto_drag_up_func(gpointer data)
+{
+    PlayList_List *pl = data;
+
+    if (pl->pl_auto_drag_up) {
+        playlist_list_move_up(pl);
+        pl->pl_first--;
+        playlistwin_update_list();
+        return TRUE;
+
+    }
+    return FALSE;
+}
+
+void
+playlist_list_move_up(PlayList_List * pl)
+{
+    GList *list;
+
+    PLAYLIST_LOCK();
+    if ((list = playlist_get()) == NULL) {
+        PLAYLIST_UNLOCK();
+        return;
+    }
+    if (PLAYLIST_ENTRY(list->data)->selected) {
+        /* We are at the top */
+        PLAYLIST_UNLOCK();
+        return;
+    }
+    while (list) {
+        if (PLAYLIST_ENTRY(list->data)->selected)
+            glist_moveup(list);
+        list = g_list_next(list);
+    }
+    PLAYLIST_UNLOCK();
+    if (pl->pl_prev_selected != -1)
+        pl->pl_prev_selected--;
+    if (pl->pl_prev_min != -1)
+        pl->pl_prev_min--;
+    if (pl->pl_prev_max != -1)
+        pl->pl_prev_max--;
+}
+
+void
+playlist_list_move_down(PlayList_List * pl)
+{
+    GList *list;
+
+    PLAYLIST_LOCK();
+
+    if (!(list = g_list_last(playlist_get()))) {
+        PLAYLIST_UNLOCK();
+        return;
+    }
+
+    if (PLAYLIST_ENTRY(list->data)->selected) {
+        /* We are at the bottom */
+        PLAYLIST_UNLOCK();
+        return;
+    }
+
+    while (list) {
+        if (PLAYLIST_ENTRY(list->data)->selected)
+            glist_movedown(list);
+        list = g_list_previous(list);
+    }
+
+    PLAYLIST_UNLOCK();
+
+    if (pl->pl_prev_selected != -1)
+        pl->pl_prev_selected++;
+    if (pl->pl_prev_min != -1)
+        pl->pl_prev_min++;
+    if (pl->pl_prev_max != -1)
+        pl->pl_prev_max++;
+}
+
+static void
+playlist_list_button_press_cb(GtkWidget * widget,
+                              GdkEventButton * event,
+                              PlayList_List * pl)
+{
+    gint nr, y;
+
+    if (event->button == 1 && pl->pl_fheight &&
+        widget_contains(&pl->pl_widget, event->x, event->y)) {
+
+        y = event->y - pl->pl_widget.y;
+        nr = (y / pl->pl_fheight) + pl->pl_first;
+
+        if (nr >= playlist_get_length())
+            nr = playlist_get_length() - 1;
+
+        if (!(event->state & GDK_CONTROL_MASK))
+            playlist_select_all(FALSE);
+
+        if (event->state & GDK_SHIFT_MASK && pl->pl_prev_selected != -1) {
+            playlist_select_range(pl->pl_prev_selected, nr, TRUE);
+            pl->pl_prev_min = pl->pl_prev_selected;
+            pl->pl_prev_max = nr;
+            pl->pl_drag_pos = nr - pl->pl_first;
+        }
+        else {
+            if (playlist_select_invert(nr)) {
+                if (event->state & GDK_CONTROL_MASK) {
+                    if (pl->pl_prev_min == -1) {
+                        pl->pl_prev_min = pl->pl_prev_selected;
+                        pl->pl_prev_max = pl->pl_prev_selected;
+                    }
+                    if (nr < pl->pl_prev_min)
+                        pl->pl_prev_min = nr;
+                    else if (nr > pl->pl_prev_max)
+                        pl->pl_prev_max = nr;
+                }
+                else
+                    pl->pl_prev_min = -1;
+                pl->pl_prev_selected = nr;
+                pl->pl_drag_pos = nr - pl->pl_first;
+            }
+        }
+        if (event->type == GDK_2BUTTON_PRESS) {
+            /*
+             * Ungrab the pointer to prevent us from
+             * hanging on to it during the sometimes slow
+             * bmp_playback_initiate().
+             */
+            gdk_pointer_ungrab(GDK_CURRENT_TIME);
+            gdk_flush();
+            playlist_set_position(nr);
+            if (!bmp_playback_get_playing())
+                bmp_playback_initiate();
+        }
+
+        pl->pl_dragging = TRUE;
+        playlistwin_update_list();
+    }
+}
+
+gint
+playlist_list_get_playlist_position(PlayList_List * pl,
+                                    gint x,
+                                    gint y)
+{
+    gint iy, length;
+
+    if (!widget_contains(WIDGET(pl), x, y) || !pl->pl_fheight)
+        return -1;
+
+    if ((length = playlist_get_length()) == 0)
+        return -1;
+    iy = y - pl->pl_widget.y;
+
+    return (MIN((iy / pl->pl_fheight) + pl->pl_first, length - 1));
+}
+
+static void
+playlist_list_motion_cb(GtkWidget * widget,
+                        GdkEventMotion * event,
+                        PlayList_List * pl)
+{
+    gint nr, y, off, i;
+
+    if (pl->pl_dragging) {
+        y = event->y - pl->pl_widget.y;
+        nr = (y / pl->pl_fheight);
+        if (nr < 0) {
+            nr = 0;
+            if (!pl->pl_auto_drag_up) {
+                pl->pl_auto_drag_up = TRUE;
+                pl->pl_auto_drag_up_tag =
+                    gtk_timeout_add(100, playlist_list_auto_drag_up_func, pl);
+            }
+        }
+        else if (pl->pl_auto_drag_up)
+            pl->pl_auto_drag_up = FALSE;
+
+        if (nr >= pl->pl_num_visible) {
+            nr = pl->pl_num_visible - 1;
+            if (!pl->pl_auto_drag_down) {
+                pl->pl_auto_drag_down = TRUE;
+                pl->pl_auto_drag_down_tag =
+                    gtk_timeout_add(100, playlist_list_auto_drag_down_func,
+                                    pl);
+            }
+        }
+        else if (pl->pl_auto_drag_down)
+            pl->pl_auto_drag_down = FALSE;
+
+        off = nr - pl->pl_drag_pos;
+        if (off) {
+            for (i = 0; i < abs(off); i++) {
+                if (off < 0)
+                    playlist_list_move_up(pl);
+                else
+                    playlist_list_move_down(pl);
+
+            }
+            playlistwin_update_list();
+        }
+        pl->pl_drag_pos = nr;
+    }
+}
+
+static void
+playlist_list_button_release_cb(GtkWidget * widget,
+                                GdkEventButton * event,
+                                PlayList_List * pl)
+{
+    pl->pl_dragging = FALSE;
+    pl->pl_auto_drag_down = FALSE;
+    pl->pl_auto_drag_up = FALSE;
+}
+
+static void
+playlist_list_draw_string(PlayList_List * pl,
+                          PangoFontDescription * font,
+                          gint line,
+                          gint width,
+                          const gchar * text,
+                          guint ppos)
+{
+    guint plist_length_int;
+
+    PangoLayout *layout;
+
+    REQUIRE_STATIC_LOCK(playlist);
+
+    if (cfg.show_numbers_in_pl) {
+        gchar *pos_string = g_strdup_printf(cfg.show_separator_in_pl == TRUE ? "%d" : "%d.", ppos);
+        plist_length_int =
+            gint_count_digits(playlist_get_length_nolock()) + !cfg.show_separator_in_pl + 1; /* cf.show_separator_in_pl will be 0 if false */
+
+        padding = plist_length_int;
+        padding = ((padding + 1) * width_approx_digits);
+
+        layout = gtk_widget_create_pango_layout(playlistwin, pos_string);
+        pango_layout_set_font_description(layout, playlist_list_font);
+        pango_layout_set_width(layout, plist_length_int * 100);
+
+        pango_layout_set_alignment(layout, PANGO_ALIGN_LEFT);
+        gdk_draw_layout(pl->pl_widget.parent, pl->pl_widget.gc,
+                        pl->pl_widget.x +
+                        (width_approx_digits *
+                         (-1 + plist_length_int - strlen(pos_string))) +
+                        (width_approx_digits / 4),
+                        pl->pl_widget.y + (line - 1) * pl->pl_fheight +
+                        ascent + abs(descent), layout);
+        g_free(pos_string);
+        g_object_unref(layout);
+
+        if (!cfg.show_separator_in_pl)
+            padding -= (width_approx_digits * 1.5);
+    }
+    else {
+        padding = 3;
+    }
+
+    width -= padding;
+
+    layout = gtk_widget_create_pango_layout(playlistwin, text);
+
+    pango_layout_set_font_description(layout, playlist_list_font);
+    pango_layout_set_width(layout, width * PANGO_SCALE);
+    pango_layout_set_single_paragraph_mode(layout, TRUE);
+    pango_layout_set_ellipsize(layout, PANGO_ELLIPSIZE_END);
+    gdk_draw_layout(pl->pl_widget.parent, pl->pl_widget.gc,
+                    pl->pl_widget.x + padding + (width_approx_letters / 4),
+                    pl->pl_widget.y + (line - 1) * pl->pl_fheight +
+                    ascent + abs(descent), layout);
+
+    g_object_unref(layout);
+}
+
+void
+playlist_list_draw(Widget * w)
+{
+    PlayList_List *pl = PLAYLIST_LIST(w);
+    GList *list;
+    GdkGC *gc;
+    GdkPixmap *obj;
+    PangoLayout *layout;
+    gchar *title;
+    gint width, height;
+    gint i, max_first;
+    guint padding, padding_dwidth, padding_plength;
+    guint max_time_len = 0;
+    gfloat queue_tailpadding = 0;
+    gint tpadding; 
+    gsize tpadding_dwidth = 0;
+    gint x, y;
+    guint tail_width;
+    guint tail_len;
+
+    gchar tail[100];
+    gchar queuepos[255];
+    gchar length[40];
+
+    gchar **frags;
+    gchar *frag0;
+
+    gint plw_w, plw_h;
+
+    GdkRectangle *playlist_rect;
+
+    gc = pl->pl_widget.gc;
+
+    width = pl->pl_widget.width;
+    height = pl->pl_widget.height;
+
+    obj = pl->pl_widget.parent;
+
+    gtk_window_get_size(GTK_WINDOW(playlistwin), &plw_w, &plw_h);
+
+    playlist_rect = g_new0(GdkRectangle, 1);
+
+    playlist_rect->x = 0;
+    playlist_rect->y = 0;
+    playlist_rect->width = plw_w - 17;
+    playlist_rect->height = plw_h - 36;
+
+    gdk_gc_set_clip_origin(gc, 31, 58);
+    gdk_gc_set_clip_rectangle(gc, playlist_rect);
+
+    if (cfg.playlist_transparent == FALSE)
+    {
+        gdk_gc_set_foreground(gc,
+                              skin_get_color(bmp_active_skin,
+                                             SKIN_PLEDIT_NORMALBG));
+        gdk_draw_rectangle(obj, gc, TRUE, pl->pl_widget.x, pl->pl_widget.y,
+                              width, height);
+    }
+    else
+    {
+	if (!rootpix)
+           rootpix = shade_pixmap(get_transparency_pixmap(), 0, 0, 0, 0, gdk_screen_width(), gdk_screen_height(), 
+    			    skin_get_color(bmp_active_skin, SKIN_PLEDIT_NORMALBG));
+        gdk_draw_pixmap(obj, gc, rootpix, cfg.playlist_x + pl->pl_widget.x,
+                    cfg.playlist_y + pl->pl_widget.y, pl->pl_widget.x, pl->pl_widget.y,
+                    width, height);
+    }
+
+    if (!playlist_list_font) {
+        g_critical("Couldn't open playlist font");
+        return;
+    }
+
+    pl->pl_fheight = (ascent + abs(descent));
+    pl->pl_num_visible = height / pl->pl_fheight;
+
+    max_first = playlist_get_length() - pl->pl_num_visible;
+    max_first = MAX(max_first, 0);
+
+    pl->pl_first = CLAMP(pl->pl_first, 0, max_first);
+
+    PLAYLIST_LOCK();
+    list = playlist_get();
+    list = g_list_nth(list, pl->pl_first);
+
+    /* It sucks having to run the iteration twice but this is the only
+       way you can reliably get the maximum width so we can get our
+       playlist nice and aligned... -- plasmaroo */
+
+    for (i = pl->pl_first;
+         list && i < pl->pl_first + pl->pl_num_visible;
+         list = g_list_next(list), i++) {
+        PlaylistEntry *entry = list->data;
+
+        if (entry->length != -1)
+        {
+            g_snprintf(length, sizeof(length), "%d:%-2.2d",
+                       entry->length / 60000, (entry->length / 1000) % 60);
+            tpadding_dwidth = MAX(tpadding_dwidth, strlen(length));
+        }
+    }
+
+    /* Reset */
+    list = playlist_get();
+    list = g_list_nth(list, pl->pl_first);
+
+    for (i = pl->pl_first;
+         list && i < pl->pl_first + pl->pl_num_visible;
+         list = g_list_next(list), i++) {
+        gint pos;
+        PlaylistEntry *entry = list->data;
+
+        if (entry->selected) {
+            gdk_gc_set_foreground(gc,
+                                  skin_get_color(bmp_active_skin,
+                                                 SKIN_PLEDIT_SELECTEDBG));
+            gdk_draw_rectangle(obj, gc, TRUE, pl->pl_widget.x,
+                               pl->pl_widget.y +
+                               ((i - pl->pl_first) * pl->pl_fheight),
+                               width, pl->pl_fheight);
+        }
+
+        /* FIXME: entry->title should NEVER be NULL, and there should
+           NEVER be a need to do a UTF-8 conversion. Playlist title
+           strings should be kept properly. */
+
+        if (!entry->title) {
+            gchar *basename = g_path_get_basename(entry->filename);
+            title = filename_to_utf8(basename);
+            g_free(basename);
+        }
+        else
+            title = str_to_utf8(entry->title);
+
+        pos = playlist_get_queue_position(entry);
+
+        tail[0] = 0;
+        queuepos[0] = 0;
+        length[0] = 0;
+
+        if (pos != -1)
+            g_snprintf(queuepos, sizeof(queuepos), "%d", pos + 1);
+
+        if (entry->length != -1)
+        {
+            g_snprintf(length, sizeof(length), "%d:%-2.2d",
+                       entry->length / 60000, (entry->length / 1000) % 60);
+        }
+
+        strncat(tail, length, sizeof(tail));
+        tail_len = strlen(tail);
+
+        max_time_len = MAX(max_time_len, tail_len);
+
+        if (pos != -1 && tpadding_dwidth <= 0)
+            tail_width = width - (width_approx_digits * (strlen(queuepos) + 2.25));
+        else if (pos != -1)
+            tail_width = width - (width_approx_digits * (tpadding_dwidth + strlen(queuepos) + 4));
+        else if (tpadding_dwidth > 0)
+            tail_width = width - (width_approx_digits * (tpadding_dwidth + 2.5));
+        else
+            tail_width = width;
+
+        if (i == playlist_get_position_nolock())
+            gdk_gc_set_foreground(gc,
+                                  skin_get_color(bmp_active_skin,
+                                                 SKIN_PLEDIT_CURRENT));
+        else
+            gdk_gc_set_foreground(gc,
+                                  skin_get_color(bmp_active_skin,
+                                                 SKIN_PLEDIT_NORMAL));
+        playlist_list_draw_string(pl, playlist_list_font,
+                                  i - pl->pl_first, tail_width, title,
+                                  i + 1);
+
+        x = pl->pl_widget.x + width - width_approx_digits * 2;
+        y = pl->pl_widget.y + ((i - pl->pl_first) -
+                               1) * pl->pl_fheight + ascent;
+
+        frags = NULL;
+        frag0 = NULL;
+
+        if ((strlen(tail) > 0) && (tail != NULL)) {
+            frags = g_strsplit(tail, ":", 0);
+            frag0 = g_strconcat(frags[0], ":", NULL);
+
+            layout = gtk_widget_create_pango_layout(playlistwin, frags[1]);
+            pango_layout_set_font_description(layout, playlist_list_font);
+            pango_layout_set_width(layout, tail_len * 100);
+            pango_layout_set_alignment(layout, PANGO_ALIGN_LEFT);
+            gdk_draw_layout(obj, gc, x - (0.5 * width_approx_digits),
+                            y + abs(descent), layout);
+            g_object_unref(layout);
+
+            layout = gtk_widget_create_pango_layout(playlistwin, frag0);
+            pango_layout_set_font_description(layout, playlist_list_font);
+            pango_layout_set_width(layout, tail_len * 100);
+            pango_layout_set_alignment(layout, PANGO_ALIGN_RIGHT);
+            gdk_draw_layout(obj, gc, x - (0.75 * width_approx_digits),
+                            y + abs(descent), layout);
+            g_object_unref(layout);
+
+            g_free(frag0);
+            g_strfreev(frags);
+        }
+
+        if (pos != -1) {
+
+            /* DON'T remove the commented code yet please     -- Milosz */
+
+            if (tpadding_dwidth > 0)
+                queue_tailpadding = tpadding_dwidth + 1;
+            else
+                queue_tailpadding = -0.75;
+
+            gdk_draw_rectangle(obj, gc, FALSE,
+                               x -
+                               (((queue_tailpadding +
+                                  strlen(queuepos)) *
+                                 width_approx_digits) +
+                                (width_approx_digits / 4)),
+                               y + abs(descent),
+                               (strlen(queuepos)) *
+                               width_approx_digits +
+                               (width_approx_digits / 2),
+                               pl->pl_fheight - 2);
+
+            layout =
+                gtk_widget_create_pango_layout(playlistwin, queuepos);
+            pango_layout_set_font_description(layout, playlist_list_font);
+            pango_layout_set_alignment(layout, PANGO_ALIGN_CENTER);
+
+            gdk_draw_layout(obj, gc,
+                            x -
+                            ((queue_tailpadding +
+                              strlen(queuepos)) * width_approx_digits) +
+                            (width_approx_digits / 4),
+                            y + abs(descent), layout);
+            g_object_unref(layout);
+        }
+
+        g_free(title);
+    }
+
+
+    /*
+     * Drop target hovering over the playlist, so draw some hint where the
+     * drop will occur.
+     *
+     * This is (currently? unfixably?) broken when dragging files from Qt/KDE apps,
+     * probably due to DnD signaling problems (actually i have no clue).
+     *
+     */
+
+    if (pl->pl_drag_motion) {
+        guint pos, plength, lpadding;
+	gint x, y, plx, ply;
+
+        if (cfg.show_numbers_in_pl) {
+            lpadding = gint_count_digits(playlist_get_length_nolock()) + 1;
+            lpadding = ((lpadding + 1) * width_approx_digits);
+        }
+        else {
+            lpadding = 3;
+        };
+
+        /* We already hold the mutex and have the playlist locked, so call
+           the non-locking function. */
+        plength = playlist_get_length_nolock();
+
+        x = pl->drag_motion_x;
+        y = pl->drag_motion_y;
+
+        plx = pl->pl_widget.x;
+        ply = pl->pl_widget.y;
+
+        if ((x > pl->pl_widget.x) && !(x > pl->pl_widget.width)) {
+
+            if ((y > pl->pl_widget.y)
+                && !(y > (pl->pl_widget.height + ply))) {
+
+                pos = ((y - ((Widget *) pl)->y) / pl->pl_fheight) +
+                    pl->pl_first;
+
+                if (pos > (plength)) {
+                    pos = plength;
+                }
+
+                gdk_gc_set_foreground(gc,
+                                      skin_get_color(bmp_active_skin,
+                                                     SKIN_PLEDIT_CURRENT));
+
+                gdk_draw_line(obj, gc, pl->pl_widget.x,
+			      pl->pl_widget.y + ((pos - pl->pl_first) * pl->pl_fheight),
+                              pl->pl_widget.width + pl->pl_widget.x - 1,
+                              pl->pl_widget.y +
+                              ((pos - pl->pl_first) * pl->pl_fheight));
+            }
+
+        }
+
+        /* When dropping on the borders of the playlist, outside the text area,
+         * files get appended at the end of the list. Show that too.
+         */
+
+        if ((y < ply) || (y > pl->pl_widget.height + ply)) {
+            if ((y >= 0) || (y <= (pl->pl_widget.height + ply))) {
+                pos = plength;
+                gdk_gc_set_foreground(gc,
+                                      skin_get_color(bmp_active_skin,
+                                                     SKIN_PLEDIT_CURRENT));
+
+                gdk_draw_line(obj, gc, pl->pl_widget.x,
+                              pl->pl_widget.y +
+                              ((pos - pl->pl_first) * pl->pl_fheight),
+                              pl->pl_widget.width + pl->pl_widget.x - 1,
+                              pl->pl_widget.y +
+                              ((pos - pl->pl_first) * pl->pl_fheight));
+
+            }
+        }
+    }
+
+    gdk_gc_set_foreground(gc,
+                          skin_get_color(bmp_active_skin,
+                                         SKIN_PLEDIT_NORMAL));
+
+    if (cfg.show_numbers_in_pl) {
+
+        padding_plength = playlist_get_length_nolock();
+
+        if (padding_plength == 0) {
+            padding_dwidth = 0;
+        }
+        else {
+            padding_dwidth = gint_count_digits(playlist_get_length_nolock());
+        }
+
+        padding =
+            (padding_dwidth *
+             width_approx_digits) + width_approx_digits;
+
+
+        /* For italic or oblique fonts we add another half of the
+         * approximate width */
+        if (has_slant)
+            padding += width_approx_digits_half;
+
+        if (cfg.show_separator_in_pl) {
+            gdk_draw_line(obj, gc,
+                          pl->pl_widget.x + padding,
+                          pl->pl_widget.y,
+                          pl->pl_widget.x + padding,
+                          pl->pl_widget.y + pl->pl_widget.height - 1);
+        }
+    }
+
+    if (tpadding_dwidth != 0)
+    {
+        tpadding = (tpadding_dwidth * width_approx_digits) + (width_approx_digits * 1.5);
+
+        if (has_slant)
+            tpadding += width_approx_digits_half;
+
+        if (cfg.show_separator_in_pl) {
+            gdk_draw_line(obj, gc,
+                          pl->pl_widget.x + pl->pl_widget.width - tpadding,
+                          pl->pl_widget.y,
+                          pl->pl_widget.x + pl->pl_widget.width - tpadding,
+                          pl->pl_widget.y + pl->pl_widget.height - 1);
+        }
+    }
+
+    gdk_gc_set_clip_origin(gc, 0, 0);
+    gdk_gc_set_clip_rectangle(gc, NULL);
+
+    PLAYLIST_UNLOCK();
+
+    gdk_flush();
+
+    g_free(playlist_rect);
+}
+
+
+PlayList_List *
+create_playlist_list(GList ** wlist,
+                     GdkPixmap * parent,
+                     GdkGC * gc,
+                     gint x, gint y,
+                     gint w, gint h)
+{
+    PlayList_List *pl;
+
+    pl = g_new0(PlayList_List, 1);
+    widget_init(&pl->pl_widget, parent, gc, x, y, w, h, TRUE);
+
+    pl->pl_widget.button_press_cb =
+        (WidgetButtonPressFunc) playlist_list_button_press_cb;
+    pl->pl_widget.button_release_cb =
+        (WidgetButtonReleaseFunc) playlist_list_button_release_cb;
+    pl->pl_widget.motion_cb = (WidgetMotionFunc) playlist_list_motion_cb;
+    pl->pl_widget.draw = playlist_list_draw;
+
+    pl->pl_prev_selected = -1;
+    pl->pl_prev_min = -1;
+    pl->pl_prev_max = -1;
+
+    widget_list_add(wlist, WIDGET(pl));
+
+#ifdef GDK_WINDOWING_X11
+    gdk_window_set_events (gdk_get_default_root_window(), GDK_PROPERTY_CHANGE_MASK);
+    gdk_window_add_filter (gdk_get_default_root_window(), (GdkFilterFunc)root_event_cb, pl);
+#endif
+
+    return pl;
+}
+
+void
+playlist_list_set_font(const gchar * font)
+{
+
+    /* Welcome to bad hack central 2k3 */
+
+    gchar *font_lower;
+    gint width_temp;
+    gint width_temp_0;
+
+    playlist_list_font = pango_font_description_from_string(font);
+
+    text_get_extents(font,
+                     "AaBbCcDdEeFfGgHhIiJjKkLlMmNnOoPpQqRrSsTtUuVvWwXxYyZz ",
+                     &width_approx_letters, NULL, &ascent, &descent);
+
+    width_approx_letters = (width_approx_letters / 53);
+
+    /* Experimental: We don't weigh the 1 into total because it's width is almost always
+     * very different from the rest
+     */
+    text_get_extents(font, "023456789", &width_approx_digits, NULL, NULL,
+                     NULL);
+    width_approx_digits = (width_approx_digits / 9);
+
+    /* Precache some often used calculations */
+    width_approx_digits_half = width_approx_digits / 2;
+
+    /* FIXME: We assume that any other number is broader than the "1" */
+    text_get_extents(font, "1", &width_temp, NULL, NULL, NULL);
+    text_get_extents(font, "2", &width_temp_0, NULL, NULL, NULL);
+
+    if (abs(width_temp_0 - width_temp) < 2) {
+        width_delta_digit_one = 0;
+    }
+    else {
+        width_delta_digit_one = ((width_temp_0 - width_temp) / 2) + 2;
+    }
+
+    text_get_extents(font, ":", &width_colon, NULL, NULL, NULL);
+    width_colon_third = width_colon / 4;
+
+    font_lower = g_utf8_strdown(font, strlen(font));
+    /* This doesn't take any i18n into account, but i think there is none with TTF fonts
+     * FIXME: This can probably be retrieved trough Pango too
+     */
+    has_slant = g_strstr_len(font_lower, strlen(font_lower), "oblique")
+        || g_strstr_len(font_lower, strlen(font_lower), "italic");
+
+    g_free(font_lower);
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/audacious/widgets/playlist_list.h	Wed Aug 09 02:47:22 2006 -0700
@@ -0,0 +1,56 @@
+/*  BMP - Cross-platform multimedia player
+ *  Copyright (C) 2003-2004  BMP development team.
+ *
+ *  Based on XMMS:
+ *  Copyright (C) 1998-2003  XMMS development team.
+ *
+ *  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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+
+#ifndef PLAYLIST_LIST_H
+#define PLAYLIST_LIST_H
+
+#include <glib.h>
+#include <gtk/gtk.h>
+#include <gdk/gdk.h>
+
+#include "widget.h"
+
+#define PLAYLIST_LIST(x)    ((PlayList_List *)(x))
+struct _PlayList_List {
+    Widget pl_widget;
+    gint pl_first, pl_fheight, pl_prev_selected, pl_prev_min, pl_prev_max;
+    gint pl_num_visible, pl_drag_pos;
+    gboolean pl_dragging, pl_auto_drag_down, pl_auto_drag_up;
+    gint pl_auto_drag_up_tag, pl_auto_drag_down_tag;
+    gboolean pl_drag_motion;
+    gint drag_motion_x, drag_motion_y;
+    gboolean pl_tooltips;
+};
+
+typedef struct _PlayList_List PlayList_List;
+
+PlayList_List *create_playlist_list(GList ** wlist, GdkPixmap * parent,
+                                    GdkGC * gc, gint x, gint y, gint w,
+                                    gint h);
+void playlist_list_move_up(PlayList_List * pl);
+void playlist_list_move_down(PlayList_List * pl);
+int playlist_list_get_playlist_position(PlayList_List * pl, gint x, gint y);
+void playlist_list_set_font(const gchar * font);
+GdkPixmap *rootpix;
+GdkPixmap *shade_pixmap(GdkDrawable *in, gint x, gint y, gint x_offset, gint y_offset, gint w, gint h, GdkColor *shade_color);
+GdkDrawable *get_transparency_pixmap(void);
+
+#endif
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/audacious/widgets/playlist_slider.c	Wed Aug 09 02:47:22 2006 -0700
@@ -0,0 +1,168 @@
+/*  BMP - Cross-platform multimedia player
+ *  Copyright (C) 2003-2004  BMP development team.
+ *
+ *  Based on XMMS:
+ *  Copyright (C) 1998-2003  XMMS development team.
+ *
+ *  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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+
+#include "playlist_slider.h"
+
+#include <glib.h>
+
+#include "playlist.h"
+#include "ui_playlist.h"
+#include "skin.h"
+#include "widget.h"
+
+void
+playlistslider_draw(Widget * w)
+{
+    PlaylistSlider *ps = (PlaylistSlider *) w;
+    GdkPixmap *obj;
+    gint y, skinx;
+
+    g_return_if_fail(ps != NULL);
+    g_return_if_fail(ps->ps_list != NULL);
+
+    if (playlist_get_length() > ps->ps_list->pl_num_visible)
+        y = (ps->ps_list->pl_first * (ps->ps_widget.height - 19)) /
+            (playlist_get_length() - ps->ps_list->pl_num_visible);
+    else
+        y = 0;
+
+    obj = ps->ps_widget.parent;
+
+    if (ps->ps_back_image) {
+        if (skin_get_id() != ps->ps_skin_id)
+            ps->ps_skin_id = skin_get_id();
+        else if (ps->ps_widget.height == ps->ps_prev_height)
+            gdk_draw_image(obj, ps->ps_widget.gc,
+                           ps->ps_back_image, 0, 0,
+                           ps->ps_widget.x,
+                           ps->ps_widget.y + ps->ps_prev_y, 8, 18);
+        gdk_image_destroy(ps->ps_back_image);
+    }
+
+    ps->ps_prev_y = y;
+    ps->ps_prev_height = ps->ps_widget.height;
+    ps->ps_back_image = gdk_drawable_get_image(obj, ps->ps_widget.x,
+                                               ps->ps_widget.y + y, 8, 18);
+    if (ps->ps_is_draging)
+        skinx = 61;
+    else
+        skinx = 52;
+
+    skin_draw_pixmap(bmp_active_skin, obj, ps->ps_widget.gc, SKIN_PLEDIT,
+                     skinx, 53, ps->ps_widget.x, ps->ps_widget.y + y, 8, 18);
+}
+
+static void
+playlistslider_set_pos(PlaylistSlider * ps, gint y)
+{
+    gint pos;
+
+    y = CLAMP(y, 0, ps->ps_widget.height - 19);
+
+    pos = (y * (playlist_get_length() - ps->ps_list->pl_num_visible)) /
+        (ps->ps_widget.height - 19);
+    playlistwin_set_toprow(pos);
+}
+
+
+void
+playlistslider_button_press_cb(GtkWidget * widget,
+                               GdkEventButton * event, PlaylistSlider * ps)
+{
+    gint y = event->y - ps->ps_widget.y;
+
+    if (!widget_contains(&ps->ps_widget, event->x, event->y))
+        return;
+
+    if (event->button != 1 && event->button != 2)
+        return;
+
+    if ((y >= ps->ps_prev_y && y < ps->ps_prev_y + 18)) {
+        ps->ps_is_draging |= event->button;
+        ps->ps_drag_y = y - ps->ps_prev_y;
+        widget_draw(WIDGET(ps));
+    }
+    else if (event->button == 2) {
+        playlistslider_set_pos(ps, y);
+        ps->ps_is_draging |= event->button;
+        ps->ps_drag_y = 0;
+        widget_draw(WIDGET(ps));
+    }
+    else {
+        gint n = ps->ps_list->pl_num_visible / 2;
+        if (y < ps->ps_prev_y)
+            n *= -1;
+        playlistwin_scroll(n);
+    }
+}
+
+void
+playlistslider_button_release_cb(GtkWidget * widget,
+                                 GdkEventButton * event,
+                                 PlaylistSlider * ps)
+{
+    if (ps->ps_is_draging) {
+        ps->ps_is_draging &= ~event->button;
+        widget_draw(WIDGET(ps));
+    }
+}
+
+void
+playlistslider_motion_cb(GtkWidget * widget, GdkEventMotion * event,
+                         PlaylistSlider * ps)
+{
+    gint y;
+
+    if (!ps->ps_is_draging)
+        return;
+
+    y = event->y - ps->ps_widget.y - ps->ps_drag_y;
+    playlistslider_set_pos(ps, y);
+}
+
+PlaylistSlider *
+create_playlistslider(GList ** wlist, GdkPixmap * parent,
+                      GdkGC * gc, gint x, gint y, gint h,
+                      PlayList_List * list)
+{
+    PlaylistSlider *ps;
+
+    ps = g_new0(PlaylistSlider, 1);
+    widget_init(&ps->ps_widget, parent, gc, x, y, 8, h, 1);
+
+    ps->ps_widget.button_press_cb =
+        (void (*)(GtkWidget *, GdkEventButton *, gpointer))
+        playlistslider_button_press_cb;
+
+    ps->ps_widget.button_release_cb =
+        (void (*)(GtkWidget *, GdkEventButton *, gpointer))
+        playlistslider_button_release_cb;
+
+    ps->ps_widget.motion_cb =
+        (void (*)(GtkWidget *, GdkEventMotion *, gpointer))
+        playlistslider_motion_cb;
+
+    ps->ps_widget.draw = playlistslider_draw;
+    ps->ps_list = list;
+
+    widget_list_add(wlist, WIDGET(ps));
+    return ps;
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/audacious/widgets/playlist_slider.h	Wed Aug 09 02:47:22 2006 -0700
@@ -0,0 +1,47 @@
+/*  BMP - Cross-platform multimedia player
+ *  Copyright (C) 2003-2004  BMP development team.
+ *
+ *  Based on XMMS:
+ *  Copyright (C) 1998-2003  XMMS development team.
+ *
+ *  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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+
+#ifndef PLAYLIST_SLIDER_H
+#define PLAYLIST_SLIDER_H
+
+#include <glib.h>
+#include <gdk/gdk.h>
+
+#include "playlist_list.h"
+#include "widget.h"
+
+#define PLAYLIST_SLIDER(x)  ((PlayerlistSlider *)(x))
+struct _PlaylistSlider {
+    Widget ps_widget;
+    PlayList_List *ps_list;
+    gboolean ps_is_draging;
+    gint ps_drag_y, ps_prev_y, ps_prev_height;
+    GdkImage *ps_back_image;
+    gint ps_skin_id;
+};
+
+typedef struct _PlaylistSlider PlaylistSlider;
+
+PlaylistSlider *create_playlistslider(GList ** wlist, GdkPixmap * parent,
+                                      GdkGC * gc, gint x, gint y, gint h,
+                                      PlayList_List * list);
+
+#endif
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/audacious/widgets/playstatus.c	Wed Aug 09 02:47:22 2006 -0700
@@ -0,0 +1,102 @@
+/*  XMMS - Cross-platform multimedia player
+ *  Copyright (C) 1998-2000  Peter Alm, Mikael Alm, Olle Hallnas, Thomas Nilsson and 4Front Technologies
+ *
+ *  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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+
+#include "playstatus.h"
+
+#include <glib.h>
+#include <gdk/gdk.h>
+
+#include "skin.h"
+#include "widget.h"
+
+void
+playstatus_draw(Widget * w)
+{
+    PlayStatus *ps = PLAY_STATUS(w);
+    GdkPixmap *obj;
+
+    if (!w)
+        return;
+
+    obj = ps->ps_widget.parent;
+    if (ps->ps_status == STATUS_STOP && ps->ps_status_buffering == TRUE)
+        ps->ps_status_buffering = FALSE;
+    if (ps->ps_status == STATUS_PLAY && ps->ps_status_buffering == TRUE)
+        skin_draw_pixmap(bmp_active_skin, obj, ps->ps_widget.gc,
+                         SKIN_PLAYPAUSE, 39, 0, ps->ps_widget.x,
+                         ps->ps_widget.y, 3, 9);
+    else if (ps->ps_status == STATUS_PLAY)
+        skin_draw_pixmap(bmp_active_skin, obj, ps->ps_widget.gc,
+                         SKIN_PLAYPAUSE, 36, 0, ps->ps_widget.x,
+                         ps->ps_widget.y, 3, 9);
+    else
+        skin_draw_pixmap(bmp_active_skin, obj, ps->ps_widget.gc,
+                         SKIN_PLAYPAUSE, 27, 0, ps->ps_widget.x,
+                         ps->ps_widget.y, 2, 9);
+    switch (ps->ps_status) {
+    case STATUS_STOP:
+        skin_draw_pixmap(bmp_active_skin, obj, ps->ps_widget.gc,
+                         SKIN_PLAYPAUSE, 18, 0,
+                         ps->ps_widget.x + 2, ps->ps_widget.y, 9, 9);
+        break;
+    case STATUS_PAUSE:
+        skin_draw_pixmap(bmp_active_skin, obj, ps->ps_widget.gc,
+                         SKIN_PLAYPAUSE, 9, 0,
+                         ps->ps_widget.x + 2, ps->ps_widget.y, 9, 9);
+        break;
+    case STATUS_PLAY:
+        skin_draw_pixmap(bmp_active_skin, obj, ps->ps_widget.gc,
+                         SKIN_PLAYPAUSE, 1, 0,
+                         ps->ps_widget.x + 3, ps->ps_widget.y, 8, 9);
+        break;
+    }
+}
+
+void
+playstatus_set_status(PlayStatus * ps, PStatus status)
+{
+    if (!ps)
+        return;
+
+    ps->ps_status = status;
+    widget_draw(WIDGET(ps));
+}
+
+void
+playstatus_set_status_buffering(PlayStatus * ps, gboolean status)
+{
+    if (!ps)
+        return;
+
+    ps->ps_status_buffering = status;
+    widget_draw(WIDGET(ps));
+}
+
+PlayStatus *
+create_playstatus(GList ** wlist, GdkPixmap * parent,
+                  GdkGC * gc, gint x, gint y)
+{
+    PlayStatus *ps;
+
+    ps = g_new0(PlayStatus, 1);
+    widget_init(&ps->ps_widget, parent, gc, x, y, 11, 9, TRUE);
+    ps->ps_widget.draw = playstatus_draw;
+
+    widget_list_add(wlist, WIDGET(ps));
+    return ps;
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/audacious/widgets/playstatus.h	Wed Aug 09 02:47:22 2006 -0700
@@ -0,0 +1,41 @@
+/*  XMMS - Cross-platform multimedia player
+ *  Copyright (C) 1998-2000  Peter Alm, Mikael Alm, Olle Hallnas, Thomas Nilsson and 4Front Technologies
+ *
+ *  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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+#ifndef PLAYSTATUS_H
+#define PLAYSTATUS_H
+
+#include "widget.h"
+
+typedef enum {
+    STATUS_STOP, STATUS_PAUSE, STATUS_PLAY
+} PStatus;
+
+#define PLAY_STATUS(x)  ((PlayStatus *)(x))
+struct _PlayStatus {
+    Widget ps_widget;
+    PStatus ps_status;
+    gboolean ps_status_buffering;
+};
+
+typedef struct _PlayStatus PlayStatus;
+
+void playstatus_set_status(PlayStatus * ps, PStatus status);
+void playstatus_set_status_buffering(PlayStatus * ps, gboolean status);
+PlayStatus *create_playstatus(GList ** wlist, GdkPixmap * parent,
+                              GdkGC * gc, gint x, gint y);
+
+#endif
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/audacious/widgets/sbutton.c	Wed Aug 09 02:47:22 2006 -0700
@@ -0,0 +1,99 @@
+/*  BMP - Cross-platform multimedia player
+ *  Copyright (C) 2003-2004  BMP development team.
+ *
+ *  Based on XMMS:
+ *  Copyright (C) 1998-2003  XMMS development team.
+ *
+ *  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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+
+#include "sbutton.h"
+
+#include <glib.h>
+#include <gtk/gtk.h>
+#include <gdk/gdk.h>
+
+void
+sbutton_button_press_cb(GtkWidget * widget,
+                        GdkEventButton * event,
+                        SButton * button)
+{
+    if (event->button != 1)
+        return;
+
+    if (widget_contains(&button->sb_widget, event->x, event->y)) {
+        button->sb_pressed = 1;
+        button->sb_inside = 1;
+    }
+}
+
+void
+sbutton_button_release_cb(GtkWidget * widget, GdkEventButton * event,
+                          SButton * button)
+{
+    if (event->button != 1)
+        return;
+    if (button->sb_inside && button->sb_pressed) {
+        button->sb_inside = 0;
+        if (button->sb_push_cb)
+            button->sb_push_cb();
+    }
+    if (button->sb_pressed)
+        button->sb_pressed = 0;
+}
+
+void
+sbutton_motion_cb(GtkWidget * widget, GdkEventMotion * event,
+                  SButton * button)
+{
+    int inside;
+
+    if (!button->sb_pressed)
+        return;
+
+    inside = widget_contains(&button->sb_widget, event->x, event->y);
+
+    if (inside != button->sb_inside)
+        button->sb_inside = inside;
+}
+
+SButton *
+create_sbutton(GList ** wlist, GdkPixmap * parent, GdkGC * gc,
+               gint x, gint y, gint w, gint h, void (*cb) (void))
+{
+    SButton *b;
+
+    b = g_new0(SButton, 1);
+    widget_init(&b->sb_widget, parent, gc, x, y, w, h, 1);
+    b->sb_widget.button_press_cb =
+        (void (*)(GtkWidget *, GdkEventButton *, gpointer))
+        sbutton_button_press_cb;
+    b->sb_widget.button_release_cb =
+        (void (*)(GtkWidget *, GdkEventButton *, gpointer))
+        sbutton_button_release_cb;
+    b->sb_widget.motion_cb =
+        (void (*)(GtkWidget *, GdkEventMotion *, gpointer))
+        sbutton_motion_cb;
+    b->sb_push_cb = cb;
+
+    widget_list_add(wlist, WIDGET(b));
+    return b;
+}
+
+void
+free_sbutton(SButton * b)
+{
+    g_free(b);
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/audacious/widgets/sbutton.h	Wed Aug 09 02:47:22 2006 -0700
@@ -0,0 +1,43 @@
+/*  BMP - Cross-platform multimedia player
+ *  Copyright (C) 2003-2004  BMP development team.
+ *
+ *  Based on XMMS:
+ *  Copyright (C) 1998-2003  XMMS development team.
+ *
+ *  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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+
+#ifndef SBUTTON_H
+#define SBUTTON_H
+
+#include <glib.h>
+#include <gdk/gdk.h>
+
+#include "widget.h"
+
+#define SBUTTON(x)  ((SButton *)(x))
+struct _SButton {
+    Widget sb_widget;
+    gint sb_pressed, sb_inside;
+    void (*sb_push_cb) (void);
+};
+
+typedef struct _SButton SButton;
+
+SButton *create_sbutton(GList ** wlist, GdkPixmap * parent, GdkGC * gc,
+                        gint x, gint y, gint w, gint h, void (*cb) (void));
+void free_sbutton(SButton * b);
+
+#endif
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/audacious/widgets/skin.c	Wed Aug 09 02:47:22 2006 -0700
@@ -0,0 +1,1260 @@
+/*  BMP - Cross-platform multimedia player
+ *  Copyright (C) 2003-2004  BMP development team.
+ *
+ *  Based on XMMS:
+ *  Copyright (C) 1998-2003  XMMS development team.
+ *
+ *  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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+
+#ifdef HAVE_CONFIG_H
+#  include "config.h"
+#endif
+
+/* TODO: enforce default sizes! */
+
+#include <glib.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <ctype.h>
+
+#include "equalizer.h"
+#include "main.h"
+#include "ui_playlist.h"
+#include "skin.h"
+#include "skinwin.h"
+#include "util.h"
+
+#include "debug.h"
+
+#include <gdk/gdkx.h>
+#include <X11/Xlib.h>
+
+#define EXTENSION_TARGETS 7
+
+static gchar *ext_targets[EXTENSION_TARGETS] = { "bmp", "xpm", "png", "svg", 
+	"gif", "jpg", "jpeg" };
+
+struct _SkinPixmapIdMapping {
+    SkinPixmapId id;
+    const gchar *name;
+    const gchar *alt_name;
+    gint width, height;
+};
+
+struct _SkinMaskInfo {
+    gint width, height;
+    gchar *inistr;
+};
+
+typedef struct _SkinPixmapIdMapping SkinPixmapIdMapping;
+typedef struct _SkinMaskInfo SkinMaskInfo;
+
+
+Skin *bmp_active_skin = NULL;
+
+static gint skin_current_num;
+
+static SkinMaskInfo skin_mask_info[] = {
+    {275, 116, "Normal"},
+    {275, 16,  "WindowShade"},
+    {275, 116, "Equalizer"},
+    {275, 16,  "EqualizerWS"}
+};
+
+static SkinPixmapIdMapping skin_pixmap_id_map[] = {
+    {SKIN_MAIN, "main", NULL, 0, 0},
+    {SKIN_CBUTTONS, "cbuttons", NULL, 0, 0},
+    {SKIN_SHUFREP, "shufrep", NULL, 0, 0},
+    {SKIN_TEXT, "text", NULL, 0, 0},
+    {SKIN_TITLEBAR, "titlebar", NULL, 0, 0},
+    {SKIN_VOLUME, "volume", NULL, 0, 0},
+    {SKIN_BALANCE, "balance", "volume", 0, 0},
+    {SKIN_MONOSTEREO, "monoster", NULL, 0, 0},
+    {SKIN_PLAYPAUSE, "playpaus", NULL, 0, 0},
+    {SKIN_NUMBERS, "nums_ex", "numbers", 0, 0},
+    {SKIN_POSBAR, "posbar", NULL, 0, 0},
+    {SKIN_EQMAIN, "eqmain", NULL, 0, 0},
+    {SKIN_PLEDIT, "pledit", NULL, 0, 0},
+    {SKIN_EQ_EX, "eq_ex", NULL, 0, 0}
+};
+
+static guint skin_pixmap_id_map_size = G_N_ELEMENTS(skin_pixmap_id_map);
+
+static const guchar skin_default_viscolor[24][3] = {
+    {9, 34, 53},
+    {10, 18, 26},
+    {0, 54, 108},
+    {0, 58, 116},
+    {0, 62, 124},
+    {0, 66, 132},
+    {0, 70, 140},
+    {0, 74, 148},
+    {0, 78, 156},
+    {0, 82, 164},
+    {0, 86, 172},
+    {0, 92, 184},
+    {0, 98, 196},
+    {0, 104, 208},
+    {0, 110, 220},
+    {0, 116, 232},
+    {0, 122, 244},
+    {0, 128, 255},
+    {0, 128, 255},
+    {0, 104, 208},
+    {0, 80, 160},
+    {0, 56, 112},
+    {0, 32, 64},
+    {200, 200, 200}
+};
+
+static GdkBitmap *
+skin_create_transparent_mask(const gchar *,
+                             const gchar *,
+                             const gchar *,
+                             GdkWindow *,
+                             gint, gint);
+
+static void
+skin_setup_masks(Skin * skin);
+
+static void
+skin_set_default_vis_color(Skin * skin);
+
+
+void
+skin_lock(Skin * skin)
+{
+    g_mutex_lock(skin->lock);
+}
+
+void
+skin_unlock(Skin * skin)
+{
+    g_mutex_unlock(skin->lock);
+}
+
+gboolean
+bmp_active_skin_reload(void) 
+{
+    return bmp_active_skin_load(bmp_active_skin->path);	
+}
+
+gboolean
+bmp_active_skin_load(const gchar * path)
+{
+    g_return_val_if_fail(bmp_active_skin != NULL, FALSE);
+
+    memset(&bmp_active_skin->properties, 0, sizeof(SkinProperties));
+
+    if (!skin_load(bmp_active_skin, path))
+        return FALSE;
+
+    skin_setup_masks(bmp_active_skin);
+
+    if (cfg.playlist_transparent)
+    {
+        if (rootpix != NULL)
+            g_object_unref(rootpix);
+
+        rootpix = shade_pixmap(get_transparency_pixmap(), 0, 0, 0, 0, gdk_screen_width(), gdk_screen_height(),
+                               skin_get_color(bmp_active_skin, SKIN_PLEDIT_NORMALBG));
+    }
+
+    draw_main_window(TRUE);
+    draw_playlist_window(TRUE);
+    draw_equalizer_window(TRUE);
+
+    vis_set_window(mainwin_vis, mainwin->window);
+    playlistwin_update_list();
+
+    return TRUE;
+}
+
+void
+skin_pixmap_free(SkinPixmap * p)
+{
+    g_return_if_fail(p != NULL);
+    g_return_if_fail(p->pixmap != NULL);
+
+    g_object_unref(p->pixmap);
+    p->pixmap = NULL;
+}
+
+Skin *
+skin_new(void)
+{
+    Skin *skin;
+    skin = g_new0(Skin, 1);
+    skin->lock = g_mutex_new();
+    return skin;
+}
+
+void
+skin_free(Skin * skin)
+{
+    gint i;
+
+    g_return_if_fail(skin != NULL);
+
+    skin_lock(skin);
+
+    for (i = 0; i < SKIN_PIXMAP_COUNT; i++)
+        skin_pixmap_free(&skin->pixmaps[i]);
+
+    for (i = 0; i < SKIN_PIXMAP_COUNT; i++) {
+        if (skin->masks[i])
+            g_object_unref(skin->masks[i]);
+
+        skin->masks[i] = NULL;
+    }
+
+    skin_set_default_vis_color(skin);
+    skin_unlock(skin);
+}
+
+void
+skin_destroy(Skin * skin)
+{
+    g_return_if_fail(skin != NULL);
+    skin_free(skin);
+    g_mutex_free(skin->lock);
+    g_free(skin);
+}
+
+const SkinPixmapIdMapping *
+skin_pixmap_id_lookup(guint id)
+{
+    guint i;
+
+    for (i = 0; i < skin_pixmap_id_map_size; i++) {
+        if (id == skin_pixmap_id_map[i].id) {
+            return &skin_pixmap_id_map[i];
+        }
+    }
+
+    return NULL;
+}
+
+const gchar *
+skin_pixmap_id_to_name(SkinPixmapId id)
+{
+    guint i;
+
+    for (i = 0; i < skin_pixmap_id_map_size; i++) {
+        if (id == skin_pixmap_id_map[i].id)
+            return skin_pixmap_id_map[i].name;
+    }
+    return NULL;
+}
+
+static void
+skin_set_default_vis_color(Skin * skin)
+{
+    memcpy(skin->vis_color, skin_default_viscolor,
+           sizeof(skin_default_viscolor));
+}
+
+/*
+ * I have rewritten this to take an array of possible targets,
+ * once we find a matching target we now return, instead of loop
+ * recursively. This allows for us to support many possible format
+ * targets for our skinning engine than just the original winamp 
+ * formats.
+ *
+ *    -- nenolod, 16 January 2006
+ */
+gchar *
+skin_pixmap_locate(const gchar * dirname, gchar ** basenames)
+{
+    gchar *filename;
+    gint i;
+
+    for (i = 0; basenames[i]; i++)
+	if (!(filename = find_file_recursively(dirname, basenames[i]))) 
+            g_free(filename);
+        else
+            return filename;
+
+    /* can't find any targets -- sorry */
+    return NULL;
+}
+
+/* FIXME: this function is temporary. It will be removed when the skinning system
+   uses GdkPixbuf in place of GdkPixmap */
+
+static GdkPixmap *
+pixmap_new_from_file(const gchar * filename)
+{
+    GdkPixbuf *pixbuf;
+    GdkPixmap *pixmap;
+    gint width, height;
+
+    if (!(pixbuf = gdk_pixbuf_new_from_file(filename, NULL)))
+        return NULL;
+
+    width = gdk_pixbuf_get_width(pixbuf);
+    height = gdk_pixbuf_get_height(pixbuf);
+
+    if (!(pixmap = gdk_pixmap_new(mainwin->window, width, height,
+                                  gdk_rgb_get_visual()->depth))) {
+        g_object_unref(pixbuf);
+        return NULL;
+    }
+
+    gdk_pixbuf_render_to_drawable(pixbuf, pixmap, mainwin_gc, 0, 0, 0, 0,
+                                  width, height, GDK_RGB_DITHER_MAX, 0, 0);
+    g_object_unref(pixbuf);
+
+    return pixmap;
+}
+
+static gboolean
+skin_load_pixmap_id(Skin * skin, SkinPixmapId id, const gchar * path_p)
+{
+    const gchar *path;
+    gchar *filename;
+    gint width, height;
+    const SkinPixmapIdMapping *pixmap_id_mapping;
+    GdkPixmap *gpm;
+    SkinPixmap *pm = NULL;
+    gchar *basenames[EXTENSION_TARGETS * 2 + 1]; /* alternate basenames */
+    gint i, y;
+
+    g_return_val_if_fail(skin != NULL, FALSE);
+    g_return_val_if_fail(id < SKIN_PIXMAP_COUNT, FALSE);
+
+    pixmap_id_mapping = skin_pixmap_id_lookup(id);
+    g_return_val_if_fail(pixmap_id_mapping != NULL, FALSE);
+
+    memset(&basenames, 0, sizeof(basenames));
+
+    for (i = 0, y = 0; i < EXTENSION_TARGETS; i++, y++)
+    {
+        basenames[y] = g_strdup_printf("%s.%s", pixmap_id_mapping->name,
+			ext_targets[i]);
+
+        if (pixmap_id_mapping->alt_name)
+            basenames[++y] = g_strdup_printf("%s.%s", 
+			pixmap_id_mapping->alt_name, ext_targets[i]);
+    }
+
+    path = path_p ? path_p : skin->path;
+    filename = skin_pixmap_locate(path, basenames);
+
+    for (i = 0; basenames[i] != NULL; i++)
+    {
+         g_free(basenames[i]);
+         basenames[i] = NULL;
+    }
+
+    if (!(gpm = pixmap_new_from_file(filename))) {
+        g_warning("loading of %s failed", filename);
+        g_free(filename);
+        return FALSE;
+    }
+
+    g_free(filename);
+
+    gdk_window_get_size(gpm, &width, &height);
+    pm = &skin->pixmaps[id];
+    pm->pixmap = gpm;
+    pm->width = width;
+    pm->height = height;
+    pm->current_width = width;
+    pm->current_height = height;
+
+    return TRUE;
+}
+
+void
+skin_mask_create(Skin * skin,
+                 const gchar * path,
+                 gint id,
+                 GdkWindow * window)
+{
+    skin->masks[id] =
+        skin_create_transparent_mask(path, "region.txt",
+                                     skin_mask_info[id].inistr, window,
+                                     skin_mask_info[id].width,
+                                     skin_mask_info[id].height);
+}
+
+static void
+skin_setup_masks(Skin * skin)
+{
+    GdkBitmap *mask;
+
+    if (cfg.show_wm_decorations)
+        return;
+
+    if (cfg.player_visible) {
+        mask = skin_get_mask(skin, SKIN_MASK_MAIN + cfg.player_shaded);
+        gtk_widget_shape_combine_mask(mainwin, mask, 0, 0);
+    }
+
+    mask = skin_get_mask(skin, SKIN_MASK_EQ + cfg.equalizer_shaded);
+    gtk_widget_shape_combine_mask(equalizerwin, mask, 0, 0);
+}
+
+static GdkBitmap *
+create_default_mask(GdkWindow * parent, gint w, gint h)
+{
+    GdkBitmap *ret;
+    GdkGC *gc;
+    GdkColor pattern;
+
+    ret = gdk_pixmap_new(parent, w, h, 1);
+    gc = gdk_gc_new(ret);
+    pattern.pixel = 1;
+    gdk_gc_set_foreground(gc, &pattern);
+    gdk_draw_rectangle(ret, gc, TRUE, 0, 0, w, h);
+    gdk_gc_destroy(gc);
+
+    return ret;
+}
+
+static void
+skin_query_color(GdkColormap * cm, GdkColor * c)
+{
+    XColor xc = { 0,0,0,0,0,0 };
+
+    xc.pixel = c->pixel;
+    XQueryColor(GDK_COLORMAP_XDISPLAY(cm), GDK_COLORMAP_XCOLORMAP(cm), &xc);
+    c->red = xc.red;
+    c->green = xc.green;
+    c->blue = xc.blue;
+}
+
+static glong
+skin_calc_luminance(GdkColor * c)
+{
+    return (0.212671 * c->red + 0.715160 * c->green + 0.072169 * c->blue);
+}
+
+static void
+skin_get_textcolors(GdkPixmap * text, GdkColor * bgc, GdkColor * fgc)
+{
+    /*
+     * Try to extract reasonable background and foreground colors
+     * from the font pixmap
+     */
+
+    GdkImage *gi;
+    GdkColormap *cm;
+    gint i;
+
+    g_return_if_fail(text != NULL);
+
+    /* Get the first line of text */
+    gi = gdk_drawable_get_image(text, 0, 0, 152, 6);
+    cm = gdk_window_get_colormap(playlistwin->window);
+    g_return_if_fail(GDK_IS_WINDOW(playlistwin->window));
+
+    for (i = 0; i < 6; i++) {
+        GdkColor c;
+        gint x;
+        glong d, max_d;
+
+        /* Get a pixel from the middle of the space character */
+        bgc[i].pixel = gdk_image_get_pixel(gi, 151, i);
+        skin_query_color(cm, &bgc[i]);
+
+        max_d = 0;
+        for (x = 1; x < 150; x++) {
+            c.pixel = gdk_image_get_pixel(gi, x, i);
+            skin_query_color(cm, &c);
+
+            d = labs(skin_calc_luminance(&c) - skin_calc_luminance(&bgc[i]));
+            if (d > max_d) {
+                memcpy(&fgc[i], &c, sizeof(GdkColor));
+                max_d = d;
+            }
+        }
+    }
+    gdk_image_destroy(gi);
+}
+
+gboolean
+init_skins(const gchar * path)
+{
+    bmp_active_skin = skin_new();
+
+    if (!bmp_active_skin_load(path)) {
+        /* FIXME: Oddly, g_message() causes a crash if path is NULL on
+         * Solaris (see bug #165) */
+        if (path) 
+            g_message("Unable to load skin (%s), trying default...", path);
+
+        /* can't load configured skin, retry with default */
+        if (!bmp_active_skin_load(BMP_DEFAULT_SKIN_PATH)) {
+            g_message("Unable to load default skin (%s)! Giving up.",
+                      BMP_DEFAULT_SKIN_PATH);
+            return FALSE;
+        }
+    }
+
+    if (cfg.random_skin_on_play)
+        skinlist_update();
+
+    return TRUE;
+}
+
+/*
+ * Opens and parses a skin's hints file.
+ * Hints files are somewhat like "scripts" in Winamp3/5.
+ * We'll probably add scripts to it next.
+ */
+void
+skin_parse_hints(Skin * skin, gchar *path_p)
+{
+    gchar *filename, *tmp;
+
+    path_p = path_p ? path_p : skin->path;
+
+    filename = find_file_recursively(path_p, "skin.hints");
+
+    if (filename == NULL)
+        return;
+
+#if 0
+    skin->description = read_ini_string(filename, "skin", "skinDescription");
+#endif
+
+    tmp = read_ini_string(filename, "skin", "mainwinOthertext");
+
+    if (tmp != NULL)
+        skin->properties.mainwin_othertext = atoi(tmp);
+}
+
+static guint
+hex_chars_to_int(gchar hi, gchar lo)
+{
+    /*
+     * Converts a value in the range 0x00-0xFF
+     * to a integer in the range 0-65535
+     */
+    gchar str[3];
+
+    str[0] = hi;
+    str[1] = lo;
+    str[2] = 0;
+
+    return (CLAMP(strtol(str, NULL, 16), 0, 0xFF) << 8);
+}
+
+GdkColor *
+skin_load_color(const gchar * path, const gchar * file,
+                const gchar * section, const gchar * key,
+                gchar * default_hex)
+{
+    gchar *filename, *value;
+    GdkColor *color = NULL;
+
+    filename = find_file_recursively(path, file);
+    if (filename || default_hex) {
+        if (filename) {
+            value = read_ini_string(filename, section, key);
+            if (value == NULL) {
+                value = g_strdup(default_hex);
+            }
+        } else {
+            value = g_strdup(default_hex);
+        }
+        if (value) {
+            gchar *ptr = value;
+            gint len;
+
+            color = g_new0(GdkColor, 1);
+            g_strstrip(value);
+
+            if (value[0] == '#')
+                ptr++;
+            len = strlen(ptr);
+            /*
+             * The handling of incomplete values is done this way
+             * to maximize winamp compatibility
+             */
+            if (len >= 6) {
+                color->red = hex_chars_to_int(*ptr, *(ptr + 1));
+                ptr += 2;
+            }
+            if (len >= 4) {
+                color->green = hex_chars_to_int(*ptr, *(ptr + 1));
+                ptr += 2;
+            }
+            if (len >= 2)
+                color->blue = hex_chars_to_int(*ptr, *(ptr + 1));
+
+            gdk_color_alloc(gdk_window_get_colormap(playlistwin->window),
+                            color);
+            g_free(value);
+        }
+        if (filename)
+            g_free(filename);
+    }
+    return color;
+}
+
+
+
+GdkBitmap *
+skin_create_transparent_mask(const gchar * path,
+                             const gchar * file,
+                             const gchar * section,
+                             GdkWindow * window,
+                             gint width,
+                             gint height)
+{
+    GdkBitmap *mask = NULL;
+    GdkGC *gc = NULL;
+    GdkColor pattern;
+    GdkPoint *gpoints;
+
+    gchar *filename = NULL;
+    gboolean created_mask = FALSE;
+    GArray *num, *point;
+    guint i, j;
+    gint k;
+
+    if (path)
+        filename = find_file_recursively(path, file);
+
+    /* filename will be null if path wasn't set */
+    if (!filename) {
+        return create_default_mask(window, width, height);
+    }
+
+    if ((num = read_ini_array(filename, section, "NumPoints")) == NULL) {
+        g_free(filename);
+        return NULL;
+    }
+
+    if ((point = read_ini_array(filename, section, "PointList")) == NULL) {
+        g_array_free(num, TRUE);
+        g_free(filename);
+        return NULL;
+    }
+
+    mask = gdk_pixmap_new(window, width, height, 1);
+    gc = gdk_gc_new(mask);
+
+    pattern.pixel = 0;
+    gdk_gc_set_foreground(gc, &pattern);
+    gdk_draw_rectangle(mask, gc, TRUE, 0, 0, width, height);
+    pattern.pixel = 1;
+    gdk_gc_set_foreground(gc, &pattern);
+
+    j = 0;
+    for (i = 0; i < num->len; i++) {
+        if ((int)(point->len - j) >= (g_array_index(num, gint, i) * 2)) {
+            created_mask = TRUE;
+            gpoints = g_new(GdkPoint, g_array_index(num, gint, i));
+            for (k = 0; k < g_array_index(num, gint, i); k++) {
+                gpoints[k].x = g_array_index(point, gint, j + k * 2);
+                gpoints[k].y = g_array_index(point, gint, j + k * 2 + 1);
+            }
+            j += k * 2;
+            gdk_draw_polygon(mask, gc, TRUE, gpoints,
+                             g_array_index(num, gint, i));
+            g_free(gpoints);
+        }
+    }
+    g_array_free(num, TRUE);
+    g_array_free(point, TRUE);
+    g_free(filename);
+
+    if (!created_mask)
+        gdk_draw_rectangle(mask, gc, TRUE, 0, 0, width, height);
+
+    gdk_gc_destroy(gc);
+
+    return mask;
+}
+
+void
+skin_load_viscolor(Skin * skin, const gchar * path, const gchar * basename)
+{
+    FILE *file;
+    gint i, c;
+    gchar line[256], *filename;
+    GArray *a;
+
+    g_return_if_fail(skin != NULL);
+    g_return_if_fail(path != NULL);
+    g_return_if_fail(basename != NULL);
+
+    skin_set_default_vis_color(skin);
+
+    filename = find_file_recursively(path, basename);
+    if (!filename)
+        return;
+
+    if (!(file = fopen(filename, "r"))) {
+        g_free(filename);
+        return;
+    }
+
+    g_free(filename);
+
+    for (i = 0; i < 24; i++) {
+        if (fgets(line, 255, file)) {
+            a = string_to_garray(line);
+            if (a->len > 2) {
+                for (c = 0; c < 3; c++)
+                    skin->vis_color[i][c] = g_array_index(a, gint, c);
+            }
+            g_array_free(a, TRUE);
+        }
+        else
+            break;
+    }
+
+    fclose(file);
+}
+
+#if 0
+static void
+skin_numbers_generate_dash(Skin * skin)
+{
+    GdkGC *gc;
+    GdkPixmap *pixmap;
+    SkinPixmap *numbers;
+
+    g_return_if_fail(skin != NULL);
+
+    numbers = &skin->pixmaps[SKIN_NUMBERS];
+    if (!numbers->pixmap || numbers->current_width < 99)
+        return;
+
+    gc = gdk_gc_new(numbers->pixmap);
+    pixmap = gdk_pixmap_new(mainwin->window, 108,
+                            numbers->current_height,
+                            -1);
+
+    skin_draw_pixmap(skin, pixmap, gc, SKIN_NUMBERS, 0, 0, 0, 0, 99, 13);
+    skin_draw_pixmap(skin, pixmap, gc, SKIN_NUMBERS, 90, 0, 99, 0, 9, 13);
+    skin_draw_pixmap(skin, pixmap, gc, SKIN_NUMBERS, 20, 6, 101, 6, 5, 1);
+
+    g_object_unref(numbers->pixmap);
+    g_object_unref(gc);
+
+    numbers->pixmap = pixmap;
+    numbers->current_width = 108;
+}
+#endif
+
+static void
+skin_load_cursor(Skin * skin, const gchar * dirname)
+{
+    const gchar * basename = "normal.cur";
+    gchar * filename = NULL;
+    GdkPixbuf * cursor_pixbuf = NULL;
+    GdkPixbufAnimation * cursor_animated = NULL;
+    GdkCursor * cursor_gdk = NULL;
+    GError * error = NULL;
+ 
+    filename = find_file_recursively(dirname, basename);
+
+    if (filename && cfg.custom_cursors)	{
+    	cursor_animated = gdk_pixbuf_animation_new_from_file(filename, &error);
+        cursor_pixbuf = gdk_pixbuf_animation_get_static_image(cursor_animated);
+        cursor_gdk = gdk_cursor_new_from_pixbuf(gdk_display_get_default(),
+                                                cursor_pixbuf, 0, 0);
+    } else {
+        cursor_gdk = gdk_cursor_new(GDK_LEFT_PTR);
+    }
+
+    gdk_window_set_cursor(mainwin->window, cursor_gdk);
+    gdk_window_set_cursor(playlistwin->window, cursor_gdk);
+    gdk_window_set_cursor(equalizerwin->window, cursor_gdk);
+    gdk_cursor_unref(cursor_gdk);
+}
+
+static void
+skin_load_pixmaps(Skin * skin, const gchar * path)
+{
+    GdkPixmap *text_pm;
+    guint i;
+
+    for (i = 0; i < SKIN_PIXMAP_COUNT; i++)
+        skin_load_pixmap_id(skin, i, path);
+
+    text_pm = skin->pixmaps[SKIN_TEXT].pixmap;
+
+    if (text_pm)
+        skin_get_textcolors(text_pm, skin->textbg, skin->textfg);
+
+#if 0
+    if (skin->pixmaps[SKIN_NUMBERS].pixmap)
+        skin_numbers_generate_dash(skin);
+#endif
+
+    skin->colors[SKIN_PLEDIT_NORMAL] =
+        skin_load_color(path, "pledit.txt", "text", "normal", "#2499ff");
+    skin->colors[SKIN_PLEDIT_CURRENT] =
+        skin_load_color(path, "pledit.txt", "text", "current", "#ffeeff");
+    skin->colors[SKIN_PLEDIT_NORMALBG] =
+        skin_load_color(path, "pledit.txt", "text", "normalbg", "#0a120a");
+    skin->colors[SKIN_PLEDIT_SELECTEDBG] =
+        skin_load_color(path, "pledit.txt", "text", "selectedbg", "#0a124a");
+
+    skin_mask_create(skin, path, SKIN_MASK_MAIN, mainwin->window);
+    skin_mask_create(skin, path, SKIN_MASK_MAIN_SHADE, mainwin->window);
+
+    skin_mask_create(skin, path, SKIN_MASK_EQ, equalizerwin->window);
+    skin_mask_create(skin, path, SKIN_MASK_EQ_SHADE, equalizerwin->window);
+
+    skin_load_viscolor(skin, path, "viscolor.txt");
+}
+
+static gboolean
+skin_load_nolock(Skin * skin, const gchar * path, gboolean force)
+{
+    gchar *cpath;
+
+    g_return_val_if_fail(skin != NULL, FALSE);
+    g_return_val_if_fail(path != NULL, FALSE);
+    REQUIRE_LOCK(skin->lock);
+
+    if (!g_file_test(path, G_FILE_TEST_IS_REGULAR | G_FILE_TEST_IS_DIR))
+	return FALSE;
+   
+    if (!force) {
+        if (skin->path)
+            if (!strcmp(skin->path, path))
+                return FALSE;
+    }
+      
+    skin_current_num++;
+
+    skin->path = g_strdup(path);
+
+    if (!file_is_archive(path)) {
+        skin_load_pixmaps(skin, path);
+        skin_load_cursor(skin, path);
+
+        /* Parse the hints for this skin. */
+        skin_parse_hints(skin, NULL);
+
+        return TRUE;
+    }
+
+    if (!(cpath = archive_decompress(path))) {
+        g_message("Unable to extract skin archive (%s)", path);
+        return FALSE;
+    }
+
+    skin_load_pixmaps(skin, cpath);
+    skin_load_cursor(skin, cpath);
+
+    /* Parse the hints for this skin. */
+    skin_parse_hints(skin, cpath);
+
+    del_directory(cpath);
+    g_free(cpath);
+
+    return TRUE;
+}
+
+void
+skin_install_skin(const gchar * path)
+{
+    gchar *command;
+
+    g_return_if_fail(path != NULL);
+
+    command = g_strdup_printf("cp %s %s", path, bmp_paths[BMP_PATH_USER_SKIN_DIR]);
+    if (system(command)) {
+        g_message("Unable to install skin (%s) into user directory (%s)",
+                  path, bmp_paths[BMP_PATH_USER_SKIN_DIR]);
+    }
+    g_free(command);
+}
+
+
+gboolean
+skin_load(Skin * skin, const gchar * path)
+{
+    gboolean error;
+
+    g_return_val_if_fail(skin != NULL, FALSE);
+
+    if (!path)
+        return FALSE;
+
+    skin_lock(skin);
+    error = skin_load_nolock(skin, path, FALSE);
+    skin_unlock(skin);
+    
+    return error;
+}
+
+gboolean
+skin_reload_forced(void) 
+{
+   gboolean error;
+
+   skin_lock(bmp_active_skin);
+   error = skin_load_nolock(bmp_active_skin, bmp_active_skin->path, TRUE);
+   skin_unlock(bmp_active_skin);
+
+   return error;
+}
+
+void
+skin_reload(Skin * skin)
+{
+    g_return_if_fail(skin != NULL);
+    skin_load_nolock(skin, skin->path, TRUE);
+}
+
+
+static SkinPixmap *
+skin_get_pixmap(Skin * skin, SkinPixmapId map_id)
+{
+    g_return_val_if_fail(skin != NULL, NULL);
+    g_return_val_if_fail(map_id < SKIN_PIXMAP_COUNT, NULL);
+
+    return &skin->pixmaps[map_id];
+}
+
+GdkBitmap *
+skin_get_mask(Skin * skin, SkinMaskId mi)
+{
+    g_return_val_if_fail(skin != NULL, NULL);
+    g_return_val_if_fail(mi < SKIN_PIXMAP_COUNT, NULL);
+
+    return skin->masks[mi];
+}
+
+GdkColor *
+skin_get_color(Skin * skin, SkinColorId color_id)
+{
+    GdkColor *ret = NULL;
+
+    g_return_val_if_fail(skin != NULL, NULL);
+
+    switch (color_id) {
+    case SKIN_TEXTBG:
+        if (skin->pixmaps[SKIN_TEXT].pixmap)
+            ret = skin->textbg;
+        else
+            ret = skin->def_textbg;
+        break;
+    case SKIN_TEXTFG:
+        if (skin->pixmaps[SKIN_TEXT].pixmap)
+            ret = skin->textfg;
+        else
+            ret = skin->def_textfg;
+        break;
+    default:
+        if (color_id < SKIN_COLOR_COUNT)
+            ret = skin->colors[color_id];
+        break;
+    }
+    return ret;
+}
+
+void
+skin_get_viscolor(Skin * skin, guchar vis_color[24][3])
+{
+    gint i;
+
+    g_return_if_fail(skin != NULL);
+
+    for (i = 0; i < 24; i++) {
+        vis_color[i][0] = skin->vis_color[i][0];
+        vis_color[i][1] = skin->vis_color[i][1];
+        vis_color[i][2] = skin->vis_color[i][2];
+    }
+}
+
+gint
+skin_get_id(void)
+{
+    return skin_current_num;
+}
+
+void
+skin_draw_pixmap(Skin * skin, GdkDrawable * drawable, GdkGC * gc,
+                 SkinPixmapId pixmap_id,
+                 gint xsrc, gint ysrc, gint xdest, gint ydest,
+                 gint width, gint height)
+{
+    SkinPixmap *pixmap;
+
+    g_return_if_fail(skin != NULL);
+
+    pixmap = skin_get_pixmap(skin, pixmap_id);
+    g_return_if_fail(pixmap != NULL);
+    g_return_if_fail(pixmap->pixmap != NULL);
+
+    if (xsrc > pixmap->width || ysrc > pixmap->height)
+        return;
+
+    width = MIN(width, pixmap->width - xsrc);
+    height = MIN(height, pixmap->height - ysrc);
+    gdk_draw_pixmap(drawable, gc, pixmap->pixmap, xsrc, ysrc,
+                    xdest, ydest, width, height);
+}
+
+void
+skin_get_eq_spline_colors(Skin * skin, guint32 colors[19])
+{
+    gint i;
+    GdkPixmap *pixmap;
+    GdkImage *img;
+    SkinPixmap *eqmainpm;
+
+    g_return_if_fail(skin != NULL);
+
+    eqmainpm = &skin->pixmaps[SKIN_EQMAIN];
+    if (eqmainpm->pixmap &&
+        eqmainpm->current_width >= 116 && eqmainpm->current_height >= 313)
+        pixmap = eqmainpm->pixmap;
+    else
+        return;
+
+    if (!GDK_IS_DRAWABLE(pixmap))
+        return;
+
+    if (!(img = gdk_drawable_get_image(pixmap, 115, 294, 1, 19)))
+        return;
+
+    for (i = 0; i < 19; i++)
+        colors[i] = gdk_image_get_pixel(img, 0, i);
+
+    gdk_image_destroy(img);
+}
+
+
+static void
+skin_draw_playlistwin_frame_top(Skin * skin,
+                                GdkDrawable * drawable,
+                                GdkGC * gc,
+                                gint width, gint height, gboolean focus)
+{
+    /* The title bar skin consists of 2 sets of 4 images, 1 set
+     * for focused state and the other for unfocused. The 4 images
+     * are: 
+     *
+     * a. right corner (25,20)
+     * b. left corner  (25,20)
+     * c. tiler        (25,20)
+     * d. title        (100,20)
+     * 
+     * min allowed width = 100+25+25 = 150
+     */
+
+    gint i, y, c;
+
+    /* get y offset of the pixmap set to use */
+    if (focus)
+        y = 0;
+    else
+        y = 21;
+
+    /* left corner */
+    skin_draw_pixmap(skin, drawable, gc, SKIN_PLEDIT, 0, y, 0, 0, 25, 20);
+
+    /* titlebar title */
+    skin_draw_pixmap(skin, drawable, gc, SKIN_PLEDIT, 26, y,
+                     (width - 100) / 2, 0, 100, 20);
+
+    /* titlebar right corner  */
+    skin_draw_pixmap(skin, drawable, gc, SKIN_PLEDIT, 153, y,
+                     width - 25, 0, 25, 20);
+
+    /* tile draw the remaining frame */
+
+    /* compute tile count */
+    c = (width - (100 + 25 + 25)) / 25;
+
+    for (i = 0; i < c / 2; i++) {
+        /* left of title */
+        skin_draw_pixmap(skin, drawable, gc, SKIN_PLEDIT, 127, y,
+                         25 + i * 25, 0, 25, 20);
+
+        /* right of title */
+        skin_draw_pixmap(skin, drawable, gc, SKIN_PLEDIT, 127, y,
+                         (width + 100) / 2 + i * 25, 0, 25, 20);
+    }
+
+    if (c & 1) {
+        /* Odd tile count, so one remaining to draw. Here we split
+         * it into two and draw half on either side of the title */
+        skin_draw_pixmap(skin, drawable, gc, SKIN_PLEDIT, 127, y,
+                         ((c / 2) * 25) + 25, 0, 12, 20);
+        skin_draw_pixmap(skin, drawable, gc, SKIN_PLEDIT, 127, y,
+                         (width / 2) + ((c / 2) * 25) + 50, 0, 13, 20);
+    }
+}
+
+static void
+skin_draw_playlistwin_frame_bottom(Skin * skin,
+                                   GdkDrawable * drawable,
+                                   GdkGC * gc,
+                                   gint width, gint height, gboolean focus)
+{
+    /* The bottom frame skin consists of 1 set of 4 images. The 4
+     * images are:
+     *
+     * a. left corner with menu buttons (125,38)
+     * b. visualization window (75,38)
+     * c. right corner with play buttons (150,38)
+     * d. frame tile (25,38)
+     * 
+     * (min allowed width = 125+150+25=300
+     */
+
+    gint i, c;
+
+    /* bottom left corner (menu buttons) */
+    skin_draw_pixmap(skin, drawable, gc, SKIN_PLEDIT, 0, 72,
+                     0, height - 38, 125, 38);
+
+    c = (width - 275) / 25;
+
+    /* draw visualization window, if width allows */
+    if (c >= 3) {
+        c -= 3;
+        skin_draw_pixmap(skin, drawable, gc, SKIN_PLEDIT, 205, 0,
+                         width - (150 + 75), height - 38, 75, 38);
+    }
+
+    /* Bottom right corner (playbuttons etc) */
+    skin_draw_pixmap(skin, drawable, gc, SKIN_PLEDIT,
+                     126, 72, width - 150, height - 38, 150, 38);
+
+    /* Tile draw the remaining undrawn portions */
+    for (i = 0; i < c; i++)
+        skin_draw_pixmap(skin, drawable, gc, SKIN_PLEDIT, 179, 0,
+                         125 + i * 25, height - 38, 25, 38);
+}
+
+static void
+skin_draw_playlistwin_frame_sides(Skin * skin,
+                                  GdkDrawable * drawable,
+                                  GdkGC * gc,
+                                  gint width, gint height, gboolean focus)
+{
+    /* The side frames consist of 2 tile images. 1 for the left, 1 for
+     * the right. 
+     * a. left  (12,29)
+     * b. right (19,29)
+     */
+
+    gint i;
+
+    /* frame sides */
+    for (i = 0; i < (height - (20 + 38)) / 29; i++) {
+        /* left */
+        skin_draw_pixmap(skin, drawable, gc, SKIN_PLEDIT, 0, 42,
+                         0, 20 + i * 29, 12, 29);
+
+        /* right */
+        skin_draw_pixmap(skin, drawable, gc, SKIN_PLEDIT, 32, 42,
+                         width - 19, 20 + i * 29, 19, 29);
+    }
+}
+
+
+void
+skin_draw_playlistwin_frame(Skin * skin,
+                            GdkDrawable * drawable, GdkGC * gc,
+                            gint width, gint height, gboolean focus)
+{
+    skin_draw_playlistwin_frame_top(skin, drawable, gc, width, height, focus);
+    skin_draw_playlistwin_frame_bottom(skin, drawable, gc, width, height,
+                                       focus);
+    skin_draw_playlistwin_frame_sides(skin, drawable, gc, width, height,
+                                      focus);
+}
+
+
+void
+skin_draw_playlistwin_shaded(Skin * skin,
+                             GdkDrawable * drawable, GdkGC * gc,
+                             gint width, gboolean focus)
+{
+    /* The shade mode titlebar skin consists of 4 images:
+     * a) left corner               offset (72,42) size (25,14)
+     * b) right corner, focused     offset (99,57) size (50,14)
+     * c) right corner, unfocused   offset (99,42) size (50,14)
+     * d) bar tile                  offset (72,57) size (25,14)
+     */
+
+    gint i;
+
+    /* left corner */
+    skin_draw_pixmap(skin, drawable, gc, SKIN_PLEDIT, 72, 42, 0, 0, 25, 14);
+
+    /* bar tile */
+    for (i = 0; i < (width - 75) / 25; i++)
+        skin_draw_pixmap(skin, drawable, gc, SKIN_PLEDIT, 72, 57,
+                         (i * 25) + 25, 0, 25, 14);
+
+    /* right corner */
+    skin_draw_pixmap(skin, drawable, gc, SKIN_PLEDIT, 99, focus ? 57 : 42,
+                     width - 50, 0, 50, 14);
+}
+
+
+void
+skin_draw_mainwin_titlebar(Skin * skin,
+                           GdkDrawable * drawable, GdkGC * gc,
+                           gboolean shaded, gboolean focus)
+{
+    /* The titlebar skin consists of 2 sets of 2 images, one for for
+     * shaded and the other for unshaded mode, giving a total of 4.
+     * The images are exactly 275x14 pixels, aligned and arranged
+     * vertically on each other in the pixmap in the following order:
+     * 
+     * a) unshaded, focused      offset (27, 0)
+     * b) unshaded, unfocused    offset (27, 15)
+     * c) shaded, focused        offset (27, 29)
+     * d) shaded, unfocused      offset (27, 42)
+     */
+
+    gint y_offset;
+
+    if (shaded) {
+        if (focus)
+            y_offset = 29;
+        else
+            y_offset = 42;
+    }
+    else {
+        if (focus)
+            y_offset = 0;
+        else
+            y_offset = 15;
+    }
+
+    skin_draw_pixmap(skin, drawable, gc, SKIN_TITLEBAR, 27, y_offset,
+                     0, 0, MAINWIN_WIDTH, MAINWIN_TITLEBAR_HEIGHT);
+}
+
+#if 0
+void
+skin_draw_mainwin(Skin * skin,
+                  GdkDrawable * drawable, GdkGC gc,
+                  gboolean doublesize, gboolean shaded, gboolean focus)
+{
+
+}
+#endif
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/audacious/widgets/skin.h	Wed Aug 09 02:47:22 2006 -0700
@@ -0,0 +1,145 @@
+/*  BMP - Cross-platform multimedia player
+ *  Copyright (C) 2003-2004  BMP development team.
+ *
+ *  Based on XMMS:
+ *  Copyright (C) 1998-2003  XMMS development team.
+ *
+ *  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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+
+#ifndef SKIN_H
+#define SKIN_H
+
+
+#include <glib.h>
+#include <gdk/gdk.h>
+
+
+#define BMP_DEFAULT_SKIN_PATH \
+  DATA_DIR G_DIR_SEPARATOR_S "Skins" G_DIR_SEPARATOR_S "Default"
+
+
+typedef enum {
+    SKIN_MAIN = 0,
+    SKIN_CBUTTONS,
+    SKIN_TITLEBAR,
+    SKIN_SHUFREP,
+    SKIN_TEXT,
+    SKIN_VOLUME,
+    SKIN_BALANCE,
+    SKIN_MONOSTEREO,
+    SKIN_PLAYPAUSE,
+    SKIN_NUMBERS,
+    SKIN_POSBAR,
+    SKIN_PLEDIT,
+    SKIN_EQMAIN,
+    SKIN_EQ_EX,
+    SKIN_PIXMAP_COUNT
+} SkinPixmapId;
+
+typedef enum {
+    SKIN_MASK_MAIN = 0,
+    SKIN_MASK_MAIN_SHADE,
+    SKIN_MASK_EQ,
+    SKIN_MASK_EQ_SHADE,
+    SKIN_MASK_COUNT
+} SkinMaskId;
+
+typedef enum {
+    SKIN_PLEDIT_NORMAL = 0,
+    SKIN_PLEDIT_CURRENT,
+    SKIN_PLEDIT_NORMALBG,
+    SKIN_PLEDIT_SELECTEDBG,
+    SKIN_TEXTBG,
+    SKIN_TEXTFG,
+    SKIN_COLOR_COUNT
+} SkinColorId;
+
+typedef struct _SkinProperties {
+	gboolean mainwin_othertext;
+} SkinProperties;
+
+#define SKIN_PIXMAP(x)  ((SkinPixmap *)(x))
+typedef struct _SkinPixmap {
+    GdkPixmap *pixmap;
+    /* GdkPixmap *def_pixmap; */
+
+    /* The real size of the pixmap */
+    gint width, height;
+
+    /* The size of the pixmap from the current skin,
+       which might be smaller */
+    gint current_width, current_height;
+} SkinPixmap;
+
+
+#define SKIN(x)  ((Skin *)(x))
+typedef struct _Skin {
+    GMutex *lock;
+    gchar *path;
+    gchar *def_path;
+    SkinPixmap pixmaps[SKIN_PIXMAP_COUNT];
+    GdkColor textbg[6], def_textbg[6];
+    GdkColor textfg[6], def_textfg[6];
+    GdkColor *colors[SKIN_COLOR_COUNT];
+    guchar vis_color[24][3];
+    GdkBitmap *masks[SKIN_MASK_COUNT];
+    SkinProperties properties;
+} Skin;
+
+extern Skin *bmp_active_skin;
+
+gboolean init_skins(const gchar * path);
+void cleanup_skins(void);
+
+gboolean bmp_active_skin_load(const gchar * path);
+gboolean bmp_active_skin_reload(void);
+
+Skin *skin_new(void);
+gboolean skin_load(Skin * skin, const gchar * path);
+void skin_reload(Skin * skin);
+void skin_free(Skin * skin);
+
+GdkBitmap *skin_get_mask(Skin * skin, SkinMaskId mi);
+GdkColor *skin_get_color(Skin * skin, SkinColorId color_id);
+
+void skin_get_viscolor(Skin * skin, guchar vis_color[24][3]);
+gint skin_get_id(void);
+void skin_draw_pixmap(Skin * skin, GdkDrawable * drawable, GdkGC * gc,
+                      SkinPixmapId pixmap_id,
+                      gint xsrc, gint ysrc, gint xdest, gint ydest,
+                      gint width, gint height);
+void skin_get_eq_spline_colors(Skin * skin, guint32 colors[19]);
+void skin_install_skin(const gchar * path);
+
+void skin_draw_playlistwin_shaded(Skin * skin,
+                                  GdkDrawable * drawable, GdkGC * gc,
+                                  gint width, gboolean focus);
+void skin_draw_playlistwin_frame(Skin * skin,
+                                 GdkDrawable * drawable, GdkGC * gc,
+                                 gint width, gint height, gboolean focus);
+
+void skin_draw_mainwin_titlebar(Skin * skin,
+                                GdkDrawable * drawable, GdkGC * gc,
+                                gboolean shaded, gboolean focus);
+
+
+void skin_parse_hints(Skin * skin, gchar *path_p);
+
+
+gboolean
+skin_reload_forced(void);
+
+#endif
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/audacious/widgets/svis.c	Wed Aug 09 02:47:22 2006 -0700
@@ -0,0 +1,204 @@
+/*  BMP - Cross-platform multimedia player
+ *  Copyright (C) 2003-2004  BMP development team.
+ *
+ *  Based on XMMS:
+ *  Copyright (C) 1998-2003  XMMS development team.
+ *
+ *  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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+
+#include "svis.h"
+
+#include <glib.h>
+#include <gdk/gdk.h>
+#include <string.h>
+
+#include "main.h"
+#include "mainwin.h"
+#include "plugin.h"
+#include "widget.h"
+#include "vis.h"
+
+static gint svis_redraw_delays[] = { 1, 2, 4, 8 };
+
+/* FIXME: Are the svis_scope_colors correct? */
+static guint8 svis_scope_colors[] = { 20, 19, 18, 19, 20 };
+static guint8 svis_vu_normal_colors[] = { 17, 17, 17, 12, 12, 12, 2, 2 };
+
+#define DRAW_DS_PIXEL(ptr,value) \
+	*(ptr) = (value); \
+	*((ptr) + 1) = (value); \
+	*((ptr) + 76) = (value); \
+	*((ptr) + 77) = (value);
+
+#define SVIS_HEIGHT 5
+#define SVIS_WIDTH 38
+
+void
+svis_timeout_func(SVis * svis, guchar * data)
+{
+    static GTimer *timer = NULL;
+    gulong micros = 9999999;
+    gboolean falloff = FALSE;
+    gint i;
+
+    if (!timer) {
+        timer = g_timer_new();
+        g_timer_start(timer);
+    }
+    else {
+        g_timer_elapsed(timer, &micros);
+        if (micros > 14000)
+            g_timer_reset(timer);
+
+    }
+
+    if (cfg.vis_type == INPUT_VIS_ANALYZER) {
+        if (micros > 14000)
+            falloff = TRUE;
+
+        for (i = 0; i < 2; i++) {
+            if (falloff || data) {
+                if (data && data[i] > svis->vs_data[i])
+                    svis->vs_data[i] = data[i];
+                else if (falloff) {
+                    if (svis->vs_data[i] >= 2)
+                        svis->vs_data[i] -= 2;
+                    else
+                        svis->vs_data[i] = 0;
+                }
+            }
+
+        }
+    }
+    else if (data) {
+        for (i = 0; i < 75; i++)
+            svis->vs_data[i] = data[i];
+    }
+
+    if (micros > 14000) {
+        if (!svis->vs_refresh_delay) {
+            svis_draw((Widget *) svis);
+            svis->vs_refresh_delay = svis_redraw_delays[cfg.vis_refresh];
+
+        }
+        svis->vs_refresh_delay--;
+    }
+}
+
+void
+svis_draw(Widget * w)
+{
+    SVis *svis = (SVis *) w;
+    gint x, y, h;
+    guchar svis_color[24][3];
+    guchar rgb_data[SVIS_WIDTH * 2 * SVIS_HEIGHT * 2], *ptr, c;
+    guint32 colors[24];
+    GdkRgbCmap *cmap;
+
+    GDK_THREADS_ENTER();
+
+    skin_get_viscolor(bmp_active_skin, svis_color);
+    for (y = 0; y < 24; y++) {
+        colors[y] =
+            svis_color[y][0] << 16 | svis_color[y][1] << 8 | svis_color[y][2];
+    }
+    cmap = gdk_rgb_cmap_new(colors, 24);
+
+    memset(rgb_data, 0, SVIS_WIDTH * SVIS_HEIGHT);
+    if (cfg.vis_type == VIS_ANALYZER) {
+        switch (cfg.vu_mode) {
+        case VU_NORMAL:
+            for (y = 0; y < 2; y++) {
+                ptr = rgb_data + ((y * 3) * 38);
+                h = (svis->vs_data[y] * 7) / 37;
+                for (x = 0; x < h; x++, ptr += 5) {
+                    c = svis_vu_normal_colors[x];
+                    *(ptr) = c;
+                    *(ptr + 1) = c;
+                    *(ptr + 2) = c;
+                    *(ptr + 38) = c;
+                    *(ptr + 39) = c;
+                    *(ptr + 40) = c;
+                }
+            }
+            break;
+        case VU_SMOOTH:
+            for (y = 0; y < 2; y++) {
+                ptr = rgb_data + ((y * 3) * SVIS_WIDTH);
+                for (x = 0; x < svis->vs_data[y]; x++, ptr++) {
+                    c = 17 - ((x * 15) / 37);
+                    *(ptr) = c;
+                    *(ptr + 38) = c;
+                }
+            }
+            break;
+        }
+    }
+    else if (cfg.vis_type == VIS_SCOPE) {
+        for (x = 0; x < 38; x++) {
+            h = svis->vs_data[x << 1] / 3;
+            ptr = rgb_data + ((4 - h) * 38) + x;
+            *ptr = svis_scope_colors[h];
+        }
+    }
+
+    gdk_draw_indexed_image(mainwin->window, mainwin_gc,
+                           svis->vs_widget.x, svis->vs_widget.y,
+                           svis->vs_widget.width,
+                           svis->vs_widget.height,
+                           GDK_RGB_DITHER_NORMAL, (guchar *) rgb_data,
+                           38, cmap);
+
+    gdk_rgb_cmap_free(cmap);
+    GDK_THREADS_LEAVE();
+}
+
+void
+svis_clear_data(SVis * svis)
+{
+    gint i;
+
+    if (!svis)
+        return;
+
+    for (i = 0; i < 75; i++) {
+        svis->vs_data[i] = (cfg.vis_type == VIS_SCOPE) ? 6 : 0;
+    }
+}
+
+void
+svis_clear(SVis * svis)
+{
+    gdk_window_clear_area(mainwin->window, svis->vs_widget.x,
+                          svis->vs_widget.y, svis->vs_widget.width,
+                          svis->vs_widget.height);
+}
+
+SVis *
+create_svis(GList ** wlist,
+            GdkPixmap * parent, 
+            GdkGC * gc,
+            gint x, gint y)
+{
+    SVis *svis;
+
+    svis = g_new0(SVis, 1);
+    widget_init(&svis->vs_widget, parent, gc, x, y, SVIS_WIDTH, SVIS_HEIGHT,
+                1);
+
+    widget_list_add(wlist, WIDGET(svis));
+    return svis;
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/audacious/widgets/svis.h	Wed Aug 09 02:47:22 2006 -0700
@@ -0,0 +1,47 @@
+/*  BMP - Cross-platform multimedia player
+ *  Copyright (C) 2003-2004  BMP development team.
+ *
+ *  Based on XMMS:
+ *  Copyright (C) 1998-2003  XMMS development team.
+ *
+ *  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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+#ifndef SVIS_H
+#define SVIS_H
+
+#include <glib.h>
+#include <gdk/gdk.h>
+
+#include "svis.h"
+#include "widget.h"
+
+#define SVIS(x)  ((SVis *)(x))
+struct _SVis {
+    Widget vs_widget;
+    gint vs_data[75];
+    gint vs_refresh_delay;
+};
+
+typedef struct _SVis SVis;
+
+void svis_draw(Widget * w);
+void svis_timeout_func(SVis * svis, guchar * data);
+SVis *create_svis(GList ** wlist, GdkPixmap * parent, GdkGC * gc, gint x,
+                  gint y);
+void svis_set_data(SVis * vis, guchar * data);
+void svis_clear_data(SVis * vis);
+void svis_clear(SVis * vis);
+
+#endif
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/audacious/widgets/tbutton.c	Wed Aug 09 02:47:22 2006 -0700
@@ -0,0 +1,176 @@
+/*  BMP - Cross-platform multimedia player
+ *  Copyright (C) 2003-2004  BMP development team.
+ *
+ *  Based on XMMS:
+ *  Copyright (C) 1998-2003  XMMS development team.
+ *
+ *  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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+
+#include "tbutton.h"
+
+#include <glib.h>
+#include <gdk/gdk.h>
+
+#include "widget.h"
+
+void
+tbutton_draw(Widget * w)
+{
+    TButton *button = TBUTTON(w);
+    GdkPixmap *obj;
+
+    obj = button->tb_widget.parent;
+
+    if (button->tb_pressed && button->tb_inside) {
+        if (button->tb_selected) {
+            skin_draw_pixmap(bmp_active_skin, obj,
+                             button->tb_widget.gc,
+                             button->tb_skin_index,
+                             button->tb_psx, button->tb_psy,
+                             button->tb_widget.x, button->tb_widget.y,
+                             button->tb_widget.width,
+                             button->tb_widget.height);
+        }
+        else {
+            skin_draw_pixmap(bmp_active_skin, obj,
+                             button->tb_widget.gc,
+                             button->tb_skin_index,
+                             button->tb_pux, button->tb_puy,
+                             button->tb_widget.x, button->tb_widget.y,
+                             button->tb_widget.width,
+                             button->tb_widget.height);
+        }
+    }
+    else {
+        if (button->tb_selected) {
+            skin_draw_pixmap(bmp_active_skin, obj,
+                             button->tb_widget.gc,
+                             button->tb_skin_index,
+                             button->tb_nsx, button->tb_nsy,
+                             button->tb_widget.x, button->tb_widget.y,
+                             button->tb_widget.width,
+                             button->tb_widget.height);
+        }
+        else {
+            skin_draw_pixmap(bmp_active_skin, obj,
+                             button->tb_widget.gc,
+                             button->tb_skin_index,
+                             button->tb_nux, button->tb_nuy,
+                             button->tb_widget.x, button->tb_widget.y,
+                             button->tb_widget.width,
+                             button->tb_widget.height);
+
+        }
+    }
+}
+
+void
+tbutton_button_press_cb(GtkWidget * widget, GdkEventButton * event,
+                        TButton * button)
+{
+    if (event->button != 1)
+        return;
+
+    if (widget_contains(&button->tb_widget, event->x, event->y)) {
+        button->tb_pressed = 1;
+        button->tb_inside = 1;
+        widget_draw(WIDGET(button));
+    }
+}
+
+void
+tbutton_button_release_cb(GtkWidget * widget, GdkEventButton * event,
+                          TButton * button)
+{
+    if (event->button != 1)
+        return;
+
+    if (button->tb_inside && button->tb_pressed) {
+        button->tb_inside = 0;
+        button->tb_selected = !button->tb_selected;
+
+        widget_draw(WIDGET(button));
+
+        if (button->tb_push_cb)
+            button->tb_push_cb(button->tb_selected);
+    }
+
+    if (button->tb_pressed)
+        button->tb_pressed = 0;
+}
+
+void
+tbutton_motion_cb(GtkWidget * widget, GdkEventMotion * event,
+                  TButton * button)
+{
+    gint inside;
+
+    if (!button->tb_pressed)
+        return;
+    inside = widget_contains(&button->tb_widget, event->x, event->y);
+    if (inside != button->tb_inside) {
+        button->tb_inside = inside;
+        widget_draw(WIDGET(button));
+    }
+}
+
+TButton *
+create_tbutton(GList ** wlist, GdkPixmap * parent, GdkGC * gc,
+               gint x, gint y, gint w, gint h, gint nux, gint nuy,
+               gint pux, gint puy, gint nsx, gint nsy, gint psx,
+               gint psy, void (*cb) (gboolean), SkinPixmapId si)
+{
+    TButton *b;
+
+    b = g_new0(TButton, 1);
+    widget_init(&b->tb_widget, parent, gc, x, y, w, h, 1);
+    b->tb_widget.button_press_cb =
+        (void (*)(GtkWidget *, GdkEventButton *, gpointer))
+        tbutton_button_press_cb;
+    b->tb_widget.button_release_cb =
+        (void (*)(GtkWidget *, GdkEventButton *, gpointer))
+        tbutton_button_release_cb;
+    b->tb_widget.motion_cb =
+        (void (*)(GtkWidget *, GdkEventMotion *, gpointer))
+        tbutton_motion_cb;
+    b->tb_widget.draw = tbutton_draw;
+    b->tb_nux = nux;
+    b->tb_nuy = nuy;
+    b->tb_pux = pux;
+    b->tb_puy = puy;
+    b->tb_nsx = nsx;
+    b->tb_nsy = nsy;
+    b->tb_psx = psx;
+    b->tb_psy = psy;
+    b->tb_push_cb = cb;
+    b->tb_skin_index = si;
+
+    widget_list_add(wlist, WIDGET(b));
+    return b;
+}
+
+void
+tbutton_set_toggled(TButton * tb, gboolean toggled)
+{
+    tb->tb_selected = toggled;
+    widget_draw(WIDGET(tb));
+}
+
+void
+free_tbutton(TButton * b)
+{
+    g_free(b);
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/audacious/widgets/tbutton.h	Wed Aug 09 02:47:22 2006 -0700
@@ -0,0 +1,48 @@
+/*  BMP - Cross-platform multimedia player
+ *  Copyright (C) 2003-2004  BMP development team.
+ *
+ *  Based on XMMS:
+ *  Copyright (C) 1998-2003  XMMS development team.
+ *
+ *  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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+
+#ifndef TBUTTON_H
+#define TBUTTON_H
+
+#include <glib.h>
+
+#include "skin.h"
+#include "widget.h"
+
+#define TBUTTON(x) ((TButton *)(x))
+struct _TButton {
+    Widget tb_widget;
+    gint tb_nux, tb_nuy, tb_pux, tb_puy, tb_nsx, tb_nsy, tb_psx, tb_psy;
+    gint tb_pressed, tb_inside, tb_selected;
+    void (*tb_push_cb) (gboolean);
+    SkinPixmapId tb_skin_index;
+};
+
+typedef struct _TButton TButton;
+
+TButton *create_tbutton(GList ** wlist, GdkPixmap * parent, GdkGC * gc,
+                        gint x, gint y, gint w, gint h, gint nux, gint nuy,
+                        gint pux, gint puy, gint nsx, gint nsy, gint psx,
+                        gint psy, void (*cb) (gboolean), SkinPixmapId si);
+void tbutton_set_toggled(TButton * tb, gboolean toggled);
+void free_tbutton(TButton * b);
+
+#endif
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/audacious/widgets/textbox.c	Wed Aug 09 02:47:22 2006 -0700
@@ -0,0 +1,579 @@
+/*  BMP - Cross-platform multimedia player
+ *  Copyright (C) 2003-2004  BMP development team.
+ *
+ *  Based on XMMS:
+ *  Copyright (C) 1998-2003  XMMS development team.
+ *
+ *  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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+
+#include "textbox.h"
+
+#include <glib.h>
+#include <gtk/gtk.h>
+#include <gdk/gdk.h>
+#include <gdk/gdkprivate.h>
+#include <string.h>
+#include <ctype.h>
+
+#include "main.h"
+#include "util.h"
+
+static void textbox_generate_pixmap(TextBox * tb);
+
+static void
+textbox_draw(Widget * w)
+{
+    TextBox *tb = TEXT_BOX(w);
+    gint cw;
+    GdkPixmap *obj;
+    GdkPixmap *src;
+
+    g_return_if_fail(tb != NULL);
+
+    if (tb->tb_text &&
+        (!tb->tb_pixmap_text || strcmp(tb->tb_text, tb->tb_pixmap_text)))
+        textbox_generate_pixmap(tb);
+
+    if (tb->tb_pixmap) {
+        if (skin_get_id() != tb->tb_skin_id) {
+            tb->tb_skin_id = skin_get_id();
+            textbox_generate_pixmap(tb);
+        }
+        obj = tb->tb_widget.parent;
+        src = tb->tb_pixmap;
+
+        cw = tb->tb_pixmap_width - tb->tb_offset;
+        if (cw > tb->tb_widget.width)
+            cw = tb->tb_widget.width;
+        gdk_draw_pixmap(obj, tb->tb_widget.gc, src, tb->tb_offset, 0,
+                        tb->tb_widget.x, tb->tb_widget.y, cw,
+                        tb->tb_widget.height);
+        if (cw < tb->tb_widget.width)
+            gdk_draw_pixmap(obj, tb->tb_widget.gc, src, 0, 0,
+                            tb->tb_widget.x + cw, tb->tb_widget.y,
+                            tb->tb_widget.width - cw, tb->tb_widget.height);
+    }
+}
+
+static gboolean
+textbox_scroll(gpointer data)
+{
+    TextBox *tb = TEXT_BOX(data);
+
+    if (!tb->tb_is_dragging) {
+        tb->tb_offset += 1;
+        if (tb->tb_offset >= tb->tb_pixmap_width)
+            tb->tb_offset -= tb->tb_pixmap_width;
+        widget_draw(WIDGET(tb));
+    }
+
+    return TRUE;
+}
+
+static void
+textbox_button_press(GtkWidget * w, GdkEventButton * event, gpointer data)
+{
+    TextBox *tb = TEXT_BOX(data);
+
+    if (event->button != 1)
+        return;
+    if (widget_contains(&tb->tb_widget, event->x, event->y) &&
+        tb->tb_scroll_allowed &&
+        tb->tb_pixmap_width > tb->tb_widget.width && tb->tb_is_scrollable) {
+        tb->tb_is_dragging = TRUE;
+        tb->tb_drag_off = tb->tb_offset;
+        tb->tb_drag_x = event->x;
+    }
+}
+
+static void
+textbox_motion(GtkWidget * w, GdkEventMotion * event, gpointer data)
+{
+    TextBox *tb = TEXT_BOX(data);
+
+    if (tb->tb_is_dragging) {
+        if (tb->tb_scroll_allowed &&
+            tb->tb_pixmap_width > tb->tb_widget.width) {
+            tb->tb_offset = tb->tb_drag_off - (event->x - tb->tb_drag_x);
+
+            while (tb->tb_offset < 0)
+                tb->tb_offset += tb->tb_pixmap_width;
+
+            while (tb->tb_offset > tb->tb_pixmap_width)
+                tb->tb_offset -= tb->tb_pixmap_width;
+
+            widget_draw(WIDGET(tb));
+        }
+    }
+}
+
+static void
+textbox_button_release(GtkWidget * w, GdkEventButton * event, gpointer data)
+{
+    TextBox *tb = TEXT_BOX(data);
+
+    if (event->button == 1)
+        tb->tb_is_dragging = FALSE;
+}
+
+static gboolean
+textbox_should_scroll(TextBox * tb)
+{
+    g_return_val_if_fail(tb != NULL, FALSE);
+
+    if (!tb->tb_scroll_allowed)
+        return FALSE;
+
+    if (tb->tb_font) {
+        gint width;
+
+        text_get_extents(tb->tb_fontname, tb->tb_text, &width, NULL, NULL,
+                         NULL);
+
+        if (width <= tb->tb_widget.width)
+            return FALSE;
+        else
+            return TRUE;
+    }
+
+    if (g_utf8_strlen(tb->tb_text, -1) * 5 > tb->tb_widget.width)
+        return TRUE;
+
+    return FALSE;
+}
+
+void
+textbox_set_text(TextBox * tb, const gchar * text)
+{
+    g_return_if_fail(tb != NULL);
+    g_return_if_fail(text != NULL);
+
+    widget_lock(WIDGET(tb));
+
+    if (tb->tb_text) {
+        if (!strcmp(text, tb->tb_text)) {
+            widget_unlock(WIDGET(tb));
+            return;
+        }
+        g_free(tb->tb_text);
+    }
+
+    tb->tb_text = str_to_utf8(text);
+
+    widget_unlock(WIDGET(tb));
+    widget_draw(WIDGET(tb));
+}
+
+static void
+textbox_generate_xfont_pixmap(TextBox * tb, const gchar * pixmaptext)
+{
+    gint length, i;
+    GdkGC *gc, *maskgc;
+    GdkColor *c, pattern;
+    GdkBitmap *mask;
+    PangoLayout *layout;
+    gint width;
+
+    g_return_if_fail(tb != NULL);
+    g_return_if_fail(pixmaptext != NULL);
+
+    length = g_utf8_strlen(pixmaptext, -1);
+
+    text_get_extents(tb->tb_fontname, pixmaptext, &width, NULL, NULL, NULL);
+
+    tb->tb_pixmap_width = MAX(width, tb->tb_widget.width);
+    tb->tb_pixmap = gdk_pixmap_new(mainwin->window, tb->tb_pixmap_width,
+                                   tb->tb_widget.height,
+                                   gdk_rgb_get_visual()->depth);
+    gc = tb->tb_widget.gc;
+    c = skin_get_color(bmp_active_skin, SKIN_TEXTBG);
+    for (i = 0; i < tb->tb_widget.height; i++) {
+        gdk_gc_set_foreground(gc, &c[6 * i / tb->tb_widget.height]);
+        gdk_draw_line(tb->tb_pixmap, gc, 0, i, tb->tb_pixmap_width, i);
+    }
+
+    mask = gdk_pixmap_new(mainwin->window, tb->tb_pixmap_width,
+                          tb->tb_widget.height, 1);
+    maskgc = gdk_gc_new(mask);
+    pattern.pixel = 0;
+    gdk_gc_set_foreground(maskgc, &pattern);
+
+    gdk_draw_rectangle(mask, maskgc, TRUE, 0, 0,
+                       tb->tb_pixmap_width, tb->tb_widget.height);
+    pattern.pixel = 1;
+    gdk_gc_set_foreground(maskgc, &pattern);
+
+    gdk_gc_set_foreground(gc, skin_get_color(bmp_active_skin, SKIN_TEXTFG));
+
+    layout = gtk_widget_create_pango_layout(mainwin, pixmaptext);
+    pango_layout_set_font_description(layout, tb->tb_font);
+
+    gdk_draw_layout(tb->tb_pixmap, gc, 0, (tb->tb_font_descent / 2), layout);
+    g_object_unref(layout);
+
+    g_object_unref(maskgc);
+
+    gdk_gc_set_clip_mask(gc, mask);
+    c = skin_get_color(bmp_active_skin, SKIN_TEXTFG);
+    for (i = 0; i < tb->tb_widget.height; i++) {
+        gdk_gc_set_foreground(gc, &c[6 * i / tb->tb_widget.height]);
+        gdk_draw_line(tb->tb_pixmap, gc, 0, i, tb->tb_pixmap_width, i);
+    }
+    g_object_unref(mask);
+    gdk_gc_set_clip_mask(gc, NULL);
+}
+
+static void
+textbox_handle_special_char(gchar c, gint * x, gint * y)
+{
+    switch (c) {
+    case '"':
+        *x = 130;
+        *y = 0;
+        break;
+    case '\r':
+        *x = 50;
+        *y = 6;
+        break;
+    case ':':
+    case ';':
+        *x = 60;
+        *y = 6;
+        break;
+    case '(':
+        *x = 65;
+        *y = 6;
+        break;
+    case ')':
+        *x = 70;
+        *y = 6;
+        break;
+    case '-':
+        *x = 75;
+        *y = 6;
+        break;
+    case '`':
+    case '\'':
+        *x = 80;
+        *y = 6;
+        break;
+    case '!':
+        *x = 85;
+        *y = 6;
+        break;
+    case '_':
+        *x = 90;
+        *y = 6;
+        break;
+    case '+':
+        *x = 95;
+        *y = 6;
+        break;
+    case '\\':
+        *x = 100;
+        *y = 6;
+        break;
+    case '/':
+        *x = 105;
+        *y = 6;
+        break;
+    case '[':
+        *x = 110;
+        *y = 6;
+        break;
+    case ']':
+        *x = 115;
+        *y = 6;
+        break;
+    case '^':
+        *x = 120;
+        *y = 6;
+        break;
+    case '&':
+        *x = 125;
+        *y = 6;
+        break;
+    case '%':
+        *x = 130;
+        *y = 6;
+        break;
+    case '.':
+    case ',':
+        *x = 135;
+        *y = 6;
+        break;
+    case '=':
+        *x = 140;
+        *y = 6;
+        break;
+    case '$':
+        *x = 145;
+        *y = 6;
+        break;
+    case '#':
+        *x = 150;
+        *y = 6;
+        break;
+    case 'å':
+    case 'Å':
+        *x = 0;
+        *y = 12;
+        break;
+    case 'ö':
+    case 'Ö':
+        *x = 5;
+        *y = 12;
+        break;
+    case 'ä':
+    case 'Ä':
+        *x = 10;
+        *y = 12;
+        break;
+    case 'ü':
+    case 'Ü':
+        *x = 100;
+        *y = 0;
+        break;
+    case '?':
+        *x = 15;
+        *y = 12;
+        break;
+    case '*':
+        *x = 20;
+        *y = 12;
+        break;
+    default:
+        *x = 145;
+        *y = 0;
+        break;
+    }
+}
+
+static void
+textbox_generate_pixmap(TextBox * tb)
+{
+    gint length, i, x, y, wl;
+    gchar *pixmaptext;
+    GdkGC *gc;
+
+    g_return_if_fail(tb != NULL);
+
+    if (tb->tb_pixmap) {
+        g_object_unref(tb->tb_pixmap);
+        tb->tb_pixmap = NULL;
+    }
+
+    /*
+     * Don't reset the offset if only text after the last '(' has
+     * changed.  This is a hack to avoid visual noice on vbr files
+     * where we guess the length.
+     */
+    if (!(tb->tb_pixmap_text && strrchr(tb->tb_text, '(') &&
+          !strncmp(tb->tb_pixmap_text, tb->tb_text,
+                   strrchr(tb->tb_text, '(') - tb->tb_text)))
+        tb->tb_offset = 0;
+
+    g_free(tb->tb_pixmap_text);
+    tb->tb_pixmap_text = g_strdup(tb->tb_text);
+
+    /*
+     * wl is the number of (partial) letters visible. Only makes
+     * sense when using skinned font.
+     */
+
+    wl = tb->tb_widget.width / 5;
+    if (wl * 5 != tb->tb_widget.width)
+        wl++;
+
+    length = g_utf8_strlen(tb->tb_text, -1);
+
+    tb->tb_is_scrollable = FALSE;
+
+    if (textbox_should_scroll(tb)) {
+        tb->tb_is_scrollable = TRUE;
+        pixmaptext = g_strconcat(tb->tb_pixmap_text, "  ***  ", NULL);
+        length += 7;
+    }
+    else if (!tb->tb_font && length <= wl) {
+        gint pad = wl - length;
+        gchar *padchars = g_strnfill(pad, ' ');
+
+        pixmaptext = g_strconcat(tb->tb_pixmap_text, padchars, NULL);
+        g_free(padchars);
+        length += pad;
+    }
+    else
+        pixmaptext = g_strdup(tb->tb_pixmap_text);
+
+
+    if (tb->tb_is_scrollable) {
+        if (tb->tb_scroll_enabled && !tb->tb_timeout_tag) {
+            gint tag;
+            tag = TEXTBOX_SCROLL_SMOOTH_TIMEOUT;
+            tb->tb_timeout_tag = gtk_timeout_add(tag, textbox_scroll, tb);
+        }
+    }
+    else {
+        if (tb->tb_timeout_tag) {
+            gtk_timeout_remove(tb->tb_timeout_tag);
+            tb->tb_timeout_tag = 0;
+        }
+        tb->tb_offset = 0;
+    }
+
+    if (tb->tb_font) {
+        textbox_generate_xfont_pixmap(tb, pixmaptext);
+        g_free(pixmaptext);
+        return;
+    }
+
+    tb->tb_pixmap_width = length * 5;
+    tb->tb_pixmap = gdk_pixmap_new(mainwin->window,
+                                   tb->tb_pixmap_width, 6,
+                                   gdk_rgb_get_visual()->depth);
+    gc = tb->tb_widget.gc;
+
+    for (i = 0; i < length; i++) {
+        gchar c;
+        x = y = -1;
+        c = toupper(pixmaptext[i]);
+        if (c >= 'A' && c <= 'Z') {
+            x = 5 * (c - 'A');
+            y = 0;
+        }
+        else if (c >= '0' && c <= '9') {
+            x = 5 * (c - '0');
+            y = 6;
+        }
+        else
+            textbox_handle_special_char(c, &x, &y);
+
+        skin_draw_pixmap(bmp_active_skin,
+                         tb->tb_pixmap, gc, tb->tb_skin_index,
+                         x, y, i * 5, 0, 5, 6);
+    }
+    g_free(pixmaptext);
+}
+
+void
+textbox_set_scroll(TextBox * tb, gboolean s)
+{
+    g_return_if_fail(tb != NULL);
+
+    tb->tb_scroll_enabled = s;
+    if (tb->tb_scroll_enabled && tb->tb_is_scrollable
+        && tb->tb_scroll_allowed) {
+        gint tag;
+        tag = TEXTBOX_SCROLL_SMOOTH_TIMEOUT;
+
+	if (tb->tb_timeout_tag)
+        {
+	    gtk_timeout_remove(tb->tb_timeout_tag);
+            tb->tb_timeout_tag = 0;
+	}
+
+        tb->tb_timeout_tag = gtk_timeout_add(tag, textbox_scroll, tb);
+    }
+    else
+    {
+        if (tb->tb_timeout_tag)
+        {
+            gtk_timeout_remove(tb->tb_timeout_tag);
+            tb->tb_timeout_tag = 0;
+        }
+
+        tb->tb_offset = 0;
+        widget_draw(WIDGET(tb));
+    }
+
+}
+
+void
+textbox_set_xfont(TextBox * tb, gboolean use_xfont, const gchar * fontname)
+{
+    gint ascent, descent;
+
+    g_return_if_fail(tb != NULL);
+
+    if (tb->tb_font) {
+        pango_font_description_free(tb->tb_font);
+        tb->tb_font = NULL;
+    }
+
+    tb->tb_widget.y = tb->tb_nominal_y;
+    tb->tb_widget.height = tb->tb_nominal_height;
+
+    /* Make sure the pixmap is regenerated */
+    if (tb->tb_pixmap_text) {
+        g_free(tb->tb_pixmap_text);
+        tb->tb_pixmap_text = NULL;
+    }
+
+    if (!use_xfont || strlen(fontname) == 0)
+        return;
+
+    tb->tb_font = pango_font_description_from_string(fontname);
+    tb->tb_fontname = g_strdup(fontname);
+
+    text_get_extents(fontname,
+                     "AaBbCcDdEeFfGgHhIiJjKkLlMmNnOoPpQqRrSsTtUuVvWwXxYyZz ",
+                     NULL, NULL, &ascent, &descent);
+    tb->tb_font_ascent = ascent;
+    tb->tb_font_descent = descent;
+
+
+    if (tb->tb_font == NULL)
+        return;
+
+    tb->tb_widget.height = tb->tb_font_ascent;
+    if (tb->tb_widget.height > tb->tb_nominal_height)
+        tb->tb_widget.y -= (tb->tb_widget.height - tb->tb_nominal_height) / 2;
+    else
+        tb->tb_widget.height = tb->tb_nominal_height;
+}
+
+TextBox *
+create_textbox(GList ** wlist, GdkPixmap * parent, GdkGC * gc,
+               gint x, gint y, gint w, gboolean allow_scroll, SkinPixmapId si)
+{
+    TextBox *tb;
+
+    tb = g_new0(TextBox, 1);
+    widget_init(&tb->tb_widget, parent, gc, x, y, w, 6, 1);
+    tb->tb_widget.button_press_cb = textbox_button_press;
+    tb->tb_widget.button_release_cb = textbox_button_release;
+    tb->tb_widget.motion_cb = textbox_motion;
+    tb->tb_widget.draw = textbox_draw;
+    tb->tb_scroll_allowed = allow_scroll;
+    tb->tb_scroll_enabled = TRUE;
+    tb->tb_skin_index = si;
+    tb->tb_nominal_y = y;
+    tb->tb_nominal_height = tb->tb_widget.height;
+    widget_list_add(wlist, WIDGET(tb));
+    tb->tb_timeout_tag = 0;
+    return tb;
+}
+
+void
+textbox_free(TextBox * tb)
+{
+    g_return_if_fail(tb != NULL);
+
+    if (tb->tb_pixmap)
+        g_object_unref(tb->tb_pixmap);
+    g_free(tb->tb_text);
+    g_free(tb);
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/audacious/widgets/textbox.h	Wed Aug 09 02:47:22 2006 -0700
@@ -0,0 +1,64 @@
+/*  BMP - Cross-platform multimedia player
+ *  Copyright (C) 2003-2004  BMP development team.
+ *
+ *  Based on XMMS:
+ *  Copyright (C) 1998-2003  XMMS development team.
+ *
+ *  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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+
+#ifndef TEXTBOX_H
+#define	TEXTBOX_H
+
+#include <glib.h>
+#include <gdk/gdk.h>
+#include <pango/pango.h>
+
+#include "skin.h"
+#include "widget.h"
+
+#define	TEXTBOX_SCROLL_TIMEOUT	       200
+#define TEXTBOX_SCROLL_SMOOTH_TIMEOUT  30
+
+#define TEXT_BOX(x)  ((TextBox *)(x))
+struct _TextBox {
+    Widget tb_widget;
+    GdkPixmap *tb_pixmap;
+    gchar *tb_text, *tb_pixmap_text;
+    gint tb_pixmap_width;
+    gint tb_offset;
+    gboolean tb_scroll_allowed, tb_scroll_enabled;
+    gboolean tb_is_scrollable, tb_is_dragging;
+    gint tb_timeout_tag, tb_drag_x, tb_drag_off;
+    gint tb_nominal_y, tb_nominal_height;
+    gint tb_skin_id;
+    SkinPixmapId tb_skin_index;
+    PangoFontDescription *tb_font;
+    gint tb_font_ascent, tb_font_descent;
+    gchar *tb_fontname;
+};
+
+typedef struct _TextBox TextBox;
+
+void textbox_set_text(TextBox * tb, const gchar * text);
+void textbox_set_scroll(TextBox * tb, gboolean s);
+TextBox *create_textbox(GList ** wlist, GdkPixmap * parent, GdkGC * gc,
+                        gint x, gint y, gint w, gboolean allow_scroll,
+                        SkinPixmapId si);
+void textbox_set_xfont(TextBox * tb, gboolean use_xfont,
+                       const gchar * fontname);
+void textbox_free(TextBox * tb);
+
+#endif
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/audacious/widgets/vis.c	Wed Aug 09 02:47:22 2006 -0700
@@ -0,0 +1,291 @@
+/*  BMP - Cross-platform multimedia player
+ *  Copyright (C) 2003-2004  BMP development team.
+ *
+ *  Based on XMMS:
+ *  Copyright (C) 1998-2003  XMMS development team.
+ *
+ *  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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+
+#include "vis.h"
+
+#include <glib.h>
+#include <gdk/gdk.h>
+#include <string.h>
+
+#include "main.h"
+#include "skin.h"
+#include "widget.h"
+
+static const gfloat vis_afalloff_speeds[] = { 0.34, 0.5, 1.0, 1.3, 1.6 };
+static const gfloat vis_pfalloff_speeds[] = { 1.2, 1.3, 1.4, 1.5, 1.6 };
+static const gint vis_redraw_delays[] = { 1, 2, 4, 8 };
+static const guint8 vis_scope_colors[] =
+    { 21, 21, 20, 20, 19, 19, 18, 19, 19, 20, 20, 21, 21 };
+
+void
+vis_timeout_func(Vis * vis, guchar * data)
+{
+    static GTimer *timer = NULL;
+    gulong micros = 9999999;
+    gboolean falloff = FALSE;
+    gint i;
+
+    if (!timer) {
+        timer = g_timer_new();
+        g_timer_start(timer);
+    }
+    else {
+        g_timer_elapsed(timer, &micros);
+        if (micros > 14000)
+            g_timer_reset(timer);
+
+    }
+
+    if (cfg.vis_type == VIS_ANALYZER) {
+        if (micros > 14000)
+            falloff = TRUE;
+        if (data || falloff) {
+            for (i = 0; i < 75; i++) {
+                if (data && data[i] > vis->vs_data[i]) {
+                    vis->vs_data[i] = data[i];
+                    if (vis->vs_data[i] > vis->vs_peak[i]) {
+                        vis->vs_peak[i] = vis->vs_data[i];
+                        vis->vs_peak_speed[i] = 0.01;
+
+                    }
+                    else if (vis->vs_peak[i] > 0.0) {
+                        vis->vs_peak[i] -= vis->vs_peak_speed[i];
+                        vis->vs_peak_speed[i] *=
+                            vis_pfalloff_speeds[cfg.peaks_falloff];
+                        if (vis->vs_peak[i] < vis->vs_data[i])
+                            vis->vs_peak[i] = vis->vs_data[i];
+                        if (vis->vs_peak[i] < 0.0)
+                            vis->vs_peak[i] = 0.0;
+                    }
+                }
+                else if (falloff) {
+                    if (vis->vs_data[i] > 0.0) {
+                        vis->vs_data[i] -=
+                            vis_afalloff_speeds[cfg.analyzer_falloff];
+                        if (vis->vs_data[i] < 0.0)
+                            vis->vs_data[i] = 0.0;
+                    }
+                    if (vis->vs_peak[i] > 0.0) {
+                        vis->vs_peak[i] -= vis->vs_peak_speed[i];
+                        vis->vs_peak_speed[i] *=
+                            vis_pfalloff_speeds[cfg.peaks_falloff];
+                        if (vis->vs_peak[i] < vis->vs_data[i])
+                            vis->vs_peak[i] = vis->vs_data[i];
+                        if (vis->vs_peak[i] < 0.0)
+                            vis->vs_peak[i] = 0.0;
+                    }
+                }
+            }
+        }
+    }
+    else if (data) {
+        for (i = 0; i < 75; i++)
+            vis->vs_data[i] = data[i];
+    }
+
+    if (micros > 14000) {
+        if (!vis->vs_refresh_delay) {
+            vis_draw((Widget *) vis);
+            vis->vs_refresh_delay = vis_redraw_delays[cfg.vis_refresh];
+
+        }
+        vis->vs_refresh_delay--;
+    }
+}
+
+void
+vis_draw(Widget * w)
+{
+    Vis *vis = (Vis *) w;
+    gint x, y, h = 0, h2;
+    guchar vis_color[24][3];
+    guchar rgb_data[152 * 32], *ptr, c;
+    guint32 colors[24];
+    GdkRgbCmap *cmap;
+
+    if (!vis->vs_widget.visible)
+        return;
+
+    skin_get_viscolor(bmp_active_skin, vis_color);
+    for (y = 0; y < 24; y++) {
+        colors[y] =
+            vis_color[y][0] << 16 | vis_color[y][1] << 8 | vis_color[y][2];
+    }
+    cmap = gdk_rgb_cmap_new(colors, 24);
+
+    memset(rgb_data, 0, 76 * 16);
+    for (y = 1; y < 16; y += 2) {
+        ptr = rgb_data + (y * 76);
+        for (x = 0; x < 76; x += 2, ptr += 2)
+            *ptr = 1;
+    }
+    if (cfg.vis_type == VIS_ANALYZER) {
+        for (x = 0; x < 75; x++) {
+            if (cfg.analyzer_type == ANALYZER_BARS && (x % 4) == 0)
+                h = vis->vs_data[x >> 2];
+            else if (cfg.analyzer_type == ANALYZER_LINES)
+                h = vis->vs_data[x];
+            if (h && (cfg.analyzer_type == ANALYZER_LINES ||
+                      (x % 4) != 3)) {
+                ptr = rgb_data + ((16 - h) * 76) + x;
+                switch (cfg.analyzer_mode) {
+                case ANALYZER_NORMAL:
+                    for (y = 0; y < h; y++, ptr += 76)
+                        *ptr = 18 - h + y;
+                    break;
+                case ANALYZER_FIRE:
+                    for (y = 0; y < h; y++, ptr += 76)
+                        *ptr = y + 2;
+                    break;
+                case ANALYZER_VLINES:
+                    for (y = 0; y < h; y++, ptr += 76)
+                        *ptr = 18 - h;
+                    break;
+                }
+            }
+        }
+        if (cfg.analyzer_peaks) {
+            for (x = 0; x < 75; x++) {
+                if (cfg.analyzer_type == ANALYZER_BARS && (x % 4) == 0)
+                    h = vis->vs_peak[x >> 2];
+                else if (cfg.analyzer_type == ANALYZER_LINES)
+                    h = vis->vs_peak[x];
+                if (h
+                    && (cfg.analyzer_type == ANALYZER_LINES
+                        || (x % 4) != 3))
+                    rgb_data[(16 - h) * 76 + x] = 23;
+            }
+        }
+    }
+    else if (cfg.vis_type == VIS_SCOPE) {
+        for (x = 0; x < 75; x++) {
+            switch (cfg.scope_mode) {
+            case SCOPE_DOT:
+                h = vis->vs_data[x];
+                ptr = rgb_data + ((15 - h) * 76) + x;
+                *ptr = vis_scope_colors[h];
+                break;
+            case SCOPE_LINE:
+                if (x != 74) {
+                    h = 15 - vis->vs_data[x];
+                    h2 = 15 - vis->vs_data[x + 1];
+                    if (h > h2) {
+                        y = h;
+                        h = h2;
+                        h2 = y;
+                    }
+                    ptr = rgb_data + (h * 76) + x;
+                    for (y = h; y <= h2; y++, ptr += 76)
+                        *ptr = vis_scope_colors[y - 3];
+
+                }
+                else {
+                    h = 15 - vis->vs_data[x];
+                    ptr = rgb_data + (h * 76) + x;
+                    *ptr = vis_scope_colors[h];
+                }
+                break;
+            case SCOPE_SOLID:
+                h = 15 - vis->vs_data[x];
+                h2 = 9;
+                c = vis_scope_colors[(gint) vis->vs_data[x]];
+                if (h > h2) {
+                    y = h;
+                    h = h2;
+                    h2 = y;
+                }
+                ptr = rgb_data + (h * 76) + x;
+                for (y = h; y <= h2; y++, ptr += 76)
+                    *ptr = c;
+                break;
+            }
+        }
+    }
+
+    /* FIXME: The check "shouldn't" be neccessary? */
+    /*	if (GTK_IS_WINDOW(vis->vs_window)) { */
+    GDK_THREADS_ENTER();
+    gdk_draw_indexed_image(vis->vs_window, vis->vs_widget.gc,
+                           vis->vs_widget.x, vis->vs_widget.y,
+                           vis->vs_widget.width, vis->vs_widget.height,
+                           GDK_RGB_DITHER_NORMAL, (guchar *) rgb_data,
+                           76, cmap);
+    GDK_THREADS_LEAVE();
+    /*	} else {
+        vis->vs_window = mainwin->window;
+        GDK_THREADS_ENTER();
+        gdk_draw_indexed_image(vis->vs_window, vis->vs_widget.gc,
+        vis->vs_widget.x, vis->vs_widget.y,
+        vis->vs_widget.width, vis->vs_widget.height,
+        GDK_RGB_DITHER_NORMAL, (guchar *) rgb_data,
+        76, cmap);
+        GDK_THREADS_LEAVE();
+        }
+    */
+
+    gdk_rgb_cmap_free(cmap);
+}
+
+void
+vis_clear_data(Vis * vis)
+{
+    gint i;
+
+    if (!vis)
+        return;
+
+    for (i = 0; i < 75; i++) {
+        vis->vs_data[i] = (cfg.vis_type == VIS_SCOPE) ? 6 : 0;
+        vis->vs_peak[i] = 0;
+    }
+}
+
+void
+vis_clear(Vis * vis)
+{
+    gdk_window_clear_area(vis->vs_window, vis->vs_widget.x,
+                          vis->vs_widget.y, vis->vs_widget.width,
+                          vis->vs_widget.height);
+}
+
+void
+vis_set_window(Vis * vis, GdkWindow * window)
+{
+    vis->vs_window = window;
+}
+
+Vis *
+create_vis(GList ** wlist,
+           GdkPixmap * parent,
+           GdkWindow * window,
+           GdkGC * gc,
+           gint x, gint y,
+           gint width)
+{
+    Vis *vis;
+
+    vis = g_new0(Vis, 1);
+
+    widget_init(&vis->vs_widget, parent, gc, x, y, width, 16, 1);
+    widget_list_add(wlist, WIDGET(vis));
+
+    return vis;
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/audacious/widgets/vis.h	Wed Aug 09 02:47:22 2006 -0700
@@ -0,0 +1,77 @@
+/*  BMP - Cross-platform multimedia player
+ *  Copyright (C) 2003-2004  BMP development team.
+ *
+ *  Based on XMMS:
+ *  Copyright (C) 1998-2003  XMMS development team.
+ *
+ *  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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+#ifndef VIS_H
+#define VIS_H
+
+#include <glib.h>
+#include <gdk/gdk.h>
+
+#include "widget.h"
+
+typedef enum {
+    VIS_ANALYZER, VIS_SCOPE, VIS_OFF
+} VisType;
+
+typedef enum {
+    ANALYZER_NORMAL, ANALYZER_FIRE, ANALYZER_VLINES
+} AnalyzerMode;
+
+typedef enum {
+    ANALYZER_LINES, ANALYZER_BARS
+} AnalyzerType;
+
+typedef enum {
+    SCOPE_DOT, SCOPE_LINE, SCOPE_SOLID
+} ScopeMode;
+
+typedef enum {
+    VU_NORMAL, VU_SMOOTH
+} VUMode;
+
+typedef enum {
+    REFRESH_FULL, REFRESH_HALF, REFRESH_QUARTER, REFRESH_EIGTH
+} RefreshRate;
+
+typedef enum {
+    FALLOFF_SLOWEST, FALLOFF_SLOW, FALLOFF_MEDIUM, FALLOFF_FAST,
+    FALLOFF_FASTEST
+} FalloffSpeed;
+
+#define VIS(x)  ((Vis *)(x))
+struct _Vis {
+    Widget vs_widget;
+    GdkWindow *vs_window;
+    gfloat vs_data[75], vs_peak[75], vs_peak_speed[75];
+    gint vs_refresh_delay;
+};
+
+typedef struct _Vis Vis;
+
+void vis_draw(Widget * w);
+
+Vis *create_vis(GList ** wlist, GdkPixmap * parent, GdkWindow * window,
+                GdkGC * gc, gint x, gint y, gint width);
+void vis_timeout_func(Vis * vis, guchar * data);
+void vis_clear_data(Vis * vis);
+void vis_clear(Vis * vis);
+void vis_set_window(Vis * vis, GdkWindow * window);
+
+#endif
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/audacious/widgets/widget.c	Wed Aug 09 02:47:22 2006 -0700
@@ -0,0 +1,263 @@
+/*  BMP - Cross-platform multimedia player
+ *  Copyright (C) 2003-2004  BMP development team.
+ *
+ *  Based on XMMS:
+ *  Copyright (C) 1998-2003  XMMS development team.
+ *
+ *  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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+
+#include "widget.h"
+
+#include <glib.h>
+#include <gdk/gdk.h>
+
+#include "debug.h"
+
+
+void
+widget_init(Widget * widget, GdkPixmap * parent, GdkGC * gc,
+            gint x, gint y, gint width, gint height, gint visible)
+{
+    widget->parent = parent;
+    widget->gc = gc;
+    widget_set_position(widget, x, y);
+    widget_set_size(widget, width, height);
+    widget->visible = visible;
+    widget->redraw = TRUE;
+    widget->mutex = g_mutex_new();
+}
+
+void
+widget_set_position(Widget * widget, gint x, gint y)
+{
+    widget->x = x;
+    widget->y = y;
+    widget_queue_redraw(widget);
+}
+
+void
+widget_set_size(Widget * widget, gint width, gint height)
+{
+    widget->width = width;
+    widget->height = height;
+    widget_queue_redraw(widget);
+}
+
+void
+widget_queue_redraw(Widget * widget)
+{
+    widget->redraw = TRUE;
+}
+
+gboolean
+widget_contains(Widget * widget, gint x, gint y)
+{
+    return (widget->visible &&
+            x >= widget->x && 
+            y >= widget->y && 
+            x <  widget->x + widget->width && 
+            y <  widget->y + widget->height);
+}
+
+void
+widget_show(Widget * widget)
+{
+    if (!widget)
+        return;
+
+    widget->visible = TRUE;
+    widget_draw(widget);
+}
+
+void
+widget_hide(Widget * widget)
+{
+    if (!widget)
+        return;
+
+    widget->visible = FALSE;
+}
+
+gboolean
+widget_is_visible(Widget * widget)
+{
+    if (!widget)
+        return FALSE;
+
+    return widget->visible;
+}
+
+void
+widget_resize(Widget * widget, gint width, gint height)
+{
+    widget_set_size(widget, width, height);
+}
+
+void
+widget_move(Widget * widget, gint x, gint y)
+{
+    widget_lock(widget);
+    widget_set_position(widget, x, y);
+    widget_unlock(widget);
+}
+
+void
+widget_draw(Widget * widget)
+{
+    widget_lock(widget);
+    WIDGET(widget)->redraw = TRUE;
+    widget_unlock(widget);
+}
+
+void
+widget_draw_quick(Widget * widget)
+{
+    widget_lock(widget);
+    if (WIDGET(widget)->draw != NULL)
+    {
+	WIDGET(widget)->draw(widget);
+        gdk_flush();
+    }
+    widget_unlock(widget);
+}
+
+void
+widget_list_add(GList ** list, Widget * widget)
+{
+    (*list) = g_list_append(*list, widget);
+}
+
+void
+handle_press_cb(GList * widget_list, GtkWidget * widget,
+                GdkEventButton * event)
+{
+    GList *wl;
+
+    for (wl = widget_list; wl; wl = g_list_next(wl)) {
+        if (WIDGET(wl->data)->button_press_cb)
+            WIDGET(wl->data)->button_press_cb(widget, event, wl->data);
+    }
+}
+
+void
+handle_release_cb(GList * widget_list, GtkWidget * widget,
+                  GdkEventButton * event)
+{
+    GList *wl;
+
+    for (wl = widget_list; wl; wl = g_list_next(wl)) {
+        if (WIDGET(wl->data)->button_release_cb)
+            WIDGET(wl->data)->button_release_cb(widget, event, wl->data);
+    }
+}
+
+void
+handle_motion_cb(GList * widget_list, GtkWidget * widget,
+                 GdkEventMotion * event)
+{
+    GList *wl;
+
+    for (wl = widget_list; wl; wl = g_list_next(wl)) {
+        if (WIDGET(wl->data)->motion_cb)
+            WIDGET(wl->data)->motion_cb(widget, event, wl->data);
+    }
+}
+
+void
+handle_scroll_cb(GList * wlist, GtkWidget * widget, GdkEventScroll * event)
+{
+    GList *wl;
+
+    for (wl = wlist; wl; wl = g_list_next(wl)) {
+        if (WIDGET(wl->data)->mouse_scroll_cb)
+            WIDGET(wl->data)->mouse_scroll_cb(widget, event, wl->data);
+    }
+}
+
+void
+widget_list_draw(GList * widget_list, gboolean * redraw, gboolean force)
+{
+    GList *wl;
+    Widget *w;
+
+    *redraw = FALSE;
+    wl = widget_list;
+
+    for (wl = widget_list; wl; wl = g_list_next(wl)) {
+        w = WIDGET(wl->data);
+
+        REQUIRE_LOCK(w->mutex);
+
+        if (!w->draw)
+            continue;
+
+        if (!w->visible)
+            continue;
+
+        if (w->redraw || force) {
+            w->draw(w);
+/*             w->redraw = FALSE; */
+            *redraw = TRUE;
+        }
+    }
+}
+
+void
+widget_list_change_pixmap(GList * widget_list, GdkPixmap * pixmap)
+{
+    GList *wl;
+
+    for (wl = widget_list; wl; wl = g_list_next(wl)) {
+        Widget *widget = wl->data;
+        widget->parent = pixmap;
+        widget_queue_redraw(widget);
+    }
+}
+
+void
+widget_list_clear_redraw(GList * widget_list)
+{
+    GList *wl;
+
+    for (wl = widget_list; wl; wl = g_list_next(wl)) {
+        REQUIRE_LOCK(WIDGET(wl->data)->mutex);
+        WIDGET(wl->data)->redraw = FALSE;
+    }
+}
+
+void
+widget_lock(Widget * widget)
+{
+    g_mutex_lock(WIDGET(widget)->mutex);
+}
+
+void
+widget_unlock(Widget * widget)
+{
+    g_mutex_unlock(WIDGET(widget)->mutex);
+}
+
+void
+widget_list_lock(GList * widget_list)
+{
+    g_list_foreach(widget_list, (GFunc) widget_lock, NULL);
+}
+
+void
+widget_list_unlock(GList * widget_list)
+{
+    g_list_foreach(widget_list, (GFunc) widget_unlock, NULL);
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/audacious/widgets/widget.h	Wed Aug 09 02:47:22 2006 -0700
@@ -0,0 +1,102 @@
+/*  BMP - Cross-platform multimedia player
+ *  Copyright (C) 2003-2004  BMP development team.
+ *
+ *  Based on XMMS:
+ *  Copyright (C) 1998-2003  XMMS development team.
+ *
+ *  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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+#ifndef WIDGET_H
+#define WIDGET_H
+
+
+#include <glib.h>
+#include <gdk/gdk.h>
+#include <gtk/gtk.h>
+
+
+typedef struct _Widget Widget;
+
+
+typedef void (*WidgetButtonPressFunc) (GtkWidget *, GdkEventButton *,
+                                       gpointer);
+typedef void (*WidgetButtonReleaseFunc) (GtkWidget *, GdkEventButton *,
+                                         gpointer);
+typedef void (*WidgetMotionFunc) (GtkWidget *, GdkEventMotion *, gpointer);
+typedef void (*WidgetDrawFunc) (Widget *);
+typedef void (*WidgetScrollFunc) (GtkWidget *, GdkEventScroll *, gpointer);
+
+
+#define WIDGET(x)  ((Widget *)(x))
+struct _Widget {
+    GdkPixmap *parent;
+    GdkGC *gc;
+
+    gint x, y;
+    gint width, height;
+
+    gint visible;
+    gboolean redraw;
+
+    GMutex *mutex;
+
+    WidgetButtonPressFunc button_press_cb;
+    WidgetButtonReleaseFunc button_release_cb;
+    WidgetMotionFunc motion_cb;
+    WidgetDrawFunc draw;
+    WidgetScrollFunc mouse_scroll_cb;
+};
+
+
+void widget_init(Widget * widget, GdkPixmap * parent, GdkGC * gc,
+                 gint x, gint y, gint width, gint height, gint visible);
+
+void widget_set_position(Widget * widget, gint x, gint y);
+void widget_set_size(Widget * widget, gint width, gint height);
+void widget_queue_redraw(Widget * widget);
+
+void widget_lock(Widget * widget);
+void widget_unlock(Widget * widget);
+
+gboolean widget_contains(Widget * widget, gint x, gint y);
+
+void widget_show(Widget * widget);
+void widget_hide(Widget * widget);
+gboolean widget_is_visible(Widget * widget);
+
+void widget_resize(Widget * widget, gint width, gint height);
+void widget_move(Widget * widget, gint x, gint y);
+void widget_draw(Widget * widget);
+void widget_draw_quick(Widget * widget);
+
+void handle_press_cb(GList * wlist, GtkWidget * widget,
+                     GdkEventButton * event);
+void handle_release_cb(GList * wlist, GtkWidget * widget,
+                       GdkEventButton * event);
+void handle_motion_cb(GList * wlist, GtkWidget * widget,
+                      GdkEventMotion * event);
+void handle_scroll_cb(GList * wlist, GtkWidget * widget,
+                      GdkEventScroll * event);
+
+void widget_list_add(GList ** list, Widget * widget);
+void widget_list_draw(GList * list, gboolean * redraw, gboolean force);
+void widget_list_change_pixmap(GList * list, GdkPixmap * pixmap);
+void widget_list_clear_redraw(GList * list);
+void widget_list_lock(GList * list);
+void widget_list_unlock(GList * list);
+
+
+
+#endif