[Goodies-commits] r3852 - in xfce4-clipman-plugin/trunk: . panel-plugin

Mike Massonnet mmassonnet at xfce.org
Thu Jan 24 14:07:35 CET 2008


Author: mmassonnet
Date: 2008-01-24 13:07:34 +0000 (Thu, 24 Jan 2008)
New Revision: 3852

Modified:
   xfce4-clipman-plugin/trunk/configure.in.in
   xfce4-clipman-plugin/trunk/panel-plugin/Makefile.am
   xfce4-clipman-plugin/trunk/panel-plugin/clipman-dialogs.c
   xfce4-clipman-plugin/trunk/panel-plugin/clipman-dialogs.h
   xfce4-clipman-plugin/trunk/panel-plugin/clipman.c
   xfce4-clipman-plugin/trunk/panel-plugin/clipman.h
Log:
New rewrite


Modified: xfce4-clipman-plugin/trunk/configure.in.in
===================================================================
--- xfce4-clipman-plugin/trunk/configure.in.in	2008-01-24 12:53:05 UTC (rev 3851)
+++ xfce4-clipman-plugin/trunk/configure.in.in	2008-01-24 13:07:34 UTC (rev 3852)
@@ -60,11 +60,10 @@
 dnl ***********************************
 dnl *** Check for required packages ***
 dnl ***********************************
-XDT_CHECK_PACKAGE([GTHREAD], [gthread-2.0], [2.6.0])
-XDT_CHECK_PACKAGE([GTK], [gtk+-2.0], [2.6.0])
-XDT_CHECK_PACKAGE([LIBXFCEGUI4], [libxfcegui4-1.0], [4.3.99.2])
-XDT_CHECK_PACKAGE([LIBXFCE4UTIL], [libxfce4util-1.0], [4.3.99.2])
-XDT_CHECK_PACKAGE([LIBXFCE4PANEL], [libxfce4panel-1.0], [4.3.99.2])
+XDT_CHECK_PACKAGE([GTK], [gtk+-2.0], [2.10.0])
+XDT_CHECK_PACKAGE([LIBXFCEGUI4], [libxfcegui4-1.0], [4.4.0])
+XDT_CHECK_PACKAGE([LIBXFCE4UTIL], [libxfce4util-1.0], [4.4.0])
+XDT_CHECK_PACKAGE([LIBXFCE4PANEL], [libxfce4panel-1.0], [4.4.0])
 
 dnl ***********************************
 dnl *** Check for debugging support ***

Modified: xfce4-clipman-plugin/trunk/panel-plugin/Makefile.am
===================================================================
--- xfce4-clipman-plugin/trunk/panel-plugin/Makefile.am	2008-01-24 12:53:05 UTC (rev 3851)
+++ xfce4-clipman-plugin/trunk/panel-plugin/Makefile.am	2008-01-24 13:07:34 UTC (rev 3852)
@@ -1,44 +1,35 @@
-# $Id$
+plugindir = $(libexecdir)/xfce4/panel-plugins
+plugin_PROGRAMS = xfce4-clipman-plugin
 
-INCLUDES =								\
-	-I$(top_srcdir)							\
-	-DG_LOG_DOMAIN=\"xfce4-battery-plugin\"				\
-	-DPACKAGE_LOCALE_DIR=\"$(localedir)\"
-
-#
-# Battery Plugin
-#
-plugindir =								\
-	$(libexecdir)/xfce4/panel-plugins
-
-plugin_PROGRAMS =							\
-	xfce4-clipman-plugin
-
 xfce4_clipman_plugin_SOURCES =						\
-	clipman.h							\
-	clipman.c							\
 	clipman-dialogs.h						\
-	clipman-dialogs.c
+	clipman-dialogs.c						\
+	clipman.h							\
+	clipman.c
 
 xfce4_clipman_plugin_CFLAGS =						\
-	$(LIBXFCEGUI4_CFLAGS)						\
-	$(LIBXFCE4PANEL_CFLAGS)
+        -I$(top_srcdir)                                                 \
+        @LIBXFCE4PANEL_CFLAGS@                                          \
+        @LIBXFCE4UTIL_CFLAGS@                                           \
+        @LIBXFCEGUI4_CFLAGS@                                            \
+        -DPACKAGE_LOCALE_DIR=\"$(localedir)\"
 
 xfce4_clipman_plugin_LDADD =						\
-	$(LIBXFCE4PANEL_LIBS)						\
-	$(LIBXFCEGUI4_LIBS)
+        @LIBXFCE4PANEL_LIBS@                                            \
+        @LIBXFCE4UTIL_LIBS@                                             \
+        @LIBXFCEGUI4_LIBS@
 
-#
-# Desktop file
-#
-desktopdir = $(datadir)/xfce4/panel-plugins
 desktop_in_in_files = clipman.desktop.in.in
 desktop_in_files = $(desktop_in_in_files:.desktop.in.in=.desktop.in)
-%.desktop.in: %.desktop.in.in
-	sed -e "s,\@libexecdir\@,$(libexecdir),g" < $< > $@
+
+desktopdir = $(datadir)/xfce4/panel-plugins
 desktop_DATA = $(desktop_in_files:.desktop.in=.desktop)
 @INTLTOOL_DESKTOP_RULE@
 
+# get full path into .desktop file
+%.desktop.in: %.desktop.in.in
+	sed -e "s,\@libexecdir\@,$(libexecdir),g" < $< > $@
+
 EXTRA_DIST =								\
 	$(desktop_in_in_files)
 

Modified: xfce4-clipman-plugin/trunk/panel-plugin/clipman-dialogs.c
===================================================================
--- xfce4-clipman-plugin/trunk/panel-plugin/clipman-dialogs.c	2008-01-24 12:53:05 UTC (rev 3851)
+++ xfce4-clipman-plugin/trunk/panel-plugin/clipman-dialogs.c	2008-01-24 13:07:34 UTC (rev 3852)
@@ -1,4 +1,4 @@
-/*  $Id$
+/*  $Id: clipman-dialogs.c 2395 2007-01-17 17:42:53Z nick $
  *
  *  Copyright (c) 2006-2007 Nick Schermer <nick at xfce.org>
  *
@@ -21,351 +21,339 @@
 #include <config.h>
 #endif
 
-#include <string.h>
-#include <gtk/gtk.h>
-
-#include <libxfcegui4/libxfcegui4.h>
-#include <libxfce4panel/xfce-panel-plugin.h>
-
 #include "clipman.h"
 #include "clipman-dialogs.h"
 
-#define PLUGIN_WEBSITE "http://goodies.xfce.org/projects/panel-plugins/xfce4-clipman-plugin"
 
-typedef struct
-{
-    ClipmanPlugin *clipman;
 
-    GtkWidget     *ExitSave;
-    GtkWidget     *IgnoreSelection;
-    GtkWidget     *PreventEmpty;
+static void                     clipman_configure_response          (GtkWidget *dialog,
+                                                                     gint response,
+                                                                     ClipmanOptions *options);
+static void                     set_scale_to_spin                   (GtkWidget *scalewidget,
+                                                                     GtkWidget *spinwidget);
+static void                     set_spin_to_scale                   (GtkWidget *spinwidget,
+                                                                     GtkWidget *scalewidget);
+static void                     toggle_button                       (GtkWidget *button,
+                                                                     ClipmanOptions *options);
 
-    GtkWidget     *Behaviour;
 
-    GtkWidget     *ItemNumbers;
-    GtkWidget     *SeparateMenu;
 
-    GtkWidget     *HistorySize;
-    GtkWidget     *ItemChars;
-}
-ClipmanOptions;
-
-static void
-clipman_configure_response (GtkWidget      *dialog,
-                            int             response,
-                            ClipmanOptions *options)
+void
+clipman_configure_new (ClipmanPlugin *clipman)
 {
-    gboolean result;
+  GtkWidget      *dialog, *dialog_vbox, *frame, *button, *label;
+  GtkWidget      *vbox, *hbox, *notebook_vbox, *notebook;
+  ClipmanOptions *options;
+  GSList         *group;
 
-	if (response == GTK_RESPONSE_HELP)
-	{
-		/* show help */
-        result = g_spawn_command_line_async ("exo-open --launch WebBrowser " PLUGIN_WEBSITE, NULL);
+  options = panel_slice_new0 (ClipmanOptions);
+  options->clipman = clipman;
 
-        if (G_UNLIKELY (result == FALSE))
-            g_warning (_("Unable to open the following url: %s"), PLUGIN_WEBSITE);
+  xfce_panel_plugin_block_menu (clipman->panel_plugin);
 
-        return;
-	}
+  dialog = xfce_titled_dialog_new_with_buttons (_("Clipboard Manager"),
+												GTK_WINDOW (gtk_widget_get_toplevel (GTK_WIDGET (clipman->panel_plugin))),
+												GTK_DIALOG_DESTROY_WITH_PARENT | GTK_DIALOG_NO_SEPARATOR,
+												GTK_STOCK_HELP, GTK_RESPONSE_HELP,
+												GTK_STOCK_CLOSE, GTK_RESPONSE_OK,
+												NULL);
 
-    DBG("Destroy the dialog");
+  gtk_window_set_position (GTK_WINDOW (dialog), GTK_WIN_POS_CENTER);
+  gtk_window_set_icon_name (GTK_WINDOW (dialog), "xfce4-settings");
 
-    g_object_set_data (G_OBJECT (options->clipman->plugin), "dialog", NULL);
+  g_object_set_data (G_OBJECT (clipman->panel_plugin), "dialog", dialog);
 
-    if (gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (options->Behaviour)))
-        options->clipman->Behaviour = NORMAL;
-    else
-        options->clipman->Behaviour = STRICTLY;
+  dialog_vbox = GTK_DIALOG (dialog)->vbox;
 
-    if (options->clipman->HistoryItems != gtk_range_get_value (GTK_RANGE (options->HistorySize)))
-    {
-        options->clipman->HistoryItems   = gtk_range_get_value (GTK_RANGE (options->HistorySize));
-        clipman_check_array_len (options->clipman);
-    }
+  notebook = gtk_notebook_new ();
+  gtk_box_pack_start (GTK_BOX (dialog_vbox), notebook, FALSE, TRUE, 0);
+  gtk_container_set_border_width (GTK_CONTAINER (notebook), BORDER-3);
 
-    options->clipman->MenuCharacters = gtk_range_get_value (GTK_RANGE (options->ItemChars));
+  notebook_vbox = gtk_vbox_new (FALSE, 2);
+  gtk_container_add (GTK_CONTAINER (notebook), notebook_vbox);
 
-    clipman_save (options->clipman->plugin, options->clipman);
+  /**
+   * The general frame
+   **/
+  vbox = gtk_vbox_new (FALSE, 2);
 
-    clipman_remove_selection_clips (options->clipman);
+  frame = xfce_create_framebox_with_content (_("Configuration"), vbox);
+  gtk_container_set_border_width (GTK_CONTAINER (frame), BORDER);
+  gtk_box_pack_start (GTK_BOX (notebook_vbox), frame, FALSE, TRUE, 0);
 
-    xfce_panel_plugin_unblock_menu (options->clipman->plugin);
+  button = options->ExitSave = gtk_check_button_new_with_mnemonic (_("Save clipboard contents on _exit"));
+  gtk_box_pack_start (GTK_BOX (vbox), button, FALSE, FALSE, 0);
+  gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (button), clipman->clipman_clips->save_on_exit);
 
-    gtk_widget_destroy (dialog);
+  g_signal_connect (G_OBJECT (button), "toggled",
+					G_CALLBACK (toggle_button), options);
 
-    panel_slice_free (ClipmanOptions, options);
-}
+  button = options->IgnoreSelection = gtk_check_button_new_with_mnemonic (_("_Ignore selections"));
+  gtk_box_pack_start (GTK_BOX (vbox), button, FALSE, FALSE, 0);
+  gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (button), clipman->clipman_clips->ignore_primary);
 
-static void
-set_scale_to_spin (GtkWidget *scalewidget,
-                   GtkWidget *spinwidget)
-{
-    guint value;
-    value = gtk_range_get_value (GTK_RANGE (scalewidget));
-    gtk_spin_button_set_value (GTK_SPIN_BUTTON(spinwidget), value);
-}
+  g_signal_connect (G_OBJECT (button), "toggled",
+					G_CALLBACK (toggle_button), options);
 
-static void
-set_spin_to_scale (GtkWidget *spinwidget,
-                   GtkWidget *scalewidget)
-{
-    guint value;
-    value = gtk_spin_button_get_value_as_int (GTK_SPIN_BUTTON(spinwidget));
-    gtk_range_set_value (GTK_RANGE (scalewidget), value);
-}
+  button = options->PreventEmpty = gtk_check_button_new_with_mnemonic (_("Pre_vent empty clipboard"));
+  gtk_box_pack_start (GTK_BOX (vbox), button, FALSE, FALSE, 0);
+  gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (button), clipman->clipman_clips->prevent_empty);
 
-static void
-toggle_button (GtkWidget      *button,
-               ClipmanOptions *options)
-{
-    if (button == options->ExitSave)
-        options->clipman->ExitSave =
-           gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (button));
+  g_signal_connect (G_OBJECT (button), "toggled",
+					G_CALLBACK (toggle_button), options);
 
-    else if (button == options->IgnoreSelection)
-    {
-        options->clipman->IgnoreSelect =
-           gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (button));
+  label = gtk_label_new (_("<b>General</b>"));
+  gtk_frame_set_label_widget (GTK_FRAME (frame), label);
+  gtk_label_set_use_markup (GTK_LABEL (label), TRUE);
+  gtk_misc_set_padding (GTK_MISC (label), 2, 0);
 
-        if (options->clipman->IgnoreSelect)
-            gtk_widget_set_sensitive (options->SeparateMenu, FALSE);
-        else
-            gtk_widget_set_sensitive (options->SeparateMenu, TRUE);
-    }
-    else if (button == options->PreventEmpty)
-        options->clipman->PreventEmpty =
-           gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (button));
+  /**
+   * separate clipboards frame
+   **/
+  vbox = gtk_vbox_new (FALSE, 2);
 
-    else if (button == options->ItemNumbers)
-        options->clipman->ItemNumbers =
-           gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (button));
+  frame = xfce_create_framebox_with_content (_("Configuration"), vbox);
+  gtk_container_set_border_width (GTK_CONTAINER (frame), BORDER);
+  gtk_box_pack_start (GTK_BOX (notebook_vbox), frame, FALSE, TRUE, 0);
 
