2 * WMClockMon - A dockapp to display time and date
3 * Copyright (C) 2002 Thomas Nemeth <tnemeth@free.fr>
5 * Based on work by Seiichi SATO <ssato@sh.rim.or.jp>
6 * Copyright (C) 2001,2002 Seiichi SATO <ssato@sh.rim.or.jp>
7 * And on work by Mark Staggs <me@markstaggs.net>
8 * Copyright (C) 2002 Mark Staggs <me@markstaggs.net>
10 * This program is free software; you can redistribute it and/or modify
11 * it under the terms of the GNU General Public License as published by
12 * the Free Software Foundation; either version 2 of the License, or
13 * (at your option) any later version.
15 * This program is distributed in the hope that it will be useful,
16 * but WITHOUT ANY WARRANTY; without even the implied warranty of
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 * GNU General Public License for more details.
20 * You should have received a copy of the GNU General Public License
21 * along with this program; if not, write to the Free Software
22 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
35 #include <sys/types.h>
41 #include "backlightB_on.xpm"
42 #include "backlightB_off.xpm"
43 #include "backlightI_on.xpm"
44 #include "backlightI_off.xpm"
45 #include "backlight0_on.xpm"
46 #include "backlight0_off.xpm"
48 #include "letters.xpm"
51 #define FREE(data) {if (data) free(data); data = NULL;}
52 #define SET_STRING(str, val) {if (str) free(str); str = xstrdup(val);}
54 #if defined(netbsd) || defined(openbsd) || defined(freebsd) || defined(darwin)
59 #define DEFAULT_CFGFILE ".wmclockmonrc"
60 #define DEFAULT_CONFIGDIR ".wmclockmoncal"
63 #define WINDOWED_BG ". c #AEAAAE"
64 #define MAX_HISTORY 16
65 #define CPUNUM_NONE -1
71 typedef enum { LIGHTON
, LIGHTOFF
} Light
;
73 typedef enum { CLOCK
, INTERNET
, BINARY
} TMode
;
75 typedef enum {T_INT
, T_BOOL
, T_STRING
, T_FILE
} KType
;
78 char *parts_s
, *letters_s
, *itime_s
, *btime_s
; /* styles files */
79 char *parts
, *letters
; /* parts and letters pixmap files */
80 char *backl
, *backu
; /* main pixmap files */
81 char *ibackl
, *ibacku
; /* internet time pixmap files */
82 char *bbackl
, *bbacku
; /* binary time pixmap files */
83 int ncolors
; /* number of shadow colors */
84 int bdigith
, bdigitw
; /* big digits size */
85 int sdigith
, sdigitw
; /* small digits size */
86 int letterh
, letterw
; /* letters size */
87 int bsep
, ssep
, lsep
; /* big, small digits and letters separations */
88 int hposx
, hposy
; /* hours */
89 Bool hbig
; /* big digits for hours */
90 int mposx
, mposy
; /* minutes */
91 Bool mbig
; /* big digits for minutes */
92 int sposx
, sposy
; /* seconds */
93 Bool sbig
, csec
; /* big digits for seconds, colon seconds */
94 int aposx
, aposy
; /* AM display */
95 int pposx
, pposy
; /* PM display */
96 int lposx
, lposy
; /* ALRM display */
97 int wposx
, wposy
; /* week day */
98 int dposx
, dposy
; /* day */
99 int oposx
, oposy
; /* month */
100 int bposx
, bposy
; /* beats */
101 Bool bbig
; /* big digits for beats */
102 int tposx
, tposy
; /* 10th of beat */
103 Bool tbig
, tdisp
; /* big digits for 10th of beats, display them */
104 int gposx
, gposy
; /* beats graph bar */
105 Bool gdisp
; /* display it */
106 int binhx
, binhy
; /* Binary hour X / Y */
107 int binmx
, binmy
; /* Binary minutes X / Y */
108 int binsx
, binsy
; /* Binary seconds X / Y */
109 int binzx
, binzy
; /* Binary time size X / size Y */
110 int binwx
, binwy
; /* Binary weekday X /Y */
111 int bindx
, bindy
; /* Binary day X / Y */
112 int binox
, binoy
; /* Binary month X / Y */
113 int binix
, biniy
; /* Binary date size X / Y */
114 int bind1x
, bind1y
; /* Binary delta X / delta Y, time same number */
115 int bind2x
, bind2y
; /* Binary delta X / delta Y, time tens->units */
116 int bind3x
, bind3y
; /* Binary delta X / delta Y, date same number */
117 int bind4x
, bind4y
; /* Binary delta X / delta Y, date tens->units */
129 typedef struct Alarm
{
140 static Style default_style
= {
142 NULL
, NULL
, NULL
, NULL
, /* styles files */
143 NULL
, NULL
, /* parts and letters pixmap files */
144 NULL
, NULL
, /* main pixmap files */
145 NULL
, NULL
, /* internet time pixmap files */
146 NULL
, NULL
, /* binary time pixmap files */
148 2, /* number of shadow colors */
149 20, 10, /* big digits size */
150 9, 5, /* small digits size */
151 7, 5, /* letters size */
152 /* DEFAULT THEME - MAIN PART */
153 2, 1, 1, /* big, small digits and letters separations */
154 5, 6, True
, /* hours pos and size */
155 32, 6, True
, /* minutes pos and size */
156 43, 28, False
, False
, /* seconds pos, size and colon */
160 5, 47, /* day of week */
163 20, 6, True
, /* beats */
164 /* DEFAULT THEME - BEATS FOR INTERNET TIME */
165 49, 28, False
, True
, /* 10th of beat pos, size and display */
166 6, 45, True
, /* graph pos and display */
167 /* DEFAULT THEME - BINARY PART */
168 5, 5, /* Binary hour X / Y */
169 23, 5, /* Binary minutes X / Y */
170 41, 5, /* Binary seconds X / Y */
171 6, 6, /* Binary time size X / size Y */
172 14, 38, /* Binary weekday X /Y */
173 25, 38, /* Binary day X / Y */
174 43, 38, /* Binary month X / Y */
175 4, 3, /* Binary date size X / Y */
176 0, 2, /* Binary delta X / delta Y, time same number */
177 2, 0, /* Binary delta X / delta Y, time tens->units */
178 0, 1, /* Binary delta X / delta Y, date same number */
179 2, 0 /* Binary delta X / delta Y, date tens->units */
183 static char *upcases
[] = {
184 "A", "B", "C", "D", "E", "F", "G", "H", "I", "J", "K", "L", "M",
185 "N", "O", "P", "Q", "R", "S", "T", "U", "V", "W", "X", "Y", "Z", "\250",
194 Pixmap backdropI_off
;
196 Pixmap backdropB_off
;
201 static char *display_name
= "";
202 static char *light_color
= NULL
; /* led or backlight color */
203 static unsigned update_interval
= 1;
204 static char *style_name
= NULL
;
205 static char *style_dir
= NULL
;
206 static Light backlight
= LIGHTOFF
;
207 static Bool switch_authorized
= True
;
208 static char *command
= NULL
;
209 static char *msgcmd
= NULL
;
210 static char *message
= NULL
;
211 static Alarm
*alarms
= NULL
;
212 static char *config_file
= NULL
;
213 static time_t config_mtime
= 0;
214 static Bool h12
= False
;
215 static TMode time_mode
= CLOCK
;
216 static Bool showcal
= False
;
217 static Bool calalrms
= False
;
218 static Bool use_locale
= True
;
219 static struct tm
*timeinfos
;
220 static double swtime
;
221 static char* label
= NULL
;
225 static void rotate_style();
226 static Bool
stringdiff(const char *s1
, const char *s2
);
227 static char *set_filename(const char *file_name
, const char *ext
);
228 static Bool
set_style_value(StyleDef opt
, char *value
);
229 static void set_style_default(StyleDef opt
);
230 static void load_stylepart(const char *filename
, StyleDef
*opts
);
231 static void load_style(const char *stylename
);
232 static void init_pixmap(char **src_pix
, Pixmap
*dst_pix
, const char *text
,
233 XpmColorSymbol
*c
, int n
, int keep_mask
);
234 static void init_pixfile(char *src_name
, Pixmap
*dst_pix
, const char *text
,
235 XpmColorSymbol
*c
, int n
, int keep_mask
);
236 static void graphics_init();
237 static void control(unsigned int btn
, int x
, int y
, unsigned int state
);
238 static void draw_dockapp();
239 static void update();
240 static void switch_light();
241 static void draw_background(Light back
);
242 static void draw_bigdigit(int num
, int x
, int y
);
243 static void draw_smalldigit(int num
, int x
, int y
);
244 static char equiv(char letter
);
245 static void draw_textdigit(const char *text
, int x
, int y
);
246 static void draw_timedigit();
247 static void draw_datedigit();
248 static void draw_itimedigit();
249 static void draw_binarytime();
250 static void parse_arguments(int argc
, char **argv
);
251 static void print_help(char *prog
);
252 static void time_update();
253 static Bool
raise_alarm();
254 static Bool
fexist(const char *filename
);
255 static Bool
filestat(const char *filename
, time_t *time
, int mode
);
256 static int my_system(char *cmd
, char *opt
);
257 void *xmalloc(size_t size
);
258 char *xstrdup(const char *string
);
259 static void alrm_add(Alarm
**list
, const char *value
);
260 static void free_alrm(Alarm
**list
);
261 static int nb_alrm(Alarm
*list
);
262 static Bool
alarms_on(Alarm
*list
);
263 static void switch_alarms(Alarm
*list
);
264 static Bool
getbool(char *value
);
265 static Bool
load_cfgfile();
266 static char *get_calend_file(int type
);
267 static int cal_alrms_chg();
268 static void load_cal_file(int type
);
269 static void load_calalrms();
270 static void reload_alarms();
271 static void show_cal_file(int type
);
272 static void show_cal();
273 static char *robust_home();
274 static void signal_reload();
278 int main(int argc
, char **argv
) {
282 sa
.sa_handler
= SIG_IGN
;
284 sa
.sa_flags
= SA_NOCLDWAIT
;
288 sigemptyset(&sa
.sa_mask
);
289 sigaction(SIGCHLD
, &sa
, NULL
);
291 /* Set default for style dir : */
292 SET_STRING(style_dir
, DATADIR
);
297 /* Load default configuration file */
299 char *Home
= robust_home();
300 config_file
= xmalloc(strlen(Home
) + strlen(DEFAULT_CFGFILE
) + 2);
301 sprintf(config_file
, "%s/%s", Home
, DEFAULT_CFGFILE
);
306 /* Parse CommandLine */
307 parse_arguments(argc
, argv
);
310 char *Home
= robust_home();
311 config_file
= xmalloc(strlen(Home
) + strlen(DEFAULT_CFGFILE
) + 2);
312 sprintf(config_file
, "%s/%s", Home
, DEFAULT_CFGFILE
);
316 style
= default_style
;
317 load_style(style_name
);
320 setlocale(LC_TIME
, "");
321 setlocale(LC_CTYPE
, "");
322 setlocale(LC_COLLATE
, "");
325 /* Initialize Application */
326 dockapp_open_window(display_name
, argv
[0], SIZE
, SIZE
, argc
, argv
);
327 dockapp_set_eventmask(ButtonPressMask
);
331 if (showcal
) show_cal();
335 if (dockapp_nextevent_or_timeout(&event
, update_interval
* 1000 - 10)) {
337 switch (event
.type
) {
339 control(event
.xbutton
.button
,
342 event
.xbutton
.state
);
356 static void rotate_style() {
358 struct dirent
*dir_ent
;
360 Bool is_next
= False
;
362 if (! style_dir
) return;
363 if ((dir
= opendir(style_dir
)) == NULL
) return;
364 while ((dir_ent
= readdir(dir
)) != NULL
) {
365 if (strstr(dir_ent
->d_name
, ".mwcs") != NULL
) {
366 if (is_next
|| (! style_name
)) {
367 next
= xstrdup(dir_ent
->d_name
);
371 if (style_name
&& (strstr(style_name
, dir_ent
->d_name
) != NULL
))
378 style_name
= xmalloc(strlen(next
)+strlen(style_dir
)+2);
379 sprintf(style_name
, "%s/%s", style_dir
, next
);
383 FREE(style
.letters_s
);
394 style
= default_style
;
400 static Bool
stringdiff(const char *s1
, const char *s2
) {
401 if (!s1
&& !s2
) return False
;
402 if (!s1
&& s2
) return True
;
403 if (s1
&& !s2
) return True
;
404 if (strcmp(s1
, s2
) == 0) return False
;
409 static char *set_filename(const char *file_name
, const char *ext
) {
410 int length
= style_dir
? strlen(style_dir
) + 1 : 0;
411 char *filename
= NULL
;
412 if (! file_name
) return NULL
;
413 if ((file_name
[0] == '.') || (file_name
[0] == '/') ||
414 (ext
&& (strstr(file_name
, ext
) != NULL
))) { /* local file */
416 filename
= xstrdup(file_name
);
417 e
= strrchr(filename
, '/');
418 if ((!style_dir
) && (e
!= NULL
)) {
420 int i
= 0, style_len
= strlen(filename
) - strlen(e
);
421 style_dir
= xmalloc(style_len
+ 2);
423 style_dir
[i
++] = p
[0];
429 length
+= strlen(file_name
);
430 length
+= ext
? strlen(ext
) + 1 : 1;
431 filename
= xmalloc(length
);
432 sprintf(filename
, "%s%s%s%s",
433 style_dir
? style_dir
: "",
434 style_dir
? "/" : "",
442 static Bool
set_style_value(StyleDef opt
, char *value
) {
444 char *string1
= NULL
;
445 char *string2
= NULL
;
449 *(int *)(opt
.var
) = atoi(value
);
452 *(Bool
*)(opt
.var
) = getbool(value
);
455 string1
= *(char **)(opt
.var
);
456 SET_STRING(string1
, value
);
457 *(char **)(opt
.var
) = string1
;
460 string1
= *(char **)(opt
.var
);
461 string2
= set_filename(value
, NULL
);
462 SET_STRING(string1
, string2
);
463 *(char **)(opt
.var
) = string1
;
466 default: res
= False
;
472 static void set_style_default(StyleDef opt
) {
473 char *string1
= NULL
;
474 char *string2
= NULL
;
478 *(int *)(opt
.var
) = *(int *)(opt
.defval
);
481 *(Bool
*)(opt
.var
) = *(Bool
*)(opt
.defval
);
484 string1
= *(char **)(opt
.var
);
485 string2
= *(char **)(opt
.defval
);
486 SET_STRING(string1
, string2
);
487 *(char **)(opt
.var
) = string1
;
490 string1
= *(char **)(opt
.var
);
491 string2
= set_filename(*(char **)(opt
.defval
), NULL
);
492 SET_STRING(string1
, string2
);
493 *(char **)(opt
.var
) = string1
;
500 static void load_stylepart(const char *filename
, StyleDef
*opts
) {
504 if ((!filename
) || (filename
[0] == '-')) {
505 for (i
= 0 ; opts
[i
].key
; i
++)
506 set_style_default(opts
[i
]);
509 if ((file
= fopen(filename
, "r")) == NULL
) return;
510 while (!feof(file
)) {
511 char line
[MAXSTRLEN
+ 1], *value
;
513 bzero(line
, MAXSTRLEN
+ 1);
514 fgets(line
, MAXSTRLEN
, file
);
517 if (line
[strlen(line
) - 1] == '\n') line
[strlen(line
) - 1] = 0;
518 if ((line
[0] == '#') || (line
[0] == 0)) continue;
519 value
= strchr(line
, '=') + 1;
520 while ((value
[0] == ' ') && (value
[0] != 0)) value
++;
521 if (value
[0] == 0) continue;
523 for (j
= 0 ; opts
[j
].key
; j
++) {
524 int length
= strlen(opts
[j
].key
);
525 if (strlen(line
) <= length
) continue;
526 if (strncmp(line
, opts
[j
].key
, length
) == 0) {
527 set_style_value(opts
[j
], value
);
533 fprintf(stderr
, "Error in %s at line %d :\n[%s].\n",
539 static void load_style(const char *stylename
) {
540 StyleDef parts_style_opts
[] = {
541 {"Parts", T_FILE
, &style
.parts
, &default_style
.parts
},
542 {"BDigitHeight", T_INT
, &style
.bdigith
, &default_style
.bdigith
},
543 {"BDigitWidth", T_INT
, &style
.bdigitw
, &default_style
.bdigitw
},
544 {"SDigitHeight", T_INT
, &style
.sdigith
, &default_style
.sdigith
},
545 {"SDigitWidth", T_INT
, &style
.sdigitw
, &default_style
.sdigitw
},
546 {"BDigitSep", T_INT
, &style
.bsep
, &default_style
.bsep
},
547 {"SDigitSep", T_INT
, &style
.ssep
, &default_style
.ssep
},
548 {NULL
, T_STRING
, NULL
}
550 StyleDef letters_style_opts
[] = {
551 {"Letters", T_FILE
, &style
.letters
, &default_style
.letters
},
552 {"LetterHeight", T_INT
, &style
.letterh
, &default_style
.letterh
},
553 {"LetterWidth", T_INT
, &style
.letterw
, &default_style
.letterw
},
554 {"LetterSep", T_INT
, &style
.lsep
, &default_style
.lsep
},
555 {NULL
, T_STRING
, NULL
}
557 StyleDef itime_style_opts
[] = {
558 {"IBacklightOn", T_FILE
, &style
.ibackl
, &default_style
.ibackl
},
559 {"IBacklightOff", T_FILE
, &style
.ibacku
, &default_style
.ibacku
},
560 {"Beats_PosX", T_INT
, &style
.bposx
, &default_style
.bposx
},
561 {"Beats_PosY", T_INT
, &style
.bposy
, &default_style
.bposy
},
562 {"Beats_Big", T_BOOL
, &style
.bbig
, &default_style
.bbig
},
563 {"10thOB_PosX", T_INT
, &style
.tposx
, &default_style
.tposx
},
564 {"10thOB_PosY", T_INT
, &style
.tposy
, &default_style
.tposy
},
565 {"10thOB_Big", T_BOOL
, &style
.tbig
, &default_style
.tbig
},
566 {"10thOB_Display", T_BOOL
, &style
.tdisp
, &default_style
.tdisp
},
567 {"Graph_PosX", T_INT
, &style
.gposx
, &default_style
.gposx
},
568 {"Graph_PosY", T_INT
, &style
.gposy
, &default_style
.gposy
},
569 {"Graph_Display", T_BOOL
, &style
.gdisp
, &default_style
.gdisp
},
570 {NULL
, T_STRING
, NULL
}
572 StyleDef btime_style_opts
[] = {
573 {"BBacklightOn", T_FILE
, &style
.bbackl
, &default_style
.bbackl
},
574 {"BBacklightOff", T_FILE
, &style
.bbacku
, &default_style
.bbacku
},
575 {"Bin_HX", T_INT
, &style
.binhx
, &default_style
.binhx
},
576 {"Bin_HY", T_INT
, &style
.binhy
, &default_style
.binhy
},
577 {"Bin_MX", T_INT
, &style
.binmx
, &default_style
.binmx
},
578 {"Bin_MY", T_INT
, &style
.binmy
, &default_style
.binmy
},
579 {"Bin_SX", T_INT
, &style
.binsx
, &default_style
.binsx
},
580 {"Bin_SY", T_INT
, &style
.binsy
, &default_style
.binsy
},
581 {"Bin_ZX", T_INT
, &style
.binzx
, &default_style
.binzx
},
582 {"Bin_ZY", T_INT
, &style
.binzy
, &default_style
.binzy
},
583 {"Bin_WX", T_INT
, &style
.binwx
, &default_style
.binwx
},
584 {"Bin_WY", T_INT
, &style
.binwy
, &default_style
.binwy
},
585 {"Bin_DX", T_INT
, &style
.bindx
, &default_style
.bindx
},
586 {"Bin_DY", T_INT
, &style
.bindy
, &default_style
.bindy
},
587 {"Bin_OX", T_INT
, &style
.binox
, &default_style
.binox
},
588 {"Bin_OY", T_INT
, &style
.binoy
, &default_style
.binoy
},
589 {"Bin_IX", T_INT
, &style
.binix
, &default_style
.binix
},
590 {"Bin_IY", T_INT
, &style
.biniy
, &default_style
.biniy
},
591 {"Bin_d1X", T_INT
, &style
.bind1x
, &default_style
.bind1x
},
592 {"Bin_d1Y", T_INT
, &style
.bind1y
, &default_style
.bind1y
},
593 {"Bin_d2X", T_INT
, &style
.bind2x
, &default_style
.bind2x
},
594 {"Bin_d2Y", T_INT
, &style
.bind2y
, &default_style
.bind2y
},
595 {"Bin_d3X", T_INT
, &style
.bind3x
, &default_style
.bind3x
},
596 {"Bin_d3Y", T_INT
, &style
.bind3y
, &default_style
.bind3y
},
597 {"Bin_d4X", T_INT
, &style
.bind4x
, &default_style
.bind4x
},
598 {"Bin_d4Y", T_INT
, &style
.bind4y
, &default_style
.bind4y
},
599 {NULL
, T_STRING
, NULL
}
601 StyleDef main_style_opts
[] = {
602 {"PartsStyle", T_FILE
, &style
.parts_s
, &default_style
.parts_s
},
603 {"LettersStyle", T_FILE
, &style
.letters_s
, &default_style
.letters_s
},
604 {"ITimeStyle", T_FILE
, &style
.itime_s
, &default_style
.itime_s
},
605 {"BTimeStyle", T_FILE
, &style
.btime_s
, &default_style
.btime_s
},
606 {"BacklightOn", T_FILE
, &style
.backl
, &default_style
.backl
},
607 {"BacklightOff", T_FILE
, &style
.backu
, &default_style
.backu
},
608 {"NbColors", T_INT
, &style
.ncolors
, &default_style
.ncolors
},
609 {"Hours_PosX", T_INT
, &style
.hposx
, &default_style
.hposx
},
610 {"Hours_PosY", T_INT
, &style
.hposy
, &default_style
.hposy
},
611 {"Hours_Big", T_BOOL
, &style
.hbig
, &default_style
.hbig
},
612 {"Minutes_PosX", T_INT
, &style
.mposx
, &default_style
.mposx
},
613 {"Minutes_PosY", T_INT
, &style
.mposy
, &default_style
.mposy
},
614 {"Minutes_Big", T_BOOL
, &style
.mbig
, &default_style
.mbig
},
615 {"Seconds_PosX", T_INT
, &style
.sposx
, &default_style
.sposx
},
616 {"Seconds_PosY", T_INT
, &style
.sposy
, &default_style
.sposy
},
617 {"Seconds_Big", T_BOOL
, &style
.sbig
, &default_style
.sbig
},
618 {"Seconds_Colon", T_BOOL
, &style
.csec
, &default_style
.csec
},
619 {"AM_PosX", T_INT
, &style
.aposx
, &default_style
.aposx
},
620 {"AM_PosY", T_INT
, &style
.aposy
, &default_style
.aposy
},
621 {"PM_PosX", T_INT
, &style
.pposx
, &default_style
.pposx
},
622 {"PM_PosY", T_INT
, &style
.pposy
, &default_style
.pposy
},
623 {"ALRM_PosX", T_INT
, &style
.lposx
, &default_style
.lposx
},
624 {"ALRM_PosY", T_INT
, &style
.lposy
, &default_style
.lposy
},
625 {"Weekday_PosX", T_INT
, &style
.wposx
, &default_style
.wposx
},
626 {"Weekday_PosY", T_INT
, &style
.wposy
, &default_style
.wposy
},
627 {"Day_PosX", T_INT
, &style
.dposx
, &default_style
.dposx
},
628 {"Day_PosY", T_INT
, &style
.dposy
, &default_style
.dposy
},
629 {"Month_PosX", T_INT
, &style
.oposx
, &default_style
.oposx
},
630 {"Month_PosY", T_INT
, &style
.oposy
, &default_style
.oposy
},
631 {NULL
, T_STRING
, NULL
}
633 char *partsfile
= xstrdup(style
.parts_s
);
634 char *lettersfile
= xstrdup(style
.letters_s
);
635 char *itimefile
= xstrdup(style
.itime_s
);
636 char *btimefile
= xstrdup(style
.btime_s
);
639 if (! stylename
) return;
640 filename
= set_filename(stylename
, ".mwcs");
643 load_stylepart(filename
, main_style_opts
);
646 if (stringdiff(partsfile
, style
.parts_s
) == True
)
647 load_stylepart(style
.parts_s
, parts_style_opts
);
650 if (stringdiff(lettersfile
, style
.letters_s
) == True
)
651 load_stylepart(style
.letters_s
, letters_style_opts
);
654 if (stringdiff(itimefile
, style
.itime_s
) == True
)
655 load_stylepart(style
.itime_s
, itime_style_opts
);
658 if (stringdiff(btimefile
, style
.btime_s
) == True
)
659 load_stylepart(style
.btime_s
, btime_style_opts
);
669 static void init_pixmap(char **src_pix
, Pixmap
*dst_pix
, const char *text
,
670 XpmColorSymbol
*c
, int n
, int keep_mask
) {
671 if (*dst_pix
) XFreePixmap(display
, *dst_pix
);
672 if (!dockapp_xpm2pixmap(src_pix
, dst_pix
, &mask
, c
, n
)) {
673 fprintf(stderr
, "Error initializing %s image.\n", text
);
676 if (!keep_mask
&& mask
) XFreePixmap(display
, mask
);
680 static void init_pixfile(char *src_name
, Pixmap
*dst_pix
, const char *text
,
681 XpmColorSymbol
*c
, int n
, int keep_mask
) {
682 if (*dst_pix
) XFreePixmap(display
, *dst_pix
);
683 if (!dockapp_file2pixmap(src_name
, dst_pix
, &mask
, c
, n
)) {
684 fprintf(stderr
, "Error initializing %s image.\n", text
);
687 if (!keep_mask
&& mask
) XFreePixmap(display
, mask
);
691 static void graphics_init() {
692 XpmColorSymbol colors
[3] = { {"Back0", NULL
, 0}, {"Back1", NULL
, 0}, {"Back2", NULL
, 0} };
696 ncolor
= style
.ncolors
;
698 colors
[0].pixel
= dockapp_getcolor(light_color
);
699 colors
[1].pixel
= dockapp_blendedcolor(light_color
, -24, -24, -24, 1.0);
701 colors
[0].pixel
= dockapp_getcolor(light_color
);
702 colors
[1].pixel
= dockapp_dividecolor(light_color
, 3);
703 colors
[2].pixel
= dockapp_blendedcolor(light_color
, -50, -50, -50, 1.0);
707 /* change raw xpm data to pixmap */
709 if (dockapp_iswindowed)
710 backlit_pix[1] = backgrd_pix[1] = WINDOWED_BG;
714 init_pixfile(style
.parts
, &parts
, "parts",
715 colors
, ncolor
, False
);
717 init_pixmap(parts_xpm
, &parts
, "parts",
718 colors
, ncolor
, False
);
721 init_pixfile(style
.letters
, &letters
, "letters",
722 colors
, ncolor
, False
);
724 init_pixmap(letters_xpm
, &letters
, "letters",
725 colors
, ncolor
, False
);
728 init_pixfile(style
.ibackl
, &backdropI_on
, "backlit background 2",
729 colors
, ncolor
, False
);
731 init_pixmap(backlightI_on_xpm
, &backdropI_on
, "backlit background 2",
732 colors
, ncolor
, False
);
735 init_pixfile(style
.ibacku
, &backdropI_off
, "background 2",
736 colors
, ncolor
, False
);
738 init_pixmap(backlightI_off_xpm
, &backdropI_off
, "background 2",
739 colors
, ncolor
, False
);
742 init_pixfile(style
.bbackl
, &backdropB_on
, "backlit background 3",
743 colors
, ncolor
, False
);
745 init_pixmap(backlightB_on_xpm
, &backdropB_on
, "backlit background 3",
746 colors
, ncolor
, False
);
749 init_pixfile(style
.bbacku
, &backdropB_off
, "background 3",
750 colors
, ncolor
, False
);
752 init_pixmap(backlightB_off_xpm
, &backdropB_off
, "background 3",
753 colors
, ncolor
, False
);
756 init_pixfile(style
.backl
, &backdrop_on
, "backlit background",
757 colors
, ncolor
, False
);
759 init_pixmap(backlight0_on_xpm
, &backdrop_on
, "backlit background",
760 colors
, ncolor
, False
);
763 init_pixfile(style
.backu
, &backdrop_off
, "background",
764 colors
, ncolor
, True
);
766 init_pixmap(backlight0_off_xpm
, &backdrop_off
, "background",
767 colors
, ncolor
, True
);
770 if (!dockapp_iswindowed
) dockapp_setshape(mask
, 0, 0);
771 if (mask
) XFreePixmap(display
, mask
);
773 /* pixmap : draw area */
774 if (pixmap
) XFreePixmap(display
, pixmap
);
775 pixmap
= dockapp_XCreatePixmap(SIZE
, SIZE
);
777 /* Initialize pixmap */
778 draw_background(backlight
);
780 dockapp_set_background(pixmap
);
786 static void control(unsigned int btn
, int x
, int y
, unsigned int state
) {
789 if (time_mode
== CLOCK
) {
790 if ( (x
>= style
.aposx
) && (x
<= style
.aposx
+ 12) &&
791 (y
>= style
.aposy
) && (y
<= style
.aposy
+ 7) ) {
794 } else if ( (x
>= style
.pposx
) && (x
<= style
.pposx
+ 12) &&
795 (y
>= style
.pposy
) && (y
<= style
.pposy
+ 7) ) {
798 } else if ( (x
>= style
.lposx
) && (x
<= style
.lposx
+ 22) &&
799 (y
>= style
.lposy
) && (y
<= style
.lposy
+ 7) ) {
800 if (alarms
) switch_alarms(alarms
);
804 if (state
& ControlMask
) {
806 if (time_mode
== 3) time_mode
= CLOCK
;
814 if (state
& ControlMask
) {
815 my_system("wmclockmon-config -f", config_file
);
818 load_style(style_name
);
824 if (state
& ControlMask
) {
825 my_system("wmclockmon-cal", NULL
);
827 switch_authorized
= !switch_authorized
;
835 static void draw_dockapp() {
837 draw_background(backlight
);
840 if (time_mode
== INTERNET
) {
842 } else if (time_mode
== BINARY
) {
850 dockapp_copy2window(pixmap
);
854 /* called by timer */
855 static void update() {
856 static Light pre_backlight
;
857 static Bool in_alarm_mode
= False
;
859 /* check config_file modifications */
860 if (load_cfgfile()) graphics_init();
862 /* get current time */
867 if (!in_alarm_mode
) {
868 in_alarm_mode
= True
;
869 my_system(command
, NULL
);
870 if (message
) my_system(msgcmd
, message
);
871 pre_backlight
= backlight
;
873 if ( (switch_authorized
) ||
874 ( (switch_authorized
) && (backlight
!= pre_backlight
) ) ) {
880 in_alarm_mode
= False
;
881 if (backlight
!= pre_backlight
) {
891 /* called when mouse button pressed */
892 static void switch_light() {
894 case LIGHTOFF
: backlight
= LIGHTON
; break;
895 case LIGHTON
: backlight
= LIGHTOFF
; break;
903 static void draw_background(Light back
) {
904 if (back
== LIGHTON
) {
905 if (time_mode
== INTERNET
)
906 dockapp_copyarea(backdropI_on
, pixmap
, 0, 0, 58, 58, 0, 0);
907 else if (time_mode
== BINARY
)
908 dockapp_copyarea(backdropB_on
, pixmap
, 0, 0, 58, 58, 0, 0);
910 dockapp_copyarea(backdrop_on
, pixmap
, 0, 0, 58, 58, 0, 0);
912 if (time_mode
== INTERNET
)
913 dockapp_copyarea(backdropI_off
, pixmap
, 0, 0, 58, 58, 0, 0);
914 else if (time_mode
== BINARY
)
915 dockapp_copyarea(backdropB_off
, pixmap
, 0, 0, 58, 58, 0, 0);
917 dockapp_copyarea(backdrop_off
, pixmap
, 0, 0, 58, 58, 0, 0);
922 static void draw_bigdigit(int num
, int x
, int y
) {
923 int dy
= 0, w
= style
.bdigitw
, h
= style
.bdigith
;
924 int incr
= style
.bdigitw
+ style
.bsep
;
926 if (num
< 0) num
= 0;
927 if (backlight
== LIGHTON
) dy
= style
.bdigith
;
930 dockapp_copyarea(parts
, pixmap
, (num
% 10) * w
, dy
, w
, h
, x
+ incr
, y
);
931 dockapp_copyarea(parts
, pixmap
, (num
/ 10) * w
, dy
, w
, h
, x
, y
);
935 static void draw_smalldigit(int num
, int x
, int y
) {
936 int dx
= 0, w
= style
.sdigitw
, h
= style
.sdigith
;
937 int incr
= style
.sdigitw
+ style
.bsep
;
938 int dy
= 2 * style
.bdigith
;
940 if (num
< 0) num
= 0;
941 if (backlight
== LIGHTON
) dx
= style
.sdigitw
* 10;
944 dockapp_copyarea(parts
, pixmap
, (num
% 10) * w
+ dx
, dy
, w
, h
, x
+ incr
, y
);
945 dockapp_copyarea(parts
, pixmap
, (num
/ 10) * w
+ dx
, dy
, w
, h
, x
, y
);
949 static char equiv(char letter
) {
950 int i
, sign
, oldsign
= 0;
951 char letr
[2], upcase
, ret
= 0;
953 upcase
= toupper(letter
);
954 letr
[0] = upcase
; letr
[1] = 0;
955 if (! isupper(upcase
)) return letter
;
956 for (i
= 0 ; upcases
[i
] ; i
++) {
957 sign
= strcoll(letr
, upcases
[i
]);
958 if ((oldsign
> 0) && (sign
< 0)) ret
= upcases
[i
-1][0];
961 if (ret
== 0) ret
= upcase
;
966 static void draw_textdigit(const char *text
, int x
, int y
) {
967 int i
, dy
= style
.letterh
, incr
= style
.letterw
+ style
.lsep
;
968 int w
= style
.letterw
, h
= style
.letterh
;
970 if (backlight
== LIGHTON
) dy
= style
.letterh
* 2;
971 for (i
= 0 ; text
[i
] ; i
++) {
972 int pos
= equiv(text
[i
]) - 'A';
973 dockapp_copyarea(letters
, pixmap
, pos
* w
, dy
, w
, h
, x
+ i
* incr
, y
);
978 static void draw_timedigit() {
979 int hour
= timeinfos
->tm_hour
, dx
= 0, dy
= 0;
981 if (backlight
== LIGHTON
) {
982 dx
= style
.sdigitw
* 10; /* AM/PM/ALRM parts positions */
983 dy
= style
.bdigith
; /* colon seconds */
990 hour
= (hour
> 12) ? hour
- 12 : hour
;
994 draw_bigdigit(hour
, style
.hposx
, style
.hposy
);
996 draw_smalldigit(hour
, style
.hposx
, style
.hposy
);
999 draw_bigdigit(timeinfos
->tm_min
, style
.mposx
, style
.mposy
);
1001 draw_smalldigit(timeinfos
->tm_min
, style
.mposx
, style
.mposy
);
1004 if (timeinfos
->tm_sec
% 2 == 1) {
1006 dockapp_copyarea(parts
, pixmap
, 4, dy
, 2, 2, style
.sposx
, style
.sposy
);
1007 dockapp_copyarea(parts
, pixmap
, 4, dy
, 2, 2, style
.sposx
, style
.sposy
+ 9);
1009 dockapp_copyarea(parts
, pixmap
, 4, dy
, 1, 1, style
.sposx
, style
.sposy
);
1010 dockapp_copyarea(parts
, pixmap
, 4, dy
, 1, 1, style
.sposx
, style
.sposy
+ 4);
1015 draw_bigdigit(timeinfos
->tm_sec
, style
.sposx
, style
.sposy
);
1017 draw_smalldigit(timeinfos
->tm_sec
, style
.sposx
, style
.sposy
);
1021 /* Some say pm is when h>12 or h==0 but others (and my watch) told me
1022 * that the good way to handle am/pm is what is below
1024 if (timeinfos
->tm_hour
>= 12) /* PM */
1025 dockapp_copyarea(parts
, pixmap
, 36 + dx
, 49, 12, 7, style
.pposx
, style
.pposy
);
1027 dockapp_copyarea(parts
, pixmap
, 23 + dx
, 49, 12, 7, style
.aposx
, style
.aposy
);
1029 if (alarms_on(alarms
))
1030 dockapp_copyarea(parts
, pixmap
, dx
, 49, 22, 7, style
.lposx
, style
.lposy
);
1034 static void draw_datedigit() {
1038 draw_textdigit(label
, style
.wposx
, style
.wposy
);
1040 strftime(text
, 4, "%a", timeinfos
);
1041 draw_textdigit(text
, style
.wposx
, style
.wposy
);
1042 draw_smalldigit(timeinfos
->tm_mday
, style
.dposx
, style
.dposy
);
1043 strftime(text
, 4, "%b", timeinfos
);
1044 draw_textdigit(text
, style
.oposx
, style
.oposy
);
1049 static void draw_itimedigit() {
1050 int dx
= 0, dy
= 0, v1
, v10
, v100
, v0
, v00
, nb
, pc
;
1051 int bw
= style
.bdigitw
, bh
= style
.bdigith
;
1052 int binc
= style
.bdigitw
+ 2;
1053 int tw
= style
.sdigitw
, th
= style
.bdigith
;
1056 if (backlight
== LIGHTON
) {
1063 v100
= swtime
/ 100.0;
1064 v10
= (swtime
- v100
* 100) / 10.0;
1065 v1
= (swtime
- v100
* 100.0 - v10
* 10.0);
1066 v0
= (swtime
- v100
* 100.0 - v10
* 10.0 - v1
) * 10;
1067 v00
= (swtime
- v100
* 100.0 - v10
* 10.0 - v1
) * 1000;
1068 pc
= v00
- v0
* 100;
1070 /* draw main beats digit */
1075 dockapp_copyarea(parts
, pixmap
, v1
* 10, dy
, bw
, bh
, style
.bposx
+ 2 * binc
, style
.bposy
);
1076 dockapp_copyarea(parts
, pixmap
, v10
* 10, dy
, bw
, bh
, style
.bposx
+ binc
, style
.bposy
);
1077 dockapp_copyarea(parts
, pixmap
, v100
* 10, dy
, bw
, bh
, style
.bposx
, style
.bposy
);
1079 /* draw 10th of beats */
1080 dockapp_copyarea(parts
, pixmap
, v0
* 5 + dx
, 40, 5, 9, 49, 28);
1083 for (nb
= 0 ; nb
< pc
/ 6.25 ; nb
++)
1084 dockapp_copyarea(parts
, pixmap
, xd
, 0, 2, 9, 6 + nb
* 3, 45);
1088 static void draw_bits(int num
, int x
, int y
, int u
, int d
, int sx
, int sy
, int d1x
, int d1y
, int d2x
, int d2y
) {
1090 int dx
= u
* (sx
+ d2x
) + d1x
;
1094 int by
= 2 * style
.bdigith
+ style
.sdigith
+ 7 + d
;
1096 if (num
== 0) return;
1097 if (backlight
== LIGHTON
) bx
= 50;
1099 b
[3] = 0; b
[2] = 0; b
[1] = 0; b
[0] = 0;
1102 fprintf(stderr
, "Error : num is too big (%d)\n", num
);
1109 for (i
= 0 ; i
< 4 ; i
++) {
1112 int py
= y
+ (3 - i
) * dy
+ d2y
;
1113 dockapp_copyarea(parts
, pixmap
, bx
, by
, sx
, sy
, px
, py
);
1119 static void draw_binarytime() {
1120 int sx
= style
.binzx
;
1121 int sy
= style
.binzy
;
1122 int d1x
= style
.bind1x
;
1123 int d1y
= style
.bind1y
;
1124 int d2x
= style
.bind2x
;
1125 int d2y
= style
.bind2y
;
1127 draw_bits(timeinfos
->tm_hour
/ 10, style
.binhx
, style
.binhy
, 0, 0,
1128 sx
, sy
, d1x
, d1y
, d2x
, d2y
);
1129 draw_bits(timeinfos
->tm_hour
% 10, style
.binhx
, style
.binhy
, 1, 0,
1130 sx
, sy
, d1x
, d1y
, d2x
, d2y
);
1132 draw_bits(timeinfos
->tm_min
/ 10, style
.binmx
, style
.binmy
, 0, 0,
1133 sx
, sy
, d1x
, d1y
, d2x
, d2y
);
1134 draw_bits(timeinfos
->tm_min
% 10, style
.binmx
, style
.binmy
, 1, 0,
1135 sx
, sy
, d1x
, d1y
, d2x
, d2y
);
1137 draw_bits(timeinfos
->tm_sec
/ 10, style
.binsx
, style
.binsy
, 0, 0,
1138 sx
, sy
, d1x
, d1y
, d2x
, d2y
);
1139 draw_bits(timeinfos
->tm_sec
% 10, style
.binsx
, style
.binsy
, 1, 0,
1140 sx
, sy
, d1x
, d1y
, d2x
, d2y
);
1142 if (style
.binix
!= -1) {
1143 int wd
= timeinfos
->tm_wday
== 0 ? 7 : timeinfos
->tm_wday
;
1152 draw_bits(wd
, style
.binwx
, style
.binwy
, 0, 1,
1153 sx
, sy
, d1x
, d1y
, d2x
, d2y
);
1155 draw_bits(timeinfos
->tm_mday
/ 10, style
.bindx
, style
.bindy
, 0, 1,
1156 sx
, sy
, d1x
, d1y
, d2x
, d2y
);
1157 draw_bits(timeinfos
->tm_mday
% 10, style
.bindx
, style
.bindy
, 1, 1,
1158 sx
, sy
, d1x
, d1y
, d2x
, d2y
);
1160 draw_bits((timeinfos
->tm_mon
+ 1) / 10, style
.binox
, style
.binoy
, 0, 1,
1161 sx
, sy
, d1x
, d1y
, d2x
, d2y
);
1162 draw_bits((timeinfos
->tm_mon
+ 1) % 10, style
.binox
, style
.binoy
, 1, 1,
1163 sx
, sy
, d1x
, d1y
, d2x
, d2y
);
1168 static void parse_arguments(int argc
, char **argv
) {
1170 for (i
= 1; i
< argc
; i
++) {
1171 if (!strcmp(argv
[i
], "--help") || !strcmp(argv
[i
], "-h")) {
1172 print_help(argv
[0]), exit(0);
1173 } else if (!strcmp(argv
[i
], "--version") || !strcmp(argv
[i
], "-v")) {
1174 printf("%s version %s\n", PACKAGE
, VERSION
), exit(0);
1175 } else if (!strcmp(argv
[i
], "--display") || !strcmp(argv
[i
], "-d")) {
1176 display_name
= argv
[i
+ 1];
1178 } else if (!strcmp(argv
[i
], "--backlight") || !strcmp(argv
[i
], "-bl")) {
1179 backlight
= LIGHTON
;
1180 } else if (!strcmp(argv
[i
], "--light-color") || !strcmp(argv
[i
], "-lc")) {
1182 fprintf(stderr
, "%s: argument \"%s\" needs an option.\n", argv
[0], argv
[i
]), exit(1);
1183 SET_STRING(light_color
, argv
[i
+ 1]);
1185 } else if (!strcmp(argv
[i
], "--windowed") || !strcmp(argv
[i
], "-w")) {
1186 dockapp_iswindowed
= True
;
1187 } else if (!strcmp(argv
[i
], "--broken-wm") || !strcmp(argv
[i
], "-bw")) {
1188 dockapp_isbrokenwm
= True
;
1189 } else if (!strcmp(argv
[i
], "--no-blink") || !strcmp(argv
[i
], "-nb")) {
1190 switch_authorized
= False
;
1191 } else if (!strcmp(argv
[i
], "--h12") || !strcmp(argv
[i
], "-12")) {
1193 } else if (!strcmp(argv
[i
], "--time-mode") || !strcmp(argv
[i
], "-tm")) {
1195 fprintf(stderr
, "%s: error parsing argument for option %s\n",
1196 argv
[0], argv
[i
]), exit(1);
1197 if (sscanf(argv
[i
+ 1], "%i", &integer
) != 1)
1198 fprintf(stderr
, "%s: error parsing argument for option %s\n",
1199 argv
[0], argv
[i
]), exit(1);
1200 if ((integer
< 0) || (integer
> 2))
1201 fprintf(stderr
, "%s: argument %s must be in [0,2]\n",
1202 argv
[0], argv
[i
]), exit(1);
1203 time_mode
= integer
;
1205 } else if (!strcmp(argv
[i
], "--alarm-cmd") || !strcmp(argv
[i
], "-c")) {
1206 SET_STRING(command
, argv
[i
+ 1]);
1208 } else if (!strcmp(argv
[i
], "--message-cmd") || !strcmp(argv
[i
], "-mc")) {
1209 SET_STRING(msgcmd
, argv
[i
+ 1]);
1211 } else if (!strcmp(argv
[i
], "--alarm") || !strcmp(argv
[i
], "-a")) {
1212 alrm_add(&alarms
, argv
[i
+ 1]);
1214 } else if (!strcmp(argv
[i
], "--cfg-file") || !strcmp(argv
[i
], "-f")) {
1215 SET_STRING(config_file
, argv
[i
+ 1]);
1217 } else if (!strcmp(argv
[i
], "--no-locale") || !strcmp(argv
[i
], "-nl")) {
1219 } else if (!strcmp(argv
[i
], "--style") || !strcmp(argv
[i
], "-s")) {
1220 SET_STRING(style_name
, argv
[i
+ 1]);
1222 } else if (!strcmp(argv
[i
], "--style-dir") || !strcmp(argv
[i
], "-sd")) {
1223 SET_STRING(style_dir
, argv
[i
+ 1]);
1225 } else if (!strcmp(argv
[i
], "--label") || !strcmp(argv
[i
], "-l")) {
1226 SET_STRING(label
, argv
[i
+ 1]);
1228 } else if (!strcmp(argv
[i
], "--show-cal") || !strcmp(argv
[i
], "-sc")) {
1230 } else if (!strcmp(argv
[i
], "--cal-alrm") || !strcmp(argv
[i
], "-ca")) {
1234 fprintf(stderr
, "%s: unrecognized option '%s'\n", argv
[0], argv
[i
]);
1235 print_help(argv
[0]), exit(1);
1241 static void print_help(char *prog
)
1243 printf("Usage : %s [OPTIONS]\n"
1244 "%s - Window Maker digital clock dockapp\n"
1245 " -h, --help show this help text and exit\n"
1246 " -v, --version show program version and exit\n"
1247 " -d, --display <string> display to use\n"
1248 " -bl, --backlight turn on back-light\n"
1249 " -lc, --light-color <color> backlight/led colour\n"
1250 " -tm, --time-mode <mode> start with time mode (0: clock, 1: internet time, 2: binary clock)\n"
1251 " -w, --windowed run the application in windowed mode\n"
1252 " -bw, --broken-wm activate broken window manager fix\n"
1253 " -a, --alarm <HH:MM> set alarm time to HH:MM (24h clock mode)\n"
1254 " -c, --alarm-cmd <string> command to launch when alarm raises\n"
1255 " -mc, --message-cmd <string> command to launch when alarm raises and a message is associated\n"
1256 " -12, --h12 12 hours clock mode (default is 24)\n"
1257 " -s, --style <file> style to use for display\n"
1258 " -sd, --style-dir <dir> directory where styles are stored\n"
1259 " -nb, --no-blink disable blinking when alarm is raised\n"
1260 " -f, --cfgfile <filename> use 'filename' as configuration file\n"
1261 " -nl, --no-locale don't use current locale\n"
1262 " -l, --label <string> use a label instead of date\n"
1263 " -ca, --cal-alrm load calendar alarms for today\n"
1264 " -sc, --show-cal show calendar at startup/00:00\n",
1269 static void time_update() {
1273 timeinfos
= localtime(&tnow
);
1275 if (time_mode
== INTERNET
) {
1277 swtime
= timeinfos
->tm_hour
* 3600
1278 + timeinfos
->tm_min
* 60
1279 + timeinfos
->tm_sec
;
1281 localtmzone
= timeinfos
->tm_gmtoff
;
1283 localtmzone
= timezone
;
1285 swtime
+= localtmzone
+3600;
1286 if (timeinfos
->tm_isdst
) swtime
-= 3600;
1292 if (swtime
< 0) swtime
+= 1000;
1297 static Bool
raise_alarm() {
1298 if ((timeinfos
->tm_hour
== 0) &&
1299 (timeinfos
->tm_min
== 0) &&
1300 (timeinfos
->tm_sec
== 0)) {
1301 if (showcal
) show_cal();
1302 if (calalrms
) reload_alarms();
1305 Alarm
*alrm
= alarms
;
1306 char thistime
[MAXSTRLEN
+ 1];
1307 char thisdate
[MAXSTRLEN
+ 1];
1309 strftime(thistime
, MAXSTRLEN
, "%H:%M", timeinfos
);
1310 strftime(thisdate
, MAXSTRLEN
, "%u", timeinfos
);
1312 if (alrm
->on
&& (strcmp(thistime
, alrm
->alarm_time
) == 0)) {
1313 message
= alrm
->message
;
1314 if (alrm
->alarm_date
) {
1315 if (strcmp(thisdate
, alrm
->alarm_date
) == 0)
1330 static Bool
fexist(const char *filename
) {
1333 if ((file
= fopen(filename
, "r")) == NULL
) return False
;
1340 static Bool
filestat(const char *filename
, time_t *time
, int mode
) {
1344 if (stat(filename
, &s
) == -1) {
1345 if (*time
== 0) return False
;
1349 case MTIME
: t
= s
.st_mtime
; break;
1350 case ATIME
: t
= s
.st_atime
; break;
1362 static int my_system(char *cmd
, char *opt
) {
1364 extern char **environ
;
1366 if (cmd
== NULL
) return 1;
1368 if (pid
== -1) return -1;
1373 char *thiscommand
= xmalloc(strlen(cmd
)
1374 + (opt
? strlen(opt
) + 4 : 1));
1375 sprintf(thiscommand
, "%s %s%s%s", cmd
,
1381 argv
[2] = thiscommand
;
1383 execve("/bin/sh", argv
, environ
);
1393 void *xmalloc(size_t size
) {
1394 void *ret
= malloc(size
);
1396 perror("malloc() ");
1403 char *xstrdup(const char *string
) {
1404 char *ret
= string
? strdup(string
) : NULL
;
1405 if (string
&& (ret
== NULL
)) {
1406 perror("strdup() ");
1413 static void put_alrm(Alarm
**list
, const char *entry
,
1414 char *time
, char *date
, char *ison
, char *mesg
, Bool cal
) {
1419 lst
= xmalloc(sizeof(Alarm
));
1422 if (strcmp(entry
, lst
->entry
) == 0) ok
= False
;
1423 while ( (lst
->next
) && ok
) {
1425 if (strcmp(entry
, lst
->entry
) == 0) ok
= False
;
1428 lst
->next
= xmalloc(sizeof(Alarm
));
1431 lst
->entry
= xstrdup(entry
);
1432 lst
->alarm_time
= time
? xstrdup(time
) : NULL
;
1433 lst
->alarm_date
= date
? xstrdup(date
) : NULL
;
1434 lst
->on
= ison
? getbool(ison
) : True
;
1435 lst
->message
= mesg
? xstrdup(mesg
) : NULL
;
1441 static void alrm_add(Alarm
**list
, const char *value
) {
1442 char *time
= NULL
, *date
= NULL
, *ison
= NULL
, *mesg
= NULL
, *at
;
1443 char *tokstr
= xstrdup(value
);
1444 char *toksav
= tokstr
;
1446 if (! value
) return;
1447 at
= strchr(value
, '@');
1448 if (at
) ison
= strtok(tokstr
, "@");
1449 time
= strtok(at
? NULL
: tokstr
, "-.");
1450 if (strchr(value
, '-')) date
= strtok(NULL
, ".");
1451 mesg
= strtok(NULL
, "\n\0");
1453 put_alrm(list
, value
, time
, date
, ison
, mesg
, False
);
1459 static void free_alrm(Alarm
**list
) {
1460 Alarm
*lst
= *list
, *next
;
1464 FREE(lst
->alarm_time
);
1465 FREE(lst
->alarm_date
);
1474 static int nb_alrm(Alarm
*list
) {
1485 static Bool
alarms_on(Alarm
*list
) {
1489 if (alrm
->on
) return True
;
1496 static void switch_alarms(Alarm
*list
) {
1500 if (alarms_on(list
)) set_to
= False
;
1502 char *tokstr
= xstrdup(alrm
->entry
);
1503 char *toksav
= tokstr
;
1504 Bool is_on
= alrm
->cal
|| getbool(strtok(tokstr
, "@"));
1506 if ((is_on
&& set_to
) || (!set_to
)) {
1515 static Bool
getbool(char *value
) {
1517 for (i
= 0 ; value
[i
] ; i
++) value
[i
] = tolower(value
[i
]);
1518 if (strcmp(value
, "0") == 0) return False
;
1519 if (strcmp(value
, "1") == 0) return True
;
1520 if (strcmp(value
, "true") == 0) return True
;
1521 if (strcmp(value
, "false") == 0) return False
;
1522 if (strcmp(value
, "yes") == 0) return True
;
1523 if (strcmp(value
, "no") == 0) return False
;
1524 if (strcmp(value
, "on") == 0) return True
;
1525 if (strcmp(value
, "off") == 0) return False
;
1526 printf("Error in converting \"%s\" to boolean value.\n", value
);
1531 static Bool
load_cfgfile() {
1533 int i
= 0, ok
= True
;
1534 char line
[MAXSTRLEN
+ 1];
1537 if ((file
= fopen(config_file
, "r")) == NULL
) {
1538 if (strstr(config_file
, "/"DEFAULT_CFGFILE
) == NULL
)
1539 printf("Unable to open configuration file \"%s\".\n", config_file
);
1542 if (ok
&& (! filestat(config_file
, &config_mtime
, MTIME
))) {
1547 if (alarms
) free_alrm(&alarms
);
1548 while (! feof(file
)) {
1549 bzero(line
, MAXSTRLEN
+ 1);
1550 fgets(line
, MAXSTRLEN
, file
);
1552 if (line
[strlen(line
) - 1] == '\n') line
[strlen(line
) - 1] = 0;
1553 if ((line
[0] == '#') || (line
[0] == 0)) continue;
1554 value
= strchr(line
, '=');
1555 if (! value
) continue;
1557 while ((value
[0] != 0) && (value
[0] == ' ')) value
++;
1558 if (value
[0] == 0) continue;
1560 if (strncmp(line
, "Backlight", 9) == 0) {
1561 backlight
= getbool(value
) ? LIGHTON
: LIGHTOFF
;
1562 } else if (strncmp(line
, "Color", 5) == 0) {
1563 SET_STRING(light_color
, value
);
1564 } else if (strncmp(line
, "Alarm", 5) == 0) {
1565 alrm_add(&alarms
, value
);
1566 } else if (strncmp(line
, "Command", 7) == 0) {
1567 SET_STRING(command
, value
);
1568 } else if (strncmp(line
, "MessageCmd", 10) == 0) {
1569 SET_STRING(msgcmd
, value
);
1570 } else if (strncmp(line
, "Blink", 5) == 0) {
1571 switch_authorized
= getbool(value
);
1572 } else if (strncmp(line
, "H12", 3) == 0) {
1573 h12
= getbool(value
);
1574 } else if (strncmp(line
, "Locale", 6) == 0) {
1575 use_locale
= getbool(value
);
1576 } else if (strncmp(line
, "StyleDir", 8) == 0) {
1577 SET_STRING(style_dir
, value
);
1578 } else if (strncmp(line
, "Style", 5) == 0) {
1579 SET_STRING(style_name
, value
);
1580 } else if (strncmp(line
, "TimeMode", 5) == 0) {
1581 time_mode
= atoi(value
);
1582 } else if (strncmp(line
, "ShowCal", 7) == 0) {
1583 showcal
= getbool(value
);
1584 } else if (strncmp(line
, "CalAlrms", 8) == 0) {
1585 calalrms
= getbool(value
);
1587 printf("Error in %s at line %d :\n[%s].\n", config_file
, i
, line
);
1590 if (calalrms
) load_calalrms();
1592 } else if (calalrms
&& cal_alrms_chg()) {
1599 static char *get_calend_file(int type
) {
1600 char *Home
= robust_home();
1601 char *filename
= xmalloc(
1603 strlen(DEFAULT_CONFIGDIR
) +
1608 sprintf(filename
, "%s/%s/%04d-%02d-%02d",
1611 timeinfos
->tm_year
+ 1900,
1612 timeinfos
->tm_mon
+ 1,
1613 timeinfos
->tm_mday
);
1616 sprintf(filename
, "%s/%s/XXXX-%02d-%02d",
1619 timeinfos
->tm_mon
+ 1,
1620 timeinfos
->tm_mday
);
1623 sprintf(filename
, "%s/%s/XXXX-XX-%02d",
1626 timeinfos
->tm_mday
);
1634 static int cal_alrms_chg() {
1635 static time_t cal_u_mtime
= 0;
1636 static time_t cal_y_mtime
= 0;
1637 static time_t cal_m_mtime
= 0;
1638 char *cal_u_fname
= NULL
;
1639 char *cal_y_fname
= NULL
;
1640 char *cal_m_fname
= NULL
;
1641 int chg_u
, chg_y
, chg_m
;
1643 if (! calalrms
) return False
;
1644 cal_u_fname
= get_calend_file(1);
1645 cal_y_fname
= get_calend_file(2);
1646 cal_m_fname
= get_calend_file(3);
1647 chg_u
= filestat(cal_u_fname
, &cal_u_mtime
, MTIME
);
1648 chg_y
= filestat(cal_y_fname
, &cal_y_mtime
, MTIME
);
1649 chg_m
= filestat(cal_m_fname
, &cal_m_mtime
, MTIME
);
1653 if (chg_u
|| chg_y
|| chg_m
) return True
;
1658 static void load_cal_file(int type
) {
1660 char *calend_file
= get_calend_file(type
);
1663 if ((file
= fopen(calend_file
, "r")) != NULL
) {
1664 while (! feof(file
)) {
1665 char line
[MAXSTRLEN
+ 1];
1666 bzero(line
, MAXSTRLEN
+ 1);
1667 fgets(line
, MAXSTRLEN
, file
);
1668 if ( (line
[0] != 0) && (strncmp(line
, "@ ", 2) == 0) ) {
1669 char time
[MAXSTRLEN
+ 1];
1670 sscanf(line
, "@ %s ", time
);
1671 put_alrm(&alarms
, line
, time
, NULL
, NULL
, line
+ 8, True
);
1680 static void load_calalrms() {
1682 for (i
= 1 ; i
< 4 ; i
++) load_cal_file(i
);
1686 static void reload_alarms() {
1689 char line
[MAXSTRLEN
+ 1];
1692 if (alarms
) free_alrm(&alarms
);
1693 if ((file
= fopen(config_file
, "r")) == NULL
) {
1694 if (strstr(config_file
, "/"DEFAULT_CFGFILE
) == NULL
)
1695 printf("Unable to open configuration file \"%s\".\n", config_file
);
1697 while (! feof(file
)) {
1698 bzero(line
, MAXSTRLEN
+ 1);
1699 fgets(line
, MAXSTRLEN
, file
);
1701 if (line
[strlen(line
) - 1] == '\n') line
[strlen(line
) - 1] = 0;
1702 if ((line
[0] == '#') || (line
[0] == 0)) continue;
1703 value
= strchr (line
, '=') + 1;
1704 while ((value
[0] == ' ') && (value
[0] != 0)) value
++;
1705 if (value
[0] == 0) continue;
1707 if (strncmp(line
, "Alarm", 5) == 0) alrm_add(&alarms
, value
);
1710 if (calalrms
) load_calalrms();
1714 static void show_cal_file(int type
) {
1718 char *calend_file
= get_calend_file(type
);
1720 if ((file
= fopen(calend_file
, "r")) != NULL
) {
1721 while (! feof(file
)) {
1722 char line
[MAXSTRLEN
+ 1];
1723 bzero(line
, MAXSTRLEN
+ 1);
1724 fgets(line
, MAXSTRLEN
, file
);
1726 int len
= data
? strlen(data
) : 0;
1727 tmp
= xmalloc(len
+ strlen(line
) + 1);
1728 sprintf(tmp
, "%s%s", data
? data
: "", line
);
1735 my_system(msgcmd
, data
);
1742 static void show_cal() {
1744 for (i
= 1 ; i
< 4 ; i
++) show_cal_file(i
);
1748 static char *robust_home() {
1750 return getenv("HOME");
1751 else if (getenv("USER") && getpwnam(getenv("USER")))
1752 return getpwnam(getenv("USER"))->pw_dir
;
1753 else if (getenv("LOGNAME") && getpwnam(getenv("LOGNAME")))
1754 return getpwnam (getenv ("LOGNAME") )->pw_dir
;
1755 else if ((getuid() != -1) && (getpwuid(getuid())))
1756 return getpwuid(getuid())->pw_dir
;