wmclockmon: properly fix allocating and freeing of `command`, `light_color` and the...
[dockapps.git] / wmcliphist / wmcliphist.c
blob5e06e1d6a4d3af1fbc81290ed6d369111e1036ed
1 /*
2 * (c) 2001 Michal Krause <michal@krause.cz>
3 */
5 #include "wmcliphist.h"
7 #define WMCLIPHIST_VERSION "2.1"
9 /*
10 * print some help
12 void
13 print_help()
15 begin_func("print_help");
17 fprintf(stderr, "Usage: wmcliphist [options]\n\n"
18 "wmcliphist is small dock applet for Window Maker which "
19 "keeps X clipboard history\n\n");
20 fprintf(stderr, "-h show this help\n"
21 "-v print version\n"
22 "-n <num> set number of items to keep (default 10)\n"
23 "-c color set color for locked items (default is red)\n"
24 "-s <size> choose wmcliphist icon size:\n"
25 " 0 = no icon\n"
26 " 16 = tiny 16x16 px icon\n"
27 " 30 = icon suitable for 32px dock/slit\n"
28 " 40 = icon suitable for 48px dock/slit\n"
29 " 60 = icon suitable for 64px dock/slit (default)\n");
30 fprintf(stderr, "-i <num> choose wmcliphist icon antialiasing:\n"
31 " 0 = for mid tones background (default)\n"
32 " 1 = for dark background\n"
33 " 2 = for light background\n");
34 fprintf(stderr, "-d dumps clipboard history to stdout"
35 " in pseudo XML format (no escaping etc.)\n");
36 fprintf(stderr, "-b <type> choose clipboard to manage\n"
37 " PRIMARY = select copies, middle click pastes (default)\n"
38 " SECONDARY = not used\n"
39 " CLIPBOARD = Ctrl+C copies, Ctrl+V pastes\n\n");
40 exit(1);
41 return_void();
44 static void
45 wmcliphist_exit(gint code)
47 begin_func("wmcliphist_exit");
48 gtk_main_quit();
49 exit(code);
50 return_void();
54 * main func
56 int
57 main(int argc, char **argv)
59 gint i = 1, res;
60 gchar *arg;
61 gchar *icon_file;
62 GList *list_node;
63 int icon_number = 0;
64 int icon_size = 60;
65 gboolean dump_only = FALSE;
66 XWMHints mywmhints;
67 GdkDisplay *display;
69 #ifdef FNCALL_DEBUG
70 debug_init_nothreads();
71 #endif
72 begin_func("main");
74 /* load configuration */
75 if ((res = rcconfig_get(rcconfig_get_name("rc"))) != 0) {
76 fprintf(stderr, "~/.wmcliphistrc parse error (%d)\n", res);
77 return_val(1);
80 /* parse command line */
81 while ((arg = argv[i])) {
82 if (*arg == '-') {
83 if (*(arg + 1) == 'h')
84 print_help();
85 else if (*(arg + 1) == 'n') {
86 i++;
87 if (!argv[i]) {
88 fprintf(stderr, "Missing value of -n\n");
89 print_help();
91 num_items_to_keep = atol(argv[i]);
92 } else if (*(arg + 1) == 'c') {
93 i++;
94 if (!argv[i]) {
95 fprintf(stderr, "Missing value of -c\n");
96 print_help();
98 memset(locked_color_str, 0, 32);
99 strncpy(locked_color_str, argv[i], 31);
100 } else if (*(arg + 1) == 'i') {
101 i++;
102 if (!argv[i]) {
103 fprintf(stderr, "Missing value of -i\n");
104 print_help();
106 icon_number = atoi(argv[i]);
107 if (icon_number < 0 || icon_number > 2) {
108 fprintf(stderr, "Invalid value of -i\n");
109 print_help();
111 } else if (*(arg + 1) == 's') {
112 i++;
113 if (!argv[i]) {
114 fprintf(stderr, "Missing value of -s\n");
115 print_help();
117 icon_size = atoi(argv[i]);
118 if (icon_size != 60 && icon_size != 40
119 && icon_size != 30
120 && icon_size != 16
121 && icon_size != 0) {
122 fprintf(stderr, "Invalid value of -s\n");
123 print_help();
125 if (icon_size == 0) {
126 icon_size = 1;
128 } else if (*(arg + 1) == 'd') {
129 dump_only = TRUE;
130 } else if (*(arg + 1) == 'v') {
131 printf("wmcliphist "WMCLIPHIST_VERSION"\n");
132 exit(1);
133 } else if (*(arg + 1) == 'b') {
134 i++;
135 if (!argv[i]) {
136 fprintf(stderr, "Missing value of -b\n");
137 print_help();
139 memset(clipboard_str, 0, 32);
140 strncpy(clipboard_str, argv[i], 31);
141 } else {
142 fprintf(stderr, "Invalid option -%c\n", *(arg + 1));
143 print_help();
145 } else {
146 fprintf(stderr, "Invalid option %s\n", arg);
147 print_help();
149 i++;
152 signal(SIGCHLD, SIG_IGN);
154 /* initialize Gtk */
155 gtk_init(&argc, &argv);
157 /* create main window */
158 main_window = gtk_window_new(GTK_WINDOW_TOPLEVEL);
160 /* set the window title */
161 gtk_window_set_title(GTK_WINDOW(main_window), "wmcliphist");
163 /* creat dock icon */
164 dock_app = main_window;
166 /* add event box to main window*/
167 event = gtk_event_box_new();
168 gtk_container_add(GTK_CONTAINER(dock_app), event);
170 /* set the default window size */
171 gtk_window_set_default_size(GTK_WINDOW(dock_app), icon_size, icon_size);
173 /* set default icon */
174 icon_file = "ico_60x060_gray.png";
176 if (icon_size) {
177 /* create icon_mask */
178 if (icon_size == 60) {
179 /* 60x60 icon */
180 if (icon_number == 0) {
181 icon_file = "ico_60x60_gray.png";
182 } else if (icon_number == 1) {
183 icon_file = "ico_60x60_black.png";
184 } else {
185 icon_file = "ico_60x60_white.png";
187 } else if (icon_size == 40) {
188 /* 40x40 icon */
189 /* create icon */
190 if (icon_number == 0) {
191 icon_file = "ico_40x40_gray.png";
192 } else if (icon_number == 1) {
193 icon_file = "ico_40x40_black.png";
194 } else {
195 icon_file = "ico_40x40_white.png";
197 } else if (icon_size == 30) {
198 /* 30x30 icon */
199 /* create icon */
200 if (icon_number == 0) {
201 icon_file = "ico_30x30_gray.png";
202 } else if (icon_number == 1) {
203 icon_file = "ico_30x30_black.png";
204 } else {
205 icon_file = "ico_30x30_white.png";
207 } else {
208 /* 16x16 icon */
209 /* create icon */
210 icon_file = "ico_16x16.png";
213 icon_file = g_strconcat(DATADIR"/", icon_file, NULL);
214 pixmap = gtk_image_new_from_file(icon_file);
215 gtk_widget_show(pixmap);
216 gtk_container_add(GTK_CONTAINER(event), pixmap);
219 /* use only mouse events */
220 gtk_widget_add_events(dock_app, GDK_BUTTON_PRESS_MASK);
222 gtk_widget_show(dock_app);
223 gtk_widget_show_all(main_window);
225 /* transparenter Hintergrund für pixmap*/
226 if (icon_size) {
227 cairo_region_t *region;
228 cairo_surface_t *surface;
230 surface = cairo_image_surface_create_from_png(icon_file);
231 region = gdk_cairo_region_create_from_surface(surface);
232 gdk_window_shape_combine_region(gtk_widget_get_window(dock_app),
233 region, 0, 0);
237 /* set the window as a dockapp*/
238 display = gdk_display_get_default();
240 mywmhints.icon_window = GDK_WINDOW_XID(gtk_widget_get_window(main_window));
241 mywmhints.window_group = GDK_WINDOW_XID(gtk_widget_get_window(main_window));
242 mywmhints.icon_x = 0;
243 mywmhints.icon_y = 0;
244 mywmhints.flags = IconWindowHint | StateHint;
245 mywmhints.initial_state = WithdrawnState;
247 XSetWMHints(GDK_DISPLAY_XDISPLAY(display), GDK_WINDOW_XID(gtk_widget_get_window(main_window)), &mywmhints);
249 /* create clipboard history menu */
250 menu_hist = gtk_menu_new();
251 menu_title = gtk_menu_item_new();
252 gtk_menu_shell_append(GTK_MENU_SHELL(menu_hist), menu_title);
253 gtk_widget_show(menu_title);
254 gtk_widget_show(menu_hist);
257 /* create application menu */
258 menu_app = gtk_menu_new();
260 menu_app_clip_lock = gtk_check_menu_item_new_with_label("Clipboard lock");
261 gtk_menu_shell_append(GTK_MENU_SHELL(menu_app), menu_app_clip_lock);
263 menu_app_clip_ignore = gtk_check_menu_item_new_with_label("Clipboard ignore");
264 gtk_menu_shell_append(GTK_MENU_SHELL(menu_app), menu_app_clip_ignore);
266 menu_app_save = gtk_menu_item_new_with_label("Save history");
267 gtk_menu_shell_append(GTK_MENU_SHELL(menu_app), menu_app_save);
268 g_signal_connect(G_OBJECT(menu_app_save),
269 "activate",
270 G_CALLBACK(menu_app_item_click),
271 GINT_TO_POINTER(0));
273 menu_app_exit = gtk_menu_item_new_with_label("Exit");
274 gtk_menu_shell_append(GTK_MENU_SHELL(menu_app), menu_app_exit);
275 g_signal_connect(G_OBJECT(menu_app_exit),
276 "activate",
277 G_CALLBACK(menu_app_item_click),
278 GINT_TO_POINTER(1));
280 gtk_widget_show_all(menu_app);
282 list_node = action_list;
283 while (list_node) {
284 ACTION *action = list_node->data;
286 if (action->action == ACT_SUBMENU &&
287 strcmp(action->command, "-") != 0) {
288 action->menu_item = gtk_menu_item_new_with_label(
289 action->command);
290 gtk_menu_shell_append(GTK_MENU_SHELL(menu_hist),
291 action->menu_item);
292 action->submenu = gtk_menu_new();
293 gtk_menu_item_set_submenu(
294 GTK_MENU_ITEM(action->menu_item),
295 action->submenu);
296 menu_title = gtk_menu_item_new();
297 gtk_menu_shell_append(GTK_MENU_SHELL(action->submenu), menu_title);
298 gtk_widget_show(menu_title);
299 gtk_widget_show(action->menu_item);
300 gtk_widget_show(action->submenu);
301 submenu_count++;
303 if (action->action == ACT_SUBMENU &&
304 strcmp(action->command, "-") == 0) {
305 printf("'%s'\n", action->command);
306 action->submenu = menu_hist;
308 list_node = list_node->next;
310 if (submenu_count) {
311 GtkWidget *separator;
313 separator = gtk_menu_item_new();
314 gtk_widget_show(separator);
315 gtk_menu_shell_insert(GTK_MENU_SHELL(menu_hist), separator, 1);
319 /* prepare colors and styles */
320 if (gdk_rgba_parse(&locked_color, locked_color_str) == FALSE) {
321 char msg_str[128];
323 sprintf(msg_str, "Invalid color string: '%s'.\n"
324 "Falling back to default (red).",
325 locked_color_str);
326 show_message(msg_str, "Warning", "OK", NULL, NULL);
327 strcpy(locked_color_str, DEF_LOCKED_COLOR);
328 gdk_rgba_parse(&locked_color, locked_color_str);
332 /* set clipboard */
333 if (strcmp(clipboard_str, "PRIMARY") == 0) {
334 clipboard = GDK_SELECTION_PRIMARY;
335 } else if (strcmp(clipboard_str, "SECONDARY") == 0) {
336 clipboard = GDK_SELECTION_SECONDARY;
337 } else if (strcmp(clipboard_str, "CLIPBOARD") == 0) {
338 clipboard = GDK_SELECTION_CLIPBOARD;
339 } else {
340 char msg_str[128];
342 sprintf(msg_str, "Invalid clipboard string: '%s'.\n"
343 "Falling back to default ("
344 DEF_CLIPBOARD_STR
345 ").",
346 clipboard_str);
347 show_message(msg_str, "Warning", "OK", NULL, NULL);
348 clipboard = DEF_CLIPBOARD;
351 /* load previously saved history */
352 if (history_load(dump_only) != 0) {
353 if (errno == E_TOO_MUCH) {
354 if (show_message("Number of items to keep (-n switch or "
355 "keep directive in ~/.wmcliphistrc)\n"
356 "is lower than actual number of items "
357 "in history file.\nSome items from "
358 "history will be lost. May I continue?",
359 "Warning", "Yes", "No", NULL) == 1) {
360 rcconfig_free();
361 exit(1);
363 } else if (errno != E_OPEN) {
364 rcconfig_free();
365 fprintf(stderr, "cannot load history (%d)\n", errno);
366 exit(1);
369 if (dump_only) {
370 rcconfig_free();
371 exit(1);
375 /* run clipboard monitor */
376 g_signal_connect(G_OBJECT(main_window),
377 "selection_received",
378 G_CALLBACK(my_get_xselection),
379 NULL);
380 g_timeout_add(250, time_conv_select, NULL);
383 /* run autosave timer */
384 if (autosave_period > 0)
385 g_timeout_add(autosave_period * 1000, history_autosave, NULL);
388 /* setup everything for supplying selection to other apps */
389 gtk_selection_add_target(dock_app,
390 clipboard,
391 GDK_SELECTION_TYPE_STRING,
394 g_signal_connect(G_OBJECT(dock_app),
395 "selection_get",
396 G_CALLBACK(selection_handle),
397 NULL);
399 /* connect signal for menu popup */
400 g_signal_connect(G_OBJECT(dock_app),
401 "event",
402 G_CALLBACK(button_press),
403 NULL);
405 g_signal_connect(G_OBJECT(dock_app),
406 "destroy",
407 G_CALLBACK(wmcliphist_exit),
408 NULL);
411 hotkeys_init();
413 gtk_main();
415 return_val(0);