-    else if (button == options->SeparateMenu)
-        options->clipman->SeparateMenu =
-           gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (button));
-}
+  group = NULL;
 
-void
-clipman_configure (XfcePanelPlugin *plugin,
-                   ClipmanPlugin   *clipman)
-{
-    GtkWidget      *dialog, *dialog_vbox, *frame, *button, *label;
-    GtkWidget      *vbox, *hbox, *notebook_vbox, *notebook;
-    ClipmanOptions *options;
-    GSList         *group;
+  button = options->Behaviour = gtk_radio_button_new_with_mnemonic (group, _("Normal clipboard _management"));
+  gtk_box_pack_start (GTK_BOX (vbox), button, FALSE, FALSE, 0);
 
-    options = panel_slice_new0 (ClipmanOptions);
-    options->clipman = clipman;
+  gtk_radio_button_set_group (GTK_RADIO_BUTTON (button), group);
+  group = gtk_radio_button_get_group (GTK_RADIO_BUTTON (button));
 
-    xfce_panel_plugin_block_menu (clipman->plugin);
+  if(clipman->clipman_clips->behavior == NORMAL)
+	gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (button), TRUE);
 
-    dialog = xfce_titled_dialog_new_with_buttons (_("Clipboard Manager"),
-                                                  GTK_WINDOW (gtk_widget_get_toplevel (GTK_WIDGET (plugin))),
-                                                  GTK_DIALOG_DESTROY_WITH_PARENT | GTK_DIALOG_NO_SEPARATOR,
-                                                  GTK_STOCK_HELP, GTK_RESPONSE_HELP,
-                                                  GTK_STOCK_CLOSE, GTK_RESPONSE_OK,
-                                                  NULL);
+  button = gtk_radio_button_new_with_mnemonic (group, _("Strictly separate _both clipboards"));
+  gtk_box_pack_start (GTK_BOX (vbox), button, FALSE, FALSE, 0);
 
-    gtk_window_set_position (GTK_WINDOW (dialog), GTK_WIN_POS_CENTER);
-    gtk_window_set_icon_name (GTK_WINDOW (dialog), "xfce4-settings");
+  gtk_radio_button_set_group (GTK_RADIO_BUTTON (button), group);
+  group = gtk_radio_button_get_group (GTK_RADIO_BUTTON (button));
 
-    g_object_set_data (G_OBJECT (clipman->plugin), "dialog", dialog);
+  if(clipman->clipman_clips->behavior == STRICTLY)
+	gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (button), TRUE);
 
-    dialog_vbox = GTK_DIALOG (dialog)->vbox;
+  label = gtk_label_new (_("<b>Clipboard Behaviour</b>"));
+  gtk_frame_set_label_widget (GTK_FRAME (frame), label);
+  gtk_label_set_use_markup (GTK_LABEL (label), TRUE);
+  gtk_misc_set_padding (GTK_MISC (label), 2, 0);
 
-    notebook = gtk_notebook_new ();
-    gtk_box_pack_start (GTK_BOX (dialog_vbox), notebook, FALSE, TRUE, 0);
-    gtk_container_set_border_width (GTK_CONTAINER (notebook), BORDER-3);
+  /**
+   * Notebook label
+   **/
+  label = gtk_label_new (_("General"));
+  gtk_notebook_set_tab_label (GTK_NOTEBOOK (notebook), gtk_notebook_get_nth_page (GTK_NOTEBOOK (notebook), 0), label);
 
-    notebook_vbox = gtk_vbox_new (FALSE, 2);
-    gtk_container_add (GTK_CONTAINER (notebook), notebook_vbox);
+  notebook_vbox = gtk_vbox_new (FALSE, 2);
+  gtk_container_add (GTK_CONTAINER (notebook), notebook_vbox);
 
-    /**
-     * The general frame
-     **/
-    frame = gtk_frame_new (NULL);
-    gtk_box_pack_start (GTK_BOX (notebook_vbox), frame, FALSE, TRUE, 0);
-    gtk_container_set_border_width (GTK_CONTAINER (frame), BORDER-3);
+  /**
+   * Menu appearance frame
+   **/
+  vbox = gtk_vbox_new (FALSE, 2);
 
-    vbox = gtk_vbox_new (FALSE, 2);
-    gtk_container_add (GTK_CONTAINER (frame), vbox);
-    gtk_container_set_border_width (GTK_CONTAINER (vbox), BORDER);
+  frame = xfce_create_framebox_with_content (_("Configuration"), vbox);
+  gtk_container_set_border_width (GTK_CONTAINER (frame), BORDER);
+  gtk_box_pack_start (GTK_BOX (notebook_vbox), frame, FALSE, TRUE, 0);
 
-    button = options->ExitSave = gtk_check_button_new_with_mnemonic (_("Save clipboard contents on _exit"));
-    gtk_box_pack_start (GTK_BOX (vbox), button, FALSE, FALSE, 0);
-    gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (button), clipman->ExitSave);
+  button = options->ItemNumbers = gtk_check_button_new_with_mnemonic (_("_Show item numbers"));
+  gtk_box_pack_start (GTK_BOX (vbox), button, FALSE, FALSE, 0);
+  gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (button), clipman->menu_item_show_number);
 
-    g_signal_connect (G_OBJECT (button), "toggled",
-            G_CALLBACK (toggle_button), options);
+  g_signal_connect (G_OBJECT (button), "toggled",
+					G_CALLBACK (toggle_button), options);
 
-    button = options->IgnoreSelection = gtk_check_button_new_with_mnemonic (_("_Ignore selections"));
-    gtk_box_pack_start (GTK_BOX (vbox), button, FALSE, FALSE, 0);
-    gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (button), clipman->IgnoreSelect);
+  label = gtk_label_new (_("<b>Menu Appearance</b>"));
+  gtk_frame_set_label_widget (GTK_FRAME (frame), label);
+  gtk_label_set_use_markup (GTK_LABEL (label), TRUE);
+  gtk_misc_set_padding (GTK_MISC (label), 2, 0);
 
-    g_signal_connect (G_OBJECT (button), "toggled",
-            G_CALLBACK (toggle_button), options);
+  /**
+   * Call some functions
+   **/
 
-    button = options->PreventEmpty = gtk_check_button_new_with_mnemonic (_("Pre_vent empty clipboard"));
-    gtk_box_pack_start (GTK_BOX (vbox), button, FALSE, FALSE, 0);
-    gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (button), clipman->PreventEmpty);
+  toggle_button (options->IgnoreSelection, options);
 
-    g_signal_connect (G_OBJECT (button), "toggled",
-            G_CALLBACK (toggle_button), options);
+  /**
+   * Numbers frame
+   **/
+  vbox = gtk_vbox_new (FALSE, 2);
 
+  frame = xfce_create_framebox_with_content (_("Configuration"), vbox);
+  gtk_container_set_border_width (GTK_CONTAINER (frame), BORDER);
+  gtk_box_pack_start (GTK_BOX (notebook_vbox), frame, FALSE, TRUE, 0);
 
-    label = gtk_label_new (_("<b>General</b>"));
-    gtk_frame_set_label_widget (GTK_FRAME (frame), label);
-    gtk_label_set_use_markup (GTK_LABEL (label), TRUE);
-    gtk_misc_set_padding (GTK_MISC (label), 2, 0);
+  label = gtk_label_new (_("Clipboard history items:"));
+  gtk_box_pack_start (GTK_BOX (vbox), label, FALSE, FALSE, 0);
+  gtk_misc_set_alignment (GTK_MISC (label), 0, 0.5);
 
-    /**
-     * separate clipboards frame
-     **/
-    frame = gtk_frame_new (NULL);
-    gtk_box_pack_start (GTK_BOX (notebook_vbox), frame, FALSE, TRUE, 0);
-    gtk_container_set_border_width (GTK_CONTAINER (frame), BORDER-3);
+  hbox = gtk_hbox_new (FALSE, 0);
+  gtk_box_pack_start (GTK_BOX (vbox), hbox, TRUE, TRUE, 0);
 
-    vbox = gtk_vbox_new (FALSE, 2);
-    gtk_container_add (GTK_CONTAINER (frame), vbox);
-    gtk_container_set_border_width (GTK_CONTAINER (vbox), BORDER);
+  button = options->HistorySize = gtk_hscale_new (GTK_ADJUSTMENT (gtk_adjustment_new (clipman->clipman_clips->history_length, MINHISTORY, MAXHISTORY, 1, 5, 0)));
+  gtk_widget_show (button);
+  gtk_box_pack_start (GTK_BOX (hbox), button, TRUE, TRUE, 10);
+  gtk_scale_set_draw_value (GTK_SCALE (button), FALSE);
+  gtk_scale_set_digits (GTK_SCALE (button), 0);
 
-    group = NULL;
+  button = gtk_spin_button_new_with_range(MINHISTORY, MAXHISTORY, 1);
+  gtk_box_pack_start (GTK_BOX (hbox), button, FALSE, TRUE, 0);
+  gtk_spin_button_set_value(GTK_SPIN_BUTTON(button), clipman->clipman_clips->history_length);
 
-    button = options->Behaviour = gtk_radio_button_new_with_mnemonic (group, _("Normal clipboard _management"));
-    gtk_box_pack_start (GTK_BOX (vbox), button, FALSE, FALSE, 0);
+  /* Sync history widgets */
+  g_signal_connect (G_OBJECT (options->HistorySize), "value_changed",
+					G_CALLBACK (set_scale_to_spin), button);
 
-    gtk_radio_button_set_group (GTK_RADIO_BUTTON (button), group);
-    group = gtk_radio_button_get_group (GTK_RADIO_BUTTON (button));
+  g_signal_connect (G_OBJECT (button), "value_changed",
+					G_CALLBACK (set_spin_to_scale), options->HistorySize);
 
-    if(clipman->Behaviour == NORMAL)
-        gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (button), TRUE);
+  label = gtk_label_new (_("Menu item characters:"));
+  gtk_box_pack_start (GTK_BOX (vbox), label, FALSE, FALSE, 0);
+  gtk_misc_set_alignment (GTK_MISC (label), 0, 0.5);
 
-    button = gtk_radio_button_new_with_mnemonic (group, _("Strictly separate _both clipboards"));
-    gtk_box_pack_start (GTK_BOX (vbox), button, FALSE, FALSE, 0);
+  hbox = gtk_hbox_new (FALSE, 0);
+  gtk_box_pack_start (GTK_BOX (vbox), hbox, TRUE, TRUE, 0);
 
-    gtk_radio_button_set_group (GTK_RADIO_BUTTON (button), group);
-    group = gtk_radio_button_get_group (GTK_RADIO_BUTTON (button));
+  button = options->ItemChars = gtk_hscale_new (GTK_ADJUSTMENT (gtk_adjustment_new (clipman->menu_item_max_chars, MINCHARS, MAXCHARS, 1, 5, 0)));
+  gtk_box_pack_start (GTK_BOX (hbox), button, TRUE, TRUE, 10);
+  gtk_scale_set_draw_value (GTK_SCALE (button), FALSE);
+  gtk_scale_set_digits (GTK_SCALE (button), 0);
 
-    if(clipman->Behaviour == STRICTLY)
-        gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (button), TRUE);
+  button = gtk_spin_button_new_with_range(MINCHARS, MAXCHARS, 1);
+  gtk_box_pack_start (GTK_BOX (hbox), button, FALSE, TRUE, 0);
+  gtk_spin_button_set_value(GTK_SPIN_BUTTON(button), clipman->menu_item_max_chars);
 
-    label = gtk_label_new (_("<b>Clipboard Behaviour</b>"));
-    gtk_frame_set_label_widget (GTK_FRAME (frame), label);
-    gtk_label_set_use_markup (GTK_LABEL (label), TRUE);
-    gtk_misc_set_padding (GTK_MISC (label), 2, 0);
+  g_signal_connect (G_OBJECT (options->ItemChars), "value_changed",
+					G_CALLBACK (set_scale_to_spin), button);
 
-    /**
-     * Notebook label
-     **/
-    label = gtk_label_new (_("General"));
-    gtk_notebook_set_tab_label (GTK_NOTEBOOK (notebook), gtk_notebook_get_nth_page (GTK_NOTEBOOK (notebook), 0), label);
+  g_signal_connect (G_OBJECT (button), "value_changed",
+					G_CALLBACK (set_spin_to_scale), options->ItemChars);
 
-    notebook_vbox = gtk_vbox_new (FALSE, 2);
-    gtk_container_add (GTK_CONTAINER (notebook), notebook_vbox);
+  label = gtk_label_new (_("<b>Numbers</b>"));
+  gtk_frame_set_label_widget (GTK_FRAME (frame), label);
+  gtk_label_set_use_markup (GTK_LABEL (label), TRUE);
+  gtk_misc_set_padding (GTK_MISC (label), 4, 0);
 
-    /**
-     * Menu appearance frame
-     **/
-    frame = gtk_frame_new (NULL);
-    gtk_box_pack_start (GTK_BOX (notebook_vbox), frame, FALSE, TRUE, 0);
-    gtk_container_set_border_width (GTK_CONTAINER (frame), BORDER-3);
+  label = gtk_label_new (_("Appearance"));
+  gtk_notebook_set_tab_label (GTK_NOTEBOOK (notebook), gtk_notebook_get_nth_page (GTK_NOTEBOOK (notebook), 1), label);
 
-    vbox = gtk_vbox_new (FALSE, 2);
-    gtk_container_add (GTK_CONTAINER (frame), vbox);
-    gtk_container_set_border_width (GTK_CONTAINER (vbox), BORDER);
+  g_signal_connect (dialog, "response",
+				   G_CALLBACK (clipman_configure_response), options);
 
-    button = options->ItemNumbers = gtk_check_button_new_with_mnemonic (_("_Show item numbers"));
-    gtk_box_pack_start (GTK_BOX (vbox), button, FALSE, FALSE, 0);
-    gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (button), clipman->ItemNumbers);
+  gtk_widget_show_all (dialog);
+}
 
