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
}
639 if (! stylename
) return;
641 partsfile
= xstrdup(style
.parts_s
);
642 lettersfile
= xstrdup(style
.letters_s
);
643 itimefile
= xstrdup(style
.itime_s
);
644 btimefile
= xstrdup(style
.btime_s
);
645 filename
= set_filename(stylename
, ".mwcs");
648 load_stylepart(filename
, main_style_opts
);
651 if (stringdiff(partsfile
, style
.parts_s
) == True
)
652 load_stylepart(style
.parts_s
, parts_style_opts
);
655 if (stringdiff(lettersfile
, style
.letters_s
) == True
)
656 load_stylepart(style
.letters_s
, letters_style_opts
);
659 if (stringdiff(itimefile
, style
.itime_s
) == True
)
660 load_stylepart(style
.itime_s
, itime_style_opts
);
663 if (stringdiff(btimefile
, style
.btime_s
) == True
)
664 load_stylepart(style
.btime_s
, btime_style_opts
);
674 static void init_pixmap(char **src_pix
, Pixmap
*dst_pix
, const char *text
,
675 XpmColorSymbol
*c
, int n
, int keep_mask
) {
676 if (*dst_pix
) XFreePixmap(display
, *dst_pix
);
677 if (!dockapp_xpm2pixmap(src_pix
, dst_pix
, &mask
, c
, n
)) {
678 fprintf(stderr
, "Error initializing %s image.\n", text
);
681 if (!keep_mask
&& mask
) XFreePixmap(display
, mask
);
685 static void init_pixfile(char *src_name
, Pixmap
*dst_pix
, const char *text
,
686 XpmColorSymbol
*c
, int n
, int keep_mask
) {
687 if (*dst_pix
) XFreePixmap(display
, *dst_pix
);
688 if (!dockapp_file2pixmap(src_name
, dst_pix
, &mask
, c
, n
)) {
689 fprintf(stderr
, "Error initializing %s image.\n", text
);
692 if (!keep_mask
&& mask
) XFreePixmap(display
, mask
);
696 static void graphics_init() {
697 XpmColorSymbol colors
[3] = { {"Back0", NULL
, 0}, {"Back1", NULL
, 0}, {"Back2", NULL
, 0} };
701 ncolor
= style
.ncolors
;
703 colors
[0].pixel
= dockapp_getcolor(light_color
);
704 colors
[1].pixel
= dockapp_blendedcolor(light_color
, -24, -24, -24, 1.0);
706 colors
[0].pixel
= dockapp_getcolor(light_color
);
707 colors
[1].pixel
= dockapp_dividecolor(light_color
, 3);
708 colors
[2].pixel
= dockapp_blendedcolor(light_color
, -50, -50, -50, 1.0);
712 /* change raw xpm data to pixmap */
714 if (dockapp_iswindowed)
715 backlit_pix[1] = backgrd_pix[1] = WINDOWED_BG;
719 init_pixfile(style
.parts
, &parts
, "parts",
720 colors
, ncolor
, False
);
722 init_pixmap(parts_xpm
, &parts
, "parts",
723 colors
, ncolor
, False
);
726 init_pixfile(style
.letters
, &letters
, "letters",
727 colors
, ncolor
, False
);
729 init_pixmap(letters_xpm
, &letters
, "letters",
730 colors
, ncolor
, False
);
733 init_pixfile(style
.ibackl
, &backdropI_on
, "backlit background 2",
734 colors
, ncolor
, False
);
736 init_pixmap(backlightI_on_xpm
, &backdropI_on
, "backlit background 2",
737 colors
, ncolor
, False
);
740 init_pixfile(style
.ibacku
, &backdropI_off
, "background 2",
741 colors
, ncolor
, False
);
743 init_pixmap(backlightI_off_xpm
, &backdropI_off
, "background 2",
744 colors
, ncolor
, False
);
747 init_pixfile(style
.bbackl
, &backdropB_on
, "backlit background 3",
748 colors
, ncolor
, False
);
750 init_pixmap(backlightB_on_xpm
, &backdropB_on
, "backlit background 3",
751 colors
, ncolor
, False
);
754 init_pixfile(style
.bbacku
, &backdropB_off
, "background 3",
755 colors
, ncolor
, False
);
757 init_pixmap(backlightB_off_xpm
, &backdropB_off
, "background 3",
758 colors
, ncolor
, False
);
761 init_pixfile(style
.backl
, &backdrop_on
, "backlit background",
762 colors
, ncolor
, False
);
764 init_pixmap(backlight0_on_xpm
, &backdrop_on
, "backlit background",
765 colors
, ncolor
, False
);
768 init_pixfile(style
.backu
, &backdrop_off
, "background",
769 colors
, ncolor
, True
);
771 init_pixmap(backlight0_off_xpm
, &backdrop_off
, "background",
772 colors
, ncolor
, True
);
775 if (!dockapp_iswindowed
) dockapp_setshape(mask
, 0, 0);
776 if (mask
) XFreePixmap(display
, mask
);
778 /* pixmap : draw area */
779 if (pixmap
) XFreePixmap(display
, pixmap
);
780 pixmap
= dockapp_XCreatePixmap(SIZE
, SIZE
);
782 /* Initialize pixmap */
783 draw_background(backlight
);
785 dockapp_set_background(pixmap
);
791 static void control(unsigned int btn
, int x
, int y
, unsigned int state
) {
794 if (time_mode
== CLOCK
) {
795 if ( (x
>= style
.aposx
) && (x
<= style
.aposx
+ 12) &&
796 (y
>= style
.aposy
) && (y
<= style
.aposy
+ 7) ) {
799 } else if ( (x
>= style
.pposx
) && (x
<= style
.pposx
+ 12) &&
800 (y
>= style
.pposy
) && (y
<= style
.pposy
+ 7) ) {
803 } else if ( (x
>= style
.lposx
) && (x
<= style
.lposx
+ 22) &&
804 (y
>= style
.lposy
) && (y
<= style
.lposy
+ 7) ) {
805 if (alarms
) switch_alarms(alarms
);
809 if (state
& ControlMask
) {
811 if (time_mode
== 3) time_mode
= CLOCK
;
819 if (state
& ControlMask
) {
820 my_system("wmclockmon-config -f", config_file
);
823 load_style(style_name
);
829 if (state
& ControlMask
) {
830 my_system("wmclockmon-cal", NULL
);
832 switch_authorized
= !switch_authorized
;
840 static void draw_dockapp() {
842 draw_background(backlight
);
845 if (time_mode
== INTERNET
) {
847 } else if (time_mode
== BINARY
) {
855 dockapp_copy2window(pixmap
);
859 /* called by timer */
860 static void update() {
861 static Light pre_backlight
;
862 static Bool in_alarm_mode
= False
;
864 /* check config_file modifications */
865 if (load_cfgfile()) graphics_init();
867 /* get current time */
872 if (!in_alarm_mode
) {
873 in_alarm_mode
= True
;
874 my_system(command
, NULL
);
875 if (message
) my_system(msgcmd
, message
);
876 pre_backlight
= backlight
;
878 if ( (switch_authorized
) ||
879 ( (switch_authorized
) && (backlight
!= pre_backlight
) ) ) {
885 in_alarm_mode
= False
;
886 if (backlight
!= pre_backlight
) {
896 /* called when mouse button pressed */
897 static void switch_light() {
899 case LIGHTOFF
: backlight
= LIGHTON
; break;
900 case LIGHTON
: backlight
= LIGHTOFF
; break;
908 static void draw_background(Light back
) {
909 if (back
== LIGHTON
) {
910 if (time_mode
== INTERNET
)
911 dockapp_copyarea(backdropI_on
, pixmap
, 0, 0, 58, 58, 0, 0);
912 else if (time_mode
== BINARY
)
913 dockapp_copyarea(backdropB_on
, pixmap
, 0, 0, 58, 58, 0, 0);
915 dockapp_copyarea(backdrop_on
, pixmap
, 0, 0, 58, 58, 0, 0);
917 if (time_mode
== INTERNET
)
918 dockapp_copyarea(backdropI_off
, pixmap
, 0, 0, 58, 58, 0, 0);
919 else if (time_mode
== BINARY
)
920 dockapp_copyarea(backdropB_off
, pixmap
, 0, 0, 58, 58, 0, 0);
922 dockapp_copyarea(backdrop_off
, pixmap
, 0, 0, 58, 58, 0, 0);
927 static void draw_bigdigit(int num
, int x
, int y
) {
928 int dy
= 0, w
= style
.bdigitw
, h
= style
.bdigith
;
929 int incr
= style
.bdigitw
+ style
.bsep
;
931 if (num
< 0) num
= 0;
932 if (backlight
== LIGHTON
) dy
= style
.bdigith
;
935 dockapp_copyarea(parts
, pixmap
, (num
% 10) * w
, dy
, w
, h
, x
+ incr
, y
);
936 dockapp_copyarea(parts
, pixmap
, (num
/ 10) * w
, dy
, w
, h
, x
, y
);
940 static void draw_smalldigit(int num
, int x
, int y
) {
941 int dx
= 0, w
= style
.sdigitw
, h
= style
.sdigith
;
942 int incr
= style
.sdigitw
+ style
.bsep
;
943 int dy
= 2 * style
.bdigith
;
945 if (num
< 0) num
= 0;
946 if (backlight
== LIGHTON
) dx
= style
.sdigitw
* 10;
949 dockapp_copyarea(parts
, pixmap
, (num
% 10) * w
+ dx
, dy
, w
, h
, x
+ incr
, y
);
950 dockapp_copyarea(parts
, pixmap
, (num
/ 10) * w
+ dx
, dy
, w
, h
, x
, y
);
954 static char equiv(char letter
) {
955 int i
, sign
, oldsign
= 0;
956 char letr
[2], upcase
, ret
= 0;
958 upcase
= toupper(letter
);
959 letr
[0] = upcase
; letr
[1] = 0;
960 if (! isupper(upcase
)) return letter
;
961 for (i
= 0 ; upcases
[i
] ; i
++) {
962 sign
= strcoll(letr
, upcases
[i
]);
963 if ((oldsign
> 0) && (sign
< 0)) ret
= upcases
[i
-1][0];
966 if (ret
== 0) ret
= upcase
;
971 static void draw_textdigit(const char *text
, int x
, int y
) {
972 int i
, dy
= style
.letterh
, incr
= style
.letterw
+ style
.lsep
;
973 int w
= style
.letterw
, h
= style
.letterh
;
975 if (backlight
== LIGHTON
) dy
= style
.letterh
* 2;
976 for (i
= 0 ; text
[i
] ; i
++) {
977 int pos
= equiv(text
[i
]) - 'A';
978 dockapp_copyarea(letters
, pixmap
, pos
* w
, dy
, w
, h
, x
+ i
* incr
, y
);
983 static void draw_timedigit() {
984 int hour
= timeinfos
->tm_hour
, dx
= 0, dy
= 0;
986 if (backlight
== LIGHTON
) {
987 dx
= style
.sdigitw
* 10; /* AM/PM/ALRM parts positions */
988 dy
= style
.bdigith
; /* colon seconds */
995 hour
= (hour
> 12) ? hour
- 12 : hour
;
999 draw_bigdigit(hour
, style
.hposx
, style
.hposy
);
1001 draw_smalldigit(hour
, style
.hposx
, style
.hposy
);
1004 draw_bigdigit(timeinfos
->tm_min
, style
.mposx
, style
.mposy
);
1006 draw_smalldigit(timeinfos
->tm_min
, style
.mposx
, style
.mposy
);
1009 if (timeinfos
->tm_sec
% 2 == 1) {
1011 dockapp_copyarea(parts
, pixmap
, 4, dy
, 2, 2, style
.sposx
, style
.sposy
);
1012 dockapp_copyarea(parts
, pixmap
, 4, dy
, 2, 2, style
.sposx
, style
.sposy
+ 9);
1014 dockapp_copyarea(parts
, pixmap
, 4, dy
, 1, 1, style
.sposx
, style
.sposy
);
1015 dockapp_copyarea(parts
, pixmap
, 4, dy
, 1, 1, style
.sposx
, style
.sposy
+ 4);
1020 draw_bigdigit(timeinfos
->tm_sec
, style
.sposx
, style
.sposy
);
1022 draw_smalldigit(timeinfos
->tm_sec
, style
.sposx
, style
.sposy
);
1026 /* Some say pm is when h>12 or h==0 but others (and my watch) told me
1027 * that the good way to handle am/pm is what is below
1029 if (timeinfos
->tm_hour
>= 12) /* PM */
1030 dockapp_copyarea(parts
, pixmap
, 36 + dx
, 49, 12, 7, style
.pposx
, style
.pposy
);
1032 dockapp_copyarea(parts
, pixmap
, 23 + dx
, 49, 12, 7, style
.aposx
, style
.aposy
);
1034 if (alarms_on(alarms
))
1035 dockapp_copyarea(parts
, pixmap
, dx
, 49, 22, 7, style
.lposx
, style
.lposy
);
1039 static void draw_datedigit() {
1043 draw_textdigit(label
, style
.wposx
, style
.wposy
);
1045 strftime(text
, 4, "%a", timeinfos
);
1046 draw_textdigit(text
, style
.wposx
, style
.wposy
);
1047 draw_smalldigit(timeinfos
->tm_mday
, style
.dposx
, style
.dposy
);
1048 strftime(text
, 4, "%b", timeinfos
);
1049 draw_textdigit(text
, style
.oposx
, style
.oposy
);
1054 static void draw_itimedigit() {
1055 int dx
= 0, dy
= 0, v1
, v10
, v100
, v0
, v00
, nb
, pc
;
1056 int bw
= style
.bdigitw
, bh
= style
.bdigith
;
1057 int binc
= style
.bdigitw
+ 2;
1058 int tw
= style
.sdigitw
, th
= style
.bdigith
;
1061 if (backlight
== LIGHTON
) {
1068 v100
= swtime
/ 100.0;
1069 v10
= (swtime
- v100
* 100) / 10.0;
1070 v1
= (swtime
- v100
* 100.0 - v10
* 10.0);
1071 v0
= (swtime
- v100
* 100.0 - v10
* 10.0 - v1
) * 10;
1072 v00
= (swtime
- v100
* 100.0 - v10
* 10.0 - v1
) * 1000;
1073 pc
= v00
- v0
* 100;
1075 /* draw main beats digit */
1080 dockapp_copyarea(parts
, pixmap
, v1
* 10, dy
, bw
, bh
, style
.bposx
+ 2 * binc
, style
.bposy
);
1081 dockapp_copyarea(parts
, pixmap
, v10
* 10, dy
, bw
, bh
, style
.bposx
+ binc
, style
.bposy
);
1082 dockapp_copyarea(parts
, pixmap
, v100
* 10, dy
, bw
, bh
, style
.bposx
, style
.bposy
);
1084 /* draw 10th of beats */
1085 dockapp_copyarea(parts
, pixmap
, v0
* 5 + dx
, 40, 5, 9, 49, 28);
1088 for (nb
= 0 ; nb
< pc
/ 6.25 ; nb
++)
1089 dockapp_copyarea(parts
, pixmap
, xd
, 0, 2, 9, 6 + nb
* 3, 45);
1093 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
) {
1095 int dx
= u
* (sx
+ d2x
) + d1x
;
1099 int by
= 2 * style
.bdigith
+ style
.sdigith
+ 7 + d
;
1101 if (num
== 0) return;
1102 if (backlight
== LIGHTON
) bx
= 50;
1104 b
[3] = 0; b
[2] = 0; b
[1] = 0; b
[0] = 0;
1107 fprintf(stderr
, "Error : num is too big (%d)\n", num
);
1114 for (i
= 0 ; i
< 4 ; i
++) {
1117 int py
= y
+ (3 - i
) * dy
+ d2y
;
1118 dockapp_copyarea(parts
, pixmap
, bx
, by
, sx
, sy
, px
, py
);
1124 static void draw_binarytime() {
1125 int sx
= style
.binzx
;
1126 int sy
= style
.binzy
;
1127 int d1x
= style
.bind1x
;
1128 int d1y
= style
.bind1y
;
1129 int d2x
= style
.bind2x
;
1130 int d2y
= style
.bind2y
;
1132 draw_bits(timeinfos
->tm_hour
/ 10, style
.binhx
, style
.binhy
, 0, 0,
1133 sx
, sy
, d1x
, d1y
, d2x
, d2y
);
1134 draw_bits(timeinfos
->tm_hour
% 10, style
.binhx
, style
.binhy
, 1, 0,
1135 sx
, sy
, d1x
, d1y
, d2x
, d2y
);
1137 draw_bits(timeinfos
->tm_min
/ 10, style
.binmx
, style
.binmy
, 0, 0,
1138 sx
, sy
, d1x
, d1y
, d2x
, d2y
);
1139 draw_bits(timeinfos
->tm_min
% 10, style
.binmx
, style
.binmy
, 1, 0,
1140 sx
, sy
, d1x
, d1y
, d2x
, d2y
);
1142 draw_bits(timeinfos
->tm_sec
/ 10, style
.binsx
, style
.binsy
, 0, 0,
1143 sx
, sy
, d1x
, d1y
, d2x
, d2y
);
1144 draw_bits(timeinfos
->tm_sec
% 10, style
.binsx
, style
.binsy
, 1, 0,
1145 sx
, sy
, d1x
, d1y
, d2x
, d2y
);
1147 if (style
.binix
!= -1) {
1148 int wd
= timeinfos
->tm_wday
== 0 ? 7 : timeinfos
->tm_wday
;
1157 draw_bits(wd
, style
.binwx
, style
.binwy
, 0, 1,
1158 sx
, sy
, d1x
, d1y
, d2x
, d2y
);
1160 draw_bits(timeinfos
->tm_mday
/ 10, style
.bindx
, style
.bindy
, 0, 1,
1161 sx
, sy
, d1x
, d1y
, d2x
, d2y
);
1162 draw_bits(timeinfos
->tm_mday
% 10, style
.bindx
, style
.bindy
, 1, 1,
1163 sx
, sy
, d1x
, d1y
, d2x
, d2y
);
1165 draw_bits((timeinfos
->tm_mon
+ 1) / 10, style
.binox
, style
.binoy
, 0, 1,
1166 sx
, sy
, d1x
, d1y
, d2x
, d2y
);
1167 draw_bits((timeinfos
->tm_mon
+ 1) % 10, style
.binox
, style
.binoy
, 1, 1,
1168 sx
, sy
, d1x
, d1y
, d2x
, d2y
);
1173 static void parse_arguments(int argc
, char **argv
) {
1175 for (i
= 1; i
< argc
; i
++) {
1176 if (!strcmp(argv
[i
], "--help") || !strcmp(argv
[i
], "-h")) {
1177 print_help(argv
[0]), exit(0);
1178 } else if (!strcmp(argv
[i
], "--version") || !strcmp(argv
[i
], "-v")) {
1179 printf("%s version %s\n", PACKAGE
, VERSION
), exit(0);
1180 } else if (!strcmp(argv
[i
], "--display") || !strcmp(argv
[i
], "-d")) {
1181 display_name
= argv
[i
+ 1];
1183 } else if (!strcmp(argv
[i
], "--backlight") || !strcmp(argv
[i
], "-bl")) {
1184 backlight
= LIGHTON
;
1185 } else if (!strcmp(argv
[i
], "--light-color") || !strcmp(argv
[i
], "-lc")) {
1187 fprintf(stderr
, "%s: argument \"%s\" needs an option.\n", argv
[0], argv
[i
]), exit(1);
1188 SET_STRING(light_color
, argv
[i
+ 1]);
1190 } else if (!strcmp(argv
[i
], "--windowed") || !strcmp(argv
[i
], "-w")) {
1191 dockapp_iswindowed
= True
;
1192 } else if (!strcmp(argv
[i
], "--broken-wm") || !strcmp(argv
[i
], "-bw")) {
1193 dockapp_isbrokenwm
= True
;
1194 } else if (!strcmp(argv
[i
], "--no-blink") || !strcmp(argv
[i
], "-nb")) {
1195 switch_authorized
= False
;
1196 } else if (!strcmp(argv
[i
], "--h12") || !strcmp(argv
[i
], "-12")) {
1198 } else if (!strcmp(argv
[i
], "--time-mode") || !strcmp(argv
[i
], "-tm")) {
1200 fprintf(stderr
, "%s: error parsing argument for option %s\n",
1201 argv
[0], argv
[i
]), exit(1);
1202 if (sscanf(argv
[i
+ 1], "%i", &integer
) != 1)
1203 fprintf(stderr
, "%s: error parsing argument for option %s\n",
1204 argv
[0], argv
[i
]), exit(1);
1205 if ((integer
< 0) || (integer
> 2))
1206 fprintf(stderr
, "%s: argument %s must be in [0,2]\n",
1207 argv
[0], argv
[i
]), exit(1);
1208 time_mode
= integer
;
1210 } else if (!strcmp(argv
[i
], "--alarm-cmd") || !strcmp(argv
[i
], "-c")) {
1211 SET_STRING(command
, argv
[i
+ 1]);
1213 } else if (!strcmp(argv
[i
], "--message-cmd") || !strcmp(argv
[i
], "-mc")) {
1214 SET_STRING(msgcmd
, argv
[i
+ 1]);
1216 } else if (!strcmp(argv
[i
], "--alarm") || !strcmp(argv
[i
], "-a")) {
1217 alrm_add(&alarms
, argv
[i
+ 1]);
1219 } else if (!strcmp(argv
[i
], "--cfg-file") || !strcmp(argv
[i
], "-f")) {
1220 SET_STRING(config_file
, argv
[i
+ 1]);
1222 } else if (!strcmp(argv
[i
], "--no-locale") || !strcmp(argv
[i
], "-nl")) {
1224 } else if (!strcmp(argv
[i
], "--style") || !strcmp(argv
[i
], "-s")) {
1225 SET_STRING(style_name
, argv
[i
+ 1]);
1227 } else if (!strcmp(argv
[i
], "--style-dir") || !strcmp(argv
[i
], "-sd")) {
1228 SET_STRING(style_dir
, argv
[i
+ 1]);
1230 } else if (!strcmp(argv
[i
], "--label") || !strcmp(argv
[i
], "-l")) {
1231 SET_STRING(label
, argv
[i
+ 1]);
1233 } else if (!strcmp(argv
[i
], "--show-cal") || !strcmp(argv
[i
], "-sc")) {
1235 } else if (!strcmp(argv
[i
], "--cal-alrm") || !strcmp(argv
[i
], "-ca")) {
1239 fprintf(stderr
, "%s: unrecognized option '%s'\n", argv
[0], argv
[i
]);
1240 print_help(argv
[0]), exit(1);
1246 static void print_help(char *prog
)
1248 printf("Usage : %s [OPTIONS]\n"
1249 "%s - Window Maker digital clock dockapp\n"
1250 " -h, --help show this help text and exit\n"
1251 " -v, --version show program version and exit\n"
1252 " -d, --display <string> display to use\n"
1253 " -bl, --backlight turn on back-light\n"
1254 " -lc, --light-color <color> backlight/led colour\n"
1255 " -tm, --time-mode <mode> start with time mode (0: clock, 1: internet time, 2: binary clock)\n"
1256 " -w, --windowed run the application in windowed mode\n"
1257 " -bw, --broken-wm activate broken window manager fix\n"
1258 " -a, --alarm <HH:MM> set alarm time to HH:MM (24h clock mode)\n"
1259 " -c, --alarm-cmd <string> command to launch when alarm raises\n"
1260 " -mc, --message-cmd <string> command to launch when alarm raises and a message is associated\n"
1261 " -12, --h12 12 hours clock mode (default is 24)\n"
1262 " -s, --style <file> style to use for display\n"
1263 " -sd, --style-dir <dir> directory where styles are stored\n"
1264 " -nb, --no-blink disable blinking when alarm is raised\n"
1265 " -f, --cfgfile <filename> use 'filename' as configuration file\n"
1266 " -nl, --no-locale don't use current locale\n"
1267 " -l, --label <string> use a label instead of date\n"
1268 " -ca, --cal-alrm load calendar alarms for today\n"
1269 " -sc, --show-cal show calendar at startup/00:00\n",
1274 static void time_update() {
1278 timeinfos
= localtime(&tnow
);
1280 if (time_mode
== INTERNET
) {
1282 swtime
= timeinfos
->tm_hour
* 3600
1283 + timeinfos
->tm_min
* 60
1284 + timeinfos
->tm_sec
;
1286 localtmzone
= timeinfos
->tm_gmtoff
;
1288 localtmzone
= timezone
;
1290 swtime
+= localtmzone
+3600;
1291 if (timeinfos
->tm_isdst
) swtime
-= 3600;
1297 if (swtime
< 0) swtime
+= 1000;
1302 static Bool
raise_alarm() {
1303 if ((timeinfos
->tm_hour
== 0) &&
1304 (timeinfos
->tm_min
== 0) &&
1305 (timeinfos
->tm_sec
== 0)) {
1306 if (showcal
) show_cal();
1307 if (calalrms
) reload_alarms();
1310 Alarm
*alrm
= alarms
;
1311 char thistime
[MAXSTRLEN
+ 1];
1312 char thisdate
[MAXSTRLEN
+ 1];
1314 strftime(thistime
, MAXSTRLEN
, "%H:%M", timeinfos
);
1315 strftime(thisdate
, MAXSTRLEN
, "%u", timeinfos
);
1317 if (alrm
->on
&& (strcmp(thistime
, alrm
->alarm_time
) == 0)) {
1318 message
= alrm
->message
;
1319 if (alrm
->alarm_date
) {
1320 if (strcmp(thisdate
, alrm
->alarm_date
) == 0)
1335 static Bool
fexist(const char *filename
) {
1338 if ((file
= fopen(filename
, "r")) == NULL
) return False
;
1345 static Bool
filestat(const char *filename
, time_t *time
, int mode
) {
1349 if (stat(filename
, &s
) == -1) {
1350 if (*time
== 0) return False
;
1354 case MTIME
: t
= s
.st_mtime
; break;
1355 case ATIME
: t
= s
.st_atime
; break;
1367 static int my_system(char *cmd
, char *opt
) {
1369 extern char **environ
;
1371 if (cmd
== NULL
) return 1;
1373 if (pid
== -1) return -1;
1378 char *thiscommand
= xmalloc(strlen(cmd
)
1379 + (opt
? strlen(opt
) + 4 : 1));
1380 sprintf(thiscommand
, "%s %s%s%s", cmd
,
1386 argv
[2] = thiscommand
;
1388 execve("/bin/sh", argv
, environ
);
1398 void *xmalloc(size_t size
) {
1399 void *ret
= malloc(size
);
1401 perror("malloc() ");
1408 char *xstrdup(const char *string
) {
1409 char *ret
= string
? strdup(string
) : NULL
;
1410 if (string
&& (ret
== NULL
)) {
1411 perror("strdup() ");
1418 static void put_alrm(Alarm
**list
, const char *entry
,
1419 char *time
, char *date
, char *ison
, char *mesg
, Bool cal
) {
1424 lst
= xmalloc(sizeof(Alarm
));
1427 if (strcmp(entry
, lst
->entry
) == 0) ok
= False
;
1428 while ( (lst
->next
) && ok
) {
1430 if (strcmp(entry
, lst
->entry
) == 0) ok
= False
;
1433 lst
->next
= xmalloc(sizeof(Alarm
));
1436 lst
->entry
= xstrdup(entry
);
1437 lst
->alarm_time
= time
? xstrdup(time
) : NULL
;
1438 lst
->alarm_date
= date
? xstrdup(date
) : NULL
;
1439 lst
->on
= ison
? getbool(ison
) : True
;
1440 lst
->message
= mesg
? xstrdup(mesg
) : NULL
;
1446 static void alrm_add(Alarm
**list
, const char *value
) {
1447 char *time
= NULL
, *date
= NULL
, *ison
= NULL
, *mesg
= NULL
, *at
;
1448 char *tokstr
= xstrdup(value
);
1449 char *toksav
= tokstr
;
1451 if (! value
) return;
1452 at
= strchr(value
, '@');
1453 if (at
) ison
= strtok(tokstr
, "@");
1454 time
= strtok(at
? NULL
: tokstr
, "-.");
1455 if (strchr(value
, '-')) date
= strtok(NULL
, ".");
1456 mesg
= strtok(NULL
, "\n\0");
1458 put_alrm(list
, value
, time
, date
, ison
, mesg
, False
);
1464 static void free_alrm(Alarm
**list
) {
1465 Alarm
*lst
= *list
, *next
;
1469 FREE(lst
->alarm_time
);
1470 FREE(lst
->alarm_date
);
1479 static int nb_alrm(Alarm
*list
) {
1490 static Bool
alarms_on(Alarm
*list
) {
1494 if (alrm
->on
) return True
;
1501 static void switch_alarms(Alarm
*list
) {
1505 if (alarms_on(list
)) set_to
= False
;
1507 char *tokstr
= xstrdup(alrm
->entry
);
1508 char *toksav
= tokstr
;
1509 Bool is_on
= alrm
->cal
|| getbool(strtok(tokstr
, "@"));
1511 if ((is_on
&& set_to
) || (!set_to
)) {
1520 static Bool
getbool(char *value
) {
1522 for (i
= 0 ; value
[i
] ; i
++) value
[i
] = tolower(value
[i
]);
1523 if (strcmp(value
, "0") == 0) return False
;
1524 if (strcmp(value
, "1") == 0) return True
;
1525 if (strcmp(value
, "true") == 0) return True
;
1526 if (strcmp(value
, "false") == 0) return False
;
1527 if (strcmp(value
, "yes") == 0) return True
;
1528 if (strcmp(value
, "no") == 0) return False
;
1529 if (strcmp(value
, "on") == 0) return True
;
1530 if (strcmp(value
, "off") == 0) return False
;
1531 printf("Error in converting \"%s\" to boolean value.\n", value
);
1536 static Bool
load_cfgfile() {
1538 int i
= 0, ok
= True
;
1539 char line
[MAXSTRLEN
+ 1];
1542 if ((file
= fopen(config_file
, "r")) == NULL
) {
1543 if (strstr(config_file
, "/"DEFAULT_CFGFILE
) == NULL
)
1544 printf("Unable to open configuration file \"%s\".\n", config_file
);
1547 if (ok
&& (! filestat(config_file
, &config_mtime
, MTIME
))) {
1552 if (alarms
) free_alrm(&alarms
);
1553 while (! feof(file
)) {
1554 bzero(line
, MAXSTRLEN
+ 1);
1555 fgets(line
, MAXSTRLEN
, file
);
1557 if (line
[strlen(line
) - 1] == '\n') line
[strlen(line
) - 1] = 0;
1558 if ((line
[0] == '#') || (line
[0] == 0)) continue;
1559 value
= strchr(line
, '=');
1560 if (! value
) continue;
1562 while ((value
[0] != 0) && (value
[0] == ' ')) value
++;
1563 if (value
[0] == 0) continue;
1565 if (strncmp(line
, "Backlight", 9) == 0) {
1566 backlight
= getbool(value
) ? LIGHTON
: LIGHTOFF
;
1567 } else if (strncmp(line
, "Color", 5) == 0) {
1568 SET_STRING(light_color
, value
);
1569 } else if (strncmp(line
, "Alarm", 5) == 0) {
1570 alrm_add(&alarms
, value
);
1571 } else if (strncmp(line
, "Command", 7) == 0) {
1572 SET_STRING(command
, value
);
1573 } else if (strncmp(line
, "MessageCmd", 10) == 0) {
1574 SET_STRING(msgcmd
, value
);
1575 } else if (strncmp(line
, "Blink", 5) == 0) {
1576 switch_authorized
= getbool(value
);
1577 } else if (strncmp(line
, "H12", 3) == 0) {
1578 h12
= getbool(value
);
1579 } else if (strncmp(line
, "Locale", 6) == 0) {
1580 use_locale
= getbool(value
);
1581 } else if (strncmp(line
, "StyleDir", 8) == 0) {
1582 SET_STRING(style_dir
, value
);
1583 } else if (strncmp(line
, "Style", 5) == 0) {
1584 SET_STRING(style_name
, value
);
1585 } else if (strncmp(line
, "TimeMode", 5) == 0) {
1586 time_mode
= atoi(value
);
1587 } else if (strncmp(line
, "ShowCal", 7) == 0) {
1588 showcal
= getbool(value
);
1589 } else if (strncmp(line
, "CalAlrms", 8) == 0) {
1590 calalrms
= getbool(value
);
1592 printf("Error in %s at line %d :\n[%s].\n", config_file
, i
, line
);
1595 if (calalrms
) load_calalrms();
1597 } else if (calalrms
&& cal_alrms_chg()) {
1604 static char *get_calend_file(int type
) {
1605 char *Home
= robust_home();
1606 char *filename
= xmalloc(
1608 strlen(DEFAULT_CONFIGDIR
) +
1613 sprintf(filename
, "%s/%s/%04d-%02d-%02d",
1616 timeinfos
->tm_year
+ 1900,
1617 timeinfos
->tm_mon
+ 1,
1618 timeinfos
->tm_mday
);
1621 sprintf(filename
, "%s/%s/XXXX-%02d-%02d",
1624 timeinfos
->tm_mon
+ 1,
1625 timeinfos
->tm_mday
);
1628 sprintf(filename
, "%s/%s/XXXX-XX-%02d",
1631 timeinfos
->tm_mday
);
1639 static int cal_alrms_chg() {
1640 static time_t cal_u_mtime
= 0;
1641 static time_t cal_y_mtime
= 0;
1642 static time_t cal_m_mtime
= 0;
1643 char *cal_u_fname
= NULL
;
1644 char *cal_y_fname
= NULL
;
1645 char *cal_m_fname
= NULL
;
1646 int chg_u
, chg_y
, chg_m
;
1648 if (! calalrms
) return False
;
1649 cal_u_fname
= get_calend_file(1);
1650 cal_y_fname
= get_calend_file(2);
1651 cal_m_fname
= get_calend_file(3);
1652 chg_u
= filestat(cal_u_fname
, &cal_u_mtime
, MTIME
);
1653 chg_y
= filestat(cal_y_fname
, &cal_y_mtime
, MTIME
);
1654 chg_m
= filestat(cal_m_fname
, &cal_m_mtime
, MTIME
);
1658 if (chg_u
|| chg_y
|| chg_m
) return True
;
1663 static void load_cal_file(int type
) {
1665 char *calend_file
= get_calend_file(type
);
1668 if ((file
= fopen(calend_file
, "r")) != NULL
) {
1669 while (! feof(file
)) {
1670 char line
[MAXSTRLEN
+ 1];
1671 bzero(line
, MAXSTRLEN
+ 1);
1672 fgets(line
, MAXSTRLEN
, file
);
1673 if ( (line
[0] != 0) && (strncmp(line
, "@ ", 2) == 0) ) {
1674 char time
[MAXSTRLEN
+ 1];
1675 sscanf(line
, "@ %s ", time
);
1676 put_alrm(&alarms
, line
, time
, NULL
, NULL
, line
+ 8, True
);
1685 static void load_calalrms() {
1687 for (i
= 1 ; i
< 4 ; i
++) load_cal_file(i
);
1691 static void reload_alarms() {
1694 char line
[MAXSTRLEN
+ 1];
1697 if (alarms
) free_alrm(&alarms
);
1698 if ((file
= fopen(config_file
, "r")) == NULL
) {
1699 if (strstr(config_file
, "/"DEFAULT_CFGFILE
) == NULL
)
1700 printf("Unable to open configuration file \"%s\".\n", config_file
);
1702 while (! feof(file
)) {
1703 bzero(line
, MAXSTRLEN
+ 1);
1704 fgets(line
, MAXSTRLEN
, file
);
1706 if (line
[strlen(line
) - 1] == '\n') line
[strlen(line
) - 1] = 0;
1707 if ((line
[0] == '#') || (line
[0] == 0)) continue;
1708 value
= strchr (line
, '=') + 1;
1709 while ((value
[0] == ' ') && (value
[0] != 0)) value
++;
1710 if (value
[0] == 0) continue;
1712 if (strncmp(line
, "Alarm", 5) == 0) alrm_add(&alarms
, value
);
1715 if (calalrms
) load_calalrms();
1719 static void show_cal_file(int type
) {
1723 char *calend_file
= get_calend_file(type
);
1725 if ((file
= fopen(calend_file
, "r")) != NULL
) {
1726 while (! feof(file
)) {
1727 char line
[MAXSTRLEN
+ 1];
1728 bzero(line
, MAXSTRLEN
+ 1);
1729 fgets(line
, MAXSTRLEN
, file
);
1731 int len
= data
? strlen(data
) : 0;
1732 tmp
= xmalloc(len
+ strlen(line
) + 1);
1733 sprintf(tmp
, "%s%s", data
? data
: "", line
);
1740 my_system(msgcmd
, data
);
1747 static void show_cal() {
1749 for (i
= 1 ; i
< 4 ; i
++) show_cal_file(i
);
1753 static char *robust_home() {
1755 return getenv("HOME");
1756 else if (getenv("USER") && getpwnam(getenv("USER")))
1757 return getpwnam(getenv("USER"))->pw_dir
;
1758 else if (getenv("LOGNAME") && getpwnam(getenv("LOGNAME")))
1759 return getpwnam (getenv ("LOGNAME") )->pw_dir
;
1760 else if ((getuid() != -1) && (getpwuid(getuid())))
1761 return getpwuid(getuid())->pw_dir
;