wmshutdown: Add version 1.3 to repository.
[dockapps.git] / wmcliphist / wmcliphist.c
blob0b5c1a7a2743dbe628c75c1d46fe951cb5d3966a
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 exit(code);
49 return_void();
52 /* gtk3 dockapp code based on wmpasman by Brad Jorsch
53 * <anomie@users.sourceforge.net>
54 * http://sourceforge.net/projects/wmpasman */
56 GtkWidget *foo_create_main_icon_window(GtkWidget *mw, unsigned int s)
58 Display *d;
59 GdkDisplay *display;
60 GtkWidget *foobox;
61 unsigned int dummy3;
62 Window mainwin, iw, p, dummy1, *dummy2, w;
63 XWMHints *wmHints;
65 display = gdk_display_get_default();
66 foobox = gtk_window_new(GTK_WINDOW_POPUP);
68 gtk_window_set_wmclass(GTK_WINDOW(mw), g_get_prgname(), "DockApp");
69 gtk_widget_set_size_request(foobox, s, s);
71 gtk_widget_realize(mw);
72 gtk_widget_realize(foobox);
74 d = GDK_DISPLAY_XDISPLAY(display);
75 mainwin = GDK_WINDOW_XID(gtk_widget_get_window(mw));
76 iw = GDK_WINDOW_XID(gtk_widget_get_window(foobox));
77 XQueryTree(d, mainwin, &dummy1, &p, &dummy2, &dummy3);
78 if (dummy2)
79 XFree(dummy2);
80 w = XCreateSimpleWindow(d, p, 0, 0, 1, 1, 0, 0, 0);
81 XReparentWindow(d, mainwin, w, 0, 0);
82 gtk_widget_show(mw);
83 gtk_widget_show(foobox);
84 wmHints = XGetWMHints(d, mainwin);
85 if (!wmHints)
86 wmHints = XAllocWMHints();
87 wmHints->flags |= IconWindowHint;
88 wmHints->icon_window = iw;
89 XSetWMHints(d, mainwin, wmHints);
90 XFree(wmHints);
91 XReparentWindow(d, mainwin, p, 0, 0);
92 XDestroyWindow(d, w);
94 return foobox;
98 * main func
101 main(int argc, char **argv)
103 gint i = 1, res;
104 gchar *arg;
105 gchar *icon_file;
106 GList *list_node;
107 int icon_number = 0;
108 int icon_size = 60;
109 gboolean dump_only = FALSE;
111 #ifdef FNCALL_DEBUG
112 debug_init_nothreads();
113 #endif
114 begin_func("main");
116 /* load configuration */
117 if ((res = rcconfig_get(rcconfig_get_name("rc"))) != 0) {
118 fprintf(stderr, "~/.wmcliphistrc parse error (%d)\n", res);
119 return_val(1);
122 /* parse command line */
123 while ((arg = argv[i])) {
124 if (*arg == '-') {
125 if (*(arg + 1) == 'h')
126 print_help();
127 else if (*(arg + 1) == 'n') {
128 i++;
129 if (!argv[i]) {
130 fprintf(stderr, "Missing value of -n\n");
131 print_help();
133 num_items_to_keep = atol(argv[i]);
134 } else if (*(arg + 1) == 'c') {
135 i++;
136 if (!argv[i]) {
137 fprintf(stderr, "Missing value of -c\n");
138 print_help();
140 memset(locked_color_str, 0, 32);
141 strncpy(locked_color_str, argv[i], 31);
142 } else if (*(arg + 1) == 'i') {
143 i++;
144 if (!argv[i]) {
145 fprintf(stderr, "Missing value of -i\n");
146 print_help();
148 icon_number = atoi(argv[i]);
149 if (icon_number < 0 || icon_number > 2) {
150 fprintf(stderr, "Invalid value of -i\n");
151 print_help();
153 } else if (*(arg + 1) == 's') {
154 i++;
155 if (!argv[i]) {
156 fprintf(stderr, "Missing value of -s\n");
157 print_help();
159 icon_size = atoi(argv[i]);
160 if (icon_size != 60 && icon_size != 40
161 && icon_size != 30
162 && icon_size != 16
163 && icon_size != 0) {
164 fprintf(stderr, "Invalid value of -s\n");
165 print_help();
167 if (icon_size == 0) {
168 icon_size = 1;
170 } else if (*(arg + 1) == 'd') {
171 dump_only = TRUE;
172 } else if (*(arg + 1) == 'v') {
173 printf("wmcliphist "WMCLIPHIST_VERSION"\n");
174 exit(1);
175 } else if (*(arg + 1) == 'b') {
176 i++;
177 if (!argv[i]) {
178 fprintf(stderr, "Missing value of -b\n");
179 print_help();
181 memset(clipboard_str, 0, 32);
182 strncpy(clipboard_str, argv[i], 31);
183 } else {
184 fprintf(stderr, "Invalid option -%c\n", *(arg + 1));
185 print_help();
187 } else {
188 fprintf(stderr, "Invalid option %s\n", arg);
189 print_help();
191 i++;
194 signal(SIGCHLD, SIG_IGN);
196 /* initialize Gtk */
197 gtk_init(&argc, &argv);
200 /* create main window */
201 main_window = gtk_window_new(GTK_WINDOW_TOPLEVEL);
203 /* creat dock icon */
204 dock_app = foo_create_main_icon_window(main_window, icon_size);
206 if (icon_size) {
207 /* create icon_mask */
208 if (icon_size == 60) {
209 /* 60x60 icon */
210 if (icon_number == 0) {
211 icon_file = "ico_60x60_gray.png";
212 } else if (icon_number == 1) {
213 icon_file = "ico_60x60_black.png";
214 } else {
215 icon_file = "ico_60x60_white.png";
217 } else if (icon_size == 40) {
218 /* 40x40 icon */
219 /* create icon */
220 if (icon_number == 0) {
221 icon_file = "ico_40x40_gray.png";
222 } else if (icon_number == 1) {
223 icon_file = "ico_40x40_black.png";
224 } else {
225 icon_file = "ico_40x40_white.png";
227 } else if (icon_size == 30) {
228 /* 30x30 icon */
229 /* create icon */
230 if (icon_number == 0) {
231 icon_file = "ico_30x30_gray.png";
232 } else if (icon_number == 1) {
233 icon_file = "ico_30x30_black.png";
234 } else {
235 icon_file = "ico_30x30_white.png";
237 } else {
238 /* 16x16 icon */
239 /* create icon */
240 icon_file = "ico_16x16.png";
243 icon_file = g_strconcat(DATADIR"/", icon_file, NULL);
244 pixmap = gtk_image_new_from_file(icon_file);
245 gtk_widget_show(pixmap);
246 gtk_container_add(GTK_CONTAINER(dock_app), pixmap);
250 /* create clipboard history menu */
251 menu_hist = gtk_menu_new();
252 menu_title = gtk_menu_item_new();
253 gtk_menu_shell_append(GTK_MENU_SHELL(menu_hist), menu_title);
254 gtk_widget_show(menu_title);
255 gtk_widget_show(menu_hist);
258 /* create application menu */
259 menu_app = gtk_menu_new();
261 menu_app_clip_lock = gtk_check_menu_item_new_with_label("Clipboard lock");
262 gtk_menu_shell_append(GTK_MENU_SHELL(menu_app), menu_app_clip_lock);
264 menu_app_clip_ignore = gtk_check_menu_item_new_with_label("Clipboard ignore");
265 gtk_menu_shell_append(GTK_MENU_SHELL(menu_app), menu_app_clip_ignore);
267 menu_app_save = gtk_menu_item_new_with_label("Save history");
268 gtk_menu_shell_append(GTK_MENU_SHELL(menu_app), menu_app_save);
269 g_signal_connect(G_OBJECT(menu_app_save),
270 "activate",
271 G_CALLBACK(menu_app_item_click),
272 GINT_TO_POINTER(0));
274 menu_app_exit = gtk_menu_item_new_with_label("Exit");
275 gtk_menu_shell_append(GTK_MENU_SHELL(menu_app), menu_app_exit);
276 g_signal_connect(G_OBJECT(menu_app_exit),
277 "activate",
278 G_CALLBACK(menu_app_item_click),
279 GINT_TO_POINTER(1));
281 gtk_widget_show_all(menu_app);
284 list_node = action_list;
285 while (list_node) {
286 ACTION *action = list_node->data;
288 if (action->action == ACT_SUBMENU &&
289 strcmp(action->command, "-") != 0) {
290 action->menu_item = gtk_menu_item_new_with_label(
291 action->command);
292 gtk_menu_shell_append(GTK_MENU_SHELL(menu_hist),
293 action->menu_item);
294 action->submenu = gtk_menu_new();
295 gtk_menu_item_set_submenu(
296 GTK_MENU_ITEM(action->menu_item),
297 action->submenu);
298 menu_title = gtk_menu_item_new();
299 gtk_menu_shell_append(GTK_MENU_SHELL(action->submenu), menu_title);
300 gtk_widget_show(menu_title);
301 gtk_widget_show(action->menu_item);
302 gtk_widget_show(action->submenu);
303 submenu_count++;
305 if (action->action == ACT_SUBMENU &&
306 strcmp(action->command, "-") == 0) {
307 printf("'%s'\n", action->command);
308 action->submenu = menu_hist;
310 list_node = list_node->next;
312 if (submenu_count) {
313 GtkWidget *separator;
315 separator = gtk_menu_item_new();
316 gtk_widget_show(separator);
317 gtk_menu_shell_insert(GTK_MENU_SHELL(menu_hist), separator, 1);
320 /* prepare colors and styles */
321 if (gdk_rgba_parse(&locked_color, locked_color_str) == FALSE) {
322 char msg_str[128];
324 sprintf(msg_str, "Invalid color string: '%s'.\n"
325 "Falling back to default (red).",
326 locked_color_str);
327 show_message(msg_str, "Warning", "OK", NULL, NULL);
328 strcpy(locked_color_str, DEF_LOCKED_COLOR);
329 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 if (icon_size) {
376 cairo_region_t *region;
377 cairo_surface_t *surface;
379 /* connect signal for menu popup */
380 gtk_widget_add_events(dock_app, GDK_BUTTON_PRESS_MASK);
381 g_signal_connect(G_OBJECT(dock_app),
382 "event",
383 G_CALLBACK(button_press),
384 G_OBJECT(menu_hist));
386 surface = cairo_image_surface_create_from_png(icon_file);
387 region = gdk_cairo_region_create_from_surface(surface);
388 gdk_window_shape_combine_region(gtk_widget_get_window(dock_app),
389 region, 0, 0);
395 /* run clipboard monitor */
396 g_signal_connect(G_OBJECT(main_window),
397 "selection_received",
398 G_CALLBACK(my_get_xselection),
399 NULL);
400 g_timeout_add(250, time_conv_select, NULL);
403 /* run autosave timer */
404 if (autosave_period > 0)
405 g_timeout_add(autosave_period * 1000, history_autosave, NULL);
408 /* setup everything for supplying selection to other apps */
409 gtk_selection_add_target(dock_app,
410 clipboard,
411 GDK_SELECTION_TYPE_STRING,
414 g_signal_connect(G_OBJECT(dock_app),
415 "selection_get",
416 G_CALLBACK(selection_handle),
417 NULL);
419 g_signal_connect(G_OBJECT(dock_app),
420 "destroy",
421 G_CALLBACK(wmcliphist_exit),
422 NULL);
425 hotkeys_init();
427 gtk_main();
429 return_val(0);