-    g_signal_connect (G_OBJECT (button), "toggled",
-            G_CALLBACK (toggle_button), options);
+static void
+clipman_configure_response (GtkWidget *dialog,
+                            gint response,
+                            ClipmanOptions *options)
+{
+  gboolean result;
 
-    button = options->SeparateMenu = gtk_check_button_new_with_mnemonic (_("Se_parate clipboards"));
-    gtk_box_pack_start (GTK_BOX (vbox), button, FALSE, FALSE, 0);
-    gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (button), clipman->SeparateMenu);
+  if (response == GTK_RESPONSE_HELP)
+	{
+	  /* show help */
+	  result = g_spawn_command_line_async ("exo-open --launch WebBrowser " PLUGIN_WEBSITE, NULL);
 
-    g_signal_connect (G_OBJECT (button), "toggled",
-            G_CALLBACK (toggle_button), options);
+	  if (G_UNLIKELY (result == FALSE))
+		g_warning (_("Unable to open the following url: %s"), PLUGIN_WEBSITE);
 
-    label = gtk_label_new (_("<b>Menu Appearance</b>"));
-    gtk_frame_set_label_widget (GTK_FRAME (frame), label);
-    gtk_label_set_use_markup (GTK_LABEL (label), TRUE);
-    gtk_misc_set_padding (GTK_MISC (label), 2, 0);
+	  return;
+	}
 
-    /**
-     * Call some functions
-     **/
+  DBG("Destroy the dialog");
 
-   toggle_button (options->IgnoreSelection, options);
+  g_object_set_data (G_OBJECT (options->clipman->panel_plugin), "dialog", NULL);
 
-    /**
-     * Numbers frame
-     **/
-    frame = gtk_frame_new (NULL);
-    gtk_box_pack_start (GTK_BOX (notebook_vbox), frame, FALSE, TRUE, 0);
-    gtk_container_set_border_width (GTK_CONTAINER (frame), BORDER-3);
+  /* Behavior */
+  if (gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (options->Behaviour)))
+	options->clipman->clipman_clips->behavior = NORMAL;
+  else
+	options->clipman->clipman_clips->behavior = STRICTLY;
 
-    vbox = gtk_vbox_new (FALSE, 2);
-    gtk_container_add (GTK_CONTAINER (frame), vbox);
-    gtk_container_set_border_width (GTK_CONTAINER (vbox), BORDER);
+  /* History length */
+  gint history_length = gtk_range_get_value (GTK_RANGE (options->HistorySize));
+  if (options->clipman->clipman_clips->history_length != history_length)
+    {
+      options->clipman->clipman_clips->history_length = history_length;
 
-    label = gtk_label_new (_("Clipboard history items:"));
-    gtk_box_pack_start (GTK_BOX (vbox), label, FALSE, FALSE, 0);
-    gtk_misc_set_alignment (GTK_MISC (label), 0, 0.5);
+      /* Free the overlap in the history */
+      ClipmanClip *clip;
+      gint length = g_slist_length (options->clipman->clipman_clips->history);
+      while (history_length < length--)
+        {
+          clip = (ClipmanClip *)(g_slist_last (options->clipman->clipman_clips->history)->data);
+          options->clipman->clipman_clips->history =
+            g_slist_remove (options->clipman->clipman_clips->history, clip);
 
-    hbox = gtk_hbox_new (FALSE, 0);
-    gtk_box_pack_start (GTK_BOX (vbox), hbox, TRUE, TRUE, 0);
+          g_free (clip->text);
+          g_free (clip->short_text);
+          g_slice_free (ClipmanClip, clip);
+        }
+    }
 
-    button = options->HistorySize = gtk_hscale_new (GTK_ADJUSTMENT (gtk_adjustment_new (clipman->HistoryItems, MINHISTORY, MAXHISTORY, 1, 5, 0)));
-    gtk_widget_show (button);
-    gtk_box_pack_start (GTK_BOX (hbox), button, TRUE, TRUE, 10);
-    gtk_scale_set_draw_value (GTK_SCALE (button), FALSE);
-    gtk_scale_set_digits (GTK_SCALE (button), 0);
+  /* Menu item max chars */
+  gint max_chars = gtk_range_get_value (GTK_RANGE (options->HistorySize));
+  if (options->clipman->menu_item_max_chars != max_chars)
+    {
+      options->clipman->menu_item_max_chars = gtk_range_get_value (GTK_RANGE (options->ItemChars));
 
-    button = gtk_spin_button_new_with_range(MINHISTORY, MAXHISTORY, 1);
-    gtk_box_pack_start (GTK_BOX (hbox), button, FALSE, TRUE, 0);
-    gtk_spin_button_set_value(GTK_SPIN_BUTTON(button), clipman->HistoryItems);
+      /* Invalidate the old clip->short_text */
+      gint i = 0;
+      ClipmanClip *clip;
+      while (NULL != (clip = (ClipmanClip *)g_slist_nth_data (options->clipman->clipman_clips->history, i++)))
+        {
+          g_free (clip->short_text);
+          clip->short_text = NULL;
+        }
+    }
 
-        /* Sync history widgets */
-    g_signal_connect (G_OBJECT (options->HistorySize), "value_changed",
-            G_CALLBACK (set_scale_to_spin), button);
+  xfce_panel_plugin_unblock_menu (options->clipman->panel_plugin);
 
-    g_signal_connect (G_OBJECT (button), "value_changed",
-            G_CALLBACK (set_spin_to_scale), options->HistorySize);
+  gtk_widget_destroy (dialog);
 
-    label = gtk_label_new (_("Menu item characters:"));
-    gtk_box_pack_start (GTK_BOX (vbox), label, FALSE, FALSE, 0);
-    gtk_misc_set_alignment (GTK_MISC (label), 0, 0.5);
+  panel_slice_free (ClipmanOptions, options);
+}
 
-    hbox = gtk_hbox_new (FALSE, 0);
-    gtk_box_pack_start (GTK_BOX (vbox), hbox, TRUE, TRUE, 0);
+static void
+set_scale_to_spin (GtkWidget *scalewidget,
+                   GtkWidget *spinwidget)
+{
+  guint value;
+  value = gtk_range_get_value (GTK_RANGE (scalewidget));
+  gtk_spin_button_set_value (GTK_SPIN_BUTTON (spinwidget), value);
+}
 
-    button = options->ItemChars = gtk_hscale_new (GTK_ADJUSTMENT (gtk_adjustment_new (clipman->MenuCharacters, MINCHARS, MAXCHARS, 1, 5, 0)));
-    gtk_box_pack_start (GTK_BOX (hbox), button, TRUE, TRUE, 10);
-    gtk_scale_set_draw_value (GTK_SCALE (button), FALSE);
-    gtk_scale_set_digits (GTK_SCALE (button), 0);
+static void
+set_spin_to_scale (GtkWidget *spinwidget,
+                   GtkWidget *scalewidget)
+{
+  guint value;
+  value = gtk_spin_button_get_value_as_int (GTK_SPIN_BUTTON (spinwidget));
+  gtk_range_set_value (GTK_RANGE (scalewidget), value);
+}
 
-    button = gtk_spin_button_new_with_range(MINCHARS, MAXCHARS, 1);
-    gtk_box_pack_start (GTK_BOX (hbox), button, FALSE, TRUE, 0);
-    gtk_spin_button_set_value(GTK_SPIN_BUTTON(button), clipman->MenuCharacters);
+static void
+toggle_button (GtkWidget *button,
+               ClipmanOptions *options)
+{
+  if (button == options->ExitSave)
+	options->clipman->clipman_clips->save_on_exit =
+	  gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (button));
 
-    g_signal_connect (G_OBJECT (options->ItemChars), "value_changed",
-            G_CALLBACK (set_scale_to_spin), button);
+  else if (button == options->IgnoreSelection)
+	options->clipman->clipman_clips->ignore_primary =
+	  gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (button));
 
-    g_signal_connect (G_OBJECT (button), "value_changed",
-            G_CALLBACK (set_spin_to_scale), options->ItemChars);
+  else if (button == options->PreventEmpty)
+	options->clipman->clipman_clips->prevent_empty =
+	  gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (button));
 
-    label = gtk_label_new (_("<b>Numbers</b>"));
-    gtk_frame_set_label_widget (GTK_FRAME (frame), label);
-    gtk_label_set_use_markup (GTK_LABEL (label), TRUE);
-    gtk_misc_set_padding (GTK_MISC (label), 4, 0);
-
-    label = gtk_label_new (_("Appearance"));
-    gtk_notebook_set_tab_label (GTK_NOTEBOOK (notebook), gtk_notebook_get_nth_page (GTK_NOTEBOOK (notebook), 1), label);
-
-    g_signal_connect(dialog, "response",
-        G_CALLBACK(clipman_configure_response), options);
-
-    gtk_widget_show_all (dialog);
+  else if (button == options->ItemNumbers)
+	options->clipman->menu_item_show_number =
+	  gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (button));
 }
+

Modified: xfce4-clipman-plugin/trunk/panel-plugin/clipman-dialogs.h
===================================================================
--- xfce4-clipman-plugin/trunk/panel-plugin/clipman-dialogs.h	2008-01-24 12:53:05 UTC (rev 3851)
+++ xfce4-clipman-plugin/trunk/panel-plugin/clipman-dialogs.h	2008-01-24 13:07:34 UTC (rev 3852)
@@ -1,4 +1,4 @@
-/*  $Id$
+/*  $Id: clipman-dialogs.h 2395 2007-01-17 17:42:53Z nick $
  *
  *  Copyright (c) 2006-2007 Nick Schermer <nick at xfce.org>
  *
@@ -22,8 +22,29 @@
 
 G_BEGIN_DECLS
 
+#define PLUGIN_WEBSITE "http://goodies.xfce.org/projects/panel-plugins/xfce4-clipman-plugin"
+
+typedef struct _ClipmanOptions      ClipmanOptions;
+
+struct _ClipmanOptions
+{
+  ClipmanPlugin        *clipman;
+
+  GtkWidget            *ExitSave;
+  GtkWidget            *IgnoreSelection;
+  GtkWidget            *PreventEmpty;
+
+  GtkWidget            *Behaviour;
+
+  GtkWidget            *ItemNumbers;
+  GtkWidget            *SeparateMenu;
+
+  GtkWidget            *HistorySize;
+  GtkWidget            *ItemChars;
+};
+
 void
-clipman_configure (XfcePanelPlugin *plugin, ClipmanPlugin *clipman);
+clipman_configure_new (ClipmanPlugin *clipman_plugin);
 
 G_END_DECLS
 

Modified: xfce4-clipman-plugin/trunk/panel-plugin/clipman.c
===================================================================
--- xfce4-clipman-plugin/trunk/panel-plugin/clipman.c	2008-01-24 12:53:05 UTC (rev 3851)
+++ xfce4-clipman-plugin/trunk/panel-plugin/clipman.c	2008-01-24 13:07:34 UTC (rev 3852)
@@ -1,6 +1,7 @@
 /*  $Id$
  *
  *  Copyright (c) 2006-2007 Nick Schermer <nick at xfce.org>
+ *  Copyright (c)      2007 Mike Massonnet <mmassonnet at xfce.org>
  *
  *  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
@@ -21,1091 +22,915 @@
 #include <config.h>
 #endif
 
-#include <string.h>
-#include <gtk/gtk.h>
-
-#include <libxfcegui4/libxfcegui4.h>
 #include <libxfce4util/libxfce4util.h>
-#include <libxfce4panel/xfce-panel-plugin.h>
 #include <libxfce4panel/xfce-panel-convenience.h>
 
 #include "clipman.h"
 #include "clipman-dialogs.h"
 
-/* The clipboards */
-static GtkClipboard *primaryClip;
-static GtkClipboard *defaultClip;
 
-/* Register the plugin */
-static void
-clipman_construct (XfcePanelPlugin *plugin);
 
-XFCE_PANEL_PLUGIN_REGISTER_EXTERNAL (clipman_construct);
+static void                     clipman_plugin_register             (XfcePanelPlugin *panel_plugin);
 
-static void
-clipman_free_clip (ClipmanClip *clip)
-{
-    g_free (clip->text);
-    g_free (clip->title);
+static ClipmanPlugin *          clipman_plugin_new                  (XfcePanelPlugin *panel_plugin);
 
-    panel_slice_free (ClipmanClip, clip);
+static void                     clipman_plugin_load_data            (ClipmanPlugin *clipman_plugin);
 
-    DBG ("Clip successfully freed");
-}
+static void                     clipman_plugin_save_data            (ClipmanPlugin *clipman_plugin);
 
-static void
-clipman_destroy_menu (GtkWidget     *menu,
-                      ClipmanPlugin *clipman)
-{
-    gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (clipman->button), FALSE);
+static void                     clipman_plugin_free                 (ClipmanPlugin *clipman_plugin);
 
-    gtk_widget_destroy (menu);
+static gboolean                 clipman_plugin_set_size             (ClipmanPlugin *clipman_plugin,
+                                                                     gint size);
+static gboolean                 clipman_plugin_button_pressed       (ClipmanPlugin *clipman_plugin,
+                                                                     GdkEventButton *event);
+static gchar *                  clipman_plugin_get_short_text       (ClipmanPlugin *clipman_plugin,
+                                                                     const gchar *text);
+static void                     clipman_plugin_menu_new             (ClipmanPlugin *clipman_plugin);
 
-    DBG ("Menu Destroyed");
-}
+static void                     clipman_plugin_menu_insert_clips    (ClipmanClip *clip,
+                                                                     ClipmanPlugin *clipman_plugin);
+static void                     clipman_plugin_menu_popup           (ClipmanPlugin *clipman_plugin);
 
-static gboolean
-clipman_clear (GtkWidget      *mi,
-               GdkEventButton *ev,
-               ClipmanPlugin  *clipman)
-{
-    ClipmanClip *clip;
+static void                     clipman_plugin_menu_position        (GtkMenu *menu,
+                                                                     gint *x,
+                                                                     gint *y,
+                                                                     gboolean *push_in,
+                                                                     gpointer user_data);
+static void                     clipman_plugin_menu_destroy         (ClipmanPlugin *clipman_plugin);
 
-    if (xfce_confirm (_("Are you sure you want to clear the history?"),
-	              "gtk-yes",
-                      NULL))
-    {
-        gtk_clipboard_clear (primaryClip);
-	gtk_clipboard_clear (defaultClip);
+static void                     clipman_plugin_menu_item_activate   (GtkWidget *widget,
+                                                                     ClipmanPlugin *clipman_plugin);
+static gboolean                 clipman_plugin_menu_item_pressed    (GtkWidget *widget,
+                                                                     GdkEventButton *event,
+                                                                     ClipmanPlugin *clipman_plugin);
 
-        while (clipman->clips->len > 0)
-        {
-            clip = g_ptr_array_index (clipman->clips, 0);
-            g_ptr_array_remove (clipman->clips, clip);
-            clipman_free_clip (clip);
-        }
-    }
 
-    /* 'Save' the empty clipboard */
-    clipman_save (clipman->plugin, clipman);
 
-    return FALSE;
-}
+static ClipmanClips *           clipman_clips_new                   ();
 
