Make AddMouseRegion's index unsigned
[dockapps.git] / wmcliphist / gui.c
blob3f3681e68247c1d52ab4855f70d8d0eb29b631d3
1 #include "wmcliphist.h"
2 #include <gdk/gdkkeysyms.h>
5 /* color of locked item */
6 gchar locked_color_str[32] = DEF_LOCKED_COLOR;
7 GdkRGBA locked_color;
9 /* Exec on middle click? */
10 int exec_middleclick = 1;
12 /* main window widget */
13 GtkWidget *main_window;
15 /* dock icon widget */
16 GtkWidget *dock_app;
18 /* clipboard history menu */
19 GtkWidget *menu_hist;
20 GtkWidget *menu_title;
21 gint submenu_count = 0;
23 /* application menu */
24 GtkWidget *menu_app;
25 GtkWidget *menu_app_clip_lock;
26 GtkWidget *menu_app_clip_ignore;
27 GtkWidget *menu_app_exit;
28 GtkWidget *menu_app_save;
30 /* event box */
31 GtkWidget *event;
33 /* button */
34 GtkWidget *button;
36 /* pixmap */
37 GtkWidget *pixmap;
39 /* which clipboard to use */
40 gchar clipboard_str[32] = DEF_CLIPBOARD_STR;
41 GdkAtom clipboard;
43 /* ==========================================================================
44 * clipboard history menu
48 * history menu item button click function
50 static gboolean
51 menu_item_button_released(GtkWidget *widget,
52 GdkEvent *event,
53 gpointer user_data)
55 GdkEventButton *bevent = (GdkEventButton *)event;
56 HISTORY_ITEM *data = user_data;
58 begin_func("menu_item_button_released");
60 /* button 2 or 3 - exec or (un)lock item respectively */
61 if (bevent->button == 2) {
62 if (exec_middleclick) {
63 gtk_menu_popdown(GTK_MENU(menu_hist));
64 exec_item(data->content, NULL);
66 return_val(TRUE);
67 } else if (bevent->button == 3) {
68 if (data->locked == 0) {
70 /* cannot lock all records */
71 if (locked_count == num_items_to_keep - 1) {
72 show_message("There must remain at least one "
73 "unlocked item\nwhen menu is full!",
74 "Warning", "OK", NULL, NULL);
75 return_val(TRUE);
78 gtk_widget_override_color(
79 gtk_bin_get_child(GTK_BIN(data->menu_item)),
80 GTK_STATE_FLAG_NORMAL, &locked_color);
81 data->locked = 1;
82 locked_count++;
84 } else {
85 gtk_widget_override_color(
86 gtk_bin_get_child(GTK_BIN(data->menu_item)),
87 GTK_STATE_FLAG_NORMAL, NULL);
88 data->locked = 0;
89 locked_count--;
91 } else {
92 return_val(FALSE);
95 return_val(TRUE);
100 * history menu item left click or keypress function
102 static gboolean
103 menu_item_activated(GtkWidget *widget, gpointer user_data)
105 move_item_to_begin((HISTORY_ITEM *) user_data);
106 return_val(TRUE);
111 * checks, if there is already such item in menu,
112 * in which case it moves it to the begining
114 HISTORY_ITEM *
115 menu_item_exists(gchar *content, GtkWidget *submenu)
117 HISTORY_ITEM *hist_item;
118 GList *list_node;
120 begin_func("menu_item_exists");
122 list_node = g_list_last(history_items);
123 while (list_node) {
124 hist_item = (HISTORY_ITEM *)list_node->data;
125 if (hist_item->menu == submenu
126 && g_utf8_collate(hist_item->content, content)
127 == 0) {
128 gtk_menu_reorder_child(GTK_MENU(hist_item->menu),
129 hist_item->menu_item, 1);
130 history_items = g_list_remove_link(history_items,
131 list_node);
132 history_items = g_list_concat(list_node, history_items);
134 return_val(hist_item);
136 list_node = g_list_previous(list_node);
139 return_val(NULL);
144 * add new item to menu
146 HISTORY_ITEM *
147 menu_item_add(gchar *content, gint locked, GtkWidget *target_menu)
149 GList *list_node;
150 gint i;
151 gchar *menu_item_name;
152 gchar *fixed_menu_item_name;
153 gsize length;
154 HISTORY_ITEM *hist_item;
156 begin_func("menu_item_add");
158 hist_item = menu_item_exists(content, target_menu);
159 if (hist_item != NULL) {
160 dump_history_list("reorder");
161 return_val(hist_item);
164 if (num_items == num_items_to_keep) {
165 /* max item limit reached, destroy oldest one */
166 list_node = g_list_last(history_items);
167 while (1) {
168 hist_item = (HISTORY_ITEM*)
169 list_node->data;
170 if (hist_item->locked == 0)
171 break;
172 list_node = g_list_previous(list_node);
173 g_assert((list_node != NULL));
176 history_items = g_list_remove_link(history_items, list_node);
177 /* gtk_container_remove(GTK_CONTAINER(hist_item->menu),
178 hist_item->menu_item); */
179 gtk_widget_destroy(hist_item->menu_item);
180 g_free(hist_item->content);
181 g_free(hist_item);
182 g_list_free_1(list_node);
183 num_items--;
184 dump_history_list("remove oldest");
187 /* prepare menu item name */
188 menu_item_name = g_new0(char, MAX_ITEM_LENGTH * 2 + 1);
189 memset(menu_item_name, 0, MAX_ITEM_LENGTH * 2 + 1);
190 length = g_utf8_strlen(content, -1);
191 if (length > (size_t) (MAX_ITEM_LENGTH)) {
192 g_utf8_strncpy(menu_item_name, content, MAX_ITEM_LENGTH - 4);
193 strcat(menu_item_name, "...");
194 } else {
195 strcpy(menu_item_name, content);
198 /* do some menu item name cleanups */
199 fixed_menu_item_name = g_new0(char, strlen(menu_item_name) + 1);
200 for (i = 0; i < g_utf8_strlen(menu_item_name, -1); i++) {
201 gchar *uchar_ptr = g_utf8_offset_to_pointer(menu_item_name, i);
202 gunichar uchar = g_utf8_get_char(uchar_ptr);
203 if (g_unichar_isprint(uchar)) {
204 gchar *decoded_char = g_ucs4_to_utf8(&uchar, 1, NULL,
205 NULL, NULL);
206 strcat(fixed_menu_item_name, decoded_char);
207 g_free(decoded_char);
208 } else {
209 strcat(fixed_menu_item_name, "_");
212 g_free(menu_item_name);
213 menu_item_name = fixed_menu_item_name;
215 /* create menu item */
216 hist_item = g_new0(HISTORY_ITEM, 1);
217 hist_item->menu_item = gtk_menu_item_new_with_label(menu_item_name);
218 hist_item->content = g_strdup(content);
219 hist_item->locked = locked;
220 hist_item->menu = target_menu;
222 if (locked == 1) {
223 gtk_widget_override_color(
224 gtk_bin_get_child(GTK_BIN(hist_item->menu_item)),
225 GTK_STATE_FLAG_NORMAL, &locked_color);
226 locked_count++;
229 /* add to menu */
230 gtk_menu_shell_insert(GTK_MENU_SHELL(hist_item->menu), hist_item->menu_item, 1);
233 /* connect actions to signals */
234 g_signal_connect(G_OBJECT(hist_item->menu_item),
235 "button-release-event",
236 G_CALLBACK(menu_item_button_released),
237 (gpointer)hist_item);
239 g_signal_connect(G_OBJECT(hist_item->menu_item),
240 "activate",
241 G_CALLBACK(menu_item_activated),
242 (gpointer)hist_item);
244 gtk_widget_show(hist_item->menu_item);
246 history_items = g_list_insert(history_items, hist_item, 0);
248 num_items++;
250 return_val(hist_item);
255 /* ==========================================================================
256 * application menu
260 * application main menu handler
262 gboolean
263 menu_app_item_click(GtkWidget *menuitem, gpointer data)
265 gint button;
267 begin_func("menu_app_item_click");
269 switch (GPOINTER_TO_INT(data)) {
270 /* save history menu */
271 case 0:
272 if (history_save() != 0) {
273 button = show_message("History was NOT saved.\n",
274 "Warning", "OK", NULL, NULL);
276 return_val(TRUE);
278 /* exit menu */
279 case 1:
280 if (history_save() != 0) {
281 button = show_message("History was NOT saved.\n"
282 "Do you really want to exit?",
283 "Error", "Yes", "No", NULL);
284 if (button != 0)
285 return_val(TRUE);
287 history_free();
288 rcconfig_free();
290 gtk_main_quit();
291 exit(0);
292 return_val(TRUE);
294 return_val(FALSE);
299 /* ==========================================================================
300 * dock button press
304 * dock button click response
306 gboolean
307 button_press(GtkWidget *widget, GdkEvent *event, gpointer data)
309 begin_func("button_press");
311 if (event->type == GDK_BUTTON_PRESS) {
312 GdkEventButton *bevent = (GdkEventButton *)event;
314 switch (bevent->button) {
315 case 1:
316 /* popup history menu */
317 gtk_menu_popup(GTK_MENU(menu_hist),
318 NULL, NULL,
319 NULL, NULL,
320 bevent->button,
321 bevent->time);
322 return_val(TRUE);
324 case 3:
325 /* popup application menu */
326 gtk_menu_popup(GTK_MENU(menu_app),
327 NULL, NULL,
328 NULL, NULL,
329 bevent->button,
330 bevent->time);
331 return_val(TRUE);
335 return_val(FALSE);
339 /* ==========================================================================
340 * message dialogs
345 * open dialog with specified message and buttons
346 * and return number of button pressed
348 gint
349 show_message(gchar *message, char *title,
350 char *b0_text, char *b1_text, char *b2_text)
352 GtkWidget *dialog,
353 *label,
354 *content_area;
355 gint result;
356 gint button_pressed = 1;
358 begin_func("show_message");
360 /* create the main widgets */
361 dialog = gtk_dialog_new();
363 content_area = gtk_dialog_get_content_area(GTK_DIALOG(dialog));
365 /* Show the message */
366 label = gtk_label_new(message);
367 gtk_container_add(GTK_CONTAINER (content_area), label);
368 gtk_widget_show(label);
370 /* add the button */
371 gtk_dialog_add_button(GTK_DIALOG (dialog), b0_text, 0);
372 if(b1_text != NULL) gtk_dialog_add_button(GTK_DIALOG (dialog), b1_text, 1);
373 if(b2_text != NULL) gtk_dialog_add_button(GTK_DIALOG (dialog), b2_text, 2);
375 gtk_widget_show_all(dialog);
377 /* set the dialog title */
378 gtk_window_set_title(GTK_WINDOW(dialog), title);
380 /* set the dialog modal and transient */
381 /* gtk_window_set_modal(GTK_WINDOW (dialog), TRUE);*/
382 gtk_window_set_transient_for(GTK_WINDOW (dialog), GTK_WINDOW (dock_app));
384 /*wait for the user response */
385 result = gtk_dialog_run (GTK_DIALOG (dialog));
386 switch (result)
388 case 0:
389 button_pressed = 0;
390 break;
391 case 1:
392 button_pressed = 1;
393 break;
394 case 2:
395 button_pressed = 2;
396 break;
397 default:
398 break;
401 /*destroy the dialog box, when the user responds */
402 gtk_widget_destroy(dialog);
404 return_val(button_pressed);