wmshutdown: Destroy dialog window before shutting down. This is especially useful...
[dockapps.git] / wmtrash / wmtrash.c
blob1b5059f1dca8f77e1e1b72953156729458a05e66
1 /*
2 * this file is part of the "wmtrash" project
3 * Copyright (C) 2004 by Jean Philippe GUILLEMIN <jp.guillemin@free.fr>
4 * license: This software is under GPL license
5 * rev: 0.2
6 */
9 #include <stdio.h>
10 #include <unistd.h>
11 #include <stdlib.h>
12 #include <string.h>
13 #include <getopt.h>
14 #include <sysexits.h>
15 #include <gtk/gtk.h>
16 #include <gdk/gdk.h>
17 #include <gdk/gdkx.h>
18 #include "wmtrash.h"
21 // Start main *******************************************************************
23 int main( int argc, char *argv[] ) {
25 // Here we parse command line args and configfile *******************************************************************
26 GtkWidget *dockapp;
27 static char *defaultcf;
28 static char *configfile;
29 static char *homecf;
30 static char *homedir;
31 homecf = malloc(MEDIUM_STRING);
32 configfile = malloc(MEDIUM_STRING);
34 defaultcf = malloc(MEDIUM_STRING);
35 strncpy(defaultcf, __CONFPATH, MEDIUM_STRING);
36 strcat(defaultcf, "/");
37 strcat(defaultcf, __CONFFILE);
39 homedir = malloc(SHORT_STRING);
40 homedir = getenv("HOME");
42 strncpy(homecf, homedir, SHORT_STRING);
43 strcat(homecf, "/");
44 strcat(homecf, ".wmtrash.cf");
46 int test1, test2;
47 if ((test1 = access(homecf, F_OK)) == -1){
48 if ((test2 = fcopy(defaultcf, homecf)) == EXIT_FAILURE){
49 fprintf (stderr,"Error creating config file %s !\n",homecf);
53 int i;
55 if (argc < 2){
56 configfile = homecf;
57 }else{
58 while ((i = getopt(argc, argv, "hc:")) != EOF){
59 switch (i){
60 case 'c': /* config file */
61 strncpy(configfile, optarg, MEDIUM_STRING);
62 break;
63 case 'h': usage(homecf, defaultcf); exit (EXIT_SUCCESS);
69 gtk_init(&argc, &argv);
70 dockapp = (GtkWidget *) build_dockapp(configfile);
71 gtk_widget_show_all (dockapp);
72 gtk_main ();
73 return(0);
74 } // end main
77 GtkWidget * build_dockapp(char *configfile) {
78 static GtkWidget *mainwin;
79 static GtkWidget *mainbox;
80 static GtkWidget *box;
81 static GtkWidget *pixmap;
82 static GdkBitmap *mask;
83 static GtkWidget *pixmap_widget;
85 static struct wmtrash *wmtrash;
86 wmtrash = malloc(sizeof(struct wmtrash));
87 memset(wmtrash, 0, sizeof(struct wmtrash));
90 char *image_path_file;
92 strncpy (wmtrash->param_img, "trashicon", MEDIUM_STRING);
93 strncpy (wmtrash->param_fm, "filemanager", MEDIUM_STRING);
94 strncpy (wmtrash->param_path, "trashpath", MEDIUM_STRING);
95 strncpy (wmtrash->configfile, configfile, MEDIUM_STRING);
97 image_path_file = malloc(LONG_STRING);
99 parse_from_config(wmtrash->configfile, wmtrash->param_img, wmtrash->imagefile);
100 sprintf(image_path_file, "%s/%s", __ICONPATH, wmtrash->imagefile);
101 parse_from_config(wmtrash->configfile, wmtrash->param_fm, wmtrash->fm);
102 parse_from_config(wmtrash->configfile, wmtrash->param_path, wmtrash->path);
104 // GTK stuff *******************************************************************
105 gtk_widget_destroy(mainwin);
106 mainwin = gtk_window_new(GTK_WINDOW_TOPLEVEL);
107 gtk_widget_realize(mainwin);
108 mainbox = create_main_dockapp_icon_window(mainwin, 52);
110 box = gtk_event_box_new();
111 pixmap = (gpointer) gdk_pixmap_create_from_xpm (mainwin->window, &mask,
112 NULL, image_path_file);
113 pixmap_widget = gtk_pixmap_new((gpointer) pixmap, mask);
114 gtk_container_add(GTK_CONTAINER(box), pixmap_widget);
117 gtk_container_add (GTK_CONTAINER (mainbox), box);
119 gtk_signal_connect (GTK_OBJECT(box), "button_press_event", GTK_SIGNAL_FUNC(launchonclick), wmtrash);
121 free(image_path_file);
122 return mainwin;
126 // Function create_main_dockapp_icon_window (c) 2000, Alexey Vyskubov <alexey@pepper.spb.ru>
128 GtkWidget *create_main_dockapp_icon_window
129 (GtkWidget *mw,
130 unsigned int s)
132 GtkWidget *dockappbox; // This will become icon box
133 Window xmw;
134 XWMHints *wm_hints;
136 xmw = GDK_WINDOW_XWINDOW(mw->window);
138 dockappbox = gtk_event_box_new();
139 gtk_widget_set_usize(dockappbox, s, s);
140 gtk_container_add (GTK_CONTAINER (mw), dockappbox);
141 gtk_widget_realize(dockappbox);
143 // Time for game with Xlib
144 wm_hints = XAllocWMHints();
145 wm_hints->window_group = xmw;
146 wm_hints->icon_window = GDK_WINDOW_XWINDOW(dockappbox->window);
147 wm_hints->icon_x = 0;
148 wm_hints->icon_y = 0;
149 wm_hints->initial_state = WithdrawnState;
150 wm_hints->flags = StateHint |
151 IconPositionHint |
152 WindowGroupHint |
153 IconWindowHint;
155 XSetWMHints(GDK_DISPLAY(), xmw, wm_hints);
157 XFree(wm_hints);
159 return dockappbox;
160 } // end create_main_dockapp_icon_window
163 /* the function to execute command when left button is clicked *************************************
164 or change the command and pixmap icon when right button is 2-clicked */
166 void launchonclick
167 (GtkWidget *event_box,
168 GdkEventButton *event,
169 struct wmtrash *data)
171 char *cmd;
172 cmd=malloc(BIG_STRING);
173 memset(cmd, 0, BIG_STRING);
175 /* left button of mouse is clicked */
176 if(event->button == 1){
177 strcat (cmd, data->fm);
178 strcat (cmd, " ");
179 strcat (cmd, data->path);
180 strcat (cmd, "&");
181 //fprintf(stderr, cmd); //debug
182 int output = system(cmd);
183 if (output){
184 fprintf(stderr, "error launching command in function \"launchonclick\"\n");
186 return;
188 if((event->button == 3)&&(event->type == GDK_2BUTTON_PRESS)) {
189 strcat (cmd, "rm -rf");
190 strcat (cmd, " ");
191 strcat (cmd, data->path);
192 strcat (cmd, "/* ");
193 strcat (cmd, data->path);
194 strcat (cmd, "/.*");
195 //fprintf(stderr, cmd); //debug
196 int output = system(cmd);
197 if (output){
198 fprintf(stderr, "error launching command in function \"launchonclick\"\n");
200 return;
203 /* right button of mouse is 2-clicked */
204 if((event->button == 2)&&(event->type == GDK_2BUTTON_PRESS)){
206 /* create a new text entry window for entering the new command */
207 GtkWidget *dialog, *table, *vbox;
208 GtkWidget *entry1, *entry2, *button;
209 // window parameters
210 dialog = gtk_window_new (GTK_WINDOW_TOPLEVEL);
211 gtk_window_set_title (GTK_WINDOW (dialog), "Change command & pixmap");
212 gtk_container_set_border_width (GTK_CONTAINER (dialog), 5);
215 table = gtk_table_new(2,2, TRUE);
216 gtk_table_set_col_spacings(GTK_TABLE (table), 5);
217 gtk_table_set_row_spacings(GTK_TABLE (table), 5);
219 vbox = gtk_vbox_new (FALSE, 0);
221 // entry box parameters
222 entry1 = gtk_entry_new ();
223 entry2 = gtk_entry_new ();
224 gtk_entry_set_max_length (GTK_ENTRY (entry1), 120);
225 gtk_entry_set_max_length (GTK_ENTRY (entry2), 120);
227 gtk_signal_connect (GTK_OBJECT (entry1), "changed", GTK_SIGNAL_FUNC (enter_callback1), data);
228 gtk_signal_connect (GTK_OBJECT (entry2), "changed", GTK_SIGNAL_FUNC (enter_callback2), data);
230 gtk_entry_set_text (GTK_ENTRY (entry1), data->fm);
231 gtk_entry_set_text (GTK_ENTRY (entry2), data->path);
232 gtk_editable_set_editable (GTK_EDITABLE (entry1), TRUE);
233 gtk_entry_set_visibility (GTK_ENTRY (entry1), TRUE);
234 gtk_editable_set_editable (GTK_EDITABLE (entry2), TRUE);
235 gtk_entry_set_visibility (GTK_ENTRY (entry2), TRUE);
237 // button parameters
238 button = gtk_button_new_with_label("OK");
239 //label = gtk_label_new ("OK");
240 gtk_signal_connect (GTK_OBJECT (button), "clicked", GTK_SIGNAL_FUNC (close_callback), data);
242 gtk_container_add (GTK_CONTAINER (vbox), entry1);
243 gtk_container_add (GTK_CONTAINER (vbox), entry2);
245 gtk_table_attach_defaults(GTK_TABLE(table), vbox, 0,1, 0,2);
246 gtk_table_attach_defaults(GTK_TABLE(table), button, 1,2, 0,2);
248 gtk_container_add (GTK_CONTAINER (dialog), table);
249 gtk_widget_show_all(dialog);
251 return;
253 free(cmd);
254 } // end launchonclick
256 /* some callback to handle change of values in entry boxes************************* */
257 void enter_callback1(
258 GtkWidget *entry,
259 struct wmtrash *data){
260 char *entry_text;
261 entry_text = malloc(BIG_STRING);
262 memset(entry_text, 0, BIG_STRING);
263 strncpy (entry_text, gtk_entry_get_text (GTK_ENTRY (entry)), BIG_STRING);
264 memset(data->fm, 0, BIG_STRING);
265 strncpy (data->fm, entry_text, BIG_STRING);
268 void enter_callback2(
269 GtkWidget *entry,
270 struct wmtrash *data){
271 char *entry_text;
272 entry_text = malloc(BIG_STRING);
273 memset(entry_text, 0, BIG_STRING);
274 strncpy (entry_text, gtk_entry_get_text (GTK_ENTRY (entry)), BIG_STRING);
275 memset(data->path, 0, BIG_STRING);
276 strncpy (data->path, entry_text, BIG_STRING);
279 void close_callback(
280 GtkWidget *entry,
281 struct wmtrash *data){
283 GtkWidget *parent;
284 GtkWidget *dockapp;
285 replace_value_in_config(data->configfile, data->param_fm, data->fm);
286 replace_value_in_config(data->configfile, data->param_path, data->path);
287 parent = gtk_widget_get_ancestor(entry, GTK_TYPE_WINDOW);
288 gtk_widget_destroy(parent); // close the dialog box
289 dockapp = (GtkWidget *) build_dockapp(data->configfile); // will redraw icons
290 gtk_widget_show_all (dockapp);
294 // the function to parse the config file for parameters *********************************************
295 int parse_from_config
296 (char *filename,
297 char *param,
298 char *value)
300 int c = 0;
301 FILE *file;
302 char *sep,
303 *buffer,
304 *line,
305 *val;
306 line = malloc(LONG_STRING);
307 buffer = malloc(MEDIUM_STRING);
308 sep = malloc(SHORT_STRING);
309 val = malloc(MEDIUM_STRING);
311 if((file=fopen(filename, "rb")) == 0) {
312 fprintf (stderr,"Error opening file %s !\n",filename);
313 exit(EXIT_FAILURE);
316 while (fgets (line, LONG_STRING, file) !=NULL) {
317 if (strstr (line, "[") !=0) continue;
318 if (strstr (line, "#") !=0) continue;
319 memset(val, 0, MEDIUM_STRING);
320 c = sscanf (line, "%s %s %s", buffer, sep, val);
322 if (strncmp (param, buffer, MEDIUM_STRING) == 0) {
323 memset(value, 0, BIG_STRING);
325 strncpy(value,line + strlen(buffer) + strlen(sep) +2, BIG_STRING);
326 //fprintf(stderr,"%s\n", value);
327 char *p = strchr (value, '\n');
328 if (p){
329 *p = 0;
331 fclose (file);
332 return(EXIT_SUCCESS);
334 memset(line, 0, LONG_STRING);
336 fclose (file);
337 free(sep);
338 free(buffer);
339 free(line);
340 free(val);
341 return(EXIT_FAILURE);
342 } // end parse_from_config
345 // the function to parse the config file to replace the value of a given parameter ****************************
346 int replace_value_in_config
347 (char *filename,
348 char *param,
349 char *new_value)
351 int c = 0;
352 FILE *file;
353 char *bigbuffer,
354 *sep,
355 *buffer,
356 *line,
357 *old_value;
358 bigbuffer = malloc(EXTRALONG_STRING);
359 line = malloc(LONG_STRING);
360 buffer = malloc(MEDIUM_STRING);
361 sep = malloc(MEDIUM_STRING);
362 old_value = malloc(BIG_STRING);
364 if((file=fopen(filename, "rb")) == 0) {
365 fprintf (stderr,"Error opening file %s !\n",filename);
366 exit(EXIT_FAILURE);
369 memset(bigbuffer, 0, EXTRALONG_STRING);
370 while (fgets (line, LONG_STRING, file) !=NULL) {
371 memset(buffer, 0, MEDIUM_STRING);
372 c = sscanf (line, "%s %s %s\n", buffer, sep, old_value);
374 if (strncmp (param, buffer, MEDIUM_STRING) == 0) {
375 memset(line, 0, LONG_STRING);
376 sprintf(line, "%s %s %s\n", buffer, sep, new_value);
379 strncat (bigbuffer, line, LONG_STRING);
380 memset(line, 0, LONG_STRING);
382 fclose (file);
384 if((file=fopen(filename, "w+")) == 0) {
385 fprintf (stderr,"Error opening file %s !\n",filename);
386 exit(EXIT_FAILURE);
388 fprintf(file,bigbuffer);
389 fclose (file);
390 memset(bigbuffer, 0, EXTRALONG_STRING);
392 free(bigbuffer);
393 free(sep);
394 free(buffer);
395 free(line);
396 free(old_value);
397 return(EXIT_SUCCESS);
398 } // end replace_value_in_config *************************************************************************
405 int usage(char *homecf, char *defaultcf) {
406 fprintf(stdout,"\nwmtrash v0.2 : Desktop trash dockapp\n");
407 fprintf(stdout, "Usage : \n");
408 fprintf(stdout,"- single LEFT click : browse trash\n");
409 fprintf(stdout,"- double MIDDLE click : change location & filemanager\n");
410 fprintf(stdout,"- double RIGHT click : empty trash\n");
411 fprintf(stdout, "---------------\n");
412 fprintf(stdout, "How to start it : \n"
413 "\t wmtrash [-c path_to_configfile] use a custom config\n"
414 "\t wmtrash [-h] display this help\n");
415 fprintf(stdout, "---------------\n");
416 fprintf(stdout,"home config file is %s\n", homecf);
417 fprintf(stdout,"default config file is %s\n",defaultcf);
418 return(EXIT_SUCCESS);
419 } // end usage
420 //*************************************************************************
424 // this one just copy sfile into dfile :)
425 int fcopy( char *sfile,
426 char *dfile){
427 int c; /* Character read/written between files */
428 FILE *IPFile; /* Pointer to the I/P file. FILE is a
429 structure defined in <stdio.h> */
430 FILE *OPFile;
432 /* Open the file - */
433 if ((IPFile = fopen(sfile,"r")) == 0) {
434 fprintf (stderr,"Error opening file %s !\n",sfile);
435 return (EXIT_FAILURE);
437 if ((OPFile = fopen(dfile,"w")) == 0) {
438 fprintf (stderr,"Error opening file %s !\n",dfile);
439 return (EXIT_FAILURE);
441 /* Read one character at a time, checking
442 for the End of File. EOF is defined
443 in <stdio.h> as -1 */
444 while ((c = fgetc(IPFile)) != EOF){
445 fputc(c, OPFile); /* O/P the character */
448 fclose(IPFile); /* Close the files. */
449 fclose(OPFile); /* Close the files. */
450 return (EXIT_SUCCESS);
451 } // end fcopy