-void
-clipman_check_array_len (ClipmanPlugin *clipman)
-{
-    ClipmanClip *clip;
+static void                     clipman_clips_load_data             (ClipmanClips *clipman_clips);
 
-    DBG ("Checking Array Length");
+static void                     clipman_clips_save_data             (ClipmanClips *clipman_clips);
 
-    while (clipman->clips->len > clipman->HistoryItems)
-    {
-        clip = g_ptr_array_index (clipman->clips, 0);
-        g_ptr_array_remove (clipman->clips, clip);
-        clipman_free_clip (clip);
+static void                     clipman_clips_clear_history         (ClipmanClips *clipman_clips);
 
-        DBG("A clip have been removed");
-    }
-}
+static void                     clipman_clips_restore_empty         (ClipmanClips *clipman_clips,
+                                                                     ClipboardType type);
+static gboolean                 clipman_clips_check_clipboard       (ClipmanClips *clipman_clips);
 
+static inline void              clipman_clips_delete                (ClipmanClips *clipman_clips,
+                                                                     ClipmanClip *clip);
+static void                     clipman_clips_add                   (ClipmanClips *clipman_clips,
+                                                                     gchar *text,
+                                                                     ClipboardType type);
+static gint                     clipman_clips_compare               (ClipmanClip *one,
+                                                                     ClipmanClip *two);
+static gint                     clipman_clips_compare_with_type     (ClipmanClip *one,
+                                                                     ClipmanClip *two);
 
 
-static gchar *
-clipman_create_title (gchar *txt,
-                      gint   length)
-{
-    gchar *s, *t, *u, *buf;
-    gint   i;
 
-    /* rough string copy */
-    s = g_strndup (txt, length*8 + 8);
 
-    if (G_UNLIKELY (!s))
-        return NULL;
+XFCE_PANEL_PLUGIN_REGISTER_EXTERNAL (clipman_plugin_register);
 
-    if (!g_utf8_validate (s, -1, NULL))
-    {
-        DBG ("Title is not utf8 complaint, we're going to convert it");
+static void
+clipman_plugin_register (XfcePanelPlugin *panel_plugin)
+{
+  xfce_textdomain (GETTEXT_PACKAGE, PACKAGE_LOCALE_DIR, "UTF-8");
 
-        u = g_locale_to_utf8 (s, -1, NULL, NULL, NULL);
-        g_free (s);
-        s = u;
+  ClipmanPlugin *clipman_plugin = clipman_plugin_new (panel_plugin);
+  g_return_if_fail (G_LIKELY (NULL != clipman_plugin));
 
-        /* Check the title again */
-        if (!g_utf8_validate (s, -1, NULL))
-        {
-            DBG ("Title is still not utf8 complaint, we going to drop this clip");
-            g_free (s);
-            return NULL;
-        }
-    }
+  g_signal_connect_swapped (panel_plugin,
+                            "save",
+                            G_CALLBACK (clipman_plugin_save_data),
+                            clipman_plugin);
+  g_signal_connect_swapped (panel_plugin,
+                            "free-data",
+                            G_CALLBACK (clipman_plugin_free),
+                            clipman_plugin);
+  g_signal_connect_swapped (panel_plugin,
+                            "size-changed",
+                            G_CALLBACK (clipman_plugin_set_size),
+                            clipman_plugin);
+  g_signal_connect_swapped (panel_plugin,
+                            "configure-plugin",
+                            G_CALLBACK (clipman_configure_new),
+                            clipman_plugin);
 
-    /* create string length */
-    buf = g_malloc(length*6); /* max length of utf8 char is 6 */
-    g_utf8_strncpy (buf, s, length);
-    g_free (s);
-    s = buf;
+  xfce_panel_plugin_menu_show_configure (panel_plugin);
+  xfce_panel_plugin_add_action_widget (panel_plugin, clipman_plugin->button);
 
-    /* remove tabs and newlines */
-    /* this works when the string is utf8-valid */
-    i = 0;
-    while (s[i] != '\0')
-    {
-        if (s[i] == '\n' || s[i] == '\r' || s[i] == '\t')
-            s[i] = ' ';
-        i++;
-    }
-
-    /* remove html characters */
-    t = g_markup_escape_text (s, -1);
-    g_free (s);
-
-    return t;
+  gtk_widget_show_all (clipman_plugin->button);
 }
 
-void
-clipman_remove_selection_clips (ClipmanPlugin *clipman)
+static ClipmanPlugin *
+clipman_plugin_new (XfcePanelPlugin *panel_plugin)
 {
-    ClipmanClip *clip;
-    guint        i;
+  ClipmanPlugin *clipman_plugin = g_slice_new0 (ClipmanPlugin);
+  clipman_plugin->panel_plugin = panel_plugin;
+  clipman_plugin->clipman_clips = clipman_clips_new ();
 
-    if (!clipman->IgnoreSelect)
-        return;
+  clipman_plugin->button = xfce_create_panel_toggle_button ();
+  clipman_plugin->icon = gtk_image_new ();
 
-    DBG ("Cleaning up all selection clips");
+  gtk_container_add (GTK_CONTAINER (clipman_plugin->button), clipman_plugin->icon);
+  gtk_container_add (GTK_CONTAINER (panel_plugin), clipman_plugin->button);
 
-    for (i = clipman->clips->len; i--; )
-    {
-        clip = g_ptr_array_index (clipman->clips, i);
+  g_signal_connect_swapped (clipman_plugin->button,
+                            "button_press_event",
+                            G_CALLBACK (clipman_plugin_button_pressed),
+                            clipman_plugin);
 
-        if (clip->fromtype == PRIMARY)
-        {
-             g_ptr_array_remove (clipman->clips, clip);
-             clipman_free_clip (clip);
-        }
-    }
+  clipman_plugin_load_data (clipman_plugin);
+
+  return clipman_plugin;
 }
 
 static void
-clipman_add_clip (ClipmanPlugin *clipman,
-                  gchar         *txt,
-                  ClipboardType  type)
+clipman_plugin_load_data (ClipmanPlugin *clipman_plugin)
 {
-    ClipmanClip *new_clip;
+  XfceRc               *rc;
+  gchar                *file;
 
-    if (G_LIKELY (txt != NULL) &&
-        G_LIKELY (strcmp (txt, "")))
-    {
-        new_clip = panel_slice_new0 (ClipmanClip);
+  file = xfce_resource_save_location (XFCE_RESOURCE_CONFIG, "xfce4/panel/clipman.rc", TRUE);
+  g_return_if_fail (G_LIKELY (NULL != file));
+  rc = xfce_rc_simple_open (file, FALSE);
+  g_free (file);
 
-        new_clip->title = clipman_create_title (txt,
-                                                clipman->MenuCharacters);
+  xfce_rc_set_group (rc, "Properties");
 
-	/* No valid title could be created, drop it... */
-	if (new_clip->title == NULL)
-	{
-	    g_free (new_clip);
-	    return;
-	}
+  clipman_plugin->menu_item_show_number     = xfce_rc_read_bool_entry   (rc, "ItemNumbers", DEFITEMNUMBERS);
+  clipman_plugin->menu_item_max_chars       = xfce_rc_read_int_entry    (rc, "MenuCharacters", DEFCHARS);
 
-	new_clip->text     = g_strdup (txt);
-        new_clip->fromtype = type;
+  if (clipman_plugin->menu_item_max_chars > MAXCHARS)
+    clipman_plugin->menu_item_max_chars = MAXCHARS;
+  else if (clipman_plugin->menu_item_max_chars < MINCHARS)
+    clipman_plugin->menu_item_max_chars = MINCHARS;
 
-        g_ptr_array_add (clipman->clips, new_clip);
-
-        DBG("Added clip %d of %d", clipman->clips->len, clipman->HistoryItems);
-    }
+  xfce_rc_close (rc);
 }
 
-static gboolean
-clipman_exists (ClipmanPlugin *clipman,
-                gchar         *txt,
-                ClipboardType  type)
+static void
+clipman_plugin_save_data (ClipmanPlugin *clipman_plugin)
 {
-    guint        i;
-    ClipmanClip *clip;
+  XfceRc               *rc;
+  gchar                *file;
 
-    /* Walk through the array backwards, because
-     * if the text exists, this will probably be the newest */
+  file = xfce_resource_save_location (XFCE_RESOURCE_CONFIG, "xfce4/panel/clipman.rc", TRUE);
+  g_return_if_fail (G_LIKELY (NULL != file));
+  rc = xfce_rc_simple_open (file, FALSE);
+  g_free (file);
 
-    for (i = clipman->clips->len; i--; )
-    {
-        clip = g_ptr_array_index (clipman->clips, i);
+  xfce_rc_set_group (rc, "Properties");
 
-        if (G_LIKELY ((clip->text != NULL) &&
-                      (strcmp(clip->text, txt) == 0))
-           )
-        {
-            switch (clipman->Behaviour)
-            {
-                case NORMAL:
-                    if (type == DEFAULT &&
-                        clip->fromtype == PRIMARY)
-                            clip->fromtype = DEFAULT;
+  xfce_rc_write_bool_entry  (rc, "ItemNumbers",     clipman_plugin->menu_item_show_number);
+  xfce_rc_write_int_entry   (rc, "MenuCharacters",  clipman_plugin->menu_item_max_chars);
 
-                    return TRUE;
+  xfce_rc_close (rc);
 
-                case STRICTLY:
-                    if (type == clip->fromtype)
-                        return TRUE;
+  clipman_clips_save_data (clipman_plugin->clipman_clips);
+}
 
-                    return FALSE;
-            }
-        }
-    }
+static void
+clipman_plugin_free (ClipmanPlugin *clipman_plugin)
+{
+  /* There are no resources to free that won't be after we quit the plugin */
+  gtk_main_quit ();
+}
 
-    return FALSE;
+static gboolean
+clipman_plugin_set_size (ClipmanPlugin *clipman_plugin,
+                         gint size)
+{
+  gtk_widget_set_size_request (GTK_WIDGET (clipman_plugin->panel_plugin), size, size);
+  size = size - (2 * MAX (clipman_plugin->button->style->xthickness,
+                          clipman_plugin->button->style->xthickness));
+  GdkPixbuf *pixbuf = xfce_themed_icon_load ("gtk-paste", size);
+  gtk_image_set_from_pixbuf (GTK_IMAGE (clipman_plugin->icon), pixbuf);
+  g_object_unref (G_OBJECT (pixbuf));
+
+  return TRUE;
 }
 
 static gboolean
-clipman_item_clicked (GtkWidget      *mi,
-                      GdkEventButton *ev,
-                      ClipmanAction  *action)
+clipman_plugin_button_pressed (ClipmanPlugin *clipman_plugin,
+                               GdkEventButton *event)
 {
-    gchar *dtext, *ptext;
+  if (G_LIKELY (event->button != 1 || event->state & GDK_CONTROL_MASK))
+    return FALSE;
 
-    if (ev->button == 1 && action->clipman->Behaviour == STRICTLY)
-    {
-        DBG("Clip copied to his own clipboard (STRICTLY)");
+  clipman_plugin_menu_popup (clipman_plugin);
 
-        if (action->clip->fromtype == DEFAULT)
-	{
-	    gtk_clipboard_clear (defaultClip);
-            gtk_clipboard_set_text (defaultClip, action->clip->text, -1);
-	}
+  return TRUE;
+}
 
-        if (action->clip->fromtype == PRIMARY)
-	{
-	    gtk_clipboard_clear (primaryClip);
-            gtk_clipboard_set_text (primaryClip, action->clip->text, -1);
-	}
-    }
-    else if (ev->button == 1)
-    {
-        gtk_clipboard_clear (defaultClip);
-        gtk_clipboard_set_text (defaultClip, action->clip->text, -1);
-	DBG ("Clip copied to default clipboard");
+static gchar *
+clipman_plugin_get_short_text (ClipmanPlugin *clipman_plugin,
+                               const gchar *text)
+{
+  gchar                *short_text, *tmp = NULL;
+  const gchar          *offset;
+  gint                  max_length;
 
-	if (!action->clipman->IgnoreSelect)
-	{
-	    gtk_clipboard_clear (primaryClip);
-	    gtk_clipboard_set_text (primaryClip, action->clip->text, -1);
-	    DBG ("Clip copied to primary clipboard");
-	}
-    }
-    else if (ev->button == 3)
-    {
-        if (xfce_confirm (_("Are you sure you want to remove this clip from the history?"),
-	              "gtk-yes", NULL))
-        {
-            DBG ("Removed the selected clip from the History");
+  g_return_val_if_fail (G_LIKELY (NULL != text), NULL);
+  g_return_val_if_fail (G_LIKELY (g_utf8_validate (text, -1, NULL)), NULL);
 
-	    dtext = gtk_clipboard_wait_for_text (defaultClip);
-            if (dtext && !strcmp(dtext, action->clip->text))
-	    {
-                gtk_clipboard_clear (defaultClip);
-		gtk_clipboard_set_text (defaultClip, "", -1);
-	    }
-	    g_free (dtext);
+  short_text = g_strstrip (g_strdup (text));
 
-	    ptext = gtk_clipboard_wait_for_text (primaryClip);
-            if (ptext && !strcmp(ptext, action->clip->text))
-	    {
-                gtk_clipboard_clear (primaryClip);
-		gtk_clipboard_set_text (primaryClip, "", -1);
-	    }
-            g_free (ptext);
+  /* Shorten */
+  max_length = clipman_plugin->menu_item_max_chars;
+  if (g_utf8_strlen (short_text, -1) > max_length)
+    {
+      offset = g_utf8_offset_to_pointer (short_text, max_length);
+      tmp = g_strndup (short_text, offset - short_text);
+      g_free (short_text);
 
-            g_ptr_array_remove (action->clipman->clips, action->clip);
-            clipman_free_clip (action->clip);
-        }
+      short_text = g_strconcat (tmp, "\342\200\246", NULL); /* Ellipsis U+2026 */
+      g_free (tmp);
     }
 
-    panel_slice_free (ClipmanAction, action);
+  /* Cleanup */
+  tmp = g_strdelimit (short_text, "\n\r\t", ' ');
+  short_text = g_markup_escape_text (tmp, -1);
+  g_free (tmp);
 
-    return FALSE;
+  return short_text;
 }
 
-static GtkWidget *
-clipman_create_menuitem (ClipmanAction *action,
-                         guint          width,
-                         guint          number,
-                         gboolean       bold)
+static void
+clipman_plugin_menu_new (ClipmanPlugin *clipman_plugin)
 {
-    GtkWidget *mi, *label;
-    gchar     *title, *string_num;
+  GtkWidget            *mi = NULL;
 
-    if (action->clipman->ItemNumbers)
+  clipman_plugin->menu = gtk_menu_new ();
+
+  /* Add clipboard entries */
+  if (g_slist_length (clipman_plugin->clipman_clips->history) > 0)
+    g_slist_foreach (clipman_plugin->clipman_clips->history,
+                     (GFunc)clipman_plugin_menu_insert_clips,
+                     clipman_plugin);
+  else
     {
-        if (number < 10)
-            string_num = g_strdup_printf("<tt><span size=\"smaller\">%d. </span></tt> ", number);
-        else
-            string_num = g_strdup_printf("<tt><span size=\"smaller\">%d.</span></tt> ", number);
+      mi = gtk_menu_item_new_with_label (_("< Clipboard Empty >"));
+      gtk_widget_set_sensitive (mi, FALSE);
+      gtk_menu_shell_append (GTK_MENU_SHELL (clipman_plugin->menu), mi);
     }
-    else
-    {
-        string_num = g_strdup ("");
-    }
 
-    if (bold)
-        title = g_strdup_printf("%s<b>%s</b>", string_num, action->clip->title);
-    else
-        title = g_strdup_printf("%s%s", string_num, action->clip->title);
+  /* Prepend title */
+  mi = gtk_separator_menu_item_new ();
+  gtk_menu_shell_prepend (GTK_MENU_SHELL (clipman_plugin->menu), mi);
 
-    g_free (string_num);
+  mi = gtk_menu_item_new_with_label  ("");
+  gtk_misc_set_alignment (GTK_MISC (GTK_BIN (mi)->child), 0.5, 0.5);
+  gchar *title = g_strdup_printf ("<b>%s</b>", _("Clipman History"));
+  gtk_label_set_markup (GTK_LABEL (GTK_BIN (mi)->child), title);
+  gtk_widget_set_sensitive (mi, FALSE);
+  gtk_menu_shell_prepend (GTK_MENU_SHELL (clipman_plugin->menu), mi);
 
+  /* Append clear history */
+  mi = gtk_separator_menu_item_new ();
+  gtk_menu_shell_append (GTK_MENU_SHELL (clipman_plugin->menu), mi);
 
-    label = gtk_label_new (title);
-    gtk_label_set_use_markup (GTK_LABEL (label), TRUE);
-    gtk_label_set_single_line_mode (GTK_LABEL (label), TRUE);
-    gtk_label_set_ellipsize (GTK_LABEL (label), PANGO_ELLIPSIZE_END);
-    gtk_label_set_max_width_chars (GTK_LABEL (label), width);
+  mi = gtk_menu_item_new_with_label (_("Clear History"));
+  gtk_menu_shell_append (GTK_MENU_SHELL (clipman_plugin->menu), mi);
+  g_signal_connect_swapped (mi,
+                            "activate",
+                            G_CALLBACK (clipman_clips_clear_history),
+                            clipman_plugin->clipman_clips);
 
-    g_free (title);
+  /* Do the rest */
+  g_signal_connect_swapped (clipman_plugin->menu,
+                            "deactivate",
+                            G_CALLBACK (clipman_plugin_menu_destroy),
+                            clipman_plugin);
 
-    mi = gtk_menu_item_new ();
-    gtk_container_add (GTK_CONTAINER (mi), label);
-    gtk_accel_label_set_accel_widget (GTK_ACCEL_LABEL (label), mi);
-    gtk_widget_show (label);
+  gtk_menu_attach_to_widget (GTK_MENU (clipman_plugin->menu),
+                             clipman_plugin->button,
+                             NULL);
+  xfce_panel_plugin_register_menu (clipman_plugin->panel_plugin,
+                                   GTK_MENU (clipman_plugin->menu));
 
-    return mi;
+  gtk_widget_show_all (clipman_plugin->menu);
 }
 
 static void
-clipman_clicked_separated (GtkWidget     *menu,
-                           ClipmanPlugin *clipman)
+clipman_plugin_menu_insert_clips (ClipmanClip *clip,
+                                  ClipmanPlugin *clipman_plugin)
 {
-    gchar         *ptext, *dtext;
-    guint          i, j;
-    ClipmanAction *action = NULL;
-    ClipmanClip   *clip;
-    GtkWidget     *mi;
+  static gint           i = 0, j = 0;
+  static ClipmanClip   *clip_default = NULL, *clip_primary = NULL, *clip_last = NULL;
+  static gboolean       clip_default_found = FALSE, clip_primary_found = FALSE;
+  gchar                *text = NULL, *bold = NULL;
+  gint                  a = -1, b = -1;
+  GtkWidget            *mi;
 
-    /* Default Clips */
-    dtext = gtk_clipboard_wait_for_text (defaultClip);
-    j = 0;
+  g_return_if_fail (G_LIKELY (NULL != clip));
 
-    for (i = clipman->clips->len; i--; )
-    {
-        clip = g_ptr_array_index (clipman->clips, i);
+  /* Generate a short text */
+  if (G_UNLIKELY (NULL == clip->short_text))
+    clip->short_text = clipman_plugin_get_short_text (clipman_plugin, clip->text);
 
-        if (clip->fromtype == DEFAULT)
-        {
-            j++;
+  /* Generate the menu item text */
+  if (clipman_plugin->menu_item_show_number && clipman_plugin->clipman_clips->behavior == STRICTLY)
+    text = g_strdup_printf ("%d. %s", (clip->type == PRIMARY) ? i+1 : j+1, clip->short_text);
+  else if (clipman_plugin->menu_item_show_number)
+    text = g_strdup_printf ("%d. %s", i+1, clip->short_text);
+  else
+    text = g_strdup (clip->short_text);
 
-            action = panel_slice_new0 (ClipmanAction);
-            action->clipman = clipman;
-            action->clip = clip;
+  /* Get current clipboards */
+  if (G_UNLIKELY (NULL == clip_default))
+    {
+      clip_default = g_slice_new0 (ClipmanClip);
+      clip_primary = g_slice_new0 (ClipmanClip);
+      clip_default->text = gtk_clipboard_wait_for_text (clipman_plugin->clipman_clips->default_clipboard);
+      clip_primary->text = gtk_clipboard_wait_for_text (clipman_plugin->clipman_clips->primary_clipboard);
+      clip_default->type = DEFAULT;
+      clip_primary->type = PRIMARY;
+      if (G_UNLIKELY (NULL == clip_default->text))
+        clip_default->text = g_strdup ("");
+      if (G_UNLIKELY (NULL == clip_primary->text))
+        clip_primary->text = g_strdup ("");
+    }
 
-            if (dtext != NULL                 &&
-                G_LIKELY (clip->text != NULL) &&
-                strcmp(clip->text, dtext) == 0)
+  /* Check if the clip matches the clipboards */
+  if (!clip_default_found || !clip_primary_found)
+    {
+      switch (clipman_plugin->clipman_clips->behavior)
+        {
+        case STRICTLY:
+          /* Check with default clipboard */
+          a = clipman_clips_compare_with_type (clip, clip_default);
+          if (a == 0)
+            clip_default_found = TRUE;
+          /* Check with primary clipboard */
+          else
             {
-                mi = clipman_create_menuitem (action, clipman->MenuCharacters,
-                                              j, TRUE);
-		g_free (dtext);
-		dtext = NULL;
+              b = clipman_clips_compare_with_type (clip, clip_primary);
+              if (b == 0)
+                clip_primary_found = TRUE;
             }
-            else
-            {
-                mi = clipman_create_menuitem (action, clipman->MenuCharacters,
-                                              j, FALSE);
-            }
+          break;
 
-            g_signal_connect (G_OBJECT(mi), "button_release_event",
-                    G_CALLBACK(clipman_item_clicked), action);
+        default:
+        case NORMAL:
+          a = clipman_clips_compare (clip, clip_default);
+          if (a != 0)
+            b = clipman_clips_compare (clip, clip_primary);
+          if (a == 0 || b == 0)
+            clip_default_found = clip_primary_found = TRUE;
+          break;
+        }
 
-            gtk_menu_shell_append (GTK_MENU_SHELL (menu), mi);
+      /* Set text in bold */
+      if (a == 0 || b == 0)
+        {
+          bold = g_strconcat ("<b>", text, "</b>", NULL);
+          g_free (text);
+          text = bold;
         }
     }
 
-    g_free (dtext);
+  /* Create the menu item */
+  mi = gtk_menu_item_new_with_label ("");
+  g_object_set_data (G_OBJECT (mi), "index", GINT_TO_POINTER (i+j));
+  gtk_label_set_markup (GTK_LABEL (GTK_BIN (mi)->child), text);
+  g_free (text);
 
-    if (j == 0)
+  /* Connect signals */
+  g_signal_connect (mi,
+                    "activate",
+                    G_CALLBACK (clipman_plugin_menu_item_activate),
+                    clipman_plugin);
+  g_signal_connect (mi,
+                    "button_press_event",
+                    G_CALLBACK (clipman_plugin_menu_item_pressed),
+                    clipman_plugin);
+
+  /* Insert in the menu */
+  switch (clipman_plugin->clipman_clips->behavior)
     {
-        mi = gtk_menu_item_new_with_label (_("< Default History Empty >"));
-        gtk_widget_set_sensitive (mi, FALSE);
-        gtk_menu_shell_append (GTK_MENU_SHELL (menu), mi);
+    case STRICTLY:
+      /* Insert primary clipboard before default clipboard */
+      if (clip->type == PRIMARY && !clipman_plugin->clipman_clips->ignore_primary)
+        {
+          gtk_menu_shell_insert (GTK_MENU_SHELL (clipman_plugin->menu), mi, i);
+          i++;
+        }
+      /* Append default clipboard */
+      else
+        {
+          gtk_menu_shell_append (GTK_MENU_SHELL (clipman_plugin->menu), mi);
+          j++;
+        }
+      break;
+
+    default:
+    case NORMAL:
+      /* Append */
+      gtk_menu_shell_append (GTK_MENU_SHELL (clipman_plugin->menu), mi);
+      i++;
+      break;
     }
 
-    /* Primairy Clips */
-    mi = gtk_separator_menu_item_new ();
-    gtk_widget_set_sensitive (mi, FALSE);
-    gtk_menu_shell_append (GTK_MENU_SHELL (menu), mi);
+  /* Get the last clip in the history */
+  if (G_UNLIKELY (NULL == clip_last))
+    clip_last = (ClipmanClip *)(g_slist_last (clipman_plugin->clipman_clips->history)->data);
 
-    ptext = gtk_clipboard_wait_for_text (primaryClip);
-    j = 0;
-
-    for (i = clipman->clips->len; i--; )
+  /* Check if the clip matches the last clip */
+  if (clip == clip_last)
     {
-        clip = g_ptr_array_index (clipman->clips, i);
-
-        if (clip->fromtype == PRIMARY)
+      if (clipman_plugin->clipman_clips->behavior == STRICTLY)
         {
-            j++;
+          /* Check if a clipboard was empty */
+          if (!clipman_plugin->clipman_clips->ignore_primary)
+            {
+              if (i == 0)
+                {
+                  mi = gtk_menu_item_new_with_label (_("< Selection History Empty >"));
+                  gtk_widget_set_sensitive (mi, FALSE);
+                  gtk_menu_shell_insert (GTK_MENU_SHELL (clipman_plugin->menu), mi, i++);
+                }
 
-            action = panel_slice_new0 (ClipmanAction);
-            action->clipman = clipman;
-            action->clip = clip;
+              mi = gtk_separator_menu_item_new ();
+              gtk_menu_shell_insert (GTK_MENU_SHELL (clipman_plugin->menu), mi, i);
+            }
 
-            if (ptext != NULL                 &&
-                G_LIKELY (clip->text != NULL) &&
-                strcmp(clip->text, ptext) == 0)
+          if (j == 0)
             {
-                mi = clipman_create_menuitem (action, clipman->MenuCharacters,
-                                              j, TRUE);
-                g_free (ptext);
-		ptext = NULL;
+              mi = gtk_menu_item_new_with_label (_("< Default History Empty >"));
+              gtk_widget_set_sensitive (mi, FALSE);
+              gtk_menu_shell_append (GTK_MENU_SHELL (clipman_plugin->menu), mi);
             }
-            else
-            {
-                mi = clipman_create_menuitem (action, clipman->MenuCharacters,
-                                              j, FALSE);
-            }
-
-            g_signal_connect (G_OBJECT(mi), "button_release_event",
-                    G_CALLBACK(clipman_item_clicked), action);
-
-            gtk_menu_shell_append (GTK_MENU_SHELL (menu), mi);
         }
-    }
 
-    g_free (ptext);
+      /* Free memory */
+      g_free (clip_default->text);
+      g_free (clip_primary->text);
+      g_slice_free (ClipmanClip, clip_default);
+      g_slice_free (ClipmanClip, clip_primary);
 
-    if (j == 0)
-    {
-        mi = gtk_menu_item_new_with_label (_("< Selection History Empty >"));
-        gtk_widget_set_sensitive (mi, FALSE);
-        gtk_menu_shell_append (GTK_MENU_SHELL (menu), mi);
+      /* Unset static variables */
+      clip_default = clip_primary = clip_last = NULL;
+      clip_default_found = clip_primary_found = FALSE;
+      i = j = 0;
     }
+}
 
-    mi = gtk_separator_menu_item_new ();
-    gtk_widget_set_sensitive (mi, FALSE);
-    gtk_menu_shell_append (GTK_MENU_SHELL (menu), mi);
+static void
+clipman_plugin_menu_popup (ClipmanPlugin *clipman_plugin)
+{
+  if (gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (clipman_plugin->button)) == TRUE)
+    return;
 
-    mi = gtk_menu_item_new_with_label (_("Clear History"));
-    gtk_menu_shell_append (GTK_MENU_SHELL (menu), mi);
-
-    g_signal_connect (G_OBJECT (mi), "button_release_event",
-        G_CALLBACK (clipman_clear), clipman);
+  TRACE ("Set button active");
+  gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (clipman_plugin->button), TRUE);
+  TRACE ("Create new menu");
+  clipman_plugin_menu_new (clipman_plugin);
+  TRACE ("Display menu");
+  /* if the menu doesn't popup, the next popup will be a bit of b0rked */
+  gtk_menu_popup (GTK_MENU (clipman_plugin->menu),
+                  NULL,
+                  NULL,
+                  (GtkMenuPositionFunc)clipman_plugin_menu_position,
+                  clipman_plugin->panel_plugin,
+                  0,
+                  gtk_get_current_event_time ());
 }
 
 static void
-clipman_clicked_not_separated (GtkWidget     *menu,
-                               ClipmanPlugin *clipman)
+clipman_plugin_menu_position (GtkMenu *menu,
+                              gint *x,
+                              gint *y,
+                              gboolean *push_in,
+                              gpointer user_data)
 {
-    gchar         *ptext, *dtext;
-    guint          i;
-    ClipmanAction *action = NULL;
-    ClipmanClip   *clip;
-    GtkWidget     *mi;
+  XfcePanelPlugin      *panel_plugin = user_data;
+  GtkWidget            *button;
+  GtkRequisition        requisition;
+  GtkOrientation        orientation;
+     
+  g_return_if_fail (GTK_IS_MENU (menu));
+  button = gtk_menu_get_attach_widget (menu);
+  g_return_if_fail (GTK_IS_WIDGET (button));
 
-    ptext = gtk_clipboard_wait_for_text (primaryClip);
-    dtext = gtk_clipboard_wait_for_text (defaultClip);
+  orientation = xfce_panel_plugin_get_orientation (panel_plugin);
+  gtk_widget_size_request (GTK_WIDGET (menu), &requisition);
+  gdk_window_get_origin (button->window, x, y);
 
-    for (i = clipman->clips->len; i--;)
+  switch (orientation)
     {
-        clip = g_ptr_array_index (clipman->clips, i);
+    case GTK_ORIENTATION_HORIZONTAL:
+      if (*y + button->allocation.height + requisition.height > gdk_screen_height ())
+        /* Show menu above */
+        *y -= requisition.height;
+      else
+        /* Show menu below */
+        *y += button->allocation.height;
 
-        action = panel_slice_new0 (ClipmanAction);
-        action->clipman = clipman;
-        action->clip = clip;
-
-        if (dtext != NULL                 &&
-            G_LIKELY (clip->text != NULL) &&
-            strcmp(clip->text, dtext) == 0)
-        {
-            mi = clipman_create_menuitem (action, clipman->MenuCharacters,
-                                          clipman->clips->len-i, TRUE);
-            g_free (dtext);
-	    dtext = NULL;
-        }
-        else if (ptext != NULL                 &&
-                 G_LIKELY (clip->text != NULL) &&
-                 strcmp(clip->text, ptext) == 0)
-        {
-            mi = clipman_create_menuitem (action, clipman->MenuCharacters,
-                                          clipman->clips->len-i, TRUE);
-            g_free (ptext);
-	    ptext = NULL;
-        }
-        else
-        {
-            mi = clipman_create_menuitem (action, clipman->MenuCharacters,
-                                          clipman->clips->len-i, FALSE);
-        }
-
-        g_signal_connect (G_OBJECT(mi), "button_release_event",
-                G_CALLBACK(clipman_item_clicked), action);
-
-        gtk_menu_shell_append (GTK_MENU_SHELL (menu), mi);
+      if (*x + requisition.width > gdk_screen_width ())
+        /* Adjust horizontal position */
+        *x = gdk_screen_width () - requisition.width;
+      break;
+  
+    case GTK_ORIENTATION_VERTICAL:
+      if (*x + button->allocation.width + requisition.width > gdk_screen_width ())
+        /* Show menu on the right */ 
+        *x -= requisition.width;
+      else
+        /* Show menu on the left */
+        *x += button->allocation.width;
+          
+      if (*y + requisition.height > gdk_screen_height ())
+        /* Adjust vertical position */
+        *y = gdk_screen_height () - requisition.height;
+      break;
+          
+    default:
+      break;
     }
+}
 
-    g_free (ptext);
-    g_free (dtext);
-
-    mi = gtk_separator_menu_item_new ();
-    gtk_widget_set_sensitive (mi, FALSE);
-    gtk_menu_shell_append (GTK_MENU_SHELL (menu), mi);
-
-    mi = gtk_menu_item_new_with_label (_("Clear History"));
-    gtk_menu_shell_append (GTK_MENU_SHELL (menu), mi);
-
-    g_signal_connect (G_OBJECT (mi), "button_release_event",
-        G_CALLBACK (clipman_clear), clipman);
+static void
+clipman_plugin_menu_destroy (ClipmanPlugin *clipman_plugin)
+{
+  if (G_LIKELY (GTK_IS_MENU (clipman_plugin->menu)))
+    gtk_menu_detach (GTK_MENU (clipman_plugin->menu));
+  gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (clipman_plugin->button), FALSE);
 }
 
 static void
-clipman_position_menu (GtkMenu       *menu,
-                       int           *x,
-                       int           *y,
-                       gboolean      *push_in,
-                       ClipmanPlugin *clipman)
+clipman_plugin_menu_item_activate (GtkWidget *widget,
+                                   ClipmanPlugin *clipman_plugin)
 {
-    GtkRequisition  req;
-    GdkScreen      *screen;
-    GdkRectangle    geom;
-    gint            num;
+  gint                  i;
+  ClipmanClip          *clip = NULL;
 
-    gtk_widget_size_request (GTK_WIDGET (menu), &req);
+  g_return_if_fail (G_LIKELY (GTK_IS_WIDGET (widget)));
+  i = GPOINTER_TO_INT (g_object_get_data (G_OBJECT (widget), "index"));
+  clip = (ClipmanClip *)g_slist_nth_data (clipman_plugin->clipman_clips->history, i);
+  g_return_if_fail (G_LIKELY (NULL != clip));
 
-    gdk_window_get_origin (GTK_WIDGET (clipman->plugin)->window, x, y);
+  DBG ("Copy `%s' to clipboard", clip->text);
 
-    switch (xfce_panel_plugin_get_screen_position(clipman->plugin))
+  switch (clipman_plugin->clipman_clips->behavior)
     {
-        case XFCE_SCREEN_POSITION_SW_H:
-        case XFCE_SCREEN_POSITION_S:
-        case XFCE_SCREEN_POSITION_SE_H:
-            DBG("Bottom");
-            *y -= req.height;
-            break;
+    default:
+    case NORMAL:
+      gtk_clipboard_set_text (clipman_plugin->clipman_clips->default_clipboard, clip->text, -1);
+      if (!clipman_plugin->clipman_clips->ignore_primary)
+        gtk_clipboard_set_text (clipman_plugin->clipman_clips->primary_clipboard, clip->text, -1);
+      break;
 
-        case XFCE_SCREEN_POSITION_NW_H:
-        case XFCE_SCREEN_POSITION_N:
-        case XFCE_SCREEN_POSITION_NE_H:
-            DBG("Top");
-            *y += clipman->button->allocation.height;
-            break;
-
-        case XFCE_SCREEN_POSITION_NW_V:
-        case XFCE_SCREEN_POSITION_W:
-        case XFCE_SCREEN_POSITION_SW_V:
-            DBG("Left");
-            *x += clipman->button->allocation.width;
-            *y += clipman->button->allocation.height - req.height;
-            break;
-
-        case XFCE_SCREEN_POSITION_NE_V:
-        case XFCE_SCREEN_POSITION_E:
-        case XFCE_SCREEN_POSITION_SE_V:
-            DBG("Right");
-            *x -= req.width;
-            *y += clipman->button->allocation.height - req.height;
-            break;
-
-        case XFCE_SCREEN_POSITION_FLOATING_H:
-        case XFCE_SCREEN_POSITION_FLOATING_V:
-        case XFCE_SCREEN_POSITION_NONE:
-            DBG("Floating");
-            gdk_display_get_pointer(gtk_widget_get_display(GTK_WIDGET(clipman->plugin)),
-                NULL, x, y, NULL);
+    case STRICTLY:
+      if (clip->type == PRIMARY)
+        gtk_clipboard_set_text (clipman_plugin->clipman_clips->primary_clipboard, clip->text, -1);
+      else
+        gtk_clipboard_set_text (clipman_plugin->clipman_clips->default_clipboard, clip->text, -1);
+      break;
     }
-
-    screen = gtk_widget_get_screen (clipman->button);
-    num = gdk_screen_get_monitor_at_window (screen, clipman->button->window);
-    gdk_screen_get_monitor_geometry (screen, num, &geom);
-
-    if (*x > geom.x + geom.width - req.width)
-        *x = geom.x + geom.width - req.width;
-    if (*x < geom.x)
-        *x = geom.x;
-
-    if (*y > geom.y + geom.height - req.height)
-        *y = geom.y + geom.height - req.height;
-    if (*y < geom.y)
-        *y = geom.y;
 }
 
 static gboolean
-clipman_clicked (GtkWidget      *button,
-                 GdkEventButton *ev,
-                 ClipmanPlugin  *clipman)
+clipman_plugin_menu_item_pressed (GtkWidget *widget,
+                                  GdkEventButton *event,
+                                  ClipmanPlugin *clipman_plugin)
 {
-    GtkWidget *mi;
-    GtkWidget *menu;
-    gchar     *title;
+  g_return_val_if_fail (G_LIKELY (GTK_IS_WIDGET (widget)), FALSE);
 
-    if (ev->button != 1)
-	return FALSE;
-
-    gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (clipman->button), TRUE);
-
-    menu = gtk_menu_new ();
-
-    title = g_strdup_printf("<span weight=\"bold\">%s</span>", _("Clipman History"));
-    mi = gtk_menu_item_new_with_label  ("");
-    gtk_label_set_markup(GTK_LABEL(GTK_BIN(mi)->child), title);
-    gtk_widget_set_sensitive (mi, FALSE);
-    gtk_menu_shell_append (GTK_MENU_SHELL (menu), mi);
-
-    mi = gtk_separator_menu_item_new ();
-    gtk_widget_set_sensitive (mi, FALSE);
-    gtk_menu_shell_append (GTK_MENU_SHELL (menu), mi);
-
-    if (clipman->SeparateMenu  &&
-        !clipman->IgnoreSelect &&
-        G_LIKELY (clipman->clips->len > 0))
+  /* Delete item */
+  if (event->button == 3)
     {
-        clipman_clicked_separated (menu, clipman);
-    }
-    else if (G_LIKELY (clipman->clips->len > 0))
-    {
-        clipman_clicked_not_separated (menu, clipman);
-    }
-    else
-    {
-        mi = gtk_menu_item_new_with_label (_("< Clipboard Empty >"));
-        gtk_widget_set_sensitive (mi, FALSE);
-        gtk_menu_shell_append (GTK_MENU_SHELL (menu), mi);
-    }
+      ClipmanClips *clipman_clips = clipman_plugin->clipman_clips;
+      gint i = GPOINTER_TO_INT (g_object_get_data (G_OBJECT (widget), "index"));
+      ClipmanClip *clip = (ClipmanClip *)g_slist_nth_data (clipman_clips->history, i);
+      g_return_val_if_fail (G_LIKELY (NULL != clip), TRUE);
 
-    gtk_widget_show_all (menu);
+      GtkWidget *dialog =
+        gtk_message_dialog_new (NULL,
+                                GTK_DIALOG_MODAL,
+                                GTK_MESSAGE_QUESTION,
+                                GTK_BUTTONS_YES_NO,
+                                _("Are you sure you want to remove this clip from the history?"));
+      gint result = gtk_dialog_run (GTK_DIALOG (dialog));
+      gtk_widget_destroy (dialog);
+      if (G_UNLIKELY (result != GTK_RESPONSE_YES))
+        return TRUE;
 
-    /* Also destroy the menu items when nothing is clicked */
-    g_signal_connect (G_OBJECT(menu), "deactivate",
-        G_CALLBACK(clipman_destroy_menu), clipman);
+      DBG ("Delete `%s' from clipboard (%d)", clip->text, clip->type);
 
-    gtk_menu_popup (GTK_MENU (menu), NULL, NULL,
-                        (GtkMenuPositionFunc) clipman_position_menu,
-                        clipman, 0,
-                        gtk_get_current_event_time ());
-
-    return TRUE;
-}
-
-static void
-clipman_restore_empty (ClipmanPlugin *clipman,
-                       ClipboardType  type)
-{
-    guint        i;
-    ClipmanClip *clip;
-
-    if (clipman->Behaviour == STRICTLY &&
-        G_LIKELY (clipman->clips->len > 0))
-    {
-        /* Walk through the array till a clip of it's own
-         * type is found, then past it in the clipboard */
-        for (i = clipman->clips->len; i--;)
+      /* TODO Check current clipboard (write _get_current()? / set widget data "current" = TRUE?) */
+      switch (clipman_clips->behavior)
         {
-            clip = g_ptr_array_index (clipman->clips, i);
+        case STRICTLY:
+          if (clip->type == PRIMARY)
+            gtk_clipboard_set_text (clipman_clips->primary_clipboard, "", -1);
+          else
+            gtk_clipboard_set_text (clipman_clips->default_clipboard, "", -1);
 
-            if (clip->fromtype == type)
-            {
-                switch (type)
-                {
-                    case PRIMARY:
-                        gtk_clipboard_set_text(primaryClip, clip->text, -1);
-                        break;
-                    case DEFAULT:
-                        gtk_clipboard_set_text(defaultClip, clip->text, -1);
-                        break;
-                }
-
-                DBG("Clipboard restored with a clip from same type");
-
-                break;
-            }
+        default:
+        case NORMAL:
+          gtk_clipboard_set_text (clipman_clips->default_clipboard, "", -1);
+          gtk_clipboard_set_text (clipman_clips->primary_clipboard, "", -1);
+          break;
         }
-    }
-    else if (clipman->clips->len > 0)
-    {
-        /* Grap the latest clip and paste it in the clipboard */
-        clip = g_ptr_array_index (clipman->clips, (clipman->clips->len-1));
 
-        switch (type)
-        {
-            case PRIMARY:
-                gtk_clipboard_set_text(primaryClip, clip->text, -1);
-                break;
-            case DEFAULT:
-                gtk_clipboard_set_text(defaultClip, clip->text, -1);
-                break;
-        }
+	  clipman_clips_delete (clipman_clips, clip);
 
-        DBG("Last clip added");
+      return TRUE;
     }
+
+  return FALSE;
 }
 
