1 #include "wmcliphist.h"
2 #include <gdk/gdkkeysyms.h>
5 /* color of locked item */
6 gchar locked_color_str
[32] = DEF_LOCKED_COLOR
;
9 /* Exec on middle click? */
10 int exec_middleclick
= 1;
12 /* main window widget */
13 GtkWidget
*main_window
;
15 /* dock icon widget */
18 /* clipboard history menu */
20 GtkWidget
*menu_title
;
21 gint submenu_count
= 0;
23 /* application menu */
25 GtkWidget
*menu_app_clip_lock
;
26 GtkWidget
*menu_app_clip_ignore
;
27 GtkWidget
*menu_app_exit
;
28 GtkWidget
*menu_app_save
;
36 /* which clipboard to use */
37 gchar clipboard_str
[32] = DEF_CLIPBOARD_STR
;
40 /* ==========================================================================
41 * clipboard history menu
45 * history menu item button click function
48 menu_item_button_released(GtkWidget
*widget
,
52 GdkEventButton
*bevent
= (GdkEventButton
*)event
;
53 HISTORY_ITEM
*data
= user_data
;
55 begin_func("menu_item_button_released");
57 /* button 2 or 3 - exec or (un)lock item respectively */
58 if (bevent
->button
== 2) {
59 if (exec_middleclick
) {
60 gtk_menu_popdown(GTK_MENU(menu_hist
));
61 exec_item(data
->content
, NULL
);
64 } else if (bevent
->button
== 3) {
65 if (data
->locked
== 0) {
67 /* cannot lock all records */
68 if (locked_count
== num_items_to_keep
- 1) {
69 show_message("There must remain at least one "
70 "unlocked item\nwhen menu is full!",
71 "Warning", "OK", NULL
, NULL
);
75 gtk_widget_override_color(
76 gtk_bin_get_child(GTK_BIN(data
->menu_item
)),
77 GTK_STATE_FLAG_NORMAL
, &locked_color
);
82 gtk_widget_override_color(
83 gtk_bin_get_child(GTK_BIN(data
->menu_item
)),
84 GTK_STATE_FLAG_NORMAL
, NULL
);
97 * history menu item left click or keypress function
100 menu_item_activated(GtkWidget
*widget
, gpointer user_data
)
102 move_item_to_begin((HISTORY_ITEM
*) user_data
);
108 * checks, if there is already such item in menu,
109 * in which case it moves it to the begining
112 menu_item_exists(gchar
*content
, GtkWidget
*submenu
)
114 HISTORY_ITEM
*hist_item
;
117 begin_func("menu_item_exists");
119 list_node
= g_list_last(history_items
);
121 hist_item
= (HISTORY_ITEM
*)list_node
->data
;
122 if (hist_item
->menu
== submenu
123 && g_utf8_collate(hist_item
->content
, content
)
125 gtk_menu_reorder_child(GTK_MENU(hist_item
->menu
),
126 hist_item
->menu_item
, 1);
127 history_items
= g_list_remove_link(history_items
,
129 history_items
= g_list_concat(list_node
, history_items
);
131 return_val(hist_item
);
133 list_node
= g_list_previous(list_node
);
141 * add new item to menu
144 menu_item_add(gchar
*content
, gint locked
, GtkWidget
*target_menu
)
148 gchar
*menu_item_name
;
149 gchar
*fixed_menu_item_name
;
151 HISTORY_ITEM
*hist_item
;
153 begin_func("menu_item_add");
155 hist_item
= menu_item_exists(content
, target_menu
);
156 if (hist_item
!= NULL
) {
157 dump_history_list("reorder");
158 return_val(hist_item
);
161 if (num_items
== num_items_to_keep
) {
162 /* max item limit reached, destroy oldest one */
163 list_node
= g_list_last(history_items
);
165 hist_item
= (HISTORY_ITEM
*)
167 if (hist_item
->locked
== 0)
169 list_node
= g_list_previous(list_node
);
170 g_assert((list_node
!= NULL
));
173 history_items
= g_list_remove_link(history_items
, list_node
);
174 gtk_container_remove(GTK_CONTAINER(hist_item
->menu
),
175 hist_item
->menu_item
);
176 gtk_widget_destroy(hist_item
->menu_item
);
177 g_free(hist_item
->content
);
179 g_list_free_1(list_node
);
181 dump_history_list("remove oldest");
184 /* prepare menu item name */
185 menu_item_name
= g_new0(char, MAX_ITEM_LENGTH
* 2 + 1);
186 memset(menu_item_name
, 0, MAX_ITEM_LENGTH
* 2 + 1);
187 length
= g_utf8_strlen(content
, -1);
188 if (length
> (size_t) (MAX_ITEM_LENGTH
)) {
189 g_utf8_strncpy(menu_item_name
, content
, MAX_ITEM_LENGTH
- 4);
190 strcat(menu_item_name
, "...");
192 strcpy(menu_item_name
, content
);
195 /* do some menu item name cleanups */
196 fixed_menu_item_name
= g_new0(char, strlen(menu_item_name
) + 1);
197 for (i
= 0; i
< g_utf8_strlen(menu_item_name
, -1); i
++) {
198 gchar
*uchar_ptr
= g_utf8_offset_to_pointer(menu_item_name
, i
);
199 gunichar uchar
= g_utf8_get_char(uchar_ptr
);
200 if (g_unichar_isprint(uchar
)) {
201 gchar
*decoded_char
= g_ucs4_to_utf8(&uchar
, 1, NULL
,
203 strcat(fixed_menu_item_name
, decoded_char
);
204 g_free(decoded_char
);
206 strcat(fixed_menu_item_name
, "_");
209 g_free(menu_item_name
);
210 menu_item_name
= fixed_menu_item_name
;
212 /* create menu item */
213 hist_item
= g_new0(HISTORY_ITEM
, 1);
214 hist_item
->menu_item
= gtk_menu_item_new_with_label(menu_item_name
);
215 hist_item
->content
= g_strdup(content
);
216 hist_item
->locked
= locked
;
217 hist_item
->menu
= target_menu
;
220 gtk_widget_override_color(
221 gtk_bin_get_child(GTK_BIN(hist_item
->menu_item
)),
222 GTK_STATE_FLAG_NORMAL
, &locked_color
);
227 gtk_menu_shell_insert(GTK_MENU_SHELL(hist_item
->menu
), hist_item
->menu_item
, 1);
230 /* connect actions to signals */
231 g_signal_connect(G_OBJECT(hist_item
->menu_item
),
232 "button-release-event",
233 G_CALLBACK(menu_item_button_released
),
234 (gpointer
)hist_item
);
236 g_signal_connect(G_OBJECT(hist_item
->menu_item
),
238 G_CALLBACK(menu_item_activated
),
239 (gpointer
)hist_item
);
241 gtk_widget_show(hist_item
->menu_item
);
243 history_items
= g_list_insert(history_items
, hist_item
, 0);
247 return_val(hist_item
);
252 /* ==========================================================================
257 * application main menu handler
260 menu_app_item_click(GtkWidget
*menuitem
, gpointer data
)
264 begin_func("menu_app_item_click");
266 switch (GPOINTER_TO_INT(data
)) {
267 /* save history menu */
269 if (history_save() != 0) {
270 button
= show_message("History was NOT saved.\n",
271 "Warning", "OK", NULL
, NULL
);
277 if (history_save() != 0) {
278 button
= show_message("History was NOT saved.\n"
279 "Do you really want to exit?",
280 "Error", "Yes", "No", NULL
);
295 /* ==========================================================================
300 * dock button click response
303 button_press(GtkWidget
*widget
, GdkEvent
*event
, gpointer data
)
305 begin_func("button_press");
307 if (event
->type
== GDK_BUTTON_PRESS
) {
308 GdkEventButton
*bevent
= (GdkEventButton
*)event
;
310 switch (bevent
->button
) {
312 /* popup history menu */
313 gtk_menu_popup(GTK_MENU(menu_hist
),
321 /* popup application menu */
322 gtk_menu_popup(GTK_MENU(menu_app
),
336 /* ==========================================================================
340 static GMainLoop
*loop
;
341 static gint button_pressed
;
345 dialog_button_press(GtkWidget
*button
, gpointer data
)
347 begin_func("dialog_button_press");
349 button_pressed
= GPOINTER_TO_INT(data
);
358 dialog_handle_key_press_event(GdkEventKey
*event
, gpointer data
, guint key
)
360 if(event
->type
!= GDK_KEY_PRESS
)
362 if(event
->keyval
!= key
)
364 button_pressed
= GPOINTER_TO_INT(data
);
373 dialog_key_press_yes(GtkWidget
*button
, GdkEventKey
*event
, gpointer data
)
375 begin_func("dialog_key_press_yes");
376 return dialog_handle_key_press_event(event
, data
, GDK_KEY_Return
);
382 dialog_key_press_no(GtkWidget
*button
, GdkEventKey
*event
, gpointer data
)
384 begin_func("dialog_key_press_no");
385 return dialog_handle_key_press_event(event
, data
, GDK_KEY_Escape
);
391 * open dialog with specified message andbuttons
392 * and return number of button pressed
395 show_message(gchar
*message
, char *title
,
396 char *b0_text
, char *b1_text
, char *b2_text
)
404 begin_func("show_message");
406 /* create the main widgets */
407 dialog
= gtk_dialog_new();
408 label
= gtk_label_new(message
);
410 /* create buttons and set signals */
411 gtk_dialog_add_button(GTK_DIALOG(dialog
), b0_text
, 0);
412 button_0
= gtk_dialog_get_widget_for_response(GTK_DIALOG(dialog
), 0);
413 g_signal_connect(G_OBJECT(button_0
), "clicked",
414 G_CALLBACK(dialog_button_press
),
417 g_signal_connect(G_OBJECT(dialog
), "key-press-event",
418 G_CALLBACK(dialog_key_press_yes
),
422 if (b1_text
!= NULL
) {
423 gtk_dialog_add_button(GTK_DIALOG(dialog
), b1_text
, 1);
424 button_1
= gtk_dialog_get_widget_for_response(GTK_DIALOG(dialog
), 1);
425 g_signal_connect(G_OBJECT(button_1
), "clicked",
426 G_CALLBACK(dialog_button_press
),
429 g_signal_connect(G_OBJECT(dialog
), "key-press-event",
430 G_CALLBACK(dialog_key_press_no
),
436 gtk_dialog_add_button(GTK_DIALOG(dialog
), b2_text
, 2);
437 button_2
= gtk_dialog_get_widget_for_response(GTK_DIALOG(dialog
), 2);
438 g_signal_connect(G_OBJECT(button_2
), "clicked",
439 G_CALLBACK(dialog_button_press
),
443 /* add the label, and show everything we've added to the dialog. */
444 gtk_misc_set_padding(>K_LABEL(label
)->misc
, 10, 10);
445 gtk_container_add(GTK_CONTAINER(gtk_dialog_get_content_area(GTK_DIALOG(dialog
))), label
);
446 gtk_widget_show_all(dialog
);
448 /* set window title */
449 gtk_window_set_title(GTK_WINDOW(dialog
), title
);
451 loop
= g_main_new(FALSE
);
453 g_main_destroy(loop
);
454 gtk_widget_destroy(dialog
);
456 return_val(button_pressed
);