wmshutdown: Destroy dialog window before shutting down. This is especially useful...
[dockapps.git] / wmcliphist / history.c
blob0f3f07830abf25522da0aa8960bd9ae270a987d8
1 #include "wmcliphist.h"
4 int autosave_period = 120;
5 int confirm_exec = 0;
6 int exec_immediately = 1;
8 /*
9 * process new history item
11 void
12 process_item(char *content, gint locked, gboolean exec)
14 GList *list_node;
15 ACTION *action;
16 gboolean processed = FALSE;
17 HISTORY_ITEM *hist_item;
19 begin_func("process_item");
21 list_node = g_list_first(action_list);
22 while (list_node) {
24 action = (ACTION *)list_node->data;
26 /* check if some action is requested */
27 if (regexec(&action->expression, content, 0, NULL, 0) != 0) {
28 list_node = g_list_next(list_node);
29 continue;
32 /* match - execute requested action */
34 if (action->action == ACT_IGNORE) {
35 processed = TRUE;
36 break;
38 if (action->action == ACT_EXEC && exec_immediately == TRUE
39 && exec == TRUE) {
40 exec_item(content, action);
42 if (action->action == ACT_SUBMENU) {
43 /* test if such item already exists in this menu */
44 processed = TRUE;
46 /* add item to menu and item list */
47 hist_item = menu_item_add(content, locked,
48 action->submenu);
50 /* when auto_take_up is true, set selection owner to myself */
51 if (auto_take_up == 1) {
52 selected = hist_item;
53 if (gtk_selection_owner_set(dock_app,
54 clipboard,
55 GDK_CURRENT_TIME) == 0) {
56 selected = NULL;
60 dump_history_list("added item");
61 break;
64 list_node = g_list_next(list_node);
67 if (processed == FALSE) {
68 hist_item = menu_item_add(content, locked, menu_hist);
70 /* when auto_take_up is true, set selection owner to myself */
71 if (auto_take_up == 1) {
72 selected = hist_item;
73 if (gtk_selection_owner_set(dock_app,
74 clipboard,
75 GDK_CURRENT_TIME) == 0) {
76 selected = NULL;
81 return_void();
84 void
85 move_item_to_begin(HISTORY_ITEM *item) {
86 GList *list_node;
88 begin_func("menu_item_activated");
90 if (!(list_node = g_list_find(history_items, item))) {
91 g_assert((list_node != NULL));
94 gtk_menu_popdown(GTK_MENU(menu_hist));
95 /* move previously stored item to beginning */
96 gtk_menu_reorder_child(GTK_MENU(item->menu),
97 item->menu_item, 1);
98 history_items = g_list_remove_link(history_items, list_node);
99 history_items = g_list_concat(list_node, history_items);
100 selected = item;
101 if (gtk_selection_owner_set(dock_app,
102 clipboard,
103 GDK_CURRENT_TIME) == 0)
104 selected = NULL;
109 * Exec's an action on item.
111 void
112 exec_item(char *content, ACTION *action)
114 int msg_result = 0, res;
115 gchar *msg_buf;
116 gchar *exec_buf;
117 gchar *converted;
119 converted = from_utf8(content);
121 /* If we're not given an action to perform, find the first matching
122 * exec action, and perform it */
123 if (!action) {
124 GList *list_node;
125 ACTION *a;
126 list_node = g_list_first(action_list);
127 while (list_node) {
128 a = (ACTION *)list_node->data;
129 /* check if some action is requested */
130 if ((regexec(&a->expression, converted, 0, NULL, 0)
131 == 0)
132 && (a->action == ACT_EXEC)) {
133 action = a;
134 break;
136 list_node = g_list_next(list_node);
140 if (!action || action->action != ACT_EXEC) {
141 g_free(converted);
142 return;
145 exec_buf = g_new0(char, strlen(converted) +
146 strlen(action->command) + 1);
147 sprintf(exec_buf, action->command, converted);
148 if (confirm_exec) {
149 msg_buf = g_new0(char, strlen(exec_buf) + 256);
150 sprintf(msg_buf, "Do you want to perform the "
151 "following action?\n\n%s\n",
152 exec_buf);
153 msg_result = show_message(msg_buf,
154 "wmcliphist", "Yes", "No", NULL);
155 g_free(msg_buf);
158 /* create child and exec command */
159 if (msg_result == 0 && fork() == 0) {
160 /* child */
161 res = system(exec_buf);
162 if (res == -1)
163 fprintf(stderr, "Cannot exec '%s'\n", exec_buf);
164 else if (res == 127)
165 fprintf(stderr, "/bin/sh not found\n");
166 g_free(exec_buf);
167 g_free(converted);
168 _exit(0);
169 } else {
170 /* parent */
171 g_free(exec_buf);
172 g_free(converted);
177 * loads history from file
180 history_load(gboolean dump_only)
182 gchar *buf;
183 gint len;
184 gint ver;
185 FILE *f;
186 gchar *fname;
187 gint locked;
188 int tmp_errno = 0;
190 begin_func("history_load");
192 fname = rcconfig_get_name(".data");
193 if (!(f = fopen(fname, "r"))) {
194 errno = E_OPEN;
195 return_val(-1);
198 if (fread(&ver, sizeof(gint), 1, f) != 1) {
199 fclose(f);
200 return_val(0);
203 /* delete old history file */
204 if (ver == 0x0001) {
205 fclose(f);
206 if (remove(rcconfig_get_name(".data"))) {
207 errno = E_REMOVE;
208 return_val(-1);
210 return_val(0);
213 if (dump_only) {
214 printf("<history>\n");
216 while (!feof(f)) {
218 if (fread(&len, sizeof(gint), 1, f) != 1)
219 break;
221 if (num_items == num_items_to_keep && !dump_only) {
222 tmp_errno = E_TOO_MUCH;
223 break;
226 buf = g_new0(gchar, len + 1);
227 if (fread(buf, len, 1, f) != 1) {
228 g_free(buf);
229 tmp_errno = E_INVALID;
230 break;
232 buf[len] = '\0';
234 if (fread(&locked, sizeof(gint), 1, f) != 1) {
235 g_free(buf);
236 tmp_errno = E_INVALID;
237 break;
240 if (dump_only) {
241 printf("<item>%s</item>\n", buf);
242 } else {
243 process_item(buf, locked, FALSE);
245 g_free(buf);
248 fclose(f);
250 if (dump_only) {
251 printf("</history>\n");
252 } else {
253 dump_history_list("load_history()");
256 errno = tmp_errno;
258 if (errno == 0)
259 return_val(0);
260 else
261 return_val(-1);
266 * store history to file
269 history_save()
271 char *fname;
272 gint version = VERSION;
273 FILE *f;
274 HISTORY_ITEM *hist_item;
275 GList *list_node;
276 int tmp_errno = 0;
278 begin_func("history_save");
280 fname = g_strdup(rcconfig_get_name(".data.tmp"));
282 if (!(f = fopen(fname, "w"))) {
283 perror("fopen");
284 g_free(fname);
285 errno = E_OPEN;
286 return_val(-1);
289 if ((chmod(fname, S_IRUSR|S_IWUSR)) != 0) {
290 perror("chmod");
291 fclose(f);
292 unlink(fname);
293 g_free(fname);
294 errno = E_OPEN;
295 return_val(-1);
298 if (fwrite(&version, sizeof(gint), 1, f) != 1) {
299 perror("fwrite version");
300 fclose(f);
301 unlink(fname);
302 g_free(fname);
303 errno = E_WRITE;
304 return_val(-1);
307 list_node = g_list_last(history_items);
308 while (list_node) {
309 int length;
310 hist_item = (HISTORY_ITEM *)list_node->data;
311 length = strlen(hist_item->content);
312 if (fwrite(&length, sizeof(gint), 1, f) != 1) {
313 tmp_errno = E_WRITE;
314 break;
316 if (fwrite(hist_item->content, length, 1, f) != 1) {
317 tmp_errno = E_WRITE;
318 break;
320 if (fwrite(&hist_item->locked, sizeof(gint), 1, f) != 1) {
321 tmp_errno = E_WRITE;
322 break;
324 list_node = g_list_previous(list_node);
327 fclose(f);
329 if (!list_node) {
330 if (rename(fname, rcconfig_get_name(".data")) != 0) {
331 perror("rename");
332 unlink(fname);
333 g_free(fname);
334 errno = E_RENAME;
335 return_val(-1);
337 g_free(fname);
338 return_val(0);
341 errno = tmp_errno;
342 unlink(fname);
343 g_free(fname);
345 return_val(-1);
350 * free history data
352 void
353 history_free()
355 HISTORY_ITEM *hist_item;
356 GList *list_node;
358 begin_func("history_free");
360 list_node = g_list_last(history_items);
361 while (list_node) {
362 hist_item = (HISTORY_ITEM *)list_node->data;
363 /* gtk_container_remove(GTK_CONTAINER(hist_item->menu),
364 hist_item->menu_item); */
365 gtk_widget_destroy(hist_item->menu_item);
366 g_free(hist_item->content);
367 g_free(hist_item);
368 list_node = g_list_previous(list_node);
370 g_list_free(history_items);
372 return_void();
377 * autosave timer function
379 gboolean
380 history_autosave()
382 begin_func("history_autosave");
384 history_save();
385 return_val(TRUE);