-static gboolean
-clipman_check (ClipmanPlugin *clipman)
-{
-    gchar           *ptext = NULL, *dtext;
-    GdkModifierType  state;
 
-    /* We ignore the selection clipboard entirely if you've activated this in the options dialog */
-    if (!clipman->IgnoreSelect)
-    {
-	/* Get mouse button information */
-	gdk_window_get_pointer(NULL, NULL, NULL, &state);
 
-        ptext = gtk_clipboard_wait_for_text (primaryClip);
 
-        if (clipman->PreventEmpty && ptext == NULL)
-        {
-            clipman_restore_empty (clipman, PRIMARY);
-        }
-        else if (ptext != NULL               &&
-                 !(state & GDK_BUTTON1_MASK) &&
-                 !clipman_exists (clipman, ptext, PRIMARY))
-        {
-            DBG("Item added from primary clipboard");
-            clipman_add_clip (clipman, ptext, PRIMARY);
-            clipman_check_array_len (clipman);
-        }
+static ClipmanClips *
+clipman_clips_new ()
+{
+  ClipmanClips *clipman_clips = g_slice_new0 (ClipmanClips);
 
-        g_free (ptext);
-    }
+  clipman_clips->default_clipboard = gtk_clipboard_get (GDK_SELECTION_CLIPBOARD);
+  clipman_clips->primary_clipboard = gtk_clipboard_get (GDK_SELECTION_PRIMARY);
 
-    dtext = gtk_clipboard_wait_for_text (defaultClip);
+  clipman_clips->history = NULL;
 
-    /* Check default clipboard */
-    if (clipman->PreventEmpty && dtext == NULL)
-    {
-        clipman_restore_empty (clipman, DEFAULT);
-    }
-    else if (G_LIKELY (dtext != NULL) &&
-	     !clipman_exists (clipman, dtext, DEFAULT))
-    {
-        DBG("Item added from default clipboard");
-        clipman_add_clip (clipman, dtext, DEFAULT);
-        clipman_check_array_len (clipman);
-    }
+  clipman_clips_load_data (clipman_clips);
 
-    g_free (dtext);
+  clipman_clips->timeout =
+    g_timeout_add_full (G_PRIORITY_LOW,
+                        TIMER_INTERVAL,
+                        (GSourceFunc)clipman_clips_check_clipboard,
+                        clipman_clips,
+                        (GDestroyNotify)NULL);
 
-    return TRUE;
+  return clipman_clips;
 }
 
 static void
-clipman_reset_timeout (ClipmanPlugin *clipman)
+clipman_clips_load_data (ClipmanClips *clipman_clips)
 {
-    if (!(clipman->killTimeout))
-    {
-        if (clipman->TimeoutId != 0)
-            g_source_remove (clipman->TimeoutId);
+  XfceRc               *rc;
+  gchar                *file;
 
-        clipman->TimeoutId = g_timeout_add_full (G_PRIORITY_LOW,
-                                                 TIMER_INTERVAL,
-                                                 (GSourceFunc) clipman_check,
-                                                 clipman,
-                                                 (GDestroyNotify) clipman_reset_timeout);
-    }
-}
+  file = xfce_resource_save_location (XFCE_RESOURCE_CONFIG, "xfce4/panel/clipman.rc", TRUE);
+  g_return_if_fail (G_LIKELY (NULL != file));
+  rc = xfce_rc_simple_open (file, FALSE);
+  g_free (file);
 
-void
-clipman_save (XfcePanelPlugin *plugin,
-              ClipmanPlugin   *clipman)
-{
-    XfceRc      *rc;
-    gchar       *file;
-    guint        i;
-    gchar        name[13];
-    ClipmanClip *clip;
+  xfce_rc_set_group (rc, "Properties");
 
-    DBG("Saving clipman settings");
+  clipman_clips->behavior       = xfce_rc_read_int_entry    (rc, "Behaviour", NORMAL);
+  clipman_clips->history_length = xfce_rc_read_int_entry    (rc, "HistoryItems", DEFHISTORY);
+  clipman_clips->save_on_exit   = xfce_rc_read_bool_entry   (rc, "ExitSave", DEFEXITSAVE);
+  clipman_clips->ignore_primary = xfce_rc_read_bool_entry   (rc, "IgnoreSelect", DEFIGNORESELECT);
+  clipman_clips->prevent_empty  = xfce_rc_read_bool_entry   (rc, "PreventEmpty", DEFPREVENTEMPTY);
 
-    file = xfce_resource_save_location (XFCE_RESOURCE_CONFIG, "xfce4/panel/clipman.rc", TRUE);
+  if (clipman_clips->history_length > MAXHISTORY)
+    clipman_clips->history_length = MAXHISTORY;
+  if (clipman_clips->history_length < MINHISTORY)
+    clipman_clips->history_length = MINHISTORY;
 
-    if (G_UNLIKELY (!file))
-        return;
+  xfce_rc_set_group (rc, "Clips");
 
-    rc = xfce_rc_simple_open (file, FALSE);
-    g_free (file);
+  gint clips_length = xfce_rc_read_int_entry (rc, "ClipsLen", 0);
+  if (clips_length > MAXHISTORY)
+    clips_length = MAXHISTORY;
 
-    /* Save the preferences */
-    xfce_rc_set_group (rc, "Properties");
-
-    xfce_rc_write_bool_entry (rc, "ExitSave",     clipman->ExitSave);
-    xfce_rc_write_bool_entry (rc, "IgnoreSelect", clipman->IgnoreSelect);
-    xfce_rc_write_bool_entry (rc, "PreventEmpty", clipman->PreventEmpty);
-
-    switch (clipman->Behaviour)
+  if (clipman_clips->save_on_exit && clips_length > 0)
     {
-        case NORMAL:
-            xfce_rc_write_int_entry (rc, "Behaviour", 1);
-            break;
-        case STRICTLY:
-            xfce_rc_write_int_entry (rc, "Behaviour", 2);
-            break;
-    }
+      DBG ("Restoring the clipboard");
 
-    xfce_rc_write_bool_entry (rc, "ItemNumbers",  clipman->ItemNumbers);
-    xfce_rc_write_bool_entry (rc, "SeparateMenu", clipman->SeparateMenu);
+      gint              i;
+      gchar             name[13];
+      gchar            *text = NULL; /* We use this allocation so no free() */
+      ClipboardType     type;
 
-    xfce_rc_write_int_entry (rc, "HistoryItems",   clipman->HistoryItems);
-    xfce_rc_write_int_entry (rc, "MenuCharacters", clipman->MenuCharacters);
-
-    /* Remove old content and create a new one */
-    xfce_rc_delete_group (rc, "Clips", TRUE );
-
-    if (clipman->ExitSave &&
-        clipman->clips->len > 0
-       )
-    {
-        DBG("Saving the clipboard history");
-
-        xfce_rc_set_group (rc, "Clips");
-        xfce_rc_write_int_entry (rc, "ClipsLen", clipman->clips->len);
-
-        for (i = 0; i < clipman->clips->len; ++i)
+      for (i = clips_length - 1; i >= 0; i--)
         {
-            clip = g_ptr_array_index (clipman->clips, i);
-
-            g_snprintf (name, 13, "clip_%d_text", i);
-            xfce_rc_write_entry (rc, name, clip->text);
-
-            g_snprintf (name, 13, "clip_%d_from", i);
-            if (clip->fromtype == PRIMARY)
-                xfce_rc_write_int_entry (rc, name, 0);
-            else
-                xfce_rc_write_int_entry (rc, name, 1);
+          g_snprintf (name, 13, "clip_%d_text", i);
+          text = g_strdup (xfce_rc_read_entry (rc, name, ""));
+          g_snprintf (name, 13, "clip_%d_from", i);
+          type = (ClipboardType)xfce_rc_read_int_entry (rc, name, 0);
+          clipman_clips_add (clipman_clips, text, type);
         }
     }
 
-    xfce_rc_close (rc);
+  xfce_rc_close (rc);
 }
 
 static void
-clipman_read (ClipmanPlugin *clipman)
+clipman_clips_save_data (ClipmanClips *clipman_clips)
 {
-    XfceRc      *rc;
-    gchar       *file, *value;
-    guint        type, i, clipslen;
-    gchar        name[13];
+  XfceRc               *rc;
+  gchar                *file;
 
-    /* Because Clipman is unique, we use 1 config file */
-    /*
-    file = xfce_panel_plugin_save_location (clipman->plugin, FALSE);
-    DBG("Read from file: %s", file);
-    */
+  file = xfce_resource_save_location (XFCE_RESOURCE_CONFIG, "xfce4/panel/clipman.rc", TRUE);
+  g_return_if_fail (G_LIKELY (NULL != file));
+  rc = xfce_rc_simple_open (file, FALSE);
+  g_free (file);
 
-    file = xfce_resource_save_location (XFCE_RESOURCE_CONFIG, "xfce4/panel/clipman.rc", TRUE);
+  xfce_rc_set_group (rc, "Properties");
 
-    if (G_UNLIKELY (!file))
-        return;
+  xfce_rc_write_bool_entry  (rc, "ExitSave",        clipman_clips->save_on_exit);
+  xfce_rc_write_int_entry   (rc, "Behaviour",       clipman_clips->behavior);
+  xfce_rc_write_int_entry   (rc, "HistoryItems",    clipman_clips->history_length);
+  xfce_rc_write_bool_entry  (rc, "IgnoreSelect",    clipman_clips->ignore_primary);
+  xfce_rc_write_bool_entry  (rc, "PreventEmpty",    clipman_clips->prevent_empty);
 
-    rc = xfce_rc_simple_open (file, FALSE);
-    g_free (file);
+  xfce_rc_delete_group (rc, "Clips", TRUE);
 
-    xfce_rc_set_group (rc, "Properties");
-
-    clipman->ExitSave         = xfce_rc_read_bool_entry (rc, "ExitSave",     DEFEXITSAVE);
-    clipman->IgnoreSelect     = xfce_rc_read_bool_entry (rc, "IgnoreSelect", DEFIGNORESELECT);
-    clipman->PreventEmpty     = xfce_rc_read_bool_entry (rc, "PreventEmpty", DEFPREVENTEMPTY);
-
-    switch (xfce_rc_read_int_entry (rc, "Behaviour", DEFBEHAVIOUR))
+  if (clipman_clips->save_on_exit && g_slist_length (clipman_clips->history) > 0)
     {
-        case 1:
-            clipman->Behaviour = NORMAL;
-            DBG ("Behaviour = NORMAL");
-            break;
-        case 2:
-            clipman->Behaviour = STRICTLY;
-            DBG ("Behaviour = STRICTLY");
-            break;
-    }
+      DBG ("Saving the clipboard history");
 
-    clipman->ItemNumbers      = xfce_rc_read_bool_entry (rc, "ItemNumbers",    DEFITEMNUMBERS);
-    clipman->SeparateMenu     = xfce_rc_read_bool_entry (rc, "SeparateMenu",   DEFSEPMENU);
+      ClipmanClip      *clip;
+      gint              i = 0;
+      gchar             name[13];
 
-    clipman->HistoryItems     = xfce_rc_read_int_entry  (rc, "HistoryItems",   DEFHISTORY);
-    clipman->MenuCharacters   = xfce_rc_read_int_entry  (rc, "MenuCharacters", DEFCHARS);
+      xfce_rc_set_group (rc, "Clips");
+      xfce_rc_write_int_entry (rc, "ClipsLen", g_slist_length (clipman_clips->history));
 
-    if (clipman->HistoryItems > MAXHISTORY)
-        clipman->HistoryItems = MAXHISTORY;
-    if (clipman->HistoryItems < MINHISTORY)
-        clipman->HistoryItems = MINHISTORY;
-
-    if (clipman->MenuCharacters > MAXCHARS)
-        clipman->MenuCharacters = MAXCHARS;
-    if (clipman->MenuCharacters < MINCHARS)
-        clipman->MenuCharacters = MINCHARS;
-
-    xfce_rc_set_group (rc, "Clips");
-    clipslen = xfce_rc_read_int_entry (rc, "ClipsLen", 0);
-
-    if (clipslen > MAXHISTORY)
-        clipslen = MAXHISTORY;
-
-    if (clipman->ExitSave &&
-        clipslen > 0
-       )
-    {
-        DBG("Restoring the clipboard");
-
-        for (i = 0; i < clipslen; ++i)
+      while (NULL != (clip = g_slist_nth_data (clipman_clips->history, i)))
         {
-            g_snprintf (name, 13, "clip_%d_text", i);
-            value = g_strdup (xfce_rc_read_entry (rc, name, ""));
-
-            g_snprintf (name, 13, "clip_%d_from", i);
-            type = xfce_rc_read_int_entry (rc, name, 0);
-
-            if (type == 0)
-                clipman_add_clip (clipman, value, PRIMARY);
-            else
-                clipman_add_clip (clipman, value, DEFAULT);
-
-	    g_free (value);
+          g_snprintf (name, 13, "clip_%d_text", i);
+          xfce_rc_write_entry (rc, name, clip->text);
+          g_snprintf (name, 13, "clip_%d_from", i);
+          xfce_rc_write_int_entry (rc, name, clip->type);
+		  i++;
         }
     }
 
-    xfce_rc_close (rc);
+  xfce_rc_close (rc);
 }
 
-static ClipmanPlugin *
-clipman_new (XfcePanelPlugin *plugin)
+static void
+clipman_clips_clear_history (ClipmanClips *clipman_clips)
 {
-    ClipmanPlugin *clipman;
-    clipman = panel_slice_new0 (ClipmanPlugin);
+  gint                  i = 0;
+  ClipmanClip          *clip;
 
-    clipman->clips = g_ptr_array_new ();
-    clipman->plugin = plugin;
+  GtkWidget *dialog =
+    gtk_message_dialog_new (NULL,
+                            GTK_DIALOG_MODAL,
+                            GTK_MESSAGE_QUESTION,
+                            GTK_BUTTONS_YES_NO,
+                            _("Are you sure you want to clear the history?"));
+  gint result = gtk_dialog_run (GTK_DIALOG (dialog));
+  gtk_widget_destroy (dialog);
+  if (G_UNLIKELY (result != GTK_RESPONSE_YES))
+    return;
 
-    clipman->tooltip = gtk_tooltips_new ();
-    g_object_ref (G_OBJECT (clipman->tooltip));
+  while (NULL != (clip = (ClipmanClip *)g_slist_nth_data (clipman_clips->history, i++)))
+    {
+      g_free (clip->text);
+      g_free (clip->short_text);
+      g_slice_free (ClipmanClip, clip);
+    }
 
-    /* Load Settings */
-    clipman_read (clipman);
+  g_slist_free (clipman_clips->history);
+  clipman_clips->history = NULL;
 
-    /* Create panel widgets */
-    clipman->button = xfce_create_panel_toggle_button ();
-    gtk_widget_show (clipman->button);
+  gtk_clipboard_set_text (clipman_clips->default_clipboard, "", -1);
+  gtk_clipboard_set_text (clipman_clips->primary_clipboard, "", -1);
+}
 
-    clipman->icon = gtk_image_new ();
-    gtk_widget_show (clipman->icon);
-    gtk_container_add (GTK_CONTAINER (clipman->button), clipman->icon);
+static void
+clipman_clips_restore_empty (ClipmanClips *clipman_clips,
+                             ClipboardType type)
+{
+  if (G_UNLIKELY (g_slist_length (clipman_clips->history) == 0))
+    return;
 
-    gtk_tooltips_set_tip (GTK_TOOLTIPS(clipman->tooltip),
-                          clipman->button, _("Clipboard Manager"),
-                          NULL);
+  gint i = 0;
+  ClipmanClip *clip = (ClipmanClip *)g_slist_nth_data (clipman_clips->history, i++);
+  g_return_if_fail (G_LIKELY (NULL != clip));
 
-    g_signal_connect(clipman->button, "button_press_event",
-            G_CALLBACK(clipman_clicked), clipman);
+  switch (clipman_clips->behavior)
+    {
+    case STRICTLY:
+      while (G_LIKELY (NULL != clip && clip->type != type))
+        clip = (ClipmanClip *)g_slist_nth_data (clipman_clips->history, i++);
 
-    /* Start the clipman_check function */
-    clipman->TimeoutId = g_timeout_add_full(G_PRIORITY_LOW,
-                                            TIMER_INTERVAL,
-                                            (GSourceFunc) clipman_check,
-                                            clipman,
-                                            (GDestroyNotify) clipman_reset_timeout);
+      if (G_UNLIKELY (NULL == clip))
+        return;
 
-    /* Connect to the clipboards */
-    defaultClip = gtk_clipboard_get (GDK_SELECTION_CLIPBOARD);
-    primaryClip = gtk_clipboard_get (GDK_SELECTION_PRIMARY);
+      if (type == DEFAULT)
+        gtk_clipboard_set_text (clipman_clips->default_clipboard, clip->text, -1);
+      else if (!clipman_clips->ignore_primary)
+        gtk_clipboard_set_text (clipman_clips->primary_clipboard, clip->text, -1);
+      break;
 
-    return clipman;
+    default:
+    case NORMAL:
+      gtk_clipboard_set_text (clipman_clips->default_clipboard, clip->text, -1);
+      if (!clipman_clips->ignore_primary)
+        gtk_clipboard_set_text (clipman_clips->primary_clipboard, clip->text, -1);
+      break;
+    }
 }
 
-static void
-clipman_free (XfcePanelPlugin *plugin,
-              ClipmanPlugin   *clipman)
+static gboolean
+clipman_clips_check_clipboard (ClipmanClips *clipman_clips)
 {
-    guint        i;
-    ClipmanClip *clip;
-    GtkWidget   *dialog;
+  GdkModifierType       state;
+  gchar                *text;	/* We use the new allocation of
+                                 * gtk_clipboard_wait_for_text,
+                                 * so no free() on that beotche */
 
-    /* Valgrind notes:
-       - primaryClip and defaultClip should be cleared, but gtk
-         takes care about this
-    */
+  text = gtk_clipboard_wait_for_text (clipman_clips->default_clipboard);
+  if (G_LIKELY (NULL != text))
+    clipman_clips_add (clipman_clips, text, DEFAULT);
+  else if (clipman_clips->prevent_empty == TRUE)
+    clipman_clips_restore_empty (clipman_clips, DEFAULT);
 
-    /* Free the clipboards */
-    gtk_clipboard_clear (primaryClip);
-    gtk_clipboard_clear (defaultClip);
-
-    /* Destroy the setting dialog, if this open */
-    dialog = g_object_get_data (G_OBJECT (plugin), "dialog");
-
-    if (dialog)
-        gtk_widget_destroy (dialog);
-
-    /* Stop the check loop */
-    clipman->killTimeout = TRUE;
-    if (clipman->TimeoutId != 0)
+  if (!clipman_clips->ignore_primary)
     {
-        g_source_remove(clipman->TimeoutId);
-        clipman->TimeoutId = 0;
-    }
+      gdk_window_get_pointer (NULL, NULL, NULL, &state);
+      if (state & GDK_BUTTON1_MASK)
+        return TRUE;
 
-    /* Remove clipboard items */
-    for (i = clipman->clips->len; i--;)
-    {
-        clip = g_ptr_array_index (clipman->clips, i);
-        g_ptr_array_remove_fast (clipman->clips, clip);
-        clipman_free_clip (clip);
+      text = gtk_clipboard_wait_for_text (clipman_clips->primary_clipboard);
+      if (G_LIKELY (NULL != text))
+        clipman_clips_add (clipman_clips, text, PRIMARY);
+      else if (clipman_clips->prevent_empty == TRUE)
+        clipman_clips_restore_empty (clipman_clips, PRIMARY);
     }
-    g_ptr_array_free (clipman->clips, TRUE);
 
-    gtk_tooltips_set_tip (clipman->tooltip, clipman->button, NULL, NULL);
-    g_object_unref (G_OBJECT (clipman->tooltip));
-
-    gtk_widget_destroy (clipman->icon);
-    gtk_widget_destroy (clipman->button);
-
-    clipman->plugin = NULL;
-
-    DBG ("Plugin Freed");
-
-    panel_slice_free (ClipmanPlugin, clipman);
+  return TRUE;
 }
 
-static gboolean
-clipman_set_size (XfcePanelPlugin *plugin,
-                  gint             wsize,
-                  ClipmanPlugin   *clipman)
+static inline void
+clipman_clips_delete (ClipmanClips *clipman_clips,
+					  ClipmanClip *clip)
 {
-    GdkPixbuf *pb;
-    gint       size;
+  g_return_if_fail (G_LIKELY (NULL != clip));
 
-    gtk_widget_set_size_request (clipman->button, wsize, wsize);
+  g_free (clip->text);
+  g_free (clip->short_text);
 
-    size = wsize - 2 - (2 * MAX (clipman->button->style->xthickness,
-                                 clipman->button->style->ythickness));
-
-    DBG("Set clipman button size to %dpx, load icon at %dpx", wsize, size);
-
-    pb = xfce_themed_icon_load ("gtk-paste", size);
-    gtk_image_set_from_pixbuf (GTK_IMAGE (clipman->icon), pb);
-    g_object_unref (G_OBJECT (pb));
-
-    return TRUE;
+  clipman_clips->history = g_slist_remove (clipman_clips->history, clip);
+  g_slice_free (ClipmanClip, clip);
 }
 
 static void
-clipman_construct (XfcePanelPlugin *plugin)
+clipman_clips_add (ClipmanClips *clipman_clips,
+                   gchar *text,
+                   ClipboardType type)
 {
-    ClipmanPlugin *clipman;
+  ClipmanClip          *clip;
+  GSList               *foobar = NULL;
 
-    xfce_textdomain(GETTEXT_PACKAGE, PACKAGE_LOCALE_DIR, "UTF-8");
+  g_return_if_fail (G_LIKELY (NULL != text));
 
-    clipman = clipman_new (plugin);
+  clip              = g_slice_new (ClipmanClip);
+  clip->type        = type;
+  clip->text        = text;
+  clip->short_text  = NULL;
 
-    gtk_container_add (GTK_CONTAINER (plugin), clipman->button);
+  if (clipman_clips->behavior == STRICTLY)
+    foobar = g_slist_find_custom (clipman_clips->history, clip, (GCompareFunc)clipman_clips_compare_with_type);
+  else
+    foobar = g_slist_find_custom (clipman_clips->history, clip, (GCompareFunc)clipman_clips_compare);
 
-    xfce_panel_plugin_add_action_widget (plugin, clipman->button);
+  if (G_UNLIKELY (NULL != foobar))
+    {
+      /* Push the existing clip to the top */
+      clip = (ClipmanClip *)foobar->data;
+      clipman_clips->history = g_slist_remove (clipman_clips->history, clip);
+      clipman_clips->history = g_slist_prepend (clipman_clips->history, clip);
 
-    g_signal_connect (plugin, "free-data",
-        G_CALLBACK (clipman_free), clipman);
+      /* Free this allocation that had should be used in the new clip */
+      g_free (text);
 
-    g_signal_connect (plugin, "save",
-        G_CALLBACK (clipman_save), clipman);
+      return;
+    }
 
-    g_signal_connect (plugin, "size-changed",
-        G_CALLBACK (clipman_set_size), clipman);
+  DBG ("Add to clipboard (%d): `%s'", type, text);
+  clipman_clips->history = g_slist_prepend (clipman_clips->history, clip);
 
-    xfce_panel_plugin_menu_show_configure (plugin);
-    g_signal_connect (plugin, "configure-plugin",
-        G_CALLBACK (clipman_configure), clipman);
+  if (g_slist_length (clipman_clips->history) > clipman_clips->history_length)
+    clipman_clips_delete (clipman_clips, (ClipmanClip *)(g_slist_last (clipman_clips->history)->data));
 }
+
+static gint
+clipman_clips_compare (ClipmanClip *one,
+                       ClipmanClip *two)
+{
+  g_return_val_if_fail (G_LIKELY (NULL != one && NULL != two), -1);
+  return g_ascii_strcasecmp (one->text, two->text);
+}
+
+static gint
+clipman_clips_compare_with_type (ClipmanClip *one,
+                                 ClipmanClip *two)
+{
+  g_return_val_if_fail (G_LIKELY (NULL != one && NULL != two), -1);
+  if (one->type == two->type)
+    return g_ascii_strcasecmp (one->text, two->text);
+  return -1;
+}
+

Modified: xfce4-clipman-plugin/trunk/panel-plugin/clipman.h
===================================================================
--- xfce4-clipman-plugin/trunk/panel-plugin/clipman.h	2008-01-24 12:53:05 UTC (rev 3851)
+++ xfce4-clipman-plugin/trunk/panel-plugin/clipman.h	2008-01-24 13:07:34 UTC (rev 3852)
@@ -1,4 +1,4 @@
-/*  $Id$
+/*  $Id: clipman.h 2395 2007-01-17 17:42:53Z nick $
  *
  *  Copyright (c) 2006-2007 Nick Schermer <nick at xfce.org>
  *
@@ -20,6 +20,10 @@
 #ifndef CLIPMAN_H
 #define CLIPMAN_H
 
+#include <gtk/gtk.h>
+#include <libxfce4panel/xfce-panel-plugin.h>
+#include <libxfcegui4/libxfcegui4.h>
+
 G_BEGIN_DECLS
 
 /* Dialog settings */
@@ -45,74 +49,63 @@
 #define DEFSEPMENU      FALSE
 
 /* Milisecond to check the clipboards(s) */
-#define TIMER_INTERVAL  500
+#define TIMER_INTERVAL  1000
 
 typedef enum
 {
-    PRIMARY = 0,
-    DEFAULT
-}
-ClipboardType;
+  DEFAULT,
+  PRIMARY
+} ClipboardType;
 
 typedef enum
 {
-    NORMAL = 0,
-    STRICTLY
-}
-ClipboardBehaviour;
+  NORMAL,
+  STRICTLY
+} ClipboardBehavior;
 
