Add activate/deactivate menu item, wordaround for OO
authorteodor <teodor>
Wed, 27 Dec 2006 13:39:49 +0000 (13:39 +0000)
committerteodor <teodor>
Wed, 27 Dec 2006 13:39:49 +0000 (13:39 +0000)
hclip.c

diff --git a/hclip.c b/hclip.c
index 1f591b7..f5c2b99 100644 (file)
--- a/hclip.c
+++ b/hclip.c
@@ -66,7 +66,6 @@
 typedef struct ClipboardMenuItem {
        GtkWidget                               *widget; /* pointer to GtkMenuItem */
        gchar                                   *buffer; /* value  and it's length */
-       size_t                                  buflen;  
        gint                                    flags;
 } ClipboardMenuItem;
 
@@ -82,6 +81,9 @@ typedef struct ClipboardDescr {
 
        GtkWidget                       *widget; /* GtkMenu */
 
+       GtkWidget                       *activator; /* GtkMenuItem for manage active state */
+       gboolean                        is_active;
+
        ClipboardMenuItem       *items[NHistItem];  /* histories item's */
        gint                            nitems;                         /* number of items */
        gint                            nlocked;                        /* number of locked items */
@@ -142,12 +144,12 @@ catchKey(GdkXEvent *gdk_xevent, GdkEvent *event, gpointer data)
  * buffer and -1 if it isn't found
  */
 static gint
-existMenuItem(ClipboardDescr *descr, const gchar *buffer, size_t buflen)
+existMenuItem(ClipboardDescr *descr, const gchar *buffer)
 {
        gint i;
 
        for(i=0;i<descr->nitems;i++)
-               if ( descr->items[i]->buflen == buflen && strcmp( descr->items[i]->buffer, buffer ) == 0 )
+               if ( strcmp( descr->items[i]->buffer, buffer ) == 0 )
                        return i;
 
        return -1;
@@ -207,8 +209,7 @@ itemActivate(GtkWidget *widget, gpointer user_data)
                moveMenuItemFirst( descr, n );
                gtk_clipboard_set_text(
                        gtk_clipboard_get(GDK_SELECTION_PRIMARY),
-                       descr->items[0]->buffer,
-                       descr->items[0]->buflen);
+                       descr->items[0]->buffer, -1 );
        }
        
        return TRUE;
@@ -318,7 +319,7 @@ newClipboardMenuItem(ClipboardDescr *descr)
  * existing
  */
 static void
