Distribute .in files too
[claws.git] / src / plugins / acpi_notifier / acpi_notifier.c
1 /*
2  * acpi_notifier -- for Claws Mail
3  *
4  * Copyright (C) 2005 Colin Leroy <colin@colino.net>
5  *
6  * Sylpheed is a GTK+ based, lightweight, and fast e-mail client
7  * Copyright (C) 1999-2005 Hiroyuki Yamamoto and the Claws Mail Team
8  *
9  * This program is free software; you can redistribute it and/or modify
10  * it under the terms of the GNU General Public License as published by
11  * the Free Software Foundation; either version 3 of the License, or
12  * (at your option) any later version.
13  *
14  * This program is distributed in the hope that it will be useful,
15  * but WITHOUT ANY WARRANTY; without even the implied warranty of
16  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17  * GNU General Public License for more details.
18  *
19  * You should have received a copy of the GNU General Public License
20  * along with this program; if not, write to the Free Software
21  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
22  */
23
24 #ifdef HAVE_CONFIG_H
25 #  include "config.h"
26 #include "claws-features.h"
27 #endif
28
29 #include <glib.h>
30 #include <glib/gi18n.h>
31
32 #include <string.h>
33
34 #include <glib.h>
35 #include <gtk/gtk.h>
36
37 #include "defs.h"
38 #include "claws.h"
39 #include "version.h"
40 #include "prefs.h"
41 #include "prefs_gtk.h"
42 #include "main.h"
43 #include "menu.h"
44 #include "hooks.h"
45 #include "plugin.h"
46 #include "alertpanel.h"
47 #include "utils.h"
48 #include "folder_item_prefs.h"
49
50 #define PREFS_BLOCK_NAME "AcpiNotifier"
51 #define PLUGIN_NAME _("Acpi Notifier")
52
53 typedef struct _PredefinedAcpis {
54         gchar *name;
55         gchar *on_param;
56         gchar *off_param;
57         gchar *file_path;
58         gboolean is_program;
59         gchar *help;
60 } PredefinedAcpis;
61
62 /**
63  * Add your implementation here (and send me the patch!) 
64  */
65 char *acpi_help[] = {
66         "",
67         N_("Make sure that the kernel module 'acerhk' is loaded.\n"
68             "You can get it from http://www.cakey.de/acerhk/"),
69         N_("Make sure that the kernel module 'acer_acpi' is loaded.\n"
70             "You can get it from http://code.google.com/p/aceracpi/"),
71         N_("Make sure that the kernel module 'asus_laptop' is loaded."),
72         N_("Make sure that the kernel module 'asus_acpi' is loaded."),
73         N_("Make sure that the kernel module 'ibm_acpi' is loaded."),
74         N_("Make sure that you have apanelc installed.\n"
75             "You can get it from http://apanel.sourceforge.net/"),
76         NULL
77 };
78 PredefinedAcpis known_implementations[] = {
79         {"Other file", "", "", "", FALSE, NULL},
80
81         {"ACER (acerhk)", "1", "0", "/proc/driver/acerhk/led", FALSE, NULL},
82
83         {"ACER (acer_acpi)", "1", "0", "/proc/acpi/acer/mailled", FALSE, NULL},
84
85         {"ASUS (asus_laptop)", "1", "0", "/sys/class/leds/asus:mail/brightness", FALSE, NULL},
86
87         {"ASUS (asus_acpi)", "1", "0", "/proc/acpi/asus/mled", FALSE, NULL},
88
89         {"IBM (ibm_acpi)", "7 on", "7 off", "/proc/acpi/ibm/led", FALSE, NULL},
90
91         {"Lenovo (tp_smapi)", "on", "off", "/proc/acpi/ibm/light", FALSE, NULL},
92
93         {"Fujitsu (apanel)", "led on", "led off", "apanelc", TRUE, NULL},
94
95         {NULL, NULL, NULL, NULL, FALSE, NULL}
96 };
97
98 static guint folder_hook_id;
99 static guint alertpanel_hook_id;
100
101 struct AcpiNotifierPage
102 {
103         PrefsPage page;
104         
105         GtkWidget *no_mail_off_btn;
106         GtkWidget *no_mail_blink_btn;
107         GtkWidget *no_mail_on_btn;
108         GtkWidget *unread_mail_off_btn;
109         GtkWidget *unread_mail_blink_btn;
110         GtkWidget *unread_mail_on_btn;
111         GtkWidget *new_mail_off_btn;
112         GtkWidget *new_mail_blink_btn;
113         GtkWidget *new_mail_on_btn;
114         GtkWidget *default_implementations_optmenu;
115         GtkWidget *on_value_entry;
116         GtkWidget *off_value_entry;
117         GtkWidget *file_entry;
118         GtkWidget *hbox_acpi_file;
119         GtkWidget *hbox_acpi_values;
120         GtkWidget *warning_label;
121         GtkWidget *warning_box;
122         GtkWidget *blink_on_err_chkbtn;
123 };
124
125 typedef struct _AcpiNotifierPrefs AcpiNotifierPrefs;
126
127 struct _AcpiNotifierPrefs
128 {
129         gint             no_mail_action;
130         gint             unread_mail_action;
131         gint             new_mail_action;
132         gboolean         blink_on_err;
133         gchar           *on_param;      
134         gchar           *off_param;     
135         gchar           *file_path;     
136 };
137
138 AcpiNotifierPrefs acpiprefs;
139
140 static struct AcpiNotifierPage acpi_prefs_page;
141
142 enum {
143         OFF = 0,
144         BLINK,
145         ON
146 } BlinkType;
147
148 static PrefParam param[] = {
149         {"no_mail_action", "0", &acpiprefs.no_mail_action, P_INT,
150          NULL, NULL, NULL},
151         {"unread_mail_action", "0", &acpiprefs.unread_mail_action, P_INT,
152          NULL, NULL, NULL},
153         {"new_mail_action", "1", &acpiprefs.new_mail_action, P_INT,
154          NULL, NULL, NULL},
155         {"blink_on_err", "TRUE", &acpiprefs.blink_on_err, P_BOOL,
156          NULL, NULL, NULL},
157         {"on_param", NULL, &acpiprefs.on_param, P_STRING,
158          NULL, NULL, NULL},
159         {"off_param", NULL, &acpiprefs.off_param, P_STRING,
160          NULL, NULL, NULL},
161         {"file_path", NULL, &acpiprefs.file_path, P_STRING,
162          NULL, NULL, NULL},
163         {NULL, NULL, NULL, P_OTHER, NULL, NULL, NULL}
164 };
165
166 static gboolean check_impl (const gchar *filepath)
167 {
168         int i;
169         for (i = 0; known_implementations[i].name != NULL; i++) {
170                 if (strcmp(known_implementations[i].file_path, filepath))
171                         continue;
172                 if (!known_implementations[i].is_program)
173                         return is_file_exist(filepath);
174                 else {
175                         gchar *cmd = g_strdup_printf("which %s", filepath);
176                         int found = system(cmd);
177                         g_free(cmd);
178                         return (found == 0);
179                 }
180         }
181         return is_file_exist(filepath);
182 }
183
184 static gboolean is_program (const gchar *filepath)
185 {
186         int i;
187         for (i = 0; known_implementations[i].name != NULL; i++) {
188                 if (strcmp(known_implementations[i].file_path, filepath))
189                         continue;
190                 return known_implementations[i].is_program;
191         }
192         return FALSE;
193 }
194
195 static void show_error (struct AcpiNotifierPage *page, const gchar *filepath)
196 {
197         int i;
198         if (!filepath) {
199                 gtk_widget_hide(page->warning_box);
200                 return;
201         }
202         for (i = 0; known_implementations[i].name != NULL; i++) {
203                 if (strcmp(known_implementations[i].file_path, filepath))
204                         continue;
205                 if (known_implementations[i].help) {
206                         gchar *tmp = g_strdup_printf("%s\n%s", 
207                                         _("Control file doesn't exist."),
208                                         known_implementations[i].help);
209                         gtk_label_set_text(GTK_LABEL(page->warning_label), tmp);
210                         g_free(tmp);
211                 } else {
212                         gtk_label_set_text(GTK_LABEL(page->warning_label), 
213                                 _("Control file doesn't exist."));
214                 }
215                 gtk_widget_show_all(page->warning_box);
216                 return;
217         }
218 }
219
220 static void type_activated(GtkMenuItem *menuitem, gpointer data)
221 {
222         GtkWidget *menu, *item;
223         struct AcpiNotifierPage *page = (struct AcpiNotifierPage *)data;
224         gint selected;
225
226         if (page->file_entry == NULL)
227                 return;
228                 
229         menu = gtk_cmoption_menu_get_menu(
230                 GTK_CMOPTION_MENU(page->default_implementations_optmenu));
231         item = gtk_menu_get_active(GTK_MENU(menu));
232         selected = GPOINTER_TO_INT
233                 (g_object_get_data(G_OBJECT(item), MENU_VAL_ID));
234
235         if (selected != 0) {
236                 gtk_widget_hide(page->hbox_acpi_file);
237                 gtk_widget_hide(page->hbox_acpi_values);
238                 gtk_entry_set_text(GTK_ENTRY(page->file_entry), 
239                         known_implementations[selected].file_path);
240                 gtk_entry_set_text(GTK_ENTRY(page->on_value_entry), 
241                         known_implementations[selected].on_param);
242                 gtk_entry_set_text(GTK_ENTRY(page->off_value_entry), 
243                         known_implementations[selected].off_param);
244                 if (!check_impl(known_implementations[selected].file_path))
245                         show_error(page, known_implementations[selected].file_path);
246                 else
247                         show_error(page, NULL);
248         } else {
249                 gtk_widget_show_all(page->hbox_acpi_file);
250                 gtk_widget_show_all(page->hbox_acpi_values);
251         }
252 }
253 static void file_entry_changed (GtkWidget *entry, gpointer data)
254 {
255         struct AcpiNotifierPage *page = (struct AcpiNotifierPage *)data;
256         if (!page->warning_box)
257                 return;
258
259         if (!check_impl(gtk_entry_get_text(GTK_ENTRY(entry))))
260                 show_error(page, gtk_entry_get_text(GTK_ENTRY(entry)));
261         else
262                 show_error(page, NULL);
263 }
264
265 static void acpi_prefs_create_widget_func(PrefsPage * _page,
266                                            GtkWindow * window,
267                                            gpointer data)
268 {
269         struct AcpiNotifierPage *page = (struct AcpiNotifierPage *) _page;
270
271         GtkWidget *vbox;
272         GtkWidget *hbox;
273         GtkWidget *hbox_acpi_file;
274         GtkWidget *hbox_acpi_values;
275         GtkWidget *start_label;
276         GtkWidget *no_mail_label;
277         GtkWidget *no_mail_off_btn;
278         GtkWidget *no_mail_blink_btn;
279         GtkWidget *no_mail_on_btn;
280         GtkWidget *unread_mail_label;
281         GtkWidget *unread_mail_off_btn;
282         GtkWidget *unread_mail_blink_btn;
283         GtkWidget *unread_mail_on_btn;
284         GtkWidget *new_mail_label;
285         GtkWidget *new_mail_off_btn;
286         GtkWidget *new_mail_blink_btn;
287         GtkWidget *new_mail_on_btn;
288         GtkWidget *default_implementations_optmenu;
289         GtkWidget *default_implementations_menu;
290         GtkWidget *on_value_entry;
291         GtkWidget *off_value_entry;
292         GtkWidget *file_entry;
293         GtkWidget *menuitem;
294         GtkWidget *warning_label;
295         GtkWidget *warning_box;
296         GtkWidget *image;
297         GtkWidget *blink_on_err_chkbtn;
298
299         int i;
300         int found = 0;
301
302         vbox = gtk_vbox_new(FALSE, 6);
303         gtk_container_set_border_width (GTK_CONTAINER (vbox), VBOX_BORDER);
304         
305         no_mail_label = gtk_label_new(_(" : no new or unread mail"));
306         unread_mail_label = gtk_label_new(_(" : unread mail"));
307         new_mail_label = gtk_label_new(_(" : new mail"));
308
309         no_mail_off_btn = gtk_radio_button_new_with_label(NULL, _("off"));
310         no_mail_blink_btn = gtk_radio_button_new_with_label_from_widget(
311                 GTK_RADIO_BUTTON(no_mail_off_btn), _("blinking"));
312         no_mail_on_btn = gtk_radio_button_new_with_label_from_widget(
313                 GTK_RADIO_BUTTON(no_mail_off_btn), _("on"));
314
315         unread_mail_off_btn = gtk_radio_button_new_with_label(NULL, _("off"));
316         unread_mail_blink_btn = gtk_radio_button_new_with_label_from_widget(
317                 GTK_RADIO_BUTTON(unread_mail_off_btn), _("blinking"));
318         unread_mail_on_btn = gtk_radio_button_new_with_label_from_widget(
319                 GTK_RADIO_BUTTON(unread_mail_off_btn), _("on"));
320
321         new_mail_off_btn = gtk_radio_button_new_with_label(NULL, _("off"));
322         new_mail_blink_btn = gtk_radio_button_new_with_label_from_widget(
323                 GTK_RADIO_BUTTON(new_mail_off_btn), _("blinking"));
324         new_mail_on_btn = gtk_radio_button_new_with_label_from_widget(
325                 GTK_RADIO_BUTTON(new_mail_off_btn), _("on"));
326
327         on_value_entry = gtk_entry_new();
328         off_value_entry = gtk_entry_new();
329         file_entry = gtk_entry_new();
330         gtk_widget_set_size_request(on_value_entry, 40, -1);
331         gtk_widget_set_size_request(off_value_entry, 40, -1);
332
333         default_implementations_optmenu = gtk_cmoption_menu_new ();
334         default_implementations_menu = gtk_menu_new();
335         gtk_cmoption_menu_set_menu (
336                         GTK_CMOPTION_MENU(default_implementations_optmenu), 
337                         default_implementations_menu);
338         for (i = 0; known_implementations[i].name != NULL; i++) {
339                 MENUITEM_ADD (default_implementations_menu, 
340                                 menuitem, known_implementations[i].name, i);
341                 g_signal_connect(G_OBJECT(menuitem), "activate",
342                                  G_CALLBACK(type_activated),
343                                  page);
344         }
345         
346         hbox = gtk_hbox_new(FALSE, 6);
347         start_label = gtk_label_new(_("LED "));
348         gtk_box_pack_start(GTK_BOX(hbox), start_label, FALSE, FALSE, 0);
349         gtk_box_pack_start(GTK_BOX(hbox), no_mail_off_btn, FALSE, FALSE, 0);
350         gtk_box_pack_start(GTK_BOX(hbox), no_mail_blink_btn, FALSE, FALSE, 0);
351         gtk_box_pack_start(GTK_BOX(hbox), no_mail_on_btn, FALSE, FALSE, 0);
352         gtk_box_pack_start(GTK_BOX(hbox), no_mail_label, FALSE, FALSE, 0);
353         gtk_box_pack_start(GTK_BOX(vbox), hbox, FALSE, FALSE, 0);
354         
355         hbox = gtk_hbox_new(FALSE, 6);
356         start_label = gtk_label_new(_("LED "));
357         gtk_box_pack_start(GTK_BOX(hbox), 
358                         start_label, FALSE, FALSE, 0);
359         gtk_box_pack_start(GTK_BOX(hbox), 
360                         unread_mail_off_btn, FALSE, FALSE, 0);
361         gtk_box_pack_start(GTK_BOX(hbox), 
362                         unread_mail_blink_btn, FALSE, FALSE, 0);
363         gtk_box_pack_start(GTK_BOX(hbox), 
364                         unread_mail_on_btn, FALSE, FALSE, 0);
365         gtk_box_pack_start(GTK_BOX(hbox), 
366                         unread_mail_label, FALSE, FALSE, 0);
367         gtk_box_pack_start(GTK_BOX(vbox), 
368                         hbox, FALSE, FALSE, 0);
369         
370         hbox = gtk_hbox_new(FALSE, 6);
371         start_label = gtk_label_new(_("LED "));
372         gtk_box_pack_start(GTK_BOX(hbox), 
373                         start_label, FALSE, FALSE, 0);
374         gtk_box_pack_start(GTK_BOX(hbox), 
375                         new_mail_off_btn, FALSE, FALSE, 0);
376         gtk_box_pack_start(GTK_BOX(hbox), 
377                         new_mail_blink_btn, FALSE, FALSE, 0);
378         gtk_box_pack_start(GTK_BOX(hbox), 
379                         new_mail_on_btn, FALSE, FALSE, 0);
380         gtk_box_pack_start(GTK_BOX(hbox), 
381                         new_mail_label, FALSE, FALSE, 0);
382         gtk_box_pack_start(GTK_BOX(vbox), 
383                         hbox, FALSE, FALSE, 0);
384         
385         hbox = gtk_hbox_new(FALSE, 6);
386         start_label = gtk_label_new(_("ACPI type: "));
387         gtk_box_pack_start(GTK_BOX(hbox), 
388                         start_label, FALSE, FALSE, 0);
389         gtk_box_pack_start(GTK_BOX(hbox), 
390                         default_implementations_optmenu, FALSE, FALSE, 0);
391         gtk_box_pack_start(GTK_BOX(vbox), 
392                         hbox, FALSE, FALSE, 0);
393
394         hbox_acpi_file = gtk_hbox_new(FALSE, 6);
395         start_label = gtk_label_new(_("ACPI file: "));
396         gtk_box_pack_start(GTK_BOX(hbox_acpi_file), 
397                         start_label, FALSE, FALSE, 0);
398         gtk_box_pack_start(GTK_BOX(hbox_acpi_file), 
399                         file_entry, FALSE, FALSE, 0);
400         gtk_box_pack_start(GTK_BOX(vbox), 
401                         hbox_acpi_file, FALSE, FALSE, 0);
402         g_signal_connect(G_OBJECT(file_entry), "changed",
403                          G_CALLBACK(file_entry_changed), page);
404
405         hbox_acpi_values = gtk_hbox_new(FALSE, 6);
406         start_label = gtk_label_new(_("values - On: "));
407         gtk_box_pack_start(GTK_BOX(hbox_acpi_values), 
408                         start_label, FALSE, FALSE, 0);
409         gtk_box_pack_start(GTK_BOX(hbox_acpi_values), 
410                         on_value_entry, FALSE, FALSE, 0);
411         start_label = gtk_label_new(_(" - Off: "));
412         gtk_box_pack_start(GTK_BOX(hbox_acpi_values), 
413                         start_label, FALSE, FALSE, 0);
414         gtk_box_pack_start(GTK_BOX(hbox_acpi_values), 
415                         off_value_entry, FALSE, FALSE, 0);
416         gtk_box_pack_start(GTK_BOX(vbox), 
417                         hbox_acpi_values, FALSE, FALSE, 0);
418
419         warning_box = gtk_hbox_new(FALSE, 6);
420         
421         image = gtk_image_new_from_stock(GTK_STOCK_DIALOG_WARNING,
422                         GTK_ICON_SIZE_SMALL_TOOLBAR);
423         gtk_box_pack_start(GTK_BOX(warning_box), image, FALSE, FALSE, 0);
424         warning_label = gtk_label_new(
425                         _("Control file doesn't exist."));
426         gtk_box_pack_start(GTK_BOX(warning_box), warning_label, FALSE, FALSE, 0);
427         gtk_box_pack_start(GTK_BOX(vbox), warning_box, FALSE, FALSE, 0);
428
429         gtk_widget_show_all(vbox);
430         gtk_widget_hide(warning_box);
431
432         blink_on_err_chkbtn = gtk_check_button_new_with_label(
433                 _("Blink when user interaction is required"));
434         gtk_box_pack_start(GTK_BOX(vbox), blink_on_err_chkbtn, FALSE, FALSE, 0);
435         gtk_toggle_button_set_active(
436                         GTK_TOGGLE_BUTTON(blink_on_err_chkbtn),
437                         acpiprefs.blink_on_err);
438         gtk_widget_show(blink_on_err_chkbtn);
439
440         switch (acpiprefs.no_mail_action) {
441         case OFF:       
442                 gtk_toggle_button_set_active(
443                         GTK_TOGGLE_BUTTON(no_mail_off_btn), TRUE); 
444                 break;
445         case BLINK:     
446                 gtk_toggle_button_set_active(
447                         GTK_TOGGLE_BUTTON(no_mail_blink_btn), TRUE); 
448                 break;
449         case ON:        
450                 gtk_toggle_button_set_active(
451                         GTK_TOGGLE_BUTTON(no_mail_on_btn), TRUE); 
452                 break;
453         }
454         
455         switch (acpiprefs.unread_mail_action) {
456         case OFF:       
457                 gtk_toggle_button_set_active(
458                         GTK_TOGGLE_BUTTON(unread_mail_off_btn), TRUE); 
459                 break;
460         case BLINK:     
461                 gtk_toggle_button_set_active(
462                         GTK_TOGGLE_BUTTON(unread_mail_blink_btn), TRUE); 
463                 break;
464         case ON:        
465                 gtk_toggle_button_set_active(
466                         GTK_TOGGLE_BUTTON(unread_mail_on_btn), TRUE); 
467                 break;
468         }
469         
470         switch (acpiprefs.new_mail_action) {
471         case OFF:       
472                 gtk_toggle_button_set_active(
473                         GTK_TOGGLE_BUTTON(new_mail_off_btn), TRUE); 
474                 break;
475         case BLINK:     
476                 gtk_toggle_button_set_active(
477                         GTK_TOGGLE_BUTTON(new_mail_blink_btn), TRUE); 
478                 break;
479         case ON:        
480                 gtk_toggle_button_set_active(
481                         GTK_TOGGLE_BUTTON(new_mail_on_btn), TRUE); 
482                 break;
483         }
484         
485         if (acpiprefs.file_path != NULL) {
486                 for (i = 0; known_implementations[i].name != NULL; i++) {
487                         if (!strcmp(acpiprefs.file_path, 
488                                     known_implementations[i].file_path)) {
489                                 gtk_cmoption_menu_set_history(
490                                         GTK_CMOPTION_MENU(
491                                         default_implementations_optmenu), i);
492                                 found = i;
493                         }
494                 }
495         }
496         if (found == 0) {
497                 for (i = 0; known_implementations[i].name != NULL; i++) {
498                         if (check_impl(known_implementations[i].file_path)) {
499                                 gtk_cmoption_menu_set_history(
500                                         GTK_CMOPTION_MENU(
501                                         default_implementations_optmenu), i);
502                                 found = i;
503                         }
504                 }
505         }
506         page->page.widget = vbox;
507
508         page->no_mail_off_btn = no_mail_off_btn;
509         page->no_mail_blink_btn = no_mail_blink_btn;
510         page->no_mail_on_btn = no_mail_on_btn;
511         page->unread_mail_off_btn = unread_mail_off_btn;
512         page->unread_mail_blink_btn = unread_mail_blink_btn;
513         page->unread_mail_on_btn = unread_mail_on_btn;
514         page->new_mail_off_btn = new_mail_off_btn;
515         page->new_mail_blink_btn = new_mail_blink_btn;
516         page->new_mail_on_btn = new_mail_on_btn;
517         page->default_implementations_optmenu = default_implementations_optmenu;
518         page->on_value_entry = on_value_entry;
519         page->off_value_entry = off_value_entry;
520         page->file_entry = file_entry;
521         page->hbox_acpi_file = hbox_acpi_file;
522         page->hbox_acpi_values = hbox_acpi_values;
523         page->warning_box = warning_box;
524         page->warning_label = warning_label;
525         page->blink_on_err_chkbtn = blink_on_err_chkbtn;
526
527         if (found != 0) {
528                 gtk_widget_hide(hbox_acpi_file);
529                 gtk_widget_hide(hbox_acpi_values);
530                 gtk_entry_set_text(GTK_ENTRY(file_entry), 
531                         known_implementations[found].file_path);
532                 gtk_entry_set_text(GTK_ENTRY(on_value_entry), 
533                         known_implementations[found].on_param);
534                 gtk_entry_set_text(GTK_ENTRY(off_value_entry), 
535                         known_implementations[found].off_param);
536                 
537                 if (!check_impl(known_implementations[found].file_path))
538                         show_error(page, known_implementations[found].file_path);
539         } else {
540                 gtk_cmoption_menu_set_history(
541                         GTK_CMOPTION_MENU(default_implementations_optmenu), 0);
542                 gtk_widget_show_all(hbox_acpi_file);
543                 gtk_widget_show_all(hbox_acpi_values);
544                 if (acpiprefs.file_path != NULL)
545                         gtk_entry_set_text(GTK_ENTRY(file_entry), 
546                                         acpiprefs.file_path);
547                 if (acpiprefs.on_param != NULL)
548                         gtk_entry_set_text(GTK_ENTRY(on_value_entry), 
549                                         acpiprefs.on_param);
550                 if (acpiprefs.off_param != NULL)
551                         gtk_entry_set_text(GTK_ENTRY(off_value_entry), 
552                                         acpiprefs.off_param);
553                 if (!acpiprefs.file_path || !check_impl(acpiprefs.file_path))
554                         show_error(page, acpiprefs.file_path);
555         }
556 }
557
558 static void acpi_prefs_destroy_widget_func(PrefsPage *_page)
559 {
560 }
561
562 static void acpi_prefs_save_func(PrefsPage * _page)
563 {
564         struct AcpiNotifierPage *page = (struct AcpiNotifierPage *) _page;
565         PrefFile *pfile;
566         gchar *rcpath;
567         GtkWidget *menu;
568         GtkWidget *menuitem;
569         gint selected = 0;
570
571         g_free(acpiprefs.file_path);
572         acpiprefs.file_path = gtk_editable_get_chars(
573                         GTK_EDITABLE(page->file_entry), 0, -1);
574         g_free(acpiprefs.on_param);
575         acpiprefs.on_param = gtk_editable_get_chars(
576                         GTK_EDITABLE(page->on_value_entry), 0, -1);
577         g_free(acpiprefs.off_param);
578         acpiprefs.off_param = gtk_editable_get_chars(
579                         GTK_EDITABLE(page->off_value_entry), 0, -1);
580
581         if (gtk_toggle_button_get_active(
582                 GTK_TOGGLE_BUTTON(page->no_mail_off_btn)))
583                 acpiprefs.no_mail_action = OFF;
584         else if (gtk_toggle_button_get_active(
585                 GTK_TOGGLE_BUTTON(page->no_mail_blink_btn)))
586                 acpiprefs.no_mail_action = BLINK;
587         else if (gtk_toggle_button_get_active(
588                 GTK_TOGGLE_BUTTON(page->no_mail_on_btn)))
589                 acpiprefs.no_mail_action = ON;
590         
591         if (gtk_toggle_button_get_active(
592                 GTK_TOGGLE_BUTTON(page->unread_mail_off_btn)))
593                 acpiprefs.unread_mail_action = OFF;
594         else if (gtk_toggle_button_get_active(
595                 GTK_TOGGLE_BUTTON(page->unread_mail_blink_btn)))
596                 acpiprefs.unread_mail_action = BLINK;
597         else if (gtk_toggle_button_get_active(
598                 GTK_TOGGLE_BUTTON(page->unread_mail_on_btn)))
599                 acpiprefs.unread_mail_action = ON;
600         
601         if (gtk_toggle_button_get_active(
602                 GTK_TOGGLE_BUTTON(page->new_mail_off_btn)))
603                 acpiprefs.new_mail_action = OFF;
604         else if (gtk_toggle_button_get_active(
605                 GTK_TOGGLE_BUTTON(page->new_mail_blink_btn)))
606                 acpiprefs.new_mail_action = BLINK;
607         else if (gtk_toggle_button_get_active(
608                 GTK_TOGGLE_BUTTON(page->new_mail_on_btn)))
609                 acpiprefs.new_mail_action = ON;
610         
611         acpiprefs.blink_on_err = gtk_toggle_button_get_active(
612                 GTK_TOGGLE_BUTTON(page->blink_on_err_chkbtn));
613
614         menu = gtk_cmoption_menu_get_menu(
615                 GTK_CMOPTION_MENU(page->default_implementations_optmenu));
616         menuitem = gtk_menu_get_active(GTK_MENU(menu));
617         selected = GPOINTER_TO_INT
618                 (g_object_get_data(G_OBJECT(menuitem), MENU_VAL_ID));
619
620         if (selected != 0) {
621                 g_free(acpiprefs.file_path);
622                 acpiprefs.file_path = g_strdup(
623                                 known_implementations[selected].file_path);
624                 g_free(acpiprefs.on_param);
625                 acpiprefs.on_param = g_strdup(
626                                 known_implementations[selected].on_param);
627                 g_free(acpiprefs.off_param);
628                 acpiprefs.off_param = g_strdup(
629                                 known_implementations[selected].off_param);
630         }
631
632         rcpath = g_strconcat(get_rc_dir(), G_DIR_SEPARATOR_S, COMMON_RC, NULL);
633         pfile = prefs_write_open(rcpath);
634         g_free(rcpath);
635         if (!pfile || (prefs_set_block_label(pfile, PREFS_BLOCK_NAME) < 0))
636                 return;
637
638         if (prefs_write_param(param, pfile->fp) < 0) {
639                 g_warning("failed to write " PREFS_BLOCK_NAME 
640                           " configuration to file\n");
641                 prefs_file_close_revert(pfile);
642                 return;
643         }
644         if (fprintf(pfile->fp, "\n") < 0) {
645                 FILE_OP_ERROR(rcpath, "fprintf");
646                 prefs_file_close_revert(pfile);
647         } else
648                 prefs_file_close(pfile);
649 }
650
651 static void acpi_set(gboolean on)
652 {
653         FILE *fp = NULL;
654
655         if (!acpiprefs.file_path) {
656                 debug_print("acpiprefs.file_path NULL\n");
657                 return;
658         }
659         if (!check_impl(acpiprefs.file_path)) {
660                 debug_print("acpiprefs.file_path not implemented\n");
661                 return;
662         }
663         if (!acpiprefs.on_param || !acpiprefs.off_param) {
664                 debug_print("no param\n");
665                 return;
666         }
667
668         if (!is_program(acpiprefs.file_path)) {
669                 fp = fopen(acpiprefs.file_path, "wb");
670                 if (fp == NULL)
671                         return;
672
673                 if (on) {
674                         fwrite(acpiprefs.on_param, 1, strlen(acpiprefs.on_param), fp);
675                 } else {
676                         fwrite(acpiprefs.off_param, 1, strlen(acpiprefs.off_param), fp);
677                 }
678                 fclose(fp);
679         } else {
680                 gchar *cmd = g_strdup_printf("%s %s", 
681                                 acpiprefs.file_path,
682                                 on ? acpiprefs.on_param:acpiprefs.off_param);
683                 execute_command_line(cmd, TRUE);
684                 g_free(cmd);
685         }
686 }
687
688 static guint should_quit = FALSE;
689 static int last_blink = 0;
690
691 static gint acpi_blink(gpointer data)
692 {
693         if (!should_quit) {
694                 acpi_set(last_blink); 
695                 last_blink = !last_blink; 
696                 return TRUE;
697         } else {
698                 acpi_set(FALSE);
699                 return FALSE;
700         }
701 }
702
703 static int blink_timeout_id = 0;
704 static int alertpanel_blink_timeout_id = 0;
705 static gint my_new = -1, my_unread = -1;
706 static int my_action = -1;
707
708 static gboolean acpi_update_hook(gpointer source, gpointer data)
709 {
710         int action = 0;
711         guint new, unread, unreadmarked, marked, total;
712         guint replied, forwarded, locked, ignored, watched;
713         
714         if (alertpanel_blink_timeout_id)
715                 return FALSE;
716
717         folder_count_total_msgs(&new, &unread, &unreadmarked, &marked, &total,
718                                 &replied, &forwarded, &locked, &ignored, &watched);
719
720         if (my_new != new || my_unread != unread) {
721                 my_new = new;
722                 my_unread = unread;
723                 if (my_new > 0) {
724                         action = acpiprefs.new_mail_action;
725                 } else if (my_unread > 0) {
726                         action = acpiprefs.unread_mail_action;
727                 } else {
728                         action = acpiprefs.no_mail_action;
729                 }
730                 
731                 if (action != my_action) {
732                         my_action = action;
733                         
734                         if (action != BLINK && blink_timeout_id != 0) {
735                                 g_source_remove(blink_timeout_id);
736                                 blink_timeout_id = 0;
737                         }
738
739                         switch (action) {
740                         case ON: 
741                                 acpi_set(TRUE); 
742                                 break;
743                         case BLINK:     
744                                 acpi_set(TRUE); 
745                                 last_blink = FALSE; 
746                                 blink_timeout_id = g_timeout_add(1000, acpi_blink, NULL);
747                                 break;
748                         case OFF:       
749                                 acpi_set(FALSE); 
750                                 break;
751                         }
752                 }
753         }
754
755         return FALSE;
756 }
757
758 static gboolean acpi_alertpanel_hook(gpointer source, gpointer data)
759 {
760         gboolean *opened = (gboolean *)source;
761
762         if (*opened == TRUE) {
763                 if (blink_timeout_id)
764                         g_source_remove(blink_timeout_id);
765                 blink_timeout_id = 0;
766                 
767                 if (alertpanel_blink_timeout_id)
768                         return FALSE;
769                 
770                 acpi_set(TRUE); 
771                 last_blink = FALSE; 
772                 alertpanel_blink_timeout_id = g_timeout_add(250, acpi_blink, NULL);
773         } else {
774                 if (alertpanel_blink_timeout_id)
775                         g_source_remove(alertpanel_blink_timeout_id);
776                 alertpanel_blink_timeout_id = 0;
777                 my_new = -1;
778                 my_unread = -1;
779                 my_action = -1;
780                 acpi_update_hook(NULL, NULL);
781         }
782         return FALSE;
783 }
784
785 void acpi_prefs_init(void)
786 {
787         static gchar *path[3];
788         gchar *rcpath;
789
790         path[0] = _("Plugins");
791         path[1] = PLUGIN_NAME;
792         path[2] = NULL;
793
794         prefs_set_default(param);
795         rcpath = g_strconcat(get_rc_dir(), G_DIR_SEPARATOR_S, COMMON_RC, NULL);
796         prefs_read_config(param, PREFS_BLOCK_NAME, rcpath, NULL);
797         g_free(rcpath);
798
799         acpi_prefs_page.page.path = path;
800         acpi_prefs_page.page.create_widget = acpi_prefs_create_widget_func;
801         acpi_prefs_page.page.destroy_widget = acpi_prefs_destroy_widget_func;
802         acpi_prefs_page.page.save_page = acpi_prefs_save_func;
803
804         prefs_gtk_register_page((PrefsPage *) &acpi_prefs_page);
805         folder_hook_id = hooks_register_hook (FOLDER_ITEM_UPDATE_HOOKLIST, 
806                         acpi_update_hook, NULL);
807         alertpanel_hook_id = hooks_register_hook (ALERTPANEL_OPENED_HOOKLIST, 
808                         acpi_alertpanel_hook, NULL);
809         should_quit = FALSE;
810 }
811
812 void acpi_prefs_done(void)
813 {
814         should_quit = TRUE;
815         acpi_set(FALSE); 
816         if (claws_is_exiting())
817                 return;
818         prefs_gtk_unregister_page((PrefsPage *) &acpi_prefs_page);
819         hooks_unregister_hook(FOLDER_ITEM_UPDATE_HOOKLIST, folder_hook_id);
820         hooks_unregister_hook(ALERTPANEL_OPENED_HOOKLIST, alertpanel_hook_id);
821 }
822
823
824 void acpi_init(void)
825 {
826         gint i;
827         for (i = 0; acpi_help[i] != NULL; i++)
828                 known_implementations[i].help = 
829                         *acpi_help[i] ? _(acpi_help[i]) : "";
830         acpi_prefs_init();
831 }
832
833 void acpi_done(void)
834 {
835         acpi_prefs_done();
836 }
837
838 gint plugin_init(gchar **error)
839 {
840         if( !check_plugin_version(MAKE_NUMERIC_VERSION(3,8,1,46),
841                                 VERSION_NUMERIC, PLUGIN_NAME, error) )
842                 return -1;
843
844         acpi_init();
845         return 0;
846 }
847
848 gboolean plugin_done(void)
849 {
850         if (blink_timeout_id)
851                 g_source_remove(blink_timeout_id);
852         if (alertpanel_blink_timeout_id)
853                 g_source_remove(alertpanel_blink_timeout_id);
854
855         acpi_done();
856         return TRUE;
857 }
858
859 const gchar *plugin_name(void)
860 {
861         return PLUGIN_NAME;
862 }
863
864 const gchar *plugin_desc(void)
865 {
866         return _("This plugin handles various ACPI mail LEDs.");
867 }
868
869 const gchar *plugin_type(void)
870 {
871         return "GTK2";
872 }
873
874 const gchar *plugin_licence(void)
875 {
876         return "GPL3+";
877 }
878
879 const gchar *plugin_version(void)
880 {
881         return VERSION;
882 }
883
884 struct PluginFeature *plugin_provides(void)
885 {
886         static struct PluginFeature features[] = 
887                 { {PLUGIN_NOTIFIER, N_("Laptop LED")},
888                   {PLUGIN_NOTHING, NULL}};
889         return features;
890 }