-typedef struct
+typedef struct _ClipmanPlugin       ClipmanPlugin;
+typedef struct _ClipmanClips        ClipmanClips;
+typedef struct _ClipmanClip         ClipmanClip;
+
+struct _ClipmanPlugin
 {
-    XfcePanelPlugin *plugin;
+  XfcePanelPlugin      *panel_plugin;
+  ClipmanClips         *clipman_clips;
 
-    GtkWidget    *icon;
-    GtkWidget    *button;
-    GtkTooltips  *tooltip;
+  GtkWidget            *button;
+  GtkWidget            *icon;
+  GtkWidget            *menu;
 
-    GPtrArray    *clips;
+  gboolean              menu_separate_clipboards;
+  gboolean              menu_item_show_number;
+  gint                  menu_item_max_chars;
+};
 
-    gint          TimeoutId;
-    gboolean      killTimeout;
+struct _ClipmanClips
+{
+  ClipmanPlugin        *clipman_plugin;
 
-    gboolean      ExitSave;
-    gboolean      IgnoreSelect;
-    gboolean      PreventEmpty;
+  GtkClipboard         *default_clipboard;
+  GtkClipboard         *primary_clipboard;
 
-    ClipboardBehaviour Behaviour;
+  gint                  timeout;
 
-    gboolean      ItemNumbers;
-    gboolean      SeparateMenu;
+  GSList               *history;
 
-    guint         HistoryItems;
-    guint         MenuCharacters;
-}
-ClipmanPlugin;
+  ClipboardBehavior     behavior;
+  gint                  history_length;
+  gboolean              save_on_exit;
+  gboolean              ignore_primary;
+  gboolean              prevent_empty;
+};
 
-typedef struct
+struct _ClipmanClip
 {
-    gchar        *text;
-    gchar        *title;        /* I've added the title to save
-                                 * some time when opening the menu */
-    ClipboardType fromtype;
-}
-ClipmanClip;
+    ClipboardType       type;
+    gchar              *text;
+    gchar              *short_text; /* Saves cycles to add menu items */
+};
 
-typedef struct
-{
-    ClipmanPlugin  *clipman;
-    ClipmanClip    *clip;
-}
-ClipmanAction;
-
-void
-clipman_check_array_len        (ClipmanPlugin *clipman);
-
-void
-clipman_save                   (XfcePanelPlugin *plugin, ClipmanPlugin *clipman);
-
-void
-clipman_remove_selection_clips (ClipmanPlugin *clipman);
-
 G_END_DECLS
 
 #endif /* CLIPMAN_H */




More information about the Goodies-commits mailing list