-addMenuItem( ClipboardDescr *descr, const gchar *buffer, size_t buflen )
+addMenuItem( ClipboardDescr *descr, gchar *buffer )
 {
        gint    i;
        static  gchar itemname[5*MaxItemName + 1];
@@ -327,7 +328,7 @@ addMenuItem( ClipboardDescr *descr, const gchar *buffer, size_t buflen )
        /*
         * if such value already exists just move to to head
         */
-       if ( (i=existMenuItem(descr, buffer, buflen)) >= 0 )
+       if ( (i=existMenuItem(descr, buffer)) >= 0 )
        {
                moveMenuItemFirst( descr, i );
                return;
@@ -365,8 +366,7 @@ addMenuItem( ClipboardDescr *descr, const gchar *buffer, size_t buflen )
        if ( descr->items[0]->buffer )
                g_free( descr->items[0]->buffer );
 
-       descr->items[0]->buffer = g_memdup(buffer, buflen+1);
-       descr->items[0]->buflen = buflen;
+       descr->items[0]->buffer = buffer;
        descr->items[0]->flags = 0;
 
        /*
@@ -377,7 +377,7 @@ addMenuItem( ClipboardDescr *descr, const gchar *buffer, size_t buflen )
        ptrname = itemname;
        ptrbuffer = (gchar*)buffer;
 
-       for(i=0; *ptrbuffer && (ptrbuffer - buffer)<buflen && i < MaxItemName; i++)
+       for(i=0; *ptrbuffer && i < MaxItemName; i++)
        {
                int     charlen = g_utf8_offset_to_pointer(ptrbuffer, 1) - ptrbuffer; 
                gunichar         widechar;
@@ -416,12 +416,40 @@ addMenuItem( ClipboardDescr *descr, const gchar *buffer, size_t buflen )
        );
 }
 
+static gboolean
+appToggleActivate(GtkWidget *widget, gpointer user_data)
+{
+       ClipboardDescr  *descr = (ClipboardDescr*)user_data;
+
+       if ( descr->is_active == TRUE )
+       {
+               gtk_widget_set_style( GTK_BIN(descr->activator)->child, descr->style_locked);
+               gtk_label_set_text(
+                       GTK_LABEL( gtk_bin_get_child(GTK_BIN(descr->activator)) ),
+                       "Activate"
+               );
+               descr->is_active = FALSE;
+       }
+       else
+       {
+               gtk_widget_set_style( GTK_BIN(descr->activator)->child, descr->style_normal);
+               gtk_label_set_text(
+                       GTK_LABEL( gtk_bin_get_child(GTK_BIN(descr->activator)) ),
+                       "Deactivate"
+               );
+               descr->is_active = TRUE;
+       }
+       
+       return TRUE;
+}
+
 /*
  * Initialize main struct
  */
 static void
 initHistMenu( ClipboardDescr *descr )
 {
+       GtkWidget       *separator;
        /*
         * set up hotkey to call menu
         */
@@ -435,6 +463,23 @@ initHistMenu( ClipboardDescr *descr )
         */
        descr->widget = gtk_menu_new();
        gtk_menu_set_title(GTK_MENU(descr->widget), "Clipboard history");
+
+       separator = gtk_separator_menu_item_new();
+       gtk_menu_shell_append(GTK_MENU_SHELL(descr->widget), separator);
+
+       descr->activator = gtk_menu_item_new_with_label("Deactivate");
+       gtk_label_set_max_width_chars(
+               GTK_LABEL( gtk_bin_get_child(GTK_BIN(descr->activator)) ),
+               MaxItemName
+       );
+       g_signal_connect(descr->activator,
+                                               "activate",
+                                               G_CALLBACK(appToggleActivate),
+                                               (gpointer)descr);
+       gtk_menu_shell_append(GTK_MENU_SHELL(descr->widget), descr->activator);
+
+       gtk_widget_show(descr->activator);
+       gtk_widget_show(separator);
        gtk_widget_show(descr->widget);
 
        descr->nitems = 0;
@@ -453,18 +498,57 @@ initHistMenu( ClipboardDescr *descr )
         * Create first item and mark it as INIT due to
         * void menu is showed very bad
         */
-       addMenuItem( descr, StartupItem, strlen(StartupItem) );
+       addMenuItem( descr, g_strdup(StartupItem) );
        descr->items[0]->flags = CMI_INIT;
+
+       descr->is_active = TRUE;
 }
 
 /*
- * Retrieves content of clipoard in a text form
+ * Receive text content of buffer
+ *
+ * it seems to me, that there is some problem in gtk+
+ * when targets MULTIPLE and TARGETS are set (at least with russian 
+ * characters in OO ). So just ignore such cases...
  */
 static void
-receiveText(GtkClipboard *cpb, const gchar *text, gpointer data) 
+receiveTarget(GtkClipboard *clipboard, GdkAtom *atoms, gint n_atoms, gpointer data)
 {
-       if ( text != NULL ) 
-               addMenuItem( (ClipboardDescr*)data, text, strlen(text) ); 
+       gint i;
+       gboolean has_text = FALSE,
+                        has_multiple = FALSE,
+                        has_targets = FALSE;
+
+       /*
+        * checks all avaliable targets
+        */
+       for(i=0;i<n_atoms;i++)
+       {
+               if ( atoms[i] == gdk_atom_intern_static_string("UTF8_STRING") ||
+                         atoms[i] == gdk_atom_intern_static_string("COMPOUND_TEXT") )
+               {
+                       has_text = TRUE;
+               }
+               else if ( atoms[i] == gdk_atom_intern_static_string("MULTIPLE") )
+               {
+                       has_multiple = TRUE;
+               } 
+               else if ( atoms[i] == gdk_atom_intern_static_string("TARGETS") )
+               {
+                       has_targets = TRUE;
+               } 
+       }
+
+       /*
+        * check for workaround
+        */
+       if ( has_text == TRUE && ( has_multiple==FALSE || has_targets == TRUE ) )
+       {
+               gchar *text = gtk_clipboard_wait_for_text(clipboard);
+
+               if (text)
+                       addMenuItem( (ClipboardDescr*)data, text );
+       }
 }
 
 /*
@@ -474,7 +558,11 @@ receiveText(GtkClipboard *cpb, const gchar *text, gpointer data)
 static void
 ClipboardChange(GtkClipboard *clipboard, GdkEvent *event, gpointer data)
 {
-       gtk_clipboard_request_text( clipboard, receiveText, data );     
+       /*
+        * Do real work if and only if application is active 
+        */
+       if ( ((ClipboardDescr*)data)->is_active ) 
+               gtk_clipboard_request_targets( clipboard, receiveTarget, data );
 }
 
 int